1 #pragma comment (compiler)
2 //#pragma comment (date)
3 //#pragma comment (timestamp)
7 #include "Local.h" /* standard header file */
8 #include "Metar.h" /* standard header file */
10 float fracPart( char * );
11 void DcdMTRmk( char **, Decoded_METAR * );
16 #pragma subtitle("subtitle - Decode METAR report. ")
17 /********************************************************************/
19 /* Title: SaveTokenString */
20 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
21 /* Date: 14 Sep 1994 */
22 /* Programmer: CARL MCCALLA */
25 /* Abstract: SaveTokenString tokenizes the input character */
26 /* string based upon the delimeter set supplied */
27 /* by the calling routine. The elements tokenized */
28 /* from the input character string are saved in an */
29 /* array of pointers to characters. The address of */
30 /* this array is the output from this function. */
32 /* Input: string - a pointer to a character string. */
34 /* delimeters - a pointer to a string of 1 or more */
35 /* characters that are used for token- */
36 /* izing the input character string. */
38 /* Output: token - the address of a pointer to an array of */
39 /* pointers to character strings. The */
40 /* array of pointers are the addresses of */
41 /* the character strings that are token- */
42 /* ized from the input character string. */
45 /* Modification History: */
48 /********************************************************************/
51 static char **SaveTokenString ( char *string , char *delimeters )
54 /***************************/
55 /* DECLARE LOCAL VARIABLES */
56 /***************************/
59 static char *token[ MAXTOKENS ],
63 /*********************************/
64 /* BEGIN THE BODY OF THE ROUTINE */
65 /*********************************/
67 /******************************************/
68 /* TOKENIZE THE INPUT CHARACTER STRING */
69 /* AND SAVE THE TOKENS TO THE token ARRAY */
70 /******************************************/
73 TOKEN = strtok( string, delimeters);
78 token[NDEX] = (char *) malloc(sizeof(char)*(strlen(TOKEN)+1));
79 strcpy( token[ NDEX ], TOKEN );
82 while ( token[NDEX] != NULL )
85 TOKEN = strtok( NULL, delimeters );
89 token[NDEX] = (char *)
90 malloc(sizeof(char)*(strlen(TOKEN)+1));
91 strcpy( token[NDEX], TOKEN );
94 token[ NDEX ] = TOKEN;
103 #pragma subtitle(" ")
104 #pragma subtitle("subtitle - Decode METAR report. ")
105 /********************************************************************/
107 /* Title: freeTokens */
108 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
109 /* Date: 14 Sep 1994 */
110 /* Programmer: CARL MCCALLA */
111 /* Language: C/370 */
113 /* Abstract: freeTokens frees the storage allocated for the */
114 /* character strings stored in the token array. */
116 /* Input: token - the address of a pointer to an array */
117 /* of string tokens. */
123 /* Modification History: */
126 /********************************************************************/
129 static void freeTokens( char **token )
134 while( *(token+NDEX) != NULL )
136 free( *(token+NDEX) );
141 #pragma subtitle(" ")
143 #pragma subtitle("subtitle - description ")
144 /********************************************************************/
146 /* Title: InitDcdMETAR */
147 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
148 /* Date: 15 Sep 1994 */
149 /* Programmer: CARL MCCALLA */
150 /* Language: C/370 */
152 /* Abstract: InitDcdMETAR initializes every member of the */
153 /* structure addressed by the pointer Mptr. */
155 /* External Functions Called: */
158 /* Input: Mptr - ptr to a decoded_METAR structure. */
162 /* Modification History: */
165 /********************************************************************/
167 static void InitDcdMETAR( Decoded_METAR *Mptr )
170 /***************************/
171 /* DECLARE LOCAL VARIABLES */
172 /***************************/
180 /*************************/
181 /* START BODY OF ROUTINE */
182 /*************************/
184 memset(Mptr->TS_LOC,'\0',3);
185 memset(Mptr->TS_MOVMNT,'\0',3);
188 memset(Mptr->TornadicType,'\0',15);
189 memset(Mptr->TornadicLOC,'\0',10);
190 memset(Mptr->TornadicDIR,'\0',4);
191 memset(Mptr->TornadicMovDir,'\0',3);
192 Mptr->BTornadicHour = MAXINT;
193 Mptr->BTornadicMinute = MAXINT;
194 Mptr->ETornadicHour = MAXINT;
195 Mptr->ETornadicMinute = MAXINT;
196 Mptr->TornadicDistance = MAXINT;
198 memset( Mptr->autoIndicator,'\0', 5 );
202 Mptr->GR_Size = (float) MAXINT;
205 memset(Mptr->CHINO_LOC, '\0', 6);
208 memset(Mptr->VISNO_LOC, '\0', 6);
212 Mptr->FZRANO = FALSE;
214 Mptr->DollarSign = FALSE;
215 Mptr->hourlyPrecip = (float) MAXINT;
217 Mptr->ObscurAloftHgt = MAXINT;
218 memset(Mptr->ObscurAloft, '\0', 12);
219 memset(Mptr->ObscurAloftSkyCond, '\0', 12);
221 memset(Mptr->VrbSkyBelow, '\0', 4);
222 memset(Mptr->VrbSkyAbove, '\0', 4);
223 Mptr->VrbSkyLayerHgt = MAXINT;
225 Mptr->SectorVsby = (float) MAXINT;
226 memset( Mptr->SectorVsby_Dir, '\0', 3);
228 memset(Mptr->codeName, '\0', 6);
229 memset(Mptr->stnid, '\0', 5);
230 Mptr->ob_hour = MAXINT;
231 Mptr->ob_minute = MAXINT;
232 Mptr->ob_date = MAXINT;
234 memset(Mptr->synoptic_cloud_type, '\0', 6);
236 Mptr->CloudLow = '\0';
237 Mptr->CloudMedium = '\0';
238 Mptr->CloudHigh = '\0';
240 memset(Mptr->snow_depth_group, '\0', 6);
241 Mptr->snow_depth = MAXINT;
243 Mptr->Temp_2_tenths = (float) MAXINT;
244 Mptr->DP_Temp_2_tenths = (float) MAXINT;
246 Mptr->OCNL_LTG = FALSE;
247 Mptr->FRQ_LTG = FALSE;
248 Mptr->CNS_LTG = FALSE;
249 Mptr->CG_LTG = FALSE;
250 Mptr->IC_LTG = FALSE;
251 Mptr->CC_LTG = FALSE;
252 Mptr->CA_LTG = FALSE;
253 Mptr->AP_LTG = FALSE;
254 Mptr->OVHD_LTG = FALSE;
255 Mptr->DSNT_LTG = FALSE;
256 Mptr->VcyStn_LTG = FALSE;
257 Mptr->LightningVCTS = FALSE;
258 Mptr->LightningTS = FALSE;
260 memset( Mptr->LTG_DIR, '\0', 3);
263 for( i = 0; i < 3; i++)
265 memset(Mptr->ReWx[i].Recent_weather, '\0', 5);
267 Mptr->ReWx[i].Bhh = MAXINT;
268 Mptr->ReWx[i].Bmm = MAXINT;
270 Mptr->ReWx[i].Ehh = MAXINT;
271 Mptr->ReWx[i].Emm = MAXINT;
275 Mptr->NIL_rpt = FALSE;
279 Mptr->winData.windDir = MAXINT;
280 Mptr->winData.windSpeed = MAXINT;
281 Mptr->winData.windGust = MAXINT;
282 Mptr->winData.windVRB = FALSE;
283 memset(Mptr->winData.windUnits, '\0', 4);
285 Mptr->minWnDir = MAXINT;
286 Mptr->maxWnDir = MAXINT;
288 memset(Mptr->horiz_vsby, '\0', 5);
289 memset(Mptr->dir_min_horiz_vsby, '\0', 3);
291 Mptr->prevail_vsbySM = (float) MAXINT;
292 Mptr->prevail_vsbyM = (float) MAXINT;
293 Mptr->prevail_vsbyKM = (float) MAXINT;
295 memset(Mptr->vsby_Dir, '\0', 3);
299 for ( i = 0; i < 12; i++ )
301 memset(Mptr->RRVR[ i ].runway_designator,
304 Mptr->RRVR[ i ].visRange = MAXINT;
306 Mptr->RRVR[ i ].vrbl_visRange = FALSE;
307 Mptr->RRVR[ i ].below_min_RVR = FALSE;
308 Mptr->RRVR[ i ].above_max_RVR = FALSE;
311 Mptr->RRVR[ i ].Max_visRange = MAXINT;
312 Mptr->RRVR[ i ].Min_visRange = MAXINT;
315 Mptr->DVR.visRange = MAXINT;
316 Mptr->DVR.vrbl_visRange = FALSE;
317 Mptr->DVR.below_min_DVR = FALSE;
318 Mptr->DVR.above_max_DVR = FALSE;
319 Mptr->DVR.Max_visRange = MAXINT;
320 Mptr->DVR.Min_visRange = MAXINT;
322 for ( i = 0; i < 5; i++ )
324 for( j = 0; j < 8; j++ )
325 Mptr->WxObstruct[i][j] = '\0';
328 /***********************/
329 /* PARTIAL OBSCURATION */
330 /***********************/
332 memset( &(Mptr->PartialObscurationAmt[0][0]), '\0', 7 );
333 memset( &(Mptr->PartialObscurationPhenom[0][0]), '\0',12);
335 memset( &(Mptr->PartialObscurationAmt[1][0]), '\0', 7 );
336 memset( &(Mptr->PartialObscurationPhenom[1][0]), '\0',12);
339 /***************************************************/
340 /* CLOUD TYPE, CLOUD LEVEL, AND SIGNIFICANT CLOUDS */
341 /***************************************************/
344 for ( i = 0; i < 6; i++ )
346 memset(Mptr->cldTypHgt[ i ].cloud_type,
349 memset(Mptr->cldTypHgt[ i ].cloud_hgt_char,
352 Mptr->cldTypHgt[ i ].cloud_hgt_meters = MAXINT;
354 memset(Mptr->cldTypHgt[ i ].other_cld_phenom,
358 Mptr->VertVsby = MAXINT;
361 Mptr->dew_pt_temp = MAXINT;
365 Mptr->SLP = (float) MAXINT;
367 Mptr->A_altstng = FALSE;
368 Mptr->inches_altstng = (double) MAXINT;
370 Mptr->Q_altstng = FALSE;
371 Mptr->hectoPasc_altstng = MAXINT;
373 Mptr->char_prestndcy = MAXINT;
374 Mptr->prestndcy = (float) MAXINT;
376 Mptr->precip_amt = (float) MAXINT;
378 Mptr->precip_24_amt = (float) MAXINT;
379 Mptr->maxtemp = (float) MAXINT;
380 Mptr->mintemp = (float) MAXINT;
381 Mptr->max24temp = (float) MAXINT;
382 Mptr->min24temp = (float) MAXINT;
385 memset( Mptr->VIRGA_DIR, '\0', 3 );
387 Mptr->VOLCASH = FALSE;
389 Mptr->minCeiling = MAXINT;
390 Mptr->maxCeiling = MAXINT;
392 Mptr->CIG_2ndSite_Meters = MAXINT;
393 memset(Mptr->CIG_2ndSite_LOC, '\0', 10 );
395 Mptr->minVsby = (float) MAXINT;
396 Mptr->maxVsby = (float) MAXINT;
397 Mptr->VSBY_2ndSite = (float) MAXINT;
398 memset(Mptr->VSBY_2ndSite_LOC,'\0',10);
400 for( i = 0; i < 6; i++ )
401 memset (&(Mptr->SfcObscuration[i][0]), '\0', 10);
403 Mptr->Num8thsSkyObscured = MAXINT;
405 Mptr->Indeterminant3_6HrPrecip = FALSE;
407 Mptr->Ceiling = MAXINT;
408 Mptr->Estimated_Ceiling = MAXINT;
410 Mptr->NOSPECI = FALSE;
413 Mptr->SNINCR = MAXINT;
414 Mptr->SNINCR_TotalDepth = MAXINT;
416 Mptr->WaterEquivSnow = (float) MAXINT;
418 Mptr->SunshineDur = MAXINT;
419 Mptr->SunSensorOut = FALSE;
422 Mptr->WshfTime_hour = MAXINT;
423 Mptr->WshfTime_minute = MAXINT;
424 Mptr->Wshft_FROPA = FALSE;
425 Mptr->min_vrbl_wind_dir = MAXINT;
426 Mptr->max_vrbl_wind_dir = MAXINT;
428 Mptr->PRESRR = FALSE;
429 Mptr->PRESFR = FALSE;
431 Mptr->TWR_VSBY = (float) MAXINT;
432 Mptr->SFC_VSBY = (float) MAXINT;
434 Mptr->PKWND_dir = MAXINT;
435 Mptr->PKWND_speed = MAXINT;
436 Mptr->PKWND_hour = MAXINT;
437 Mptr->PKWND_minute = MAXINT;
442 #pragma subtitle(" ")
444 #pragma subtitle("subtitle - description ")
445 /********************************************************************/
447 /* Title: ResetMETARGroup */
448 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
449 /* Date: 15 Sep 1994 */
450 /* Programmer: CARL MCCALLA */
451 /* Language: C/370 */
453 /* Abstract: ResetMETARGroup returns a METAR_obGroup enumerated */
454 /* variable that indicates which METAR reporting group */
455 /* might next appear in the METAR report and should be */
456 /* considered for decoding. */
458 /* External Functions Called: */
461 /* Input: StartGroup - a METAR_obGroup variable that */
462 /* indicates where or on what group */
463 /* METAR Decoding began. */
465 /* SaveStartGroup - a METAR_obGroup variable that */
466 /* indicates the reporting group */
467 /* in the METAR report that was */
468 /* successfully decoded. */
470 /* Output: A METAR_obGroup variable that indicates which */
471 /* reporting group in the METAR report should next */
472 /* be considered for decoding */
474 /* Modification History: */
477 /********************************************************************/
479 static int ResetMETARGroup( int StartGroup,
483 enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
484 AUTO, COR, windData, MinMaxWinDir,
486 RVR, presentWX, skyCond, tempGroup,
487 altimStng, NotIDed = 99};
489 if( StartGroup == NotIDed && SaveStartGroup == NotIDed )
491 else if( StartGroup == NotIDed && SaveStartGroup != NotIDed &&
492 SaveStartGroup != altimStng )
493 return (++SaveStartGroup);
495 return (++SaveStartGroup);
500 #pragma subtitle(" ")
502 #pragma subtitle("subtitle - description ")
503 /********************************************************************/
505 /* Title: CodedHgt2Meters */
506 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
507 /* Date: 15 Sep 1994 */
508 /* Programmer: CARL MCCALLA */
509 /* Language: C/370 */
511 /* Abstract: CodedHgt2Meters converts a coded cloud height into */
514 /* External Functions Called: */
517 /* Input: token - a pointer to a METAR report group. */
518 /* Mptr - a pointer to a decoded_METAR structure. */
520 /* Output: Cloud height in meters */
522 /* Modification History: */
525 /********************************************************************/
528 static int CodedHgt2Meters( char *token, Decoded_METAR *Mptr )
531 static int maxhgt = 30000;
534 if( (hgt = atoi(token)) == 999 )
541 #pragma subtitle(" ")
543 #pragma subtitle("subtitle - description ")
544 /********************************************************************/
546 /* Title: isPartObscur */
547 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
548 /* Date: 15 Sep 1994 */
549 /* Programmer: CARL MCCALLA */
550 /* Language: C/370 */
552 /* Abstract: isPartObscur determines whether or not the METAR */
553 /* report element that is passed to it is or is not */
554 /* a partial obscuration indicator for an amount of */
558 /* External Functions Called: */
561 /* Input: token - the address of a pointer to the group */
562 /* in the METAR report that isPartObscur */
563 /* determines is or is not a partial */
564 /* obscuration indicator. */
567 /* Mptr - a pointer to a decoded_METAR structure. */
569 /* Output: TRUE, if the group is a partial obscuration */
570 /* indicator and FALSE, if it is not. */
573 /* Modification History: */
576 /********************************************************************/
578 static bool isPartObscur( char **string, Decoded_METAR *Mptr,
582 if( *string == NULL )
585 if( strcmp( *string, "FEW///" ) == 0 ||
586 strcmp( *string, "SCT///" ) == 0 ||
587 strcmp( *string, "BKN///" ) == 0 ||
588 strcmp( *string, "FEW000" ) == 0 ||
589 strcmp( *string, "SCT000" ) == 0 ||
590 strcmp( *string, "BKN000" ) == 0 ) {
591 strcpy( &(Mptr->PartialObscurationAmt[0][0]), *string );
595 if( *string == NULL )
598 if( strcmp( (*string+3), "///") ) {
599 if( strcmp( *string, "FEW000" ) == 0 ||
600 strcmp( *string, "SCT000" ) == 0 ||
601 strcmp( *string, "BKN000" ) == 0 ) {
602 strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
607 if( strcmp( *string, "FEW///" ) == 0 ||
608 strcmp( *string, "SCT///" ) == 0 ||
609 strcmp( *string, "BKN///" ) == 0 ) {
610 strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
621 #pragma subtitle(" ")
623 #pragma subtitle("subtitle - description ")
624 /********************************************************************/
626 /* Title: isCldLayer */
627 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
628 /* Date: 15 Sep 1994 */
629 /* Programmer: CARL MCCALLA */
630 /* Language: C/370 */
632 /* Abstract: isCldLayer determines whether or not the */
633 /* current group has a valid cloud layer */
637 /* External Functions Called: */
640 /* Input: token - pointer to a METAR report group. */
642 /* Output: TRUE, if the report group is a valid cloud */
643 /* layer indicator. */
645 /* FALSE, if the report group is not a valid cloud */
646 /* layer indicator. */
649 /* Modification History: */
652 /********************************************************************/
655 static bool isCldLayer( char *token )
660 if( strlen(token) < 6 )
663 return ((strncmp(token,"OVC",3) == 0 ||
664 strncmp(token,"SCT",3) == 0 ||
665 strncmp(token,"FEW",3) == 0 ||
666 strncmp(token,"BKN",3) == 0 ||
668 strncmp(token+1,"CU",2) == 0) ||
670 strncmp(token+1,"SC",2) == 0) ) &&
671 nisdigit((token+3),3)) ? TRUE:FALSE;
675 #pragma subtitle(" ")
677 #pragma subtitle("subtitle - description ")
678 /********************************************************************/
681 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
682 /* Date: 09 May 1996 */
683 /* Programmer: CARL MCCALLA */
684 /* Language: C/370 */
686 /* Abstract: isCAVOK determines whether or not the current */
687 /* group is a valid CAVOK indicator. */
690 /* External Functions Called: */
693 /* Input: token - pointer to a METAR report group. */
695 /* Output: TRUE, if the input group is a valid CAVOK */
696 /* indicator. FALSE, otherwise. */
700 /* Modification History: */
703 /********************************************************************/
706 static bool isCAVOK( char *token, Decoded_METAR *Mptr, int *NDEX )
712 if( strcmp(token, "CAVOK") != 0 )
721 #pragma subtitle(" ")
723 #pragma subtitle("subtitle - description ")
724 /********************************************************************/
726 /* Title: parseCldData */
727 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
728 /* Date: 15 Sep 1994 */
729 /* Programmer: CARL MCCALLA */
730 /* Language: C/370 */
734 /* External Functions Called: */
741 /* Modification History: */
744 /********************************************************************/
747 static void parseCldData( char *token, Decoded_METAR *Mptr, int next)
754 if( strlen(token) > 6 )
755 strncpy(Mptr->cldTypHgt[next].other_cld_phenom,token+6,
758 strncpy(Mptr->cldTypHgt[next].cloud_type,token,3);
760 strncpy(Mptr->cldTypHgt[next].cloud_hgt_char,token+3,3);
762 Mptr->cldTypHgt[next].cloud_hgt_meters =
763 CodedHgt2Meters( token+3, Mptr );
769 #pragma subtitle(" ")
771 #pragma subtitle("subtitle - description ")
772 /********************************************************************/
774 /* Title: isSkyCond */
775 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
776 /* Date: 15 Sep 1994 */
777 /* Programmer: CARL MCCALLA */
778 /* Language: C/370 */
782 /* External Functions Called: */
789 /* Modification History: */
792 /********************************************************************/
794 static bool isSkyCond( char **skycond, Decoded_METAR *Mptr,
806 /********************************************************/
807 /* INTERROGATE skycond TO DETERMINE IF "CLR" IS PRESENT */
808 /********************************************************/
810 if( *skycond == NULL )
814 if( strcmp(*skycond,"CLR") == 0)
816 strcpy(Mptr->cldTypHgt[0].cloud_type,"CLR");
818 memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
819 memset(Mptr->cldTypHgt[0].other_cld_phenom,
826 /********************************************************/
827 /* INTERROGATE skycond TO DETERMINE IF "SKC" IS PRESENT */
828 /********************************************************/
830 else if( strcmp(*skycond,"SKC") == 0)
832 strcpy(Mptr->cldTypHgt[0].cloud_type,"SKC");
834 memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
835 memset(Mptr->cldTypHgt[0].other_cld_phenom,
842 /****************************************/
843 /* INTERROGATE skycond TO DETERMINE IF */
844 /* VERTICAL VISIBILITY IS PRESENT */
845 /****************************************/
847 else if( strncmp(*skycond,"VV",2) == 0
848 && strlen(*skycond) == 5 &&
849 nisdigit((*skycond+2),3) )
851 Mptr->VertVsby = CodedHgt2Meters( (*skycond+2), Mptr);
856 /****************************************/
857 /* INTERROGATE skycond TO DETERMINE IF */
858 /* CLOUD LAYER DATA IS PRESENT */
859 /****************************************/
861 else if( isCldLayer( *skycond ))
865 parseCldData( *skycond , Mptr, next );
870 if( *skycond == NULL )
873 second_layer = FALSE;
875 fourth_layer = FALSE;
880 if( isCldLayer( *skycond ) && first_layer )
882 parseCldData( *skycond, Mptr, next );
887 if( *skycond == NULL )
892 if( isCldLayer( *skycond ) && first_layer &&
895 parseCldData( *skycond , Mptr, next );
900 if( *skycond == NULL )
905 if( isCldLayer( *skycond ) && first_layer && second_layer &&
908 parseCldData( *skycond, Mptr, next );
913 if( *skycond == NULL )
918 if( isCldLayer( *skycond ) && first_layer && second_layer &&
919 third_layer && fourth_layer )
921 parseCldData( *skycond , Mptr, next );
926 if( *skycond == NULL )
931 if( isCldLayer( *skycond ) && first_layer && second_layer &&
932 third_layer && fourth_layer && fifth_layer )
934 parseCldData( *skycond , Mptr, next );
950 else if( fifth_layer )
959 else if( fourth_layer )
967 else if( third_layer )
974 else if( second_layer )
980 else if( first_layer )
992 #pragma subtitle(" ")
994 #pragma subtitle("subtitle - description ")
995 /********************************************************************/
997 /* Title: prevailVSBY */
998 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
999 /* Date: 15 Sep 1994 */
1000 /* Programmer: CARL MCCALLA */
1001 /* Language: C/370 */
1005 /* External Functions Called: */
1012 /* Modification History: */
1015 /********************************************************************/
1017 static float prevailVSBY( char *visibility )
1027 if( (SM_KM_ptr = strstr( visibility, "SM" )) == NULL )
1028 SM_KM_ptr = strstr(visibility, "KM");
1030 Slash_ptr = strchr( visibility, '/' );
1032 if( Slash_ptr == NULL )
1034 temp = (char *) malloc(sizeof(char) *
1035 ((SM_KM_ptr - visibility)+1));
1036 memset( temp, '\0', (SM_KM_ptr-visibility)+1);
1037 strncpy( temp, visibility, (SM_KM_ptr-visibility) );
1038 Miles_vsby = (float) (atoi(temp));
1044 memset(numerator, '\0', 3);
1045 memset(denominator, '\0', 3);
1047 strncpy(numerator, visibility, (Slash_ptr - visibility));
1049 /*>>>>>>>>>>>>>>>>>>>>>>
1050 if( (SM_KM_ptr - (Slash_ptr+1)) == 0 )
1051 strcpy(denominator, "4");
1053 <<<<<<<<<<<<<<<<<<<<<<*/
1055 strncpy(denominator,
1056 Slash_ptr+1, (SM_KM_ptr - Slash_ptr));
1058 return ( ((float)(atoi(numerator)))/
1059 ((float)(atoi(denominator))) );
1064 #pragma subtitle(" ")
1066 #pragma subtitle("subtitle - description ")
1067 /********************************************************************/
1069 /* Title: isVisibility */
1070 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1071 /* Date: 15 Sep 1994 */
1072 /* Programmer: CARL MCCALLA */
1073 /* Language: C/370 */
1077 /* External Functions Called: */
1084 /* Modification History: */
1087 /********************************************************************/
1091 static bool isVisibility( char **visblty, Decoded_METAR *Mptr,
1099 /****************************************/
1100 /* CHECK FOR VISIBILITY MEASURED <1/4SM */
1101 /****************************************/
1103 if( *visblty == NULL )
1107 if( strcmp(*visblty,"M1/4SM") == 0 ||
1108 strcmp(*visblty,"<1/4SM") == 0 ) {
1109 Mptr->prevail_vsbySM = 0.0;
1114 /***********************************************/
1115 /* CHECK FOR VISIBILITY MEASURED IN KILOMETERS */
1116 /***********************************************/
1118 if( (achar = strstr(*visblty, "KM")) != NULL )
1120 if( nisdigit(*visblty,(achar - *visblty)) &&
1121 (achar - *visblty) > 0 )
1123 Mptr->prevail_vsbyKM = prevailVSBY( *visblty );
1131 /***********************************/
1132 /* CHECK FOR VISIBILITY MEASURED */
1133 /* IN A FRACTION OF A STATUTE MILE */
1134 /***********************************/
1136 else if( (achar = strchr( *visblty, '/' )) !=
1138 (astring = strstr( *visblty, "SM")) != NULL )
1140 if( nisdigit(*visblty,(achar - *visblty))
1142 (achar - *visblty) > 0 &&
1143 (astring - (achar+1)) > 0 &&
1144 nisdigit(achar+1, (astring - (achar+1))) )
1146 Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1154 /***********************************/
1155 /* CHECK FOR VISIBILITY MEASURED */
1156 /* IN WHOLE STATUTE MILES */
1157 /***********************************/
1159 else if( (astring = strstr(*visblty,"SM") ) != NULL )
1161 if( nisdigit(*visblty,(astring - *visblty)) &&
1162 (astring- *visblty) > 0 )
1164 Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1172 /***********************************/
1173 /* CHECK FOR VISIBILITY MEASURED */
1174 /* IN WHOLE AND FRACTIONAL STATUTE */
1176 /***********************************/
1178 else if( nisdigit( *visblty,
1179 strlen(*visblty)) &&
1180 strlen(*visblty) < 4 )
1182 save_token = (char *) malloc(sizeof(char)*
1183 (strlen(*visblty)+1));
1184 strcpy(save_token,*visblty);
1185 if( *(++visblty) == NULL)
1191 if( (achar = strchr( *visblty, '/' ) ) != NULL &&
1192 (astring = strstr( *visblty, "SM") ) != NULL )
1194 if( nisdigit(*visblty,
1195 (achar - *visblty)) &&
1196 (achar - *visblty) > 0 &&
1197 (astring - (achar+1)) > 0 &&
1198 nisdigit(achar+1, (astring - (achar+1))) )
1200 Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1201 Mptr->prevail_vsbySM +=
1202 (float) (atoi(save_token));
1219 /***********************************/
1220 /* CHECK FOR VISIBILITY MEASURED */
1221 /* IN METERS WITH OR WITHOUT DI- */
1222 /* RECTION OF OBSERVATION */
1223 /***********************************/
1225 else if( nisdigit(*visblty,4) &&
1226 strlen(*visblty) >= 4)
1228 if( strcmp(*visblty+4,"NE") == 0 )
1230 memset(Mptr->vsby_Dir,'\0',3);
1231 strcpy(Mptr->vsby_Dir,*visblty+4);
1233 if( strcmp(*visblty+4,"NW") == 0 )
1235 memset(Mptr->vsby_Dir,'\0',3);
1236 strcpy(Mptr->vsby_Dir,*visblty+4);
1238 if( strcmp(*visblty+4,"SE") == 0 )
1240 memset(Mptr->vsby_Dir,'\0',3);
1241 strcpy(Mptr->vsby_Dir,*visblty+4);
1243 if( strcmp(*visblty+4,"SW") == 0 )
1245 memset(Mptr->vsby_Dir,'\0',3);
1246 strcpy(Mptr->vsby_Dir,*visblty+4);
1248 if( strcmp(*visblty+4,"N") == 0 )
1250 memset(Mptr->vsby_Dir,'\0',3);
1251 strcpy(Mptr->vsby_Dir,*visblty+4);
1253 if( strcmp(*visblty+4,"S") == 0 )
1255 memset(Mptr->vsby_Dir,'\0',3);
1256 strcpy(Mptr->vsby_Dir,*visblty+4);
1258 if( strcmp(*visblty+4,"E") == 0 )
1260 memset(Mptr->vsby_Dir,'\0',3);
1261 strcpy(Mptr->vsby_Dir,*visblty+4);
1263 if( strcmp(*visblty+4,"W") == 0 )
1265 memset(Mptr->vsby_Dir,'\0',3);
1266 strcpy(Mptr->vsby_Dir,*visblty+4);
1270 strlen(*visblty)) >= 50 &&
1272 strlen(*visblty)) <= 500 &&
1274 strlen(*visblty)) % 50) == 0 )
1276 Mptr->prevail_vsbyM =
1277 (float) (antoi(*visblty,
1282 else if( antoi(*visblty,
1283 strlen(*visblty)) >= 500 &&
1285 strlen(*visblty)) <= 3000 &&
1287 strlen(*visblty)) % 100) == 0 )
1289 Mptr->prevail_vsbyM =
1290 (float) (antoi(*visblty,
1295 else if( antoi(*visblty,
1296 strlen(*visblty)) >= 3000 &&
1298 strlen(*visblty)) <= 5000 &&
1300 strlen(*visblty)) % 500) == 0 )
1302 Mptr->prevail_vsbyM =
1303 (float) (antoi(*visblty,
1308 else if( antoi(*visblty,
1309 strlen(*visblty)) >= 5000 &&
1311 strlen(*visblty)) <= 9999 &&
1313 strlen(*visblty)) % 500) == 0 ||
1315 strlen(*visblty)) == 9999 )
1317 Mptr->prevail_vsbyM =
1318 (float) (antoi(*visblty,
1332 #pragma subtitle(" ")
1334 #pragma subtitle("subtitle - description ")
1335 /********************************************************************/
1337 /* Title: vrblVsby */
1338 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1339 /* Date: 15 Sep 1994 */
1340 /* Programmer: CARL MCCALLA */
1341 /* Language: C/370 */
1345 /* External Functions Called: */
1352 /* Modification History: */
1355 /********************************************************************/
1357 static bool vrblVsby( char *string1, char *string2,
1358 Decoded_METAR *Mptr, int *NDEX )
1367 if( string1 == NULL )
1370 V_char = strchr(string1,'V');
1371 slash = strchr(string1,'/');
1375 if(nisdigit(string1,V_char-string1))
1377 memset(buf, '\0', 6);
1378 strncpy(buf, string1, V_char-string1);
1380 if( Mptr->minVsby != (float) MAXINT )
1381 Mptr->minVsby += (float) atoi(buf);
1383 Mptr->minVsby = (float) atoi(buf);
1385 memset(buf, '\0', 6);
1386 strncpy(buf, V_char+1, 5);
1387 Mptr->maxVsby = (float) atoi(buf);
1395 temp = (char *) malloc(sizeof(char)*((V_char-string1)+1));
1396 memset(temp, '\0', (V_char-string1) +1);
1397 strncpy(temp, string1, V_char-string1);
1398 if( Mptr->minVsby != MAXINT )
1399 Mptr->minVsby += fracPart(temp);
1401 Mptr->minVsby = fracPart(temp);
1405 if( strchr(V_char+1,'/') != NULL)
1406 Mptr->maxVsby = fracPart(V_char+1);
1408 Mptr->maxVsby = (float) atoi(V_char+1);
1411 if( string2 == NULL )
1415 slash = strchr( string2, '/' );
1421 if( nisdigit(string2,slash-string2) &&
1422 nisdigit(slash+1,strlen(slash+1)) )
1424 Mptr->maxVsby += fracPart(string2);
1434 #pragma subtitle(" ")
1436 #pragma subtitle("subtitle - description ")
1437 /********************************************************************/
1439 /* Title: isMinMaxWinDir */
1440 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1441 /* Date: 15 Sep 1994 */
1442 /* Programmer: CARL MCCALLA */
1443 /* Language: C/370 */
1447 /* External Functions Called: */
1454 /* Modification History: */
1457 /********************************************************************/
1459 static bool isMinMaxWinDir( char *string, Decoded_METAR *Mptr,
1463 char buf[ buf_len ];
1466 if( string == NULL )
1469 if( (V_char = strchr(string,'V')) == NULL )
1473 if( nisdigit(string,(V_char - string)) &&
1474 nisdigit(V_char+1,3) )
1476 memset( buf, '\0', buf_len);
1477 strncpy( buf, string, V_char - string);
1478 Mptr->minWnDir = atoi( buf );
1480 memset( buf, '\0', buf_len);
1481 strcpy( buf, V_char+1 );
1482 Mptr->maxWnDir = atoi( buf );
1491 #pragma subtitle(" ")
1493 #pragma subtitle("subtitle - description ")
1494 /********************************************************************/
1497 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1498 /* Date: 15 Sep 1994 */
1499 /* Programmer: CARL MCCALLA */
1500 /* Language: C/370 */
1504 /* External Functions Called: */
1511 /* Modification History: */
1514 /********************************************************************/
1517 static bool isRVR( char *token, Decoded_METAR *Mptr, int *NDEX,
1520 char *slashPtr, *FT_ptr;
1527 if( *token != 'R' || (length = strlen(token)) < 7 ||
1528 (slashPtr = strchr(token,'/')) == NULL ||
1529 nisdigit(token+1,2) == FALSE )
1532 if( (slashPtr - (token+3)) > 0 )
1533 if( !nisalpha(token+3,(slashPtr - (token+3))) )
1536 if( strcmp(token+(strlen(token)-2),"FT") != 0 )
1539 FT_ptr = token + (strlen(token)-2);
1541 if( strchr(slashPtr+1, 'P' ) != NULL )
1542 Mptr->RRVR[ndex].above_max_RVR = TRUE;
1544 if( strchr(slashPtr+1, 'M' ) != NULL )
1545 Mptr->RRVR[ndex].below_min_RVR = TRUE;
1548 strncpy(Mptr->RRVR[ndex].runway_designator, token+1,
1549 (slashPtr-(token+1)));
1551 if( (vPtr = strchr(slashPtr, 'V' )) != NULL )
1553 Mptr->RRVR[ndex].vrbl_visRange = TRUE;
1554 Mptr->RRVR[ndex].Min_visRange = antoi(slashPtr+1,
1555 (vPtr-(slashPtr+1)) );
1556 Mptr->RRVR[ndex].Max_visRange = antoi(vPtr+1,
1557 (FT_ptr - (vPtr+1)) );
1563 if( Mptr->RRVR[ndex].below_min_RVR ||
1564 Mptr->RRVR[ndex].above_max_RVR )
1565 Mptr->RRVR[ndex].visRange = antoi(slashPtr+2,
1566 (FT_ptr - (slashPtr+2)) );
1568 Mptr->RRVR[ndex].visRange = antoi(slashPtr+1,
1569 (FT_ptr - (slashPtr+1)) );
1578 #pragma subtitle(" ")
1580 #pragma subtitle("subtitle - description ")
1581 /********************************************************************/
1583 /* Title: isAltimStng */
1584 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1585 /* Date: 15 Sep 1994 */
1586 /* Programmer: CARL MCCALLA */
1587 /* Language: C/370 */
1591 /* External Functions Called: */
1598 /* Modification History: */
1601 /********************************************************************/
1604 static bool isAltimStng( char *token, Decoded_METAR *Mptr, int *NDEX )
1612 if( strlen(token) < 5 )
1616 Mptr->A_altstng = FALSE;
1617 Mptr->Q_altstng = FALSE;
1619 if( (*token == 'A' || *token == 'Q') &&
1620 (nisdigit(token+1, strlen(token)-1) ||
1621 nisdigit(token+1,strlen(token)-3)) )
1625 Mptr->A_altstng = TRUE;
1626 Mptr->inches_altstng = atof(token+1) * 0.01;
1630 Mptr->Q_altstng = TRUE;
1632 if( strchr(token,'.') != NULL)
1634 memset(dummy, '\0', 6);
1635 strncpy(dummy,token+1,4);
1636 Mptr->hectoPasc_altstng = atoi(dummy);
1639 Mptr->hectoPasc_altstng = atoi(token+1);
1651 #pragma subtitle(" ")
1653 #pragma subtitle("subtitle - description ")
1654 /********************************************************************/
1656 /* Title: isTempGroup */
1657 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1658 /* Date: 15 Sep 1994 */
1659 /* Programmer: CARL MCCALLA */
1660 /* Language: C/370 */
1664 /* External Functions Called: */
1671 /* Modification History: */
1674 /********************************************************************/
1677 static bool isTempGroup( char *token, Decoded_METAR *Mptr, int *NDEX)
1680 /***************************/
1681 /* DECLARE LOCAL VARIABLES */
1682 /***************************/
1689 if( (slash = strchr(token,'/')) == NULL)
1693 if( charcmp(token,"aa'/'dd") ) {
1694 Mptr->dew_pt_temp = atoi(slash+1);
1698 else if( charcmp(token,"aa'/''M'dd") ) {
1699 Mptr->dew_pt_temp = atoi(slash+2) * -1;
1703 else if( charcmp(token,"dd'/'aa") ) {
1704 Mptr->temp = antoi(token,(slash-token));
1708 else if( charcmp(token,"'M'dd'/'aa") ) {
1709 Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1713 else if( nisdigit(token,(slash-token)) &&
1714 nisdigit(slash+1,strlen(slash+1)) )
1716 Mptr->temp = antoi(token,(slash-token));
1717 Mptr->dew_pt_temp = atoi(slash+1);
1721 else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
1722 && *(slash+1) != '\0' &&
1723 *(slash+1) == 'M' && nisdigit(slash+2,strlen(slash+2)) )
1725 Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1726 Mptr->dew_pt_temp = atoi(slash+2) * -1;
1730 else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
1731 && *(slash+1) != '\0' &&
1732 nisdigit(slash+1,strlen(slash+1)) )
1734 Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1735 Mptr->dew_pt_temp = atoi(slash+1);
1739 else if( nisdigit(token,(slash - token)) &&
1740 *(slash+1) != '\0' &&
1741 nisdigit(slash+2,strlen(slash+2)) )
1743 Mptr->temp = antoi(token,(slash-token));
1744 Mptr->dew_pt_temp = atoi(slash+2) * -1;
1748 else if( nisdigit(token,(slash-token)) &&
1751 Mptr->temp = antoi(token,(slash-token));
1755 else if( *token == 'M' &&
1756 nisdigit(token+1,(slash-(token+1))) &&
1759 Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1771 #pragma subtitle(" ")
1773 #pragma subtitle("subtitle - description ")
1774 /********************************************************************/
1776 /* Title: isWxToken */
1777 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1778 /* Date: 15 Sep 1994 */
1779 /* Programmer: CARL MCCALLA */
1780 /* Language: C/370 */
1784 /* External Functions Called: */
1791 /* Modification History: */
1794 /********************************************************************/
1797 static bool isWxToken( char *token )
1803 for( i = 0; i < strlen(token); i++ )
1805 if( !(isalpha(*(token+i)) || *(token+i) == '+' ||
1806 *(token+i) == '-' ) )
1813 #pragma subtitle(" ")
1815 #pragma subtitle("subtitle - description ")
1816 /********************************************************************/
1818 /* Title: isPresentWX */
1819 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1820 /* Date: 15 Sep 1994 */
1821 /* Programmer: CARL MCCALLA */
1822 /* Language: C/370 */
1826 /* External Functions Called: */
1833 /* Modification History: */
1836 /********************************************************************/
1839 static bool isPresentWX( char *token, Decoded_METAR *Mptr,
1840 int *NDEX, int *next )
1843 static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
1844 "DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
1845 "FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
1846 "PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
1847 "SHGR", "SN", "SG", "SQ", "SA", "SS", "TSRA",
1848 "TSSN", "TSPE", "TSGS", "TSGR", "TS", "VA", "VCFG", "VCFC",
1849 "VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
1851 static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
1852 "BR", "FZBR", "VCBR",
1853 "DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
1854 "FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
1855 "PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
1856 "SHGR", "SN", "SG", "SQ", "SA", "SS", "TS",
1857 "VA", "VCFG", "VCFC",
1858 "VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
1868 temp_token_orig = temp_token =
1869 (char *) malloc(sizeof(char)*(strlen(token)+1));
1870 strcpy(temp_token, token);
1871 while( temp_token != NULL && (*next) < MAXWXSYMBOLS )
1876 if( *temp_token == '+' || *temp_token == '-' )
1878 save_token = temp_token;
1882 while( WxSymbols[i] != NULL )
1883 if( strncmp(temp_token, WxSymbols[i],
1884 strlen(WxSymbols[i])) != 0 )
1889 if( WxSymbols[i] == NULL ) {
1890 free( temp_token_orig );
1896 if( save_token != NULL )
1898 strncpy( Mptr->WxObstruct[*next], save_token, 1);
1899 strcpy( (Mptr->WxObstruct[*next])+1,
1905 strcpy( Mptr->WxObstruct[*next], WxSymbols[i]);
1910 if( strcmp(temp_token, WxSymbols[i]) != 0)
1912 ptr = strstr(temp_token, WxSymbols[i]);
1913 temp_token = ptr + strlen(WxSymbols[i]);
1917 free( temp_token_orig );
1927 free( temp_token_orig );
1932 #pragma subtitle(" ")
1934 #pragma subtitle("subtitle - description ")
1935 /********************************************************************/
1937 /* Title: isStnID */
1938 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1939 /* Date: 15 Sep 1994 */
1940 /* Programmer: CARL MCCALLA */
1941 /* Language: C/370 */
1945 /* External Functions Called: */
1952 /* Modification History: */
1955 /********************************************************************/
1958 static bool isStnId( char *stnID, Decoded_METAR *Mptr, int *NDEX)
1964 if( strlen(stnID) == 4 )
1966 if( nisalpha(stnID,1) && nisalnum(stnID+1,3) ) {
1967 strcpy(Mptr->stnid,stnID);
1979 #pragma subtitle(" ")
1981 #pragma subtitle("subtitle - description ")
1982 /********************************************************************/
1984 /* Title: isCodeName */
1985 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
1986 /* Date: 15 Sep 1994 */
1987 /* Programmer: CARL MCCALLA */
1988 /* Language: C/370 */
1992 /* External Functions Called: */
1999 /* Modification History: */
2002 /********************************************************************/
2005 static bool isCodeName( char *codename, Decoded_METAR *Mptr, int *NDEX)
2007 if( codename == NULL )
2010 if( strcmp(codename,"METAR") == 0 ||
2011 strcmp(codename,"SPECI") == 0 )
2013 strcpy(Mptr->codeName, codename );
2023 #pragma subtitle(" ")
2025 #pragma subtitle("subtitle - description ")
2026 /********************************************************************/
2029 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2030 /* Date: 15 Sep 1994 */
2031 /* Programmer: CARL MCCALLA */
2032 /* Language: C/370 */
2036 /* External Functions Called: */
2043 /* Modification History: */
2046 /********************************************************************/
2049 static bool isNIL( char *token, Decoded_METAR *Mptr, int *NDEX)
2055 if( strcmp(token, "NIL") == 0 )
2057 Mptr->NIL_rpt = TRUE;
2066 #pragma subtitle(" ")
2068 #pragma subtitle("subtitle - description ")
2069 /********************************************************************/
2072 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2073 /* Date: 15 Sep 1994 */
2074 /* Programmer: CARL MCCALLA */
2075 /* Language: C/370 */
2079 /* External Functions Called: */
2086 /* Modification History: */
2089 /********************************************************************/
2092 static bool isAUTO( char *token, Decoded_METAR *Mptr, int *NDEX)
2098 if( strcmp(token, "AUTO") == 0 )
2109 #pragma subtitle(" ")
2111 #pragma subtitle("subtitle - description ")
2112 /********************************************************************/
2115 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2116 /* Date: 24 Apr 1996 */
2117 /* Programmer: CARL MCCALLA */
2118 /* Language: C/370 */
2122 /* External Functions Called: */
2129 /* Modification History: */
2132 /********************************************************************/
2135 static bool isCOR ( char *token, Decoded_METAR *Mptr, int *NDEX)
2141 if( strcmp(token, "COR") == 0 )
2152 #pragma subtitle(" ")
2154 #pragma subtitle("subtitle - description ")
2155 /********************************************************************/
2157 /* Title: isTimeUTC */
2158 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2159 /* Date: 15 Sep 1994 */
2160 /* Programmer: CARL MCCALLA */
2161 /* Language: C/370 */
2165 /* External Functions Called: */
2172 /* Modification History: */
2175 /********************************************************************/
2178 static bool isTimeUTC( char *UTC, Decoded_METAR *Mptr, int *NDEX )
2184 if( strlen( UTC ) == 4 ) {
2185 if(nisdigit(UTC,4) ) {
2186 Mptr->ob_hour = antoi(UTC,2);
2187 Mptr->ob_minute = antoi(UTC+2,2);
2194 else if( strlen( UTC ) == 6 ) {
2195 if(nisdigit(UTC,6) ) {
2196 Mptr->ob_date = antoi(UTC,2);
2197 Mptr->ob_hour = antoi(UTC+2,2);
2198 Mptr->ob_minute = antoi(UTC+4,2);
2205 if( strlen( UTC ) == 5 ) {
2206 if(nisdigit(UTC,4) && (*(UTC+4) == 'Z') ) {
2207 Mptr->ob_hour = antoi(UTC,2);
2208 Mptr->ob_minute = antoi(UTC+2,2);
2215 else if( strlen( UTC ) == 7 ) {
2216 if(nisdigit(UTC,6) && (*(UTC+6) == 'Z') ) {
2217 Mptr->ob_date = antoi(UTC,2);
2218 Mptr->ob_hour = antoi(UTC+2, 2);
2219 Mptr->ob_minute = antoi(UTC+4, 2 );
2231 #pragma subtitle(" ")
2233 #pragma subtitle("subtitle - description ")
2234 /********************************************************************/
2236 /* Title: isWindData */
2237 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2238 /* Date: 15 Sep 1994 */
2239 /* Programmer: CARL MCCALLA */
2240 /* Language: C/370 */
2244 /* External Functions Called: */
2251 /* Modification History: */
2254 /********************************************************************/
2257 static bool isWindData( char *wind, Decoded_METAR *Mptr, int *NDEX )
2267 if( strlen(wind) < 7 )
2270 memset(dummy,'\0',8);
2272 if( ( unitsPtr = strstr( wind, "KMH" ) ) != NULL )
2273 strcpy( dummy, "KMH" );
2274 else if( (unitsPtr = strstr( wind, "KT") ) != NULL )
2275 strcpy( dummy, "KT" );
2276 else if( (unitsPtr = strstr( wind, "MPS") ) != NULL )
2277 strcpy( dummy, "MPS" );
2281 if( (GustPtr = strchr( wind, 'G' )) != NULL )
2283 if( (nisdigit(wind,(GustPtr-wind)) ||
2284 (strncmp(wind,"VRB",3) == 0 &&
2285 nisdigit(wind+3,(GustPtr-(wind+3))))) &&
2286 nisdigit(GustPtr+1,(unitsPtr-(GustPtr+1))) &&
2287 ((GustPtr-wind) >= 5 && (GustPtr-wind) <= 6) &&
2288 ((unitsPtr-(GustPtr+1)) >= 2 &&
2289 (unitsPtr-(GustPtr+1)) <= 3) )
2291 if( strncmp(wind,"VRB",3) == 0 )
2292 Mptr->winData.windVRB = TRUE;
2294 Mptr->winData.windDir = antoi(wind,3);
2296 Mptr->winData.windSpeed = antoi(wind+3, (GustPtr-(wind+3)));
2297 Mptr->winData.windGust = antoi(GustPtr+1,(unitsPtr-
2300 strcpy( Mptr->winData.windUnits, dummy );
2306 else if( nisdigit(wind,(unitsPtr-wind)) ||
2307 (strncmp(wind,"VRB",3) == 0 &&
2308 nisdigit(wind+3,(unitsPtr-(wind+3)))) &&
2309 ((unitsPtr-wind) >= 5 && (unitsPtr-wind) <= 6) )
2311 if( strncmp(wind,"VRB",3) == 0 )
2312 Mptr->winData.windVRB = TRUE;
2314 Mptr->winData.windDir = antoi(wind, 3);
2316 Mptr->winData.windSpeed = antoi(wind+3,(unitsPtr-(wind+3)));
2318 strcpy( Mptr->winData.windUnits, dummy );
2326 #pragma subtitle(" ")
2327 #pragma subtitle("subtitle - Decode METAR report. ")
2328 /********************************************************************/
2330 /* Title: DcdMETAR */
2331 /* Organization: W/OSO242 - GRAPHICS AND DISPLAY SECTION */
2332 /* Date: 14 Sep 1994 */
2333 /* Programmer: CARL MCCALLA */
2334 /* Language: C/370 */
2336 /* Abstract: DcdMETAR takes a pointer to a METAR report char- */
2337 /* acter string as input, decodes the report, and */
2338 /* puts the individual decoded/parsed groups into */
2339 /* a structure that has the variable type */
2340 /* Decoded_METAR. */
2342 /* Input: string - a pointer to a METAR report character */
2345 /* Output: Mptr - a pointer to a structure that has the */
2346 /* variable type Decoded_METAR. */
2348 /* Modification History: */
2351 /********************************************************************/
2355 int DcdMETAR( char *string , Decoded_METAR *Mptr )
2358 /***************************/
2359 /* DECLARE LOCAL VARIABLES */
2360 /***************************/
2363 enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
2364 AUTO, COR, windData, MinMaxWinDir,
2366 RVR, presentWX, PartialObscur,
2368 altimStng, NotIDed = 99} StartGroup,
2372 WindStruct *WinDataPtr;
2382 *delimeters = {" "};
2386 /*********************************/
2387 /* BEGIN THE BODY OF THE ROUTINE */
2388 /*********************************/
2390 /********************************************************/
2391 /* ONLY PARSE OR DECOCODE NON-NULL METAR REPORT STRINGS */
2392 /********************************************************/
2394 if( string == NULL )
2398 /*****************************************/
2399 /* INITIALIZE STRUCTURE THAT HAS THE */
2400 /* VARIABLE TYPE Decoded_METAR */
2401 /*****************************************/
2403 InitDcdMETAR( Mptr );
2406 printf("DcdMETAR: Returned from InitDcdMETAR\n");
2410 /****************************************************/
2411 /* TOKENIZE AND STORE THE INPUT METAR REPORT STRING */
2412 /****************************************************/
2414 printf("DcdMETAR: Before start of tokenizing, string = %s\n",
2418 token = SaveTokenString( string, delimeters );
2422 /*********************************************************/
2423 /* DECODE THE METAR REPORT (POSITIONAL ORDER PRECEDENCE) */
2424 /*********************************************************/
2427 MetarGroup = codename;
2431 printf("DcdMETAR: token[0] = %s\n",token[0]);
2434 while( token[NDEX] != NULL && IS_NOT_RMKS ) {
2437 if( strcmp(token[0],"OPKC") == 0 || strcmp(token[0],"MDSD") == 0 )
2438 printf("DcdMETAR: token[%d] = %s\n",NDEX,token[NDEX]);
2442 printf("DcdMETAR: Token[%d] = %s\n",NDEX,token[NDEX]);
2445 printf("DcdMETAR: MetarGroup = %d\n",MetarGroup);
2448 if( strcmp( token[NDEX], "RMK" ) != 0 ) {
2450 StartGroup = NotIDed;
2453 printf("DcdMETAR: StartGroup = %d\n",StartGroup);
2454 printf("DcdMETAR: SaveStartGroup = %d\n",SaveStartGroup);
2457 /**********************************************/
2458 /* SET ID_break_CODE TO ITS DEFAULT VALUE OF */
2459 /* 99, WHICH MEANS THAT NO SUCCESSFUL ATTEMPT */
2460 /* WAS MADE TO DECODE ANY METAR CODED GROUP */
2461 /* FOR THIS PASS THROUGH THE DECODING LOOP */
2462 /**********************************************/
2463 switch( MetarGroup ) {
2465 if( isCodeName( token[NDEX], Mptr, &NDEX ) )
2466 SaveStartGroup = StartGroup = codename;
2470 if( isStnId( token[NDEX], Mptr, &NDEX ) ) {
2471 SaveStartGroup = StartGroup = stnid;
2476 printf("DcdMETAR: token[%d] = %s\n",NDEX,token[NDEX]);
2478 freeTokens( token );
2483 if( isNIL( token[NDEX], Mptr, &NDEX ) )
2484 SaveStartGroup = StartGroup = NIL1;
2488 if( isCOR( token[NDEX], Mptr, &NDEX ) )
2489 SaveStartGroup = StartGroup = COR1;
2490 MetarGroup = obDateTime;
2494 if( isTimeUTC( token[NDEX], Mptr, &NDEX ) ) {
2495 SaveStartGroup = StartGroup = obDateTime;
2499 freeTokens( token );
2504 if( isTimeUTC( token[NDEX], Mptr, &NDEX ) )
2505 SaveStartGroup = StartGroup = obDateTime;
2509 if( isNIL( token[NDEX], Mptr, &NDEX ) )
2510 SaveStartGroup = StartGroup = NIL2;
2514 if( isAUTO( token[NDEX], Mptr, &NDEX ) )
2515 SaveStartGroup = StartGroup = AUTO;
2519 if( isCOR( token[NDEX], Mptr, &NDEX ) )
2520 SaveStartGroup = StartGroup = COR;
2521 MetarGroup = windData;
2524 if( isWindData( token[NDEX], Mptr, &NDEX ) )
2525 SaveStartGroup = StartGroup = windData;
2526 MetarGroup = MinMaxWinDir;
2528 case( MinMaxWinDir ):
2529 if( isMinMaxWinDir( token[NDEX], Mptr, &NDEX ) )
2530 SaveStartGroup = StartGroup = MinMaxWinDir;
2534 if( isCAVOK( token[NDEX], Mptr, &NDEX ) )
2535 SaveStartGroup = StartGroup = CAVOK;
2536 MetarGroup = visibility;
2539 if( isVisibility( &(token[NDEX]), Mptr, &NDEX ) )
2540 SaveStartGroup = StartGroup = visibility;
2545 MetarGroup = presentWX;
2547 while (isRVR( token[NDEX], Mptr, &NDEX, ndex ) &&
2550 SaveStartGroup = StartGroup = RVR;
2551 MetarGroup = presentWX;
2556 MetarGroup = skyCond;
2558 while( isPresentWX( token[NDEX], Mptr, &NDEX,
2559 &ndex ) && ndex < MAXWXSYMBOLS) {
2560 SaveStartGroup = StartGroup = presentWX;
2561 MetarGroup = PartialObscur;
2564 case( PartialObscur ):
2565 if( isPartObscur( &(token[NDEX]), Mptr, &NDEX ) )
2566 SaveStartGroup = StartGroup = PartialObscur;
2567 MetarGroup = skyCond;
2570 if( isSkyCond( &(token[NDEX]), Mptr, &NDEX ) )
2571 SaveStartGroup = StartGroup = skyCond;
2572 MetarGroup = tempGroup;
2575 if( isTempGroup( token[NDEX], Mptr, &NDEX ) )
2576 SaveStartGroup = StartGroup = tempGroup;
2577 MetarGroup = altimStng;
2580 if( isAltimStng( token[NDEX], Mptr, &NDEX ) )
2581 SaveStartGroup = StartGroup = altimStng;
2582 MetarGroup = NotIDed;
2586 MetarGroup = SaveStartGroup;
2587 /* MetarGroup = ResetMETARGroup( StartGroup,
2588 SaveStartGroup ); */
2593 IS_NOT_RMKS = FALSE;
2599 printf("DcdMETAR: while loop exited, Token[%d] = %s\n",
2602 /******************************/
2603 /* DECODE GROUPS FOUND IN THE */
2604 /* REMARKS SECTION OF THE */
2606 /******************************/
2608 if( token[NDEX] != NULL )
2609 if( strcmp( token[NDEX], "RMK" ) == 0 )
2610 DcdMTRmk( token, Mptr );
2612 /****************************************/
2613 freeTokens( token ); /* FREE THE STORAGE ALLOCATED FOR THE */
2614 /* ARRAY USED TO HOLD THE METAR REPORT */
2616 /****************************************/