1/*********************************************************************
2 *   Copyright 2009, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *********************************************************************/
5/* $Id: data.c,v 1.7 2010/05/24 19:59:56 dmh Exp $ */
6/* $Header: /upc/share/CVS/netcdf-3/ncgen/data.c,v 1.7 2010/05/24 19:59:56 dmh Exp $ */
7
8#include        "includes.h"
9#include        "offsets.h"
10#include        "dump.h"
11
12#define XVSNPRINTF vsnprintf
13/*
14#define XVSNPRINTF lvsnprintf
15extern int lvsnprintf(char*, size_t, const char*, va_list);
16*/
17
18#define DATALISTINIT 32
19
20/* Track all known datalist*/
21Datalistalldatalists = NULL;
22
23NCConstant nullconstant;
24NCConstant fillconstant;
25
26Datalist nildatalist; /* to support NIL keyword */
27
28Bytebuffercodebuffer;
29Bytebuffercodetmp;
30Bytebufferstmt;
31
32
33/* Forward */
34
35/**************************************************/
36/**************************************************/
37
38/* return 1 if the next element in the datasrc is compound*/
39int
40issublist(Datasrcdatasrc) {return istype(datasrc,NC_COMPOUND);}
41
42/* return 1 if the next element in the datasrc is a string*/
43int
44isstring(Datasrcdatasrc) {return istype(datasrc,NC_STRING);}
45
46/* return 1 if the next element in the datasrc is a fill value*/
47int
48isfillvalue(Datasrcdatasrc)
49{
50return srcpeek(datasrc) == NULL || istype(datasrc,NC_FILLVALUE);
51}
52
53/* return 1 if the next element in the datasrc is nc_type*/
54int
55istype(Datasrcdatasrc , nc_type nctype)
56{
57    NCConstantci = srcpeek(datasrc);
58    if(ci != NULL && ci->nctype == nctype) return 1;
59    return 0;
60}
61
62int
63isstringable(nc_type nctype)
64{
65    switch (nctype) {
66    case NC_CHAR: case NC_STRING:
67    case NC_BYTE: case NC_UBYTE:
68    case NC_FILLVALUE:
69 return 1;
70    default: break;
71    }
72    return 0;
73}
74
75/**************************************************/
76
77void
78freedatasrc(Datasrcsrc)
79{
80    efree(src);
81}
82
83Datasrc*
84allocdatasrc(void)
85{
86    Datasrcsrc;
87    src = emalloc(sizeof(Datasrc));
88    src->data = NULL;
89    src->index = 0;
90    src->length = 0;
91    src->prev = NULL;
92    return src;
93}
94
95Datasrc*
96datalist2src(Datalistlist)
97{
98    Datasrcsrc;
99    ASSERT(list != NULL);
100    src = allocdatasrc();
101    src->data = list->data;
102    src->index = 0;
103    src->length = list->length;
104    DUMPSRC(src,"#");
105    return src;
106}
107
108Datasrc*
109const2src(NCConstantcon)
110{
111    Datasrcsrc;
112    ASSERT(con != NULL);
113    src = allocdatasrc();
114    src->data = con;
115    src->index = 0;
116    src->length = 1;
117    DUMPSRC(src,"#");
118    return src;
119}
120
121NCConstant
122list2const(Datalistlist)
123{
124    NCConstant con;
125    ASSERT(list != NULL);
126    con.nctype = NC_COMPOUND;
127    con.lineno = list->data[0].lineno;
128    con.value.compoundv = list;
129    con.filled = 0;
130    return con;
131}
132
133Datalist*
134const2list(NCConstantcon)
135{
136    Datalistlist;
137    ASSERT(con != NULL);
138    list = builddatalist(1);
139    if(list != NULL) {
140        dlappend(list,con);
141    }
142    return list;
143}
144
145NCConstant*
146srcpeek(Datasrcds)
147{
148    if(ds == NULL) return NULL;
149    if(ds->index < ds->length)
150 return &ds->data[ds->index];
151    if(ds->spliced)
152 return srcpeek(ds->prev);
153    return NULL;
154}
155
156void
157srcreset(Datasrcds)
158{
159    ds->index = 0;
160}
161
162NCConstant*
163srcnext(Datasrcds)
164{
165    DUMPSRC(ds,"!");
166    if(ds == NULL) return NULL;
167    if(ds->index < ds->length)
168 return &ds->data[ds->index++];
169    if(ds->spliced) {
170 srcpop(ds);
171 return srcnext(ds);
172    }
173    return NULL;
174}
175
176int
177srcmore(Datasrcds)
178{
179    if(ds == NULL) return 0;
180    if(ds->index < ds->length) return 1;
181    if(ds->spliced) return srcmore(ds->prev);
182    return 0;
183}
184
185int
186srcline(Datasrcds)
187{
188    int index = ds->index;
189    int len = ds->length;
190    /* pick closest available entry*/
191    if(len == 0) return 0;
192    if(index >= lenindex = len-1;
193    return ds->data[index].lineno;
194}
195
196void
197srcpush(Datasrcsrc)
198{
199    NCConstantcon;
200    ASSERT(src != NULL);
201    con = srcnext(src);
202    ASSERT(con->nctype == NC_COMPOUND);
203    srcpushlist(src,con->value.compoundv);
204}
205
206void
207srcpushlist(DatasrcsrcDatalistdl)
208{
209    Datasrcnewsrc;
210    ASSERT(src != NULL && dl != NULL);
211    newsrc = allocdatasrc();
212    *newsrc = *src;
213    src->prev = newsrc;
214    src->index = 0;
215    src->data = dl->data;
216    src->length = dl->length;
217    DUMPSRC(src,">!");
218}
219
220void
221srcpop(Datasrcsrc)
222{
223    if(src != NULL) {
224        Datasrcprev = src->prev;
225 *src = *prev;
226        freedatasrc(prev);
227    }
228    DUMPSRC(src,"<");
229}
230
231void
232srcsplice(DatasrcdsDatalistlist)
233{
234    srcpushlist(ds,list);
235    ds->spliced = 1;
236}
237
238void
239srcsetfill(DatasrcdsDatalistlist)
240{
241    if(ds->index >= ds->lengthPANIC("srcsetfill: no space");
242    if(ds->data[ds->index].nctype != NC_FILLVALUEPANIC("srcsetfill: not fill");
243    ds->data[ds->index].nctype = NC_COMPOUND;
244    ds->data[ds->index].value.compoundv = list;
245}
246
247
248/**************************************************/
249#ifdef GENDEBUG
250void
251report(char* leadDatalistlist)
252{
253extern void bufdump(Datalist*,Bytebuffer*);
254Bytebufferbuf = bbNew();
255bufdump(list,buf);
256fprintf(stderr,"\n%s::%s\n",lead,bbContents(buf));
257fflush(stderr);
258bbFree(buf);
259}
260
261void
262report0(char* leadDatasrcsrc, int index)
263{
264}
265#endif
266
267/**************************************************/
268
269/* Shallow constant cloning*/
270NCConstant
271cloneconstant(NCConstantcon)
272{
273    NCConstant newcon = *con;
274    char* s;
275    switch (newcon.nctype) {
276    case NC_STRING:
277 s = (char*)emalloc(newcon.value.stringv.len+1);
278 memcpy(s,newcon.value.stringv.stringv,newcon.value.stringv.len);
279 s[newcon.value.stringv.len] = '\0';
280 newcon.value.stringv.stringv = s;
281 break;
282    case NC_OPAQUE:
283 s = (char*)emalloc(newcon.value.opaquev.len+1);
284 memcpy(s,newcon.value.opaquev.stringv,newcon.value.opaquev.len);
285 s[newcon.value.opaquev.len] = '\0';
286 newcon.value.opaquev.stringv = s;
287 break;
288    default: break;
289    }
290    return newcon;
291}
292
293/**************************************************/
294
295Datalist*
296datalistclone(Datalistdl)
297{
298    int i;
299    Datalistclone = builddatalist(dl->length);
300    for(i=0;i<dl->length;i++) {
301 clone->data[i] = cloneconstant(dl->data+i);
302    }
303    return clone;
304}
305
306Datalist*
307datalistconcat(Datalistdl1Datalistdl2)
308{
309    NCConstantvector;
310    ASSERT(dl1 != NULL);
311    if(dl2 == NULL) return dl1;
312    vector = (NCConstant*)erealloc(dl1->data,sizeof(NCConstant)*(dl1->length+dl2->length));
313    if(vector == NULL) return NULL;
314    memcpy((void*)(vector+dl1->length),dl2->data,sizeof(NCConstant)*(dl2->length));
315    dl1->data = vector;
316    return dl1;
317}
318
319Datalist*
320datalistappend(DatalistdlNCConstantcon)
321{
322    NCConstantvector;
323    ASSERT(dl != NULL);
324    if(con == NULL) return dl;
325    vector = (NCConstant*)erealloc(dl->data,sizeof(NCConstant)*(dl->length+1));
326    if(vector == NULL) return NULL;
327    vector[dl->length] = *con;
328    dl->length++;
329    dl->data = vector;
330    return dl;
331}
332
333Datalist*
334datalistreplace(Datalistdl, unsigned int indexNCConstantcon)
335{
336    ASSERT(dl != NULL);
337    ASSERT(index < dl->length);
338    ASSERT(con != NULL);
339    dl->data[index] = *con;
340    return dl;
341}
342
343int
344datalistline(Datalistds)
345{
346    if(ds == NULL || ds->length == 0) return 0;
347    return ds->data[0].lineno;
348}
349
350
351/* Go thru a databuf of possibly nested constants
352   and insert commas as needed; ideally, this
353   operation should be idempotent so that
354   the caller need not worry about it having already
355   been applied. Also, handle situation where there may be missing
356   matching right braces.
357*/
358
359static char* commifyr(char* pBytebufferbuf);
360static char* wordstring(char* pBytebufferbuf, int quote);
361
362void
363commify(Bytebufferbuf)
364{
365    char* list,*p;
366
367    if(bbLength(buf) == 0) return;
368    list = bbDup(buf);
369    p = list;
370    bbClear(buf);
371    commifyr(p,buf);
372    bbNull(buf);
373    efree(list);
374}
375
376/* Requires that the string be balanced
377   WRT to braces
378*/
379static char*
380commifyr(char* pBytebufferbuf)
381{
382    int comma = 0;
383    int c;
384    while((c=*p++)) {
385 if(c == ' ') continue;
386 if(c == ',') continue;
387 else if(c == '}') {
388     break;
389 }
390 if(commabbCat(buf,", "); else comma=1;
391 if(c == '{') {
392     bbAppend(buf,'{');
393     p = commifyr(p,buf);
394     bbAppend(buf,'}');
395 } else if(c == '\'' || c == '\"') {
396     p = wordstring(p,buf,c);
397 } else {
398     bbAppend(buf,c);
399     p=word(p,buf);
400 }
401    }
402    return p;
403}
404
405char*
406word(char* pBytebufferbuf)
407{
408    int c;
409    while((c=*p++)) {
410 if(c == '}' || c == ' ' || c == ',') break;
411 if(c == '\\') {
412     bbAppend(buf,c);
413     c=*p++;
414     if(!c) break;
415 }
416 bbAppend(buf,(char)c);
417    }
418    p--; /* leave terminator for parent */
419    return p;
420}
421
422static char*
423wordstring(char* pBytebufferbuf, int quote)
424{
425    int c;
426    bbAppend(buf,quote);
427    while((c=*p++)) {
428 if(c == '\\') {
429     bbAppend(buf,c);
430     c = *p++;
431     if(c == '\0') return --p;
432 } else if(c == quote) {
433     bbAppend(buf,c);
434     return p;
435 }
436 bbAppend(buf,c);
437    }
438    return p;
439}
440
441
442static const char zeros[] =
443    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
444void
445alignbuffer(NCConstantprimBytebufferbuf)
446{
447    int alignment,pad,offset;
448
449    if(prim->nctype == NC_ECONST)
450        alignment = nctypealignment(prim->value.enumv->typ.typecode);
451    else if(usingclassic && prim->nctype == NC_STRING)
452        alignment = nctypealignment(NC_CHAR);
453    else if(prim->nctype == NC_CHAR)
454        alignment = nctypealignment(NC_CHAR);
455    else
456        alignment = nctypealignment(prim->nctype);
457    offset = bbLength(buf);
458    pad = getpadding(offset,alignment);
459    if(pad > 0) {
460 bbAppendn(buf,(void*)zeros,pad);
461    }
462}
463
464
465
466/*
467Following routines are in support of language-oriented output
468*/
469
470void
471codedump(Bytebufferbuf)
472{
473   bbCatbuf(codebuffer,buf);
474   bbClear(buf);
475}
476
477void
478codepartial(const char* txt)
479{
480    bbCat(codebuffer,txt);
481}
482
483void
484codeline(const char* line)
485{
486    codepartial(line);
487    codepartial("\n");
488}
489
490void
491codelined(int n, const char* txt)
492{
493    bbindent(codebuffer,n);
494    bbCat(codebuffer,txt);
495    codepartial("\n");
496}
497
498void
499codeflush(void)
500{
501    if(bbLength(codebuffer) > 0) {
502        bbNull(codebuffer);
503        fputs(bbContents(codebuffer),stdout);
504        fflush(stdout);
505        bbClear(codebuffer);
506    }
507}
508
509void
510bbindent(Bytebufferbuf, const int n)
511{
512    bbCat(buf,indented(n));
513}
514
515/* Provide an restrict snprintf that writes to an expandable buffer */
516/* Simulates a simple snprintf because apparently
517   the IRIX one is broken wrt return value.
518   Supports only %u %d %f %s and %% specifiers
519   with optional leading hh or ll.
520*/
521
522static void
523vbbprintf(Bytebufferbuf, const char* fmt, va_list argv)
524{
525    char tmp[128];
526    const char* p;
527    int c;
528    int hcount;
529    int lcount;
530
531    char* text;
532
533    for(p=fmt;(c=*p++);) {
534 hcount = 0; lcount = 0;
535 switch (c) {
536 case '%':
537retry:     switch ((c=*p++)) {
538     case '\0': bbAppend(buf,'%'); p--; break;
539     case '%': bbAppend(buf,c); break;
540     case 'h':
541 hcount++;
542 while((c=*p) && (c == 'h')) {hcount++; p++;}
543 if(hcount > 2) hcount = 2;
544 goto retry;
545     case 'l':
546 lcount++;
547 while((c=*p) && (c == 'l')) {
548     lcount++;
549     p++;
550 }
551 if(lcount > 2) lcount = 2;
552 goto retry;
553     case 'u':
554 if(hcount == 2) {
555                snprintf(tmp,sizeof(tmp),"%hhu",
556 (unsigned int)va_arg(argv,unsigned int));
557 } else if(hcount == 1) {
558                snprintf(tmp,sizeof(tmp),"%hu",
559 (unsigned int)va_arg(argv,unsigned int));
560 } else if(lcount == 2) {
561                snprintf(tmp,sizeof(tmp),"%llu",
562 (unsigned long long)va_arg(argv,unsigned long long));
563 } else if(lcount == 1) {
564                snprintf(tmp,sizeof(tmp),"%lu",
565 (unsigned long)va_arg(argv,unsigned long));
566 } else {
567                snprintf(tmp,sizeof(tmp),"%u",
568 (unsigned int)va_arg(argv,unsigned int));
569 }
570 bbCat(buf,tmp);
571 break;
572     case 'd':
573 if(hcount == 2) {
574                snprintf(tmp,sizeof(tmp),"%hhd",
575 (signed int)va_arg(argv,signed int));
576 } else if(hcount == 1) {
577                snprintf(tmp,sizeof(tmp),"%hd",
578 (signed int)va_arg(argv,signed int));
579 } else if(lcount == 2) {
580                snprintf(tmp,sizeof(tmp),"%lld",
581 (signed long long)va_arg(argv,signed long long));
582 } else if(lcount == 1) {
583                snprintf(tmp,sizeof(tmp),"%ld",
584 (signed long)va_arg(argv,signed long));
585 } else {
586                snprintf(tmp,sizeof(tmp),"%d",
587 (signed int)va_arg(argv,signed int));
588 }
589 bbCat(buf,tmp);
590 break;
591            case 'f':
592 if(lcount > 0) {
593                snprintf(tmp,sizeof(tmp),"((double)%.16g)",
594 (double)va_arg(argv,double));
595 } else {
596                snprintf(tmp,sizeof(tmp),"((float)%.8g)",
597 (double)va_arg(argv,double));
598 }
599 bbCat(buf,tmp);
600         break;
601     case 's':
602 text = va_arg(argv,char*);
603 bbCat(buf,text);
604 break;
605     case 'c':
606 c = va_arg(argv,int);
607 bbAppend(buf,(char)c);
608 break;
609            default:
610 PANIC1("vbbprintf: unknown specifier: %c",(char)c);
611     }
612     break;
613 default:
614     bbAppend(buf,c);
615 }
616    }
617}
618
619void
620bbprintf(Bytebufferbuf, const char *fmt, ...)
621{
622    va_list argv;
623    va_start(argv,fmt);
624    vbbprintf(buf,fmt,argv);
625    va_end(argv);
626}
627
628void
629bbprintf0(Bytebufferbuf, const char *fmt, ...)
630{
631    va_list argv;
632    va_start(argv,fmt);
633    bbClear(buf);
634    vbbprintf(buf,fmt,argv);
635    va_end(argv);
636}
637
638void
639codeprintf(const char *fmt, ...)
640{
641    va_list argv;
642    va_start(argv,fmt);
643    vbbprintf(codebuffer,fmt,argv);
644    va_end(argv);
645}
646
647NCConstant*
648emptycompoundconst(int linenoNCConstantc)
649{
650    ASSERT(c != NULL);
651    c->lineno = lineno;
652    c->nctype = NC_COMPOUND;
653    c->value.compoundv = builddatalist(0);
654    c->filled = 0;
655    return c;
656}
657
658NCConstant*
659emptystringconst(int linenoNCConstantc)
660{
661    ASSERT(c != NULL);
662    c->lineno = lineno;
663    c->nctype = NC_STRING;
664    c->value.stringv.len = 0;
665    c->value.stringv.stringv = NULL;
666    c->filled = 0;
667    return c;
668}
669
670#define INDENTMAX 256
671static char* dent = NULL;
672
673char*
674indented(int n)
675{
676    char* indentation;
677    if(dent == NULL) {
678 dent = (char*)emalloc(INDENTMAX+1);
679 memset((void*)dent,' ',INDENTMAX);
680 dent[INDENTMAX] = '\0';
681    }
682    if(n*4 >= INDENTMAXn = INDENTMAX/4;
683    indentation = dent+(INDENTMAX - 4*n);
684    return indentation;
685}
686
687void
688dlextend(Datalistdl)
689{
690    size_t newalloc;
691    newalloc = (dl->alloc > 0?2*dl->alloc:1);
692    dlsetalloc(dl,newalloc);
693}
694
695void
696dlsetalloc(Datalistdl, size_t newalloc)
697{
698    NCConstantnewdata;
699    if(newalloc <= 0) newalloc = 1;
700    if(dl->alloc > 0)
701        newdata = (NCConstant*)erealloc((void*)dl->data,sizeof(NCConstant)*newalloc);
702    else {
703        newdata = (NCConstant*)emalloc(sizeof(NCConstant)*newalloc);
704        memset((void*)newdata,0,sizeof(NCConstant)*newalloc);
705    }
706    dl->alloc = newalloc;
707    dl->data = newdata;
708}
709
710
711Datalist*
712builddatalist(int initial)
713{
714    Datalistci;
715    if(initial <= 0) initial = DATALISTINIT;
716    initial++; /* for header*/
717    ci = (Datalist*)emalloc(sizeof(Datalist));
718    memset((void*)ci,0,sizeof(Datalist)); /* only clear the hdr*/
719    ci->data = (NCConstant*)emalloc(sizeof(NCConstant)*initial);
720    memset((void*)ci->data,0,sizeof(NCConstant)*initial);
721    ci->alloc = initial;
722    ci->length = 0;
723    return ci;
724}
725
726void
727dlappend(DatalistdlNCConstantconstant)
728{
729    if(dl->length >= dl->allocdlextend(dl);
730    if(constant == NULLconstant = &nullconstant;
731    dl->data[dl->length++] = *constant;
732}
733
734NCConstant
735builddatasublist(Datalistdl)
736{
737
738  NCConstant d;
739  d.nctype = NC_COMPOUND;
740  d.lineno = (dl->length > 0?dl->data[0].lineno:0);
741  d.value.compoundv = dl;
742  d.filled = 0;
743  return d;
744
745}
746
747/*! Function to free an allocated datalist.
748
749  This function is used to free an individual datalist
750  object.  It is possible, hypothetically, that a
751  datalist will appear in the middle of a set of datalists,
752  in which case we'll need to determine that and shuffle around
753  'next' pointers.  For the time being, this assumes that
754  we are freeing a datalist which was allocated locally
755  and must be discarded.
756
757  Using this function instead of an inline 'free' just in
758  case we ever want to extend it, we won't have to go back
759  and re-write a bunch of stuff. I hope.
760
761  @param dlist Pointer to datalist object being freed.
762
763 */
764void dlfree(Datalist **dlist) {
765
766  if(*dlist) free(*dlist);
767  dlist = NULL;
768}
769
770


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