1 /*
2  * (C) Copyright 2005- ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  *
7  * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9  */
10 
11 /***************************************************************************
12  *   Jean Baptiste Filippi - 01.11.2005                                    *
13  *   Enrico Fucile
14  *                                                                         *
15  ***************************************************************************/
16 #include "grib_api_internal.h"
17 
18 grib_action* grib_parser_all_actions          = 0;
19 grib_context* grib_parser_context             = 0;
20 grib_concept_value* grib_parser_concept       = 0;
21 grib_hash_array_value* grib_parser_hash_array = 0;
22 grib_rule* grib_parser_rules                  = 0;
23 
24 extern FILE* grib_yyin;
25 extern int grib_yydebug;
26 
27 static const char* parse_file = 0;
28 
29 #if GRIB_PTHREADS
30 static pthread_once_t once              = PTHREAD_ONCE_INIT;
31 static pthread_mutex_t mutex_file       = PTHREAD_MUTEX_INITIALIZER;
32 static pthread_mutex_t mutex_rules      = PTHREAD_MUTEX_INITIALIZER;
33 static pthread_mutex_t mutex_concept    = PTHREAD_MUTEX_INITIALIZER;
34 static pthread_mutex_t mutex_hash_array = PTHREAD_MUTEX_INITIALIZER;
35 static pthread_mutex_t mutex_stream     = PTHREAD_MUTEX_INITIALIZER;
36 static pthread_mutex_t mutex_parse      = PTHREAD_MUTEX_INITIALIZER;
37 
init()38 static void init()
39 {
40     pthread_mutexattr_t attr;
41     pthread_mutexattr_init(&attr);
42     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
43     pthread_mutex_init(&mutex_file, &attr);
44     pthread_mutex_init(&mutex_rules, &attr);
45     pthread_mutex_init(&mutex_concept, &attr);
46     pthread_mutex_init(&mutex_hash_array, &attr);
47     pthread_mutex_init(&mutex_stream, &attr);
48     pthread_mutex_init(&mutex_parse, &attr);
49     pthread_mutexattr_destroy(&attr);
50 }
51 #elif GRIB_OMP_THREADS
52 static int once = 0;
53 static omp_nest_lock_t mutex_file;
54 static omp_nest_lock_t mutex_rules;
55 static omp_nest_lock_t mutex_concept;
56 static omp_nest_lock_t mutex_hash_array;
57 static omp_nest_lock_t mutex_stream;
58 static omp_nest_lock_t mutex_parse;
59 
init()60 static void init()
61 {
62     GRIB_OMP_CRITICAL(lock_grib_parse_utils_c)
63     {
64         if (once == 0) {
65             omp_init_nest_lock(&mutex_file);
66             omp_init_nest_lock(&mutex_rules);
67             omp_init_nest_lock(&mutex_concept);
68             omp_init_nest_lock(&mutex_hash_array);
69             omp_init_nest_lock(&mutex_stream);
70             omp_init_nest_lock(&mutex_parse);
71             once = 1;
72         }
73     }
74 }
75 #endif
76 
grib_recompose_name(grib_handle * h,grib_accessor * observer,const char * uname,char * fname,int fail)77 int grib_recompose_name(grib_handle* h, grib_accessor* observer, const char* uname, char* fname, int fail)
78 {
79     grib_accessor* a;
80     char loc[1024] = {0,};
81     int i          = 0;
82     int ret        = 0;
83     int mode       = -1;
84     char val[1024] = {0,};
85     double dval        = 0;
86     long lval          = 0;
87     int type           = GRIB_TYPE_STRING;
88     size_t replen      = 0;
89     char* ptrEnd_fname = NULL; /* Maintain ptr to end of fname string */
90 
91     loc[0]       = 0;
92     fname[0]     = 0;
93     ptrEnd_fname = fname;
94 
95     /* uname is a string like "grib[GRIBEditionNumber:l]/boot.def". The result fname will be grib2/boot.def */
96     while (uname[i] != '\0') {
97         if (mode > -1) {
98             if (uname[i] == ':') {
99                 type = grib_type_to_int(uname[i + 1]);
100                 i++;
101             }
102             else if (uname[i] == ']') {
103                 loc[mode] = 0;
104                 mode      = -1;
105                 a         = grib_find_accessor(h, loc);
106                 if (!a) {
107                     if (!fail) {
108                         sprintf(val, "undef");
109                     }
110                     else {
111                         grib_context_log(h->context, GRIB_LOG_WARNING, "grib_recompose_name: Problem to recompose filename with : %s ( %s no accessor found)", uname, loc);
112                         return GRIB_NOT_FOUND;
113                     }
114                 }
115                 else {
116                     switch (type) {
117                         case GRIB_TYPE_STRING:
118                             replen = 1024;
119                             ret    = grib_unpack_string(a, val, &replen);
120                             break;
121                         case GRIB_TYPE_DOUBLE:
122                             replen = 1;
123                             ret    = grib_unpack_double(a, &dval, &replen);
124                             sprintf(val, "%.12g", dval);
125                             break;
126                         case GRIB_TYPE_LONG:
127                             replen = 1;
128                             ret    = grib_unpack_long(a, &lval, &replen);
129                             sprintf(val, "%d", (int)lval);
130                             break;
131                         default:
132                             grib_context_log(h->context, GRIB_LOG_WARNING, "grib_recompose_name: Problem to recompose filename with : %s, invalid type %d", loc, type);
133                             break;
134                     }
135 
136                     grib_dependency_add(observer, a);
137 
138                     if ((ret != GRIB_SUCCESS)) {
139                         grib_context_log(h->context, GRIB_LOG_ERROR, "grib_recompose_name: Could not recompose filename : %s", uname);
140                         return ret;
141                     }
142                 }
143                 {
144                     char* pc = fname;
145                     while (*pc != '\0')
146                         pc++;
147                     strcpy(pc, val);
148                     ptrEnd_fname = pc + strlen(val); /* Update ptr to end of fname */
149                 }
150 
151                 loc[0] = 0;
152             }
153             else
154                 loc[mode++] = uname[i];
155         }
156         else if (uname[i] == '[')
157             mode = 0;
158         else {
159 #if 0
160             int llen=strlen(fname);  /* The strlen cost is too high */
161             fname[llen]=uname[i];
162             fname[llen+1]='\0';
163 #else
164             /* Performance: faster to avoid call to strlen. Append to end */
165             *ptrEnd_fname++ = uname[i];
166             *ptrEnd_fname   = '\0';
167 #endif
168             type = GRIB_TYPE_STRING;
169         }
170         i++;
171     }
172     /*fprintf(stdout,"parsed > %s\n",fname);*/
173     return GRIB_SUCCESS;
174 }
175 
176 #if 0
177 int grib_accessor_print(grib_accessor* a, const char* name, int type, const char* format,
178                         const char* separator, int maxcols, int* newline, FILE* out)
179 {
180     size_t size     = 0;
181     char* sval      = NULL;
182     char* p         = NULL;
183     double* dval    = 0;
184     long* lval      = 0;
185     char sbuf[1024] = {0,};
186     size_t replen            = 0;
187     int ret                  = 0;
188     char* myformat           = NULL;
189     char* myseparator        = NULL;
190     char double_format[]     = "%.12g"; /* default format for printing double keys */
191     char long_format[]       = "%ld";   /* default format for printing integer keys */
192     char default_separator[] = " ";
193     grib_handle* h           = grib_handle_of_accessor(a);
194 
195     if (type == -1)
196         type = grib_accessor_get_native_type(a);
197     switch (type) {
198         case GRIB_TYPE_STRING:
199             replen = sizeof(sbuf) / sizeof(*sbuf);
200             ret    = grib_unpack_string(a, sbuf, &replen);
201             fprintf(out, "%s", sbuf);
202             break;
203         case GRIB_TYPE_DOUBLE:
204             myformat    = format ? (char*)format : double_format;
205             myseparator = separator ? (char*)separator : default_separator;
206             if (name[0] == '/' || name[0] == '#') {
207                 long count;
208                 ret  = grib_value_count(a, &count);
209                 size = count;
210             }
211             else {
212                 ret = _grib_get_size(h, a, &size);
213             }
214             if (ret) return ret;
215             dval = (double*)grib_context_malloc_clear(h->context, sizeof(double) * size);
216             if (name[0] == '/' || name[0] == '#') {
217                 replen = size;
218                 ret    = grib_unpack_double(a, dval, &replen);
219             }
220             else {
221                 replen = 0;
222                 ret    = _grib_get_double_array_internal(h, a, dval, size, &replen);
223             }
224             if (replen == 1)
225                 fprintf(out, myformat, dval[0]);
226             else {
227                 int i    = 0;
228                 int cols = 0;
229                 for (i = 0; i < replen; i++) {
230                     *newline = 1;
231                     fprintf(out, myformat, dval[i]);
232                     if (i < replen - 1)
233                         fprintf(out, "%s", myseparator);
234                     cols++;
235                     if (cols >= maxcols) {
236                         fprintf(out, "\n");
237                         *newline = 1;
238                         cols     = 0;
239                     }
240                 }
241             }
242             grib_context_free(h->context, dval);
243             break;
244         case GRIB_TYPE_LONG:
245             myformat    = format ? (char*)format : long_format;
246             myseparator = separator ? (char*)separator : default_separator;
247             if (name[0] == '/' || name[0] == '#') {
248                 long count;
249                 ret  = grib_value_count(a, &count);
250                 size = count;
251             }
252             else {
253                 ret = _grib_get_size(h, a, &size);
254             }
255             if (ret) return ret;
256             lval = (long*)grib_context_malloc_clear(h->context, sizeof(long) * size);
257             if (name[0] == '/' || name[0] == '#') {
258                 replen = size;
259                 ret    = grib_unpack_long(a, lval, &replen);
260             }
261             else {
262                 replen = 0;
263                 ret    = _grib_get_long_array_internal(h, a, lval, size, &replen);
264             }
265             if (replen == 1)
266                 fprintf(out, myformat, lval[0]);
267             else {
268                 int i    = 0;
269                 int cols = 0;
270                 for (i = 0; i < replen; i++) {
271                     *newline = 1;
272                     fprintf(out, myformat, lval[i]);
273                     if (i < replen - 1)
274                         fprintf(out, "%s", myseparator);
275                     cols++;
276                     if (cols >= maxcols) {
277                         fprintf(out, "\n");
278                         *newline = 1;
279                         cols     = 0;
280                     }
281                 }
282             }
283             grib_context_free(h->context, lval);
284             break;
285         case GRIB_TYPE_BYTES:
286             replen = a->length;
287             sval   = (char*)grib_context_malloc(h->context, replen * sizeof(char));
288             ret    = grib_unpack_string(a, sval, &replen);
289             p      = sval;
290             while ((replen--) > 0)
291                 fprintf(out, "%c", *(p++));
292             grib_context_free(h->context, sval);
293             *newline = 0;
294             break;
295         default:
296             grib_context_log(h->context, GRIB_LOG_WARNING, "grib_accessor_print: Problem to print \"%s\", invalid type %d", a->name, type);
297     }
298     return ret;
299 }
300 #endif
301 
grib_accessors_list_print(grib_handle * h,grib_accessors_list * al,const char * name,int type,const char * format,const char * separator,int maxcols,int * newline,FILE * out)302 int grib_accessors_list_print(grib_handle* h, grib_accessors_list* al, const char* name,
303                               int type, const char* format, const char* separator, int maxcols, int* newline, FILE* out)
304 {
305     size_t size = 0, len = 0, replen = 0, j = 0;
306     unsigned char* bval      = NULL;
307     double* dval             = 0;
308     long* lval               = 0;
309     char** cvals             = NULL;
310     int ret                  = 0;
311     char* myformat           = NULL;
312     char* myseparator        = NULL;
313     char double_format[]     = "%.12g"; /* default format for printing double keys */
314     char long_format[]       = "%ld";   /* default format for printing integer keys */
315     char default_separator[] = " ";
316     grib_accessor* a         = al->accessor;
317 
318     /* Number of columns specified as 0 means print on ONE line i.e. num cols = infinity */
319     if (maxcols == 0)
320         maxcols = INT_MAX;
321 
322     if (type == -1)
323         type = grib_accessor_get_native_type(al->accessor);
324     grib_accessors_list_value_count(al, &size);
325     switch (type) {
326         case GRIB_TYPE_STRING:
327             myseparator = separator ? (char*)separator : default_separator;
328             if (size == 1) {
329                 char sbuf[1024] = {0,};
330                 len = sizeof(sbuf);
331                 ret = grib_unpack_string(al->accessor, sbuf, &len);
332                 if (grib_is_missing_string(al->accessor, (unsigned char*)sbuf, len)) {
333                     fprintf(out, "%s", "MISSING");
334                 }
335                 else {
336                     fprintf(out, "%s", sbuf);
337                 }
338             }
339             else {
340                 int cols = 0;
341                 j = 0;
342                 cvals    = (char**)grib_context_malloc_clear(h->context, sizeof(char*) * size);
343                 grib_accessors_list_unpack_string(al, cvals, &size);
344                 for (j = 0; j < size; j++) {
345                     *newline = 1;
346                     fprintf(out, "%s", cvals[j]);
347                     if (j < size - 1)
348                         fprintf(out, "%s", myseparator);
349                     cols++;
350                     if (cols >= maxcols) {
351                         fprintf(out, "\n");
352                         *newline = 1;
353                         cols     = 0;
354                     }
355                     grib_context_free(h->context, cvals[j]);
356                 }
357             }
358             grib_context_free(h->context, cvals);
359             break;
360         case GRIB_TYPE_DOUBLE:
361             myformat    = format ? (char*)format : double_format;
362             myseparator = separator ? (char*)separator : default_separator;
363             dval        = (double*)grib_context_malloc_clear(h->context, sizeof(double) * size);
364             ret         = grib_accessors_list_unpack_double(al, dval, &size);
365             if (size == 1)
366                 fprintf(out, myformat, dval[0]);
367             else {
368                 int cols = 0;
369                 j = 0;
370                 for (j = 0; j < size; j++) {
371                     *newline = 1;
372                     fprintf(out, myformat, dval[j]);
373                     if (j < size - 1)
374                         fprintf(out, "%s", myseparator);
375                     cols++;
376                     if (cols >= maxcols) {
377                         fprintf(out, "\n");
378                         *newline = 1;
379                         cols     = 0;
380                     }
381                 }
382             }
383             grib_context_free(h->context, dval);
384             break;
385         case GRIB_TYPE_LONG:
386             myformat    = format ? (char*)format : long_format;
387             myseparator = separator ? (char*)separator : default_separator;
388             lval        = (long*)grib_context_malloc_clear(h->context, sizeof(long) * size);
389             ret         = grib_accessors_list_unpack_long(al, lval, &size);
390             if (size == 1)
391                 fprintf(out, myformat, lval[0]);
392             else {
393                 int cols = 0;
394                 j = 0;
395                 for (j = 0; j < size; j++) {
396                     *newline = 1;
397                     fprintf(out, myformat, lval[j]);
398                     if (j < size - 1)
399                         fprintf(out, "%s", myseparator);
400                     cols++;
401                     if (cols >= maxcols) {
402                         fprintf(out, "\n");
403                         *newline = 1;
404                         cols     = 0;
405                     }
406                 }
407             }
408             grib_context_free(h->context, lval);
409             break;
410         case GRIB_TYPE_BYTES:
411             replen = a->length;
412             bval   = (unsigned char*)grib_context_malloc(h->context, replen * sizeof(unsigned char));
413             ret    = grib_unpack_bytes(al->accessor, bval, &replen);
414             for (j = 0; j < replen; j++) {
415                 fprintf(out, "%02x", bval[j]);
416             }
417             grib_context_free(h->context, bval);
418             *newline = 1;
419             break;
420         default:
421             grib_context_log(h->context, GRIB_LOG_WARNING,
422                              "grib_accessor_print: Problem printing \"%s\", invalid type %d", a->name, grib_get_type_name(type));
423     }
424     return ret;
425 }
426 
grib_recompose_print(grib_handle * h,grib_accessor * observer,const char * uname,int fail,FILE * out)427 int grib_recompose_print(grib_handle* h, grib_accessor* observer, const char* uname, int fail, FILE* out)
428 {
429     grib_accessors_list* al = NULL;
430     char loc[1024];
431     int i           = 0;
432     int ret         = 0;
433     int mode        = -1;
434     char* pp        = NULL;
435     char* format    = NULL;
436     int type        = -1;
437     char* separator = NULL;
438     int l;
439     char buff[10] = {0,};
440     char buff1[1024] = {0,};
441     int maxcolsd = 8;
442     int maxcols;
443     long numcols           = 0;
444     int newline            = 1;
445     const size_t uname_len = strlen(uname);
446 
447     maxcols = maxcolsd;
448     loc[0]  = 0;
449     for (i = 0; i < uname_len; i++) {
450         if (mode > -1) {
451             switch (uname[i]) {
452                 case ':':
453                     type = grib_type_to_int(uname[i + 1]);
454                     i++;
455                     break;
456                 case '\'':
457                     pp = (char*)(uname + i + 1);
458                     while (*pp != '%' && *pp != '!' && *pp != ']' && *pp != ':' && *pp != '\'')
459                         pp++;
460                     l = pp - uname - i;
461                     if (*pp == '\'')
462                         separator = strncpy(buff1, uname + i + 1, l - 1);
463                     i += l;
464                     break;
465                 case '%':
466                     pp = (char*)(uname + i + 1);
467                     while (*pp != '%' && *pp != '!' && *pp != ']' && *pp != ':' && *pp != '\'')
468                         pp++;
469                     l      = pp - uname - i;
470                     format = strncpy(buff, uname + i, l);
471                     i += l - 1;
472                     break;
473                 case '!':
474                     pp = (char*)uname;
475                     if (string_to_long(uname + i + 1, &numcols) == GRIB_SUCCESS) {
476                         maxcols = (int)numcols;
477                     }
478                     else {
479                         /* Columns specification is invalid integer */
480                         maxcols = maxcolsd;
481                     }
482                     strtol(uname + i + 1, &pp, 10);
483                     while (pp && *pp != '%' && *pp != '!' && *pp != ']' && *pp != ':' && *pp != '\'')
484                         pp++;
485                     i += pp - uname - i - 1;
486                     break;
487                 case ']':
488                     loc[mode] = 0;
489                     mode      = -1;
490                     if (al) grib_accessors_list_delete(h->context, al);
491                     al        = grib_find_accessors_list(h, loc); /* This allocates memory */
492                     if (!al) {
493                         if (!fail) {
494                             fprintf(out, "undef");
495                             ret = GRIB_NOT_FOUND;
496                         }
497                         else {
498                             grib_context_log(h->context, GRIB_LOG_WARNING, "grib_recompose_print: Problem to recompose print with : %s, no accessor found", loc);
499                             return GRIB_NOT_FOUND;
500                         }
501                     }
502                     else {
503                         ret = grib_accessors_list_print(h, al, loc, type, format, separator, maxcols, &newline, out);
504 
505                         if (ret != GRIB_SUCCESS) {
506                             /* grib_context_log(h->context, GRIB_LOG_ERROR,"grib_recompose_print: Could not recompose print : %s", uname); */
507                             grib_accessors_list_delete(h->context, al);
508                             return ret;
509                         }
510                     }
511                     loc[0] = 0;
512                     break;
513                 default:
514                     loc[mode++] = uname[i];
515                     break;
516             }
517         }
518         else if (uname[i] == '[') {
519             mode = 0;
520         }
521         else {
522             fprintf(out, "%c", uname[i]);
523             type = -1;
524         }
525     }
526     if (newline)
527         fprintf(out, "\n");
528 
529     grib_accessors_list_delete(h->context, al);
530     return ret;
531 }
532 
533 /* Note: A fast cut-down version of strcmp which does NOT return -1 */
534 /* 0 means input strings are equal and 1 means not equal */
grib_inline_strcmp(const char * a,const char * b)535 GRIB_INLINE static int grib_inline_strcmp(const char* a, const char* b)
536 {
537     if (*a != *b)
538         return 1;
539     while ((*a != 0 && *b != 0) && *(a) == *(b)) {
540         a++;
541         b++;
542     }
543     return (*a == 0 && *b == 0) ? 0 : 1;
544 }
545 
grib_find_action_file(const char * fname,grib_action_file_list * afl)546 grib_action_file* grib_find_action_file(const char* fname, grib_action_file_list* afl)
547 {
548     grib_action_file* act = afl->first;
549     while (act) {
550         if (grib_inline_strcmp(act->filename, fname) == 0)
551             return act;
552         act = act->next;
553     }
554     return 0;
555 }
556 
grib_push_action_file(grib_action_file * af,grib_action_file_list * afl)557 static void grib_push_action_file(grib_action_file* af, grib_action_file_list* afl)
558 {
559     if (!afl->first)
560         afl->first = afl->last = af;
561     else
562         afl->last->next = af;
563     afl->last = af;
564 }
565 
566 #define MAXINCLUDE 10
567 
568 typedef struct
569 {
570     char* name;
571     FILE* file;
572     char* io_buffer;
573     int line;
574 } context;
575 
576 static context stack[MAXINCLUDE];
577 static int top = 0;
578 extern FILE* grib_yyin;
579 extern int grib_yylineno;
580 extern void grib_yyrestart(FILE*);
581 static int error = 0;
582 
grib_yywrap()583 int grib_yywrap()
584 {
585     /* int i; */
586     top--;
587 
588     /* for(i = 0; i < top ; i++) printf("   "); */
589     /* printf("CLOSE %s\n",parse_file); */
590 
591     fclose(stack[top].file);
592     /* if (stack[top].io_buffer) free(stack[top].io_buffer); */
593 
594     grib_yylineno = stack[top].line;
595 
596     if (top) {
597         parse_file = stack[top - 1].name;
598         grib_yyin  = stack[top - 1].file;
599         Assert(parse_file);
600         Assert(grib_yyin);
601         /* grib_yyrestart(grib_yyin); */
602 
603         /* for(i = 0; i < top ; i++) printf("   "); */
604         /* printf("BACK TO %s\n",parse_file); */
605 
606         grib_context_free(grib_parser_context, stack[top].name);
607         return 0;
608     }
609     else {
610         grib_context_free(grib_parser_context, stack[top].name);
611         parse_file = 0;
612         grib_yyin  = NULL;
613         return 1;
614     }
615 }
616 
file_being_parsed()617 char* file_being_parsed()
618 {
619     return (char*)parse_file;
620 }
621 
grib_yyerror(const char * msg)622 int grib_yyerror(const char* msg)
623 {
624     grib_context_log(grib_parser_context, GRIB_LOG_ERROR,
625                      "grib_parser: %s at line %d of %s", msg, grib_yylineno + 1, parse_file);
626     grib_context_log(grib_parser_context, GRIB_LOG_ERROR,
627                      "ecCodes Version: %s", ECCODES_VERSION_STR);
628     error = 1;
629     return 1;
630 }
631 
grib_parser_include(const char * included_fname)632 void grib_parser_include(const char* included_fname)
633 {
634     FILE* f         = NULL;
635     char* io_buffer = 0;
636     /* int i; */
637     Assert(top < MAXINCLUDE);
638     Assert(included_fname);
639     if (!included_fname)
640         return;
641 
642     if (parse_file == 0) {
643         parse_file = included_fname;
644         Assert(top == 0);
645     }
646     else {
647         /* When parse_file is not NULL, it's the path of the parent file (includer) */
648         /* and 'included_fname' is the name of the file being included (includee) */
649 
650         /* GRIB-796: Search for the included file in ECCODES_DEFINITION_PATH */
651         char* new_path = NULL;
652         Assert(*included_fname != '/');
653         new_path = grib_context_full_defs_path(grib_parser_context, included_fname);
654         if (!new_path) {
655             fprintf(stderr, "ecCodes Version:       %s\nDefinition files path: %s\n",
656                     ECCODES_VERSION_STR,
657                     grib_parser_context->grib_definition_files_path);
658 
659             grib_context_log(grib_parser_context, GRIB_LOG_FATAL,
660                              "grib_parser_include: Could not resolve '%s' (included in %s)", included_fname, parse_file);
661 
662             return;
663         }
664         parse_file = new_path;
665     }
666 
667     if (strcmp(parse_file, "-") == 0) {
668         grib_context_log(grib_parser_context, GRIB_LOG_DEBUG, "parsing standard input");
669         f = stdin; /* read from std input */
670     }
671     else {
672         grib_context_log(grib_parser_context, GRIB_LOG_DEBUG, "parsing include file %s", parse_file);
673         f = codes_fopen(parse_file, "r");
674     }
675     /* for(i = 0; i < top ; i++) printf("   "); */
676     /* printf("PARSING %s\n",parse_file); */
677 
678     if (f == NULL) {
679         char buffer[1024];
680         grib_context_log(grib_parser_context, (GRIB_LOG_ERROR) | (GRIB_LOG_PERROR), "grib_parser_include: cannot open: '%s'", parse_file);
681         sprintf(buffer, "Cannot include file: '%s'", parse_file);
682         grib_yyerror(buffer);
683     }
684     else {
685         /*
686         c=grib_context_get_default();
687         if (c->io_buffer_size) {
688             if (posix_memalign(&(io_buffer),sysconf(_SC_PAGESIZE),c->io_buffer_size) ) {
689                         grib_context_log(c,GRIB_LOG_FATAL,"grib_parser_include: posix_memalign unable to allocate io_buffer\n");
690             }
691             setvbuf(f,io_buffer,_IOFBF,c->io_buffer_size);
692         }
693         */
694         grib_yyin            = f;
695         stack[top].file      = f;
696         stack[top].io_buffer = io_buffer;
697         stack[top].name      = grib_context_strdup(grib_parser_context, parse_file);
698         parse_file           = stack[top].name;
699         stack[top].line      = grib_yylineno;
700         grib_yylineno        = 0;
701         top++;
702         /* grib_yyrestart(f); */
703     }
704 }
705 
706 extern int grib_yyparse(void);
707 
parse(grib_context * gc,const char * filename)708 static int parse(grib_context* gc, const char* filename)
709 {
710     int err = 0;
711     GRIB_MUTEX_INIT_ONCE(&once, &init);
712     GRIB_MUTEX_LOCK(&mutex_parse);
713 
714 #ifdef YYDEBUG
715     {
716         extern int grib_yydebug;
717         grib_yydebug = getenv("YYDEBUG") != NULL;
718     }
719 #endif
720 
721     gc = gc ? gc : grib_context_get_default();
722 
723     grib_yyin  = NULL;
724     top        = 0;
725     parse_file = 0;
726     grib_parser_include(filename);
727     if (!grib_yyin) {
728         /* Could not read from file */
729         parse_file = 0;
730         GRIB_MUTEX_UNLOCK(&mutex_parse);
731         return GRIB_FILE_NOT_FOUND;
732     }
733     err        = grib_yyparse();
734     parse_file = 0;
735 
736     if (err)
737         grib_context_log(gc, GRIB_LOG_ERROR, "Parsing error: %s, file: %s\n",
738                 grib_get_error_message(err), filename);
739 
740     GRIB_MUTEX_UNLOCK(&mutex_parse);
741     return err;
742 }
743 
grib_parse_stream(grib_context * gc,const char * filename)744 static grib_action* grib_parse_stream(grib_context* gc, const char* filename)
745 {
746     GRIB_MUTEX_INIT_ONCE(&once, &init);
747     GRIB_MUTEX_LOCK(&mutex_stream);
748 
749     grib_parser_all_actions = 0;
750 
751     if (parse(gc, filename) == 0) {
752         if (grib_parser_all_actions) {
753             GRIB_MUTEX_UNLOCK(&mutex_stream)
754             return grib_parser_all_actions;
755         }
756         else {
757             grib_action* ret = grib_action_create_noop(gc, filename);
758             GRIB_MUTEX_UNLOCK(&mutex_stream)
759             return ret;
760         }
761     }
762     else {
763         GRIB_MUTEX_UNLOCK(&mutex_stream);
764         return NULL;
765     }
766 }
767 
grib_parse_concept_file(grib_context * gc,const char * filename)768 grib_concept_value* grib_parse_concept_file(grib_context* gc, const char* filename)
769 {
770     GRIB_MUTEX_INIT_ONCE(&once, &init);
771     GRIB_MUTEX_LOCK(&mutex_file);
772 
773     gc                  = gc ? gc : grib_context_get_default();
774     grib_parser_context = gc;
775 
776     if (parse(gc, filename) == 0) {
777         GRIB_MUTEX_UNLOCK(&mutex_file);
778         return grib_parser_concept;
779     }
780     else {
781         GRIB_MUTEX_UNLOCK(&mutex_file);
782         return NULL;
783     }
784 }
785 
grib_parse_hash_array_file(grib_context * gc,const char * filename)786 grib_hash_array_value* grib_parse_hash_array_file(grib_context* gc, const char* filename)
787 {
788     GRIB_MUTEX_INIT_ONCE(&once, &init);
789     GRIB_MUTEX_LOCK(&mutex_file);
790 
791     gc                  = gc ? gc : grib_context_get_default();
792     grib_parser_context = gc;
793 
794     if (parse(gc, filename) == 0) {
795         GRIB_MUTEX_UNLOCK(&mutex_file);
796         return grib_parser_hash_array;
797     }
798     else {
799         GRIB_MUTEX_UNLOCK(&mutex_file);
800         return NULL;
801     }
802 }
803 
grib_parse_rules_file(grib_context * gc,const char * filename)804 grib_rule* grib_parse_rules_file(grib_context* gc, const char* filename)
805 {
806     if (!gc)
807         gc = grib_context_get_default();
808 
809     GRIB_MUTEX_INIT_ONCE(&once, &init);
810     GRIB_MUTEX_LOCK(&mutex_rules);
811 
812     gc                  = gc ? gc : grib_context_get_default();
813     grib_parser_context = gc;
814 
815     if (parse(gc, filename) == 0) {
816         GRIB_MUTEX_UNLOCK(&mutex_rules);
817         return grib_parser_rules;
818     }
819     else {
820         GRIB_MUTEX_UNLOCK(&mutex_rules);
821         return NULL;
822     }
823 }
824 
grib_parse_file(grib_context * gc,const char * filename)825 grib_action* grib_parse_file(grib_context* gc, const char* filename)
826 {
827     grib_action_file* af;
828 
829     GRIB_MUTEX_INIT_ONCE(&once, &init);
830     GRIB_MUTEX_LOCK(&mutex_file);
831 
832     af = 0;
833 
834     gc = gc ? gc : grib_context_get_default();
835 
836     grib_parser_context = gc;
837 
838     if (!gc->grib_reader)
839         gc->grib_reader = (grib_action_file_list*)grib_context_malloc_clear_persistent(gc, sizeof(grib_action_file_list));
840     else {
841         af = grib_find_action_file(filename, gc->grib_reader);
842     }
843 
844     if (!af) {
845         grib_action* a;
846         grib_context_log(gc, GRIB_LOG_DEBUG, "Loading %s", filename);
847 
848         a = grib_parse_stream(gc, filename);
849 
850         if (error) {
851             if (a)
852                 grib_action_delete(gc, a);
853             GRIB_MUTEX_UNLOCK(&mutex_file);
854             return NULL;
855         }
856 
857         af = (grib_action_file*)grib_context_malloc_clear_persistent(gc, sizeof(grib_action_file));
858 
859         af->root = a;
860 
861         af->filename = grib_context_strdup_persistent(gc, filename);
862         grib_push_action_file(af, gc->grib_reader); /* Add af to grib_reader action file list */
863     }
864     else
865         grib_context_log(gc, GRIB_LOG_DEBUG, "Using cached version of %s", filename);
866 
867     GRIB_MUTEX_UNLOCK(&mutex_file);
868     return af->root;
869 }
870 
grib_type_to_int(char id)871 int grib_type_to_int(char id)
872 {
873     switch (id) {
874         case 'd':
875             return GRIB_TYPE_DOUBLE;
876             break;
877         case 'f':
878             return GRIB_TYPE_DOUBLE;
879             break;
880         case 'l':
881             return GRIB_TYPE_LONG;
882             break;
883         case 'i':
884             return GRIB_TYPE_LONG;
885             break;
886         case 's':
887             return GRIB_TYPE_STRING;
888             break;
889     }
890     return GRIB_TYPE_UNDEFINED;
891 }
892