]> git.mxchange.org Git - simgear.git/blob - simgear/metar/Dcdmetar.cpp
Patch from Melchior Franz:
[simgear.git] / simgear / metar / Dcdmetar.cpp
1 #include "Local.h"     /* standard header file */
2 #include "Metar.h"     /* standard header file */
3  
4 float fracPart( char * );
5 void DcdMTRmk( char **, Decoded_METAR * );
6  
7  
8 /********************************************************************/
9 /*                                                                  */
10 /*  Title:         SaveTokenString                                  */
11 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
12 /*  Date:          14 Sep 1994                                      */
13 /*  Programmer:    CARL MCCALLA                                     */
14 /*  Language:      C/370                                            */
15 /*                                                                  */
16 /*  Abstract:      SaveTokenString tokenizes the input character    */
17 /*                 string based upon the delimeter set supplied     */
18 /*                 by the calling routine.  The elements tokenized  */
19 /*                 from the input character string are saved in an  */
20 /*                 array of pointers to characters.  The address of */
21 /*                 this array is the output from this function.     */
22 /*                                                                  */
23 /*  Input:         string - a pointer to a character string.        */
24 /*                                                                  */
25 /*                 delimeters - a pointer to a string of 1 or more  */
26 /*                              characters that are used for token- */
27 /*                              izing the input character string.   */
28 /*                                                                  */
29 /*  Output:        token  - the address of a pointer to an array of */
30 /*                          pointers to character strings.  The     */
31 /*                          array of pointers are the addresses of  */
32 /*                          the character strings that are token-   */
33 /*                          ized from the input character string.   */
34 /*                                                                  */
35 /*                                                                  */
36 /*  Modification History:                                           */
37 /*                 None.                                            */
38 /*                                                                  */
39 /********************************************************************/
40  
41 static char **SaveTokenString ( char *string , char *delimeters )
42 {
43  
44    /***************************/
45    /* DECLARE LOCAL VARIABLES */
46    /***************************/
47  
48    int NDEX;
49    static char *token[ MAXTOKENS ],
50         *TOKEN;
51  
52  
53    /*********************************/
54    /* BEGIN THE BODY OF THE ROUTINE */
55    /*********************************/
56  
57    /******************************************/
58    /* TOKENIZE THE INPUT CHARACTER STRING    */
59    /* AND SAVE THE TOKENS TO THE token ARRAY */
60    /******************************************/
61  
62    NDEX = 0;
63    TOKEN = strtok( string, delimeters);
64  
65    if( TOKEN == NULL )
66       return NULL;
67  
68    token[NDEX] = (char *) malloc(sizeof(char)*(strlen(TOKEN)+1));
69    strcpy( token[ NDEX ], TOKEN );
70  
71  
72    while ( token[NDEX] != NULL )
73    {
74       NDEX++;
75       TOKEN = strtok( NULL, delimeters );
76  
77       if( TOKEN != NULL )
78       {
79          token[NDEX] = (char *)
80                               malloc(sizeof(char)*(strlen(TOKEN)+1));
81          strcpy( token[NDEX], TOKEN );
82       }
83       else
84          token[ NDEX ] = TOKEN;
85  
86    }
87  
88  
89    return token;
90  
91 }
92 /********************************************************************/
93 /*                                                                  */
94 /*  Title:         freeTokens                                       */
95 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
96 /*  Date:          14 Sep 1994                                      */
97 /*  Programmer:    CARL MCCALLA                                     */
98 /*  Language:      C/370                                            */
99 /*                                                                  */
100 /*  Abstract:      freeTokens frees the storage allocated for the   */
101 /*                 character strings stored in the token array.     */
102 /*                                                                  */
103 /*  Input:         token  - the address of a pointer to an array    */
104 /*                          of string tokens.                       */
105 /*                                                                  */
106 /*                                                                  */
107 /*  Output:        None.                                            */
108 /*                                                                  */
109 /*                                                                  */
110 /*  Modification History:                                           */
111 /*                 None.                                            */
112 /*                                                                  */
113 /********************************************************************/
114  
115 static void freeTokens( char **token )
116 {
117    int NDEX;
118  
119    NDEX = 0;
120    while( *(token+NDEX) != NULL )
121    {
122       free( *(token+NDEX) );
123       NDEX++;
124    }
125    return;
126 }
127 /********************************************************************/
128 /*                                                                  */
129 /*  Title:         InitDcdMETAR                                     */
130 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
131 /*  Date:          15 Sep 1994                                      */
132 /*  Programmer:    CARL MCCALLA                                     */
133 /*  Language:      C/370                                            */
134 /*                                                                  */
135 /*  Abstract:  InitDcdMETAR initializes every member of the         */
136 /*             structure addressed by the pointer Mptr.             */
137 /*                                                                  */
138 /*  External Functions Called:                                      */
139 /*                 None.                                            */
140 /*                                                                  */
141 /*  Input:         Mptr - ptr to a decoded_METAR structure.         */
142 /*                                                                  */
143 /*  Output:        NONE                                             */
144 /*                                                                  */
145 /*  Modification History:                                           */
146 /*                 None.                                            */
147 /*                                                                  */
148 /********************************************************************/
149 static void InitDcdMETAR( Decoded_METAR *Mptr )
150 {
151  
152    /***************************/
153    /* DECLARE LOCAL VARIABLES */
154    /***************************/
155  
156  
157    int i,
158        j;
159  
160  
161  
162    /*************************/
163    /* START BODY OF ROUTINE */
164    /*************************/
165  
166    memset(Mptr->TS_LOC,'\0',3);
167    memset(Mptr->TS_MOVMNT,'\0',3);
168  
169  
170    memset(Mptr->TornadicType,'\0',15);
171    memset(Mptr->TornadicLOC,'\0',10);
172    memset(Mptr->TornadicDIR,'\0',4);
173    memset(Mptr->TornadicMovDir,'\0',3);
174    Mptr->BTornadicHour = MAXINT;
175    Mptr->BTornadicMinute = MAXINT;
176    Mptr->ETornadicHour = MAXINT;
177    Mptr->ETornadicMinute = MAXINT;
178    Mptr->TornadicDistance = MAXINT;
179  
180    memset( Mptr->autoIndicator,'\0', 5 );
181  
182    Mptr->RVRNO = FALSE;
183    Mptr->GR = FALSE;
184    Mptr->GR_Size = (float) MAXINT;
185  
186    Mptr->CHINO = FALSE;
187    memset(Mptr->CHINO_LOC, '\0', 6);
188  
189    Mptr->VISNO = FALSE;
190    memset(Mptr->VISNO_LOC, '\0', 6);
191  
192    Mptr->PNO = FALSE;
193    Mptr->PWINO = FALSE;
194    Mptr->FZRANO  = FALSE;
195    Mptr->TSNO   = FALSE;
196    Mptr->DollarSign  = FALSE;
197    Mptr->hourlyPrecip = (float) MAXINT;
198  
199    Mptr->ObscurAloftHgt = MAXINT;
200    memset(Mptr->ObscurAloft, '\0', 12);
201    memset(Mptr->ObscurAloftSkyCond, '\0', 12);
202  
203    memset(Mptr->VrbSkyBelow, '\0', 4);
204    memset(Mptr->VrbSkyAbove, '\0', 4);
205    Mptr->VrbSkyLayerHgt = MAXINT;
206  
207    Mptr->SectorVsby = (float) MAXINT;
208    memset( Mptr->SectorVsby_Dir, '\0', 3);
209  
210    memset(Mptr->codeName, '\0', 6);
211    memset(Mptr->stnid, '\0', 5);
212    Mptr->ob_hour   = MAXINT;
213    Mptr->ob_minute = MAXINT;
214    Mptr->ob_date   = MAXINT;
215  
216    memset(Mptr->synoptic_cloud_type, '\0', 6);
217  
218    Mptr->CloudLow    = '\0';
219    Mptr->CloudMedium = '\0';
220    Mptr->CloudHigh   = '\0';
221  
222    memset(Mptr->snow_depth_group, '\0', 6);
223    Mptr->snow_depth = MAXINT;
224  
225    Mptr->Temp_2_tenths    = (float) MAXINT;
226    Mptr->DP_Temp_2_tenths = (float) MAXINT;
227  
228    Mptr->OCNL_LTG      = FALSE;
229    Mptr->FRQ_LTG       = FALSE;
230    Mptr->CNS_LTG       = FALSE;
231    Mptr->CG_LTG        = FALSE;
232    Mptr->IC_LTG        = FALSE;
233    Mptr->CC_LTG        = FALSE;
234    Mptr->CA_LTG        = FALSE;
235    Mptr->AP_LTG        = FALSE;
236    Mptr->OVHD_LTG      = FALSE;
237    Mptr->DSNT_LTG      = FALSE;
238    Mptr->VcyStn_LTG    = FALSE;
239    Mptr->LightningVCTS = FALSE;
240    Mptr->LightningTS   = FALSE;
241  
242    memset( Mptr->LTG_DIR, '\0', 3);
243  
244  
245    for( i = 0; i < 3; i++)
246    {
247       memset(Mptr->ReWx[i].Recent_weather, '\0', 5);
248  
249       Mptr->ReWx[i].Bhh = MAXINT;
250       Mptr->ReWx[i].Bmm = MAXINT;
251  
252       Mptr->ReWx[i].Ehh = MAXINT;
253       Mptr->ReWx[i].Emm = MAXINT;
254  
255    }
256  
257    Mptr->NIL_rpt = FALSE;
258    Mptr->AUTO = FALSE;
259    Mptr->COR  = FALSE;
260  
261    Mptr->winData.windDir = MAXINT;
262    Mptr->winData.windSpeed = MAXINT;
263    Mptr->winData.windGust = MAXINT;
264    Mptr->winData.windVRB  = FALSE;
265    memset(Mptr->winData.windUnits, '\0', 4);
266  
267    Mptr->minWnDir = MAXINT;
268    Mptr->maxWnDir = MAXINT;
269  
270    memset(Mptr->horiz_vsby, '\0', 5);
271    memset(Mptr->dir_min_horiz_vsby, '\0', 3);
272  
273    Mptr->prevail_vsbySM = (float) MAXINT;
274    Mptr->prevail_vsbyM  = (float) MAXINT;
275    Mptr->prevail_vsbyKM = (float) MAXINT;
276  
277    memset(Mptr->vsby_Dir, '\0', 3);
278  
279    Mptr->CAVOK = FALSE;
280  
281    for ( i = 0; i < 12; i++ )
282    {
283       memset(Mptr->RRVR[ i ].runway_designator,
284               '\0', 6);
285  
286       Mptr->RRVR[ i ].visRange = MAXINT;
287  
288       Mptr->RRVR[ i ].vrbl_visRange = FALSE;
289       Mptr->RRVR[ i ].below_min_RVR = FALSE;
290       Mptr->RRVR[ i ].above_max_RVR = FALSE;
291  
292  
293       Mptr->RRVR[ i ].Max_visRange = MAXINT;
294       Mptr->RRVR[ i ].Min_visRange = MAXINT;
295    }
296  
297    Mptr->DVR.visRange = MAXINT;
298    Mptr->DVR.vrbl_visRange = FALSE;
299    Mptr->DVR.below_min_DVR = FALSE;
300    Mptr->DVR.above_max_DVR = FALSE;
301    Mptr->DVR.Max_visRange = MAXINT;
302    Mptr->DVR.Min_visRange = MAXINT;
303  
304    for ( i = 0; i < 5; i++ )
305    {
306       for( j = 0; j < 8; j++ )
307          Mptr->WxObstruct[i][j] = '\0';
308    }
309  
310    /***********************/
311    /* PARTIAL OBSCURATION */
312    /***********************/
313  
314    memset( &(Mptr->PartialObscurationAmt[0][0]), '\0', 7 );
315    memset( &(Mptr->PartialObscurationPhenom[0][0]), '\0',12);
316  
317    memset( &(Mptr->PartialObscurationAmt[1][0]), '\0', 7 );
318    memset( &(Mptr->PartialObscurationPhenom[1][0]), '\0',12);
319  
320  
321    /***************************************************/
322    /* CLOUD TYPE, CLOUD LEVEL, AND SIGNIFICANT CLOUDS */
323    /***************************************************/
324  
325  
326    for ( i = 0; i < 6; i++ )
327    {
328       memset(Mptr->cldTypHgt[ i ].cloud_type,
329               '\0', 5);
330  
331       memset(Mptr->cldTypHgt[ i ].cloud_hgt_char,
332               '\0', 4);
333  
334       Mptr->cldTypHgt[ i ].cloud_hgt_meters = MAXINT;
335  
336       memset(Mptr->cldTypHgt[ i ].other_cld_phenom,
337               '\0', 4);
338    }
339  
340    Mptr->VertVsby = MAXINT;
341  
342    Mptr->temp = MAXINT;
343    Mptr->dew_pt_temp = MAXINT;
344    Mptr->QFE = MAXINT;
345  
346    Mptr->SLPNO = FALSE;
347    Mptr->SLP = (float) MAXINT;
348  
349    Mptr->A_altstng = FALSE;
350    Mptr->inches_altstng = (double) MAXINT;
351  
352    Mptr->Q_altstng = FALSE;
353    Mptr->hectoPasc_altstng = MAXINT;
354  
355    Mptr->char_prestndcy = MAXINT;
356    Mptr->prestndcy = (float) MAXINT;
357  
358    Mptr->precip_amt = (float) MAXINT;
359  
360    Mptr->precip_24_amt = (float) MAXINT;
361    Mptr->maxtemp       = (float) MAXINT;
362    Mptr->mintemp       = (float) MAXINT;
363    Mptr->max24temp     = (float) MAXINT;
364    Mptr->min24temp     = (float) MAXINT;
365  
366    Mptr->VIRGA         = FALSE;
367    memset( Mptr->VIRGA_DIR, '\0', 3 );
368  
369    Mptr->VOLCASH       = FALSE;
370  
371    Mptr->minCeiling    = MAXINT;
372    Mptr->maxCeiling    = MAXINT;
373  
374    Mptr->CIG_2ndSite_Meters = MAXINT;
375    memset(Mptr->CIG_2ndSite_LOC, '\0', 10 );
376  
377    Mptr->minVsby = (float) MAXINT;
378    Mptr->maxVsby = (float) MAXINT;
379    Mptr->VSBY_2ndSite = (float) MAXINT;
380    memset(Mptr->VSBY_2ndSite_LOC,'\0',10);
381  
382    for( i = 0; i < 6; i++ )
383       memset (&(Mptr->SfcObscuration[i][0]), '\0', 10);
384  
385    Mptr->Num8thsSkyObscured = MAXINT;
386  
387    Mptr->Indeterminant3_6HrPrecip = FALSE;
388    Mptr->CIGNO = FALSE;
389    Mptr->Ceiling = MAXINT;
390    Mptr->Estimated_Ceiling = MAXINT;
391  
392    Mptr->NOSPECI = FALSE;
393    Mptr->LAST    = FALSE;
394  
395    Mptr->SNINCR = MAXINT;
396    Mptr->SNINCR_TotalDepth = MAXINT;
397  
398    Mptr->WaterEquivSnow = (float) MAXINT;
399  
400    Mptr->SunshineDur = MAXINT;
401    Mptr->SunSensorOut = FALSE;
402  
403  
404    Mptr->WshfTime_hour = MAXINT;
405    Mptr->WshfTime_minute = MAXINT;
406    Mptr->Wshft_FROPA     = FALSE;
407    Mptr->min_vrbl_wind_dir = MAXINT;
408    Mptr->max_vrbl_wind_dir = MAXINT;
409  
410    Mptr->PRESRR        = FALSE;
411    Mptr->PRESFR        = FALSE;
412  
413    Mptr->TWR_VSBY = (float) MAXINT;
414    Mptr->SFC_VSBY = (float) MAXINT;
415  
416    Mptr->PKWND_dir = MAXINT;
417    Mptr->PKWND_speed = MAXINT;
418    Mptr->PKWND_hour = MAXINT;
419    Mptr->PKWND_minute = MAXINT;
420  
421    return;
422  
423 }
424 /********************************************************************/
425 /*                                                                  */
426 /*  Title:         ResetMETARGroup                                  */
427 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
428 /*  Date:          15 Sep 1994                                      */
429 /*  Programmer:    CARL MCCALLA                                     */
430 /*  Language:      C/370                                            */
431 /*                                                                  */
432 /*  Abstract:  ResetMETARGroup returns a METAR_obGroup enumerated   */
433 /*             variable that indicates which METAR reporting group  */
434 /*             might next appear in the METAR report and should be  */
435 /*             considered for decoding.                             */
436 /*                                                                  */
437 /*  External Functions Called:                                      */
438 /*                 None.                                            */
439 /*                                                                  */
440 /*  Input:         StartGroup - a METAR_obGroup variable that       */
441 /*                              indicates where or on what group    */
442 /*                              METAR Decoding began.               */
443 /*                                                                  */
444 /*                 SaveStartGroup - a METAR_obGroup variable that   */
445 /*                                  indicates the reporting group   */
446 /*                                  in the METAR report that was    */
447 /*                                  successfully decoded.           */
448 /*                                                                  */
449 /*  Output:        A METAR_obGroup variable that indicates which    */
450 /*                 reporting group in the METAR report should next  */
451 /*                 be considered for decoding                       */
452 /*                                                                  */
453 /*  Modification History:                                           */
454 /*                 None.                                            */
455 /*                                                                  */
456 /********************************************************************/
457 /*static int ResetMETARGroup( int StartGroup,
458                             int SaveStartGroup )
459 {
460  
461    enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
462                         AUTO, COR, windData, MinMaxWinDir,
463                         CAVOK, visibility,
464                         RVR, presentWX, skyCond, tempGroup,
465                         altimStng, NotIDed = 99};
466  
467    if( StartGroup == NotIDed && SaveStartGroup == NotIDed )
468       return NotIDed;
469    else if( StartGroup == NotIDed && SaveStartGroup != NotIDed &&
470             SaveStartGroup != altimStng )
471       return (++SaveStartGroup);
472    else
473       return (++SaveStartGroup);
474  
475 }
476 */
477  
478 /********************************************************************/
479 /*                                                                  */
480 /*  Title:         CodedHgt2Meters                                  */
481 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
482 /*  Date:          15 Sep 1994                                      */
483 /*  Programmer:    CARL MCCALLA                                     */
484 /*  Language:      C/370                                            */
485 /*                                                                  */
486 /*  Abstract:  CodedHgt2Meters converts a coded cloud height into   */
487 /*             meters.                                              */
488 /*                                                                  */
489 /*  External Functions Called:                                      */
490 /*                 None.                                            */
491 /*                                                                  */
492 /*  Input:         token - a pointer to a METAR report group.       */
493 /*                 Mptr - a pointer to a decoded_METAR structure.   */
494 /*                                                                  */
495 /*  Output:        Cloud height in meters                           */
496 /*                                                                  */
497 /*  Modification History:                                           */
498 /*                 None.                                            */
499 /*                                                                  */
500 /********************************************************************/
501  
502 static int CodedHgt2Meters( char *token, Decoded_METAR *Mptr )
503 {
504    int hgt;
505    static int maxhgt = 30000;
506  
507  
508    if( (hgt = atoi(token)) == 999 )
509       return maxhgt;
510    else
511       return (hgt*30);
512 }
513  
514 /********************************************************************/
515 /*                                                                  */
516 /*  Title:         isPartObscur                                     */
517 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
518 /*  Date:          15 Sep 1994                                      */
519 /*  Programmer:    CARL MCCALLA                                     */
520 /*  Language:      C/370                                            */
521 /*                                                                  */
522 /*  Abstract:  isPartObscur determines whether or not the METAR     */
523 /*             report element that is passed to it is or is not     */
524 /*             a partial obscuration indicator for an amount of     */
525 /*             obscuration.                                         */
526 /*                                                                  */
527 /*                                                                  */
528 /*  External Functions Called:                                      */
529 /*                 None.                                            */
530 /*                                                                  */
531 /*  Input:         token - the address of a pointer to the group    */
532 /*                         in the METAR report that isPartObscur    */
533 /*                         determines is or is not a partial        */
534 /*                         obscuration indicator.                   */
535 /*                                                                  */
536 /*                                                                  */
537 /*                 Mptr - a pointer to a decoded_METAR structure.   */
538 /*                                                                  */
539 /*  Output:        TRUE, if the group is a partial obscuration      */
540 /*                 indicator and FALSE, if it is not.               */
541 /*                                                                  */
542 /*                                                                  */
543 /*  Modification History:                                           */
544 /*                 None.                                            */
545 /*                                                                  */
546 /********************************************************************/
547 static bool isPartObscur( char **string, Decoded_METAR *Mptr,
548                           int *NDEX )
549 {
550  
551    if( *string == NULL )
552       return FALSE;
553  
554    if( strcmp( *string, "FEW///" ) == 0 ||
555        strcmp( *string, "SCT///" ) == 0 ||
556        strcmp( *string, "BKN///" ) == 0 ||
557        strcmp( *string, "FEW000" ) == 0 ||
558        strcmp( *string, "SCT000" ) == 0 ||
559        strcmp( *string, "BKN000" ) == 0    ) {
560       strcpy( &(Mptr->PartialObscurationAmt[0][0]), *string );
561       (*NDEX)++;
562       string++;
563  
564       if( *string == NULL )
565          return TRUE;
566  
567       if( strcmp( (*string+3), "///") ) {
568           if( strcmp( *string, "FEW000" ) == 0 ||
569               strcmp( *string, "SCT000" ) == 0 ||
570               strcmp( *string, "BKN000" ) == 0    ) {
571             strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
572             (*NDEX)++;
573          }
574       }
575       else {
576          if( strcmp( *string, "FEW///" ) == 0 ||
577              strcmp( *string, "SCT///" ) == 0 ||
578              strcmp( *string, "BKN///" ) == 0 ) {
579             strcpy( &(Mptr->PartialObscurationAmt[1][0]), *string );
580             (*NDEX)++;
581          }
582       }
583       return TRUE;
584    }
585    else
586       return FALSE;
587 }
588  
589 /********************************************************************/
590 /*                                                                  */
591 /*  Title:         isCldLayer                                       */
592 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
593 /*  Date:          15 Sep 1994                                      */
594 /*  Programmer:    CARL MCCALLA                                     */
595 /*  Language:      C/370                                            */
596 /*                                                                  */
597 /*  Abstract:      isCldLayer determines whether or not the         */
598 /*                 current group has a valid cloud layer            */
599 /*                 identifier.                                      */
600 /*                                                                  */
601 /*                                                                  */
602 /*  External Functions Called:                                      */
603 /*                 None.                                            */
604 /*                                                                  */
605 /*  Input:         token - pointer to a METAR report group.         */
606 /*                                                                  */
607 /*  Output:        TRUE, if the report group is a valid cloud       */
608 /*                 layer indicator.                                 */
609 /*                                                                  */
610 /*                 FALSE, if the report group is not a valid cloud  */
611 /*                 layer indicator.                                 */
612 /*                                                                  */
613 /*                                                                  */
614 /*  Modification History:                                           */
615 /*                 None.                                            */
616 /*                                                                  */
617 /********************************************************************/
618  
619 static bool isCldLayer( char *token )
620 {
621    if( token == NULL )
622       return FALSE;
623  
624    if( strlen(token) < 6 )
625       return FALSE;
626    else
627       return ((strncmp(token,"OVC",3) == 0 ||
628                strncmp(token,"SCT",3) == 0 ||
629                strncmp(token,"FEW",3) == 0 ||
630                strncmp(token,"BKN",3) == 0 ||
631                (isdigit(*token) &&
632                 strncmp(token+1,"CU",2) == 0) ||
633                (isdigit(*token) &&
634                 strncmp(token+1,"SC",2) == 0) ) &&
635                nisdigit((token+3),3)) ? TRUE:FALSE;
636 }
637  
638 /********************************************************************/
639 /*                                                                  */
640 /*  Title:         isCAVOK                                          */
641 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
642 /*  Date:          09 May 1996                                      */
643 /*  Programmer:    CARL MCCALLA                                     */
644 /*  Language:      C/370                                            */
645 /*                                                                  */
646 /*  Abstract:      isCAVOK determines whether or not the current    */
647 /*                 group is a valid CAVOK indicator.                */
648 /*                                                                  */
649 /*                                                                  */
650 /*  External Functions Called:                                      */
651 /*                 None.                                            */
652 /*                                                                  */
653 /*  Input:         token - pointer to a METAR report group.         */
654 /*                                                                  */
655 /*  Output:        TRUE, if the input group is a valid CAVOK        */
656 /*                 indicator.  FALSE, otherwise.                    */
657 /*                                                                  */
658 /*                                                                  */
659 /*                                                                  */
660 /*  Modification History:                                           */
661 /*                 None.                                            */
662 /*                                                                  */
663 /********************************************************************/
664  
665 static bool isCAVOK( char *token, Decoded_METAR *Mptr, int *NDEX )
666 {
667  
668    if( token == NULL )
669       return FALSE;
670  
671    if( strcmp(token, "CAVOK") != 0 )
672       return FALSE;
673    else {
674       (*NDEX)++;
675       Mptr->CAVOK = TRUE;
676       return TRUE;
677    }
678 }
679  
680 /********************************************************************/
681 /*                                                                  */
682 /*  Title:         parseCldData                                     */
683 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
684 /*  Date:          15 Sep 1994                                      */
685 /*  Programmer:    CARL MCCALLA                                     */
686 /*  Language:      C/370                                            */
687 /*                                                                  */
688 /*  Abstract:                                                       */
689 /*                                                                  */
690 /*  External Functions Called:                                      */
691 /*                 None.                                            */
692 /*                                                                  */
693 /*  Input:         x                                                */
694 /*                                                                  */
695 /*  Output:        x                                                */
696 /*                                                                  */
697 /*  Modification History:                                           */
698 /*                 None.                                            */
699 /*                                                                  */
700 /********************************************************************/
701  
702 static void parseCldData( char *token, Decoded_METAR *Mptr, int next)
703 {
704  
705  
706    if( token == NULL )
707       return;
708  
709    if( strlen(token) > 6 )
710       strncpy(Mptr->cldTypHgt[next].other_cld_phenom,token+6,
711               (strlen(token)-6));
712  
713    strncpy(Mptr->cldTypHgt[next].cloud_type,token,3);
714  
715    strncpy(Mptr->cldTypHgt[next].cloud_hgt_char,token+3,3);
716  
717    Mptr->cldTypHgt[next].cloud_hgt_meters =
718                                CodedHgt2Meters( token+3, Mptr );
719  
720    return;
721 }
722  
723  
724 /********************************************************************/
725 /*                                                                  */
726 /*  Title:         isSkyCond                                        */
727 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
728 /*  Date:          15 Sep 1994                                      */
729 /*  Programmer:    CARL MCCALLA                                     */
730 /*  Language:      C/370                                            */
731 /*                                                                  */
732 /*  Abstract:                                                       */
733 /*                                                                  */
734 /*  External Functions Called:                                      */
735 /*                 None.                                            */
736 /*                                                                  */
737 /*  Input:         x                                                */
738 /*                                                                  */
739 /*  Output:        x                                                */
740 /*                                                                  */
741 /*  Modification History:                                           */
742 /*                 None.                                            */
743 /*                                                                  */
744 /********************************************************************/
745 static bool isSkyCond( char **skycond, Decoded_METAR *Mptr,
746                         int *NDEX )
747 {
748  
749    bool first_layer,
750         second_layer,
751         third_layer,
752         fourth_layer,
753         fifth_layer,
754         sixth_layer;
755    int next;
756  
757       /********************************************************/
758       /* INTERROGATE skycond TO DETERMINE IF "CLR" IS PRESENT */
759       /********************************************************/
760  
761    if( *skycond == NULL )
762       return FALSE;
763  
764  
765    if( strcmp(*skycond,"CLR") == 0)
766    {
767       strcpy(Mptr->cldTypHgt[0].cloud_type,"CLR");
768 /*
769       memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
770       memset(Mptr->cldTypHgt[0].other_cld_phenom,
771               '\0', 1);
772 */
773       (*NDEX)++;
774       return TRUE;
775    }
776  
777       /********************************************************/
778       /* INTERROGATE skycond TO DETERMINE IF "SKC" IS PRESENT */
779       /********************************************************/
780  
781    else if( strcmp(*skycond,"SKC") == 0)
782    {
783       strcpy(Mptr->cldTypHgt[0].cloud_type,"SKC");
784 /*
785       memset(Mptr->cldTypHgt[0].cloud_hgt_char,'\0',1);
786       memset(Mptr->cldTypHgt[0].other_cld_phenom,
787               '\0', 1);
788 */
789       (*NDEX)++;
790       return TRUE;
791    }
792  
793       /****************************************/
794       /* INTERROGATE skycond TO DETERMINE IF  */
795       /*    VERTICAL VISIBILITY IS PRESENT    */
796       /****************************************/
797  
798    else if( strncmp(*skycond,"VV",2) == 0
799              && strlen(*skycond) == 5 &&
800                   nisdigit((*skycond+2),3) )
801    {
802       Mptr->VertVsby = CodedHgt2Meters( (*skycond+2), Mptr);
803       (*NDEX)++;
804       return TRUE;
805    }
806  
807       /****************************************/
808       /* INTERROGATE skycond TO DETERMINE IF  */
809       /*    CLOUD LAYER DATA IS PRESENT       */
810       /****************************************/
811  
812    else if( isCldLayer( *skycond ))
813    {
814       next = 0;
815  
816       parseCldData( *skycond , Mptr, next );
817       first_layer = TRUE;
818       next++;
819       (++skycond);
820  
821       if( *skycond == NULL )
822          return TRUE;
823  
824       second_layer = FALSE;
825       third_layer = FALSE;
826       fourth_layer = FALSE;
827       fifth_layer = FALSE;
828       sixth_layer = FALSE;
829  
830  
831       if( isCldLayer( *skycond ) && first_layer )
832       {
833          parseCldData( *skycond, Mptr, next );
834          second_layer = TRUE;
835          next++;
836          (++skycond);
837  
838          if( *skycond == NULL )
839             return TRUE;
840  
841       }
842  
843       if( isCldLayer( *skycond ) && first_layer &&
844           second_layer )
845       {
846          parseCldData( *skycond , Mptr, next );
847          third_layer = TRUE;
848          next++;
849          (++skycond);
850  
851          if( *skycond == NULL )
852             return TRUE;
853  
854       }
855  
856       if( isCldLayer( *skycond ) && first_layer && second_layer &&
857                       third_layer )
858       {
859          parseCldData( *skycond, Mptr, next );
860          fourth_layer = TRUE;
861          next++;
862          (++skycond);
863  
864          if( *skycond == NULL )
865             return TRUE;
866  
867       }
868  
869       if( isCldLayer( *skycond ) && first_layer && second_layer &&
870           third_layer && fourth_layer )
871       {
872          parseCldData( *skycond , Mptr, next );
873          fifth_layer = TRUE;
874          next++;
875          (++skycond);
876  
877          if( *skycond == NULL )
878             return TRUE;
879  
880       }
881  
882       if( isCldLayer( *skycond ) && first_layer && second_layer &&
883           third_layer && fourth_layer && fifth_layer )
884       {
885          parseCldData( *skycond , Mptr, next );
886          sixth_layer = TRUE;
887       }
888  
889  
890  
891       if( sixth_layer )
892       {
893          (*NDEX)++;
894          (*NDEX)++;
895          (*NDEX)++;
896          (*NDEX)++;
897          (*NDEX)++;
898          (*NDEX)++;
899          return TRUE;
900       }
901       else if( fifth_layer )
902       {
903          (*NDEX)++;
904          (*NDEX)++;
905          (*NDEX)++;
906          (*NDEX)++;
907          (*NDEX)++;
908          return TRUE;
909       }
910       else if( fourth_layer )
911       {
912          (*NDEX)++;
913          (*NDEX)++;
914          (*NDEX)++;
915          (*NDEX)++;
916          return TRUE;
917       }
918       else if( third_layer )
919       {
920          (*NDEX)++;
921          (*NDEX)++;
922          (*NDEX)++;
923          return TRUE;
924       }
925       else if( second_layer )
926       {
927          (*NDEX)++;
928          (*NDEX)++;
929          return TRUE;
930       }
931       else if( first_layer )
932       {
933          (*NDEX)++;
934          return TRUE;
935       }
936       else
937          return FALSE;
938  
939    }
940    else
941       return FALSE;
942 }
943 /********************************************************************/
944 /*                                                                  */
945 /*  Title:         prevailVSBY                                      */
946 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
947 /*  Date:          15 Sep 1994                                      */
948 /*  Programmer:    CARL MCCALLA                                     */
949 /*  Language:      C/370                                            */
950 /*                                                                  */
951 /*  Abstract:                                                       */
952 /*                                                                  */
953 /*  External Functions Called:                                      */
954 /*                 None.                                            */
955 /*                                                                  */
956 /*  Input:         x                                                */
957 /*                                                                  */
958 /*  Output:        x                                                */
959 /*                                                                  */
960 /*  Modification History:                                           */
961 /*                 None.                                            */
962 /*                                                                  */
963 /********************************************************************/
964 static float prevailVSBY( char *visibility )
965 {
966    float Miles_vsby;
967    char *temp,
968         *Slash_ptr,
969         *SM_KM_ptr;
970    char numerator[3],
971         denominator[3];
972  
973  
974    if( (SM_KM_ptr = strstr( visibility, "SM" )) == NULL )
975       SM_KM_ptr = strstr(visibility, "KM");
976  
977    Slash_ptr = strchr( visibility, '/' );
978  
979    if( Slash_ptr == NULL )
980    {
981       temp = (char *) malloc(sizeof(char) *
982                           ((SM_KM_ptr - visibility)+1));
983       memset( temp, '\0', (SM_KM_ptr-visibility)+1);
984       strncpy( temp, visibility, (SM_KM_ptr-visibility) );
985       Miles_vsby = (float) (atoi(temp));
986       free( temp );
987       return Miles_vsby;
988    }
989    else
990    {
991       memset(numerator,   '\0', 3);
992       memset(denominator, '\0', 3);
993  
994       strncpy(numerator, visibility, (Slash_ptr - visibility));
995  
996 /*>>>>>>>>>>>>>>>>>>>>>>
997       if( (SM_KM_ptr - (Slash_ptr+1)) == 0 )
998          strcpy(denominator, "4");
999       else
1000 <<<<<<<<<<<<<<<<<<<<<<*/
1001  
1002       strncpy(denominator,
1003               Slash_ptr+1, (SM_KM_ptr - Slash_ptr));
1004  
1005       return ( ((float)(atoi(numerator)))/
1006                ((float)(atoi(denominator))) );
1007    }
1008  
1009 }
1010  
1011 /********************************************************************/
1012 /*                                                                  */
1013 /*  Title:         isVisibility                                     */
1014 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1015 /*  Date:          15 Sep 1994                                      */
1016 /*  Programmer:    CARL MCCALLA                                     */
1017 /*  Language:      C/370                                            */
1018 /*                                                                  */
1019 /*  Abstract:                                                       */
1020 /*                                                                  */
1021 /*  External Functions Called:                                      */
1022 /*                 None.                                            */
1023 /*                                                                  */
1024 /*  Input:         x                                                */
1025 /*                                                                  */
1026 /*  Output:        x                                                */
1027 /*                                                                  */
1028 /*  Modification History:                                           */
1029 /*                 None.                                            */
1030 /*                                                                  */
1031 /********************************************************************/
1032  
1033  
1034 static bool isVisibility( char **visblty, Decoded_METAR *Mptr,
1035                           int *NDEX )
1036 {
1037    char *achar,
1038         *astring,
1039         *save_token;
1040  
1041  
1042    /****************************************/
1043    /* CHECK FOR VISIBILITY MEASURED <1/4SM */
1044    /****************************************/
1045  
1046    if( *visblty == NULL )
1047       return FALSE;
1048  
1049  
1050    if( strcmp(*visblty,"M1/4SM") == 0 ||
1051        strcmp(*visblty,"<1/4SM") == 0 ) {
1052       Mptr->prevail_vsbySM = 0.0;
1053       (*NDEX)++;
1054       return TRUE;
1055    }
1056  
1057    /***********************************************/
1058    /* CHECK FOR VISIBILITY MEASURED IN KILOMETERS */
1059    /***********************************************/
1060  
1061    if( (achar = strstr(*visblty, "KM")) != NULL )
1062    {
1063       if( nisdigit(*visblty,(achar - *visblty)) &&
1064                         (achar - *visblty) > 0 )
1065       {
1066          Mptr->prevail_vsbyKM = prevailVSBY( *visblty );
1067          (*NDEX)++;
1068          return TRUE;
1069       }
1070       else
1071          return FALSE;
1072    }
1073  
1074    /***********************************/
1075    /* CHECK FOR VISIBILITY MEASURED   */
1076    /* IN A FRACTION OF A STATUTE MILE */
1077    /***********************************/
1078  
1079    else if( (achar = strchr( *visblty, '/' )) !=
1080                     NULL &&
1081        (astring = strstr( *visblty, "SM")) != NULL )
1082    {
1083       if( nisdigit(*visblty,(achar - *visblty))
1084                      &&
1085                (achar - *visblty) > 0 &&
1086                (astring - (achar+1)) > 0 &&
1087                 nisdigit(achar+1, (astring - (achar+1))) )
1088       {
1089          Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1090          (*NDEX)++;
1091          return TRUE;
1092       }
1093       else
1094          return FALSE;
1095    }
1096  
1097    /***********************************/
1098    /* CHECK FOR VISIBILITY MEASURED   */
1099    /*     IN WHOLE STATUTE MILES      */
1100    /***********************************/
1101  
1102    else if( (astring = strstr(*visblty,"SM") ) != NULL )
1103    {
1104       if( nisdigit(*visblty,(astring - *visblty)) &&
1105                        (astring- *visblty) > 0 )
1106       {
1107          Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1108          (*NDEX)++;
1109          return TRUE;
1110       }
1111       else
1112          return FALSE;
1113    }
1114  
1115    /***********************************/
1116    /* CHECK FOR VISIBILITY MEASURED   */
1117    /* IN WHOLE AND FRACTIONAL STATUTE */
1118    /*             MILES               */
1119    /***********************************/
1120  
1121    else if( nisdigit( *visblty,
1122                strlen(*visblty)) &&
1123                             strlen(*visblty) < 4 )
1124    {
1125       save_token = (char *) malloc(sizeof(char)*
1126                               (strlen(*visblty)+1));
1127       strcpy(save_token,*visblty);
1128       if( *(++visblty) == NULL)
1129       {
1130          free( save_token );
1131          return FALSE;
1132       }
1133  
1134       if( (achar = strchr( *visblty, '/' ) ) != NULL &&
1135           (astring = strstr( *visblty, "SM") ) != NULL  )
1136       {
1137          if( nisdigit(*visblty,
1138                  (achar - *visblty)) &&
1139                  (achar - *visblty) > 0 &&
1140                  (astring - (achar+1)) > 0 &&
1141              nisdigit(achar+1, (astring - (achar+1))) )
1142          {
1143             Mptr->prevail_vsbySM = prevailVSBY (*visblty);
1144             Mptr->prevail_vsbySM +=
1145                                  (float) (atoi(save_token));
1146             free( save_token);
1147  
1148             (*NDEX)++;
1149             (*NDEX)++;
1150  
1151             return TRUE;
1152  
1153          }
1154          else
1155             return FALSE;
1156       }
1157       else
1158          return FALSE;
1159  
1160    }
1161  
1162    /***********************************/
1163    /* CHECK FOR VISIBILITY MEASURED   */
1164    /* IN METERS WITH OR WITHOUT DI-   */
1165    /*     RECTION OF OBSERVATION      */
1166    /***********************************/
1167  
1168    else if( nisdigit(*visblty,4) &&
1169                 strlen(*visblty) >= 4)
1170    {
1171       if( strcmp(*visblty+4,"NE") == 0 )
1172       {
1173          memset(Mptr->vsby_Dir,'\0',3);
1174          strcpy(Mptr->vsby_Dir,*visblty+4);
1175       }
1176       if( strcmp(*visblty+4,"NW") == 0 )
1177       {
1178          memset(Mptr->vsby_Dir,'\0',3);
1179          strcpy(Mptr->vsby_Dir,*visblty+4);
1180       }
1181       if( strcmp(*visblty+4,"SE") == 0 )
1182       {
1183          memset(Mptr->vsby_Dir,'\0',3);
1184          strcpy(Mptr->vsby_Dir,*visblty+4);
1185       }
1186       if( strcmp(*visblty+4,"SW") == 0 )
1187       {
1188          memset(Mptr->vsby_Dir,'\0',3);
1189          strcpy(Mptr->vsby_Dir,*visblty+4);
1190       }
1191       if( strcmp(*visblty+4,"N") == 0 )
1192       {
1193          memset(Mptr->vsby_Dir,'\0',3);
1194          strcpy(Mptr->vsby_Dir,*visblty+4);
1195       }
1196       if( strcmp(*visblty+4,"S") == 0 )
1197       {
1198          memset(Mptr->vsby_Dir,'\0',3);
1199          strcpy(Mptr->vsby_Dir,*visblty+4);
1200       }
1201       if( strcmp(*visblty+4,"E") == 0 )
1202       {
1203          memset(Mptr->vsby_Dir,'\0',3);
1204          strcpy(Mptr->vsby_Dir,*visblty+4);
1205       }
1206       if( strcmp(*visblty+4,"W") == 0 )
1207       {
1208          memset(Mptr->vsby_Dir,'\0',3);
1209          strcpy(Mptr->vsby_Dir,*visblty+4);
1210       }
1211  
1212       if( antoi(*visblty,
1213                   strlen(*visblty)) >= 50 &&
1214                antoi(*visblty,
1215                   strlen(*visblty)) <= 500 &&
1216               (antoi(*visblty,
1217                   strlen(*visblty)) % 50) == 0 )
1218       {
1219          Mptr->prevail_vsbyM =
1220            (float) (antoi(*visblty,
1221                        strlen(*visblty)));
1222          (*NDEX)++;
1223          return TRUE;
1224       }
1225       else if( antoi(*visblty,
1226                  strlen(*visblty)) >= 500 &&
1227            antoi(*visblty,
1228                  strlen(*visblty)) <= 3000 &&
1229           (antoi(*visblty,
1230                  strlen(*visblty)) % 100) == 0 )
1231       {
1232          Mptr->prevail_vsbyM =
1233             (float) (antoi(*visblty,
1234                       strlen(*visblty)));
1235          (*NDEX)++;
1236          return TRUE;
1237       }
1238       else if( antoi(*visblty,
1239               strlen(*visblty)) >= 3000 &&
1240           antoi(*visblty,
1241               strlen(*visblty)) <= 5000 &&
1242           (antoi(*visblty,
1243                   strlen(*visblty)) % 500) == 0 )
1244       {
1245          Mptr->prevail_vsbyM =
1246                (float) (antoi(*visblty,
1247                     strlen(*visblty)));
1248          (*NDEX)++;
1249          return TRUE;
1250       }
1251       else if( antoi(*visblty,
1252             strlen(*visblty)) >= 5000 &&
1253           antoi(*visblty,
1254             strlen(*visblty)) <= 9999 &&
1255           (antoi(*visblty,
1256             strlen(*visblty)) % 500) == 0 ||
1257            antoi(*visblty,
1258             strlen(*visblty)) == 9999 )
1259       {
1260          Mptr->prevail_vsbyM =
1261                 (float) (antoi(*visblty,
1262                      strlen(*visblty)));
1263          (*NDEX)++;
1264          return TRUE;
1265       }
1266       else
1267          return FALSE;
1268  
1269    }
1270    else
1271       return FALSE;
1272  
1273 }
1274  
1275 /********************************************************************/
1276 /*                                                                  */
1277 /*  Title:         vrblVsby                                         */
1278 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1279 /*  Date:          15 Sep 1994                                      */
1280 /*  Programmer:    CARL MCCALLA                                     */
1281 /*  Language:      C/370                                            */
1282 /*                                                                  */
1283 /*  Abstract:                                                       */
1284 /*                                                                  */
1285 /*  External Functions Called:                                      */
1286 /*                 None.                                            */
1287 /*                                                                  */
1288 /*  Input:         x                                                */
1289 /*                                                                  */
1290 /*  Output:        x                                                */
1291 /*                                                                  */
1292 /*  Modification History:                                           */
1293 /*                 None.                                            */
1294 /*                                                                  */
1295 /********************************************************************/
1296 static bool vrblVsby( char *string1, char *string2,
1297                       Decoded_METAR *Mptr, int *NDEX )
1298 {
1299    char buf[ 6 ];
1300    /* int numerator,
1301        denominator; */
1302    char *slash,
1303         *V_char,
1304         *temp;
1305  
1306    if( string1 == NULL )
1307       return FALSE;
1308  
1309    V_char = strchr(string1,'V');
1310    slash =  strchr(string1,'/');
1311  
1312    if(slash == NULL)
1313    {
1314       if(nisdigit(string1,V_char-string1))
1315       {
1316          memset(buf, '\0', 6);
1317          strncpy(buf, string1, V_char-string1);
1318  
1319          if( Mptr->minVsby != (float) MAXINT )
1320             Mptr->minVsby += (float) atoi(buf);
1321          else
1322             Mptr->minVsby  = (float) atoi(buf);
1323  
1324          memset(buf, '\0', 6);
1325          strncpy(buf, V_char+1, 5);
1326          Mptr->maxVsby = (float) atoi(buf);
1327  
1328       }
1329       else
1330          return FALSE;
1331    }
1332    else
1333    {
1334       temp = (char *) malloc(sizeof(char)*((V_char-string1)+1));
1335       memset(temp, '\0', (V_char-string1) +1);
1336       strncpy(temp, string1, V_char-string1);
1337       if( Mptr->minVsby != MAXINT )
1338          Mptr->minVsby += fracPart(temp);
1339       else
1340          Mptr->minVsby = fracPart(temp);
1341  
1342       free( temp );
1343  
1344       if( strchr(V_char+1,'/') != NULL)
1345          Mptr->maxVsby = fracPart(V_char+1);
1346       else
1347          Mptr->maxVsby = (float) atoi(V_char+1);
1348    }
1349  
1350    if( string2 == NULL )
1351       return TRUE;
1352    else
1353    {
1354       slash = strchr( string2, '/' );
1355  
1356       if( slash == NULL )
1357          return TRUE;
1358       else
1359       {
1360          if( nisdigit(string2,slash-string2) &&
1361              nisdigit(slash+1,strlen(slash+1)) )
1362          {
1363             Mptr->maxVsby += fracPart(string2);
1364             (*NDEX)++;
1365          }
1366          return TRUE;
1367       }
1368    }
1369  
1370 }
1371  
1372  
1373 /********************************************************************/
1374 /*                                                                  */
1375 /*  Title:         isMinMaxWinDir                                   */
1376 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1377 /*  Date:          15 Sep 1994                                      */
1378 /*  Programmer:    CARL MCCALLA                                     */
1379 /*  Language:      C/370                                            */
1380 /*                                                                  */
1381 /*  Abstract:                                                       */
1382 /*                                                                  */
1383 /*  External Functions Called:                                      */
1384 /*                 None.                                            */
1385 /*                                                                  */
1386 /*  Input:         x                                                */
1387 /*                                                                  */
1388 /*  Output:        x                                                */
1389 /*                                                                  */
1390 /*  Modification History:                                           */
1391 /*                 None.                                            */
1392 /*                                                                  */
1393 /********************************************************************/
1394 static bool isMinMaxWinDir( char *string, Decoded_METAR *Mptr,
1395      int *NDEX )
1396 {
1397 #define buf_len 50
1398    char buf[ buf_len ];
1399    char *V_char;
1400  
1401    if( string == NULL )
1402       return FALSE;
1403  
1404    if( (V_char = strchr(string,'V')) == NULL )
1405       return FALSE;
1406    else
1407    {
1408       if( nisdigit(string,(V_char - string)) &&
1409                nisdigit(V_char+1,3) )
1410       {
1411          memset( buf, '\0', buf_len);
1412          strncpy( buf, string, V_char - string);
1413          Mptr->minWnDir = atoi( buf );
1414  
1415          memset( buf, '\0', buf_len);
1416          strcpy( buf, V_char+1 );
1417          Mptr->maxWnDir = atoi( buf );
1418  
1419          (*NDEX)++;
1420          return TRUE;
1421       }
1422       else
1423          return FALSE;
1424    }
1425 }
1426 /********************************************************************/
1427 /*                                                                  */
1428 /*  Title:         isRVR                                            */
1429 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1430 /*  Date:          15 Sep 1994                                      */
1431 /*  Programmer:    CARL MCCALLA                                     */
1432 /*  Language:      C/370                                            */
1433 /*                                                                  */
1434 /*  Abstract:                                                       */
1435 /*                                                                  */
1436 /*  External Functions Called:                                      */
1437 /*                 None.                                            */
1438 /*                                                                  */
1439 /*  Input:         x                                                */
1440 /*                                                                  */
1441 /*  Output:        x                                                */
1442 /*                                                                  */
1443 /*  Modification History:                                           */
1444 /*                 None.                                            */
1445 /*                                                                  */
1446 /********************************************************************/
1447  
1448 static bool isRVR( char *token, Decoded_METAR *Mptr, int *NDEX,
1449                      int ndex )
1450 {
1451    char *slashPtr, *FT_ptr;
1452    char *vPtr;
1453    int length;
1454  
1455    if( token == NULL )
1456       return FALSE;
1457  
1458    if( *token != 'R' || (length = strlen(token)) < 7 ||
1459         (slashPtr = strchr(token,'/')) == NULL ||
1460         nisdigit(token+1,2) == FALSE )
1461       return FALSE;
1462  
1463    if( (slashPtr - (token+3)) > 0 )
1464       if( !nisalpha(token+3,(slashPtr - (token+3))) )
1465          return FALSE;
1466  
1467    if( strcmp(token+(strlen(token)-2),"FT") != 0 )
1468       return FALSE;
1469    else
1470       FT_ptr = token + (strlen(token)-2);
1471  
1472    if( strchr(slashPtr+1, 'P' ) != NULL )
1473       Mptr->RRVR[ndex].above_max_RVR = TRUE;
1474  
1475    if( strchr(slashPtr+1, 'M' ) != NULL )
1476       Mptr->RRVR[ndex].below_min_RVR = TRUE;
1477  
1478  
1479    strncpy(Mptr->RRVR[ndex].runway_designator, token+1,
1480            (slashPtr-(token+1)));
1481  
1482    if( (vPtr = strchr(slashPtr, 'V' )) != NULL )
1483    {
1484       Mptr->RRVR[ndex].vrbl_visRange = TRUE;
1485       Mptr->RRVR[ndex].Min_visRange = antoi(slashPtr+1,
1486                               (vPtr-(slashPtr+1)) );
1487       Mptr->RRVR[ndex].Max_visRange = antoi(vPtr+1,
1488                               (FT_ptr - (vPtr+1)) );
1489       (*NDEX)++;
1490       return TRUE;
1491    }
1492    else
1493    {
1494       if( Mptr->RRVR[ndex].below_min_RVR ||
1495           Mptr->RRVR[ndex].above_max_RVR    )
1496          Mptr->RRVR[ndex].visRange = antoi(slashPtr+2,
1497                            (FT_ptr - (slashPtr+2)) );
1498       else
1499          Mptr->RRVR[ndex].visRange = antoi(slashPtr+1,
1500                            (FT_ptr - (slashPtr+1)) );
1501  
1502       (*NDEX)++;
1503       return TRUE;
1504    }
1505  
1506 }
1507  
1508  
1509 /********************************************************************/
1510 /*                                                                  */
1511 /*  Title:         isAltimStng                                      */
1512 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1513 /*  Date:          15 Sep 1994                                      */
1514 /*  Programmer:    CARL MCCALLA                                     */
1515 /*  Language:      C/370                                            */
1516 /*                                                                  */
1517 /*  Abstract:                                                       */
1518 /*                                                                  */
1519 /*  External Functions Called:                                      */
1520 /*                 None.                                            */
1521 /*                                                                  */
1522 /*  Input:         x                                                */
1523 /*                                                                  */
1524 /*  Output:        x                                                */
1525 /*                                                                  */
1526 /*  Modification History:                                           */
1527 /*                 None.                                            */
1528 /*                                                                  */
1529 /********************************************************************/
1530  
1531 static bool isAltimStng( char *token, Decoded_METAR *Mptr, int *NDEX )
1532 {
1533    char dummy[6];
1534  
1535  
1536    if( token == NULL )
1537       return FALSE;
1538  
1539    if( strlen(token) < 5 )
1540       return FALSE;
1541    else
1542    {
1543       Mptr->A_altstng = FALSE;
1544       Mptr->Q_altstng = FALSE;
1545  
1546       if( (*token == 'A' || *token == 'Q') &&
1547            (nisdigit(token+1, strlen(token)-1) ||
1548             nisdigit(token+1,strlen(token)-3)) )
1549       {
1550          if( *token == 'A' )
1551          {
1552             Mptr->A_altstng = TRUE;
1553             Mptr->inches_altstng = atof(token+1) * 0.01;
1554          }
1555          else
1556          {
1557             Mptr->Q_altstng = TRUE;
1558  
1559             if( strchr(token,'.') != NULL)
1560             {
1561                memset(dummy, '\0', 6);
1562                strncpy(dummy,token+1,4);
1563                Mptr->hectoPasc_altstng = atoi(dummy);
1564             }
1565             else
1566                Mptr->hectoPasc_altstng = atoi(token+1);
1567          }
1568  
1569          (*NDEX)++;
1570          return TRUE;
1571  
1572       }
1573       return FALSE;
1574    }
1575 }
1576  
1577  
1578 /********************************************************************/
1579 /*                                                                  */
1580 /*  Title:         isTempGroup                                      */
1581 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1582 /*  Date:          15 Sep 1994                                      */
1583 /*  Programmer:    CARL MCCALLA                                     */
1584 /*  Language:      C/370                                            */
1585 /*                                                                  */
1586 /*  Abstract:                                                       */
1587 /*                                                                  */
1588 /*  External Functions Called:                                      */
1589 /*                 None.                                            */
1590 /*                                                                  */
1591 /*  Input:         x                                                */
1592 /*                                                                  */
1593 /*  Output:        x                                                */
1594 /*                                                                  */
1595 /*  Modification History:                                           */
1596 /*                 None.                                            */
1597 /*                                                                  */
1598 /********************************************************************/
1599  
1600 static bool isTempGroup( char *token, Decoded_METAR *Mptr, int *NDEX)
1601 {
1602  
1603    /***************************/
1604    /* DECLARE LOCAL VARIABLES */
1605    /***************************/
1606  
1607    char *slash;
1608  
1609    if( token == NULL )
1610       return FALSE;
1611  
1612    if( (slash = strchr(token,'/')) == NULL)
1613       return FALSE;
1614    else
1615    {
1616       if( charcmp(token,"aa'/'dd") ) {
1617          Mptr->dew_pt_temp = atoi(slash+1);
1618          (*NDEX)++;
1619          return TRUE;
1620       }
1621       else if( charcmp(token,"aa'/''M'dd") ) {
1622          Mptr->dew_pt_temp = atoi(slash+2) * -1;
1623          (*NDEX)++;
1624          return TRUE;
1625       }
1626       else if( charcmp(token,"dd'/'aa") ) {
1627          Mptr->temp = antoi(token,(slash-token));
1628          (*NDEX)++;
1629          return TRUE;
1630       }
1631       else if( charcmp(token,"'M'dd'/'aa") ) {
1632          Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1633          (*NDEX)++;
1634          return TRUE;
1635       }
1636       else if( nisdigit(token,(slash-token)) &&
1637            nisdigit(slash+1,strlen(slash+1)) )
1638       {
1639          Mptr->temp = antoi(token,(slash-token));
1640          Mptr->dew_pt_temp = atoi(slash+1);
1641          (*NDEX)++;
1642          return TRUE;
1643       }
1644       else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
1645                 && *(slash+1) != '\0' &&
1646             *(slash+1) == 'M' && nisdigit(slash+2,strlen(slash+2)) )
1647       {
1648          Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1649          Mptr->dew_pt_temp = atoi(slash+2) * -1;
1650          (*NDEX)++;
1651          return TRUE;
1652       }
1653       else if( *token == 'M' && nisdigit(token+1,(slash-(token+1)))
1654                  && *(slash+1) != '\0' &&
1655                nisdigit(slash+1,strlen(slash+1)) )
1656       {
1657          Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1658          Mptr->dew_pt_temp = atoi(slash+1);
1659          (*NDEX)++;
1660          return TRUE;
1661       }
1662       else if( nisdigit(token,(slash - token)) &&
1663                     *(slash+1) != '\0' &&
1664                     nisdigit(slash+2,strlen(slash+2)) )
1665       {
1666          Mptr->temp = antoi(token,(slash-token));
1667          Mptr->dew_pt_temp = atoi(slash+2) * -1;
1668          (*NDEX)++;
1669          return TRUE;
1670       }
1671       else if( nisdigit(token,(slash-token)) &&
1672            strlen(token) <= 3)
1673       {
1674          Mptr->temp = antoi(token,(slash-token));
1675          (*NDEX)++;
1676          return TRUE;
1677       }
1678       else if( *token == 'M' &&
1679                    nisdigit(token+1,(slash-(token+1))) &&
1680                    strlen(token) <= 4)
1681       {
1682          Mptr->temp = antoi(token+1,(slash-(token+1))) * -1;
1683          (*NDEX)++;
1684          return TRUE;
1685       }
1686       else
1687          return FALSE;
1688    }
1689  
1690 }
1691  
1692  
1693  
1694 /********************************************************************/
1695 /*                                                                  */
1696 /*  Title:         isWxToken                                        */
1697 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1698 /*  Date:          15 Sep 1994                                      */
1699 /*  Programmer:    CARL MCCALLA                                     */
1700 /*  Language:      C/370                                            */
1701 /*                                                                  */
1702 /*  Abstract:                                                       */
1703 /*                                                                  */
1704 /*  External Functions Called:                                      */
1705 /*                 None.                                            */
1706 /*                                                                  */
1707 /*  Input:         x                                                */
1708 /*                                                                  */
1709 /*  Output:        x                                                */
1710 /*                                                                  */
1711 /*  Modification History:                                           */
1712 /*                 None.                                            */
1713 /*                                                                  */
1714 /********************************************************************/
1715  
1716 /*static bool isWxToken( char *token )
1717 {
1718    int i;
1719  
1720    if( token == NULL )
1721       return FALSE;
1722    for( i = 0; i < (int)strlen(token); i++ )
1723    {
1724       if( !(isalpha(*(token+i)) || *(token+i) == '+' ||
1725                                    *(token+i) == '-'   ) )
1726          return FALSE;
1727    }
1728    return TRUE;
1729 }*/
1730  
1731  
1732 /********************************************************************/
1733 /*                                                                  */
1734 /*  Title:         isPresentWX                                      */
1735 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1736 /*  Date:          15 Sep 1994                                      */
1737 /*  Programmer:    CARL MCCALLA                                     */
1738 /*  Language:      C/370                                            */
1739 /*                                                                  */
1740 /*  Abstract:                                                       */
1741 /*                                                                  */
1742 /*  External Functions Called:                                      */
1743 /*                 None.                                            */
1744 /*                                                                  */
1745 /*  Input:         x                                                */
1746 /*                                                                  */
1747 /*  Output:        x                                                */
1748 /*                                                                  */
1749 /*  Modification History:                                           */
1750 /*                 None.                                            */
1751 /*                                                                  */
1752 /********************************************************************/
1753  
1754 static bool isPresentWX( char *token, Decoded_METAR *Mptr,
1755                         int *NDEX, int *next )
1756 {
1757 /*
1758    static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
1759           "DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
1760           "FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
1761           "PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
1762           "SHGR", "SN", "SG", "SQ", "SA", "SS", "TSRA",
1763           "TSSN", "TSPE", "TSGS", "TSGR", "TS", "VA", "VCFG", "VCFC",
1764           "VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
1765 */
1766    static char *WxSymbols[] = {"BCFG", "BLDU", "BLSA", "BLPY",
1767           "BR", "FZBR", "VCBR",
1768           "DRDU", "DRSA", "DRSN", "DZ", "DS", "FZFG", "FZDZ", "FZRA",
1769           "FG", "FC", "FU", "GS", "GR", "HZ", "IC", "MIFG",
1770           "PE", "PO", "RA", "SHRA", "SHSN", "SHPE", "SHGS",
1771           "SHGR", "SN", "SG", "SQ", "SA", "SS", "TS",
1772           "VA", "VCFG", "VCFC",
1773           "VCSH", "VCPO", "VCBLDU", "VCBLSA", "VCBLSN", NULL};
1774    int i;
1775    char *ptr,
1776         *temp_token,
1777         *save_token,
1778         *temp_token_orig;
1779  
1780    if( token == NULL)
1781       return FALSE;
1782  
1783    temp_token_orig = temp_token =
1784         (char *) malloc(sizeof(char)*(strlen(token)+1));
1785    strcpy(temp_token, token);
1786    while( temp_token != NULL && (*next) < MAXWXSYMBOLS )
1787    {
1788       i = 0;
1789       save_token = NULL;
1790  
1791       if( *temp_token == '+' || *temp_token == '-' )
1792       {
1793          save_token = temp_token;
1794          temp_token++;
1795       }
1796  
1797       while( WxSymbols[i] != NULL )
1798          if( strncmp(temp_token, WxSymbols[i],
1799                       strlen(WxSymbols[i])) != 0 )
1800             i++;
1801          else
1802             break;
1803  
1804       if( WxSymbols[i] == NULL ) {
1805          free( temp_token_orig );
1806          return FALSE;
1807       }
1808       else
1809       {
1810  
1811          if( save_token != NULL )
1812          {
1813             strncpy( Mptr->WxObstruct[*next], save_token, 1);
1814             strcpy( (Mptr->WxObstruct[*next])+1,
1815                               WxSymbols[i]);
1816             (*next)++;
1817          }
1818          else
1819          {
1820             strcpy( Mptr->WxObstruct[*next], WxSymbols[i]);
1821             (*next)++;
1822          }
1823  
1824  
1825          if( strcmp(temp_token, WxSymbols[i]) != 0)
1826          {
1827             ptr = strstr(temp_token, WxSymbols[i]);
1828             temp_token = ptr + strlen(WxSymbols[i]);
1829          }
1830          else
1831          {
1832             free( temp_token_orig );
1833             temp_token = NULL;
1834             (*NDEX)++;
1835             return TRUE;
1836          }
1837  
1838       }
1839  
1840    }
1841  
1842    free( temp_token_orig );
1843    return FALSE;
1844  
1845 }
1846  
1847 /********************************************************************/
1848 /*                                                                  */
1849 /*  Title:         isStnID                                          */
1850 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1851 /*  Date:          15 Sep 1994                                      */
1852 /*  Programmer:    CARL MCCALLA                                     */
1853 /*  Language:      C/370                                            */
1854 /*                                                                  */
1855 /*  Abstract:                                                       */
1856 /*                                                                  */
1857 /*  External Functions Called:                                      */
1858 /*                 None.                                            */
1859 /*                                                                  */
1860 /*  Input:         x                                                */
1861 /*                                                                  */
1862 /*  Output:        x                                                */
1863 /*                                                                  */
1864 /*  Modification History:                                           */
1865 /*                 None.                                            */
1866 /*                                                                  */
1867 /********************************************************************/
1868  
1869 static bool isStnId( char *stnID, Decoded_METAR *Mptr, int *NDEX)
1870 {
1871  
1872    if( stnID == NULL )
1873       return FALSE;
1874  
1875    if( strlen(stnID) == 4 )
1876    {
1877       if( nisalpha(stnID,1) && nisalnum(stnID+1,3) ) {
1878          strcpy(Mptr->stnid,stnID);
1879          (*NDEX)++;
1880          return TRUE;
1881       }
1882       else
1883          return FALSE;
1884    }
1885    else
1886       return FALSE;
1887  
1888 }
1889  
1890 /********************************************************************/
1891 /*                                                                  */
1892 /*  Title:         isCodeName                                       */
1893 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1894 /*  Date:          15 Sep 1994                                      */
1895 /*  Programmer:    CARL MCCALLA                                     */
1896 /*  Language:      C/370                                            */
1897 /*                                                                  */
1898 /*  Abstract:                                                       */
1899 /*                                                                  */
1900 /*  External Functions Called:                                      */
1901 /*                 None.                                            */
1902 /*                                                                  */
1903 /*  Input:         x                                                */
1904 /*                                                                  */
1905 /*  Output:        x                                                */
1906 /*                                                                  */
1907 /*  Modification History:                                           */
1908 /*                 None.                                            */
1909 /*                                                                  */
1910 /********************************************************************/
1911  
1912 static bool isCodeName( char *codename, Decoded_METAR *Mptr, int *NDEX)
1913 {
1914    if( codename == NULL )
1915       return FALSE;
1916  
1917    if( strcmp(codename,"METAR") == 0 ||
1918        strcmp(codename,"SPECI") == 0   )
1919    {
1920       strcpy(Mptr->codeName, codename );
1921       (*NDEX)++;
1922       return TRUE;
1923    }
1924    else
1925       return FALSE;
1926  
1927 }
1928  
1929  
1930 /********************************************************************/
1931 /*                                                                  */
1932 /*  Title:         isNIL                                            */
1933 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1934 /*  Date:          15 Sep 1994                                      */
1935 /*  Programmer:    CARL MCCALLA                                     */
1936 /*  Language:      C/370                                            */
1937 /*                                                                  */
1938 /*  Abstract:                                                       */
1939 /*                                                                  */
1940 /*  External Functions Called:                                      */
1941 /*                 None.                                            */
1942 /*                                                                  */
1943 /*  Input:         x                                                */
1944 /*                                                                  */
1945 /*  Output:        x                                                */
1946 /*                                                                  */
1947 /*  Modification History:                                           */
1948 /*                 None.                                            */
1949 /*                                                                  */
1950 /********************************************************************/
1951  
1952 static bool isNIL( char *token, Decoded_METAR *Mptr, int *NDEX)
1953 {
1954  
1955    if( token == NULL )
1956       return FALSE;
1957  
1958    if( strcmp(token, "NIL") == 0 )
1959    {
1960       Mptr->NIL_rpt = TRUE;
1961       (*NDEX)++;
1962       return TRUE;
1963    }
1964    else
1965       return FALSE;
1966  
1967 }
1968  
1969 /********************************************************************/
1970 /*                                                                  */
1971 /*  Title:         isAUTO                                           */
1972 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
1973 /*  Date:          15 Sep 1994                                      */
1974 /*  Programmer:    CARL MCCALLA                                     */
1975 /*  Language:      C/370                                            */
1976 /*                                                                  */
1977 /*  Abstract:                                                       */
1978 /*                                                                  */
1979 /*  External Functions Called:                                      */
1980 /*                 None.                                            */
1981 /*                                                                  */
1982 /*  Input:         x                                                */
1983 /*                                                                  */
1984 /*  Output:        x                                                */
1985 /*                                                                  */
1986 /*  Modification History:                                           */
1987 /*                 None.                                            */
1988 /*                                                                  */
1989 /********************************************************************/
1990  
1991 static bool isAUTO( char *token, Decoded_METAR *Mptr, int *NDEX)
1992 {
1993  
1994    if( token == NULL )
1995       return FALSE;
1996  
1997    if( strcmp(token, "AUTO") == 0 )
1998    {
1999       Mptr->AUTO = TRUE;
2000       (*NDEX)++;
2001       return TRUE;
2002    }
2003    else
2004       return FALSE;
2005  
2006 }
2007  
2008 /********************************************************************/
2009 /*                                                                  */
2010 /*  Title:         isCOR                                            */
2011 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
2012 /*  Date:          24 Apr 1996                                      */
2013 /*  Programmer:    CARL MCCALLA                                     */
2014 /*  Language:      C/370                                            */
2015 /*                                                                  */
2016 /*  Abstract:                                                       */
2017 /*                                                                  */
2018 /*  External Functions Called:                                      */
2019 /*                 None.                                            */
2020 /*                                                                  */
2021 /*  Input:         x                                                */
2022 /*                                                                  */
2023 /*  Output:        x                                                */
2024 /*                                                                  */
2025 /*  Modification History:                                           */
2026 /*                 None.                                            */
2027 /*                                                                  */
2028 /********************************************************************/
2029  
2030 static bool isCOR ( char *token, Decoded_METAR *Mptr, int *NDEX)
2031 {
2032  
2033    if( token == NULL )
2034       return FALSE;
2035  
2036    if( strcmp(token, "COR") == 0 )
2037    {
2038       Mptr->COR  = TRUE;
2039       (*NDEX)++;
2040       return TRUE;
2041    }
2042    else
2043       return FALSE;
2044  
2045 }
2046  
2047 /********************************************************************/
2048 /*                                                                  */
2049 /*  Title:         isTimeUTC                                        */
2050 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
2051 /*  Date:          15 Sep 1994                                      */
2052 /*  Programmer:    CARL MCCALLA                                     */
2053 /*  Language:      C/370                                            */
2054 /*                                                                  */
2055 /*  Abstract:                                                       */
2056 /*                                                                  */
2057 /*  External Functions Called:                                      */
2058 /*                 None.                                            */
2059 /*                                                                  */
2060 /*  Input:         x                                                */
2061 /*                                                                  */
2062 /*  Output:        x                                                */
2063 /*                                                                  */
2064 /*  Modification History:                                           */
2065 /*                 None.                                            */
2066 /*                                                                  */
2067 /********************************************************************/
2068  
2069 static bool isTimeUTC( char *UTC, Decoded_METAR *Mptr, int *NDEX )
2070 {
2071  
2072    if( UTC == NULL )
2073       return FALSE;
2074  
2075    if( strlen( UTC ) == 4 ) {
2076       if(nisdigit(UTC,4) ) {
2077          Mptr->ob_hour = antoi(UTC,2);
2078          Mptr->ob_minute = antoi(UTC+2,2);
2079          (*NDEX)++;
2080          return TRUE;
2081       }
2082       else
2083          return FALSE;
2084    }
2085    else if( strlen( UTC ) == 6 ) {
2086       if(nisdigit(UTC,6) ) {
2087          Mptr->ob_date = antoi(UTC,2);
2088          Mptr->ob_hour = antoi(UTC+2,2);
2089          Mptr->ob_minute = antoi(UTC+4,2);
2090          (*NDEX)++;
2091          return TRUE;
2092       }
2093       else
2094          return FALSE;
2095    }
2096    if( strlen( UTC ) == 5 ) {
2097       if(nisdigit(UTC,4) && (*(UTC+4) == 'Z') ) {
2098          Mptr->ob_hour = antoi(UTC,2);
2099          Mptr->ob_minute = antoi(UTC+2,2);
2100          (*NDEX)++;
2101          return TRUE;
2102       }
2103       else
2104          return FALSE;
2105    }
2106    else if( strlen( UTC ) == 7 ) {
2107       if(nisdigit(UTC,6) && (*(UTC+6) == 'Z') ) {
2108          Mptr->ob_date = antoi(UTC,2);
2109          Mptr->ob_hour = antoi(UTC+2, 2);
2110          Mptr->ob_minute = antoi(UTC+4, 2 );
2111          (*NDEX)++;
2112          return TRUE;
2113       }
2114       else
2115          return FALSE;
2116    }
2117    else
2118       return FALSE;
2119 }
2120  
2121  
2122 /********************************************************************/
2123 /*                                                                  */
2124 /*  Title:         isWindData                                       */
2125 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
2126 /*  Date:          15 Sep 1994                                      */
2127 /*  Programmer:    CARL MCCALLA                                     */
2128 /*  Language:      C/370                                            */
2129 /*                                                                  */
2130 /*  Abstract:                                                       */
2131 /*                                                                  */
2132 /*  External Functions Called:                                      */
2133 /*                 None.                                            */
2134 /*                                                                  */
2135 /*  Input:         x                                                */
2136 /*                                                                  */
2137 /*  Output:        x                                                */
2138 /*                                                                  */
2139 /*  Modification History:                                           */
2140 /*                 None.                                            */
2141 /*                                                                  */
2142 /********************************************************************/
2143  
2144 static bool isWindData( char *wind, Decoded_METAR *Mptr, int *NDEX )
2145 {
2146  
2147    char *GustPtr,
2148         *unitsPtr;
2149    char dummy[8];
2150  
2151    if( wind == NULL )
2152       return FALSE;
2153  
2154    if( strlen(wind) < 7 )
2155       return FALSE;
2156  
2157    memset(dummy,'\0',8);
2158  
2159    if( ( unitsPtr = strstr( wind, "KMH" ) ) != NULL )
2160       strcpy( dummy, "KMH" );
2161    else if( (unitsPtr = strstr( wind, "KT") ) != NULL )
2162       strcpy( dummy, "KT" );
2163    else if( (unitsPtr = strstr( wind, "MPS") ) != NULL )
2164       strcpy( dummy, "MPS" );
2165    else
2166       return FALSE;
2167  
2168    if( (GustPtr = strchr( wind, 'G' )) != NULL )
2169    {
2170       if( (nisdigit(wind,(GustPtr-wind)) ||
2171             (strncmp(wind,"VRB",3) == 0 &&
2172               nisdigit(wind+3,(GustPtr-(wind+3))))) &&
2173             nisdigit(GustPtr+1,(unitsPtr-(GustPtr+1))) &&
2174             ((GustPtr-wind) >= 5 && (GustPtr-wind) <= 6) &&
2175             ((unitsPtr-(GustPtr+1)) >= 2 &&
2176              (unitsPtr-(GustPtr+1)) <= 3) )
2177       {
2178          if( strncmp(wind,"VRB",3) == 0 )
2179             Mptr->winData.windVRB = TRUE;
2180          else
2181             Mptr->winData.windDir = antoi(wind,3);
2182  
2183          Mptr->winData.windSpeed = antoi(wind+3, (GustPtr-(wind+3)));
2184          Mptr->winData.windGust = antoi(GustPtr+1,(unitsPtr-
2185                                                     (GustPtr+1)));
2186          (*NDEX)++;
2187          strcpy( Mptr->winData.windUnits, dummy );
2188          return TRUE;
2189       }
2190       else
2191          return FALSE;
2192    }
2193    else if( nisdigit(wind,(unitsPtr-wind)) ||
2194                 (strncmp(wind,"VRB",3) == 0 &&
2195                   nisdigit(wind+3,(unitsPtr-(wind+3)))) &&
2196             ((unitsPtr-wind) >= 5 && (unitsPtr-wind) <= 6) )
2197    {
2198       if( strncmp(wind,"VRB",3) == 0 )
2199          Mptr->winData.windVRB = TRUE;
2200       else
2201          Mptr->winData.windDir = antoi(wind, 3);
2202  
2203       Mptr->winData.windSpeed = antoi(wind+3,(unitsPtr-(wind+3)));
2204       (*NDEX)++;
2205       strcpy( Mptr->winData.windUnits, dummy );
2206       return TRUE;
2207    }
2208    else
2209       return FALSE;
2210  
2211 }
2212 /********************************************************************/
2213 /*                                                                  */
2214 /*  Title:         DcdMETAR                                         */
2215 /*  Organization:  W/OSO242 - GRAPHICS AND DISPLAY SECTION          */
2216 /*  Date:          14 Sep 1994                                      */
2217 /*  Programmer:    CARL MCCALLA                                     */
2218 /*  Language:      C/370                                            */
2219 /*                                                                  */
2220 /*  Abstract:      DcdMETAR takes a pointer to a METAR report char- */
2221 /*                 acter string as input, decodes the report, and   */
2222 /*                 puts the individual decoded/parsed groups into   */
2223 /*                 a structure that has the variable type           */
2224 /*                 Decoded_METAR.                                   */
2225 /*                                                                  */
2226 /*  Input:         string - a pointer to a METAR report character   */
2227 /*                          string.                                 */
2228 /*                                                                  */
2229 /*  Output:        Mptr   - a pointer to a structure that has the   */
2230 /*                          variable type Decoded_METAR.            */
2231 /*                                                                  */
2232 /*  Modification History:                                           */
2233 /*                 None.                                            */
2234 /*                                                                  */
2235 /********************************************************************/
2236  
2237  
2238 int DcdMETAR( char *string , Decoded_METAR *Mptr )
2239 {
2240  
2241    /***************************/
2242    /* DECLARE LOCAL VARIABLES */
2243    /***************************/
2244  
2245  
2246    enum METAR_obGroup { codename, stnid, NIL1, COR1, obDateTime, NIL2,
2247                         AUTO, COR, windData, MinMaxWinDir,
2248                         CAVOK, visibility,
2249                         RVR, presentWX, PartialObscur,
2250                         skyCond, tempGroup,
2251                         altimStng, NotIDed = 99 }
2252    StartGroup, SaveStartGroup, MetarGroup;
2253  
2254    // WindStruct *WinDataPtr;
2255  
2256    int ndex;
2257    int NDEX;
2258    // int i, jkj, j;
2259  
2260  
2261    char   **token,
2262           *delimeters = {" "};
2263  
2264    bool IS_NOT_RMKS;
2265  
2266 /*********************************/
2267 /* BEGIN THE BODY OF THE ROUTINE */
2268 /*********************************/
2269  
2270    /********************************************************/
2271    /* ONLY PARSE OR DECOCODE NON-NULL METAR REPORT STRINGS */
2272    /********************************************************/
2273  
2274    if( string == NULL )
2275       return 8;
2276  
2277  
2278    /*****************************************/
2279    /*   INITIALIZE STRUCTURE THAT HAS THE   */
2280    /*      VARIABLE TYPE Decoded_METAR      */
2281    /*****************************************/
2282  
2283    InitDcdMETAR( Mptr );
2284  
2285 #ifdef DEBUGZZ
2286    printf("DcdMETAR: Returned from InitDcdMETAR\n");
2287 #endif
2288  
2289  
2290    /****************************************************/
2291    /* TOKENIZE AND STORE THE INPUT METAR REPORT STRING */
2292    /****************************************************/
2293 #ifdef DEBUGZZ
2294    printf("DcdMETAR: Before start of tokenizing, string = %s\n",
2295              string);
2296 #endif
2297  
2298    token = SaveTokenString( string, delimeters );
2299  
2300  
2301  
2302    /*********************************************************/
2303    /* DECODE THE METAR REPORT (POSITIONAL ORDER PRECEDENCE) */
2304    /*********************************************************/
2305  
2306    NDEX = 0;
2307    MetarGroup = codename;
2308    IS_NOT_RMKS = TRUE;
2309  
2310 #ifdef DEBUGZZ
2311 printf("DcdMETAR: token[0] = %s\n",token[0]);
2312 #endif
2313  
2314    while( token[NDEX] != NULL && IS_NOT_RMKS ) {
2315  
2316 #ifdef DEBUGZZ
2317 if( strcmp(token[0],"OPKC") == 0 || strcmp(token[0],"MDSD") == 0 )
2318    printf("DcdMETAR:  token[%d] = %s\n",NDEX,token[NDEX]);
2319 #endif
2320  
2321 #ifdef DEBUGZZ
2322    printf("DcdMETAR: Token[%d] = %s\n",NDEX,token[NDEX]);
2323 #endif
2324 #ifdef DEBUGZZ
2325    printf("DcdMETAR: MetarGroup = %d\n",MetarGroup);
2326 #endif
2327  
2328     if( strcmp( token[NDEX], "RMK" ) != 0 ) {
2329  
2330       StartGroup = NotIDed;
2331  
2332 #ifdef DEBUGZZ
2333    printf("DcdMETAR: StartGroup = %d\n",StartGroup);
2334    printf("DcdMETAR: SaveStartGroup = %d\n",SaveStartGroup);
2335 #endif
2336  
2337       /**********************************************/
2338       /* SET ID_break_CODE TO ITS DEFAULT VALUE OF  */
2339       /* 99, WHICH MEANS THAT NO SUCCESSFUL ATTEMPT */
2340       /* WAS MADE TO DECODE ANY METAR CODED GROUP   */
2341       /* FOR THIS PASS THROUGH THE DECODING LOOP    */
2342       /**********************************************/
2343       switch( MetarGroup ) {
2344          case( codename ):
2345             if( isCodeName( token[NDEX], Mptr, &NDEX ) )
2346                SaveStartGroup = StartGroup = codename;
2347             MetarGroup = stnid;
2348             break;
2349          case( stnid ):
2350             if( isStnId( token[NDEX], Mptr, &NDEX ) ) {
2351                SaveStartGroup = StartGroup = stnid;
2352                MetarGroup = NIL1;
2353             }
2354             else {
2355 #ifdef DEBUGZZ
2356 printf("DcdMETAR:  token[%d] = %s\n",NDEX,token[NDEX]);
2357 #endif
2358                freeTokens( token );
2359                return 12;
2360             }
2361             break;
2362          case( NIL1 ):
2363             if( isNIL( token[NDEX], Mptr, &NDEX ) )
2364                SaveStartGroup = StartGroup = NIL1;
2365             MetarGroup = COR1;
2366             break;
2367          case( COR1 ):
2368             if( isCOR( token[NDEX], Mptr, &NDEX ) )
2369                SaveStartGroup = StartGroup = COR1;
2370             MetarGroup = obDateTime;
2371             break;
2372          case( obDateTime ):
2373 /*
2374             if( isTimeUTC( token[NDEX], Mptr, &NDEX ) ) {
2375                SaveStartGroup = StartGroup = obDateTime;
2376                MetarGroup = NIL2;
2377             }
2378             else {
2379                freeTokens( token );
2380                return 12;
2381             }
2382             break;
2383 */
2384             if( isTimeUTC( token[NDEX], Mptr, &NDEX ) )
2385                SaveStartGroup = StartGroup = obDateTime;
2386             MetarGroup = NIL2;
2387             break;
2388          case( NIL2 ):
2389             if( isNIL( token[NDEX], Mptr, &NDEX ) )
2390                SaveStartGroup = StartGroup = NIL2;
2391             MetarGroup = AUTO;
2392             break;
2393          case( AUTO ):
2394             if( isAUTO( token[NDEX], Mptr, &NDEX ) )
2395                SaveStartGroup = StartGroup = AUTO;
2396             MetarGroup = COR;
2397             break;
2398          case( COR ):
2399             if( isCOR( token[NDEX], Mptr, &NDEX ) )
2400                SaveStartGroup = StartGroup = COR;
2401             MetarGroup = windData;
2402             break;
2403          case( windData ):
2404             if( isWindData( token[NDEX], Mptr, &NDEX ) )
2405                SaveStartGroup = StartGroup = windData;
2406             MetarGroup = MinMaxWinDir;
2407             break;
2408          case( MinMaxWinDir ):
2409             if( isMinMaxWinDir( token[NDEX], Mptr, &NDEX ) )
2410                SaveStartGroup = StartGroup = MinMaxWinDir;
2411             MetarGroup = CAVOK;
2412             break;
2413          case( CAVOK ):
2414             if( isCAVOK( token[NDEX], Mptr, &NDEX ) )
2415                SaveStartGroup = StartGroup = CAVOK;
2416             MetarGroup = visibility;
2417             break;
2418          case( visibility ):
2419             if( isVisibility( &(token[NDEX]), Mptr, &NDEX ) )
2420                SaveStartGroup = StartGroup = visibility;
2421             MetarGroup = RVR;
2422             break;
2423          case( RVR ):
2424             ndex = 0;
2425             MetarGroup = presentWX;
2426  
2427             while (isRVR( token[NDEX], Mptr, &NDEX, ndex ) &&
2428                                ndex < 12 ) {
2429                ndex++;
2430                SaveStartGroup = StartGroup = RVR;
2431                MetarGroup = presentWX;
2432             }
2433             break;
2434          case( presentWX ):
2435             ndex = 0;
2436             MetarGroup = skyCond;
2437  
2438             while( isPresentWX( token[NDEX], Mptr, &NDEX,
2439                           &ndex ) && ndex < MAXWXSYMBOLS) {
2440                SaveStartGroup = StartGroup = presentWX;
2441                MetarGroup = PartialObscur;
2442             }
2443             break;
2444          case( PartialObscur ):
2445             if( isPartObscur( &(token[NDEX]), Mptr, &NDEX ) )
2446                SaveStartGroup = StartGroup = PartialObscur;
2447             MetarGroup = skyCond;
2448             break;
2449          case( skyCond ):
2450             if( isSkyCond( &(token[NDEX]), Mptr, &NDEX ) )
2451                SaveStartGroup = StartGroup = skyCond;
2452             MetarGroup = tempGroup;
2453             break;
2454          case( tempGroup ):
2455             if( isTempGroup( token[NDEX], Mptr, &NDEX ) )
2456                SaveStartGroup = StartGroup = tempGroup;
2457             MetarGroup = altimStng;
2458             break;
2459          case( altimStng ):
2460             if( isAltimStng( token[NDEX], Mptr, &NDEX ) )
2461                SaveStartGroup = StartGroup = altimStng;
2462             MetarGroup = NotIDed;
2463             break;
2464          default:
2465             NDEX++;
2466             MetarGroup = SaveStartGroup;
2467 /*          MetarGroup = ResetMETARGroup( StartGroup,
2468                                           SaveStartGroup );  */
2469             break;
2470       }
2471     }
2472     else
2473       IS_NOT_RMKS = FALSE;
2474  
2475    }
2476  
2477  
2478 #ifdef DEBUGZZ
2479    printf("DcdMETAR:  while loop exited, Token[%d] = %s\n",
2480                   NDEX,token[NDEX]);
2481 #endif
2482                                      /******************************/
2483                                      /* DECODE GROUPS FOUND IN THE */
2484                                      /*  REMARKS SECTION OF THE    */
2485                                      /*       METAR REPORT         */
2486                                      /******************************/
2487  
2488    if( token[NDEX] != NULL )
2489       if( strcmp( token[NDEX], "RMK" ) == 0 )
2490          DcdMTRmk( token, Mptr );
2491  
2492                            /****************************************/
2493    freeTokens( token );    /* FREE THE STORAGE ALLOCATED FOR THE   */
2494                            /* ARRAY USED TO HOLD THE METAR REPORT  */
2495                            /*                GROUPS                */
2496                            /****************************************/
2497    return 0;
2498  
2499 }