BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 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  
30 #include <stdlib.h>
31 #include <limits.h>
32 #include <string.h>
33  
34 #include <misc/offset.h>
35 #include <misc/strdup.h>
36  
37 #include "NCDAst.h"
38  
39 struct NCDValue__list_element {
40 LinkedList1Node list_node;
41 NCDValue v;
42 };
43  
44 struct NCDValue__map_element {
45 LinkedList1Node list_node;
46 NCDValue key;
47 NCDValue val;
48 };
49  
50 struct ProgramElem {
51 LinkedList1Node elems_list_node;
52 NCDProgramElem elem;
53 };
54  
55 struct BlockStatement {
56 LinkedList1Node statements_list_node;
57 NCDStatement s;
58 };
59  
60 struct IfBlockIf {
61 LinkedList1Node ifs_list_node;
62 NCDIf ifc;
63 };
64  
65 static void value_assert (NCDValue *o)
66 {
67 switch (o->type) {
68 case NCDVALUE_STRING:
69 case NCDVALUE_LIST:
70 case NCDVALUE_MAP:
71 case NCDVALUE_VAR:
72 case NCDVALUE_INVOC:
73 return;
74 default:
75 ASSERT(0);
76 }
77 }
78  
79 void NCDValue_Free (NCDValue *o)
80 {
81 switch (o->type) {
82 case NCDVALUE_STRING: {
83 free(o->string);
84 } break;
85  
86 case NCDVALUE_LIST: {
87 LinkedList1Node *n;
88 while (n = LinkedList1_GetFirst(&o->list)) {
89 struct NCDValue__list_element *e = UPPER_OBJECT(n, struct NCDValue__list_element, list_node);
90  
91 NCDValue_Free(&e->v);
92 LinkedList1_Remove(&o->list, &e->list_node);
93 free(e);
94 }
95 } break;
96  
97 case NCDVALUE_MAP: {
98 LinkedList1Node *n;
99 while (n = LinkedList1_GetFirst(&o->map_list)) {
100 struct NCDValue__map_element *e = UPPER_OBJECT(n, struct NCDValue__map_element, list_node);
101  
102 LinkedList1_Remove(&o->map_list, &e->list_node);
103 NCDValue_Free(&e->key);
104 NCDValue_Free(&e->val);
105 free(e);
106 }
107 } break;
108  
109 case NCDVALUE_VAR: {
110 free(o->var_name);
111 } break;
112  
113 case NCDVALUE_INVOC: {
114 NCDValue_Free(o->invoc_arg);
115 NCDValue_Free(o->invoc_func);
116 free(o->invoc_arg);
117 free(o->invoc_func);
118 } break;
119  
120 default:
121 ASSERT(0);
122 }
123 }
124  
125 int NCDValue_Type (NCDValue *o)
126 {
127 value_assert(o);
128  
129 return o->type;
130 }
131  
132 int NCDValue_InitString (NCDValue *o, const char *str)
133 {
134 return NCDValue_InitStringBin(o, (const uint8_t *)str, strlen(str));
135 }
136  
137 int NCDValue_InitStringBin (NCDValue *o, const uint8_t *str, size_t len)
138 {
139 if (len == SIZE_MAX) {
140 return 0;
141 }
142  
143 if (!(o->string = malloc(len + 1))) {
144 return 0;
145 }
146  
147 memcpy(o->string, str, len);
148 o->string[len] = '\0';
149 o->string_len = len;
150  
151 o->type = NCDVALUE_STRING;
152  
153 return 1;
154 }
155  
156 const char * NCDValue_StringValue (NCDValue *o)
157 {
158 ASSERT(o->type == NCDVALUE_STRING)
159  
160 return (char *)o->string;
161 }
162  
163 size_t NCDValue_StringLength (NCDValue *o)
164 {
165 ASSERT(o->type == NCDVALUE_STRING)
166  
167 return o->string_len;
168 }
169  
170 void NCDValue_InitList (NCDValue *o)
171 {
172 o->type = NCDVALUE_LIST;
173 LinkedList1_Init(&o->list);
174 o->list_count = 0;
175 }
176  
177 size_t NCDValue_ListCount (NCDValue *o)
178 {
179 value_assert(o);
180 ASSERT(o->type == NCDVALUE_LIST)
181  
182 return o->list_count;
183 }
184  
185 int NCDValue_ListAppend (NCDValue *o, NCDValue v)
186 {
187 value_assert(o);
188 ASSERT(o->type == NCDVALUE_LIST)
189 value_assert(&v);
190  
191 if (o->list_count == SIZE_MAX) {
192 return 0;
193 }
194  
195 struct NCDValue__list_element *e = malloc(sizeof(*e));
196 if (!e) {
197 return 0;
198 }
199  
200 e->v = v;
201 LinkedList1_Append(&o->list, &e->list_node);
202  
203 o->list_count++;
204  
205 return 1;
206 }
207  
208 int NCDValue_ListPrepend (NCDValue *o, NCDValue v)
209 {
210 value_assert(o);
211 ASSERT(o->type == NCDVALUE_LIST)
212 value_assert(&v);
213  
214 if (o->list_count == SIZE_MAX) {
215 return 0;
216 }
217  
218 struct NCDValue__list_element *e = malloc(sizeof(*e));
219 if (!e) {
220 return 0;
221 }
222  
223 e->v = v;
224 LinkedList1_Prepend(&o->list, &e->list_node);
225  
226 o->list_count++;
227  
228 return 1;
229 }
230  
231 NCDValue * NCDValue_ListFirst (NCDValue *o)
232 {
233 value_assert(o);
234 ASSERT(o->type == NCDVALUE_LIST)
235  
236 LinkedList1Node *ln = LinkedList1_GetFirst(&o->list);
237  
238 if (!ln) {
239 return NULL;
240 }
241  
242 struct NCDValue__list_element *e = UPPER_OBJECT(ln, struct NCDValue__list_element, list_node);
243  
244 return &e->v;
245 }
246  
247 NCDValue * NCDValue_ListNext (NCDValue *o, NCDValue *ev)
248 {
249 value_assert(o);
250 ASSERT(o->type == NCDVALUE_LIST)
251  
252 struct NCDValue__list_element *cur_e = UPPER_OBJECT(ev, struct NCDValue__list_element, v);
253 LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->list_node);
254  
255 if (!ln) {
256 return NULL;
257 }
258  
259 struct NCDValue__list_element *e = UPPER_OBJECT(ln, struct NCDValue__list_element, list_node);
260  
261 return &e->v;
262 }
263  
264 void NCDValue_InitMap (NCDValue *o)
265 {
266 o->type = NCDVALUE_MAP;
267 LinkedList1_Init(&o->map_list);
268 o->map_count = 0;
269 }
270  
271 size_t NCDValue_MapCount (NCDValue *o)
272 {
273 value_assert(o);
274 ASSERT(o->type == NCDVALUE_MAP)
275  
276 return o->map_count;
277 }
278  
279 int NCDValue_MapPrepend (NCDValue *o, NCDValue key, NCDValue val)
280 {
281 value_assert(o);
282 ASSERT(o->type == NCDVALUE_MAP)
283 value_assert(&key);
284 value_assert(&val);
285  
286 if (o->map_count == SIZE_MAX) {
287 return 0;
288 }
289  
290 struct NCDValue__map_element *e = malloc(sizeof(*e));
291 if (!e) {
292 return 0;
293 }
294  
295 e->key = key;
296 e->val = val;
297 LinkedList1_Prepend(&o->map_list, &e->list_node);
298  
299 o->map_count++;
300  
301 return 1;
302 }
303  
304 NCDValue * NCDValue_MapFirstKey (NCDValue *o)
305 {
306 value_assert(o);
307 ASSERT(o->type == NCDVALUE_MAP)
308  
309 LinkedList1Node *ln = LinkedList1_GetFirst(&o->map_list);
310  
311 if (!ln) {
312 return NULL;
313 }
314  
315 struct NCDValue__map_element *e = UPPER_OBJECT(ln, struct NCDValue__map_element, list_node);
316  
317 value_assert(&e->key);
318 value_assert(&e->val);
319  
320 return &e->key;
321 }
322  
323 NCDValue * NCDValue_MapNextKey (NCDValue *o, NCDValue *ekey)
324 {
325 value_assert(o);
326 ASSERT(o->type == NCDVALUE_MAP)
327  
328 struct NCDValue__map_element *e0 = UPPER_OBJECT(ekey, struct NCDValue__map_element, key);
329 value_assert(&e0->key);
330 value_assert(&e0->val);
331  
332 LinkedList1Node *ln = LinkedList1Node_Next(&e0->list_node);
333  
334 if (!ln) {
335 return NULL;
336 }
337  
338 struct NCDValue__map_element *e = UPPER_OBJECT(ln, struct NCDValue__map_element, list_node);
339  
340 value_assert(&e->key);
341 value_assert(&e->val);
342  
343 return &e->key;
344 }
345  
346 NCDValue * NCDValue_MapKeyValue (NCDValue *o, NCDValue *ekey)
347 {
348 value_assert(o);
349 ASSERT(o->type == NCDVALUE_MAP)
350  
351 struct NCDValue__map_element *e = UPPER_OBJECT(ekey, struct NCDValue__map_element, key);
352 value_assert(&e->key);
353 value_assert(&e->val);
354  
355 return &e->val;
356 }
357  
358 int NCDValue_InitVar (NCDValue *o, const char *var_name)
359 {
360 ASSERT(var_name)
361  
362 if (!(o->var_name = strdup(var_name))) {
363 return 0;
364 }
365  
366 o->type = NCDVALUE_VAR;
367  
368 return 1;
369 }
370  
371 const char * NCDValue_VarName (NCDValue *o)
372 {
373 value_assert(o);
374 ASSERT(o->type == NCDVALUE_VAR)
375  
376 return o->var_name;
377 }
378  
379 int NCDValue_InitInvoc (NCDValue *o, NCDValue func, NCDValue arg)
380 {
381 value_assert(&func);
382 value_assert(&arg);
383  
384 if (!(o->invoc_func = malloc(sizeof(*o->invoc_func)))) {
385 goto fail0;
386 }
387 if (!(o->invoc_arg = malloc(sizeof(*o->invoc_arg)))) {
388 goto fail1;
389 }
390  
391 *o->invoc_func = func;
392 *o->invoc_arg = arg;
393  
394 o->type = NCDVALUE_INVOC;
395  
396 return 1;
397  
398 fail1:
399 free(o->invoc_func);
400 fail0:
401 return 0;
402 }
403  
404 NCDValue * NCDValue_InvocFunc (NCDValue *o)
405 {
406 value_assert(o);
407 ASSERT(o->type == NCDVALUE_INVOC)
408  
409 return o->invoc_func;
410 }
411  
412 NCDValue * NCDValue_InvocArg (NCDValue *o)
413 {
414 value_assert(o);
415 ASSERT(o->type == NCDVALUE_INVOC)
416  
417 return o->invoc_arg;
418 }
419  
420 void NCDProgram_Init (NCDProgram *o)
421 {
422 LinkedList1_Init(&o->elems_list);
423 o->num_elems = 0;
424 }
425  
426 void NCDProgram_Free (NCDProgram *o)
427 {
428 LinkedList1Node *ln;
429 while (ln = LinkedList1_GetFirst(&o->elems_list)) {
430 struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
431 NCDProgramElem_Free(&e->elem);
432 LinkedList1_Remove(&o->elems_list, &e->elems_list_node);
433 free(e);
434 }
435 }
436  
437 NCDProgramElem * NCDProgram_PrependElem (NCDProgram *o, NCDProgramElem elem)
438 {
439 if (o->num_elems == SIZE_MAX) {
440 return NULL;
441 }
442  
443 struct ProgramElem *e = malloc(sizeof(*e));
444 if (!e) {
445 return NULL;
446 }
447  
448 LinkedList1_Prepend(&o->elems_list, &e->elems_list_node);
449 e->elem = elem;
450  
451 o->num_elems++;
452  
453 return &e->elem;
454 }
455  
456 NCDProgramElem * NCDProgram_FirstElem (NCDProgram *o)
457 {
458 LinkedList1Node *ln = LinkedList1_GetFirst(&o->elems_list);
459 if (!ln) {
460 return NULL;
461 }
462  
463 struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
464  
465 return &e->elem;
466 }
467  
468 NCDProgramElem * NCDProgram_NextElem (NCDProgram *o, NCDProgramElem *ee)
469 {
470 ASSERT(ee)
471  
472 struct ProgramElem *cur_e = UPPER_OBJECT(ee, struct ProgramElem, elem);
473  
474 LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->elems_list_node);
475 if (!ln) {
476 return NULL;
477 }
478  
479 struct ProgramElem *e = UPPER_OBJECT(ln, struct ProgramElem, elems_list_node);
480  
481 return &e->elem;
482 }
483  
484 size_t NCDProgram_NumElems (NCDProgram *o)
485 {
486 return o->num_elems;
487 }
488  
489 int NCDProgram_ContainsElemType (NCDProgram *o, int elem_type)
490 {
491 for (NCDProgramElem *elem = NCDProgram_FirstElem(o); elem; elem = NCDProgram_NextElem(o, elem)) {
492 if (NCDProgramElem_Type(elem) == elem_type) {
493 return 1;
494 }
495 }
496  
497 return 0;
498 }
499  
500 void NCDProgram_RemoveElem (NCDProgram *o, NCDProgramElem *ee)
501 {
502 ASSERT(ee)
503  
504 struct ProgramElem *e = UPPER_OBJECT(ee, struct ProgramElem, elem);
505 NCDProgramElem_Free(&e->elem);
506 LinkedList1_Remove(&o->elems_list, &e->elems_list_node);
507 free(e);
508  
509 ASSERT(o->num_elems > 0)
510 o->num_elems--;
511 }
512  
513 int NCDProgram_ReplaceElemWithProgram (NCDProgram *o, NCDProgramElem *ee, NCDProgram replace_prog)
514 {
515 ASSERT(ee)
516  
517 if (replace_prog.num_elems > SIZE_MAX - o->num_elems) {
518 return 0;
519 }
520  
521 struct ProgramElem *e = UPPER_OBJECT(ee, struct ProgramElem, elem);
522  
523 LinkedList1_InsertListAfter(&o->elems_list, replace_prog.elems_list, &e->elems_list_node);
524 o->num_elems += replace_prog.num_elems;
525  
526 NCDProgram_RemoveElem(o, ee);
527  
528 return 1;
529 }
530  
531 void NCDProgramElem_InitProcess (NCDProgramElem *o, NCDProcess process)
532 {
533 o->type = NCDPROGRAMELEM_PROCESS;
534 o->process = process;
535 }
536  
537 int NCDProgramElem_InitInclude (NCDProgramElem *o, const char *path_data, size_t path_length)
538 {
539 if (!(o->include.path_data = b_strdup_bin(path_data, path_length))) {
540 return 0;
541 }
542  
543 o->type = NCDPROGRAMELEM_INCLUDE;
544 o->include.path_length = path_length;
545  
546 return 1;
547 }
548  
549 int NCDProgramElem_InitIncludeGuard (NCDProgramElem *o, const char *id_data, size_t id_length)
550 {
551 if (!(o->include_guard.id_data = b_strdup_bin(id_data, id_length))) {
552 return 0;
553 }
554  
555 o->type = NCDPROGRAMELEM_INCLUDE_GUARD;
556 o->include_guard.id_length = id_length;
557  
558 return 1;
559 }
560  
561  
562 void NCDProgramElem_Free (NCDProgramElem *o)
563 {
564 switch (o->type) {
565 case NCDPROGRAMELEM_PROCESS: {
566 NCDProcess_Free(&o->process);
567 } break;
568  
569 case NCDPROGRAMELEM_INCLUDE: {
570 free(o->include.path_data);
571 } break;
572  
573 case NCDPROGRAMELEM_INCLUDE_GUARD: {
574 free(o->include_guard.id_data);
575 } break;
576  
577 default: ASSERT(0);
578 }
579 }
580  
581 int NCDProgramElem_Type (NCDProgramElem *o)
582 {
583 return o->type;
584 }
585  
586 NCDProcess * NCDProgramElem_Process (NCDProgramElem *o)
587 {
588 ASSERT(o->type == NCDPROGRAMELEM_PROCESS)
589  
590 return &o->process;
591 }
592  
593 const char * NCDProgramElem_IncludePathData (NCDProgramElem *o)
594 {
595 ASSERT(o->type == NCDPROGRAMELEM_INCLUDE)
596  
597 return o->include.path_data;
598 }
599  
600 size_t NCDProgramElem_IncludePathLength (NCDProgramElem *o)
601 {
602 ASSERT(o->type == NCDPROGRAMELEM_INCLUDE)
603  
604 return o->include.path_length;
605 }
606  
607 const char * NCDProgramElem_IncludeGuardIdData (NCDProgramElem *o)
608 {
609 ASSERT(o->type == NCDPROGRAMELEM_INCLUDE_GUARD)
610  
611 return o->include_guard.id_data;
612 }
613  
614 size_t NCDProgramElem_IncludeGuardIdLength (NCDProgramElem *o)
615 {
616 ASSERT(o->type == NCDPROGRAMELEM_INCLUDE_GUARD)
617  
618 return o->include_guard.id_length;
619 }
620  
621 int NCDProcess_Init (NCDProcess *o, int is_template, const char *name, NCDBlock block)
622 {
623 ASSERT(is_template == !!is_template)
624 ASSERT(name)
625  
626 if (!(o->name = strdup(name))) {
627 return 0;
628 }
629  
630 o->is_template = is_template;
631 o->block = block;
632  
633 return 1;
634 }
635  
636 void NCDProcess_Free (NCDProcess *o)
637 {
638 NCDBlock_Free(&o->block);
639 free(o->name);
640 }
641  
642 int NCDProcess_IsTemplate (NCDProcess *o)
643 {
644 return o->is_template;
645 }
646  
647 const char * NCDProcess_Name (NCDProcess *o)
648 {
649 return o->name;
650 }
651  
652 NCDBlock * NCDProcess_Block (NCDProcess *o)
653 {
654 return &o->block;
655 }
656  
657 void NCDBlock_Init (NCDBlock *o)
658 {
659 LinkedList1_Init(&o->statements_list);
660 o->count = 0;
661 }
662  
663 void NCDBlock_Free (NCDBlock *o)
664 {
665 LinkedList1Node *ln;
666 while (ln = LinkedList1_GetFirst(&o->statements_list)) {
667 struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
668 NCDStatement_Free(&e->s);
669 LinkedList1_Remove(&o->statements_list, &e->statements_list_node);
670 free(e);
671 }
672 }
673  
674 int NCDBlock_PrependStatement (NCDBlock *o, NCDStatement s)
675 {
676 return NCDBlock_InsertStatementAfter(o, NULL, s);
677 }
678  
679 int NCDBlock_InsertStatementAfter (NCDBlock *o, NCDStatement *after, NCDStatement s)
680 {
681 struct BlockStatement *after_e = NULL;
682 if (after) {
683 after_e = UPPER_OBJECT(after, struct BlockStatement, s);
684 }
685  
686 if (o->count == SIZE_MAX) {
687 return 0;
688 }
689  
690 struct BlockStatement *e = malloc(sizeof(*e));
691 if (!e) {
692 return 0;
693 }
694  
695 if (after_e) {
696 LinkedList1_InsertAfter(&o->statements_list, &e->statements_list_node, &after_e->statements_list_node);
697 } else {
698 LinkedList1_Prepend(&o->statements_list, &e->statements_list_node);
699 }
700 e->s = s;
701  
702 o->count++;
703  
704 return 1;
705 }
706  
707 NCDStatement * NCDBlock_ReplaceStatement (NCDBlock *o, NCDStatement *es, NCDStatement s)
708 {
709 ASSERT(es)
710  
711 struct BlockStatement *e = UPPER_OBJECT(es, struct BlockStatement, s);
712  
713 NCDStatement_Free(&e->s);
714 e->s = s;
715  
716 return &e->s;
717 }
718  
719 NCDStatement * NCDBlock_FirstStatement (NCDBlock *o)
720 {
721 LinkedList1Node *ln = LinkedList1_GetFirst(&o->statements_list);
722 if (!ln) {
723 return NULL;
724 }
725  
726 struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
727  
728 return &e->s;
729 }
730  
731 NCDStatement * NCDBlock_NextStatement (NCDBlock *o, NCDStatement *es)
732 {
733 ASSERT(es)
734  
735 struct BlockStatement *cur_e = UPPER_OBJECT(es, struct BlockStatement, s);
736  
737 LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->statements_list_node);
738 if (!ln) {
739 return NULL;
740 }
741  
742 struct BlockStatement *e = UPPER_OBJECT(ln, struct BlockStatement, statements_list_node);
743  
744 return &e->s;
745 }
746  
747 size_t NCDBlock_NumStatements (NCDBlock *o)
748 {
749 return o->count;
750 }
751  
752 int NCDStatement_InitReg (NCDStatement *o, const char *name, const char *objname, const char *cmdname, NCDValue args)
753 {
754 ASSERT(cmdname)
755 ASSERT(NCDValue_Type(&args) == NCDVALUE_LIST)
756  
757 o->name = NULL;
758 o->reg.objname = NULL;
759 o->reg.cmdname = NULL;
760  
761 if (name && !(o->name = strdup(name))) {
762 goto fail;
763 }
764  
765 if (objname && !(o->reg.objname = strdup(objname))) {
766 goto fail;
767 }
768  
769 if (!(o->reg.cmdname = strdup(cmdname))) {
770 goto fail;
771 }
772  
773 o->type = NCDSTATEMENT_REG;
774 o->reg.args = args;
775  
776 return 1;
777  
778 fail:
779 free(o->name);
780 free(o->reg.objname);
781 free(o->reg.cmdname);
782 return 0;
783 }
784  
785 int NCDStatement_InitIf (NCDStatement *o, const char *name, NCDIfBlock ifblock, int iftype)
786 {
787 o->name = NULL;
788  
789 if (name && !(o->name = strdup(name))) {
790 return 0;
791 }
792  
793 o->type = NCDSTATEMENT_IF;
794 o->ifc.ifblock = ifblock;
795 o->ifc.have_else = 0;
796 o->ifc.iftype = iftype;
797  
798 return 1;
799 }
800  
801 int NCDStatement_InitForeach (NCDStatement *o, const char *name, NCDValue collection, const char *name1, const char *name2, NCDBlock block)
802 {
803 ASSERT(name1)
804  
805 o->name = NULL;
806 o->foreach.name1 = NULL;
807 o->foreach.name2 = NULL;
808  
809 if (name && !(o->name = strdup(name))) {
810 goto fail;
811 }
812  
813 if (!(o->foreach.name1 = strdup(name1))) {
814 goto fail;
815 }
816  
817 if (name2 && !(o->foreach.name2 = strdup(name2))) {
818 goto fail;
819 }
820  
821 o->type = NCDSTATEMENT_FOREACH;
822 o->foreach.collection = collection;
823 o->foreach.block = block;
824 o->foreach.is_grabbed = 0;
825  
826 return 1;
827  
828 fail:
829 free(o->name);
830 free(o->foreach.name1);
831 free(o->foreach.name2);
832 return 0;
833 }
834  
835 int NCDStatement_InitBlock (NCDStatement *o, const char *name, NCDBlock block)
836 {
837 o->name = NULL;
838  
839 if (name && !(o->name = strdup(name))) {
840 return 0;
841 }
842  
843 o->type = NCDSTATEMENT_BLOCK;
844 o->block.block = block;
845 o->block.is_grabbed = 0;
846  
847 return 1;
848 }
849  
850 void NCDStatement_Free (NCDStatement *o)
851 {
852 switch (o->type) {
853 case NCDSTATEMENT_REG: {
854 NCDValue_Free(&o->reg.args);
855 free(o->reg.cmdname);
856 free(o->reg.objname);
857 } break;
858  
859 case NCDSTATEMENT_IF: {
860 if (o->ifc.have_else) {
861 NCDBlock_Free(&o->ifc.else_block);
862 }
863  
864 NCDIfBlock_Free(&o->ifc.ifblock);
865 } break;
866  
867 case NCDSTATEMENT_FOREACH: {
868 if (!o->foreach.is_grabbed) {
869 NCDBlock_Free(&o->foreach.block);
870 NCDValue_Free(&o->foreach.collection);
871 }
872 free(o->foreach.name2);
873 free(o->foreach.name1);
874 } break;
875  
876 case NCDSTATEMENT_BLOCK: {
877 if (!o->block.is_grabbed) {
878 NCDBlock_Free(&o->block.block);
879 }
880 } break;
881  
882 default: ASSERT(0);
883 }
884  
885 free(o->name);
886 }
887  
888 int NCDStatement_Type (NCDStatement *o)
889 {
890 return o->type;
891 }
892  
893 const char * NCDStatement_Name (NCDStatement *o)
894 {
895 return o->name;
896 }
897  
898 const char * NCDStatement_RegObjName (NCDStatement *o)
899 {
900 ASSERT(o->type == NCDSTATEMENT_REG)
901  
902 return o->reg.objname;
903 }
904  
905 const char * NCDStatement_RegCmdName (NCDStatement *o)
906 {
907 ASSERT(o->type == NCDSTATEMENT_REG)
908  
909 return o->reg.cmdname;
910 }
911  
912 NCDValue * NCDStatement_RegArgs (NCDStatement *o)
913 {
914 ASSERT(o->type == NCDSTATEMENT_REG)
915  
916 return &o->reg.args;
917 }
918  
919 int NCDStatement_IfType (NCDStatement *o)
920 {
921 ASSERT(o->type == NCDSTATEMENT_IF)
922  
923 return o->ifc.iftype;
924 }
925  
926 NCDIfBlock * NCDStatement_IfBlock (NCDStatement *o)
927 {
928 ASSERT(o->type == NCDSTATEMENT_IF)
929  
930 return &o->ifc.ifblock;
931 }
932  
933 void NCDStatement_IfAddElse (NCDStatement *o, NCDBlock else_block)
934 {
935 ASSERT(o->type == NCDSTATEMENT_IF)
936 ASSERT(!o->ifc.have_else)
937  
938 o->ifc.have_else = 1;
939 o->ifc.else_block = else_block;
940 }
941  
942 NCDBlock * NCDStatement_IfElse (NCDStatement *o)
943 {
944 ASSERT(o->type == NCDSTATEMENT_IF)
945  
946 if (!o->ifc.have_else) {
947 return NULL;
948 }
949  
950 return &o->ifc.else_block;
951 }
952  
953 NCDBlock NCDStatement_IfGrabElse (NCDStatement *o)
954 {
955 ASSERT(o->type == NCDSTATEMENT_IF)
956 ASSERT(o->ifc.have_else)
957  
958 o->ifc.have_else = 0;
959  
960 return o->ifc.else_block;
961 }
962  
963 NCDValue * NCDStatement_ForeachCollection (NCDStatement *o)
964 {
965 ASSERT(o->type == NCDSTATEMENT_FOREACH)
966 ASSERT(!o->foreach.is_grabbed)
967  
968 return &o->foreach.collection;
969 }
970  
971 const char * NCDStatement_ForeachName1 (NCDStatement *o)
972 {
973 ASSERT(o->type == NCDSTATEMENT_FOREACH)
974  
975 return o->foreach.name1;
976 }
977  
978 const char * NCDStatement_ForeachName2 (NCDStatement *o)
979 {
980 ASSERT(o->type == NCDSTATEMENT_FOREACH)
981  
982 return o->foreach.name2;
983 }
984  
985 NCDBlock * NCDStatement_ForeachBlock (NCDStatement *o)
986 {
987 ASSERT(o->type == NCDSTATEMENT_FOREACH)
988 ASSERT(!o->foreach.is_grabbed)
989  
990 return &o->foreach.block;
991 }
992  
993 void NCDStatement_ForeachGrab (NCDStatement *o, NCDValue *out_collection, NCDBlock *out_block)
994 {
995 ASSERT(o->type == NCDSTATEMENT_FOREACH)
996 ASSERT(!o->foreach.is_grabbed)
997  
998 *out_collection = o->foreach.collection;
999 *out_block = o->foreach.block;
1000 o->foreach.is_grabbed = 1;
1001 }
1002  
1003 NCDBlock * NCDStatement_BlockBlock (NCDStatement *o)
1004 {
1005 ASSERT(o->type == NCDSTATEMENT_BLOCK)
1006 ASSERT(!o->block.is_grabbed)
1007  
1008 return &o->block.block;
1009 }
1010  
1011 NCDBlock NCDStatement_BlockGrabBlock (NCDStatement *o)
1012 {
1013 ASSERT(o->type == NCDSTATEMENT_BLOCK)
1014 ASSERT(!o->block.is_grabbed)
1015  
1016 o->block.is_grabbed = 1;
1017 return o->block.block;
1018 }
1019  
1020 void NCDIfBlock_Init (NCDIfBlock *o)
1021 {
1022 LinkedList1_Init(&o->ifs_list);
1023 }
1024  
1025 void NCDIfBlock_Free (NCDIfBlock *o)
1026 {
1027 LinkedList1Node *ln;
1028 while (ln = LinkedList1_GetFirst(&o->ifs_list)) {
1029 struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
1030 NCDIf_Free(&e->ifc);
1031 LinkedList1_Remove(&o->ifs_list, &e->ifs_list_node);
1032 free(e);
1033 }
1034 }
1035  
1036 int NCDIfBlock_PrependIf (NCDIfBlock *o, NCDIf ifc)
1037 {
1038 struct IfBlockIf *e = malloc(sizeof(*e));
1039 if (!e) {
1040 return 0;
1041 }
1042  
1043 LinkedList1_Prepend(&o->ifs_list, &e->ifs_list_node);
1044 e->ifc = ifc;
1045  
1046 return 1;
1047 }
1048  
1049 NCDIf * NCDIfBlock_FirstIf (NCDIfBlock *o)
1050 {
1051 LinkedList1Node *ln = LinkedList1_GetFirst(&o->ifs_list);
1052 if (!ln) {
1053 return NULL;
1054 }
1055  
1056 struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
1057  
1058 return &e->ifc;
1059 }
1060  
1061 NCDIf * NCDIfBlock_NextIf (NCDIfBlock *o, NCDIf *ei)
1062 {
1063 ASSERT(ei)
1064  
1065 struct IfBlockIf *cur_e = UPPER_OBJECT(ei, struct IfBlockIf, ifc);
1066  
1067 LinkedList1Node *ln = LinkedList1Node_Next(&cur_e->ifs_list_node);
1068 if (!ln) {
1069 return NULL;
1070 }
1071  
1072 struct IfBlockIf *e = UPPER_OBJECT(ln, struct IfBlockIf, ifs_list_node);
1073  
1074 return &e->ifc;
1075 }
1076  
1077 NCDIf NCDIfBlock_GrabIf (NCDIfBlock *o, NCDIf *ei)
1078 {
1079 ASSERT(ei)
1080  
1081 struct IfBlockIf *e = UPPER_OBJECT(ei, struct IfBlockIf, ifc);
1082  
1083 NCDIf old_ifc = e->ifc;
1084  
1085 LinkedList1_Remove(&o->ifs_list, &e->ifs_list_node);
1086 free(e);
1087  
1088 return old_ifc;
1089 }
1090  
1091 void NCDIf_Init (NCDIf *o, NCDValue cond, NCDBlock block)
1092 {
1093 o->cond = cond;
1094 o->block = block;
1095 }
1096  
1097 void NCDIf_InitBlock (NCDIf *o, NCDBlock block)
1098 {
1099 NCDValue_InitList(&o->cond);
1100 o->block = block;
1101 }
1102  
1103 void NCDIf_Free (NCDIf *o)
1104 {
1105 NCDValue_Free(&o->cond);
1106 NCDBlock_Free(&o->block);
1107 }
1108  
1109 void NCDIf_FreeGrab (NCDIf *o, NCDValue *out_cond, NCDBlock *out_block)
1110 {
1111 *out_cond = o->cond;
1112 *out_block = o->block;
1113 }
1114  
1115 NCDBlock NCDIf_FreeGrabBlock (NCDIf *o)
1116 {
1117 NCDValue_Free(&o->cond);
1118 return o->block;
1119 }
1120  
1121 NCDValue * NCDIf_Cond (NCDIf *o)
1122 {
1123 return &o->cond;
1124 }
1125  
1126 NCDBlock * NCDIf_Block (NCDIf *o)
1127 {
1128 return &o->block;
1129 }