1 /*********************************************************************
2  *   Copyright 1993, UCAR/Unidata
3  *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4  *   $Header: /upc/share/CVS/netcdf-3/ncgen/genc.c,v 1.6 2010/05/17 23:26:44 dmh Exp $
5  *********************************************************************/
6 
7 #include "includes.h"
8 #include "nc_iter.h"
9 #include <ctype.h>	/* for isprint() */
10 
11 #ifdef ENABLE_C
12 
13 #undef TRACE
14 
15 /* Forward */
16 static const char* groupncid(Symbol*);
17 static const char* typencid(Symbol*);
18 static const char* varncid(Symbol*);
19 static const char* dimncid(Symbol*);
20 
21 #ifdef USE_NETCDF4
22 static void definectype(Symbol*);
23 static void genc_deftype(Symbol*);
24 static void genc_definespecialattributes(Symbol* vsym);
25 static void genc_defineglobalspecials(void);
26 #endif
27 
28 static void genc_defineattr(Symbol* asym);
29 static void genc_definevardata(Symbol*);
30 static void genc_write(Generator*,Symbol* sym, Bytebuffer* code,
31                        int rank, size_t* start, size_t* count);
32 static void genc_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
33 static void genc_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
34 
35 /*
36  * Generate C code for creating netCDF from in-memory structure.
37  */
38 void
genc_netcdf(void)39 genc_netcdf(void)
40 {
41     int idim, ivar, iatt, maxdims;
42     int ndims, nvars, natts, ngatts;
43     char* cmode_string;
44     const char *filename = rootgroup->file.filename;
45 
46 #ifdef USE_NETCDF4
47     int igrp,ityp, ngrps, ntyps;
48 #endif
49 
50     ndims = listlength(dimdefs);
51     nvars = listlength(vardefs);
52     natts = listlength(attdefs);
53     ngatts = listlength(gattdefs);
54 #ifdef USE_NETCDF4
55     ngrps = listlength(grpdefs);
56     ntyps = listlength(typdefs);
57 #endif /*USE_NETCDF4*/
58 
59     /* wrap in main program */
60     codeline("#include <stdio.h>");
61     codeline("#include <stdlib.h>");
62     codeline("#include <netcdf.h>");
63     codeline("");
64     codeflush();
65 
66     if(specialconstants) {
67 	/* If the input referenced e.g. nan, inf, etc;
68 	   then provide definitions for them */
69         codeline("");
70 	codeline("#define nanf (0.0f/0.0f)");
71 	codeline("#define nan  (0.0/0.0)");
72 	codeline("#define inff (1.0f/0.0f)");
73 	codeline("#define inf  (1.0/0.0)");
74 	codeline("#define infinityf inff");
75 	codeline("#define infinity  inf");
76         codeline("");
77         codeflush();
78     }
79     codeline("");
80     codeflush();
81 
82 #ifdef USE_NETCDF4
83 
84     /* Construct C type definitions*/
85     if (ntyps > 0) {
86 	for(ityp = 0; ityp < ntyps; ityp++) {
87 	    Symbol* tsym = (Symbol*)listget(typdefs,ityp);
88 	    definectype(tsym);
89 	}
90 	codeline("");
91     }
92     codeflush();
93 
94     /* Construct the chunking constants*/
95     if(!usingclassic) {
96         for(ivar=0;ivar<nvars;ivar++) {
97             Bytebuffer* tmp = bbNew();
98             Symbol* var = (Symbol*)listget(vardefs,ivar);
99             Specialdata* special = var->var.special;
100             if(special->flags & _CHUNKSIZES_FLAG) {
101                 int i;
102                 size_t* chunks = special->_ChunkSizes;
103                 if(special->nchunks == 0 || chunks == NULL) continue;
104                 bbClear(tmp);
105                 for(i=0;i<special->nchunks;i++) {
106                     bbprintf(tmp,"%s%ld",
107                             (i == 0?"":", "),special->_ChunkSizes[i]);
108                 }
109                 bbprintf0(stmt,"static size_t %s_chunksizes[%d] = {",
110                             cname(var),special->nchunks);
111                 codedump(stmt);
112                 codedump(tmp);
113                 codeline("} ;");
114             }
115             if(special->flags & _FILTER_FLAG) {
116                 int i;
117                 unsigned int* params = special->_FilterParams;
118                 if(special->nparams == 0 || params == NULL) continue;
119                 bbClear(tmp);
120                 for(i=0;i<special->nparams;i++) {
121                     bbprintf(tmp,"%s%luU",
122                             (i == 0?"":", "),params[i]);
123                 }
124                 bbprintf0(stmt,"static unsigned int %s_filterparams[%d] = {",
125                             cname(var),special->nparams);
126                 codedump(stmt);
127                 codedump(tmp);
128                 codeline("} ;");
129             }
130 	    bbFree(tmp);
131         }
132 	codeline("");
133     }
134 #endif /*USE_NETCDF4*/
135 
136     /* Now construct the main procedures*/
137     codeline("void");
138     codeline("check_err(const int stat, const int line, const char *file) {");
139     codelined(1,"if (stat != NC_NOERR) {");
140     codelined(2,"(void)fprintf(stderr,\"line %d of %s: %s\\n\", line, file, nc_strerror(stat));");
141     codelined(2,"fflush(stderr);");
142     codelined(2,"exit(1);");
143     codelined(1,"}");
144     codeline("}");
145     codeline("");
146     codeline("int");
147     bbprintf0(stmt,"%s() {/* create %s */\n", mainname, filename);
148     codedump(stmt);
149     /* create necessary declarations */
150     codeline("");
151     codelined(1,"int  stat;  /* return status */");
152     codelined(1,"int  ncid;  /* netCDF id */");
153     codeflush();
154 
155 #ifdef USE_NETCDF4
156     /* Define variables to hold group ids*/
157     if(!usingclassic) {
158         codeline("");
159         codelined(1,"/* group ids */");
160     }
161     if(!usingclassic && ngrps > 0) {
162         for(igrp = 0; igrp < ngrps; igrp++) {
163 	    Symbol* gsym = (Symbol*)listget(grpdefs,igrp);
164 	    bbprintf0(stmt,"%sint %s;\n",indented(1),groupncid(gsym));
165 	    codedump(stmt);
166 	}
167     }
168 
169     /* define variables to hold type ids*/
170     if(!usingclassic && ntyps > 0) {
171 	codeline("");
172 	codelined(1,"/* type ids */");
173 	for(ityp = 0; ityp < ntyps; ityp++) {
174 	    Symbol* tsym = (Symbol*)listget(typdefs,ityp);
175 	    bbprintf0(stmt,"%sint %s;\n",indented(1), typencid(tsym));
176 	    codedump(stmt);
177 	}
178     }
179     codeflush();
180 #endif
181 
182     if (ndims > 0) {
183 	codeline("");
184 	codelined(1,"/* dimension ids */");
185 	for(idim = 0; idim < ndims; idim++) {
186 	    Symbol* dsym = (Symbol*)listget(dimdefs,idim);
187 	    bbprintf0(stmt,"%sint %s;\n", indented(1), dimncid(dsym));
188 	    codedump(stmt);
189 	}
190 
191 	codeline("");
192 	codelined(1,"/* dimension lengths */");
193 	for(idim = 0; idim < ndims; idim++) {
194 	    Symbol* dsym = (Symbol*)listget(dimdefs,idim);
195 	    if(dsym->dim.isunlimited) {
196 		bbprintf0(stmt,"%ssize_t %s_len = NC_UNLIMITED;\n",
197 			indented(1),cname(dsym));
198 	    } else {
199 		bbprintf0(stmt,"%ssize_t %s_len = %lu;\n",
200 			indented(1),
201 			cname(dsym),
202 			(unsigned long) dsym->dim.declsize);
203 	    }
204 	    codedump(stmt);
205 	}
206     }
207     codeflush();
208 
209     maxdims = 0;	/* most dimensions of any variable */
210     for(ivar = 0; ivar < nvars; ivar++) {
211       Symbol* vsym = (Symbol*)listget(vardefs,ivar);
212       if(vsym->typ.dimset.ndims > maxdims)
213 	maxdims = vsym->typ.dimset.ndims;
214     }
215 
216     if (nvars > 0) {
217 	codeline("");
218 	codelined(1,"/* variable ids */");
219 	for(ivar = 0; ivar < nvars; ivar++) {
220             Symbol* vsym = (Symbol*)listget(vardefs,ivar);
221 	    bbprintf0(stmt,"    int %s;\n", varncid(vsym));
222 	    codedump(stmt);
223 	}
224 
225 	codeline("");
226 	codelined(1,"/* rank (number of dimensions) for each variable */");
227 	for(ivar = 0; ivar < nvars; ivar++) {
228             Symbol* vsym = (Symbol*)listget(vardefs,ivar);
229 	    bbprintf0(stmt,"#   define RANK_%s %d\n", cname(vsym),
230 		    vsym->typ.dimset.ndims);
231 	    codedump(stmt);
232 	}
233 	if (maxdims > 0) {	/* we have dimensioned variables */
234 	    codeline("");
235 	    codelined(1,"/* variable shapes */");
236 	    for(ivar = 0; ivar < nvars; ivar++) {
237                 Symbol* vsym = (Symbol*)listget(vardefs,ivar);
238 		if (vsym->typ.dimset.ndims > 0) {
239 		    bbprintf0(stmt,"    int %s_dims[RANK_%s];\n",
240 			    cname(vsym), cname(vsym));
241 		    codedump(stmt);
242 		}
243 	    }
244 	}
245     }
246     codeflush();
247 
248     /* Set log level */
249     if(ncloglevel >= 0) {
250         codeline("");
251         bbprintf0(stmt,"    nc_set_log_level(%d); /* set log level */",ncloglevel);
252         codedump(stmt);
253         codeline("");
254     }
255 
256     /* create netCDF file, uses NC_CLOBBER mode */
257     codeline("");
258     codelined(1,"/* enter define mode */");
259 
260     if (!cmode_modifier) {
261 	cmode_string = "NC_CLOBBER";
262     } else if (cmode_modifier & NC_64BIT_OFFSET) {
263 	cmode_string = "NC_CLOBBER|NC_64BIT_OFFSET";
264 #ifdef USE_NETCDF4
265     } else if (cmode_modifier & NC_CLASSIC_MODEL) {
266 	cmode_string = "NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL";
267     } else if (cmode_modifier & NC_NETCDF4) {
268 	cmode_string = "NC_CLOBBER|NC_NETCDF4";
269 #endif
270     } else {
271         derror("unknown cmode modifier");
272 	cmode_string = "NC_CLOBBER";
273     }
274     bbprintf0(stmt,"    stat = nc_create(\"%s\", %s, &ncid);\n",
275 		 filename,cmode_string);
276     codedump(stmt);
277     codelined(1,"check_err(stat,__LINE__,__FILE__);");
278     codeflush();
279 
280 #ifdef USE_NETCDF4
281     genc_defineglobalspecials();
282 #endif /*USE_NETCDF4*/
283 
284 #ifdef USE_NETCDF4
285     /* Define the group structure */
286     /* ncid created above is also root group*/
287     if(!usingclassic) {
288         bbprintf0(stmt,"    %s = ncid;\n",groupncid(rootgroup));
289         codedump(stmt);
290         /* walking grpdefs list will do a preorder walk of all defined groups*/
291         for(igrp=0;igrp<listlength(grpdefs);igrp++) {
292 	    Symbol* gsym = (Symbol*)listget(grpdefs,igrp);
293 	    if(gsym == rootgroup) continue; /* ignore root*/
294 	    if(gsym->container == NULL)
295 		PANIC("null container");
296 	    bbprintf0(stmt,
297 		"    stat = nc_def_grp(%s, \"%s\", &%s);\n",
298 		groupncid(gsym->container),
299 		gsym->name, groupncid(gsym));
300 	    codedump(stmt);
301 	    codelined(1,"check_err(stat,__LINE__,__FILE__);");
302 	}
303         codeflush();
304     }
305 #endif
306 
307 #ifdef USE_NETCDF4
308     /* Construct code to define types*/
309     if(ntyps > 0) {
310         codeline("");
311 	for(ityp = 0; ityp < ntyps; ityp++) {
312 	    Symbol* tsym = (Symbol*)listget(typdefs,ityp);
313 	    if(tsym->subclass == NC_PRIM
314 		|| tsym->subclass == NC_ARRAY) continue; /* no need to do these*/
315 	    genc_deftype(tsym);
316 	    codeline("");
317 	}
318     }
319     codeflush();
320 #endif
321 
322     /* define dimensions from info in dims array */
323     if (ndims > 0) {
324 	codeline("");
325 	codelined(1,"/* define dimensions */");
326         for(idim = 0; idim < ndims; idim++) {
327             Symbol* dsym = (Symbol*)listget(dimdefs,idim);
328 	    {
329 		bbprintf0(stmt,
330 		          "    stat = nc_def_dim(%s, \"%s\", %s_len, &%s);\n",
331 		          groupncid(dsym->container),
332                           escapifyname(dsym->name),
333                           cname(dsym),
334                           dimncid(dsym));
335 	    }
336 	    codedump(stmt);
337 	    codelined(1,"check_err(stat,__LINE__,__FILE__);");
338        }
339     }
340     codeflush();
341 
342     /* define variables from info in vars array */
343     if (nvars > 0) {
344 	codeline("");
345 	codelined(1,"/* define variables */");
346 	for(ivar = 0; ivar < nvars; ivar++) {
347             Symbol* vsym = (Symbol*)listget(vardefs,ivar);
348             Symbol* basetype = vsym->typ.basetype;
349 	    Dimset* dimset = &vsym->typ.dimset;
350 	    codeline("");
351 	    if(dimset->ndims > 0) {
352 	        for(idim = 0; idim < dimset->ndims; idim++) {
353 		    Symbol* dsym = dimset->dimsyms[idim];
354 		    bbprintf0(stmt,
355 			    "    %s_dims[%d] = %s;\n",
356 			    cname(vsym),
357 			    idim,
358 			    dimncid(dsym));
359 		    codedump(stmt);
360 		}
361 	    }
362 	    bbprintf0(stmt,
363 			"    stat = nc_def_var(%s, \"%s\", %s, RANK_%s, %s, &%s);\n",
364 		        groupncid(vsym->container),
365 			escapifyname(vsym->name),
366 			typencid(basetype),
367 			cname(vsym),
368 			(dimset->ndims == 0?"0":poolcat(cname(vsym),"_dims")),
369 			varncid(vsym));
370 	    codedump(stmt);
371 	    codelined(1,"check_err(stat,__LINE__,__FILE__);");
372 #ifdef USE_NETCDF4
373 	    genc_definespecialattributes(vsym);
374 #endif /*USE_NETCDF4*/
375 	}
376     }
377     codeflush();
378 
379     /* Define the global attributes*/
380     if(ngatts > 0) {
381 	codeline("");
382 	codelined(1,"/* assign global attributes */");
383 	for(iatt = 0; iatt < ngatts; iatt++) {
384 	    Symbol* gasym = (Symbol*)listget(gattdefs,iatt);
385 	    genc_defineattr(gasym);
386 	}
387 	codeline("");
388     }
389     codeflush();
390 
391     /* Define the variable specific attributes*/
392     if(natts > 0) {
393 	codeline("");
394 	codelined(1,"/* assign per-variable attributes */");
395 	for(iatt = 0; iatt < natts; iatt++) {
396 	    Symbol* asym = (Symbol*)listget(attdefs,iatt);
397 	    genc_defineattr(asym);
398 	}
399 	codeline("");
400     }
401     codeflush();
402 
403     if (nofill_flag) {
404         codelined(1,"/* don't initialize variables with fill values */");
405 	bbindent(stmt,1);
406 	bbprintf0(stmt,"stat = nc_set_fill(%s, NC_NOFILL, 0);",groupncid(rootgroup));
407 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
408     }
409 
410     codeline("");
411     codelined(1,"/* leave define mode */");
412     bbprintf0(stmt,"    stat = nc_enddef (%s);\n",groupncid(rootgroup));
413     codedump(stmt);
414     codelined(1,"check_err(stat,__LINE__,__FILE__);");
415     codeflush();
416 
417     if(!header_only) {
418         /* Load values into those variables with defined data */
419         if(nvars > 0) {
420             codeline("");
421             codelined(1,"/* assign variable data */");
422             for(ivar = 0; ivar < nvars; ivar++) {
423                 Symbol* vsym = (Symbol*)listget(vardefs,ivar);
424                 if(vsym->data != NULL) genc_definevardata(vsym);
425             }
426             codeline("");
427         }
428         codeflush();
429     }
430 }
431 
432 #ifdef USE_NETCDF4
433 
434 static void
genc_defineglobalspecials(void)435 genc_defineglobalspecials(void)
436 {
437     const char* format = NULL;
438     if(usingclassic) return;
439     if(!/*Main.*/format_attribute) return;
440     /* Watch out, this is a global Attribute */
441     format = kind_string(globalspecials._Format);
442     bbprintf0(stmt,"%sstat = nc_put_att_text(ncid, NC_GLOBAL, \"_Format\", 1, \"%s\");\n",
443 	          indented(1),
444 		  format);
445     codedump(stmt);
446     codelined(1,"check_err(stat,__LINE__,__FILE__);");
447 }
448 
449 static void
genc_definespecialattributes(Symbol * vsym)450 genc_definespecialattributes(Symbol* vsym)
451 {
452     Specialdata* special = vsym->var.special;
453     if(usingclassic) return;
454     if(special->flags & _STORAGE_FLAG) {
455         int storage = special->_Storage;
456         size_t* chunks = special->_ChunkSizes;
457         bbprintf0(stmt,
458                 "    stat = nc_def_var_chunking(%s, %s, %s, ",
459                 groupncid(vsym->container),
460                 varncid(vsym),
461                 (storage == NC_CONTIGUOUS?"NC_CONTIGUOUS":"NC_CHUNKED"));
462         codedump(stmt);
463         if(special->nchunks == 0 || chunks == NULL)
464             codepartial("NULL");
465         else {
466             bbprintf0(stmt,"%s_chunksizes",cname(vsym));
467             codedump(stmt);
468         }
469         codeline(");");
470         codelined(1,"check_err(stat,__LINE__,__FILE__);");
471     }
472     if(special->flags & _FLETCHER32_FLAG) {
473         bbprintf0(stmt,
474                 "    stat = nc_def_var_fletcher32(%s, %s, %d);\n",
475                 groupncid(vsym->container),
476                 varncid(vsym),
477                 special->_Fletcher32);
478         codedump(stmt);
479         codelined(1,"check_err(stat,__LINE__,__FILE__);");
480     }
481     if(special->flags & (_DEFLATE_FLAG | _SHUFFLE_FLAG)) {
482         bbprintf0(stmt,
483                 "    stat = nc_def_var_deflate(%s, %s, %s, %d, %d);\n",
484                 groupncid(vsym->container),
485                 varncid(vsym),
486                 (special->_Shuffle == 1?"NC_SHUFFLE":"NC_NOSHUFFLE"),
487                 (special->_DeflateLevel >= 0?1:0),
488                 (special->_DeflateLevel >= 0?special->_DeflateLevel:0));
489         codedump(stmt);
490         codelined(1,"check_err(stat,__LINE__,__FILE__);");
491     }
492     if(special->flags & _ENDIAN_FLAG) {
493         bbprintf0(stmt,
494                 "    stat = nc_def_var_endian(%s, %s, %s);\n",
495                 groupncid(vsym->container),
496                 varncid(vsym),
497                 (special->_Endianness == NC_ENDIAN_LITTLE?"NC_ENDIAN_LITTLE"
498                                                     :"NC_ENDIAN_BIG")
499                 );
500         codedump(stmt);
501         codelined(1,"check_err(stat,__LINE__,__FILE__);");
502     }
503     if(special->flags & _NOFILL_FLAG) {
504         bbprintf0(stmt,
505                 "    stat = nc_def_var_fill(%s, %s, %s, NULL);\n",
506                 groupncid(vsym->container),
507                 varncid(vsym),
508                 (special->_Fill?"NC_FILL":"NC_NOFILL")
509                 );
510         codedump(stmt);
511         codelined(1,"check_err(stat,__LINE__,__FILE__);");
512     }
513     if(special->flags & _FILTER_FLAG) {
514 	/* Special check for alternate way to specify _Deflate */
515 	if(special->_FilterID == ZIP_ID) {
516 	    unsigned int level;
517 	    if(special->nparams == 0 || special->_FilterParams == NULL)
518 		level = 9; /* default */
519 	    else
520 		level = special->_FilterParams[0];
521 	    if(level > 9)
522 		derror("Illegal deflate level");
523 	    else {
524 	        bbprintf0(stmt,
525 	                "    stat = nc_def_var_deflate(%s, %s, %s, %d, %d);\n",
526 	                groupncid(vsym->container),
527 	                varncid(vsym),
528 	                (special->_Shuffle == 1?"NC_SHUFFLE":"NC_NOSHUFFLE"),
529 	                1,
530 			level);
531 	        codedump(stmt);
532 	    }
533 	} else {
534 	        bbprintf0(stmt,
535 	                "    stat = nc_def_var_filter(%s, %s, %u, %lu, ",
536 	                groupncid(vsym->container),
537 	                varncid(vsym),
538 			special->_FilterID,
539 			special->nparams
540 			);
541 	        codedump(stmt);
542 	        if(special->nparams == 0 || special->_FilterParams == NULL)
543 	            codepartial("NULL");
544         	else {
545 	            bbprintf0(stmt,"%s_filterparams",cname(vsym));
546 	            codedump(stmt);
547 		}
548 	        codeline(");");
549 	}
550         codelined(1,"check_err(stat,__LINE__,__FILE__);");
551     }
552 
553 
554 }
555 #endif /*USE_NETCDF4*/
556 
557 void
genc_close(void)558 genc_close(void)
559 {
560     bbprintf0(stmt,"%sstat = nc_close(%s);\n",indented(1),groupncid(rootgroup));
561     codedump(stmt);
562     codelined(1,"check_err(stat,__LINE__,__FILE__);");
563 #ifndef vms
564     codelined(1,"return 0;");
565 #else
566     codelined(1,"return 1;");
567 #endif
568     codeline("}");
569     codeflush();
570 }
571 
572 /*
573  * Output a C statement
574  */
575 
576 
577 
578 /* return C name for netCDF type, given type code */
579 const char *
nctype(nc_type type)580 nctype(nc_type type)
581 {
582     switch (type) {
583       case NC_CHAR: return "NC_CHAR";
584       case NC_BYTE: return "NC_BYTE";
585       case NC_SHORT: return "NC_SHORT";
586       case NC_INT: return "NC_INT";
587       case NC_FLOAT: return "NC_FLOAT";
588       case NC_DOUBLE: return "NC_DOUBLE";
589       case NC_UBYTE: return "NC_UBYTE";
590       case NC_USHORT: return "NC_USHORT";
591       case NC_UINT: return "NC_UINT";
592       case NC_INT64: return "NC_INT64";
593       case NC_UINT64: return "NC_UINT64";
594       case NC_STRING: return "NC_STRING";
595       default: PANIC("nctype: bad type code");
596     }
597     return NULL;
598 }
599 
600 
601 
602 /*
603  * Return C type name for netCDF type, given type code.
604  */
605 const char*
ncctype(nc_type type)606 ncctype(nc_type type)
607 {
608     switch (type) {
609       case NC_CHAR:
610 	return "char";
611       case NC_BYTE:
612 	return "signed char";
613       case NC_SHORT:
614 	return "short";
615       case NC_INT:
616 	return "int";
617       case NC_FLOAT:
618 	return "float";
619       case NC_DOUBLE:
620 	return "double";
621       case NC_UBYTE:
622 	return "unsigned char";
623       case NC_USHORT:
624 	return "unsigned short";
625       case NC_UINT:
626 	return "unsigned int";
627       case NC_INT64:
628 	return "signed long long";
629       case NC_UINT64:
630 	return "unsigned long long";
631       case NC_STRING:
632 	return "char*";
633       default:
634 	PANIC1("ncctype: bad type code:%d",type);
635     }
636     return 0;
637 }
638 
639 /*
640  * Return C type name for netCDF type suffix, given type code.
641  */
642 const char*
ncstype(nc_type nctype)643 ncstype(nc_type nctype)
644 {
645     switch (nctype) {
646       case NC_CHAR:
647 	return "text";
648       case NC_BYTE:
649 	return "schar";
650       case NC_SHORT:
651 	return "short";
652       case NC_INT:
653 	return "int";
654       case NC_FLOAT:
655 	return "float";
656       case NC_DOUBLE:
657 	return "double";
658       case NC_UBYTE:
659 	return "ubyte";
660       case NC_USHORT:
661 	return "ushort";
662       case NC_UINT:
663 	return "uint";
664       case NC_INT64:
665 	return "longlong";
666       case NC_UINT64:
667 	return "ulonglong";
668       case NC_STRING:
669 	return "string";
670       default:
671 	derror("ncstype: bad type code: %d",nctype);
672 	return 0;
673     }
674 }
675 
676 /* Return the group name for the specified group*/
677 static const char*
groupncid(Symbol * sym)678 groupncid(Symbol* sym)
679 {
680 #ifdef USE_NETCDF4
681     if(usingclassic) {
682         return "ncid";
683     } else {
684         char* grptmp;
685 	const char* tmp1;
686         if(sym == NULL) return groupncid(rootgroup);
687         ASSERT(sym->objectclass == NC_GRP);
688         tmp1 = cname(sym);
689         grptmp = poolalloc(strlen(tmp1)+strlen("_grp")+1);
690         strcpy(grptmp,tmp1);
691         strcat(grptmp,"_grp");
692         return grptmp;
693     }
694 #else
695     return "ncid";
696 #endif
697 }
698 
699 /* Compute the C name for a given type's id*/
700 /* Watch out: the result is a static*/
701 static const char*
typencid(Symbol * tsym)702 typencid(Symbol* tsym)
703 {
704     char* typtmp;
705     const char* tmp1;
706     if(tsym->subclass == NC_PRIM)
707 	return nctype(tsym->typ.typecode);
708     tmp1 = ctypename(tsym);
709     typtmp = poolalloc(strlen(tmp1)+strlen("_typ")+1);
710     strcpy(typtmp,tmp1);
711     strcat(typtmp,"_typ");
712     return typtmp;
713 }
714 
715 /* Compute the C name for a given var's id*/
716 /* Watch out: the result is a static*/
717 static const char*
varncid(Symbol * vsym)718 varncid(Symbol* vsym)
719 {
720     const char* tmp1;
721     char* vartmp;
722     tmp1 = cname(vsym);
723     vartmp = poolalloc(strlen(tmp1)+strlen("_id")+1);
724     strcpy(vartmp,tmp1);
725     strcat(vartmp,"_id");
726     return vartmp;
727 }
728 
729 /* Compute the C name for a given dim's id*/
730 /* Watch out: the result is pooled*/
731 static const char*
dimncid(Symbol * dsym)732 dimncid(Symbol* dsym)
733 {
734     const char* tmp1;
735     char* dimtmp;
736     tmp1 = cname(dsym);
737     dimtmp = poolalloc(strlen(tmp1)+strlen("_dim")+1);
738     strcpy(dimtmp,tmp1);
739     strcat(dimtmp,"_dim");
740     return dimtmp;
741 }
742 
743 /* Compute the C name for a given type*/
744 const char*
ctypename(Symbol * tsym)745 ctypename(Symbol* tsym)
746 {
747     const char* name;
748     ASSERT(tsym->objectclass == NC_TYPE);
749     if(tsym->subclass == NC_PRIM)
750 	name = ncctype(tsym->typ.typecode);
751     else
752         name = cname(tsym);
753     return name;
754 }
755 
756 #ifdef USE_NETCDF4
757 static void
definectype(Symbol * tsym)758 definectype(Symbol* tsym)
759 {
760     int i,j;
761 
762     ASSERT(tsym->objectclass == NC_TYPE);
763     switch (tsym->subclass) {
764     case NC_PRIM: break; /* these are already taken care of*/
765     case NC_OPAQUE:
766 	bbprintf0(stmt,"typedef unsigned char %s[%lu];\n",
767 		cname(tsym), tsym->typ.size);
768 	codedump(stmt);
769 	break;
770     case NC_ENUM:
771 	for(i=0;i<listlength(tsym->subnodes);i++) {
772 	    Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
773 	    Bytebuffer* econststring = bbNew();
774 	    ASSERT(econst->subclass == NC_ECONST);
775 	    c_generator->constant(c_generator,tsym,econst->typ.econst,econststring);
776 	    bbNull(econststring);
777             /* Enum constants must be converted to a fully qualified name */
778 	    bbprintf0(stmt,"#define %s ((%s)%s)\n",
779 		    cname(econst),
780 		    ctypename(econst->typ.basetype),
781 		    bbContents(econststring));
782 	    bbFree(econststring);
783 	    codedump(stmt);
784 	}
785 	bbprintf0(stmt,"typedef %s %s;\n",
786 		ctypename(tsym->typ.basetype), cname(tsym));
787 	codedump(stmt);
788 	break;
789     case NC_VLEN:
790 	bbprintf0(stmt,"typedef nc_vlen_t %s;\n",
791 		ctypename(tsym));
792 	codedump(stmt);
793 	break;
794     case NC_COMPOUND:
795 	bbprintf0(stmt,"typedef struct %s {\n",cname(tsym));
796 	codedump(stmt);
797 	for(i=0;i<listlength(tsym->subnodes);i++) {
798 	    Symbol* efield = (Symbol*)listget(tsym->subnodes,i);
799 	    ASSERT(efield->subclass == NC_FIELD);
800 	    bbprintf0(stmt,"%s%s %s",
801 			indented(1),ctypename(efield->typ.basetype),cname(efield));
802 	    codedump(stmt);
803 	    /* compute any dimension specification*/
804 	    if(efield->typ.dimset.ndims > 0) {
805 		Bytebuffer* dimbuf = bbNew();
806 	        for(j=0;j<efield->typ.dimset.ndims;j++) {
807 		    Symbol* dim;
808 		    char tmp[64];
809 		    bbCat(dimbuf,"[");
810 		    dim = efield->typ.dimset.dimsyms[j];
811 		    ASSERT(dim->dim.isconstant);
812 		    snprintf(tmp,sizeof(tmp),"%u",
813 			(unsigned int)dim->dim.declsize);
814 		    bbCat(dimbuf,tmp);
815 		    bbCat(dimbuf,"]");
816 		}
817 		codedump(dimbuf);
818 		bbFree(dimbuf);
819 	    }
820 	    codeline(";");
821 	}
822 	bbprintf0(stmt,"} %s;\n", ctypename(tsym));
823 	codedump(stmt);
824 	break;
825 
826     case NC_ARRAY:
827 	/* ignore: this will be handled by def_var*/
828 	break;
829 
830     default: panic("definectype: unexpected type subclass: %d",tsym->subclass);
831     }
832 }
833 
834 /*
835 Generate the C code for defining a given type
836 */
837 static void
genc_deftype(Symbol * tsym)838 genc_deftype(Symbol* tsym)
839 {
840     int i;
841 
842     ASSERT(tsym->objectclass == NC_TYPE);
843     switch (tsym->subclass) {
844     case NC_PRIM: break; /* these are already taken care of*/
845     case NC_OPAQUE:
846 	bbprintf0(stmt,"%sstat = nc_def_opaque(%s, %lu, \"%s\", &%s);\n",
847 		indented(1),
848 		groupncid(tsym->container),
849 		tsym->typ.size,
850 		tsym->name,
851 		typencid(tsym));
852 	codedump(stmt);
853 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
854 	break;
855     case NC_ENUM:
856 	codelined(1,"{");
857 	bbprintf0(stmt,"%s%s econst;\n",
858 		indented(1),
859 		ncctype(tsym->typ.basetype->typ.typecode));
860 	codedump(stmt);
861 	bbprintf0(stmt,"%sstat = nc_def_enum(%s, %s, \"%s\", &%s);\n",
862 		indented(1),
863 		groupncid(tsym->container),
864 		nctype(tsym->typ.basetype->typ.typecode),
865 		tsym->name,
866 		typencid(tsym));
867 	codedump(stmt);
868 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
869 	for(i=0;i<listlength(tsym->subnodes);i++) {
870 	    Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
871 	    Bytebuffer* econststring = bbNew();
872 	    ASSERT(econst->subclass == NC_ECONST);
873 	    c_generator->constant(c_generator,tsym,econst->typ.econst,econststring);
874 	    bbNull(econststring);
875 	    bbprintf0(stmt,"%seconst = %s;\n",
876 		indented(1),bbContents(econststring));
877 	    bbFree(econststring);
878 	    codedump(stmt);
879 	    bbprintf0(stmt,"%sstat = nc_insert_enum(%s, %s, \"%s\", &econst);\n",
880 		    indented(1),
881 		    groupncid(tsym->container),
882 		    typencid(tsym),
883 		    escapifyname(econst->name));
884 	    codedump(stmt);
885 	}
886 	codelined(1,"}");
887 	break;
888     case NC_VLEN:
889 	bbprintf0(stmt,"%sstat = nc_def_vlen(%s, \"%s\", %s, &%s);",
890 		indented(1),
891 		groupncid(tsym->container),
892 		escapifyname(tsym->name),
893 		typencid(tsym->typ.basetype),
894 		typencid(tsym));
895 	codedump(stmt);
896 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
897 	break;
898     case NC_COMPOUND:
899 	bbprintf0(stmt,"%sstat = nc_def_compound(%s, sizeof(%s), \"%s\", &%s);",
900 		indented(1),
901 		groupncid(tsym->container),
902 		ctypename(tsym),
903 		escapifyname(tsym->name),
904 		typencid(tsym));
905 	codedump(stmt);
906 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
907 	/* Generate the field dimension constants*/
908 	codelined(1,"{");
909 	for(i=0;i<listlength(tsym->subnodes);i++) {
910 	    int j;
911 	    Symbol* efield = (Symbol*)listget(tsym->subnodes,i);
912 	    ASSERT(efield->subclass == NC_FIELD);
913 	    if(efield->typ.dimset.ndims == 0) continue;
914 	    bbprintf0(stmt,"%sstatic int %s_dims[%d] = {\n",
915 			indented(1),
916 			cname(efield),efield->typ.dimset.ndims);
917 	    for(j=0;j<efield->typ.dimset.ndims;j++) {
918 		char tmp[256];
919 	        Symbol* e = efield->typ.dimset.dimsyms[j];
920 		ASSERT(e->dim.isconstant);
921 		snprintf(tmp,sizeof(tmp),"%u",(unsigned int)e->dim.declsize);
922 		bbCat(stmt,(j==0?"":", "));
923 		bbCat(stmt,tmp);
924 	    }
925 	    bbCat(stmt,"};");
926 	    codedump(stmt);
927 	}
928 	for(i=0;i<listlength(tsym->subnodes);i++) {
929 	    Symbol* efield = (Symbol*)listget(tsym->subnodes,i);
930 	    char tmp[1024];
931 	    ASSERT(efield->subclass == NC_FIELD);
932 #ifdef TESTALIGNMENT
933 	    snprintf(tmp,sizeof(tmp),"%lu",efield->typ.offset);
934 #else
935 	    snprintf(tmp,sizeof(tmp),"NC_COMPOUND_OFFSET(%s,%s)",
936 			ctypename(tsym), cname(efield));
937 #endif
938 	    if(efield->typ.dimset.ndims > 0){
939 	        bbprintf0(stmt,"%sstat = nc_insert_array_compound(%s, %s, \"%s\", %s, %s, %d, %s_dims);",
940 		    indented(1),
941 		    groupncid(tsym->container),
942 		    typencid(tsym),
943 		    escapifyname(efield->name),
944 		    tmp,
945 		    typencid(efield->typ.basetype),
946 		    efield->typ.dimset.ndims,
947 		    cname(efield));
948 	    } else {
949 	        bbprintf0(stmt,"%sstat = nc_insert_compound(%s, %s, \"%s\", %s, %s);",
950 		    indented(1),
951 		    groupncid(tsym->container),
952 		    typencid(tsym),
953 		    escapifyname(efield->name),
954 		    tmp,
955 		    typencid(efield->typ.basetype));
956 	    }
957 	    codedump(stmt);
958 	    codelined(1,"check_err(stat,__LINE__,__FILE__);");
959 	}
960 	codelined(1,"}");
961 	break;
962 
963     case NC_ARRAY:
964 	/* ignore: this will be handled by def_var*/
965 	break;
966 
967     default: panic("genc_deftype: unexpected type subclass: %d",tsym->subclass);
968     }
969 }
970 
971 #endif /*USE_NETCDF4*/
972 
973 static void
genc_defineattr(Symbol * asym)974 genc_defineattr(Symbol* asym)
975 {
976     /* we need to capture vlen strings for dumping */
977     Bytebuffer* save = bbNew(); /* capture so we can dump
978                                    vlens first */
979     List* oldstate = NULL;
980     generator_getstate(c_generator,(void*)&oldstate);
981     listfree(oldstate);
982     generator_reset(c_generator,(void*)listnew());
983     generate_attrdata(asym,c_generator,(Writer)genc_write,save);
984     bbFree(save);
985 }
986 
987 static void
genc_definevardata(Symbol * vsym)988 genc_definevardata(Symbol* vsym)
989 {
990     Bytebuffer* save; /* capture so we can dump vlens first */
991     List* oldstate = NULL;
992     if(vsym->data == NULL) return;
993     save = bbNew();
994     generator_getstate(c_generator,(void*)&oldstate);
995     listfree(oldstate);
996     generator_reset(c_generator,(void*)listnew());
997     generate_vardata(vsym,c_generator,(Writer)genc_write,save);
998     bbFree(save);
999 }
1000 
1001 static void
genc_write(Generator * generator,Symbol * sym,Bytebuffer * code,int rank,size_t * start,size_t * count)1002 genc_write(Generator* generator, Symbol* sym, Bytebuffer* code,
1003            int rank, size_t* start, size_t* count)
1004 {
1005     if(sym->objectclass == NC_ATT)
1006 	genc_writeattr(generator,sym,code,rank,start,count);
1007     else if(sym->objectclass == NC_VAR)
1008 	genc_writevar(generator,sym,code,rank,start,count);
1009     else
1010 	PANIC("illegal symbol for genc_write");
1011 }
1012 
1013 static void
genc_writevar(Generator * generator,Symbol * vsym,Bytebuffer * code,int rank,size_t * start,size_t * count)1014 genc_writevar(Generator* generator, Symbol* vsym, Bytebuffer* code,
1015            int rank, size_t* start, size_t* count)
1016 {
1017     Symbol* basetype = vsym->typ.basetype;
1018     nc_type typecode = basetype->typ.typecode;
1019     List* vlendecls;
1020 
1021     /* define a block to avoid name clashes*/
1022     codeline("");
1023     codelined(1,"{");
1024 
1025     /* Dump any vlen decls first */
1026     generator_getstate(generator,(void**)&vlendecls);
1027     if(vlendecls != NULL && listlength(vlendecls) > 0) {
1028 	int i;
1029 	for(i=0;i<listlength(vlendecls);i++) {
1030 	   Bytebuffer* decl = (Bytebuffer*)listget(vlendecls,i);
1031 	   codelined(1,bbContents(decl));
1032 	   bbFree(decl);
1033 	}
1034 	listfree(vlendecls);
1035 	generator_reset(generator,NULL);
1036     }
1037 
1038     if(rank == 0) {
1039 	codelined(1,"size_t count = 0;");
1040 	    /* We make the data be an array so we do not need to
1041                ampersand it later => we need an outer pair of braces
1042             */
1043 	commify(code); /* insert commas at proper places */
1044         bbprintf0(stmt,"%sstatic %s %s_data[1] = {%s};\n",
1045 			    indented(1),
1046 			    ctypename(basetype),
1047 			    cname(vsym),
1048 			    bbContents(code));
1049 	codedump(stmt);
1050         bbprintf0(stmt,"%sstat = nc_put_var1(%s, %s, &count, %s_data);\n",
1051 		indented(1),
1052 		groupncid(vsym->container),
1053 		varncid(vsym),
1054 		cname(vsym));
1055         codedump(stmt);
1056         codelined(1,"check_err(stat,__LINE__,__FILE__);");
1057 	codeflush();
1058     } else { /* rank > 0 */
1059 	int i;
1060         size_t length = 0;
1061         if(typecode == NC_CHAR) {
1062 	    length = bbLength(code);
1063 	    /* generate data constant */
1064 	    bbprintf(stmt,"%schar* %s_data = ",
1065 			indented(1),
1066 			cname(vsym),
1067 			(unsigned long)length);
1068 	    codedump(stmt);
1069 	    cquotestring(code,'"');
1070 	    codedump(code);
1071 	    codeline(" ;");
1072 	} else {
1073 	    /* Compute total size */
1074 	    length = 1;
1075     	    for(i=0;i<rank;i++) length *= count[i];
1076 	    /* generate data constant */
1077 	    commify(code); /* insert commas at proper places */
1078 	    bbprintf(stmt,"%s%s %s_data[%lu] = ",
1079 			indented(1),
1080 			ctypename(basetype),
1081 			cname(vsym),
1082 			(unsigned long)length);
1083 	    codedump(stmt);
1084     	    /* C requires an outer set of braces on datalist constants */
1085 	    codepartial("{");
1086 	    codedump(code);
1087 	    codeline("} ;");
1088 	}
1089 
1090 	/* generate constants for startset, countset*/
1091 	bbprintf0(stmt,"%ssize_t %s_startset[%u] = {",
1092 			indented(1),
1093 			cname(vsym),
1094 			rank);
1095 	for(i=0;i<rank;i++) {
1096 	    bbprintf(stmt,"%s%lu",(i>0?", ":""),start[i]);
1097 	}
1098 	codedump(stmt);
1099 	codeline("} ;");
1100 
1101 	bbprintf0(stmt,"%ssize_t %s_countset[%u] = {",
1102 			indented(1),
1103 			cname(vsym),
1104 			rank);
1105 	for(i=0;i<rank;i++) {
1106 	    bbprintf(stmt,"%s%lu",(i>0?", ":""),count[i]);
1107 	}
1108 	codedump(stmt);
1109 	codeline("};");
1110 
1111 	bbprintf0(stmt,"%sstat = nc_put_vara(%s, %s, %s_startset, %s_countset, %s_data);\n",
1112 			indented(1),
1113 			groupncid(vsym->container), varncid(vsym),
1114 			cname(vsym),
1115 			cname(vsym),
1116 			cname(vsym));
1117 	codedump(stmt);
1118 	codelined(1,"check_err(stat,__LINE__,__FILE__);");
1119 
1120     }
1121     /* end defined block*/
1122     codelined(1,"}\n");
1123     codeflush();
1124 }
1125 
1126 static void
genc_writeattr(Generator * generator,Symbol * asym,Bytebuffer * code,int rank,size_t * start,size_t * count)1127 genc_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code,
1128                int rank, size_t* start, size_t* count)
1129 {
1130     Symbol* basetype = asym->typ.basetype;
1131     int typecode = basetype->typ.typecode;
1132     size_t len = asym->data->length; /* default assumption */
1133 
1134     /* define a block to avoid name clashes*/
1135     codeline("");
1136     codelined(1,"{");
1137 
1138     /* Handle NC_CHAR specially */
1139     if(typecode == NC_CHAR) {
1140         len = bbLength(code); /* presumably before quoting */
1141 	/* Revise length if length == 0 */
1142 	if(len == 0) len++;
1143 	cquotestring(code,'"');
1144     } else {
1145         /* All other cases */
1146         /* Dump any vlen decls first */
1147         List* vlendecls;
1148         generator_getstate(generator,(void**)&vlendecls);
1149         if(vlendecls != NULL && listlength(vlendecls) > 0) {
1150             int i;
1151             for(i=0;i<listlength(vlendecls);i++) {
1152                 Bytebuffer* decl = (Bytebuffer*)listget(vlendecls,i);
1153                 codelined(1,bbContents(decl));
1154                 bbFree(decl);
1155             }
1156             listfree(vlendecls);
1157             generator_reset(generator,NULL);
1158         }
1159         commify(code);
1160         bbprintf0(stmt,"%sstatic const %s %s_att[%ld] = ",
1161                         indented(1),
1162                         ctypename(basetype),
1163                         cname(asym),
1164                         asym->data->length
1165                         );
1166         codedump(stmt);
1167         codepartial("{");
1168         codedump(code);
1169         codepartial("}");
1170         codeline(" ;");
1171         bbClear(code);
1172     }
1173 
1174     /* Use the specialized put_att_XX routines if possible*/
1175     switch (basetype->typ.typecode) {
1176     case NC_BYTE:
1177     case NC_SHORT:
1178     case NC_INT:
1179     case NC_FLOAT:
1180     case NC_DOUBLE:
1181         bbprintf0(stmt,"%sstat = nc_put_att_%s(%s, %s, \"%s\", %s, %lu, %s_att);\n",
1182 		indented(1),
1183 		ncstype(basetype->typ.typecode),
1184 		groupncid(asym->container),
1185 		(asym->att.var == NULL?"NC_GLOBAL"
1186 			              :varncid(asym->att.var)),
1187 		escapifyname(asym->name),
1188 		typencid(basetype),
1189 	 	len,
1190 		cname(asym));
1191 	codedump(stmt);
1192 	break;
1193 
1194     case NC_CHAR:
1195 	/* Include the string constant in-line */
1196         bbprintf0(stmt,"%sstat = nc_put_att_%s(%s, %s, \"%s\", %lu, %s);\n",
1197 		indented(1),
1198 		ncstype(basetype->typ.typecode),
1199 		groupncid(asym->container),
1200 		(asym->att.var == NULL?"NC_GLOBAL"
1201 			              :varncid(asym->att.var)),
1202 		escapifyname(asym->name),
1203 	 	len,
1204 		bbContents(code));
1205 	codedump(stmt);
1206 	break;
1207 
1208     /* !usingclassic only (except NC_STRING) */
1209     case NC_UBYTE:
1210     case NC_USHORT:
1211     case NC_UINT:
1212     case NC_INT64:
1213     case NC_UINT64:
1214 	if(usingclassic && k_flag <= 2) {
1215 	    verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
1216 	    return;
1217 	}
1218         bbprintf0(stmt,"%sstat = nc_put_att_%s(%s, %s, \"%s\", %s, %lu, %s_att);",
1219 		indented(1),
1220 		ncstype(basetype->typ.typecode),
1221 		groupncid(asym->container),
1222 		(asym->att.var == NULL?"NC_GLOBAL"
1223 			              :varncid(asym->att.var)),
1224 		escapifyname(asym->name),
1225 		typencid(basetype),
1226 	 	len,
1227 		cname(asym));
1228 	codedump(stmt);
1229 	break;
1230 
1231 #ifdef USE_NETCDF4
1232     case NC_STRING:
1233 	if(usingclassic) {
1234 	    verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
1235 	    return;
1236 	}
1237         bbprintf0(stmt,"%sstat = nc_put_att_%s(%s, %s, \"%s\", %lu, %s_att);",
1238 		indented(1),
1239 		ncstype(basetype->typ.typecode),
1240 		groupncid(asym->container),
1241 		(asym->att.var == NULL?"NC_GLOBAL"
1242 			              :varncid(asym->att.var)),
1243 		escapifyname(asym->name),
1244 	 	len,
1245 		cname(asym));
1246 	codedump(stmt);
1247 	break;
1248 #endif
1249 
1250     default: /* User defined type */
1251 #ifndef USE_NETCDF4
1252         verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
1253 #else /* !USE_NETCDF4 */
1254 	if(usingclassic && !isclassicprim(basetype->typ.typecode)) {
1255             verror("Non-classic type: %s",nctypename(basetype->typ.typecode));
1256 	}
1257         bbprintf0(stmt,"%sstat = nc_put_att(%s, %s, \"%s\", %s, %lu, %s_att);\n",
1258 		indented(1),
1259 		groupncid(asym->container),
1260 		(asym->att.var == NULL?"NC_GLOBAL"
1261 			              :varncid(asym->att.var)),
1262 		escapifyname(asym->name),
1263 		typencid(basetype),
1264 	        len,
1265 		cname(asym));
1266         codedump(stmt);
1267 #endif
1268 	break;
1269     }
1270 
1271     codelined(1,"check_err(stat,__LINE__,__FILE__);");
1272     codelined(1,"}");
1273 }
1274 
1275 
1276 /* Compute the C name for a given symbol;
1277 modified to use the fqn
1278 */
1279 const char*
cname(Symbol * sym)1280 cname(Symbol* sym)
1281 {
1282     char* name;
1283 
1284     assert (sym->fqn != NULL && sym->name != NULL);
1285     /* Convert the fqn as its C name. */
1286     if(sym->grp.is_root)
1287 	name = codify(sym->name);
1288     else
1289 	name = codify(sym->fqn);
1290     return name;
1291 }
1292 
1293 #endif /*ENABLE_C*/
1294