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


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed