1 /*********************************************************************
2  *   Copyright 1993, UCAR/Unidata
3  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  *   $Id$
5  *********************************************************************/
6 
7 /* yacc source for "ncgen", a netCDL parser and netCDF generator */
8 
9 %{
10 #ifndef lint
11 static char SccsId[] = "$Id$";
12 #endif
13 #include        <string.h>
14 #include	<stdlib.h>
15 #include        "ncgen.h"
16 
17 typedef struct Symbol {		/* symbol table entry */
18 	char    	*name;
19 	struct Symbol   *next;
20 	unsigned	is_dim : 1;	/* appears as netCDF dimension */
21 	unsigned	is_var : 1;	/* appears as netCDF variable */
22 	unsigned	is_att : 1;	/* appears as netCDF attribute */
23 	int             dnum;	        /* handle as a dimension */
24 	int             vnum;	        /* handle as a variable */
25 	} *YYSTYPE1;
26 
27 #define YYSTYPE YYSTYPE1
28 YYSTYPE install(), lookup();
29 YYSTYPE symlist;		/* symbol table: linked list */
30 
31 void init_netcdf();		/* initializes netcdf counts (e.g. nvars) */
32 void define_netcdf();		/* generates all define mode stuff */
33 void load_netcdf();		/* generates variable puts */
34 void close_netcdf();		/* generates close */
35 
36 void derror();			/* varargs message emitter */
37 void *emalloc(), *erealloc();	/* malloc that checks for memory exhausted */
38 void clearout();		/* initializes symbol table */
39 void nc_getfill();		/* to get fill value for various types */
40 void nc_putfill();		/* to get fill value for various types */
41 void nc_fill();		/* fills a generic array with a value */
42 int  put_variable();            /* invoke nc calls or generate code to put */
43                                 /* variable values            */
44 extern int derror_count;	/* counts errors in netcdf definition */
45 extern int lineno;		/* line number for error messages */
46 
47 static int not_a_string;	/* whether last constant read was a string */
48 static char termstring[MAXTRST]; /* last terminal string read */
49 static double double_val;	/* last double value read */
50 static float float_val;		/* last float value read */
51 static nclong long_val;		/* last long value read */
52 static short short_val;		/* last short value read */
53 static char char_val;		/* last char value read */
54 static char byte_val;		/* last byte value read */
55 
56 static nc_type type_code;	/* holds declared type for variables */
57 static nc_type atype_code;	/* holds derived type for attributes */
58 static char *netcdfname;	/* to construct netcdf file name */
59 static void *att_space;		/* pointer to block for attribute values */
60 static nc_type valtype;		/* type code for list of attribute values  */
61 
62 static char *char_valp;		/* pointers used to accumulate data values */
63 static char *byte_valp;
64 static short *short_valp;
65 static nclong *long_valp;
66 static float *float_valp;
67 static double *double_valp;
68 static void *rec_cur;		/* pointer to where next data value goes */
69 static void *rec_start;		/* start of space for a record of data */
70 %}
71 
72 /* DECLARATIONS */
73 
74 %token
75 	NC_UNLIMITED_K /* keyword for unbounded record dimension */
76 	BYTE_K	    /* keyword for byte datatype */
77 	CHAR_K	    /* keyword for char datatype */
78 	SHORT_K	    /* keyword for short datatype */
79 	LONG_K	    /* keyword for long datatype */
80 	FLOAT_K	    /* keyword for float datatype */
81 	DOUBLE_K    /* keyword for double datatype */
82 	IDENT	    /* name for a dimension, variable, or attribute */
83 	TERMSTRING  /* terminal string */
84 	BYTE_CONST  /* byte constant */
85 	CHAR_CONST  /* char constant */
86 	SHORT_CONST /* short constant */
87 	LONG_CONST  /* long constant */
88 	FLOAT_CONST /* float constant */
89 	DOUBLE_CONST /* double constant */
90 	DIMENSIONS  /* keyword starting dimensions section, if any */
91 	VARIABLES   /* keyword starting variables section, if any */
92 	NETCDF      /* keyword declaring netcdf name */
93 	DATA        /* keyword starting data section, if any */
94 
95 %start	ncdesc /* start symbol for grammar */
96 
97 %%
98 
99 /* RULES */
100 
101 ncdesc:	NETCDF
102 		'{'
103 		   { init_netcdf(); }
104                 dimsection	/* dimension declarations */
105                      {
106                        if (ndims > H4_MAX_NC_DIMS)
107                          derror("Too many dimensions");
108                    }
109                 vasection	/* variable and attribute declarations */
110 		   {
111 		       if (derror_count == 0)
112 			 define_netcdf(netcdfname);
113 		   }
114 		datasection     /* data, variables loaded as encountered */
115                 '}'
116 		   {
117 		       if (derror_count == 0)
118 			 close_netcdf();
119 		   }
120 		;
121 dimsection:     /* empty */
122 		| DIMENSIONS dimdecls
123 		;
124 dimdecls:       dimdecline ';'
125 		| dimdecls dimdecline ';'
126 		;
127 dimdecline:     dimdecl
128                 | dimdecline ',' dimdecl
129                 ;
130 dimdecl:        dimd '=' LONG_CONST
131 		   { if (long_val <= 0)
132 			 derror("negative dimension size");
133 		     dims[ndims].size = long_val;
134 		     ndims++;
135 		   }
136                 | dimd '=' NC_UNLIMITED_K
137 		   {  if (rec_dim != -1)
138 			 derror("only one NC_UNLIMITED dimension allowed");
139 		     rec_dim = ndims; /* the unlimited (record) dimension */
140 		     dims[ndims].size = NC_UNLIMITED;
141 		     ndims++;
142 		   }
143                 ;
144 dimd:           dim
145 		   { if ($1->is_dim == 1) {
146 		        derror( "duplicate dimension declaration for %s",
147 		                $1->name);
148 		     }
149 	             $1->is_dim = 1;
150 		     $1->dnum = ndims;
151 		     dims[ndims].name = (char *) emalloc(strlen($1->name)+1);
152 		     (void) strcpy(dims[ndims].name, $1->name);
153 		   }
154                 ;
155 dim:		IDENT
156 		;
157 vasection:      /* empty */
158 		| VARIABLES vadecls
159 		;
160 vadecls:        vadecl ';'
161                 | vadecls vadecl ';'
162                 ;
163 vadecl:         vardecl | attdecl
164                 ;
165 vardecl:        type varlist
166                 ;
167 type:             BYTE_K  { type_code = NC_BYTE; }
168 		| CHAR_K  { type_code = NC_CHAR; }
169 		| SHORT_K  { type_code = NC_SHORT; }
170 		| LONG_K  { type_code = NC_LONG; }
171 		| FLOAT_K  { type_code = NC_FLOAT; }
172 		| DOUBLE_K  { type_code = NC_DOUBLE; }
173 		;
174 varlist:        varspec
175                 | varlist ',' varspec
176                 ;
177 varspec:        var
178 		   {
179 		    if (nvars >= H4_MAX_NC_VARS)
180 		       derror("too many variables");
181 		    nvdims = 0;
182 		    /* make sure variable not re-declared */
183 		    if ($1->is_var == 1) {
184 		       derror( "duplicate variable declaration for %s",
185 		               $1->name);
186 		    }
187 	            $1->is_var = 1;
188 		    $1->vnum = nvars;
189 		    vars[nvars].name = (char *) emalloc(strlen($1->name)+1);
190 		    (void) strcpy(vars[nvars].name, $1->name);
191 		    vars[nvars].type = type_code;
192 		    /* set default fill value.  You can override this with
193 		     * the variable attribute "_FillValue". */
194 		    nc_getfill(type_code, &vars[nvars].fill_value);
195 		    vars[nvars].has_data = 0; /* has no data (yet) */
196 		   }
197 		dimspec
198 		   {
199 		    vars[nvars].ndims = nvdims;
200 		    nvars++;
201 		   }
202 		;
203 var:            IDENT
204                 ;
205 dimspec:	/* empty */
206 		| '(' dimlist ')'
207 		;
208 dimlist:        vdim
209                 | dimlist ',' vdim
210                 ;
211 vdim:		dim
212 		   {
213 		    if (nvdims >= H4_MAX_VAR_DIMS) {
214 		       derror("%s has too many dimensions",vars[nvars].name);
215 		    }
216 		    if ($1->is_dim == 1)
217 		       dimnum = $1->dnum;
218 		    else {
219 		       derror( "%s is not declared as a dimension",
220 			       $1->name);
221 	               dimnum = ndims;
222 		    }
223 		    if (rec_dim != -1 && dimnum == rec_dim && nvdims != 0) {
224 		       derror("unlimited dimension must be first");
225 		    }
226 		    vars[nvars].dims[nvdims] = dimnum;
227                     nvdims++;
228 		   }
229 		;
230 attdecl:        att
231 		   {
232 		       valnum = 0;
233 		       valtype = NC_UNSPECIFIED;
234 		       /* get a large block for attributes, realloc later */
235 		       att_space = emalloc(H4_MAX_NC_ATTSIZE);
236 		       /* make all kinds of pointers point to it */
237 		       char_valp = (char *) att_space;
238 		       byte_valp = (char *) att_space;
239 		       short_valp = (short *) att_space;
240 		       long_valp = (nclong *) att_space;
241 		       float_valp = (float *) att_space;
242 		       double_valp = (double *) att_space;
243 		   }
244 		'=' attvallist
245 		   {
246 		       if (natts >= H4_MAX_NC_ATTRS)
247 			 derror("too many attributes");
248 		       atts[natts].var = varnum ;
249 		       atts[natts].type = valtype;
250 		       atts[natts].len = valnum;
251 		       /* shrink space down to what was really needed */
252 		       att_space = erealloc(att_space, valnum*nctypelen(valtype));
253 		       atts[natts].val = att_space;
254 		       if (STREQ(atts[natts].name, _FillValue)) {
255 			   nc_putfill(atts[natts].type,
256 				       atts[natts].val,
257 				       &vars[atts[natts].var].fill_value);
258 		       }
259 		       natts++;
260 		   }
261                 ;
262 att:            avar ':' attr
263                 |    ':' attr
264 		   {
265 		    varnum = -1;  /* handle of "global" attribute */
266 		   }
267                 ;
268 
269 avar:           var
270 		   { if ($1->is_var == 1)
271 		       varnum = $1->vnum;
272 		    else {
273 		      derror("%s not declared as a variable, fatal error",
274 			     $1->name);
275 		      YYABORT;
276 		      }
277 		   }
278 		;
279 attr:		IDENT
280 		   {
281 		       atts[natts].name = (char *) emalloc(strlen($1->name)+1);
282 		       (void) strcpy(atts[natts].name,$1->name);
283 		   }
284 		;
285 attvallist:     aconst
286                 | attvallist ',' aconst
287                 ;
288 aconst:		attconst
289 		   {
290 		    if (valtype == NC_UNSPECIFIED)
291 		      valtype = atype_code;
292 		    if (valtype != atype_code)
293 		      derror("values for attribute must be all of same type");
294 		   }
295 		;
296 
297 attconst:      CHAR_CONST
298                    {
299 		       atype_code = NC_CHAR;
300 		       *char_valp++ = char_val;
301 		       valnum++;
302 		   }
303 	       | TERMSTRING
304 		   {
305 		       atype_code = NC_CHAR;
306 		       {
307 			   /* don't null-terminate attribute strings */
308 			   int len = strlen(termstring);
309 			   valnum += len;
310 			   (void)strncpy(char_valp,termstring,len);
311 			   char_valp += len;
312 		       }
313 		   }
314                 | BYTE_CONST
315                    {
316 		       atype_code = NC_BYTE;
317 		       *byte_valp++ = byte_val;
318 		       valnum++;
319 		   }
320                 | SHORT_CONST
321                    {
322 		       atype_code = NC_SHORT;
323 		       *short_valp++ = short_val;
324 		       valnum++;
325 		   }
326                 | LONG_CONST
327                    {
328 		       atype_code = NC_LONG;
329 		       *long_valp++ = long_val;
330 		       valnum++;
331 		   }
332                 | FLOAT_CONST
333                    {
334 		       atype_code = NC_FLOAT;
335 		       *float_valp++ = float_val;
336 		       valnum++;
337 		   }
338                 | DOUBLE_CONST
339                    {
340 		       atype_code = NC_DOUBLE;
341 		       *double_valp++ = double_val;
342 		       valnum++;
343 		   }
344                 ;
345 
346 datasection:    /* empty */
347 		| DATA datadecls
348 		;
349 
350 datadecls:      datadecl ';'
351                 | datadecls datadecl ';'
352                 ;
353 datadecl:       avar
354 		   {
355 		       valtype = vars[varnum].type; /* variable type */
356 		       valnum = 0;	/* values accumulated for variable */
357 		       vars[varnum].has_data = 1;
358 		       /* compute dimensions product (size of a "record") */
359 		       var_size = nctypelen(valtype);
360 		       if (vars[varnum].ndims == 0)
361 			   var_len = 1;
362 		       else if (vars[varnum].dims[0] == rec_dim) {
363 			   var_len = 1; /* one record for unlimited vars */
364 			   netcdf_record_number = 0;
365 		       }
366 		       else
367 			 var_len = dims[vars[varnum].dims[0]].size;
368 		       for(dimnum = 1; dimnum < vars[varnum].ndims; dimnum++)
369 			 var_len = var_len*dims[vars[varnum].dims[dimnum]].size;
370 		       /* allocate memory for a record of variable data */
371 		       if (var_len*var_size != (unsigned)(var_len*var_size)) {
372 			   derror("too much data for this machine");
373 			   exit(9);
374 		       }
375 		       rec_start = malloc ((unsigned)(var_len*var_size));
376 		       if (rec_start == 0) {
377 			   derror ("out of memory\n");
378 			   exit(3);
379 		       }
380 		       rec_cur = rec_start;
381 		       switch (valtype) {
382 			 case NC_CHAR:
383 			   char_valp = (char *) rec_start;
384 			   break;
385 			 case NC_BYTE:
386 			   byte_valp = (char *) rec_start;
387 			   break;
388 			 case NC_SHORT:
389 			   short_valp = (short *) rec_start;
390 			   break;
391 			 case NC_LONG:
392 			   long_valp = (nclong *) rec_start;
393 			   break;
394 			 case NC_FLOAT:
395 			   float_valp = (float *) rec_start;
396 			   break;
397 			 case NC_DOUBLE:
398 			   double_valp = (double *) rec_start;
399 			   break;
400 		       }
401 		 }
402 		'=' constlist
403                    {
404 		       if (valnum > 0 && valnum < var_len) { /* leftovers */
405 			   nc_fill(valtype,
406 				    var_len - valnum,
407 				    rec_cur,
408 				    vars[varnum].fill_value);
409 			   /* put out record of var_len values */
410 			   if (derror_count == 0)
411 			     put_variable(rec_start);
412 		       }
413 		       free ((char *) rec_start);
414 		 }
415                 ;
416 constlist:      dconst
417                 | constlist ',' dconst
418                 ;
419 dconst:
420                    {
421 		       if(valnum >= var_len) {
422 			   derror("too many values for this variable");
423 			   exit (4);
424 		       }
425 		       not_a_string = 1;
426                    }
427                 const
428 		   {
429 		       if (not_a_string) {
430 			   switch (valtype) {
431 			     case NC_CHAR:
432 			       rec_cur = (void *) char_valp;
433 			       break;
434 			     case NC_BYTE:
435 			       rec_cur = (void *) byte_valp;
436 			       break;
437 			     case NC_SHORT:
438 			       rec_cur = (void *) short_valp;
439 			       break;
440 			     case NC_LONG:
441 			       rec_cur = (void *) long_valp;
442 			       break;
443 			     case NC_FLOAT:
444 			       rec_cur = (void *) float_valp;
445 			       break;
446 			     case NC_DOUBLE:
447 			       rec_cur = (void *) double_valp;
448 			       break;
449 			   }
450 		       }
451 		       if (valnum >= var_len) {
452 			   /* put out record of var_len elements */
453 			   if (derror_count == 0)
454 			     put_variable(rec_start);
455 			   /* if this variable is unbounded, reset for */
456 			   /* next record */
457 			   if (vars[varnum].dims[0] == rec_dim) {
458 			       valnum = 0;
459 			       netcdf_record_number++;
460 			       rec_cur = rec_start;
461 			       switch (valtype) {
462 				 case NC_CHAR:
463 				   char_valp = (char *) rec_start;
464 				   break;
465 				 case NC_BYTE:
466 				   byte_valp = (char *) rec_start;
467 				   break;
468 				 case NC_SHORT:
469 				   short_valp = (short *) rec_start;
470 				   break;
471 				 case NC_LONG:
472 				   long_valp = (nclong *) rec_start;
473 				   break;
474 				 case NC_FLOAT:
475 				   float_valp = (float *) rec_start;
476 				   break;
477 				 case NC_DOUBLE:
478 				   double_valp = (double *) rec_start;
479 				   break;
480 			       }
481 			   }
482 		       }
483 		 }
484 		;
485 
486 const:         CHAR_CONST
487                    {
488 		       atype_code = NC_CHAR;
489 		       switch (valtype) {
490 			 case NC_CHAR:
491 			   *char_valp++ = char_val;
492 			   break;
493 			 case NC_BYTE:
494 			   *byte_valp++ = char_val;
495 			   break;
496 			 case NC_SHORT:
497 			   *short_valp++ = char_val;
498 			   break;
499 			 case NC_LONG:
500 			   *long_valp++ = char_val;
501 			   break;
502 			 case NC_FLOAT:
503 			   *float_valp++ = char_val;
504 			   break;
505 			 case NC_DOUBLE:
506 			   *double_valp++ = char_val;
507 			   break;
508 		       }
509 		       valnum++;
510 		   }
511 	       | TERMSTRING
512 		   {
513 		       not_a_string = 0;
514 		       atype_code = NC_CHAR;
515 		       {
516 			   int len = strlen(termstring);
517 
518 			   valnum += len;
519 			   if(valnum > var_len) {
520 			       derror("string won't fit in this variable");
521 			       exit (5);
522 			   }
523 			   switch (valtype) {
524 			     case NC_CHAR:
525 			       (void)strncpy(char_valp,termstring,len);
526 			       char_valp += len;
527 			       rec_cur = (void *) char_valp;
528 			       break;
529 			     case NC_BYTE:
530 			       (void)strncpy(byte_valp,termstring,len);
531 			       byte_valp += len;
532 			       rec_cur = (void *) byte_valp;
533 			       break;
534 			     case NC_SHORT:
535 			     case NC_LONG:
536 			     case NC_FLOAT:
537 			     case NC_DOUBLE:
538 			       derror("string value invalid for %s variable",
539 				      nctype(valtype));
540 			       break;
541 			   }
542 		       }
543 		   }
544                 | BYTE_CONST
545                    {
546 		       atype_code = NC_BYTE;
547 		       switch (valtype) {
548 			 case NC_CHAR:
549 			   *char_valp++ = byte_val;
550 			   break;
551 			 case NC_BYTE:
552 			   *byte_valp++ = byte_val;
553 			   break;
554 			 case NC_SHORT:
555 			   *short_valp++ = byte_val;
556 			   break;
557 			 case NC_LONG:
558 			   *long_valp++ = byte_val;
559 			   break;
560 			 case NC_FLOAT:
561 			   *float_valp++ = byte_val;
562 			   break;
563 			 case NC_DOUBLE:
564 			   *double_valp++ = byte_val;
565 			   break;
566 		       }
567 		       valnum++;
568 		   }
569                 | SHORT_CONST
570                    {
571 		       atype_code = NC_SHORT;
572 		       switch (valtype) {
573 			 case NC_CHAR:
574 			   *char_valp++ = short_val;
575 			   break;
576 			 case NC_BYTE:
577 			   *byte_valp++ = short_val;
578 			   break;
579 			 case NC_SHORT:
580 			   *short_valp++ = short_val;
581 			   break;
582 			 case NC_LONG:
583 			   *long_valp++ = short_val;
584 			   break;
585 			 case NC_FLOAT:
586 			   *float_valp++ = short_val;
587 			   break;
588 			 case NC_DOUBLE:
589 			   *double_valp++ = short_val;
590 			   break;
591 		       }
592 		       valnum++;
593 		   }
594                 | LONG_CONST
595                    {
596 		       atype_code = NC_LONG;
597 		       switch (valtype) {
598 			 case NC_CHAR:
599 			   *char_valp++ = long_val;
600 			   break;
601 			 case NC_BYTE:
602 			   *byte_valp++ = long_val;
603 			   break;
604 			 case NC_SHORT:
605 			   *short_valp++ = long_val;
606 			   break;
607 			 case NC_LONG:
608 			   *long_valp++ = long_val;
609 			   break;
610 			 case NC_FLOAT:
611 			   *float_valp++ = long_val;
612 			   break;
613 			 case NC_DOUBLE:
614 			   *double_valp++ = long_val;
615 			   break;
616 		       }
617 		       valnum++;
618 		   }
619                 | FLOAT_CONST
620                    {
621 		       atype_code = NC_FLOAT;
622 		       switch (valtype) {
623 			 case NC_CHAR:
624 			   *char_valp++ = float_val;
625 			   break;
626 			 case NC_BYTE:
627 			   *byte_valp++ = float_val;
628 			   break;
629 			 case NC_SHORT:
630 			   *short_valp++ = float_val;
631 			   break;
632 			 case NC_LONG:
633 			   *long_valp++ = float_val;
634 			   break;
635 			 case NC_FLOAT:
636 			   *float_valp++ = float_val;
637 			   break;
638 			 case NC_DOUBLE:
639 			   *double_valp++ = float_val;
640 			   break;
641 		       }
642 		       valnum++;
643 		   }
644                 | DOUBLE_CONST
645                    {
646 		       atype_code = NC_DOUBLE;
647 		       switch (valtype) {
648 			 case NC_CHAR:
649 			   *char_valp++ = double_val;
650 			   break;
651 			 case NC_BYTE:
652 			   *byte_valp++ = double_val;
653 			   break;
654 			 case NC_SHORT:
655 			   *short_valp++ = double_val;
656 			   break;
657 			 case NC_LONG:
658 			   *long_valp++ = double_val;
659 			   break;
660 			 case NC_FLOAT:
661 			   if (double_val == FILL_DOUBLE)
662 			     *float_valp++ = FILL_FLOAT;
663 			   else
664 			     *float_valp++ = double_val;
665 			   break;
666 			 case NC_DOUBLE:
667 			   *double_valp++ = double_val;
668 			   break;
669 		       }
670 		       valnum++;
671 		   }
672                 ;
673 
674 /* END OF RULES */
675 
676 %%
677 
678 /* PROGRAMS */
679 
680 /* get lexical input routine generated by lex  */
681 #include "ncgenyy.c"
682 
683 void derror();
684 
yyerror(s)685 yyerror(s)	/* called for yacc syntax error */
686      char *s;
687 {
688 	derror(s);
689 }
690 
691 #ifndef yywrap
692 int
yywrap()693 yywrap()			/* returns 1 on EOF if no more input */
694 {
695     return  1;
696 }
697 #endif /* yywrap() */
698 
699 
700 /* Symbol table operations for ncgen tool */
701 
lookup(sname)702 YYSTYPE lookup(sname)       /* find sname in symbol table (linear search) */
703 char *sname;
704 {
705     YYSTYPE sp;
706     for (sp = symlist; sp != (YYSTYPE) 0; sp = sp -> next)
707 	if (STREQ(sp -> name, sname)) {
708 	    return sp;
709 	}
710     return 0;			/* 0 ==> not found */
711 }
712 
install(sname)713 YYSTYPE install(sname)  /* install sname in symbol table */
714 char *sname;
715 {
716     YYSTYPE sp;
717 
718     sp = (YYSTYPE) emalloc (sizeof (struct Symbol));
719     sp -> name = (char *) emalloc (strlen (sname) + 1);/* +1 for '\0' */
720     (void) strcpy (sp -> name, sname);
721     sp -> next = symlist;	/* put at front of list */
722     sp -> is_dim = 0;
723     sp -> is_var = 0;
724     sp -> is_att = 0;
725     symlist = sp;
726     return sp;
727 }
728 
729 void
clearout()730 clearout()	/* reset symbol table to empty */
731 {
732     YYSTYPE sp, tp;
733     for (sp = symlist; sp != (YYSTYPE) 0;) {
734 	tp = sp -> next;
735 	free (sp -> name);
736 	free ((char *) sp);
737 	sp = tp;
738     }
739     symlist = 0;
740 }
741