BadVPN – Blame information for rev 1
?pathlinks?
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 | } |