Files
simgear/simgear/metar/Dcdmetar.cpp
T
david a6291b286c Patch from Julian Foad:
Remove unused static function (warning because it cannot possibly be used).
2002-06-28 15:53:58 +00:00

2502 lines
89 KiB
C++

#include "Local.h" /* standard header file */
#include "Metar.h" /* standard header file */
float fracPart( char * );
void DcdMTRmk( char **, Decoded_METAR * );
/********************************************************************/
/* */
/* Title: SaveTokenString */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 14 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: SaveTokenString tokenizes the input character */
/* string based upon the delimeter set supplied */
/* by the calling routine. The elements tokenized */
/* from the input character string are saved in an */
/* array of pointers to characters. The address of */
/* this array is the output from this function. */
/* */
/* Input: string - a pointer to a character string. */
/* */
/* delimeters - a pointer to a string of 1 or more */
/* characters that are used for token- */
/* izing the input character string. */
/* */
/* Output: token - the address of a pointer to an array of */
/* pointers to character strings. The */
/* array of pointers are the addresses of */
/* the character strings that are token- */
/* ized from the input character string. */
/* */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static char **SaveTokenString ( char *string , char *delimeters )
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
int NDEX;
static char *token[ MAXTOKENS ],
*TOKEN;
/*********************************/
/* BEGIN THE BODY OF THE ROUTINE */
/*********************************/
/******************************************/
/* TOKENIZE THE INPUT CHARACTER STRING */
/* AND SAVE THE TOKENS TO THE token ARRAY */
/******************************************/
NDEX = 0;
TOKEN = strtok( string, delimeters);
if( TOKEN == NULL )
return NULL;
token[NDEX] = (char *) malloc(sizeof(char)*(strlen(TOKEN)+1));
strcpy( token[ NDEX ], TOKEN );
while ( token[NDEX] != NULL )
{
NDEX++;
TOKEN = strtok( NULL, delimeters );
if( TOKEN != NULL )
{
token[NDEX] = (char *)
malloc(sizeof(char)*(strlen(TOKEN)+1));
strcpy( token[NDEX], TOKEN );
}
else
token[ NDEX ] = TOKEN;
}
return token;
}
/********************************************************************/
/* */
/* Title: freeTokens */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 14 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: freeTokens frees the storage allocated for the */
/* character strings stored in the token array. */
/* */
/* Input: token - the address of a pointer to an array */
/* of string tokens. */
/* */
/* */
/* Output: None. */
/* */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static void freeTokens( char **token )
{
int NDEX;
NDEX = 0;
while( *(token+NDEX) != NULL )
{
free( *(token+NDEX) );
NDEX++;
}
return;
}
/********************************************************************/
/* */
/* Title: InitDcdMETAR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: InitDcdMETAR initializes every member of the */
/* structure addressed by the pointer Mptr. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: Mptr - ptr to a decoded_METAR structure. */
/* */
/* Output: NONE */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static void InitDcdMETAR( Decoded_METAR *Mptr )
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
int i,
j;
/*************************/
/* START BODY OF ROUTINE */
/*************************/
memset(Mptr->TS_LOC,'\0',3);
memset(Mptr->TS_MOVMNT,'\0',3);
memset(Mptr->TornadicType,'\0',15);
memset(Mptr->TornadicLOC,'\0',10);
memset(Mptr->TornadicDIR,'\0',4);
memset(Mptr->TornadicMovDir,'\0',3);
Mptr->BTornadicHour = MAXINT;
Mptr->BTornadicMinute = MAXINT;
Mptr->ETornadicHour = MAXINT;
Mptr->ETornadicMinute = MAXINT;
Mptr->TornadicDistance = MAXINT;
memset( Mptr->autoIndicator,'\0', 5 );
Mptr->RVRNO = FALSE;
Mptr->GR = FALSE;
Mptr->GR_Size = (float) MAXINT;
Mptr->CHINO = FALSE;
memset(Mptr->CHINO_LOC, '\0', 6);
Mptr->VISNO = FALSE;
memset(Mptr->VISNO_LOC, '\0', 6);
Mptr->PNO = FALSE;
Mptr->PWINO = FALSE;
Mptr->FZRANO = FALSE;
Mptr->TSNO = FALSE;
Mptr->DollarSign = FALSE;
Mptr->hourlyPrecip = (float) MAXINT;
Mptr->ObscurAloftHgt = MAXINT;
memset(Mptr->ObscurAloft, '\0', 12);
memset(Mptr->ObscurAloftSkyCond, '\0', 12);
memset(Mptr->VrbSkyBelow, '\0', 4);
memset(Mptr->VrbSkyAbove, '\0', 4);
Mptr->VrbSkyLayerHgt = MAXINT;
Mptr->SectorVsby = (float) MAXINT;
memset( Mptr->SectorVsby_Dir, '\0', 3);
memset(Mptr->codeName, '\0', 6);
memset(Mptr->stnid, '\0', 5);
Mptr->ob_hour = MAXINT;
Mptr->ob_minute = MAXINT;
Mptr->ob_date = MAXINT;
memset(Mptr->synoptic_cloud_type, '\0', 6);
Mptr->CloudLow = '\0';
Mptr->CloudMedium = '\0';
Mptr->CloudHigh = '\0';
memset(Mptr->snow_depth_group, '\0', 6);
Mptr->snow_depth = MAXINT;
Mptr->Temp_2_tenths = (float) MAXINT;
Mptr->DP_Temp_2_tenths = (float) MAXINT;
Mptr->OCNL_LTG = FALSE;
Mptr->FRQ_LTG = FALSE;
Mptr->CNS_LTG = FALSE;
Mptr->CG_LTG = FALSE;
Mptr->IC_LTG = FALSE;
Mptr->CC_LTG = FALSE;
Mptr->CA_LTG = FALSE;
Mptr->AP_LTG = FALSE;
Mptr->OVHD_LTG = FALSE;
Mptr->DSNT_LTG = FALSE;
Mptr->VcyStn_LTG = FALSE;
Mptr->LightningVCTS = FALSE;
Mptr->LightningTS = FALSE;
memset( Mptr->LTG_DIR, '\0', 3);
for( i = 0; i < 3; i++)
{
memset(Mptr->ReWx[i].Recent_weather, '\0', 5);
Mptr->ReWx[i].Bhh = MAXINT;
Mptr->ReWx[i].Bmm = MAXINT;
Mptr->ReWx[i].Ehh = MAXINT;
Mptr->ReWx[i].Emm = MAXINT;
}
Mptr->NIL_rpt = FALSE;
Mptr->AUTO = FALSE;
Mptr->COR = FALSE;
Mptr->winData.windDir = MAXINT;
Mptr->winData.windSpeed = MAXINT;
Mptr->winData.windGust = MAXINT;
Mptr->winData.windVRB = FALSE;
memset(Mptr->winData.windUnits, '\0', 4);
Mptr->minWnDir = MAXINT;
Mptr->maxWnDir = MAXINT;
memset(Mptr->horiz_vsby, '\0', 5);
memset(Mptr->dir_min_horiz_vsby, '\0', 3);
Mptr->prevail_vsbySM = (float) MAXINT;
Mptr->prevail_vsbyM = (float) MAXINT;
Mptr->prevail_vsbyKM = (float) MAXINT;
memset(Mptr->vsby_Dir, '\0', 3);
Mptr->CAVOK = FALSE;
for ( i = 0; i < 12; i++ )
{
memset(Mptr->RRVR[ i ].runway_designator,
'\0', 6);
Mptr->RRVR[ i ].visRange = MAXINT;
Mptr->RRVR[ i ].vrbl_visRange = FALSE;
Mptr->RRVR[ i ].below_min_RVR = FALSE;
Mptr->RRVR[ i ].above_max_RVR = FALSE;
Mptr->RRVR[ i ].Max_visRange = MAXINT;
Mptr->RRVR[ i ].Min_visRange = MAXINT;
}
Mptr->DVR.visRange = MAXINT;
Mptr->DVR.vrbl_visRange = FALSE;
Mptr->DVR.below_min_DVR = FALSE;
Mptr->DVR.above_max_DVR = FALSE;
Mptr->DVR.Max_visRange = MAXINT;
Mptr->DVR.Min_visRange = MAXINT;
for ( i = 0; i < 5; i++ )
{
for( j = 0; j < 8; j++ )
Mptr->WxObstruct[i][j] = '\0';
}
/***********************/
/* PARTIAL OBSCURATION */
/***********************/
memset( &(Mptr->PartialObscurationAmt[0][0]), '\0', 7 );
memset( &(Mptr->PartialObscurationPhenom[0][0]), '\0',12);
memset( &(Mptr->PartialObscurationAmt[1][0]), '\0', 7 );
memset( &(Mptr->PartialObscurationPhenom[1][0]), '\0',12);
/***************************************************/
/* CLOUD TYPE, CLOUD LEVEL, AND SIGNIFICANT CLOUDS */
/***************************************************/
for ( i = 0; i < 6; i++ )
{
memset(Mptr->cldTypHgt[ i ].cloud_type,
'\0', 5);
memset(Mptr->cldTypHgt[ i ].cloud_hgt_char,
'\0', 4);
Mptr->cldTypHgt[ i ].cloud_hgt_meters = MAXINT;
memset(Mptr->cldTypHgt[ i ].other_cld_phenom,
'\0', 4);
}
Mptr->VertVsby = MAXINT;
Mptr->temp = MAXINT;
Mptr->dew_pt_temp = MAXINT;
Mptr->QFE = MAXINT;
Mptr->SLPNO = FALSE;
Mptr->SLP = (float) MAXINT;
Mptr->A_altstng = FALSE;
Mptr->inches_altstng = (double) MAXINT;
Mptr->Q_altstng = FALSE;
Mptr->hectoPasc_altstng = MAXINT;
Mptr->char_prestndcy = MAXINT;
Mptr->prestndcy = (float) MAXINT;
Mptr->precip_amt = (float) MAXINT;
Mptr->precip_24_amt = (float) MAXINT;
Mptr->maxtemp = (float) MAXINT;
Mptr->mintemp = (float) MAXINT;
Mptr->max24temp = (float) MAXINT;
Mptr->min24temp = (float) MAXINT;
Mptr->VIRGA = FALSE;
memset( Mptr->VIRGA_DIR, '\0', 3 );
Mptr->VOLCASH = FALSE;
Mptr->minCeiling = MAXINT;
Mptr->maxCeiling = MAXINT;
Mptr->CIG_2ndSite_Meters = MAXINT;
memset(Mptr->CIG_2ndSite_LOC, '\0', 10 );
Mptr->minVsby = (float) MAXINT;
Mptr->maxVsby = (float) MAXINT;
Mptr->VSBY_2ndSite = (float) MAXINT;
memset(Mptr->VSBY_2ndSite_LOC,'\0',10);
for( i = 0; i < 6; i++ )
memset (&(Mptr->SfcObscuration[i][0]), '\0', 10);
Mptr->Num8thsSkyObscured = MAXINT;
Mptr->Indeterminant3_6HrPrecip = FALSE;
Mptr->CIGNO = FALSE;
Mptr->Ceiling = MAXINT;
Mptr->Estimated_Ceiling = MAXINT;
Mptr->NOSPECI = FALSE;
Mptr->LAST = FALSE;
Mptr->SNINCR = MAXINT;
Mptr->SNINCR_TotalDepth = MAXINT;
Mptr->WaterEquivSnow = (float) MAXINT;
Mptr->SunshineDur = MAXINT;
Mptr->SunSensorOut = FALSE;
Mptr->WshfTime_hour = MAXINT;
Mptr->WshfTime_minute = MAXINT;
Mptr->Wshft_FROPA = FALSE;
Mptr->min_vrbl_wind_dir = MAXINT;
Mptr->max_vrbl_wind_dir = MAXINT;
Mptr->PRESRR = FALSE;
Mptr->PRESFR = FALSE;
Mptr->TWR_VSBY = (float) MAXINT;
Mptr->SFC_VSBY = (float) MAXINT;
Mptr->PKWND_dir = MAXINT;
Mptr->PKWND_speed = MAXINT;
Mptr->PKWND_hour = MAXINT;
Mptr->PKWND_minute = MAXINT;
return;
}
/********************************************************************/
/* */
/* Title: ResetMETARGroup */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: ResetMETARGroup returns a METAR_obGroup enumerated */
/* variable that indicates which METAR reporting group */
/* might next appear in the METAR report and should be */
/* considered for decoding. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: StartGroup - a METAR_obGroup variable that */
/* indicates where or on what group */
/* METAR Decoding began. */
/* */
/* SaveStartGroup - a METAR_obGroup variable that */
/* indicates the reporting group */
/* in the METAR report that was */
/* successfully decoded. */
/* */
/* Output: A METAR_obGroup variable that indicates which */
/* reporting group in the METAR report should next */
/* be considered for decoding */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
/*static int ResetMETARGroup( int StartGroup,
int SaveStartGroup )
{
enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
AUTO, COR, windData, MinMaxWinDir,
CAVOK, visibility,
RVR, presentWX, skyCond, tempGroup,
altimStng, NotIDed = 99};
if( StartGroup == NotIDed && SaveStartGroup == NotIDed )
return NotIDed;
else if( StartGroup == NotIDed && SaveStartGroup != NotIDed &&
SaveStartGroup != altimStng )
return (++SaveStartGroup);
else
return (++SaveStartGroup);
}
*/
/********************************************************************/
/* */
/* Title: CodedHgt2Meters */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: CodedHgt2Meters converts a coded cloud height into */
/* meters. */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: token - a pointer to a METAR report group. */
/* Mptr - a pointer to a decoded_METAR structure. */
/* */
/* Output: Cloud height in meters */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static int CodedHgt2Meters( char *token, Decoded_METAR *Mptr )
{
int hgt;
static int maxhgt = 30000;
if( (hgt = atoi(token)) == 999 )
return maxhgt;
else
return (hgt*30);
}
/********************************************************************/
/* */
/* Title: isPartObscur */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: isPartObscur determines whether or not the METAR */
/* report element that is passed to it is or is not */
/* a partial obscuration indicator for an amount of */
/* obscuration. */
/* */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: token - the address of a pointer to the group */
/* in the METAR report that isPartObscur */
/* determines is or is not a partial */
/* obscuration indicator. */
/* */
/* */
/* Mptr - a pointer to a decoded_METAR structure. */
/* */
/* Output: TRUE, if the group is a partial obscuration */
/* indicator and FALSE, if it is not. */
/* */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isPartObscur( char **string, Decoded_METAR *Mptr,
int *NDEX )
{
if( *string == NULL )
return FALSE;
if( strcmp( *string, "FEW///" ) == 0 ||
strcmp( *string, "SCT///" ) == 0 ||
strcmp( *string, "BKN///" ) == 0 ||
strcmp( *string, "FEW000" ) == 0 ||
strcmp( *string, "SCT000" ) == 0 ||
strcmp( *string, "BKN000" ) == 0 ) {
strcpy( &(Mptr->PartialObscurationAmt[0][0]), *string );
(*NDEX)++;
string++;
if( *string == NULL )
return TRUE;
if( strcmp( (*string+3), "///") ) {
if( strcmp( *string, "FEW000" ) == 0 ||
strcmp( *string, "SCT000" ) == 0 ||
strcmp( *string, "BKN000" ) == 0 ) {
strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
(*NDEX)++;
}
}
else {
if( strcmp( *string, "FEW///" ) == 0 ||
strcmp( *string, "SCT///" ) == 0 ||
strcmp( *string, "BKN///" ) == 0 ) {
strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
(*NDEX)++;
}
}
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isCldLayer */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: isCldLayer determines whether or not the */
/* current group has a valid cloud layer */
/* identifier. */
/* */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: token - pointer to a METAR report group. */
/* */
/* Output: TRUE, if the report group is a valid cloud */
/* layer indicator. */
/* */
/* FALSE, if the report group is not a valid cloud */
/* layer indicator. */
/* */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isCldLayer( char *token )
{
if( token == NULL )
return FALSE;
if( strlen(token) < 6 )
return FALSE;
else
return ((strncmp(token,"OVC",3) == 0 ||
strncmp(token,"SCT",3) == 0 ||
strncmp(token,"FEW",3) == 0 ||
strncmp(token,"BKN",3) == 0 ||
(isdigit(*token) &&
strncmp(token+1,"CU",2) == 0) ||
(isdigit(*token) &&
strncmp(token+1,"SC",2) == 0) ) &&
nisdigit((token+3),3)) ? TRUE:FALSE;
}
/********************************************************************/
/* */
/* Title: isCAVOK */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 09 May 1996 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: isCAVOK determines whether or not the current */
/* group is a valid CAVOK indicator. */
/* */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: token - pointer to a METAR report group. */
/* */
/* Output: TRUE, if the input group is a valid CAVOK */
/* indicator. FALSE, otherwise. */
/* */
/* */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isCAVOK( char *token, Decoded_METAR *Mptr, int *NDEX )
{
if( token == NULL )
return FALSE;
if( strcmp(token, "CAVOK") != 0 )
return FALSE;
else {
(*NDEX)++;
Mptr->CAVOK = TRUE;
return TRUE;
}
}
/********************************************************************/
/* */
/* Title: parseCldData */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static void parseCldData( char *token, Decoded_METAR *Mptr, int next)
{
if( token == NULL )
return;
if( strlen(token) > 6 )
strncpy(Mptr->cldTypHgt[next].other_cld_phenom,token+6,
(strlen(token)-6));
strncpy(Mptr->cldTypHgt[next].cloud_type,token,3);
strncpy(Mptr->cldTypHgt[next].cloud_hgt_char,token+3,3);
Mptr->cldTypHgt[next].cloud_hgt_meters =
CodedHgt2Meters( token+3, Mptr );
return;
}
/********************************************************************/
/* */
/* Title: isSkyCond */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isSkyCond( char **skycond, Decoded_METAR *Mptr,
int *NDEX )
{
bool first_layer,
second_layer,
third_layer,
fourth_layer,
fifth_layer,
sixth_layer;
int next;
/********************************************************/
/* INTERROGATE skycond TO DETERMINE IF "CLR" IS PRESENT */
/********************************************************/
if( *skycond == NULL )
return FALSE;
if( strcmp(*skycond,"CLR") == 0)
{
strcpy(Mptr->cldTypHgt[0].cloud_type,"CLR");
/*
memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
memset(Mptr->cldTypHgt[0].other_cld_phenom,
'\0', 1);
*/
(*NDEX)++;
return TRUE;
}
/********************************************************/
/* INTERROGATE skycond TO DETERMINE IF "SKC" IS PRESENT */
/********************************************************/
else if( strcmp(*skycond,"SKC") == 0)
{
strcpy(Mptr->cldTypHgt[0].cloud_type,"SKC");
/*
memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
memset(Mptr->cldTypHgt[0].other_cld_phenom,
'\0', 1);
*/
(*NDEX)++;
return TRUE;
}
/****************************************/
/* INTERROGATE skycond TO DETERMINE IF */
/* VERTICAL VISIBILITY IS PRESENT */
/****************************************/
else if( strncmp(*skycond,"VV",2) == 0
&& strlen(*skycond) == 5 &&
nisdigit((*skycond+2),3) )
{
Mptr->VertVsby = CodedHgt2Meters( (*skycond+2), Mptr);
(*NDEX)++;
return TRUE;
}
/****************************************/
/* INTERROGATE skycond TO DETERMINE IF */
/* CLOUD LAYER DATA IS PRESENT */
/****************************************/
else if( isCldLayer( *skycond ))
{
next = 0;
parseCldData( *skycond , Mptr, next );
first_layer = TRUE;
next++;
(++skycond);
if( *skycond == NULL )
return TRUE;
second_layer = FALSE;
third_layer = FALSE;
fourth_layer = FALSE;
fifth_layer = FALSE;
sixth_layer = FALSE;
if( isCldLayer( *skycond ) && first_layer )
{
parseCldData( *skycond, Mptr, next );
second_layer = TRUE;
next++;
(++skycond);
if( *skycond == NULL )
return TRUE;
}
if( isCldLayer( *skycond ) && first_layer &&
second_layer )
{
parseCldData( *skycond , Mptr, next );
third_layer = TRUE;
next++;
(++skycond);
if( *skycond == NULL )
return TRUE;
}
if( isCldLayer( *skycond ) && first_layer && second_layer &&
third_layer )
{
parseCldData( *skycond, Mptr, next );
fourth_layer = TRUE;
next++;
(++skycond);
if( *skycond == NULL )
return TRUE;
}
if( isCldLayer( *skycond ) && first_layer && second_layer &&
third_layer && fourth_layer )
{
parseCldData( *skycond , Mptr, next );
fifth_layer = TRUE;
next++;
(++skycond);
if( *skycond == NULL )
return TRUE;
}
if( isCldLayer( *skycond ) && first_layer && second_layer &&
third_layer && fourth_layer && fifth_layer )
{
parseCldData( *skycond , Mptr, next );
sixth_layer = TRUE;
}
if( sixth_layer )
{
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else if( fifth_layer )
{
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else if( fourth_layer )
{
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else if( third_layer )
{
(*NDEX)++;
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else if( second_layer )
{
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else if( first_layer )
{
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: prevailVSBY */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static float prevailVSBY( char *visibility )
{
float Miles_vsby;
char *temp,
*Slash_ptr,
*SM_KM_ptr;
char numerator[3],
denominator[3];
if( (SM_KM_ptr = strstr( visibility, "SM" )) == NULL )
SM_KM_ptr = strstr(visibility, "KM");
Slash_ptr = strchr( visibility, '/' );
if( Slash_ptr == NULL )
{
temp = (char *) malloc(sizeof(char) *
((SM_KM_ptr - visibility)+1));
memset( temp, '\0', (SM_KM_ptr-visibility)+1);
strncpy( temp, visibility, (SM_KM_ptr-visibility) );
Miles_vsby = (float) (atoi(temp));
free( temp );
return Miles_vsby;
}
else
{
memset(numerator, '\0', 3);
memset(denominator, '\0', 3);
strncpy(numerator, visibility, (Slash_ptr - visibility));
/*>>>>>>>>>>>>>>>>>>>>>>
if( (SM_KM_ptr - (Slash_ptr+1)) == 0 )
strcpy(denominator, "4");
else
<<<<<<<<<<<<<<<<<<<<<<*/
strncpy(denominator,
Slash_ptr+1, (SM_KM_ptr - Slash_ptr));
return ( ((float)(atoi(numerator)))/
((float)(atoi(denominator))) );
}
}
/********************************************************************/
/* */
/* Title: isVisibility */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isVisibility( char **visblty, Decoded_METAR *Mptr,
int *NDEX )
{
char *achar,
*astring,
*save_token;
/****************************************/
/* CHECK FOR VISIBILITY MEASURED <1/4SM */
/****************************************/
if( *visblty == NULL )
return FALSE;
if( strcmp(*visblty,"M1/4SM") == 0 ||
strcmp(*visblty,"<1/4SM") == 0 ) {
Mptr->prevail_vsbySM = 0.0;
(*NDEX)++;
return TRUE;
}
/***********************************************/
/* CHECK FOR VISIBILITY MEASURED IN KILOMETERS */
/***********************************************/
if( (achar = strstr(*visblty, "KM")) != NULL )
{
if( nisdigit(*visblty,(achar - *visblty)) &&
(achar - *visblty) > 0 )
{
Mptr->prevail_vsbyKM = prevailVSBY( *visblty );
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/***********************************/
/* CHECK FOR VISIBILITY MEASURED */
/* IN A FRACTION OF A STATUTE MILE */
/***********************************/
else if( (achar = strchr( *visblty, '/' )) !=
NULL &&
(astring = strstr( *visblty, "SM")) != NULL )
{
if( nisdigit(*visblty,(achar - *visblty))
&&
(achar - *visblty) > 0 &&
(astring - (achar+1)) > 0 &&
nisdigit(achar+1, (astring - (achar+1))) )
{
Mptr->prevail_vsbySM = prevailVSBY (*visblty);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/***********************************/
/* CHECK FOR VISIBILITY MEASURED */
/* IN WHOLE STATUTE MILES */
/***********************************/
else if( (astring = strstr(*visblty,"SM") ) != NULL )
{
if( nisdigit(*visblty,(astring - *visblty)) &&
(astring- *visblty) > 0 )
{
Mptr->prevail_vsbySM = prevailVSBY (*visblty);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/***********************************/
/* CHECK FOR VISIBILITY MEASURED */
/* IN WHOLE AND FRACTIONAL STATUTE */
/* MILES */
/***********************************/
else if( nisdigit( *visblty,
strlen(*visblty)) &&
strlen(*visblty) < 4 )
{
save_token = (char *) malloc(sizeof(char)*
(strlen(*visblty)+1));
strcpy(save_token,*visblty);
if( *(++visblty) == NULL)
{
free( save_token );
return FALSE;
}
if( (achar = strchr( *visblty, '/' ) ) != NULL &&
(astring = strstr( *visblty, "SM") ) != NULL )
{
if( nisdigit(*visblty,
(achar - *visblty)) &&
(achar - *visblty) > 0 &&
(astring - (achar+1)) > 0 &&
nisdigit(achar+1, (astring - (achar+1))) )
{
Mptr->prevail_vsbySM = prevailVSBY (*visblty);
Mptr->prevail_vsbySM +=
(float) (atoi(save_token));
free( save_token);
(*NDEX)++;
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
/***********************************/
/* CHECK FOR VISIBILITY MEASURED */
/* IN METERS WITH OR WITHOUT DI- */
/* RECTION OF OBSERVATION */
/***********************************/
else if( nisdigit(*visblty,4) &&
strlen(*visblty) >= 4)
{
if( strcmp(*visblty+4,"NE") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"NW") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"SE") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"SW") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"N") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"S") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"E") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( strcmp(*visblty+4,"W") == 0 )
{
memset(Mptr->vsby_Dir,'\0',3);
strcpy(Mptr->vsby_Dir,*visblty+4);
}
if( antoi(*visblty,
strlen(*visblty)) >= 50 &&
antoi(*visblty,
strlen(*visblty)) <= 500 &&
(antoi(*visblty,
strlen(*visblty)) % 50) == 0 )
{
Mptr->prevail_vsbyM =
(float) (antoi(*visblty,
strlen(*visblty)));
(*NDEX)++;
return TRUE;
}
else if( antoi(*visblty,
strlen(*visblty)) >= 500 &&
antoi(*visblty,
strlen(*visblty)) <= 3000 &&
(antoi(*visblty,
strlen(*visblty)) % 100) == 0 )
{
Mptr->prevail_vsbyM =
(float) (antoi(*visblty,
strlen(*visblty)));
(*NDEX)++;
return TRUE;
}
else if( antoi(*visblty,
strlen(*visblty)) >= 3000 &&
antoi(*visblty,
strlen(*visblty)) <= 5000 &&
(antoi(*visblty,
strlen(*visblty)) % 500) == 0 )
{
Mptr->prevail_vsbyM =
(float) (antoi(*visblty,
strlen(*visblty)));
(*NDEX)++;
return TRUE;
}
else if( antoi(*visblty,
strlen(*visblty)) >= 5000 &&
antoi(*visblty,
strlen(*visblty)) <= 9999 &&
(antoi(*visblty,
strlen(*visblty)) % 500) == 0 ||
antoi(*visblty,
strlen(*visblty)) == 9999 )
{
Mptr->prevail_vsbyM =
(float) (antoi(*visblty,
strlen(*visblty)));
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: vrblVsby */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
#if 0
static bool vrblVsby( char *string1, char *string2,
Decoded_METAR *Mptr, int *NDEX )
{
char buf[ 6 ];
/* int numerator,
denominator; */
char *slash,
*V_char,
*temp;
if( string1 == NULL )
return FALSE;
V_char = strchr(string1,'V');
slash = strchr(string1,'/');
if(slash == NULL)
{
if(nisdigit(string1,V_char-string1))
{
memset(buf, '\0', 6);
strncpy(buf, string1, V_char-string1);
if( Mptr->minVsby != (float) MAXINT )
Mptr->minVsby += (float) atoi(buf);
else
Mptr->minVsby = (float) atoi(buf);
memset(buf, '\0', 6);
strncpy(buf, V_char+1, 5);
Mptr->maxVsby = (float) atoi(buf);
}
else
return FALSE;
}
else
{
temp = (char *) malloc(sizeof(char)*((V_char-string1)+1));
memset(temp, '\0', (V_char-string1) +1);
strncpy(temp, string1, V_char-string1);
if( Mptr->minVsby != MAXINT )
Mptr->minVsby += fracPart(temp);
else
Mptr->minVsby = fracPart(temp);
free( temp );
if( strchr(V_char+1,'/') != NULL)
Mptr->maxVsby = fracPart(V_char+1);
else
Mptr->maxVsby = (float) atoi(V_char+1);
}
if( string2 == NULL )
return TRUE;
else
{
slash = strchr( string2, '/' );
if( slash == NULL )
return TRUE;
else
{
if( nisdigit(string2,slash-string2) &&
nisdigit(slash+1,strlen(slash+1)) )
{
Mptr->maxVsby += fracPart(string2);
(*NDEX)++;
}
return TRUE;
}
}
}
#endif
/********************************************************************/
/* */
/* Title: isMinMaxWinDir */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isMinMaxWinDir( char *string, Decoded_METAR *Mptr,
int *NDEX )
{
#define buf_len 50
char buf[ buf_len ];
char *V_char;
if( string == NULL )
return FALSE;
if( (V_char = strchr(string,'V')) == NULL )
return FALSE;
else
{
if( nisdigit(string,(V_char - string)) &&
nisdigit(V_char+1,3) )
{
memset( buf, '\0', buf_len);
strncpy( buf, string, V_char - string);
Mptr->minWnDir = atoi( buf );
memset( buf, '\0', buf_len);
strcpy( buf, V_char+1 );
Mptr->maxWnDir = atoi( buf );
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
}
/********************************************************************/
/* */
/* Title: isRVR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isRVR( char *token, Decoded_METAR *Mptr, int *NDEX,
int ndex )
{
char *slashPtr, *FT_ptr;
char *vPtr;
int length;
if( token == NULL )
return FALSE;
if( *token != 'R' || (length = strlen(token)) < 7 ||
(slashPtr = strchr(token,'/')) == NULL ||
nisdigit(token+1,2) == FALSE )
return FALSE;
if( (slashPtr - (token+3)) > 0 )
if( !nisalpha(token+3,(slashPtr - (token+3))) )
return FALSE;
if( strcmp(token+(strlen(token)-2),"FT") != 0 )
return FALSE;
else
FT_ptr = token + (strlen(token)-2);
if( strchr(slashPtr+1, 'P' ) != NULL )
Mptr->RRVR[ndex].above_max_RVR = TRUE;
if( strchr(slashPtr+1, 'M' ) != NULL )
Mptr->RRVR[ndex].below_min_RVR = TRUE;
strncpy(Mptr->RRVR[ndex].runway_designator, token+1,
(slashPtr-(token+1)));
if( (vPtr = strchr(slashPtr, 'V' )) != NULL )
{
Mptr->RRVR[ndex].vrbl_visRange = TRUE;
Mptr->RRVR[ndex].Min_visRange = antoi(slashPtr+1,
(vPtr-(slashPtr+1)) );
Mptr->RRVR[ndex].Max_visRange = antoi(vPtr+1,
(FT_ptr - (vPtr+1)) );
(*NDEX)++;
return TRUE;
}
else
{
if( Mptr->RRVR[ndex].below_min_RVR ||
Mptr->RRVR[ndex].above_max_RVR )
Mptr->RRVR[ndex].visRange = antoi(slashPtr+2,
(FT_ptr - (slashPtr+2)) );
else
Mptr->RRVR[ndex].visRange = antoi(slashPtr+1,
(FT_ptr - (slashPtr+1)) );
(*NDEX)++;
return TRUE;
}
}
/********************************************************************/
/* */
/* Title: isAltimStng */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isAltimStng( char *token, Decoded_METAR *Mptr, int *NDEX )
{
char dummy[6];
if( token == NULL )
return FALSE;
if( strlen(token) < 5 )
return FALSE;
else
{
Mptr->A_altstng = FALSE;
Mptr->Q_altstng = FALSE;
if( (*token == 'A' || *token == 'Q') &&
(nisdigit(token+1, strlen(token)-1) ||
nisdigit(token+1,strlen(token)-3)) )
{
if( *token == 'A' )
{
Mptr->A_altstng = TRUE;
Mptr->inches_altstng = atof(token+1) * 0.01;
}
else
{
Mptr->Q_altstng = TRUE;
if( strchr(token,'.') != NULL)
{
memset(dummy, '\0', 6);
strncpy(dummy,token+1,4);
Mptr->hectoPasc_altstng = atoi(dummy);
}
else
Mptr->hectoPasc_altstng = atoi(token+1);
}
(*NDEX)++;
return TRUE;
}
return FALSE;
}
}
/********************************************************************/
/* */
/* Title: isTempGroup */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isTempGroup( char *token, Decoded_METAR *Mptr, int *NDEX)
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
char *slash;
if( token == NULL )
return FALSE;
if( (slash = strchr(token,'/')) == NULL)
return FALSE;
else
{
if( charcmp(token,"aa'/'dd") ) {
Mptr->dew_pt_temp = atoi(slash+1);
(*NDEX)++;
return TRUE;
}
else if( charcmp(token,"aa'/''M'dd") ) {
Mptr->dew_pt_temp = atoi(slash+2) * -1;
(*NDEX)++;
return TRUE;
}
else if( charcmp(token,"dd'/'aa") ) {
Mptr->temp = antoi(token,(slash-token));
(*NDEX)++;
return TRUE;
}
else if( charcmp(token,"'M'dd'/'aa") ) {
Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
(*NDEX)++;
return TRUE;
}
else if( nisdigit(token,(slash-token)) &&
nisdigit(slash+1,strlen(slash+1)) )
{
Mptr->temp = antoi(token,(slash-token));
Mptr->dew_pt_temp = atoi(slash+1);
(*NDEX)++;
return TRUE;
}
else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
&& *(slash+1) != '\0' &&
*(slash+1) == 'M' && nisdigit(slash+2,strlen(slash+2)) )
{
Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
Mptr->dew_pt_temp = atoi(slash+2) * -1;
(*NDEX)++;
return TRUE;
}
else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
&& *(slash+1) != '\0' &&
nisdigit(slash+1,strlen(slash+1)) )
{
Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
Mptr->dew_pt_temp = atoi(slash+1);
(*NDEX)++;
return TRUE;
}
else if( nisdigit(token,(slash - token)) &&
*(slash+1) != '\0' &&
nisdigit(slash+2,strlen(slash+2)) )
{
Mptr->temp = antoi(token,(slash-token));
Mptr->dew_pt_temp = atoi(slash+2) * -1;
(*NDEX)++;
return TRUE;
}
else if( nisdigit(token,(slash-token)) &&
strlen(token) <= 3)
{
Mptr->temp = antoi(token,(slash-token));
(*NDEX)++;
return TRUE;
}
else if( *token == 'M' &&
nisdigit(token+1,(slash-(token+1))) &&
strlen(token) <= 4)
{
Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
}
/********************************************************************/
/* */
/* Title: isWxToken */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
/*static bool isWxToken( char *token )
{
int i;
if( token == NULL )
return FALSE;
for( i = 0; i < (int)strlen(token); i++ )
{
if( !(isalpha(*(token+i)) || *(token+i) == '+' ||
*(token+i) == '-' ) )
return FALSE;
}
return TRUE;
}*/
/********************************************************************/
/* */
/* Title: isPresentWX */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isPresentWX( char *token, Decoded_METAR *Mptr,
int *NDEX, int *next )
{
/*
static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
"DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
"FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
"PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
"SHGR", "SN", "SG", "SQ", "SA", "SS", "TSRA",
"TSSN", "TSPE", "TSGS", "TSGR", "TS", "VA", "VCFG", "VCFC",
"VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
*/
static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
"BR", "FZBR", "VCBR",
"DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
"FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
"PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
"SHGR", "SN", "SG", "SQ", "SA", "SS", "TS",
"VA", "VCFG", "VCFC",
"VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
int i;
char *ptr,
*temp_token,
*save_token,
*temp_token_orig;
if( token == NULL)
return FALSE;
temp_token_orig = temp_token =
(char *) malloc(sizeof(char)*(strlen(token)+1));
strcpy(temp_token, token);
while( temp_token != NULL && (*next) < MAXWXSYMBOLS )
{
i = 0;
save_token = NULL;
if( *temp_token == '+' || *temp_token == '-' )
{
save_token = temp_token;
temp_token++;
}
while( WxSymbols[i] != NULL )
if( strncmp(temp_token, WxSymbols[i],
strlen(WxSymbols[i])) != 0 )
i++;
else
break;
if( WxSymbols[i] == NULL ) {
free( temp_token_orig );
return FALSE;
}
else
{
if( save_token != NULL )
{
strncpy( Mptr->WxObstruct[*next], save_token, 1);
strcpy( (Mptr->WxObstruct[*next])+1,
WxSymbols[i]);
(*next)++;
}
else
{
strcpy( Mptr->WxObstruct[*next], WxSymbols[i]);
(*next)++;
}
if( strcmp(temp_token, WxSymbols[i]) != 0)
{
ptr = strstr(temp_token, WxSymbols[i]);
temp_token = ptr + strlen(WxSymbols[i]);
}
else
{
free( temp_token_orig );
temp_token = NULL;
(*NDEX)++;
return TRUE;
}
}
}
free( temp_token_orig );
return FALSE;
}
/********************************************************************/
/* */
/* Title: isStnID */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isStnId( char *stnID, Decoded_METAR *Mptr, int *NDEX)
{
if( stnID == NULL )
return FALSE;
if( strlen(stnID) == 4 )
{
if( nisalpha(stnID,1) && nisalnum(stnID+1,3) ) {
strcpy(Mptr->stnid,stnID);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isCodeName */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isCodeName( char *codename, Decoded_METAR *Mptr, int *NDEX)
{
if( codename == NULL )
return FALSE;
if( strcmp(codename,"METAR") == 0 ||
strcmp(codename,"SPECI") == 0 )
{
strcpy(Mptr->codeName, codename );
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isNIL */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isNIL( char *token, Decoded_METAR *Mptr, int *NDEX)
{
if( token == NULL )
return FALSE;
if( strcmp(token, "NIL") == 0 )
{
Mptr->NIL_rpt = TRUE;
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isAUTO */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isAUTO( char *token, Decoded_METAR *Mptr, int *NDEX)
{
if( token == NULL )
return FALSE;
if( strcmp(token, "AUTO") == 0 )
{
Mptr->AUTO = TRUE;
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isCOR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 24 Apr 1996 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isCOR ( char *token, Decoded_METAR *Mptr, int *NDEX)
{
if( token == NULL )
return FALSE;
if( strcmp(token, "COR") == 0 )
{
Mptr->COR = TRUE;
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isTimeUTC */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isTimeUTC( char *UTC, Decoded_METAR *Mptr, int *NDEX )
{
if( UTC == NULL )
return FALSE;
if( strlen( UTC ) == 4 ) {
if(nisdigit(UTC,4) ) {
Mptr->ob_hour = antoi(UTC,2);
Mptr->ob_minute = antoi(UTC+2,2);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else if( strlen( UTC ) == 6 ) {
if(nisdigit(UTC,6) ) {
Mptr->ob_date = antoi(UTC,2);
Mptr->ob_hour = antoi(UTC+2,2);
Mptr->ob_minute = antoi(UTC+4,2);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
if( strlen( UTC ) == 5 ) {
if(nisdigit(UTC,4) && (*(UTC+4) == 'Z') ) {
Mptr->ob_hour = antoi(UTC,2);
Mptr->ob_minute = antoi(UTC+2,2);
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else if( strlen( UTC ) == 7 ) {
if(nisdigit(UTC,6) && (*(UTC+6) == 'Z') ) {
Mptr->ob_date = antoi(UTC,2);
Mptr->ob_hour = antoi(UTC+2, 2);
Mptr->ob_minute = antoi(UTC+4, 2 );
(*NDEX)++;
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: isWindData */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 15 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: */
/* */
/* External Functions Called: */
/* None. */
/* */
/* Input: x */
/* */
/* Output: x */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
static bool isWindData( char *wind, Decoded_METAR *Mptr, int *NDEX )
{
char *GustPtr,
*unitsPtr;
char dummy[8];
if( wind == NULL )
return FALSE;
if( strlen(wind) < 7 )
return FALSE;
memset(dummy,'\0',8);
if( ( unitsPtr = strstr( wind, "KMH" ) ) != NULL )
strcpy( dummy, "KMH" );
else if( (unitsPtr = strstr( wind, "KT") ) != NULL )
strcpy( dummy, "KT" );
else if( (unitsPtr = strstr( wind, "MPS") ) != NULL )
strcpy( dummy, "MPS" );
else
return FALSE;
if( (GustPtr = strchr( wind, 'G' )) != NULL )
{
if( (nisdigit(wind,(GustPtr-wind)) ||
(strncmp(wind,"VRB",3) == 0 &&
nisdigit(wind+3,(GustPtr-(wind+3))))) &&
nisdigit(GustPtr+1,(unitsPtr-(GustPtr+1))) &&
((GustPtr-wind) >= 5 && (GustPtr-wind) <= 6) &&
((unitsPtr-(GustPtr+1)) >= 2 &&
(unitsPtr-(GustPtr+1)) <= 3) )
{
if( strncmp(wind,"VRB",3) == 0 )
Mptr->winData.windVRB = TRUE;
else
Mptr->winData.windDir = antoi(wind,3);
Mptr->winData.windSpeed = antoi(wind+3, (GustPtr-(wind+3)));
Mptr->winData.windGust = antoi(GustPtr+1,(unitsPtr-
(GustPtr+1)));
(*NDEX)++;
strcpy( Mptr->winData.windUnits, dummy );
return TRUE;
}
else
return FALSE;
}
else if( nisdigit(wind,(unitsPtr-wind)) ||
(strncmp(wind,"VRB",3) == 0 &&
nisdigit(wind+3,(unitsPtr-(wind+3)))) &&
((unitsPtr-wind) >= 5 && (unitsPtr-wind) <= 6) )
{
if( strncmp(wind,"VRB",3) == 0 )
Mptr->winData.windVRB = TRUE;
else
Mptr->winData.windDir = antoi(wind, 3);
Mptr->winData.windSpeed = antoi(wind+3,(unitsPtr-(wind+3)));
(*NDEX)++;
strcpy( Mptr->winData.windUnits, dummy );
return TRUE;
}
else
return FALSE;
}
/********************************************************************/
/* */
/* Title: DcdMETAR */
/* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
/* Date: 14 Sep 1994 */
/* Programmer: CARL MCCALLA */
/* Language: C/370 */
/* */
/* Abstract: DcdMETAR takes a pointer to a METAR report char- */
/* acter string as input, decodes the report, and */
/* puts the individual decoded/parsed groups into */
/* a structure that has the variable type */
/* Decoded_METAR. */
/* */
/* Input: string - a pointer to a METAR report character */
/* string. */
/* */
/* Output: Mptr - a pointer to a structure that has the */
/* variable type Decoded_METAR. */
/* */
/* Modification History: */
/* None. */
/* */
/********************************************************************/
int DcdMETAR( char *string , Decoded_METAR *Mptr )
{
/***************************/
/* DECLARE LOCAL VARIABLES */
/***************************/
enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
AUTO, COR, windData, MinMaxWinDir,
CAVOK, visibility,
RVR, presentWX, PartialObscur,
skyCond, tempGroup,
altimStng, NotIDed = 99 }
StartGroup, SaveStartGroup, MetarGroup;
// WindStruct *WinDataPtr;
int ndex;
int NDEX;
// int i, jkj, j;
char **token,
*delimeters = {" "};
bool IS_NOT_RMKS;
/*********************************/
/* BEGIN THE BODY OF THE ROUTINE */
/*********************************/
/********************************************************/
/* ONLY PARSE OR DECOCODE NON-NULL METAR REPORT STRINGS */
/********************************************************/
if( string == NULL )
return 8;
/*****************************************/
/* INITIALIZE STRUCTURE THAT HAS THE */
/* VARIABLE TYPE Decoded_METAR */
/*****************************************/
InitDcdMETAR( Mptr );
#ifdef DEBUGZZ
printf("DcdMETAR: Returned from InitDcdMETAR\n");
#endif
/****************************************************/
/* TOKENIZE AND STORE THE INPUT METAR REPORT STRING */
/****************************************************/
#ifdef DEBUGZZ
printf("DcdMETAR: Before start of tokenizing, string = %s\n",
string);
#endif
token = SaveTokenString( string, delimeters );
/*********************************************************/
/* DECODE THE METAR REPORT (POSITIONAL ORDER PRECEDENCE) */
/*********************************************************/
NDEX = 0;
MetarGroup = codename;
IS_NOT_RMKS = TRUE;
#ifdef DEBUGZZ
printf("DcdMETAR: token[0] = %s\n",token[0]);
#endif
while( token[NDEX] != NULL && IS_NOT_RMKS ) {
#ifdef DEBUGZZ
if( strcmp(token[0],"OPKC") == 0 || strcmp(token[0],"MDSD") == 0 )
printf("DcdMETAR: token[%d] = %s\n",NDEX,token[NDEX]);
#endif
#ifdef DEBUGZZ
printf("DcdMETAR: Token[%d] = %s\n",NDEX,token[NDEX]);
#endif
#ifdef DEBUGZZ
printf("DcdMETAR: MetarGroup = %d\n",MetarGroup);
#endif
if( strcmp( token[NDEX], "RMK" ) != 0 ) {
StartGroup = NotIDed;
#ifdef DEBUGZZ
printf("DcdMETAR: StartGroup = %d\n",StartGroup);
printf("DcdMETAR: SaveStartGroup = %d\n",SaveStartGroup);
#endif
/**********************************************/
/* SET ID_break_CODE TO ITS DEFAULT VALUE OF */
/* 99, WHICH MEANS THAT NO SUCCESSFUL ATTEMPT */
/* WAS MADE TO DECODE ANY METAR CODED GROUP */
/* FOR THIS PASS THROUGH THE DECODING LOOP */
/**********************************************/
switch( MetarGroup ) {
case( codename ):
if( isCodeName( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = codename;
MetarGroup = stnid;
break;
case( stnid ):
if( isStnId( token[NDEX], Mptr, &NDEX ) ) {
SaveStartGroup = StartGroup = stnid;
MetarGroup = NIL1;
}
else {
#ifdef DEBUGZZ
printf("DcdMETAR: token[%d] = %s\n",NDEX,token[NDEX]);
#endif
freeTokens( token );
return 12;
}
break;
case( NIL1 ):
if( isNIL( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = NIL1;
MetarGroup = COR1;
break;
case( COR1 ):
if( isCOR( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = COR1;
MetarGroup = obDateTime;
break;
case( obDateTime ):
/*
if( isTimeUTC( token[NDEX], Mptr, &NDEX ) ) {
SaveStartGroup = StartGroup = obDateTime;
MetarGroup = NIL2;
}
else {
freeTokens( token );
return 12;
}
break;
*/
if( isTimeUTC( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = obDateTime;
MetarGroup = NIL2;
break;
case( NIL2 ):
if( isNIL( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = NIL2;
MetarGroup = AUTO;
break;
case( AUTO ):
if( isAUTO( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = AUTO;
MetarGroup = COR;
break;
case( COR ):
if( isCOR( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = COR;
MetarGroup = windData;
break;
case( windData ):
if( isWindData( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = windData;
MetarGroup = MinMaxWinDir;
break;
case( MinMaxWinDir ):
if( isMinMaxWinDir( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = MinMaxWinDir;
MetarGroup = CAVOK;
break;
case( CAVOK ):
if( isCAVOK( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = CAVOK;
MetarGroup = visibility;
break;
case( visibility ):
if( isVisibility( &(token[NDEX]), Mptr, &NDEX ) )
SaveStartGroup = StartGroup = visibility;
MetarGroup = RVR;
break;
case( RVR ):
ndex = 0;
MetarGroup = presentWX;
while (isRVR( token[NDEX], Mptr, &NDEX, ndex ) &&
ndex < 12 ) {
ndex++;
SaveStartGroup = StartGroup = RVR;
MetarGroup = presentWX;
}
break;
case( presentWX ):
ndex = 0;
MetarGroup = skyCond;
while( isPresentWX( token[NDEX], Mptr, &NDEX,
&ndex ) && ndex < MAXWXSYMBOLS) {
SaveStartGroup = StartGroup = presentWX;
MetarGroup = PartialObscur;
}
break;
case( PartialObscur ):
if( isPartObscur( &(token[NDEX]), Mptr, &NDEX ) )
SaveStartGroup = StartGroup = PartialObscur;
MetarGroup = skyCond;
break;
case( skyCond ):
if( isSkyCond( &(token[NDEX]), Mptr, &NDEX ) )
SaveStartGroup = StartGroup = skyCond;
MetarGroup = tempGroup;
break;
case( tempGroup ):
if( isTempGroup( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = tempGroup;
MetarGroup = altimStng;
break;
case( altimStng ):
if( isAltimStng( token[NDEX], Mptr, &NDEX ) )
SaveStartGroup = StartGroup = altimStng;
MetarGroup = NotIDed;
break;
default:
NDEX++;
MetarGroup = SaveStartGroup;
/* MetarGroup = ResetMETARGroup( StartGroup,
SaveStartGroup ); */
break;
}
}
else
IS_NOT_RMKS = FALSE;
}
#ifdef DEBUGZZ
printf("DcdMETAR: while loop exited, Token[%d] = %s\n",
NDEX,token[NDEX]);
#endif
/******************************/
/* DECODE GROUPS FOUND IN THE */
/* REMARKS SECTION OF THE */
/* METAR REPORT */
/******************************/
if( token[NDEX] != NULL )
if( strcmp( token[NDEX], "RMK" ) == 0 )
DcdMTRmk( token, Mptr );
/****************************************/
freeTokens( token ); /* FREE THE STORAGE ALLOCATED FOR THE */
/* ARRAY USED TO HOLD THE METAR REPORT */
/* GROUPS */
/****************************************/
return 0;
}