1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information.
3*/
4
5#include "config.h"
6#include <sys/stat.h>
7
8#ifdef NETINET_IN_H
9#include <netinet/in.h>
10#endif
11
12#ifndef HAVE_SSIZE_T
13#ifdef SSIZE_T
14#define ssize_t SSIZE_T
15#else
16#define ssize_t int
17#endif
18#define HAVE_SSIZE_T
19#endif
20
21#include "ocinternal.h"
22#include "ocdebug.h"
23
24#define MAXLEVEL 1
25
26/*Forward*/
27static void dumpocnode1(OCnodenode, int depth);
28static void dumpdimensions(OCnodenode);
29static void dumpattvalue(OCtype nctype, char** aset, int index);
30
31static char* sindent = NULL;
32
33static char*
34dent(int n)
35{
36    if(sindent == NULL) {
37 sindent = (char*)ocmalloc(102);
38 MEMCHECK(sindent,NULL);
39 memset((void*)sindent,(int)' ',(size_t)101);
40 sindent[101] = '\0';
41    }
42    if(n > 100) n = 100;
43    return sindent+(100-n);
44}
45
46/* support [dd] leader*/
47static char*
48dent2(int n) {return dent(n+4);}
49
50static void
51tabto(int posOCbytesbuffer)
52{
53    int bol,len,pad;
54    len = ocbyteslength(buffer);
55    /* find preceding newline */
56    for(bol=len-1;;bol--) {
57 int c = ocbytesget(buffer,(size_t)bol);
58 if(c < 0) break;
59 if(c == '\n') {bol++; break;}
60    }
61    len = (len - bol);
62    pad = (pos - len);
63    while(pad-- > 0) ocbytescat(buffer," ");
64}
65
66void
67ocdumpnode(OCnodenode)
68{
69    if(node != NULL) {
70        dumpocnode1(node,0);
71    } else {
72 fprintf(stdout,"<NULL>\n");
73    }
74    fflush(stdout);
75}
76
77static void
78dumpocnode1(OCnodenode, int depth)
79{
80    unsigned int n;
81    switch (node->octype) {
82    case OC_Atomic: {
83        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
84 if(node->name == NULLOCPANIC("prim without name");
85 fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
86 dumpdimensions(node);
87 fprintf(stdout," &%lx",(unsigned long)node);
88 fprintf(stdout,"\n");
89    } break;
90
91    case OC_Dataset: {
92        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
93 fprintf(stdout,"dataset %s\n",
94 (node->name?node->name:""));
95 for(n=0;n<oclistlength(node->subnodes);n++) {
96     dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
97 }
98    } break;
99
100    case OC_Structure: {
101        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
102 fprintf(stdout,"struct %s",
103 (node->name?node->name:""));
104 dumpdimensions(node);
105 fprintf(stdout," &%lx",(unsigned long)node);
106 fprintf(stdout,"\n");
107 for(n=0;n<oclistlength(node->subnodes);n++) {
108     dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
109 }
110    } break;
111
112    case OC_Sequence: {
113        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
114 fprintf(stdout,"sequence %s",
115 (node->name?node->name:""));
116 dumpdimensions(node);
117 fprintf(stdout," &%lx",(unsigned long)node);
118 fprintf(stdout,"\n");
119 for(n=0;n<oclistlength(node->subnodes);n++) {
120     dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
121 }
122    } break;
123
124    case OC_Grid: {
125 unsigned int i;
126        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
127 fprintf(stdout,"grid %s",
128 (node->name?node->name:""));
129 dumpdimensions(node);
130 fprintf(stdout," &%lx",(unsigned long)node);
131 fprintf(stdout,"\n");
132 fprintf(stdout,"%sarray:\n",dent2(depth+1));
133 dumpocnode1((OCnode*)oclistget(node->subnodes,0),depth+2);
134 fprintf(stdout,"%smaps:\n",dent2(depth+1));
135 for(i=1;i<oclistlength(node->subnodes);i++) {
136     dumpocnode1((OCnode*)oclistget(node->subnodes,i),depth+2);
137 }
138    } break;
139
140    case OC_Attribute: {
141        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
142 if(node->name == NULLOCPANIC("Attribute without name");
143 fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
144 for(n=0;n<oclistlength(node->att.values);n++) {
145     char* value = (char*)oclistget(node->att.values,n);
146     if(n > 0) fprintf(stdout,",");
147     fprintf(stdout," %s",value);
148 }
149 fprintf(stdout," &%lx",(unsigned long)node);
150 fprintf(stdout,"\n");
151    } break;
152
153    case OC_Attributeset: {
154        fprintf(stdout,"[%2d]%s ",depth,dent(depth));
155 fprintf(stdout,"%s:\n",node->name?node->name:"Attributes");
156 for(n=0;n<oclistlength(node->subnodes);n++) {
157     dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
158 }
159    } break;
160
161    default:
162 OCPANIC1("encountered unexpected node type: %x",node->octype);
163    }
164
165    if(node->attributes != NULL) {
166 unsigned int i;
167 for(i=0;i<oclistlength(node->attributes);i++) {
168     OCattributeatt = (OCattribute*)oclistget(node->attributes,i);
169     fprintf(stdout,"%s[%s=",dent2(depth+2),att->name);
170     if(att->nvalues == 0)
171 OCPANIC("Attribute.nvalues == 0");
172     if(att->nvalues == 1) {
173 dumpattvalue(att->etype,att->values,0);
174     } else {
175 int j;
176         fprintf(stdout,"{");
177 for(j=0;j<att->nvalues;j++) {
178     if(j>0) fprintf(stdout,", ");
179     dumpattvalue(att->etype,att->values,j);
180 }
181         fprintf(stdout,"}");
182     }
183     fprintf(stdout,"]\n");
184 }
185    }
186}
187
188static void
189dumpdimensions(OCnodenode)
190{
191    unsigned int i;
192    for(i=0;i<node->array.rank;i++) {
193        OCnodedim = (OCnode*)oclistget(node->array.dimensions,i);
194        fprintf(stdout,"[%s=%lu]",
195 (dim->name?dim->name:"?"),
196 (unsigned long)dim->dim.declsize);
197    }
198}
199
200static void
201dumpattvalue(OCtype nctype, char** strings, int index)
202{
203    if(nctype == OC_String || nctype == OC_URL) {
204        fprintf(stdout,"\"%s\"",strings[index]);
205    } else {
206        fprintf(stdout,"%s",strings[index]);
207    }
208}
209
210void
211ocdumpslice(OCsliceslice)
212{
213    fprintf(stdout,"[");
214    fprintf(stdout,"%lu",(unsigned long)slice->first);
215    if(slice->stride > 1) fprintf(stdout,":%lu",(unsigned long)slice->stride);
216    fprintf(stdout,":%lu",(unsigned long)(slice->first+slice->count)-1);
217    fprintf(stdout,"]");
218}
219
220void
221ocdumpclause(OCprojectionclauseref)
222{
223    unsigned int i;
224    OClistpath = oclistnew();
225    occollectpathtonode(ref->node,path);
226    for(i=0;i<oclistlength(path);i++) {
227        OClistsliceset;
228 OCnodenode = (OCnode*)oclistget(path,i);
229 if(node->tree != NULL) continue; /* leave off the root node*/
230 fprintf(stdout,"%s%s",(i>0?PATHSEPARATOR:""),node->name);
231 sliceset = (OClist*)oclistget(ref->indexsets,i);
232 if(sliceset != NULL) {
233     unsigned int j;
234     for(j=0;j<oclistlength(sliceset);j++) {
235         OCsliceslice = (OCslice*)oclistget(sliceset,j);
236         ocdumpslice(slice);
237     }
238 }
239    }
240}
241
242
243static void
244addfield(char* field, char* line, int align)
245{
246    int len,rem;
247    strcat(line,"|");
248    strcat(line,field);
249    len = strlen(field);
250    rem = (align - len);
251    while(rem-- > 0) strcat(line," ");
252}
253
254static void
255dumpfield(size_t index, char* n8, int isxdr)
256{
257    char line[1024];
258    char tmp[32];
259
260    union {
261 unsigned int uv;
262 int sv;
263 char cv[4];
264 float fv;
265    } form;
266    union {
267 char cv[8];
268        unsigned long long ll;
269        double d;
270    } dform;
271
272    line[0] = '\0';
273
274    /* offset */
275    sprintf(tmp,"%6zd",index);
276    addfield(tmp,line,5);
277
278    memcpy(form.cv,n8,4);
279
280    /* straight hex*/
281    sprintf(tmp,"%08x",form.uv);
282    addfield(tmp,line,8);
283
284    if(isxdr) {swapinline32(&form.uv);}
285
286    /* unsigned integer */
287    sprintf(tmp,"%12u",form.uv);
288    addfield(tmp,line,12);
289
290    /* signed integer */
291    sprintf(tmp,"%12d",form.sv);
292    addfield(tmp,line,12);
293
294    /* float */
295    sprintf(tmp,"%#g",form.fv);
296    addfield(tmp,line,12);
297
298    /* char[4] */
299    {
300        /* use raw form (i.e. n8)*/
301        int i;
302 tmp[0] = '\0';
303        for(i=0;i<4;i++) {
304     char stmp[64];
305     unsigned int c = (n8[i] & 0xff);
306     if(c < ' ' || c > 126)
307                snprintf(stmp,sizeof(stmp),"\\%02x",c);
308     else
309                snprintf(stmp,sizeof(stmp),"%c",c);
310     if(!occoncat(tmp,sizeof(tmp),1,stmp))
311 return;
312        }
313    }
314
315    addfield(tmp,line,16);
316
317    /* double */
318    memcpy(dform.cv,n8,(size_t)(2*XDRUNIT));
319    if(isxdrxxdrntohdouble(dform.cv,&dform.d);
320    sprintf(tmp,"%#g",dform.d);
321    addfield(tmp,line,12);
322
323    fprintf(stdout,"%s\n",line);
324}
325
326static void
327typedmemorydump(char* memory, size_t len, int fromxdr)
328{
329    unsigned int i,count,rem;
330    char line[1024];
331    char* pmem;
332    char mem[8];
333
334    assert(memory[len] == 0);
335
336    /* build the header*/
337    line[0] = '\0';
338    addfield("offset",line,6);
339    addfield("hex",line,8);
340    addfield("uint",line,12);
341    addfield("int",line,12);
342    addfield("float",line,12);
343    addfield("char[4]",line,16);
344    addfield("double",line,12);
345    strcat(line,"\n");
346    fprintf(stdout,"%s",line);
347
348    count = (len / sizeof(int));
349    rem = (len % sizeof(int));
350
351    for(pmem=memory,i=0;i<count;i++,pmem+=4) {
352 memset(mem,0,8);
353 if(i<(count-1))
354     memcpy(mem,pmem,8);
355 else
356     memcpy(mem,pmem,4);
357 dumpfield(i*sizeof(unsigned int),mem,fromxdr);
358    }
359    if(rem > 0) {
360 memset(mem,0,8);
361 memcpy(mem,pmem,4);
362 dumpfield(i*sizeof(unsigned int),mem,fromxdr);
363    }
364    fflush(stdout);
365}
366
367static void
368simplememorydump(char* memory, size_t len, int fromxdr)
369{
370    unsigned int i,count,rem;
371    int* imemory;
372    char tmp[32];
373    char line[1024];
374
375    assert(memory[len] == 0);
376
377    /* build the header*/
378    line[0] = '\0';
379    addfield("offset",line,6);
380    addfield("XDR (hex)",line,9);
381    addfield("!XDR (hex)",line,10);
382    fprintf(stdout,"%s\n",line);
383
384    count = (len / sizeof(int));
385    rem = (len % sizeof(int));
386    if(rem != 0)
387 fprintf(stderr,"ocdump: |mem|%%4 != 0\n");
388    imemory = (int*)memory;
389
390    for(i=0;i<count;i++) {
391 unsigned int vx = (unsigned int)imemory[i];
392 unsigned int v = vx;
393 if(!xxdr_network_orderswapinline32(&v);
394        line[0] = '\0';
395        sprintf(tmp,"%6d",i);
396        addfield(tmp,line,6);
397        sprintf(tmp,"%08x",vx);
398        addfield(tmp,line,9);
399        sprintf(tmp,"%08x",v);
400        addfield(tmp,line,10);
401        fprintf(stdout,"%s\n",line);
402    }
403    fflush(stdout);
404}
405
406void
407ocdumpmemory(char* memory, size_t len, int xdrencoded, int level)
408{
409    if(level > MAXLEVELlevel = MAXLEVEL;
410    switch (level) {
411    case 1: /* Do a multi-type dump */
412        typedmemorydump(memory,len,xdrencoded);
413 break;
414    case 0: /* Dump a simple linear list of the contents of the memory as 32-bit hex and decimal */
415    default:
416        simplememorydump(memory,len,xdrencoded);
417 break;
418    }
419}
420
421static OCerror
422ocreadfile(FILEfileoff_t datastart, char** memp, size_t* lenp)
423{
424    char* mem = NULL;
425    size_t len;
426    long red;
427    struct stat stats;
428    long pos;
429    OCerror stat = OC_NOERR;
430
431    pos = ftell(file);
432    if(pos < 0) {
433      fprintf(stderr,"ocreadfile: ftell error.\n");
434      stat = OC_ERCFILE;
435      goto done;
436    }
437
438    fseek(file,0,SEEK_SET);
439    if(fseek(file,(long)datastart,SEEK_SET) < 0) {
440 fprintf(stderr,"ocreadfile: fseek error.\n");
441 stat = OC_ERCFILE;
442 goto done;
443    }
444
445    if(fstat(fileno(file),&stats) < 0) {
446 fprintf(stderr,"ocreadfile: fstat error.\n");
447 stat = OC_ERCFILE;
448 goto done;
449    }
450    len = stats.st_size;
451    len -= datastart;
452
453    mem = (char*)calloc(len+1,1);
454    if(mem == NULL) {stat = OC_ENOMEM; goto done;}
455
456    /* Read only the data part */
457    red = fread(mem,1,len,file);
458    if(red < len) {
459 fprintf(stderr,"ocreadfile: short file\n");
460 stat = OC_ERCFILE;
461 goto done;
462    }
463
464    if(fseek(file,pos,SEEK_SET) < 0) {; /* leave it as we found it*/
465      fprintf(stderr,"ocreadfile: fseek error.\n");
466      stat = OC_ERCFILE;
467      goto done;
468    }
469    if(memp) {*memp = memmem = NULL;}
470    if(lenp) *lenp = len;
471
472 done:
473    if(mem != NULL)
474      free(mem);
475    return OCTHROW(stat);
476}
477
478void
479ocdd(OCstatestateOCnoderoot, int xdrencoded, int level)
480{
481    char* mem;
482    size_t len;
483    if(root->tree->data.file != NULL) {
484        if(!ocreadfile(root->tree->data.file,
485                       root->tree->data.bod,
486                       &mem,
487                       &len)) {
488          /* ocreadfile allocates memory that must be freed. */
489          if(mem != NULL) free(mem);
490          fprintf(stderr,"ocdd could not read data file\n");
491          return;
492        }
493        ocdumpmemory(mem,len,xdrencoded,level);
494        free(mem);
495    } else {
496        mem = root->tree->data.memory;
497        mem += root->tree->data.bod;
498        len = root->tree->data.datasize;
499        len -= root->tree->data.bod;
500        ocdumpmemory(mem,len,xdrencoded,level);
501    }
502}
503
504void
505ocdumpdata(OCstatestateOCdatadataOCbytesbuffer, int frominstance)
506{
507    char tmp[1024];
508    OCnodepattern = data->pattern;
509    snprintf(tmp,sizeof(tmp),"%lx:",(unsigned long)data);
510    ocbytescat(buffer,tmp);
511    if(!frominstance) {
512        ocbytescat(buffer," node=");
513        ocbytescat(buffer,pattern->name);
514    }
515    snprintf(tmp,sizeof(tmp)," xdroffset=%ld",(unsigned long)data->xdroffset);
516    ocbytescat(buffer,tmp);
517    if(data->pattern->octype == OC_Atomic) {
518        snprintf(tmp,sizeof(tmp)," xdrsize=%ld",(unsigned long)data->xdrsize);
519        ocbytescat(buffer,tmp);
520    }
521    if(ociscontainer(pattern->octype)) {
522        snprintf(tmp,sizeof(tmp)," ninstances=%d",(int)data->ninstances);
523        ocbytescat(buffer,tmp);
524    } else if(pattern->etype == OC_String || pattern->etype == OC_URL) {
525        snprintf(tmp,sizeof(tmp)," nstrings=%d",(int)data->nstrings);
526        ocbytescat(buffer,tmp);
527    }
528    ocbytescat(buffer," container=");
529    snprintf(tmp,sizeof(tmp),"%lx",(unsigned long)data->container);
530    ocbytescat(buffer,tmp);
531    ocbytescat(buffer," mode=");
532    ocbytescat(buffer,ocdtmodestring(data->datamode,0));
533}
534
535/*
536Depth Offset   Index Flags Size Type      Name
5370123456789012345678901234567890123456789012345
5380         1         2         3         4
539[001] 00000000 0000  FS    0000 Structure person
540*/
541static const int tabstops[] = {0,6,15,21,27,32,42};
542static const char* header =
543"Depth Offset   Index Flags Size Type     Name\n";
544
545void
546ocdumpdatatree(OCstatestateOCdatadataOCbytesbuffer, int depth)
547{
548    size_t i,rank;
549    OCnodepattern;
550    char tmp[1024];
551    size_t crossproduct;
552    int tabstop = 0;
553    const char* typename;
554
555    /* If this is the first call, then dump a header line */
556    if(depth == 0) {
557 ocbytescat(buffer,header);
558    }
559
560    /* get info about the pattern */
561    pattern = data->pattern;
562    rank = pattern->array.rank;
563
564    /* get total dimension size */
565    if(rank > 0)
566        crossproduct = octotaldimsize(pattern->array.rank,pattern->array.sizes);
567
568    /* Dump the depth first */
569    snprintf(tmp,sizeof(tmp),"[%03d]",depth);
570    ocbytescat(buffer,tmp);
571
572    tabto(tabstops[++tabstop],buffer);
573
574    snprintf(tmp,sizeof(tmp),"%08lu",(unsigned long)data->xdroffset);
575    ocbytescat(buffer,tmp);
576
577    tabto(tabstops[++tabstop],buffer);
578
579    /* Dump the Index wrt to parent, if defined */
580    if(fisset(data->datamode,OCDT_FIELD)
581       || fisset(data->datamode,OCDT_ELEMENT)
582       || fisset(data->datamode,OCDT_RECORD)) {
583        snprintf(tmp,sizeof(tmp),"%04lu ",(unsigned long)data->index);
584        ocbytescat(buffer,tmp);
585    }
586
587    tabto(tabstops[++tabstop],buffer);
588
589    /* Dump the mode flags in compact form */
590    ocbytescat(buffer,ocdtmodestring(data->datamode,1));
591
592    tabto(tabstops[++tabstop],buffer);
593
594    /* Dump the size or ninstances */
595    if(fisset(data->datamode,OCDT_ARRAY)
596       || fisset(data->datamode,OCDT_SEQUENCE)) {
597        snprintf(tmp,sizeof(tmp),"%04lu",(unsigned long)data->ninstances);
598    } else {
599        snprintf(tmp,sizeof(tmp),"%04lu",(unsigned long)data->xdrsize);
600    }
601    ocbytescat(buffer,tmp);
602
603    tabto(tabstops[++tabstop],buffer);
604
605    if(pattern->octype == OC_Atomic) {
606 typename = octypetoddsstring(pattern->etype);
607    } else { /*must be container*/
608 typename = octypetoddsstring(pattern->octype);
609    }
610    ocbytescat(buffer,typename);
611
612    tabto(tabstops[++tabstop],buffer);
613
614    if(!occopycat(tmp,sizeof(tmp),1,pattern->name))
615 return;
616    ocbytescat(buffer,tmp);
617
618    if(rank > 0) {
619 snprintf(tmp,sizeof(tmp),"[%lu]",(unsigned long)crossproduct);
620 ocbytescat(buffer,tmp);
621    }
622    ocbytescat(buffer,"\n");
623
624    /* dump the sub-instance, which might be fields, records, or elements */
625    if(!fisset(data->datamode,OCDT_ATOMIC)) {
626        for(i=0;i<data->ninstances;i++)
627     ocdumpdatatree(state,data->instances[i],buffer,depth+1);
628    }
629}
630
631void
632ocdumpdatapath(OCstatestateOCdatadataOCbytesbuffer)
633{
634    int i;
635    OCdatapath[1024];
636    char tmp[1024];
637    OCdatapathdata;
638    OCnodepattern;
639    int isrecord;
640
641    path[0] = data;
642    for(i=1;;i++) {
643 OCdatanext = path[i-1];
644 if(next->container == NULL) break;
645 path[i] = next->container;
646    }
647    /* Path is in reverse order */
648    for(i=i-1;i>=0;i--) {
649 pathdata = path[i];
650 pattern = pathdata->pattern;
651 ocbytescat(buffer,"/");
652 ocbytescat(buffer,pattern->name);
653 /* Check the mode of the next step in path */
654 if(i > 0) {
655     OCdatanext = path[i-1];
656     if(fisset(next->datamode,OCDT_FIELD)
657 || fisset(next->datamode,OCDT_ELEMENT)
658 || fisset(next->datamode,OCDT_RECORD)) {
659 snprintf(tmp,sizeof(tmp),".%lu",(unsigned long)next->index);
660         ocbytescat(buffer,tmp);
661     }
662 }
663 if(pattern->octype == OC_Atomic) {
664     if(pattern->array.rank > 0) {
665         off_t xproduct = octotaldimsize(pattern->array.rank,pattern->array.sizes);
666         snprintf(tmp,sizeof(tmp),"[0..%lu]",(unsigned long)xproduct-1);
667         ocbytescat(buffer,tmp);
668     }
669 }
670 isrecord = 0;
671 if(pattern->octype == OC_Sequence) {
672     /* Is this a record or a sequence ? */
673     isrecord = (fisset(pathdata->datamode,OCDT_RECORD) ? 1 : 0);
674 }
675    }
676    /* Add suffix to path */
677    if(ociscontainer(pattern->octype)) {
678        /* add the container type, except distinguish record and sequence */
679 ocbytescat(buffer,":");
680 if(isrecord)
681     ocbytescat(buffer,"Record");
682 else
683     ocbytescat(buffer,octypetoddsstring(pattern->octype));
684    } else if(ocisatomic(pattern->octype)) {
685 /* add the atomic etype */
686 ocbytescat(buffer,":");
687 ocbytescat(buffer,octypetoddsstring(pattern->etype));
688    }
689    snprintf(tmp,sizeof(tmp),"->0x%0lx",(unsigned long)pathdata);
690    ocbytescat(buffer,tmp);
691}


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