1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/ncgen/genbin.c,v 1.4 2010/05/27 21:34:17 dmh Exp $
5 *********************************************************************/
6
7#include "includes.h"
8#include <ctype.h> /* for isprint() */
9
10#ifdef ENABLE_BINARY
11
12#undef TRACE
13
14/* Forward*/
15static void genbin_defineattr(Symbolasym);
16static void genbin_definevardata(Symbolvsym);
17static int  genbin_write(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
18static int genbin_writevar(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
19static int genbin_writeattr(Generator*,Symbol*,Bytebuffer*,int,size_t*,size_t*);
20#ifdef USE_NETCDF4
21static void genbin_deftype(Symboltsym);
22static void genbin_definespecialattributes(Symbolvar);
23#endif
24
25/*
26 * Generate C code for creating netCDF from in-memory structure.
27 */
28void
29gen_netcdf(const char *filename)
30{
31    int statncid;
32    int idimivariatt;
33    int ndimsnvarsnattsngatts;
34
35#ifdef USE_NETCDF4
36    int ntypsngrpsigrp;
37#endif
38
39    Bytebufferdatabuf = bbNew();
40
41    ndims = listlength(dimdefs);
42    nvars = listlength(vardefs);
43    natts = listlength(attdefs);
44    ngatts = listlength(gattdefs);
45#ifdef USE_NETCDF4
46    ntyps = listlength(typdefs);
47    ngrps = listlength(grpdefs);
48#endif /*USE_NETCDF4*/
49
50    /* Turn on logging */
51#ifdef LOGGING
52    nc_set_log_level(ncloglevel);
53#endif
54
55    /* create netCDF file, uses NC_CLOBBER mode */
56    cmode_modifier |= NC_CLOBBER;
57#ifdef USE_NETCDF4
58    if(!usingclassic)
59        cmode_modifier |= NC_NETCDF4;
60#endif
61
62    stat = nc_create(filenamecmode_modifier, &ncid);
63    check_err(stat,__LINE__,__FILE__);
64
65    /* ncid created above is also root group*/
66    rootgroup->ncid = ncid;
67
68#ifdef USE_NETCDF4
69    /* Define the group structure */
70    /* walking grdefs list will do a preorder walk of all defined groups*/
71    for(igrp=0;igrp<ngrps;igrp++) {
72 Symbolgsym = (Symbol*)listget(grpdefs,igrp);
73 if(gsym == rootgroup) continue; /* ignore root group*/
74 stat = nc_def_grp(gsym->container->ncid,gsym->name,&gsym->ncid);
75 check_err(stat,__LINE__,__FILE__);
76    }
77#endif
78
79#ifdef USE_NETCDF4
80    /* Define the types*/
81    if (ntyps > 0) {
82 int ityp;
83 for(ityp = 0; ityp < ntypsityp++) {
84     Symboltsym = (Symbol*)listget(typdefs,ityp);
85     genbin_deftype(tsym);
86 }
87    }
88#endif
89
90    /* define dimensions from info in dims array */
91    if (ndims > 0) {
92        for(idim = 0; idim < ndimsidim++) {
93            Symboldsym = (Symbol*)listget(dimdefs,idim);
94     stat = nc_def_dim(dsym->container->ncid,
95       dsym->name,
96       (dsym->dim.isunlimited?NC_UNLIMITED:dsym->dim.declsize),
97       &dsym->ncid);
98     check_err(stat,__LINE__,__FILE__);
99       }
100    }
101
102    /* define variables from info in vars array */
103    if (nvars > 0) {
104 for(ivar = 0; ivar < nvarsivar++) {
105            Symbolvsym = (Symbol*)listget(vardefs,ivar);
106     if (vsym->typ.dimset.ndims > 0) { /* a dimensioned variable */
107 /* construct a vector of dimension ids*/
108 int dimids[NC_MAX_VAR_DIMS];
109 for(idim=0;idim<vsym->typ.dimset.ndims;idim++)
110     dimids[idim] = vsym->typ.dimset.dimsyms[idim]->ncid;
111 stat = nc_def_var(vsym->container->ncid,
112   vsym->name,
113           vsym->typ.basetype->ncid,
114            vsym->typ.dimset.ndims,
115   dimids,
116   &vsym->ncid);
117     } else { /* a scalar */
118 stat = nc_def_var(vsym->container->ncid,
119   vsym->name,
120           vsym->typ.basetype->ncid,
121            vsym->typ.dimset.ndims,
122   NULL,
123   &vsym->ncid);
124     }
125     check_err(stat,__LINE__,__FILE__);
126 }
127    }
128
129#ifdef USE_NETCDF4
130    /* define special variable properties */
131    if(nvars > 0) {
132 for(ivar = 0; ivar < nvarsivar++) {
133            Symbolvar = (Symbol*)listget(vardefs,ivar);
134     genbin_definespecialattributes(var);
135 }
136    }
137#endif /*USE_NETCDF4*/
138
139/* define global attributes */
140    if(ngatts > 0) {
141 for(iatt = 0; iatt < ngattsiatt++) {
142     Symbolgasym = (Symbol*)listget(gattdefs,iatt);
143     genbin_defineattr(gasym);
144 }
145    }
146
147    /* define per-variable attributes */
148    if(natts > 0) {
149 for(iatt = 0; iatt < nattsiatt++) {
150     Symbolasym = (Symbol*)listget(attdefs,iatt);
151     genbin_defineattr(asym);
152 }
153    }
154
155    if (nofill_flag) {
156 stat = nc_set_fill(rootgroup->ncidNC_NOFILL, 0);
157 check_err(stat,__LINE__,__FILE__);
158    }
159
160    /* leave define mode */
161    stat = nc_enddef(rootgroup->ncid);
162    check_err(stat,__LINE__,__FILE__);
163
164    if(!header_only) {
165        /* Load values into those variables with defined data */
166        if(nvars > 0) {
167            for(ivar = 0; ivar < nvarsivar++) {
168                Symbolvsym = (Symbol*)listget(vardefs,ivar);
169                if(vsym->data != NULL) {
170                    bbClear(databuf);
171                    genbin_definevardata(vsym);
172                }
173            }
174        }
175    }
176    bbFree(databuf);
177}
178
179#ifdef USE_NETCDF4
180
181#if 0
182Turn off for now.
183
184static void
185genbin_defineglobalspecials(void)
186{
187    int stat = NC_NOERR;
188    const char* format = NULL;
189    if(usingclassic) return;
190    if(!/*Main.*/format_attribute) return;
191    /* Watch out, this is a global Attribute */
192    format = kind_string(/*Main.*/format_flag);
193    stat = nc_put_att_text(rootgroup->ncid,NC_GLOBAL,"_Format",strlen(format),format);
194    check_err(stat,__LINE__,__FILE__);
195}
196#endif /*0*/
197
198static void
199genbin_definespecialattributes(Symbolvar)
200{
201    int stat;
202    Specialdataspecial = &var->var.special;
203    if(special->flags & _STORAGE_FLAG) {
204        int storage = special->_Storage;
205        size_t* chunks = special->_ChunkSizes;
206        if(special->nchunks == 0 || chunks == NULLchunks = NULL;
207        stat = nc_def_var_chunking(var->container->ncid,
208                                   var->ncid,
209                                   (storage == NC_CONTIGUOUS?NC_CONTIGUOUS
210                                                            :NC_CHUNKED),
211                                   chunks);
212        check_err(stat,__LINE__,__FILE__);
213    }
214    if(special->flags & _FLETCHER32_FLAG) {
215        stat = nc_def_var_fletcher32(var->container->ncid,
216                                     var->ncid,
217                                     special->_Fletcher32);
218        check_err(stat,__LINE__,__FILE__);
219    }
220    if(special->flags & (_DEFLATE_FLAG | _SHUFFLE_FLAG)) {
221        stat = nc_def_var_deflate(var->container->ncid,
222                                  var->ncid,
223                                  (special->_Shuffle == 1?1:0),
224                                  (special->_DeflateLevel >= 0?1:0),
225                                  (special->_DeflateLevel >= 0?special->_DeflateLevel
226                                                              :0));
227        check_err(stat,__LINE__,__FILE__);
228    }
229    if(special->flags & _ENDIAN_FLAG) {
230        stat = nc_def_var_endian(var->container->ncid,
231                                 var->ncid,
232                                 (special->_Endianness == NC_ENDIAN_LITTLE?
233                                        NC_ENDIAN_LITTLE
234                                       :NC_ENDIAN_BIG));
235        check_err(stat,__LINE__,__FILE__);
236    }
237    if(special->flags & _NOFILL_FLAG) {
238        stat = nc_def_var_fill(var->container->ncid,
239                                 var->ncid,
240                  (special->_Fill?NC_FILL:NC_NOFILL),
241                                 NULL);
242        check_err(stat,__LINE__,__FILE__);
243    }
244}
245#endif /*USE_NETCDF4*/
246
247
248void
249cl_netcdf(void)
250{
251    int stat;
252    stat = nc_close(rootgroup->ncid);
253    check_err(stat,__LINE__,__FILE__);
254}
255
256#ifdef USE_NETCDF4
257/*
258Generate type definitions
259*/
260static void
261genbin_deftype(Symboltsym)
262{
263    unsigned long i;
264    int stat;
265
266    ASSERT(tsym->objectclass == NC_TYPE);
267    switch (tsym->subclass) {
268    case NC_PRIM: break; /* these are already taken care of*/
269    case NC_OPAQUE:
270 stat = nc_def_opaque(tsym->container->ncid,
271      tsym->typ.size,
272      tsym->name,
273      &tsym->ncid);
274        check_err(stat,__LINE__,__FILE__);
275 break;
276    case NC_ENUM:
277      {
278        Bytebufferdatum;
279        Datalistecdl;
280 stat = nc_def_enum(tsym->container->ncid,
281    tsym->typ.basetype->typ.typecode,
282    tsym->name,
283    &tsym->ncid);
284        check_err(stat,__LINE__,__FILE__);
285 datum = bbNew();
286        ecdl = builddatalist(1);
287        dlextend(ecdl); /* make room for one constant*/
288 ecdl->length = 1;
289 for(i=0;i<listlength(tsym->subnodes);i++) {
290   Symboleconst = (Symbol*)listget(tsym->subnodes,i);
291   ASSERT(econst->subclass == NC_ECONST);
292   generator_reset(bin_generator,NULL);
293   bbClear(datum);
294   generate_basetype(econst->typ.basetype,&econst->typ.econst,datum,NULL,bin_generator);
295   stat = nc_insert_enum(tsym->container->ncid,
296 tsym->ncid,
297 econst->name,
298 bbContents(datum));
299   check_err(stat,__LINE__,__FILE__);
300 }
301 bbFree(datum);
302    dlfree(&ecdl);
303      }
304      break;
305    case NC_VLEN:
306 stat = nc_def_vlen(tsym->container->ncid,
307    tsym->name,
308    tsym->typ.basetype->ncid,
309    &tsym->ncid);
310        check_err(stat,__LINE__,__FILE__);
311 break;
312    case NC_COMPOUND:
313 stat = nc_def_compound(tsym->container->ncid,
314        tsym->typ.size,
315        tsym->name,
316        &tsym->ncid);
317        check_err(stat,__LINE__,__FILE__);
318 for(i=0;i<listlength(tsym->subnodes);i++) {
319     Symbolefield = (Symbol*)listget(tsym->subnodes,i);
320     ASSERT(efield->subclass == NC_FIELD);
321     if(efield->typ.dimset.ndims == 0){
322         stat = nc_insert_compound(
323 tsym->container->ncid,
324 tsym->ncid,
325 efield->name,
326         efield->typ.offset,
327 efield->typ.basetype->ncid);
328     } else {
329 int j;
330 int dimsizes[NC_MAX_VAR_DIMS]; /* int because inside compound */
331 /* Generate the field dimension constants*/
332 for(j=0;j<efield->typ.dimset.ndims;j++) {
333      unsigned int size = efield->typ.dimset.dimsyms[j]->dim.declsize;
334      dimsizes[j] = size;
335 }
336         stat = nc_insert_array_compound(
337 tsym->container->ncid,
338 tsym->ncid,
339 efield->name,
340         efield->typ.offset,
341 efield->typ.basetype->ncid,
342 efield->typ.dimset.ndims,
343 dimsizes);
344     }
345            check_err(stat,__LINE__,__FILE__);
346 }
347 break;
348    default: panic("definectype: unexpected type subclass");
349    }
350}
351#endif /*USE_NETCDF4*/
352
353static void
354genbin_defineattr(Symbolasym)
355{
356    Bytebufferdatabuf = bbNew();
357    generator_reset(bin_generator,NULL);
358    generate_attrdata(asym,bin_generator,(Writer)genbin_write,databuf);
359}
360
361
362/* Following is patterned after the walk functions in semantics.c */
363static void
364genbin_definevardata(Symbolvsym)
365{
366    Bytebufferdatabuf;
367    if(vsym->data == NULL) return;
368    databuf = bbNew();
369    generator_reset(bin_generator,NULL);
370    generate_vardata(vsym,bin_generator,(Writer)genbin_write,databuf);
371}
372
373static int
374genbin_write(GeneratorgeneratorSymbolsymBytebuffermemory,
375             int rank, size_t* start, size_t* count)
376{
377    if(sym->objectclass == NC_ATT)
378 return genbin_writeattr(generator,sym,memory,rank,start,count);
379    else if(sym->objectclass == NC_VAR)
380 return genbin_writevar(generator,sym,memory,rank,start,count);
381    else
382 PANIC("illegal symbol for genbin_write");
383    return NC_EINVAL;
384}
385
386static int
387genbin_writevar(GeneratorgeneratorSymbolvsymBytebuffermemory,
388                int rank, size_t* start,
389#ifdef USE_NOFILL
390         size_t* indices
391#else
392         size_t* count
393#endif
394        )
395{
396    int stat = NC_NOERR;
397    char* data = bbContents(memory);
398#ifdef USE_NOFILL
399    size_t count[NC_MAX_VAR_DIMS];
400    { int i; for(i=0;i<rank;i++) count[i] = indices[i] - start[i];}
401#endif
402
403#ifdef GENDEBUG
404    {
405    int i;
406    fprintf(stderr,"startset = [");
407    for(i=0;i<rank;i++)
408 fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)start[i]);
409    fprintf(stderr,"] ");
410    fprintf(stderr,"countset = [");
411    for(i=0;i<rank;i++)
412 fprintf(stderr,"%s%lu",(i>0?", ":""),(unsigned long)count[i]);
413    fprintf(stderr,"]\n");
414    fflush(stderr);
415    }
416#endif
417
418    if(rank == 0) {
419 size_t count[1] = {1};
420        stat = nc_put_var1(vsym->container->ncidvsym->ncidcountdata);
421    } else {
422        stat = nc_put_vara(vsym->container->ncidvsym->ncidstartcountdata);
423    }
424    check_err(stat,__LINE__,__FILE__);
425    bbClear(memory);
426    return stat;
427}
428
429static int
430genbin_writeattr(GeneratorgeneratorSymbolasymBytebufferdatabuf,
431           int rank, size_t* start, size_t* count)
432{
433    int stat;
434    size_t len;
435    Datalistlist;
436    int varidgrpidtypid;
437    Symbolbasetype = asym->typ.basetype;
438
439    grpid = asym->container->ncid;
440    varid = (asym->att.var == NULL?NC_GLOBAL : asym->att.var->ncid);
441    typid = basetype->ncid;
442
443    list = asym->data;
444    len = list->length;
445
446    /* Use the specialized put_att_XX routines if possible*/
447    if(isprim(basetype->typ.typecode)) {
448      switch (basetype->typ.typecode) {
449      case NC_BYTE: {
450        signed char* data = (signed char*)bbContents(databuf);
451        stat = nc_put_att_schar(grpid,varid,asym->name,typid,len,data);
452        check_err(stat,__LINE__,__FILE__);
453      } break;
454      case NC_CHAR: {
455        char* data = (char*)bbContents(databuf);
456 size_t slen = bbLength(databuf);
457 /* Revise length if slen == 0 */
458 if(slen == 0) {
459          bbAppend(databuf,'\0');
460          /* bbAppend frees the memory pointed to by char* data,
461             so re-assign.  See Coverity issue: 1265731.*/
462          data = (char*)bbContents(databuf);
463          slen++;
464        }
465        stat = nc_put_att_text(grpid,varid,asym->name,slen,data);
466        check_err(stat,__LINE__,__FILE__);
467      } break;
468      case NC_SHORT: {
469        short* data = (short*)bbContents(databuf);
470        stat = nc_put_att_short(grpid,varid,asym->name,typid,len,data);
471        check_err(stat,__LINE__,__FILE__);
472            } break;
473            case NC_INT: {
474                int* data = (int*)bbContents(databuf);
475                stat = nc_put_att_int(grpid,varid,asym->name,typid,len,data);
476                check_err(stat,__LINE__,__FILE__);
477            } break;
478            case NC_FLOAT: {
479                float* data = (float*)bbContents(databuf);
480                stat = nc_put_att_float(grpid,varid,asym->name,typid,len,data);
481                check_err(stat,__LINE__,__FILE__);
482            } break;
483            case NC_DOUBLE: {
484                double* data = (double*)bbContents(databuf);
485                stat = nc_put_att_double(grpid,varid,asym->name,typid,len,data);
486                check_err(stat,__LINE__,__FILE__);
487            } break;
488#ifdef USE_NETCDF4
489     case NC_STRING: {
490 const char** data;
491         data = (const char**)bbContents(databuf);
492                stat = nc_put_att_string(grpid,varid,asym->name,
493  bbLength(databuf)/sizeof(char*),
494          data);
495 } break;
496            case NC_UBYTE: {
497                unsigned char* data = (unsigned char*)bbContents(databuf);
498                stat = nc_put_att_uchar(grpid,varid,asym->name,typid,len,data);
499                check_err(stat,__LINE__,__FILE__);
500            } break;
501            case NC_USHORT: {
502                unsigned short* data = (unsigned short*)bbContents(databuf);
503                stat = nc_put_att_ushort(grpid,varid,asym->name,typid,len,data);
504                check_err(stat,__LINE__,__FILE__);
505            } break;
506            case NC_UINT: {
507                unsigned int* data = (unsigned int*)bbContents(databuf);
508                stat = nc_put_att_uint(grpid,varid,asym->name,typid,len,data);
509                check_err(stat,__LINE__,__FILE__);
510            } break;
511            case NC_INT64: {
512                long long* data = (long long*)bbContents(databuf);
513                stat = nc_put_att_longlong(grpid,varid,asym->name,typid,len,data);
514                check_err2(stat,asym->lineno,__LINE__,__FILE__);
515            } break;
516            case NC_UINT64: {
517                unsigned long long* data = (unsigned long long*)bbContents(databuf);
518                stat = nc_put_att_ulonglong(grpid,varid,asym->name,typid,len,data);
519                check_err(stat,__LINE__,__FILE__);
520            } break;
521#endif
522            default: PANIC1("genbin_defineattr: unexpected basetype: %d",basetype->typ.typecode);
523 }
524    } else { /* use the generic put_attribute for user defined types*/
525 const char* data;
526 data = (const char*)bbContents(databuf);
527        stat = nc_put_att(grpid,varid,asym->name,typid,
528         len,(void*)data);
529        check_err(stat,__LINE__,__FILE__);
530#ifdef GENDEBUG
531 {
532     char out[4096];
533     memset(out,0x77,sizeof(out));
534     stat = nc_get_att(grpid,varid,asym->name,&out);
535            check_err(stat,__LINE__,__FILE__);
536 }
537#endif
538    }
539    return stat;
540}
541
542#endif /*ENABLE_BINARY*/


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