ocdump.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
  2. See the COPYRIGHT file for more information.
  3. */
  4. #include "config.h"
  5. #include <sys/stat.h>
  6. #ifdef NETINET_IN_H
  7. #include <netinet/in.h>
  8. #endif
  9. #include "ocinternal.h"
  10. #include "ocdata.h"
  11. #include "ocdebug.h"
  12. #define MAXLEVEL 1
  13. /*Forward*/
  14. static void dumpocnode1(OCnode* node, int depth);
  15. static void dumpdimensions(OCnode* node);
  16. static void dumpattvalue(OCtype nctype, char** aset, int index);
  17. static char* sindent = NULL;
  18. static char*
  19. dent(int n)
  20. {
  21. if(sindent == NULL) {
  22. sindent = (char*)ocmalloc(102);
  23. MEMCHECK(sindent,NULL);
  24. memset((void*)sindent,(int)' ',(size_t)101);
  25. sindent[101] = '\0';
  26. }
  27. if(n > 100) n = 100;
  28. return sindent+(100-n);
  29. }
  30. /* support [dd] leader*/
  31. static char*
  32. dent2(int n) {return dent(n+4);}
  33. void
  34. ocdumpnode(OCnode* node)
  35. {
  36. if(node != NULL) {
  37. dumpocnode1(node,0);
  38. } else {
  39. fprintf(stdout,"<NULL>\n");
  40. }
  41. fflush(stdout);
  42. }
  43. static void
  44. dumpskip(OCnode* node)
  45. {
  46. char tmpc[64];
  47. char tmpi[64];
  48. char tmpt[64];
  49. char tmpo[64];
  50. if(node->skip.count == OCINDETERMINATE)
  51. strcpy(tmpc,"?");
  52. else
  53. snprintf(tmpc,sizeof(tmpc),"%lu",(unsigned long)node->skip.count);
  54. if(node->skip.instancesize == OCINDETERMINATE)
  55. strcpy(tmpi,"?");
  56. else
  57. snprintf(tmpi,sizeof(tmpi),"%lu",(unsigned long)node->skip.instancesize);
  58. if(node->skip.totalsize == OCINDETERMINATE)
  59. strcpy(tmpt,"?");
  60. else
  61. snprintf(tmpt,sizeof(tmpt),"%lu",(unsigned long)node->skip.totalsize);
  62. if(node->skip.offset == OCINDETERMINATE)
  63. strcpy(tmpo,"?");
  64. else
  65. snprintf(tmpo,sizeof(tmpo),"%lu",(unsigned long)node->skip.offset);
  66. fprintf(stdout," [(%s*%s)/%s@%s]",tmpi,tmpc,tmpt,tmpo);
  67. }
  68. static void
  69. dumpocnode1(OCnode* node, int depth)
  70. {
  71. unsigned int n;
  72. switch (node->octype) {
  73. case OC_Primitive: {
  74. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  75. if(node->name == NULL) OCPANIC("prim without name");
  76. fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
  77. dumpdimensions(node);
  78. #ifdef OCIGNORE
  79. if(node->cache.cacheable) fprintf(stdout," [cached]");
  80. #endif
  81. dumpskip(node);
  82. fprintf(stdout," &%lx",(unsigned long)node);
  83. fprintf(stdout,"\n");
  84. } break;
  85. case OC_Dataset: {
  86. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  87. fprintf(stdout,"dataset %s\n",
  88. (node->name?node->name:""));
  89. for(n=0;n<oclistlength(node->subnodes);n++) {
  90. dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
  91. }
  92. } break;
  93. case OC_Structure: {
  94. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  95. fprintf(stdout,"struct %s",
  96. (node->name?node->name:""));
  97. dumpdimensions(node);
  98. dumpskip(node);
  99. fprintf(stdout," &%lx",(unsigned long)node);
  100. fprintf(stdout,"\n");
  101. for(n=0;n<oclistlength(node->subnodes);n++) {
  102. dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
  103. }
  104. } break;
  105. case OC_Sequence: {
  106. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  107. fprintf(stdout,"sequence %s",
  108. (node->name?node->name:""));
  109. dumpdimensions(node);
  110. dumpskip(node);
  111. fprintf(stdout," &%lx",(unsigned long)node);
  112. fprintf(stdout,"\n");
  113. for(n=0;n<oclistlength(node->subnodes);n++) {
  114. dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
  115. }
  116. } break;
  117. case OC_Grid: {
  118. unsigned int i;
  119. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  120. fprintf(stdout,"grid %s",
  121. (node->name?node->name:""));
  122. dumpdimensions(node);
  123. dumpskip(node);
  124. fprintf(stdout," &%lx",(unsigned long)node);
  125. fprintf(stdout,"\n");
  126. fprintf(stdout,"%sarray:\n",dent2(depth+1));
  127. dumpocnode1((OCnode*)oclistget(node->subnodes,0),depth+2);
  128. fprintf(stdout,"%smaps:\n",dent2(depth+1));
  129. for(i=1;i<oclistlength(node->subnodes);i++) {
  130. dumpocnode1((OCnode*)oclistget(node->subnodes,i),depth+2);
  131. }
  132. } break;
  133. case OC_Attribute: {
  134. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  135. if(node->name == NULL) OCPANIC("Attribute without name");
  136. fprintf(stdout,"%s %s",octypetostring(node->etype),node->name);
  137. for(n=0;n<oclistlength(node->att.values);n++) {
  138. char* value = (char*)oclistget(node->att.values,n);
  139. if(n > 0) fprintf(stdout,",");
  140. fprintf(stdout," %s",value);
  141. }
  142. fprintf(stdout," &%lx",(unsigned long)node);
  143. fprintf(stdout,"\n");
  144. } break;
  145. case OC_Attributeset: {
  146. fprintf(stdout,"[%2d]%s ",depth,dent(depth));
  147. fprintf(stdout,"%s:\n",node->name?node->name:"Attributes");
  148. for(n=0;n<oclistlength(node->subnodes);n++) {
  149. dumpocnode1((OCnode*)oclistget(node->subnodes,n),depth+1);
  150. }
  151. } break;
  152. default:
  153. OCPANIC1("encountered unexpected node type: %x",node->octype);
  154. }
  155. if(node->attributes != NULL) {
  156. unsigned int i;
  157. for(i=0;i<oclistlength(node->attributes);i++) {
  158. OCattribute* att = (OCattribute*)oclistget(node->attributes,i);
  159. fprintf(stdout,"%s[%s=",dent2(depth+2),att->name);
  160. if(att->nvalues == 0)
  161. OCPANIC("Attribute.nvalues == 0");
  162. if(att->nvalues == 1) {
  163. dumpattvalue(att->etype,att->values,0);
  164. } else {
  165. unsigned int j;
  166. fprintf(stdout,"{");
  167. for(j=0;j<att->nvalues;j++) {
  168. if(j>0) fprintf(stdout,", ");
  169. dumpattvalue(att->etype,att->values,j);
  170. }
  171. fprintf(stdout,"}");
  172. }
  173. fprintf(stdout,"]\n");
  174. }
  175. }
  176. }
  177. static void
  178. dumpdimensions(OCnode* node)
  179. {
  180. unsigned int i;
  181. for(i=0;i<node->array.rank;i++) {
  182. OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
  183. fprintf(stdout,"[%s=%lu]",
  184. (dim->name?dim->name:"?"),
  185. (unsigned long)dim->dim.declsize);
  186. }
  187. }
  188. static void
  189. dumpattvalue(OCtype nctype, char** strings, int index)
  190. {
  191. if(nctype == OC_String || nctype == OC_URL) {
  192. fprintf(stdout,"\"%s\"",strings[index]);
  193. } else {
  194. fprintf(stdout,"%s",strings[index]);
  195. }
  196. }
  197. void
  198. ocdumpslice(OCslice* slice)
  199. {
  200. fprintf(stdout,"[");
  201. fprintf(stdout,"%lu",(unsigned long)slice->first);
  202. if(slice->stride > 1) fprintf(stdout,":%lu",(unsigned long)slice->stride);
  203. fprintf(stdout,":%lu",(unsigned long)(slice->first+slice->count)-1);
  204. fprintf(stdout,"]");
  205. }
  206. void
  207. ocdumpclause(OCprojectionclause* ref)
  208. {
  209. unsigned int i;
  210. OClist* path = oclistnew();
  211. occollectpathtonode(ref->node,path);
  212. for(i=0;i<oclistlength(path);i++) {
  213. OClist* sliceset;
  214. OCnode* node = (OCnode*)oclistget(path,i);
  215. if(node->tree != NULL) continue; /* leave off the root node*/
  216. fprintf(stdout,"%s%s",(i>0?PATHSEPARATOR:""),node->name);
  217. sliceset = (OClist*)oclistget(ref->indexsets,i);
  218. if(sliceset != NULL) {
  219. unsigned int j;
  220. for(j=0;j<oclistlength(sliceset);j++) {
  221. OCslice* slice = (OCslice*)oclistget(sliceset,j);
  222. ocdumpslice(slice);
  223. }
  224. }
  225. }
  226. }
  227. static void
  228. addfield(char* field, char* line, int align)
  229. {
  230. int len,rem;
  231. strcat(line,"|");
  232. strcat(line,field);
  233. len = strlen(field);
  234. rem = (align - len);
  235. while(rem-- > 0) strcat(line," ");
  236. }
  237. static void
  238. dumpfield(int index, char* n8, int isxdr)
  239. {
  240. char line[1024];
  241. char tmp[32];
  242. union {
  243. unsigned int uv;
  244. int sv;
  245. char cv[4];
  246. float fv;
  247. } form;
  248. union {
  249. char cv[8];
  250. unsigned long long ll;
  251. double d;
  252. } dform;
  253. line[0] = '\0';
  254. /* offset */
  255. sprintf(tmp,"%6d",index);
  256. addfield(tmp,line,5);
  257. memcpy(form.cv,n8,4);
  258. /* straight hex*/
  259. sprintf(tmp,"%08x",form.uv);
  260. addfield(tmp,line,8);
  261. if(isxdr) {swapinline32(&form.uv);}
  262. /* unsigned integer */
  263. sprintf(tmp,"%12u",form.uv);
  264. addfield(tmp,line,12);
  265. /* signed integer */
  266. sprintf(tmp,"%12d",form.sv);
  267. addfield(tmp,line,12);
  268. /* float */
  269. sprintf(tmp,"%#g",form.fv);
  270. addfield(tmp,line,12);
  271. /* char[4] */
  272. {
  273. /* use raw form (i.e. n8)*/
  274. int i;
  275. tmp[0] = '\0';
  276. for(i=0;i<4;i++) {
  277. char stmp[64];
  278. unsigned int c = (n8[i] & 0xff);
  279. if(c < ' ' || c > 126)
  280. sprintf(stmp,"\\%02x",c);
  281. else
  282. sprintf(stmp,"%c",c);
  283. strcat(tmp,stmp);
  284. }
  285. }
  286. addfield(tmp,line,16);
  287. /* double */
  288. memcpy(dform.cv,n8,2*XDRUNIT);
  289. if(isxdr) xxdrntohdouble(dform.cv,&dform.d);
  290. sprintf(tmp,"%#g",dform.d);
  291. addfield(tmp,line,12);
  292. fprintf(stdout,"%s\n",line);
  293. }
  294. static void
  295. typedmemorydump(char* memory, size_t len, int fromxdr)
  296. {
  297. unsigned int i,count,rem;
  298. char line[1024];
  299. char* pmem;
  300. char mem[8];
  301. assert(memory[len] == 0);
  302. /* build the header*/
  303. line[0] = '\0';
  304. addfield("offset",line,6);
  305. addfield("hex",line,8);
  306. addfield("uint",line,12);
  307. addfield("int",line,12);
  308. addfield("float",line,12);
  309. addfield("char[4]",line,16);
  310. addfield("double",line,12);
  311. strcat(line,"\n");
  312. fprintf(stdout,"%s",line);
  313. count = (len / sizeof(int));
  314. rem = (len % sizeof(int));
  315. for(pmem=memory,i=0;i<count;i++,pmem+=4) {
  316. memset(mem,0,8);
  317. if(i<(count-1))
  318. memcpy(mem,pmem,8);
  319. else
  320. memcpy(mem,pmem,4);
  321. dumpfield(i*sizeof(unsigned int),mem,fromxdr);
  322. }
  323. if(rem > 0) {
  324. memset(mem,0,8);
  325. memcpy(mem,pmem,4);
  326. dumpfield(i*sizeof(unsigned int),mem,fromxdr);
  327. }
  328. fflush(stdout);
  329. }
  330. static void
  331. simplememorydump(char* memory, size_t len, int fromxdr)
  332. {
  333. unsigned int i,count,rem;
  334. int* imemory;
  335. char tmp[32];
  336. char line[1024];
  337. assert(memory[len] == 0);
  338. /* build the header*/
  339. line[0] = '\0';
  340. addfield("offset",line,6);
  341. addfield("XDR (hex)",line,9);
  342. addfield("!XDR (hex)",line,10);
  343. fprintf(stdout,"%s\n",line);
  344. count = (len / sizeof(int));
  345. rem = (len % sizeof(int));
  346. if(rem != 0)
  347. fprintf(stderr,"ocdump: |mem|%%4 != 0\n");
  348. imemory = (int*)memory;
  349. for(i=0;i<count;i++) {
  350. unsigned int vx = (unsigned int)imemory[i];
  351. unsigned int v = vx;
  352. if(!xxdr_network_order) swapinline32(&v);
  353. line[0] = '\0';
  354. sprintf(tmp,"%6d",i);
  355. addfield(tmp,line,6);
  356. sprintf(tmp,"%08x",vx);
  357. addfield(tmp,line,9);
  358. sprintf(tmp,"%08x",v);
  359. addfield(tmp,line,10);
  360. fprintf(stdout,"%s\n",line);
  361. }
  362. fflush(stdout);
  363. }
  364. void
  365. ocdumpmemory(char* memory, size_t len, int xdrencoded, int level)
  366. {
  367. if(level > MAXLEVEL) level = MAXLEVEL;
  368. switch (level) {
  369. case 1: /* Do a multi-type dump */
  370. typedmemorydump(memory,len,xdrencoded);
  371. break;
  372. case 0: /* Dump a simple linear list of the contents of the memory as 32-bit hex and decimal */
  373. default:
  374. simplememorydump(memory,len,xdrencoded);
  375. break;
  376. }
  377. }
  378. static int
  379. ocreadfile(FILE* file, int datastart, char** memp, size_t* lenp)
  380. {
  381. char* mem;
  382. size_t len;
  383. size_t pos;
  384. size_t red;
  385. struct stat stats;
  386. pos = ftell(file);
  387. fseek(file,0,SEEK_SET);
  388. fseek(file,datastart,SEEK_SET);
  389. fstat(fileno(file),&stats);
  390. len = stats.st_size;
  391. len -= datastart;
  392. mem = (char*)calloc(len+1,1);
  393. if(mem == NULL) return 0;
  394. /* Read only the data part */
  395. red = fread(mem,1,len,file);
  396. if(red < len) {
  397. fprintf(stderr,"ocreadfile: short file\n");
  398. return 0;
  399. }
  400. fseek(file,pos,SEEK_SET); /* leave it as we found it*/
  401. if(memp) *memp = mem;
  402. if(lenp) *lenp = len;
  403. return 1;
  404. }
  405. void
  406. ocdd(OCstate* state, OCnode* root, int xdrencoded, int level)
  407. {
  408. char* mem;
  409. size_t len;
  410. if(root->tree->data.file != NULL) {
  411. if(!ocreadfile(root->tree->data.file,root->tree->data.bod,&mem,&len)) {
  412. fprintf(stderr,"ocdd could not read data file\n");
  413. return;
  414. }
  415. ocdumpmemory(mem,len,xdrencoded,level);
  416. free(mem);
  417. } else {
  418. mem = root->tree->data.memory;
  419. mem += root->tree->data.bod;
  420. len = root->tree->data.datasize;
  421. len -= root->tree->data.bod;
  422. ocdumpmemory(mem,len,xdrencoded,level);
  423. }
  424. }