NCDAst.c 22 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. /**
  2. * @file NCDAst.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdlib.h>
  30. #include <limits.h>
  31. #include <string.h>
  32. #include <misc/offset.h>
  33. #include <misc/strdup.h>
  34. #include "NCDAst.h"
  35. struct NCDValue__list_element {
  36. LinkedList1Node list_node;
  37. NCDValue v;
  38. };
  39. struct NCDValue__map_element {
  40. LinkedList1Node list_node;
  41. NCDValue key;
  42. NCDValue val;
  43. };
  44. struct ProgramElem {
  45. LinkedList1Node elems_list_node;
  46. NCDProgramElem elem;
  47. };
  48. struct BlockStatement {
  49. LinkedList1Node statements_list_node;
  50. NCDStatement s;
  51. };
  52. struct IfBlockIf {
  53. LinkedList1Node ifs_list_node;
  54. NCDIf ifc;
  55. };
  56. static void value_assert (NCDValue *o)
  57. {
  58. switch (o->type) {
  59. case NCDVALUE_STRING:
  60. case NCDVALUE_LIST:
  61. case NCDVALUE_MAP:
  62. case NCDVALUE_VAR:
  63. return;
  64. default:
  65. ASSERT(0);
  66. }
  67. }
  68. void NCDValue_Free (NCDValue *o)
  69. {
  70. switch (o->type) {
  71. case NCDVALUE_STRING: {
  72. free(o->string);
  73. } break;
  74. case NCDVALUE_LIST: {
  75. LinkedList1Node *n;
  76. while (n = LinkedList1_GetFirst(&o->list)) {
  77. struct NCDValue__list_element *e = UPPER_OBJECT(n, struct NCDValue__list_element, list_node);
  78. NCDValue_Free(&e->v);
  79. LinkedList1_Remove(&o->list, &e->list_node);
  80. free(e);
  81. }
  82. } break;
  83. case NCDVALUE_MAP: {
  84. LinkedList1Node *n;
  85. while (n = LinkedList1_GetFirst(&o->map_list)) {
  86. struct NCDValue__map_element *e = UPPER_OBJECT(n, struct NCDValue__map_element, list_node);
  87. LinkedList1_Remove(&o->map_list, &e->list_node);
  88. NCDValue_Free(&e->key);
  89. NCDValue_Free(&e->val);
  90. free(e);
  91. }
  92. } break;
  93. case NCDVALUE_VAR: {
  94. free(o->var_name);
  95. } break;
  96. default:
  97. ASSERT(0);
  98. }
  99. }
  100. int NCDValue_Type (NCDValue *o)
  101. {
  102. value_assert(o);
  103. return o->type;
  104. }
  105. int NCDValue_InitString (NCDValue *o, const char *str)
  106. {
  107. return NCDValue_InitStringBin(o, (const uint8_t *)str, strlen(str));
  108. }
  109. int NCDValue_InitStringBin (NCDValue *o, const uint8_t *str, size_t len)
  110. {
  111. if (len == SIZE_MAX) {
  112. return 0;
  113. }
  114. if (!(o->string = malloc(len + 1))) {
  115. return 0;
  116. }
  117. memcpy(o->string, str, len);
  118. o->string[len] = '\0';
  119. o->string_len = len;
  120. o->type = NCDVALUE_STRING;
  121. return 1;
  122. }
  123. const char * NCDValue_StringValue (NCDValue *o)
  124. {
  125. ASSERT(o->type == NCDVALUE_STRING)
  126. return (char *)o->string;
  127. }
  128. size_t NCDValue_StringLength (NCDValue *o)
  129. {
  130. ASSERT(o->type == NCDVALUE_STRING)
  131. return o->string_len;
  132. }
  133. void NCDValue_InitList (NCDValue *o)
  134. {
  135. o->type = NCDVALUE_LIST;
  136. LinkedList1_Init(&o->list);
  137. o->list_count = 0;
  138. }
  139. size_t NCDValue_ListCount (NCDValue *o)
  140. {
  141. value_assert(o);
  142. ASSERT(o->type == NCDVALUE_LIST)
  143. return o->list_count;
  144. }
  145. int NCDValue_ListAppend (NCDValue *o, NCDValue v)
  146. {
  147. value_assert(o);
  148. ASSERT(o->type == NCDVALUE_LIST)
  149. value_assert(&v);
  150. if (o->list_count == SIZE_MAX) {
  151. return 0;
  152. }
  153. struct NCDValue__list_element *e = malloc(sizeof(*e));
  154. if (!e) {
  155. return 0;
  156. }
  157. e->v = v;
  158. LinkedList1_Append(&o->list, &e->list_node);
  159. o->list_count++;
  160. return 1;
  161. }
  162. int NCDValue_ListPrepend (NCDValue *o, NCDValue v)
  163. {
  164. value_assert(o);
  165. ASSERT(o->type == NCDVALUE_LIST)
  166. value_assert(&v);
  167. if (o->list_count == SIZE_MAX) {
  168. return 0;
  169. }
  170. struct NCDValue__list_element *e = malloc(sizeof(*e));
  171. if (!e) {
  172. return 0;
  173. }
  174. e->v = v;
  175. LinkedList1_Prepend(&o->list, &e->list_node);
  176. o->list_count++;
  177. return 1;
  178. }
  179. NCDValue * NCDValue_ListFirst (NCDValue *o)
  180. {
  181. value_assert(o);
  182. ASSERT(o->type == NCDVALUE_LIST)
  183. LinkedList1Node *ln = LinkedList1_GetFirst(&o->list);
  184. if (!ln) {
  185. return NULL;
  186. }
  187. struct NCDValue__list_element *e = UPPER_OBJECT(ln, struct NCDValue__list_element, list_node);
  188. return &e->v;
  189. }
  190. NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
  191. {
  192. value_assert(o);
  193. ASSERT(o->type == NCDVALUE_LIST)
  194. struct NCDValue__list_element *cur_e = UPPER_OBJECT(ev, struct NCDValue__list_element, v);
  195. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->list_node);
  196. if (!ln) {
  197. return NULL;
  198. }
  199. struct NCDValue__list_element *e = UPPER_OBJECT(ln, struct NCDValue__list_element, list_node);
  200. return &e->v;
  201. }
  202. void NCDValue_InitMap (NCDValue *o)
  203. {
  204. o->type = NCDVALUE_MAP;
  205. LinkedList1_Init(&o->map_list);
  206. o->map_count = 0;
  207. }
  208. size_t NCDValue_MapCount (NCDValue *o)
  209. {
  210. value_assert(o);
  211. ASSERT(o->type == NCDVALUE_MAP)
  212. return o->map_count;
  213. }
  214. int NCDValue_MapPrepend (NCDValue *o, NCDValue key, NCDValue val)
  215. {
  216. value_assert(o);
  217. ASSERT(o->type == NCDVALUE_MAP)
  218. value_assert(&key);
  219. value_assert(&val);
  220. if (o->map_count == SIZE_MAX) {
  221. return 0;
  222. }
  223. struct NCDValue__map_element *e = malloc(sizeof(*e));
  224. if (!e) {
  225. return 0;
  226. }
  227. e->key = key;
  228. e->val = val;
  229. LinkedList1_Prepend(&o->map_list, &e->list_node);
  230. o->map_count++;
  231. return 1;
  232. }
  233. NCDValue * NCDValue_MapFirstKey (NCDValue *o)
  234. {
  235. value_assert(o);
  236. ASSERT(o->type == NCDVALUE_MAP)
  237. LinkedList1Node *ln = LinkedList1_GetFirst(&o->map_list);
  238. if (!ln) {
  239. return NULL;
  240. }
  241. struct NCDValue__map_element *e = UPPER_OBJECT(ln, struct NCDValue__map_element, list_node);
  242. value_assert(&e->key);
  243. value_assert(&e->val);
  244. return &e->key;
  245. }
  246. NCDValue * NCDValue_MapNextKey (NCDValue *o, NCDValue *ekey)
  247. {
  248. value_assert(o);
  249. ASSERT(o->type == NCDVALUE_MAP)
  250. struct NCDValue__map_element *e0 = UPPER_OBJECT(ekey, struct NCDValue__map_element, key);
  251. value_assert(&e0->key);
  252. value_assert(&e0->val);
  253. LinkedList1Node *ln = LinkedList1Node_Next(&e0->list_node);
  254. if (!ln) {
  255. return NULL;
  256. }
  257. struct NCDValue__map_element *e = UPPER_OBJECT(ln, struct NCDValue__map_element, list_node);
  258. value_assert(&e->key);
  259. value_assert(&e->val);
  260. return &e->key;
  261. }
  262. NCDValue * NCDValue_MapKeyValue (NCDValue *o, NCDValue *ekey)
  263. {
  264. value_assert(o);
  265. ASSERT(o->type == NCDVALUE_MAP)
  266. struct NCDValue__map_element *e = UPPER_OBJECT(ekey, struct NCDValue__map_element, key);
  267. value_assert(&e->key);
  268. value_assert(&e->val);
  269. return &e->val;
  270. }
  271. int NCDValue_InitVar (NCDValue *o, const char *var_name)
  272. {
  273. ASSERT(var_name)
  274. if (!(o->var_name = strdup(var_name))) {
  275. return 0;
  276. }
  277. o->type = NCDVALUE_VAR;
  278. return 1;
  279. }
  280. const char * NCDValue_VarName (NCDValue *o)
  281. {
  282. value_assert(o);
  283. ASSERT(o->type == NCDVALUE_VAR)
  284. return o->var_name;
  285. }
  286. void NCDProgram_Init (NCDProgram *o)
  287. {
  288. LinkedList1_Init(&o->elems_list);
  289. o->num_elems = 0;
  290. }
  291. void NCDProgram_Free (NCDProgram *o)
  292. {
  293. LinkedList1Node *ln;
  294. while (ln = LinkedList1_GetFirst(&o->elems_list)) {
  295. struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
  296. NCDProgramElem_Free(&e->elem);
  297. LinkedList1_Remove(&o->elems_list, &e->elems_list_node);
  298. free(e);
  299. }
  300. }
  301. NCDProgramElem * NCDProgram_PrependElem (NCDProgram *o, NCDProgramElem elem)
  302. {
  303. if (o->num_elems == SIZE_MAX) {
  304. return NULL;
  305. }
  306. struct ProgramElem *e = malloc(sizeof(*e));
  307. if (!e) {
  308. return NULL;
  309. }
  310. LinkedList1_Prepend(&o->elems_list, &e->elems_list_node);
  311. e->elem = elem;
  312. o->num_elems++;
  313. return &e->elem;
  314. }
  315. NCDProgramElem * NCDProgram_FirstElem (NCDProgram *o)
  316. {
  317. LinkedList1Node *ln = LinkedList1_GetFirst(&o->elems_list);
  318. if (!ln) {
  319. return NULL;
  320. }
  321. struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
  322. return &e->elem;
  323. }
  324. NCDProgramElem * NCDProgram_NextElem (NCDProgram *o, NCDProgramElem *ee)
  325. {
  326. ASSERT(ee)
  327. struct ProgramElem *cur_e = UPPER_OBJECT(ee, struct ProgramElem, elem);
  328. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->elems_list_node);
  329. if (!ln) {
  330. return NULL;
  331. }
  332. struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
  333. return &e->elem;
  334. }
  335. size_t NCDProgram_NumElems (NCDProgram *o)
  336. {
  337. return o->num_elems;
  338. }
  339. int NCDProgram_ContainsElemType (NCDProgram *o, int elem_type)
  340. {
  341. for (NCDProgramElem *elem = NCDProgram_FirstElem(o); elem; elem = NCDProgram_NextElem(o, elem)) {
  342. if (NCDProgramElem_Type(elem) == elem_type) {
  343. return 1;
  344. }
  345. }
  346. return 0;
  347. }
  348. void NCDProgram_RemoveElem (NCDProgram *o, NCDProgramElem *ee)
  349. {
  350. ASSERT(ee)
  351. struct ProgramElem *e = UPPER_OBJECT(ee, struct ProgramElem, elem);
  352. NCDProgramElem_Free(&e->elem);
  353. LinkedList1_Remove(&o->elems_list, &e->elems_list_node);
  354. free(e);
  355. ASSERT(o->num_elems > 0)
  356. o->num_elems--;
  357. }
  358. int NCDProgram_ReplaceElemWithProgram (NCDProgram *o, NCDProgramElem *ee, NCDProgram replace_prog)
  359. {
  360. ASSERT(ee)
  361. if (replace_prog.num_elems > SIZE_MAX - o->num_elems) {
  362. return 0;
  363. }
  364. struct ProgramElem *e = UPPER_OBJECT(ee, struct ProgramElem, elem);
  365. LinkedList1_InsertListAfter(&o->elems_list, replace_prog.elems_list, &e->elems_list_node);
  366. o->num_elems += replace_prog.num_elems;
  367. NCDProgram_RemoveElem(o, ee);
  368. return 1;
  369. }
  370. void NCDProgramElem_InitProcess (NCDProgramElem *o, NCDProcess process)
  371. {
  372. o->type = NCDPROGRAMELEM_PROCESS;
  373. o->process = process;
  374. }
  375. int NCDProgramElem_InitInclude (NCDProgramElem *o, const char *path_data, size_t path_length)
  376. {
  377. if (!(o->include.path_data = b_strdup_bin(path_data, path_length))) {
  378. return 0;
  379. }
  380. o->type = NCDPROGRAMELEM_INCLUDE;
  381. o->include.path_length = path_length;
  382. return 1;
  383. }
  384. int NCDProgramElem_InitIncludeGuard (NCDProgramElem *o, const char *id_data, size_t id_length)
  385. {
  386. if (!(o->include_guard.id_data = b_strdup_bin(id_data, id_length))) {
  387. return 0;
  388. }
  389. o->type = NCDPROGRAMELEM_INCLUDE_GUARD;
  390. o->include_guard.id_length = id_length;
  391. return 1;
  392. }
  393. void NCDProgramElem_Free (NCDProgramElem *o)
  394. {
  395. switch (o->type) {
  396. case NCDPROGRAMELEM_PROCESS: {
  397. NCDProcess_Free(&o->process);
  398. } break;
  399. case NCDPROGRAMELEM_INCLUDE: {
  400. free(o->include.path_data);
  401. } break;
  402. case NCDPROGRAMELEM_INCLUDE_GUARD: {
  403. free(o->include_guard.id_data);
  404. } break;
  405. default: ASSERT(0);
  406. }
  407. }
  408. int NCDProgramElem_Type (NCDProgramElem *o)
  409. {
  410. return o->type;
  411. }
  412. NCDProcess * NCDProgramElem_Process (NCDProgramElem *o)
  413. {
  414. ASSERT(o->type == NCDPROGRAMELEM_PROCESS)
  415. return &o->process;
  416. }
  417. const char * NCDProgramElem_IncludePathData (NCDProgramElem *o)
  418. {
  419. ASSERT(o->type == NCDPROGRAMELEM_INCLUDE)
  420. return o->include.path_data;
  421. }
  422. size_t NCDProgramElem_IncludePathLength (NCDProgramElem *o)
  423. {
  424. ASSERT(o->type == NCDPROGRAMELEM_INCLUDE)
  425. return o->include.path_length;
  426. }
  427. const char * NCDProgramElem_IncludeGuardIdData (NCDProgramElem *o)
  428. {
  429. ASSERT(o->type == NCDPROGRAMELEM_INCLUDE_GUARD)
  430. return o->include_guard.id_data;
  431. }
  432. size_t NCDProgramElem_IncludeGuardIdLength (NCDProgramElem *o)
  433. {
  434. ASSERT(o->type == NCDPROGRAMELEM_INCLUDE_GUARD)
  435. return o->include_guard.id_length;
  436. }
  437. int NCDProcess_Init (NCDProcess *o, int is_template, const char *name, NCDBlock block)
  438. {
  439. ASSERT(is_template == !!is_template)
  440. ASSERT(name)
  441. if (!(o->name = strdup(name))) {
  442. return 0;
  443. }
  444. o->is_template = is_template;
  445. o->block = block;
  446. return 1;
  447. }
  448. void NCDProcess_Free (NCDProcess *o)
  449. {
  450. NCDBlock_Free(&o->block);
  451. free(o->name);
  452. }
  453. int NCDProcess_IsTemplate (NCDProcess *o)
  454. {
  455. return o->is_template;
  456. }
  457. const char * NCDProcess_Name (NCDProcess *o)
  458. {
  459. return o->name;
  460. }
  461. NCDBlock * NCDProcess_Block (NCDProcess *o)
  462. {
  463. return &o->block;
  464. }
  465. void NCDBlock_Init (NCDBlock *o)
  466. {
  467. LinkedList1_Init(&o->statements_list);
  468. o->count = 0;
  469. }
  470. void NCDBlock_Free (NCDBlock *o)
  471. {
  472. LinkedList1Node *ln;
  473. while (ln = LinkedList1_GetFirst(&o->statements_list)) {
  474. struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
  475. NCDStatement_Free(&e->s);
  476. LinkedList1_Remove(&o->statements_list, &e->statements_list_node);
  477. free(e);
  478. }
  479. }
  480. int NCDBlock_PrependStatement (NCDBlock *o, NCDStatement s)
  481. {
  482. return NCDBlock_InsertStatementAfter(o, NULL, s);
  483. }
  484. int NCDBlock_InsertStatementAfter (NCDBlock *o, NCDStatement *after, NCDStatement s)
  485. {
  486. struct BlockStatement *after_e = NULL;
  487. if (after) {
  488. after_e = UPPER_OBJECT(after, struct BlockStatement, s);
  489. }
  490. if (o->count == SIZE_MAX) {
  491. return 0;
  492. }
  493. struct BlockStatement *e = malloc(sizeof(*e));
  494. if (!e) {
  495. return 0;
  496. }
  497. if (after_e) {
  498. LinkedList1_InsertAfter(&o->statements_list, &e->statements_list_node, &after_e->statements_list_node);
  499. } else {
  500. LinkedList1_Prepend(&o->statements_list, &e->statements_list_node);
  501. }
  502. e->s = s;
  503. o->count++;
  504. return 1;
  505. }
  506. NCDStatement * NCDBlock_ReplaceStatement (NCDBlock *o, NCDStatement *es, NCDStatement s)
  507. {
  508. ASSERT(es)
  509. struct BlockStatement *e = UPPER_OBJECT(es, struct BlockStatement, s);
  510. NCDStatement_Free(&e->s);
  511. e->s = s;
  512. return &e->s;
  513. }
  514. NCDStatement * NCDBlock_FirstStatement (NCDBlock *o)
  515. {
  516. LinkedList1Node *ln = LinkedList1_GetFirst(&o->statements_list);
  517. if (!ln) {
  518. return NULL;
  519. }
  520. struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
  521. return &e->s;
  522. }
  523. NCDStatement * NCDBlock_NextStatement (NCDBlock *o, NCDStatement *es)
  524. {
  525. ASSERT(es)
  526. struct BlockStatement *cur_e = UPPER_OBJECT(es, struct BlockStatement, s);
  527. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->statements_list_node);
  528. if (!ln) {
  529. return NULL;
  530. }
  531. struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
  532. return &e->s;
  533. }
  534. size_t NCDBlock_NumStatements (NCDBlock *o)
  535. {
  536. return o->count;
  537. }
  538. int NCDStatement_InitReg (NCDStatement *o, const char *name, const char *objname, const char *cmdname, NCDValue args)
  539. {
  540. ASSERT(cmdname)
  541. ASSERT(NCDValue_Type(&args) == NCDVALUE_LIST)
  542. o->name = NULL;
  543. o->reg.objname = NULL;
  544. o->reg.cmdname = NULL;
  545. if (name && !(o->name = strdup(name))) {
  546. goto fail;
  547. }
  548. if (objname && !(o->reg.objname = strdup(objname))) {
  549. goto fail;
  550. }
  551. if (!(o->reg.cmdname = strdup(cmdname))) {
  552. goto fail;
  553. }
  554. o->type = NCDSTATEMENT_REG;
  555. o->reg.args = args;
  556. return 1;
  557. fail:
  558. free(o->name);
  559. free(o->reg.objname);
  560. free(o->reg.cmdname);
  561. return 0;
  562. }
  563. int NCDStatement_InitIf (NCDStatement *o, const char *name, NCDIfBlock ifblock)
  564. {
  565. o->name = NULL;
  566. if (name && !(o->name = strdup(name))) {
  567. return 0;
  568. }
  569. o->type = NCDSTATEMENT_IF;
  570. o->ifc.ifblock = ifblock;
  571. o->ifc.have_else = 0;
  572. return 1;
  573. }
  574. int NCDStatement_InitForeach (NCDStatement *o, const char *name, NCDValue collection, const char *name1, const char *name2, NCDBlock block)
  575. {
  576. ASSERT(name1)
  577. o->name = NULL;
  578. o->foreach.name1 = NULL;
  579. o->foreach.name2 = NULL;
  580. if (name && !(o->name = strdup(name))) {
  581. goto fail;
  582. }
  583. if (!(o->foreach.name1 = strdup(name1))) {
  584. goto fail;
  585. }
  586. if (name2 && !(o->foreach.name2 = strdup(name2))) {
  587. goto fail;
  588. }
  589. o->type = NCDSTATEMENT_FOREACH;
  590. o->foreach.collection = collection;
  591. o->foreach.block = block;
  592. o->foreach.is_grabbed = 0;
  593. return 1;
  594. fail:
  595. free(o->name);
  596. free(o->foreach.name1);
  597. free(o->foreach.name2);
  598. return 0;
  599. }
  600. void NCDStatement_Free (NCDStatement *o)
  601. {
  602. switch (o->type) {
  603. case NCDSTATEMENT_REG: {
  604. NCDValue_Free(&o->reg.args);
  605. free(o->reg.cmdname);
  606. free(o->reg.objname);
  607. } break;
  608. case NCDSTATEMENT_IF: {
  609. if (o->ifc.have_else) {
  610. NCDBlock_Free(&o->ifc.else_block);
  611. }
  612. NCDIfBlock_Free(&o->ifc.ifblock);
  613. } break;
  614. case NCDSTATEMENT_FOREACH: {
  615. if (!o->foreach.is_grabbed) {
  616. NCDBlock_Free(&o->foreach.block);
  617. NCDValue_Free(&o->foreach.collection);
  618. }
  619. free(o->foreach.name2);
  620. free(o->foreach.name1);
  621. } break;
  622. default: ASSERT(0);
  623. }
  624. free(o->name);
  625. }
  626. int NCDStatement_Type (NCDStatement *o)
  627. {
  628. return o->type;
  629. }
  630. const char * NCDStatement_Name (NCDStatement *o)
  631. {
  632. return o->name;
  633. }
  634. const char * NCDStatement_RegObjName (NCDStatement *o)
  635. {
  636. ASSERT(o->type == NCDSTATEMENT_REG)
  637. return o->reg.objname;
  638. }
  639. const char * NCDStatement_RegCmdName (NCDStatement *o)
  640. {
  641. ASSERT(o->type == NCDSTATEMENT_REG)
  642. return o->reg.cmdname;
  643. }
  644. NCDValue * NCDStatement_RegArgs (NCDStatement *o)
  645. {
  646. ASSERT(o->type == NCDSTATEMENT_REG)
  647. return &o->reg.args;
  648. }
  649. NCDIfBlock * NCDStatement_IfBlock (NCDStatement *o)
  650. {
  651. ASSERT(o->type == NCDSTATEMENT_IF)
  652. return &o->ifc.ifblock;
  653. }
  654. void NCDStatement_IfAddElse (NCDStatement *o, NCDBlock else_block)
  655. {
  656. ASSERT(o->type == NCDSTATEMENT_IF)
  657. ASSERT(!o->ifc.have_else)
  658. o->ifc.have_else = 1;
  659. o->ifc.else_block = else_block;
  660. }
  661. NCDBlock * NCDStatement_IfElse (NCDStatement *o)
  662. {
  663. ASSERT(o->type == NCDSTATEMENT_IF)
  664. if (!o->ifc.have_else) {
  665. return NULL;
  666. }
  667. return &o->ifc.else_block;
  668. }
  669. NCDBlock NCDStatement_IfGrabElse (NCDStatement *o)
  670. {
  671. ASSERT(o->type == NCDSTATEMENT_IF)
  672. ASSERT(o->ifc.have_else)
  673. o->ifc.have_else = 0;
  674. return o->ifc.else_block;
  675. }
  676. NCDValue * NCDStatement_ForeachCollection (NCDStatement *o)
  677. {
  678. ASSERT(o->type == NCDSTATEMENT_FOREACH)
  679. ASSERT(!o->foreach.is_grabbed)
  680. return &o->foreach.collection;
  681. }
  682. const char * NCDStatement_ForeachName1 (NCDStatement *o)
  683. {
  684. ASSERT(o->type == NCDSTATEMENT_FOREACH)
  685. return o->foreach.name1;
  686. }
  687. const char * NCDStatement_ForeachName2 (NCDStatement *o)
  688. {
  689. ASSERT(o->type == NCDSTATEMENT_FOREACH)
  690. return o->foreach.name2;
  691. }
  692. NCDBlock * NCDStatement_ForeachBlock (NCDStatement *o)
  693. {
  694. ASSERT(o->type == NCDSTATEMENT_FOREACH)
  695. ASSERT(!o->foreach.is_grabbed)
  696. return &o->foreach.block;
  697. }
  698. void NCDStatement_ForeachGrab (NCDStatement *o, NCDValue *out_collection, NCDBlock *out_block)
  699. {
  700. ASSERT(o->type == NCDSTATEMENT_FOREACH)
  701. ASSERT(!o->foreach.is_grabbed)
  702. *out_collection = o->foreach.collection;
  703. *out_block = o->foreach.block;
  704. o->foreach.is_grabbed = 1;
  705. }
  706. void NCDIfBlock_Init (NCDIfBlock *o)
  707. {
  708. LinkedList1_Init(&o->ifs_list);
  709. }
  710. void NCDIfBlock_Free (NCDIfBlock *o)
  711. {
  712. LinkedList1Node *ln;
  713. while (ln = LinkedList1_GetFirst(&o->ifs_list)) {
  714. struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
  715. NCDIf_Free(&e->ifc);
  716. LinkedList1_Remove(&o->ifs_list, &e->ifs_list_node);
  717. free(e);
  718. }
  719. }
  720. int NCDIfBlock_PrependIf (NCDIfBlock *o, NCDIf ifc)
  721. {
  722. struct IfBlockIf *e = malloc(sizeof(*e));
  723. if (!e) {
  724. return 0;
  725. }
  726. LinkedList1_Prepend(&o->ifs_list, &e->ifs_list_node);
  727. e->ifc = ifc;
  728. return 1;
  729. }
  730. NCDIf * NCDIfBlock_FirstIf (NCDIfBlock *o)
  731. {
  732. LinkedList1Node *ln = LinkedList1_GetFirst(&o->ifs_list);
  733. if (!ln) {
  734. return NULL;
  735. }
  736. struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
  737. return &e->ifc;
  738. }
  739. NCDIf * NCDIfBlock_NextIf (NCDIfBlock *o, NCDIf *ei)
  740. {
  741. ASSERT(ei)
  742. struct IfBlockIf *cur_e = UPPER_OBJECT(ei, struct IfBlockIf, ifc);
  743. LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->ifs_list_node);
  744. if (!ln) {
  745. return NULL;
  746. }
  747. struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
  748. return &e->ifc;
  749. }
  750. NCDIf NCDIfBlock_GrabIf (NCDIfBlock *o, NCDIf *ei)
  751. {
  752. ASSERT(ei)
  753. struct IfBlockIf *e = UPPER_OBJECT(ei, struct IfBlockIf, ifc);
  754. NCDIf old_ifc = e->ifc;
  755. LinkedList1_Remove(&o->ifs_list, &e->ifs_list_node);
  756. free(e);
  757. return old_ifc;
  758. }
  759. void NCDIf_Init (NCDIf *o, NCDValue cond, NCDBlock block)
  760. {
  761. o->cond = cond;
  762. o->block = block;
  763. }
  764. void NCDIf_Free (NCDIf *o)
  765. {
  766. NCDValue_Free(&o->cond);
  767. NCDBlock_Free(&o->block);
  768. }
  769. void NCDIf_FreeGrab (NCDIf *o, NCDValue *out_cond, NCDBlock *out_block)
  770. {
  771. *out_cond = o->cond;
  772. *out_block = o->block;
  773. }
  774. NCDValue * NCDIf_Cond (NCDIf *o)
  775. {
  776. return &o->cond;
  777. }
  778. NCDBlock * NCDIf_Block (NCDIf *o)
  779. {
  780. return &o->block;
  781. }