BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDConfigParser.y
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 {
31  
32 #include <string.h>
33 #include <stddef.h>
34  
35 #include <misc/debug.h>
36 #include <misc/concat_strings.h>
37 #include <ncd/NCDAst.h>
38  
39 struct parser_out {
40 int out_of_memory;
41 int syntax_error;
42 int have_ast;
43 NCDProgram ast;
44 };
45  
46 struct token {
47 char *str;
48 size_t len;
49 };
50  
51 struct program {
52 int have;
53 NCDProgram v;
54 };
55  
56 struct block {
57 int have;
58 NCDBlock v;
59 };
60  
61 struct statement {
62 int have;
63 NCDStatement v;
64 };
65  
66 struct ifblock {
67 int have;
68 NCDIfBlock v;
69 };
70  
71 struct value {
72 int have;
73 NCDValue v;
74 };
75  
76 static void free_token (struct token o) { free(o.str); }
77 static void free_program (struct program o) { if (o.have) NCDProgram_Free(&o.v); }
78 static void free_block (struct block o) { if (o.have) NCDBlock_Free(&o.v); }
79 static void free_statement (struct statement o) { if (o.have) NCDStatement_Free(&o.v); }
80 static void free_ifblock (struct ifblock o) { if (o.have) NCDIfBlock_Free(&o.v); }
81 static void free_value (struct value o) { if (o.have) NCDValue_Free(&o.v); }
82  
83 }
84  
85 %extra_argument { struct parser_out *parser_out }
86  
87 %token_type { struct token }
88  
89 %token_destructor { free_token($$); }
90  
91 %type processes { struct program }
92 %type statement { struct statement }
93 %type elif_maybe { struct ifblock }
94 %type elif { struct ifblock }
95 %type else_maybe { struct block }
96 %type statements { struct block }
97 %type dotted_name { char * }
98 %type list_contents_maybe { struct value }
99 %type list_contents { struct value }
100 %type list { struct value }
101 %type map_contents { struct value }
102 %type map { struct value }
103 %type invoc { struct value }
104 %type value { struct value }
105 %type name_maybe { char * }
106 %type process_or_template { int }
107 %type name_list { struct value }
108 %type interrupt_maybe { struct block }
109  
110 // mention parser_out in some destructor to avoid an unused-variable warning
111 %destructor processes { (void)parser_out; free_program($$); }
112 %destructor statement { free_statement($$); }
113 %destructor elif_maybe { free_ifblock($$); }
114 %destructor elif { free_ifblock($$); }
115 %destructor else_maybe { free_block($$); }
116 %destructor statements { free_block($$); }
117 %destructor dotted_name { free($$); }
118 %destructor list_contents_maybe { free_value($$); }
119 %destructor list_contents { free_value($$); }
120 %destructor list { free_value($$); }
121 %destructor map_contents { free_value($$); }
122 %destructor map { free_value($$); }
123 %destructor invoc { free_value($$); }
124 %destructor value { free_value($$); }
125 %destructor name_maybe { free($$); }
126 %destructor name_list { free_value($$); }
127 %destructor interrupt_maybe { free_block($$); }
128  
129 %stack_size 0
130  
131 %syntax_error {
132 parser_out->syntax_error = 1;
133 }
134  
135 // workaroud Lemon bug: if the stack overflows, the token that caused the overflow will be leaked
136 %stack_overflow {
137 if (yypMinor) {
138 free_token(yypMinor->yy0);
139 }
140 }
141  
142 input ::= processes(A). {
143 ASSERT(!parser_out->have_ast)
144  
145 if (A.have) {
146 parser_out->have_ast = 1;
147 parser_out->ast = A.v;
148 }
149 }
150  
151 processes(R) ::= . {
152 NCDProgram prog;
153 NCDProgram_Init(&prog);
154  
155 R.have = 1;
156 R.v = prog;
157 }
158  
159 processes(R) ::= INCLUDE STRING(A) processes(N). {
160 ASSERT(A.str)
161 if (!N.have) {
162 goto failA0;
163 }
164  
165 NCDProgramElem elem;
166 if (!NCDProgramElem_InitInclude(&elem, A.str, A.len)) {
167 goto failA0;
168 }
169  
170 if (!NCDProgram_PrependElem(&N.v, elem)) {
171 goto failA1;
172 }
173  
174 R.have = 1;
175 R.v = N.v;
176 N.have = 0;
177 goto doneA;
178  
179 failA1:
180 NCDProgramElem_Free(&elem);
181 failA0:
182 R.have = 0;
183 parser_out->out_of_memory = 1;
184 doneA:
185 free_token(A);
186 free_program(N);
187 }
188  
189 processes(R) ::= INCLUDE_GUARD STRING(A) processes(N). {
190 ASSERT(A.str)
191 if (!N.have) {
192 goto failZ0;
193 }
194  
195 NCDProgramElem elem;
196 if (!NCDProgramElem_InitIncludeGuard(&elem, A.str, A.len)) {
197 goto failZ0;
198 }
199  
200 if (!NCDProgram_PrependElem(&N.v, elem)) {
201 goto failZ1;
202 }
203  
204 R.have = 1;
205 R.v = N.v;
206 N.have = 0;
207 goto doneZ;
208  
209 failZ1:
210 NCDProgramElem_Free(&elem);
211 failZ0:
212 R.have = 0;
213 parser_out->out_of_memory = 1;
214 doneZ:
215 free_token(A);
216 free_program(N);
217 }
218  
219 processes(R) ::= process_or_template(T) NAME(A) CURLY_OPEN statements(B) CURLY_CLOSE processes(N). {
220 ASSERT(A.str)
221 if (!B.have || !N.have) {
222 goto failB0;
223 }
224  
225 NCDProcess proc;
226 if (!NCDProcess_Init(&proc, T, A.str, B.v)) {
227 goto failB0;
228 }
229 B.have = 0;
230  
231 NCDProgramElem elem;
232 NCDProgramElem_InitProcess(&elem, proc);
233  
234 if (!NCDProgram_PrependElem(&N.v, elem)) {
235 goto failB1;
236 }
237  
238 R.have = 1;
239 R.v = N.v;
240 N.have = 0;
241 goto doneB;
242  
243 failB1:
244 NCDProgramElem_Free(&elem);
245 failB0:
246 R.have = 0;
247 parser_out->out_of_memory = 1;
248 doneB:
249 free_token(A);
250 free_block(B);
251 free_program(N);
252 }
253  
254 statement(R) ::= dotted_name(A) ROUND_OPEN list_contents_maybe(B) ROUND_CLOSE name_maybe(C) SEMICOLON. {
255 if (!A || !B.have) {
256 goto failC0;
257 }
258  
259 if (!NCDStatement_InitReg(&R.v, C, NULL, A, B.v)) {
260 goto failC0;
261 }
262 B.have = 0;
263  
264 R.have = 1;
265 goto doneC;
266  
267 failC0:
268 R.have = 0;
269 parser_out->out_of_memory = 1;
270 doneC:
271 free(A);
272 free_value(B);
273 free(C);
274 }
275  
276 statement(R) ::= dotted_name(M) ARROW dotted_name(A) ROUND_OPEN list_contents_maybe(B) ROUND_CLOSE name_maybe(C) SEMICOLON. {
277 if (!M || !A || !B.have) {
278 goto failD0;
279 }
280  
281 if (!NCDStatement_InitReg(&R.v, C, M, A, B.v)) {
282 goto failD0;
283 }
284 B.have = 0;
285  
286 R.have = 1;
287 goto doneD;
288  
289 failD0:
290 R.have = 0;
291 parser_out->out_of_memory = 1;
292 doneD:
293 free(M);
294 free(A);
295 free_value(B);
296 free(C);
297 }
298  
299 statement(R) ::= IF ROUND_OPEN value(A) ROUND_CLOSE CURLY_OPEN statements(B) CURLY_CLOSE elif_maybe(I) else_maybe(E) name_maybe(C) SEMICOLON. {
300 if (!A.have || !B.have || !I.have) {
301 goto failE0;
302 }
303  
304 NCDIf ifc;
305 NCDIf_Init(&ifc, A.v, B.v);
306 A.have = 0;
307 B.have = 0;
308  
309 if (!NCDIfBlock_PrependIf(&I.v, ifc)) {
310 NCDIf_Free(&ifc);
311 goto failE0;
312 }
313  
314 if (!NCDStatement_InitIf(&R.v, C, I.v, NCDIFTYPE_IF)) {
315 goto failE0;
316 }
317 I.have = 0;
318  
319 if (E.have) {
320 NCDStatement_IfAddElse(&R.v, E.v);
321 E.have = 0;
322 }
323  
324 R.have = 1;
325 goto doneE;
326  
327 failE0:
328 R.have = 0;
329 parser_out->out_of_memory = 1;
330 doneE:
331 free_value(A);
332 free_block(B);
333 free_ifblock(I);
334 free_block(E);
335 free(C);
336 }
337  
338 statement(R) ::= FOREACH ROUND_OPEN value(A) AS NAME(B) ROUND_CLOSE CURLY_OPEN statements(S) CURLY_CLOSE name_maybe(N) SEMICOLON. {
339 if (!A.have || !B.str || !S.have) {
340 goto failEA0;
341 }
342  
343 if (!NCDStatement_InitForeach(&R.v, N, A.v, B.str, NULL, S.v)) {
344 goto failEA0;
345 }
346 A.have = 0;
347 S.have = 0;
348  
349 R.have = 1;
350 goto doneEA0;
351  
352 failEA0:
353 R.have = 0;
354 parser_out->out_of_memory = 1;
355 doneEA0:
356 free_value(A);
357 free_token(B);
358 free_block(S);
359 free(N);
360 }
361  
362 statement(R) ::= FOREACH ROUND_OPEN value(A) AS NAME(B) COLON NAME(C) ROUND_CLOSE CURLY_OPEN statements(S) CURLY_CLOSE name_maybe(N) SEMICOLON. {
363 if (!A.have || !B.str || !C.str || !S.have) {
364 goto failEB0;
365 }
366  
367 if (!NCDStatement_InitForeach(&R.v, N, A.v, B.str, C.str, S.v)) {
368 goto failEB0;
369 }
370 A.have = 0;
371 S.have = 0;
372  
373 R.have = 1;
374 goto doneEB0;
375  
376 failEB0:
377 R.have = 0;
378 parser_out->out_of_memory = 1;
379 doneEB0:
380 free_value(A);
381 free_token(B);
382 free_token(C);
383 free_block(S);
384 free(N);
385 }
386  
387 elif_maybe(R) ::= . {
388 NCDIfBlock_Init(&R.v);
389 R.have = 1;
390 }
391  
392 elif_maybe(R) ::= elif(A). {
393 R = A;
394 }
395  
396 elif(R) ::= ELIF ROUND_OPEN value(A) ROUND_CLOSE CURLY_OPEN statements(B) CURLY_CLOSE. {
397 if (!A.have || !B.have) {
398 goto failF0;
399 }
400  
401 NCDIfBlock_Init(&R.v);
402  
403 NCDIf ifc;
404 NCDIf_Init(&ifc, A.v, B.v);
405 A.have = 0;
406 B.have = 0;
407  
408 if (!NCDIfBlock_PrependIf(&R.v, ifc)) {
409 goto failF1;
410 }
411  
412 R.have = 1;
413 goto doneF0;
414  
415 failF1:
416 NCDIf_Free(&ifc);
417 NCDIfBlock_Free(&R.v);
418 failF0:
419 R.have = 0;
420 parser_out->out_of_memory = 1;
421 doneF0:
422 free_value(A);
423 free_block(B);
424 }
425  
426 elif(R) ::= ELIF ROUND_OPEN value(A) ROUND_CLOSE CURLY_OPEN statements(B) CURLY_CLOSE elif(N). {
427 if (!A.have || !B.have || !N.have) {
428 goto failG0;
429 }
430  
431 NCDIf ifc;
432 NCDIf_Init(&ifc, A.v, B.v);
433 A.have = 0;
434 B.have = 0;
435  
436 if (!NCDIfBlock_PrependIf(&N.v, ifc)) {
437 goto failG1;
438 }
439  
440 R.have = 1;
441 R.v = N.v;
442 N.have = 0;
443 goto doneG0;
444  
445 failG1:
446 NCDIf_Free(&ifc);
447 failG0:
448 R.have = 0;
449 parser_out->out_of_memory = 1;
450 doneG0:
451 free_value(A);
452 free_block(B);
453 free_ifblock(N);
454 }
455  
456 else_maybe(R) ::= . {
457 R.have = 0;
458 }
459  
460 else_maybe(R) ::= ELSE CURLY_OPEN statements(B) CURLY_CLOSE. {
461 R = B;
462 }
463  
464 statement(R) ::= BLOCK CURLY_OPEN statements(S) CURLY_CLOSE name_maybe(N) SEMICOLON. {
465 if (!S.have) {
466 goto failGA0;
467 }
468  
469 if (!NCDStatement_InitBlock(&R.v, N, S.v)) {
470 goto failGA0;
471 }
472 S.have = 0;
473  
474 R.have = 1;
475 goto doneGA0;
476  
477 failGA0:
478 R.have = 0;
479 parser_out->out_of_memory = 1;
480 doneGA0:
481 free_block(S);
482 free(N);
483 }
484  
485 interrupt_maybe(R) ::= . {
486 R.have = 0;
487 }
488  
489 interrupt_maybe(R) ::= TOKEN_INTERRUPT CURLY_OPEN statements(S) CURLY_CLOSE. {
490 R = S;
491 }
492  
493 statement(R) ::= TOKEN_DO CURLY_OPEN statements(S) CURLY_CLOSE interrupt_maybe(I) name_maybe(N) SEMICOLON. {
494 if (!S.have) {
495 goto failGB0;
496 }
497  
498 NCDIfBlock if_block;
499 NCDIfBlock_Init(&if_block);
500  
501 if (I.have) {
502 NCDIf int_if;
503 NCDIf_InitBlock(&int_if, I.v);
504 I.have = 0;
505  
506 if (!NCDIfBlock_PrependIf(&if_block, int_if)) {
507 NCDIf_Free(&int_if);
508 goto failGB1;
509 }
510 }
511  
512 NCDIf the_if;
513 NCDIf_InitBlock(&the_if, S.v);
514 S.have = 0;
515  
516 if (!NCDIfBlock_PrependIf(&if_block, the_if)) {
517 NCDIf_Free(&the_if);
518 goto failGB1;
519 }
520  
521 if (!NCDStatement_InitIf(&R.v, N, if_block, NCDIFTYPE_DO)) {
522 goto failGB1;
523 }
524  
525 R.have = 1;
526 goto doneGB0;
527  
528 failGB1:
529 NCDIfBlock_Free(&if_block);
530 failGB0:
531 R.have = 0;
532 parser_out->out_of_memory = 1;
533 doneGB0:
534 free_block(S);
535 free_block(I);
536 free(N);
537 }
538  
539 statements(R) ::= statement(A). {
540 if (!A.have) {
541 goto failH0;
542 }
543  
544 NCDBlock_Init(&R.v);
545  
546 if (!NCDBlock_PrependStatement(&R.v, A.v)) {
547 goto failH1;
548 }
549 A.have = 0;
550  
551 R.have = 1;
552 goto doneH;
553  
554 failH1:
555 NCDBlock_Free(&R.v);
556 failH0:
557 R.have = 0;
558 parser_out->out_of_memory = 1;
559 doneH:
560 free_statement(A);
561 }
562  
563 statements(R) ::= statement(A) statements(N). {
564 if (!A.have || !N.have) {
565 goto failI0;
566 }
567  
568 if (!NCDBlock_PrependStatement(&N.v, A.v)) {
569 goto failI1;
570 }
571 A.have = 0;
572  
573 R.have = 1;
574 R.v = N.v;
575 N.have = 0;
576 goto doneI;
577  
578 failI1:
579 NCDBlock_Free(&R.v);
580 failI0:
581 R.have = 0;
582 parser_out->out_of_memory = 1;
583 doneI:
584 free_statement(A);
585 free_block(N);
586 }
587  
588 dotted_name(R) ::= NAME(A). {
589 ASSERT(A.str)
590  
591 R = A.str;
592 }
593  
594 dotted_name(R) ::= NAME(A) DOT dotted_name(N). {
595 ASSERT(A.str)
596 if (!N) {
597 goto failJ0;
598 }
599  
600 if (!(R = concat_strings(3, A.str, ".", N))) {
601 goto failJ0;
602 }
603  
604 goto doneJ;
605  
606 failJ0:
607 R = NULL;
608 parser_out->out_of_memory = 1;
609 doneJ:
610 free_token(A);
611 free(N);
612 }
613  
614 name_list(R) ::= NAME(A). {
615 if (!A.str) {
616 goto failK0;
617 }
618  
619 NCDValue_InitList(&R.v);
620  
621 NCDValue this_string;
622 if (!NCDValue_InitString(&this_string, A.str)) {
623 goto failK1;
624 }
625  
626 if (!NCDValue_ListPrepend(&R.v, this_string)) {
627 goto failK2;
628 }
629  
630 R.have = 1;
631 goto doneK;
632  
633 failK2:
634 NCDValue_Free(&this_string);
635 failK1:
636 NCDValue_Free(&R.v);
637 failK0:
638 R.have = 0;
639 parser_out->out_of_memory = 1;
640 doneK:
641 free_token(A);
642 }
643  
644 name_list(R) ::= NAME(A) DOT name_list(N). {
645 if (!A.str || !N.have) {
646 goto failKA0;
647 }
648  
649 NCDValue this_string;
650 if (!NCDValue_InitString(&this_string, A.str)) {
651 goto failKA0;
652 }
653  
654 if (!NCDValue_ListPrepend(&N.v, this_string)) {
655 goto failKA1;
656 }
657  
658 R.have = 1;
659 R.v = N.v;
660 N.have = 0;
661 goto doneKA;
662  
663 failKA1:
664 NCDValue_Free(&this_string);
665 failKA0:
666 R.have = 0;
667 parser_out->out_of_memory = 1;
668 doneKA:
669 free_token(A);
670 free_value(N);
671 }
672  
673 list_contents_maybe(R) ::= . {
674 R.have = 1;
675 NCDValue_InitList(&R.v);
676 }
677  
678 list_contents_maybe(R) ::= list_contents(A). {
679 R = A;
680 }
681  
682 list_contents(R) ::= value(A). {
683 if (!A.have) {
684 goto failL0;
685 }
686  
687 NCDValue_InitList(&R.v);
688  
689 if (!NCDValue_ListPrepend(&R.v, A.v)) {
690 goto failL1;
691 }
692 A.have = 0;
693  
694 R.have = 1;
695 goto doneL;
696  
697 failL1:
698 NCDValue_Free(&R.v);
699 failL0:
700 R.have = 0;
701 parser_out->out_of_memory = 1;
702 doneL:
703 free_value(A);
704 }
705  
706 list_contents(R) ::= value(A) COMMA list_contents(N). {
707 if (!A.have || !N.have) {
708 goto failM0;
709 }
710  
711 if (!NCDValue_ListPrepend(&N.v, A.v)) {
712 goto failM0;
713 }
714 A.have = 0;
715  
716 R.have = 1;
717 R.v = N.v;
718 N.have = 0;
719 goto doneM;
720  
721 failM0:
722 R.have = 0;
723 parser_out->out_of_memory = 1;
724 doneM:
725 free_value(A);
726 free_value(N);
727 }
728  
729 list(R) ::= CURLY_OPEN CURLY_CLOSE. {
730 R.have = 1;
731 NCDValue_InitList(&R.v);
732 }
733  
734 list(R) ::= CURLY_OPEN list_contents(A) CURLY_CLOSE. {
735 R = A;
736 }
737  
738 map_contents(R) ::= value(A) COLON value(B). {
739 if (!A.have || !B.have) {
740 goto failS0;
741 }
742  
743 NCDValue_InitMap(&R.v);
744  
745 if (!NCDValue_MapPrepend(&R.v, A.v, B.v)) {
746 goto failS1;
747 }
748 A.have = 0;
749 B.have = 0;
750  
751 R.have = 1;
752 goto doneS;
753  
754 failS1:
755 NCDValue_Free(&R.v);
756 failS0:
757 R.have = 0;
758 parser_out->out_of_memory = 1;
759 doneS:
760 free_value(A);
761 free_value(B);
762 }
763  
764 map_contents(R) ::= value(A) COLON value(B) COMMA map_contents(N). {
765 if (!A.have || !B.have || !N.have) {
766 goto failT0;
767 }
768  
769 if (!NCDValue_MapPrepend(&N.v, A.v, B.v)) {
770 goto failT0;
771 }
772 A.have = 0;
773 B.have = 0;
774  
775 R.have = 1;
776 R.v = N.v;
777 N.have = 0;
778 goto doneT;
779  
780 failT0:
781 R.have = 0;
782 parser_out->out_of_memory = 1;
783 doneT:
784 free_value(A);
785 free_value(B);
786 free_value(N);
787 }
788  
789 map(R) ::= BRACKET_OPEN BRACKET_CLOSE. {
790 R.have = 1;
791 NCDValue_InitMap(&R.v);
792 }
793  
794 map(R) ::= BRACKET_OPEN map_contents(A) BRACKET_CLOSE. {
795 R = A;
796 }
797  
798 invoc(R) ::= value(F) ROUND_OPEN list_contents_maybe(A) ROUND_CLOSE. {
799 if (!F.have || !A.have) {
800 goto failQ0;
801 }
802  
803 if (!NCDValue_InitInvoc(&R.v, F.v, A.v)) {
804 goto failQ0;
805 }
806 F.have = 0;
807 A.have = 0;
808 R.have = 1;
809 goto doneQ;
810  
811 failQ0:
812 R.have = 0;
813 parser_out->out_of_memory = 1;
814 doneQ:
815 free_value(F);
816 free_value(A);
817 }
818  
819 value(R) ::= STRING(A). {
820 ASSERT(A.str)
821  
822 if (!NCDValue_InitStringBin(&R.v, (uint8_t *)A.str, A.len)) {
823 goto failU0;
824 }
825  
826 R.have = 1;
827 goto doneU;
828  
829 failU0:
830 R.have = 0;
831 parser_out->out_of_memory = 1;
832 doneU:
833 free_token(A);
834 }
835  
836 value(R) ::= AT_SIGN dotted_name(A). {
837 if (!A) {
838 goto failUA0;
839 }
840  
841 if (!NCDValue_InitString(&R.v, A)) {
842 goto failUA0;
843 }
844  
845 R.have = 1;
846 goto doneUA0;
847  
848 failUA0:
849 R.have = 0;
850 parser_out->out_of_memory = 1;
851 doneUA0:
852 free(A);
853 }
854  
855 value(R) ::= CARET name_list(A). {
856 R = A;
857 }
858  
859 value(R) ::= dotted_name(A). {
860 if (!A) {
861 goto failV0;
862 }
863  
864 if (!NCDValue_InitVar(&R.v, A)) {
865 goto failV0;
866 }
867  
868 R.have = 1;
869 goto doneV;
870  
871 failV0:
872 R.have = 0;
873 parser_out->out_of_memory = 1;
874 doneV:
875 free(A);
876 }
877  
878 value(R) ::= list(A). {
879 R = A;
880 }
881  
882 value(R) ::= map(A). {
883 R = A;
884 }
885  
886 value(R) ::= ROUND_OPEN value(A) ROUND_CLOSE. {
887 R = A;
888 }
889  
890 value(R) ::= invoc(A). {
891 R = A;
892 }
893  
894 name_maybe(R) ::= . {
895 R = NULL;
896 }
897  
898 name_maybe(R) ::= NAME(A). {
899 ASSERT(A.str)
900  
901 R = A.str;
902 }
903  
904 process_or_template(R) ::= PROCESS. {
905 R = 0;
906 }
907  
908 process_or_template(R) ::= TEMPLATE. {
909 R = 1;
910 }