dceconstraints.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. /*********************************************************************
  2. * Copyright 1993, UCAR/Unidata
  3. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. * $Header: /upc/share/CVS/netcdf-3/libncdap3/constraints3.c,v 1.40 2010/05/27 21:34:07 dmh Exp $
  5. *********************************************************************/
  6. #include "config.h"
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include "nclist.h"
  12. #include "ncbytes.h"
  13. #include "nclog.h"
  14. #include "netcdf.h"
  15. #include "dceconstraints.h"
  16. #include "dapdebug.h"
  17. #include "dceparselex.h"
  18. #define DEBUG
  19. int dceverbose = 0;
  20. static char* opstrings[] = OPSTRINGS ;
  21. static void ceallnodesr(DCEnode* node, NClist* allnodes, CEsort which);
  22. /* Parse incoming url constraints, if any,
  23. to check for syntactic correctness
  24. */
  25. int
  26. dapparseconstraints(char* constraints, DCEconstraint* dapconstraint)
  27. {
  28. int ncstat = NC_NOERR;
  29. char* errmsg;
  30. assert(dapconstraint != NULL);
  31. nclistclear(dapconstraint->projections);
  32. nclistclear(dapconstraint->selections);
  33. ncstat = dapceparse(constraints,dapconstraint,&errmsg);
  34. if(ncstat) {
  35. nclog(NCLOGWARN,"DAP constraint parse failure: %s",errmsg);
  36. if(errmsg) free(errmsg);
  37. nclistclear(dapconstraint->projections);
  38. nclistclear(dapconstraint->selections);
  39. }
  40. #ifdef DEBUG
  41. fprintf(stderr,"constraint: %s",dcetostring((DCEnode*)dapconstraint));
  42. #endif
  43. return ncstat;
  44. }
  45. /* Worksheet
  46. mg.st = md.st * ms.st
  47. mg.f = md.f+(ms.f*md.st)
  48. mg.l = ((ms.l-1) / ms.st) * mg.st + 1
  49. mg.p = mg.f + mg.l
  50. mg.c = mg.l / mg.st
  51. 0000000000111111111122222222223
  52. 0123456789012345678901234567890
  53. xxxxxx
  54. xxxxxx
  55. 0 1 2 3 4 5 6 7 8 md=(st=3 f=1 l=25 p=26)
  56. 0 1 2 ms=(st=2 f=3 l=5 p=8 )
  57. ----------------------------
  58. mg=(st=6 f=10 p=23 l=13)
  59. c = 4 / 2 = 2
  60. l = 2 * 6 + 1 = 13
  61. 0000000000111111
  62. 0123456789012345
  63. 0 1 2 3 4 md=(st=2 f=1 l=9 p=10)
  64. 0 1 2 ms=(st=1 f=2 l=3 p=5)
  65. ----------------------------
  66. mg=(st=2 f=5 p=10 l=5 )
  67. c = 2/1 = 2
  68. l = 2 * 2 + 1 = 13
  69. 0000000000111111111
  70. 0123456789012345678
  71. 0 1 2 3 4 5 6 7 8 md=(st=2 f=1 l=17 p=18)
  72. 0 1 2 ms=(st=2 f=3 l=5 p=8)
  73. ----------------------------
  74. mg=(st=4 f=7 p=16 l=9 )
  75. c = 4/2 = 2
  76. l = 2 * 4 + 1 = 9
  77. 0000000000111111111
  78. 0123456789012345678
  79. 0 1 2 3 4 md=(st=2 f=1 l=9 p=10)
  80. 0 1 2 3 4 ms=(st=1 f=0 l=5 p=5)
  81. ----------------------------
  82. mg=(st=2 f=1 p=10 l=9 )
  83. c = 4/1 = 4
  84. l = 4 * 2 + 1 = 9
  85. 00000
  86. 01234
  87. 01 md=(st=1 f=0 l=2 p=2)
  88. 0 ms=(st=1 f=0 l=1 p=1)
  89. ----------------------------
  90. mg=(st=1 f=0 p=1 l=1 )
  91. c = 0/1 = 0
  92. l = 0 * 1 + 1 = 1
  93. 000000000011
  94. 012345678901
  95. 012 md=(st=1 f=0 l=3 p=3)
  96. 012 ms=(st=1 f=0 l=3 p=2)
  97. ----------------------------
  98. mg=(st=1 f=0 p=3 l=3 )
  99. c = 2/1 = 2
  100. l = 2 * 1 + 1 = 3
  101. */
  102. /* Merge slice src into slice dst; dst != src */
  103. int
  104. dceslicemerge(DCEslice* dst, DCEslice* src)
  105. {
  106. int err = NC_NOERR;
  107. DCEslice tmp;
  108. tmp.node.sort = CES_SLICE;
  109. tmp.stride = (dst->stride * src->stride);
  110. tmp.first = (dst->first+((src->first)*(dst->stride)));
  111. tmp.length = (((src->length - 1) / src->stride) * tmp.stride) + 1;
  112. tmp.stop = tmp.first + tmp.length;
  113. tmp.count = tmp.length / tmp.stride;
  114. /* use max declsize */
  115. if(dst->declsize > src->declsize) {
  116. tmp.declsize = dst->declsize;
  117. } else {
  118. tmp.declsize = src->declsize;
  119. }
  120. if(tmp.length % tmp.stride != 0) tmp.count++;
  121. if(tmp.first >= dst->stop || tmp.stop > dst->stop)
  122. err = NC_EINVALCOORDS;
  123. else
  124. *dst = tmp;
  125. return err;
  126. }
  127. /*
  128. Given two projection lists, merge
  129. src into dst taking
  130. overlapping projections into acct.
  131. */
  132. int
  133. dcemergeprojectionlists(NClist* dst, NClist* src)
  134. {
  135. int i;
  136. NClist* cat = nclistnew();
  137. int ncstat = NC_NOERR;
  138. #ifdef DEBUG
  139. fprintf(stderr,"dapmergeprojection: dst = %s\n",dcetostring((DCEnode*)dst));
  140. fprintf(stderr,"dapmergeprojection: src = %s\n",dcetostring((DCEnode*)src));
  141. #endif
  142. /* get dst concat clone(src) */
  143. nclistsetalloc(cat,nclistlength(dst)+nclistlength(src));
  144. for(i=0;i<nclistlength(dst);i++) {
  145. DCEprojection* p = (DCEprojection*)nclistget(dst,i);
  146. nclistpush(cat,(ncelem)p);
  147. }
  148. for(i=0;i<nclistlength(src);i++) {
  149. DCEprojection* p = (DCEprojection*)nclistget(src,i);
  150. nclistpush(cat,(ncelem)dceclone((DCEnode*)p));
  151. }
  152. nclistclear(dst);
  153. /* Repeatedly pull elements from the concat,
  154. merge with all duplicates, and stick into
  155. the dst
  156. */
  157. while(nclistlength(cat) > 0) {
  158. DCEprojection* target = (DCEprojection*)nclistremove(cat,0);
  159. if(target == NULL) continue;
  160. if(target->discrim != CES_VAR) continue;
  161. for(i=0;i<nclistlength(cat);i++) {
  162. DCEprojection* p2 = (DCEprojection*)nclistget(cat,i);
  163. if(p2 == NULL) continue;
  164. if(p2->discrim != CES_VAR) continue;
  165. if(dcesamepath(target->var->segments,
  166. p2->var->segments)!=0) continue;
  167. /* This entry matches our current target; merge */
  168. ncstat = dcemergeprojections(target,p2);
  169. /* null out this merged entry and release it */
  170. nclistset(cat,i,(ncelem)NULL);
  171. dcefree((DCEnode*)p2);
  172. }
  173. /* Capture the clone */
  174. nclistpush(dst,(ncelem)target);
  175. }
  176. nclistfree(cat);
  177. return ncstat;
  178. }
  179. /* Modify merged projection to include "addition" projection */
  180. int
  181. dcemergeprojections(DCEprojection* merged, DCEprojection* addition)
  182. {
  183. int ncstat = NC_NOERR;
  184. int i,j;
  185. ASSERT((merged->discrim == CES_VAR && addition->discrim == CES_VAR));
  186. ASSERT((nclistlength(merged->var->segments) == nclistlength(addition->var->segments)));
  187. for(i=0;i<nclistlength(merged->var->segments);i++) {
  188. DCEsegment* mergedseg = (DCEsegment*)nclistget(merged->var->segments,i);
  189. DCEsegment* addedseg = (DCEsegment*)nclistget(addition->var->segments,i);
  190. /* If one segment has larger rank, then copy the extra slices unchanged */
  191. for(j=0;j<addedseg->rank;j++) {
  192. if(j < mergedseg->rank)
  193. dceslicemerge(mergedseg->slices+j,addedseg->slices+j);
  194. else
  195. mergedseg->slices[j] = addedseg->slices[j];
  196. }
  197. if(addedseg->rank > mergedseg->rank)
  198. mergedseg->rank = addedseg->rank;
  199. }
  200. return ncstat;
  201. }
  202. /* Convert a DCEprojection instance into a string
  203. that can be used with the url
  204. */
  205. char*
  206. buildprojectionstring(NClist* projections)
  207. {
  208. char* pstring;
  209. NCbytes* buf = ncbytesnew();
  210. dcelisttobuffer(projections,buf,",");
  211. pstring = ncbytesdup(buf);
  212. ncbytesfree(buf);
  213. return pstring;
  214. }
  215. char*
  216. buildselectionstring(NClist* selections)
  217. {
  218. NCbytes* buf = ncbytesnew();
  219. char* sstring;
  220. dcelisttobuffer(selections,buf,",");
  221. sstring = ncbytesdup(buf);
  222. ncbytesfree(buf);
  223. return sstring;
  224. }
  225. char*
  226. buildconstraintstring(DCEconstraint* constraints)
  227. {
  228. NCbytes* buf = ncbytesnew();
  229. char* result = NULL;
  230. dcetobuffer((DCEnode*)constraints,buf);
  231. result = ncbytesdup(buf);
  232. ncbytesfree(buf);
  233. return result;
  234. }
  235. DCEnode*
  236. dceclone(DCEnode* node)
  237. {
  238. DCEnode* result = NULL;
  239. result = (DCEnode*)dcecreate(node->sort);
  240. if(result == NULL) goto done;
  241. switch (node->sort) {
  242. case CES_SLICE: {
  243. DCEslice* clone = (DCEslice*)result;
  244. DCEslice* orig = (DCEslice*)node;
  245. *clone = *orig;
  246. } break;
  247. case CES_SEGMENT: {
  248. DCEsegment* clone = (DCEsegment*)result;
  249. DCEsegment* orig = (DCEsegment*)node;
  250. *clone = *orig;
  251. clone->name = nulldup(orig->name);
  252. if(orig->rank > 0)
  253. memcpy(clone->slices,orig->slices,orig->rank*sizeof(DCEslice));
  254. } break;
  255. case CES_VAR: {
  256. DCEvar* clone = (DCEvar*)result;
  257. DCEvar* orig = (DCEvar*)node;
  258. *clone = *orig;
  259. clone->segments = dceclonelist(clone->segments);
  260. } break;
  261. case CES_FCN: {
  262. DCEfcn* clone = (DCEfcn*)result;
  263. DCEfcn* orig = (DCEfcn*)node;
  264. *clone = *orig;
  265. clone->name = nulldup(orig->name);
  266. clone->args = dceclonelist(orig->args);
  267. } break;
  268. case CES_CONST: {
  269. DCEconstant* clone = (DCEconstant*)result;
  270. DCEconstant* orig = (DCEconstant*)node;
  271. *clone = *orig;
  272. if(clone->discrim == CES_STR)
  273. clone->text = nulldup(clone->text);
  274. } break;
  275. case CES_VALUE: {
  276. DCEvalue* clone = (DCEvalue*)result;
  277. DCEvalue* orig = (DCEvalue*)node;
  278. *clone = *orig;
  279. switch (clone->discrim) {
  280. case CES_CONST:
  281. clone->constant = (DCEconstant*)dceclone((DCEnode*)orig->constant); break;
  282. case CES_VAR:
  283. clone->var = (DCEvar*)dceclone((DCEnode*)orig->var); break;
  284. case CES_FCN:
  285. clone->fcn = (DCEfcn*)dceclone((DCEnode*)orig->fcn); break;
  286. default: assert(0);
  287. }
  288. } break;
  289. case CES_PROJECT: {
  290. DCEprojection* clone = (DCEprojection*)result;
  291. DCEprojection* orig = (DCEprojection*)node;
  292. *clone = *orig;
  293. switch (orig->discrim) {
  294. case CES_VAR:
  295. clone->var = (DCEvar*)dceclone((DCEnode*)orig->var); break;
  296. case CES_FCN:
  297. clone->fcn = (DCEfcn*)dceclone((DCEnode*)orig->fcn); break;
  298. default: assert(0);
  299. }
  300. } break;
  301. case CES_SELECT: {
  302. DCEselection* clone = (DCEselection*)result;
  303. DCEselection* orig = (DCEselection*)node;
  304. *clone = *orig;
  305. clone->lhs = (DCEvalue*)dceclone((DCEnode*)orig->lhs);
  306. clone->rhs = dceclonelist(orig->rhs);
  307. } break;
  308. case CES_CONSTRAINT: {
  309. DCEconstraint* clone = (DCEconstraint*)result;
  310. DCEconstraint* orig = (DCEconstraint*)node;
  311. *clone = *orig;
  312. clone->projections = dceclonelist(orig->projections);
  313. clone->selections = dceclonelist(orig->selections);
  314. } break;
  315. default:
  316. assert(0);
  317. }
  318. done:
  319. return result;
  320. }
  321. NClist*
  322. dceclonelist(NClist* list)
  323. {
  324. int i;
  325. NClist* clone;
  326. if(list == NULL) return NULL;
  327. clone = nclistnew();
  328. for(i=0;i<nclistlength(list);i++) {
  329. DCEnode* node = (DCEnode*)nclistget(list,i);
  330. DCEnode* newnode = dceclone((DCEnode*)node);
  331. nclistpush(clone,(ncelem)newnode);
  332. }
  333. return clone;
  334. }
  335. void
  336. dcefree(DCEnode* node)
  337. {
  338. if(node == NULL) return;
  339. switch (node->sort) {
  340. case CES_VAR: {
  341. DCEvar* target = (DCEvar*)node;
  342. dcefreelist(target->segments);
  343. } break;
  344. case CES_FCN: {
  345. DCEfcn* target = (DCEfcn*)node;
  346. dcefreelist(target->args);
  347. nullfree(target->name);
  348. } break;
  349. case CES_CONST: {
  350. DCEconstant* target = (DCEconstant*)node;
  351. if(target->discrim == CES_STR)
  352. nullfree(target->text);
  353. } break;
  354. case CES_VALUE: {
  355. DCEvalue* target = (DCEvalue*)node;
  356. switch(target->discrim) {
  357. case CES_CONST: dcefree((DCEnode*)target->constant); break;
  358. case CES_VAR: dcefree((DCEnode*)target->var); break;
  359. case CES_FCN: dcefree((DCEnode*)target->fcn); break;
  360. default: assert(0);
  361. }
  362. } break;
  363. case CES_PROJECT: {
  364. DCEprojection* target = (DCEprojection*)node;
  365. switch (target->discrim) {
  366. case CES_VAR: dcefree((DCEnode*)target->var); break;
  367. case CES_FCN: dcefree((DCEnode*)target->fcn); break;
  368. default: assert(0);
  369. }
  370. } break;
  371. case CES_SELECT: {
  372. DCEselection* target = (DCEselection*)node;
  373. dcefreelist(target->rhs);
  374. dcefree((DCEnode*)target->lhs);
  375. } break;
  376. case CES_CONSTRAINT: {
  377. DCEconstraint* target = (DCEconstraint*)node;
  378. dcefreelist(target->projections);
  379. dcefreelist(target->selections);
  380. } break;
  381. case CES_SEGMENT: {
  382. DCEsegment* target = (DCEsegment*)node;
  383. target->rank = 0;
  384. nullfree(target->name);
  385. } break;
  386. case CES_SLICE: {
  387. } break;
  388. default:
  389. assert(0);
  390. }
  391. /* final action */
  392. free(node);
  393. }
  394. void
  395. dcefreelist(NClist* list)
  396. {
  397. int i;
  398. if(list == NULL) return;
  399. for(i=0;i<nclistlength(list);i++) {
  400. DCEnode* node = (DCEnode*)nclistget(list,i);
  401. dcefree((DCEnode*)node);
  402. }
  403. nclistfree(list);
  404. }
  405. char*
  406. dcetostring(DCEnode* node)
  407. {
  408. char* s;
  409. NCbytes* buf = ncbytesnew();
  410. dcetobuffer(node,buf);
  411. s = ncbytesextract(buf);
  412. ncbytesfree(buf);
  413. return s;
  414. }
  415. /* For debugging */
  416. #ifdef DEBUG
  417. static char*
  418. dimdecl(size_t declsize)
  419. {
  420. static char tag[16];
  421. tag[0] = '\0';
  422. if(dceverbose)
  423. snprintf(tag,sizeof(tag),"/%lu",(unsigned long)declsize);
  424. return tag;
  425. }
  426. #else
  427. static char*
  428. dimdecl(size_t declsize)
  429. {
  430. return "";
  431. }
  432. #endif
  433. void
  434. dcetobuffer(DCEnode* node, NCbytes* buf)
  435. {
  436. int i;
  437. char tmp[1024];
  438. if(buf == NULL) return;
  439. if(node == NULL) {ncbytescat(buf,"<null>"); return;}
  440. switch (node->sort) {
  441. case CES_SLICE: {
  442. DCEslice* slice = (DCEslice*)node;
  443. size_t last = (slice->first+slice->length)-1;
  444. if(slice->count == 1) {
  445. snprintf(tmp,sizeof(tmp),"[%lu%s]",
  446. (unsigned long)slice->first,dimdecl(slice->declsize));
  447. } else if(slice->stride == 1) {
  448. snprintf(tmp,sizeof(tmp),"[%lu:%lu%s]",
  449. (unsigned long)slice->first,
  450. (unsigned long)last,
  451. dimdecl(slice->declsize));
  452. } else {
  453. snprintf(tmp,sizeof(tmp),"[%lu:%lu:%lu%s]",
  454. (unsigned long)slice->first,
  455. (unsigned long)slice->stride,
  456. (unsigned long)last,
  457. dimdecl(slice->declsize));
  458. }
  459. ncbytescat(buf,tmp);
  460. } break;
  461. case CES_SEGMENT: {
  462. DCEsegment* segment = (DCEsegment*)node;
  463. int rank = segment->rank;
  464. char* name = (segment->name?segment->name:"<unknown>");
  465. name = nulldup(name);
  466. ncbytescat(buf,name);
  467. nullfree(name);
  468. if(dceverbose && dceiswholesegment(segment))
  469. ncbytescat(buf,"*");
  470. if(dceverbose || !dceiswholesegment(segment)) {
  471. for(i=0;i<rank;i++) {
  472. DCEslice* slice = segment->slices+i;
  473. dcetobuffer((DCEnode*)slice,buf);
  474. }
  475. }
  476. } break;
  477. case CES_VAR: {
  478. DCEvar* var = (DCEvar*)node;
  479. dcelisttobuffer(var->segments,buf,".");
  480. } break;
  481. case CES_FCN: {
  482. DCEfcn* fcn = (DCEfcn*)node;
  483. ncbytescat(buf,fcn->name);
  484. ncbytescat(buf,"(");
  485. dcelisttobuffer(fcn->args,buf,",");
  486. ncbytescat(buf,")");
  487. } break;
  488. case CES_CONST: {
  489. DCEconstant* value = (DCEconstant*)node;
  490. switch (value->discrim) {
  491. case CES_STR:
  492. ncbytescat(buf,value->text);
  493. break;
  494. case CES_INT:
  495. snprintf(tmp,sizeof(tmp),"%lld",value->intvalue);
  496. ncbytescat(buf,tmp);
  497. break;
  498. case CES_FLOAT:
  499. snprintf(tmp,sizeof(tmp),"%g",value->floatvalue);
  500. ncbytescat(buf,tmp);
  501. break;
  502. default: assert(0);
  503. }
  504. } break;
  505. case CES_VALUE: {
  506. DCEvalue* value = (DCEvalue*)node;
  507. switch (value->discrim) {
  508. case CES_CONST:
  509. dcetobuffer((DCEnode*)value->constant,buf);
  510. break;
  511. case CES_VAR:
  512. dcetobuffer((DCEnode*)value->var,buf);
  513. break;
  514. case CES_FCN:
  515. dcetobuffer((DCEnode*)value->fcn,buf);
  516. break;
  517. default: assert(0);
  518. }
  519. } break;
  520. case CES_PROJECT: {
  521. DCEprojection* target = (DCEprojection*)node;
  522. switch (target->discrim) {
  523. case CES_VAR:
  524. dcetobuffer((DCEnode*)target->var,buf);
  525. break;
  526. case CES_FCN: dcetobuffer((DCEnode*)target->fcn,buf); break;
  527. default: assert(0);
  528. }
  529. } break;
  530. case CES_SELECT: {
  531. DCEselection* sel = (DCEselection*)node;
  532. dcetobuffer((DCEnode*)sel->lhs,buf);
  533. if(sel->operator == CES_NIL) break;
  534. ncbytescat(buf,opstrings[(int)sel->operator]);
  535. if(nclistlength(sel->rhs) > 1)
  536. ncbytescat(buf,"{");
  537. dcelisttobuffer(sel->rhs,buf,",");
  538. if(nclistlength(sel->rhs) > 1)
  539. ncbytescat(buf,"}");
  540. } break;
  541. case CES_CONSTRAINT: {
  542. DCEconstraint* con = (DCEconstraint*)node;
  543. if(con->projections != NULL && nclistlength(con->projections) > 0) {
  544. dcelisttobuffer(con->projections,buf,",");
  545. }
  546. if(con->selections != NULL && nclistlength(con->selections) > 0) {
  547. ncbytescat(buf,"&"); /* because & is really a prefix */
  548. dcelisttobuffer(con->selections,buf,"&");
  549. }
  550. } break;
  551. case CES_NIL: {
  552. ncbytescat(buf,"<nil>");
  553. } break;
  554. default:
  555. assert(0);
  556. }
  557. }
  558. char*
  559. dcelisttostring(NClist* list, char* sep)
  560. {
  561. char* s;
  562. NCbytes* buf = ncbytesnew();
  563. dcelisttobuffer(list,buf,sep);
  564. s = ncbytesextract(buf);
  565. ncbytesfree(buf);
  566. return s;
  567. }
  568. void
  569. dcelisttobuffer(NClist* list, NCbytes* buf, char* sep)
  570. {
  571. int i;
  572. if(list == NULL || buf == NULL) return;
  573. if(sep == NULL) sep = ",";
  574. for(i=0;i<nclistlength(list);i++) {
  575. DCEnode* node = (DCEnode*)nclistget(list,i);
  576. if(node == NULL) continue;
  577. if(i>0) ncbytescat(buf,sep);
  578. dcetobuffer((DCEnode*)node,buf);
  579. }
  580. }
  581. /* Collect all nodes within a specified constraint tree */
  582. /* Caller frees result */
  583. NClist*
  584. dceallnodes(DCEnode* node, CEsort which)
  585. {
  586. NClist* allnodes = nclistnew();
  587. ceallnodesr(node,allnodes,which);
  588. return allnodes;
  589. }
  590. static void
  591. ceallnodesr(DCEnode* node, NClist* allnodes, CEsort which)
  592. {
  593. int i;
  594. if(node == NULL) return;
  595. if(nclistcontains(allnodes,(ncelem)node)) return;
  596. if(which == CES_NIL || node->sort == which)
  597. nclistpush(allnodes,(ncelem)node);
  598. switch(node->sort) {
  599. case CES_FCN: {
  600. DCEfcn* fcn = (DCEfcn*)node;
  601. for(i=0;i<nclistlength(fcn->args);i++) {
  602. ceallnodesr((DCEnode*)nclistget(fcn->args,i),allnodes,which);
  603. }
  604. } break;
  605. case CES_VAR: {
  606. DCEvar* var = (DCEvar*)node;
  607. for(i=0;i<nclistlength(var->segments);i++) {
  608. ceallnodesr((DCEnode*)nclistget(var->segments,i),allnodes,which);
  609. }
  610. } break;
  611. case CES_VALUE: {
  612. DCEvalue* value = (DCEvalue*)node;
  613. if(value->discrim == CES_VAR)
  614. ceallnodesr((DCEnode*)value->var,allnodes,which);
  615. else if(value->discrim == CES_FCN)
  616. ceallnodesr((DCEnode*)value->fcn,allnodes,which);
  617. else
  618. ceallnodesr((DCEnode*)value->constant,allnodes,which);
  619. } break;
  620. case CES_SELECT: {
  621. DCEselection* selection = (DCEselection*)node;
  622. ceallnodesr((DCEnode*)selection->lhs,allnodes,which);
  623. for(i=0;i<nclistlength(selection->rhs);i++)
  624. ceallnodesr((DCEnode*)nclistget(selection->rhs,i),allnodes,which);
  625. } break;
  626. case CES_PROJECT: {
  627. DCEprojection* projection = (DCEprojection*)node;
  628. if(projection->discrim == CES_VAR)
  629. ceallnodesr((DCEnode*)projection->var,allnodes,which);
  630. else
  631. ceallnodesr((DCEnode*)projection->fcn,allnodes,which);
  632. } break;
  633. case CES_CONSTRAINT: {
  634. DCEconstraint* constraint = (DCEconstraint*)node;
  635. for(i=0;i<nclistlength(constraint->projections);i++)
  636. ceallnodesr((DCEnode*)nclistget(constraint->projections,i),allnodes,which);
  637. for(i=0;i<nclistlength(constraint->selections);i++)
  638. ceallnodesr((DCEnode*)nclistget(constraint->selections,i),allnodes,which);
  639. } break;
  640. /* All others have no subnodes */
  641. default:
  642. break;
  643. }
  644. }
  645. DCEnode*
  646. dcecreate(CEsort sort)
  647. {
  648. DCEnode* node = NULL;
  649. switch (sort) {
  650. case CES_SLICE: {
  651. DCEslice* target = (DCEslice*)calloc(1,sizeof(DCEslice));
  652. if(target == NULL) return NULL;
  653. node = (DCEnode*)target;
  654. } break;
  655. case CES_SEGMENT: {
  656. int i;
  657. DCEsegment* target = (DCEsegment*)calloc(1,sizeof(DCEsegment));
  658. if(target == NULL) return NULL;
  659. /* Initialize the sort of the slices */
  660. for(i=0;i<NC_MAX_VAR_DIMS;i++)
  661. target->slices[i].node.sort = CES_SLICE;
  662. node = (DCEnode*)target;
  663. } break;
  664. case CES_CONST: {
  665. DCEconstant* target = (DCEconstant*)calloc(1,sizeof(DCEconstant));
  666. if(target == NULL) return NULL;
  667. node = (DCEnode*)target;
  668. target->discrim = CES_NIL;
  669. } break;
  670. case CES_VALUE: {
  671. DCEvalue* target = (DCEvalue*)calloc(1,sizeof(DCEvalue));
  672. if(target == NULL) return NULL;
  673. node = (DCEnode*)target;
  674. target->discrim = CES_NIL;
  675. } break;
  676. case CES_VAR: {
  677. DCEvar* target = (DCEvar*)calloc(1,sizeof(DCEvar));
  678. if(target == NULL) return NULL;
  679. node = (DCEnode*)target;
  680. } break;
  681. case CES_FCN: {
  682. DCEfcn* target = (DCEfcn*)calloc(1,sizeof(DCEfcn));
  683. if(target == NULL) return NULL;
  684. node = (DCEnode*)target;
  685. } break;
  686. case CES_PROJECT: {
  687. DCEprojection* target = (DCEprojection*)calloc(1,sizeof(DCEprojection));
  688. if(target == NULL) return NULL;
  689. node = (DCEnode*)target;
  690. } break;
  691. case CES_SELECT: {
  692. DCEselection* target = (DCEselection*)calloc(1,sizeof(DCEselection));
  693. if(target == NULL) return NULL;
  694. node = (DCEnode*)target;
  695. target->operator = CEO_NIL;
  696. } break;
  697. case CES_CONSTRAINT: {
  698. DCEconstraint* target = (DCEconstraint*)calloc(1,sizeof(DCEconstraint));
  699. if(target == NULL) return NULL;
  700. node = (DCEnode*)target;
  701. } break;
  702. default:
  703. assert(0);
  704. }
  705. /* final action */
  706. node->sort = sort;
  707. return node;
  708. }
  709. int
  710. dceiswholeslice(DCEslice* slice)
  711. {
  712. if(slice->first != 0
  713. || slice->stride != 1
  714. || slice->stop != slice->declsize) return 0;
  715. return 1;
  716. }
  717. int
  718. dceiswholesegment(DCEsegment* seg)
  719. {
  720. int i,whole;
  721. if(!seg->slicesdefined) return 0; /* actually, we don't know */
  722. whole = 1; /* assume so */
  723. for(i=0;i<seg->rank;i++) {
  724. if(!dceiswholeslice(&seg->slices[i])) {whole = 0; break;}
  725. }
  726. return whole;
  727. }
  728. void
  729. dcemakewholeslice(DCEslice* slice, size_t declsize)
  730. {
  731. slice->first = 0;
  732. slice->stride = 1;
  733. slice->length = declsize;
  734. slice->stop = declsize;
  735. slice->declsize = declsize;
  736. slice->count = declsize;
  737. }
  738. /* Remove slicing from terminal segment of p */
  739. void
  740. dcemakewholeprojection(DCEprojection* p)
  741. {
  742. /* Remove the slicing (if any) from the last segment */
  743. if(p->discrim == CES_VAR && p->var != NULL && p->var->segments != NULL) {
  744. int lastindex = nclistlength(p->var->segments) - 1;
  745. DCEsegment* lastseg = (DCEsegment*)nclistget(p->var->segments,lastindex);
  746. lastseg->rank = 0;
  747. }
  748. }
  749. int
  750. dcesamepath(NClist* list1, NClist* list2)
  751. {
  752. int i;
  753. int len = nclistlength(list1);
  754. if(len != nclistlength(list2)) return 0;
  755. for(i=0;i<len;i++) {
  756. DCEsegment* s1 = (DCEsegment*)nclistget(list1,i);
  757. DCEsegment* s2 = (DCEsegment*)nclistget(list2,i);
  758. if(strcmp(s1->name,s2->name) != 0) return 0;
  759. }
  760. return 1;
  761. }