cdf3.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /*********************************************************************
  2. * Copyright 1993, UCAR/Unidata
  3. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. * $Header: /upc/share/CVS/netcdf-3/libncdap3/cdf3.c,v 1.33 2009/12/03 03:42:37 dmh Exp $
  5. *********************************************************************/
  6. #include "ncdap3.h"
  7. #include "daputil.h"
  8. #include "dapdump.h"
  9. CDFnode* v4node = NULL;
  10. /* Forward*/
  11. static NCerror sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq);
  12. static NCerror regrid3r(CDFnode*, CDFnode*, NClist*);
  13. static NCerror testregrid3(CDFnode* node, CDFnode* template, NClist*);
  14. static CDFnode* makenewgrid3(CDFnode* node, CDFnode* template);
  15. static NCerror regridinsert(CDFnode* newgrid, CDFnode* node);
  16. static NCerror regridremove(CDFnode* newgrid, CDFnode* node);
  17. static NCerror mapnodes3r(CDFnode*, CDFnode*, int depth);
  18. static NCerror mapfcn(CDFnode* dstnode, CDFnode* srcnode);
  19. static NCerror definedimsetplus3(NCDAPCOMMON* nccomm, CDFnode* node);
  20. static NCerror definedimsetall3(NCDAPCOMMON* nccomm, CDFnode* node);
  21. /* Accumulate useful node sets */
  22. NCerror
  23. computecdfnodesets3(NCDAPCOMMON* nccomm)
  24. {
  25. unsigned int i;
  26. NClist* varnodes = nclistnew();
  27. NClist* allnodes = nccomm->cdf.ddsroot->tree->nodes;
  28. if(nccomm->cdf.seqnodes == NULL) nccomm->cdf.seqnodes = nclistnew();
  29. if(nccomm->cdf.gridnodes == NULL) nccomm->cdf.gridnodes = nclistnew();
  30. nclistclear(nccomm->cdf.seqnodes);
  31. nclistclear(nccomm->cdf.gridnodes);
  32. computevarnodes3(nccomm,allnodes,varnodes);
  33. nclistfree(nccomm->cdf.varnodes);
  34. nccomm->cdf.varnodes = varnodes;
  35. /* Now compute other sets of interest */
  36. for(i=0;i<nclistlength(allnodes);i++) {
  37. CDFnode* node = (CDFnode*)nclistget(allnodes,i);
  38. if(!node->visible) continue;
  39. switch (node->nctype) {
  40. case NC_Sequence:
  41. nclistpush(nccomm->cdf.seqnodes,(ncelem)node);
  42. break;
  43. case NC_Grid:
  44. nclistpush(nccomm->cdf.gridnodes,(ncelem)node);
  45. break;
  46. default: break;
  47. }
  48. }
  49. return NC_NOERR;
  50. }
  51. NCerror
  52. computevarnodes3(NCDAPCOMMON* nccomm, NClist* allnodes, NClist* varnodes)
  53. {
  54. unsigned int i,len;
  55. NClist* allvarnodes = nclistnew();
  56. for(i=0;i<nclistlength(allnodes);i++) {
  57. CDFnode* node = (CDFnode*)nclistget(allnodes,i);
  58. /* If this node has a bad name, repair it */
  59. if(dap_badname(node->ocname)) {
  60. char* newname = dap_repairname(node->ocname);
  61. nullfree(node->ocname);
  62. node->ocname = newname;
  63. }
  64. if(!node->visible) continue;
  65. if(node->nctype == NC_Primitive)
  66. nclistpush(allvarnodes,(ncelem)node);
  67. }
  68. /* Further process the variable nodes to get the final set */
  69. /* Use toplevel vars first */
  70. len = nclistlength(allvarnodes);
  71. for(i=0;i<len;i++) {
  72. CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
  73. if(node == NULL) continue;
  74. if(daptoplevel(node)) {
  75. nclistpush(varnodes,(ncelem)node);
  76. nclistset(allvarnodes,i,(ncelem)NULL);
  77. }
  78. }
  79. /*... then grid arrays and maps.
  80. but exclude the coordinate variables if we are trying to
  81. exactly mimic nc-dap
  82. */
  83. for(i=0;i<len;i++) {
  84. CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
  85. if(node == NULL) continue;
  86. if(dapgridarray(node)) {
  87. nclistpush(varnodes,(ncelem)node);
  88. nclistset(allvarnodes,i,(ncelem)NULL);
  89. } else if(dapgridmap(node)) {
  90. if(!FLAGSET(nccomm->controls,NCF_NCDAP))
  91. nclistpush(varnodes,(ncelem)node);
  92. nclistset(allvarnodes,i,(ncelem)NULL);
  93. }
  94. }
  95. /*... then all others */
  96. for(i=0;i<len;i++) {
  97. CDFnode* node = (CDFnode*)nclistget(allvarnodes,i);
  98. if(node == NULL) continue;
  99. nclistpush(varnodes,(ncelem)node);
  100. }
  101. nclistfree(allvarnodes);
  102. #ifdef DEBUG2
  103. for(i=0;i<nclistlength(varnodes);i++) {
  104. CDFnode* node = (CDFnode*)nclistget(varnodes,i);
  105. if(node == NULL) continue;
  106. fprintf(stderr,"computevarnodes: var: %s\n",makecdfpathstring3(node,"."));
  107. }
  108. #endif
  109. return NC_NOERR;
  110. }
  111. NCerror
  112. fixgrids3(NCDAPCOMMON* nccomm)
  113. {
  114. unsigned int i;
  115. NClist* gridnodes = nccomm->cdf.gridnodes;
  116. for(i=0;i<nclistlength(gridnodes);i++) {
  117. CDFnode* grid = (CDFnode*)nclistget(gridnodes,i);
  118. (void)fixgrid34(nccomm,grid);
  119. /* Ignore mal-formed grids */
  120. }
  121. return NC_NOERR;
  122. }
  123. /*
  124. Figure out the names for variables.
  125. */
  126. NCerror
  127. computecdfvarnames3(NCDAPCOMMON* nccomm, CDFnode* root, NClist* varnodes)
  128. {
  129. unsigned int i,j,d;
  130. /* clear all elided marks; except for dataset and grids */
  131. for(i=0;i<nclistlength(root->tree->nodes);i++) {
  132. CDFnode* node = (CDFnode*)nclistget(root->tree->nodes,i);
  133. node->elided = 0;
  134. if(node->nctype == NC_Grid || node->nctype == NC_Dataset)
  135. node->elided = 1;
  136. }
  137. /* ensure all variables have an initial full name defined */
  138. for(i=0;i<nclistlength(varnodes);i++) {
  139. CDFnode* var = (CDFnode*)nclistget(varnodes,i);
  140. nullfree(var->ncfullname);
  141. var->ncfullname = makecdfpathstring3(var,nccomm->cdf.separator);
  142. #ifdef DEBUG2
  143. fprintf(stderr,"var names: %s %s %s\n",
  144. var->ocname,var->ncbasename,var->ncfullname);
  145. #endif
  146. }
  147. /* unify all variables with same fullname and dimensions
  148. basevar fields says: "for duplicate grid variables";
  149. when does this happen?
  150. */
  151. if(FLAGSET(nccomm->controls,NCF_NC3)) {
  152. for(i=0;i<nclistlength(varnodes);i++) {
  153. int match;
  154. CDFnode* var = (CDFnode*)nclistget(varnodes,i);
  155. for(j=0;j<i;j++) {
  156. CDFnode* testnode = (CDFnode*)nclistget(varnodes,j);
  157. match = 1;
  158. if(testnode->array.basevar != NULL)
  159. continue; /* already processed */
  160. if(strcmp(var->ncfullname,testnode->ncfullname) != 0)
  161. match = 0;
  162. else if(nclistlength(testnode->array.dimsetall)
  163. != nclistlength(var->array.dimsetall))
  164. match = 0;
  165. else for(d=0;d<nclistlength(testnode->array.dimsetall);d++) {
  166. CDFnode* vdim = (CDFnode*)nclistget(var->array.dimsetall,d);
  167. CDFnode* tdim = (CDFnode*)nclistget(testnode->array.dimsetall,d);
  168. if(vdim->dim.declsize != tdim->dim.declsize) {
  169. match = 0;
  170. break;
  171. }
  172. }
  173. if(match) {
  174. testnode->array.basevar = var;
  175. fprintf(stderr,"basevar invoked: %s\n",var->ncfullname);
  176. }
  177. }
  178. }
  179. }
  180. /* Finally, verify unique names */
  181. for(i=0;i<nclistlength(varnodes);i++) {
  182. CDFnode* var1 = (CDFnode*)nclistget(varnodes,i);
  183. if(var1->array.basevar != NULL) continue;
  184. for(j=0;j<i;j++) {
  185. CDFnode* var2 = (CDFnode*)nclistget(varnodes,j);
  186. if(var2->array.basevar != NULL) continue;
  187. if(strcmp(var1->ncfullname,var2->ncfullname)==0) {
  188. PANIC1("duplicate var names: %s",var1->ncfullname);
  189. }
  190. }
  191. }
  192. return NC_NOERR;
  193. }
  194. /* locate and connect usable sequences and vars.
  195. A sequence is usable iff:
  196. 1. it has a path from one of its subnodes to a leaf and that
  197. path does not contain a sequence.
  198. 2. No parent container has dimensions.
  199. */
  200. NCerror
  201. sequencecheck3(NCDAPCOMMON* nccomm)
  202. {
  203. (void)sequencecheck3r(nccomm->cdf.ddsroot,nccomm->cdf.varnodes,NULL);
  204. return NC_NOERR;
  205. }
  206. static NCerror
  207. sequencecheck3r(CDFnode* node, NClist* vars, CDFnode* topseq)
  208. {
  209. unsigned int i;
  210. NCerror err = NC_NOERR;
  211. int ok = 0;
  212. if(topseq == NULL && nclistlength(node->array.dimset0) > 0) {
  213. err = NC_EINVAL; /* This container has dimensions, so no sequence within it
  214. can be usable */
  215. } else if(node->nctype == NC_Sequence) {
  216. /* Recursively walk the path for each subnode of this sequence node
  217. looking for a path without any sequence */
  218. for(i=0;i<nclistlength(node->subnodes);i++) {
  219. CDFnode* sub = (CDFnode*)nclistget(node->subnodes,i);
  220. err = sequencecheck3r(sub,vars,node);
  221. if(err == NC_NOERR) ok = 1; /* there is at least 1 usable var below */
  222. }
  223. if(topseq == NULL && ok == 1) {
  224. /* this sequence is usable because it has scalar container
  225. (by construction) and has a path to a leaf without an intermediate
  226. sequence. */
  227. err = NC_NOERR;
  228. node->usesequence = 1;
  229. } else {
  230. /* this sequence is unusable because it has no path
  231. to a leaf without an intermediate sequence. */
  232. node->usesequence = 0;
  233. err = NC_EINVAL;
  234. }
  235. } else if(nclistcontains(vars,(ncelem)node)) {
  236. /* If we reach a leaf, then topseq is usable, so save it */
  237. node->array.sequence = topseq;
  238. } else { /* Some kind of non-sequence container node with no dimensions */
  239. /* recursively compute usability */
  240. for(i=0;i<nclistlength(node->subnodes);i++) {
  241. CDFnode* sub = (CDFnode*)nclistget(node->subnodes,i);
  242. err = sequencecheck3r(sub,vars,topseq);
  243. if(err == NC_NOERR) ok = 1;
  244. }
  245. err = (ok?NC_NOERR:NC_EINVAL);
  246. }
  247. return err;
  248. }
  249. /*
  250. OPeNDAP is in the process of changing servers so that
  251. partial grids are converted to structures. However, not all
  252. servers do this: some elide the grid altogether, which can
  253. lead to ambiguities. Handle this last case by attempting to
  254. convert the elided case to look like the newer structure
  255. case. [for some reason, this code has been difficult to get
  256. right; I have rewritten 6 times and it probably is still not
  257. right.]
  258. Input is
  259. (1) the root of the dds that needs to be re-gridded
  260. (2) the full datadds tree that defines where the grids are.
  261. (3) the projections that were used to produce (1) from (2).
  262. */
  263. NCerror
  264. regrid3(CDFnode* ddsroot, CDFnode* template, NClist* projections)
  265. {
  266. NCerror ncstat = NC_NOERR;
  267. NClist* newgrids = nclistnew();
  268. /* The current regrid assumes that the ddsroot tree
  269. has missing grids compared to the template.
  270. It is also assumed that order of the nodes
  271. in the ddsroot is the same as in the template.
  272. */
  273. if(ddsroot->tree->regridded) return NC_NOERR;
  274. #ifdef DEBUG
  275. fprintf(stderr,"regrid: ddsroot=%s\n",dumptree(ddsroot));
  276. fprintf(stderr,"regrid: template=%s\n",dumptree(template));
  277. #endif
  278. #ifdef PROJECTED
  279. /* turn off the projection tag for all nodes */
  280. unprojected3(template->tree->nodes);
  281. /* Set the projection flag for all paths of all nodes
  282. that are referenced in the projections that produced ddsroot.
  283. This includes containers and subnodes. If there are no
  284. projections then mark all nodes
  285. */
  286. projectall3(template->tree->nodes);
  287. #endif
  288. if(simplenodematch34(ddsroot,template)) {
  289. ncstat = regrid3r(ddsroot,template,newgrids);
  290. ddsroot->tree->regridded = 1;
  291. } else
  292. ncstat = NC_EINVAL;
  293. nclistfree(newgrids);
  294. return ncstat;
  295. }
  296. #ifdef PROJECTED
  297. static void
  298. unprojected3(NClist* nodes)
  299. {
  300. int i;
  301. for(i=0;i<nclistlength(nodes);i++) {
  302. CDFnode* node = (CDFnode*)nclistget(nodes,i);
  303. node->projected = 0;
  304. }
  305. }
  306. static void
  307. projectall3(NClist* nodes)
  308. {
  309. int i;
  310. for(i=0;i<nclistlength(nodes);i++) {
  311. CDFnode* node = (CDFnode*)nclistget(nodes,i);
  312. node->projected = 1;
  313. }
  314. }
  315. static void
  316. projection3r(CDFnode* node)
  317. {
  318. int i;
  319. NClist* path = nclistnew();
  320. collectnodepath3(node,path,!WITHDATASET);
  321. for(i=0;i<nclistlength(path);i++) {
  322. CDFnode* pathnode = (CDFnode*)nclistget(path,i);
  323. #ifdef DEBUG
  324. if(pathnode->projected == 0)
  325. fprintf(stderr,"projection: %s\n",makesimplepathstring3(pathnode));
  326. #endif
  327. pathnode->projected = 1;
  328. }
  329. /* Now tag everything below me */
  330. for(i=0;i<nclistlength(node->subnodes);i++) {
  331. CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,i);
  332. projection3r(subnode);
  333. }
  334. nclistfree(path);
  335. }
  336. #endif /*PROJECTED*/
  337. /*
  338. Add in virtual structure nodes so that
  339. old style constrainted DDS and DATADDS
  340. look like the new style with structures.
  341. */
  342. static NCerror
  343. regrid3r(CDFnode* node, CDFnode* template, NClist* gridnodes)
  344. {
  345. unsigned int inode, itemp;
  346. NCerror ncstat = NC_NOERR;
  347. /* Try to match node's subnodes to a subset of the
  348. template subnodes
  349. */
  350. #ifdef DEBUG
  351. fprintf(stderr,"regrid: matched: %s -> %s\n",
  352. node->ocname,template->ocname);
  353. #endif
  354. for(inode=0;inode<nclistlength(node->subnodes);inode++) {
  355. CDFnode* subnode = (CDFnode*)nclistget(node->subnodes,inode);
  356. int match = 0;
  357. for(itemp=0;itemp<nclistlength(template->subnodes);itemp++) {
  358. CDFnode* subtemp = (CDFnode*)nclistget(template->subnodes,itemp);
  359. if(
  360. #ifdef PROJECTED
  361. subtemp->projected &&
  362. #endif
  363. simplenodematch34(subnode,subtemp)) {
  364. ncstat = regrid3r(subnode,subtemp,gridnodes);
  365. if(ncstat != NC_NOERR) return THROW(ncstat);
  366. match = 1;
  367. #ifdef PROJECTED
  368. subtemp->projected = 0; /*make sure we dont reuse this node*/
  369. #endif
  370. break;
  371. }
  372. }
  373. if(!match) { /* subnode has no match */
  374. /* ok, see if we can regrid */
  375. for(itemp=0;itemp<nclistlength(template->subnodes);itemp++) {
  376. CDFnode* subtemp = (CDFnode*)nclistget(template->subnodes,itemp);
  377. #ifdef DEBUG
  378. fprintf(stderr,"regrid: inside: %s.%s :: %s.%s\n",
  379. node->ocname,subnode->ocname,
  380. template->ocname,subtemp->ocname);
  381. #endif
  382. if(subtemp->nctype != NC_Grid)
  383. continue;
  384. #ifdef PROJECTED
  385. if(!subtemp->projected) continue;
  386. #endif
  387. ncstat = testregrid3(subnode,subtemp,gridnodes);
  388. if(ncstat == NC_NOERR) {match=1; break;}
  389. }
  390. if(!match) {/* really no match */
  391. ncstat = THROW(NC_EDDS); /* no match */
  392. }
  393. }
  394. }
  395. return THROW(ncstat);
  396. }
  397. /* See if this node can match a subnode of the template
  398. as a grid, and if so, then rebuild the node graph.
  399. */
  400. static NCerror
  401. testregrid3(CDFnode* node, CDFnode* template, NClist* gridnodes)
  402. {
  403. int i,match;
  404. NCerror ncstat = NC_NOERR;
  405. ASSERT((template->nctype == NC_Grid));
  406. { /* try to match inside the grid */
  407. for(match=0,i=0;i<nclistlength(template->subnodes);i++) {
  408. CDFnode* gridelem = (CDFnode*)nclistget(template->subnodes,i);
  409. if(!simplenodematch34(gridelem,node))
  410. continue;
  411. ncstat = regrid3r(node,gridelem,gridnodes);
  412. if(ncstat == NC_NOERR) {
  413. /* create new grid node if not already created */
  414. CDFnode* newgrid = NULL;
  415. match = 1;
  416. for(i=0;i<nclistlength(gridnodes);i++) {
  417. newgrid = (CDFnode*)nclistget(gridnodes,i);
  418. if(newgrid->template == template) break;
  419. newgrid = NULL;
  420. }
  421. if(newgrid == NULL) {
  422. newgrid = makenewgrid3(node,template);
  423. if(newgrid == NULL) {ncstat = NC_ENOMEM; goto done;}
  424. /* Insert the grid into node's parent */
  425. regridinsert(newgrid,node);
  426. nclistpush(gridnodes,(ncelem)newgrid);
  427. nclistpush(node->root->tree->nodes,(ncelem)newgrid);
  428. }
  429. regridremove(newgrid, node);
  430. node->container = newgrid;
  431. nclistpush(newgrid->subnodes,(ncelem)node);
  432. break; /* done with node */
  433. }
  434. }
  435. }
  436. if(!match) ncstat = NC_EDDS;
  437. done:
  438. return ncstat;
  439. }
  440. static CDFnode*
  441. makenewgrid3(CDFnode* node, CDFnode* template)
  442. {
  443. CDFnode* newgrid;
  444. newgrid = (CDFnode*)calloc(1,sizeof(CDFnode));
  445. if(newgrid == NULL) return NULL;
  446. memset((void*)newgrid,0,sizeof(CDFnode));
  447. newgrid->virtual = 1;
  448. newgrid->ocname = nulldup(template->ocname);
  449. newgrid->ncbasename = nulldup(template->ncbasename);
  450. newgrid->nctype = NC_Grid;
  451. newgrid->subnodes = nclistnew();
  452. newgrid->container = node->container;
  453. newgrid->template = template;
  454. return newgrid;
  455. }
  456. static NCerror
  457. regridinsert(CDFnode* newgrid, CDFnode* node)
  458. {
  459. int i;
  460. CDFnode* parent;
  461. /* Locate the index of the node in its current parent */
  462. parent = node->container;
  463. for(i=0;i<nclistlength(parent->subnodes);i++) {
  464. CDFnode* subnode = (CDFnode*)nclistget(parent->subnodes,i);
  465. if(subnode == node) {
  466. /* Insert the grid right before this node */
  467. nclistinsert(parent->subnodes,i,(ncelem)newgrid);
  468. return NC_NOERR;
  469. }
  470. }
  471. PANIC("regridinsert failure");
  472. return NC_EINVAL;
  473. }
  474. static NCerror
  475. regridremove(CDFnode* newgrid, CDFnode* node)
  476. {
  477. int i;
  478. CDFnode* parent;
  479. /* Locate the index of the node in its current parent and remove */
  480. parent = node->container;
  481. for(i=0;i<nclistlength(parent->subnodes);i++) {
  482. CDFnode* subnode = (CDFnode*)nclistget(parent->subnodes,i);
  483. if(subnode == node) {
  484. nclistremove(parent->subnodes,i);
  485. return NC_NOERR;
  486. }
  487. }
  488. PANIC("regridremove failure");
  489. return NC_EINVAL;
  490. }
  491. /**
  492. Make the constrained dds nodes (root)
  493. point to the corresponding unconstrained
  494. dds nodes (fullroot).
  495. */
  496. NCerror
  497. mapnodes3(CDFnode* root, CDFnode* fullroot)
  498. {
  499. NCerror ncstat = NC_NOERR;
  500. ASSERT(root != NULL && fullroot != NULL);
  501. if(!simplenodematch34(root,fullroot))
  502. {THROWCHK(ncstat=NC_EINVAL); goto done;}
  503. /* clear out old associations*/
  504. unmap3(root);
  505. ncstat = mapnodes3r(root,fullroot,0);
  506. done:
  507. return ncstat;
  508. }
  509. static NCerror
  510. mapnodes3r(CDFnode* connode, CDFnode* fullnode, int depth)
  511. {
  512. unsigned int i,j;
  513. NCerror ncstat = NC_NOERR;
  514. ASSERT((simplenodematch34(connode,fullnode)));
  515. #ifdef DEBUG
  516. {
  517. char* path1 = makecdfpathstring3(fullnode,".");
  518. char * path2 = makecdfpathstring3(connode,".");
  519. fprintf(stderr,"mapnode: %s->%s\n",path1,path2);
  520. nullfree(path1); nullfree(path2);
  521. }
  522. #endif
  523. /* Map node */
  524. mapfcn(connode,fullnode);
  525. /* Try to match connode subnodes against fullnode subnodes */
  526. ASSERT(nclistlength(connode->subnodes) <= nclistlength(fullnode->subnodes));
  527. for(i=0;i<nclistlength(connode->subnodes);i++) {
  528. CDFnode* consubnode = (CDFnode*)nclistget(connode->subnodes,i);
  529. /* Search full subnodes for a matching subnode from con */
  530. for(j=0;j<nclistlength(fullnode->subnodes);j++) {
  531. CDFnode* fullsubnode = (CDFnode*)nclistget(fullnode->subnodes,j);
  532. if(simplenodematch34(fullsubnode,consubnode)) {
  533. ncstat = mapnodes3r(consubnode,fullsubnode,depth+1);
  534. if(ncstat) goto done;
  535. }
  536. }
  537. }
  538. done:
  539. return THROW(ncstat);
  540. }
  541. /* The specific actions of a map are defined
  542. by this function.
  543. */
  544. static NCerror
  545. mapfcn(CDFnode* dstnode, CDFnode* srcnode)
  546. {
  547. /* Mark node as having been mapped */
  548. dstnode->visible = 1;
  549. dstnode->basenode = srcnode;
  550. return NC_NOERR;
  551. }
  552. void
  553. unmap3(CDFnode* root)
  554. {
  555. unsigned int i;
  556. CDFtree* tree = root->tree;
  557. for(i=0;i<nclistlength(tree->nodes);i++) {
  558. CDFnode* node = (CDFnode*)nclistget(tree->nodes,i);
  559. node->basenode = NULL;
  560. node->visible = 0;
  561. }
  562. }
  563. /*
  564. Move dimension data from basenodes to nodes
  565. */
  566. NCerror
  567. dimimprint3(NCDAPCOMMON* nccomm)
  568. {
  569. NCerror ncstat = NC_NOERR;
  570. NClist* allnodes;
  571. int i,j;
  572. CDFnode* basenode;
  573. allnodes = nccomm->cdf.ddsroot->tree->nodes;
  574. for(i=0;i<nclistlength(allnodes);i++) {
  575. CDFnode* node = (CDFnode*)nclistget(allnodes,i);
  576. int noderank, baserank;
  577. /* Do dimension imprinting */
  578. basenode = node->basenode;
  579. if(basenode == NULL) continue;
  580. noderank = nclistlength(node->array.dimset0);
  581. baserank = nclistlength(basenode->array.dimset0);
  582. if(noderank == 0) continue;
  583. ASSERT(noderank == baserank);
  584. #ifdef DEBUG
  585. fprintf(stderr,"dimimprint %s/%d -> %s/%d\n",
  586. makecdfpathstring3(basenode,"."),
  587. noderank,
  588. makecdfpathstring3(node,"."),
  589. baserank);
  590. #endif
  591. for(j=0;j<noderank;j++) {
  592. CDFnode* dim = (CDFnode*)nclistget(node->array.dimset0,j);
  593. CDFnode* basedim = (CDFnode*)nclistget(basenode->array.dimset0,j);
  594. dim->dim.declsize0 = basedim->dim.declsize;
  595. #ifdef DEBUG
  596. fprintf(stderr,"dimimprint: %d: %lu -> %lu\n",i,basedim->dim.declsize,dim->dim.declsize0);
  597. #endif
  598. }
  599. }
  600. return ncstat;
  601. }
  602. static CDFnode*
  603. clonedim(NCDAPCOMMON* nccomm, CDFnode* dim, CDFnode* var)
  604. {
  605. CDFnode* clone;
  606. clone = makecdfnode34(nccomm,dim->ocname,OC_Dimension,
  607. OCNULL,dim->container);
  608. /* Record its existence */
  609. nclistpush(dim->container->root->tree->nodes,(ncelem)clone);
  610. clone->dim = dim->dim; /* copy most everything */
  611. clone->dim.dimflags |= CDFDIMCLONE;
  612. clone->dim.array = var;
  613. return clone;
  614. }
  615. static NClist*
  616. clonedimset3(NCDAPCOMMON* nccomm, NClist* dimset, CDFnode* var)
  617. {
  618. NClist* result = nclistnew();
  619. int i;
  620. for(i=0;i<nclistlength(dimset);i++) {
  621. CDFnode* dim = (CDFnode*)nclistget(dimset,i);
  622. nclistpush(result,(ncelem)clonedim(nccomm,dim,var));
  623. }
  624. return result;
  625. }
  626. /* Define the dimsetplus list for a node */
  627. static NCerror
  628. definedimsetplus3(NCDAPCOMMON* nccomm, CDFnode* node)
  629. {
  630. int ncstat = NC_NOERR;
  631. NClist* dimset;
  632. CDFnode* clone;
  633. ASSERT(node->array.dimsetplus == NULL);
  634. if(node->array.dimset0 == NULL)
  635. dimset = nclistnew();
  636. else { /* copy the dimset0 into dimset */
  637. dimset = nclistclone(node->array.dimset0);
  638. }
  639. /* Insert the sequence or string dims */
  640. if(node->array.stringdim != NULL) {
  641. clone = node->array.stringdim;
  642. nclistpush(dimset,(ncelem)clone);
  643. }
  644. if(node->array.seqdim != NULL) {
  645. clone = node->array.seqdim;
  646. nclistpush(dimset,(ncelem)clone);
  647. }
  648. node->array.dimsetplus = dimset;
  649. return ncstat;
  650. }
  651. /* Define the dimsetall list for a node */
  652. static NCerror
  653. definedimsetall3(NCDAPCOMMON* nccomm, CDFnode* node)
  654. {
  655. int i;
  656. int ncstat = NC_NOERR;
  657. NClist* dimsetall;
  658. ASSERT(node->array.dimsetall == NULL);
  659. if(node->container != NULL) {
  660. if(node->container->array.dimsetall == NULL) {
  661. #ifdef DEBUG1
  662. fprintf(stderr,"dimsetall: recurse %s\n",node->container->ocname);
  663. #endif
  664. ncstat = definedimsetall3(nccomm,node->container);
  665. if(ncstat != NC_NOERR) return ncstat;
  666. }
  667. /* We need to clone the parent dimensions because we will be assigning
  668. indices vis-a-vis this variable */
  669. dimsetall = clonedimset3(nccomm,node->container->array.dimsetall,node);
  670. } else
  671. dimsetall = nclistnew();
  672. /* concat parentall and dimset;*/
  673. for(i=0;i<nclistlength(node->array.dimsetplus);i++) {
  674. CDFnode* clone = (CDFnode*)nclistget(node->array.dimsetplus,i);
  675. nclistpush(dimsetall,(ncelem)clone);
  676. }
  677. node->array.dimsetall = dimsetall;
  678. #ifdef DEBUG1
  679. fprintf(stderr,"dimsetall: |%s|=%d\n",node->ocname,nclistlength(dimsetall));
  680. #endif
  681. return ncstat;
  682. }
  683. /* Define the dimsetplus and dimsetall lists for
  684. all nodes with dimensions
  685. */
  686. NCerror
  687. definedimsets3(NCDAPCOMMON* nccomm)
  688. {
  689. int i;
  690. int ncstat = NC_NOERR;
  691. NClist* allnodes = nccomm->cdf.ddsroot->tree->nodes;
  692. for(i=0;i<nclistlength(allnodes);i++) {
  693. CDFnode* rankednode = (CDFnode*)nclistget(allnodes,i);
  694. if(rankednode->nctype == NC_Dimension) continue; /* ignore */
  695. ASSERT((rankednode->array.dimsetplus == NULL));
  696. ncstat = definedimsetplus3(nccomm,rankednode);
  697. if(ncstat != NC_NOERR) return ncstat;
  698. }
  699. for(i=0;i<nclistlength(allnodes);i++) {
  700. CDFnode* rankednode = (CDFnode*)nclistget(allnodes,i);
  701. if(rankednode->nctype == NC_Dimension) continue; /*ignore*/
  702. ASSERT((rankednode->array.dimsetall == NULL));
  703. ASSERT((rankednode->array.dimsetplus != NULL));
  704. ncstat = definedimsetall3(nccomm,rankednode);
  705. if(ncstat != NC_NOERR) return ncstat;
  706. }
  707. return NC_NOERR;
  708. }