libamxo  4.3.4
Object Definition Language (ODL) parsing
amxo_parser.y
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (c) 2020 SoftAtHome
4 **
5 ** Redistribution and use in source and binary forms, with or
6 ** without modification, are permitted provided that the following
7 ** conditions are met:
8 **
9 ** 1. Redistributions of source code must retain the above copyright
10 ** notice, this list of conditions and the following disclaimer.
11 **
12 ** 2. Redistributions in binary form must reproduce the above
13 ** copyright notice, this list of conditions and the following
14 ** disclaimer in the documentation and/or other materials provided
15 ** with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each
18 ** copyright holder and contributor hereby grants to those receiving
19 ** rights under this license a perpetual, worldwide, non-exclusive,
20 ** no-charge, royalty-free, irrevocable (except for failure to
21 ** satisfy the conditions of this license) patent license to make,
22 ** have made, use, offer to sell, sell, import, and otherwise
23 ** transfer this software, where such license applies only to those
24 ** patent claims, already acquired or hereafter acquired, licensable
25 ** by such copyright holder or contributor that are necessarily
26 ** infringed by:
27 **
28 ** (a) their Contribution(s) (the licensed copyrights of copyright
29 ** holders and non-copyrightable additions of contributors, in
30 ** source or binary form) alone; or
31 **
32 ** (b) combination of their Contribution(s) with the work of
33 ** authorship to which such Contribution(s) was added by such
34 ** copyright holder or contributor, if, at the time the Contribution
35 ** is added, such addition causes such combination to be necessarily
36 ** infringed. The patent license shall not apply to any other
37 ** combinations which include the Contribution.
38 **
39 ** Except as expressly stated above, no rights or licenses from any
40 ** copyright holder or contributor is granted under this license,
41 ** whether expressly, by implication, estoppel or otherwise.
42 **
43 ** DISCLAIMER
44 **
45 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
46 ** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
47 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
48 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
49 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
50 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
54 ** AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56 ** ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 ** POSSIBILITY OF SUCH DAMAGE.
58 **
59 ****************************************************************************/
60 %define api.pure full
61 %locations
62 %defines
63 %define parse.error verbose
64 %parse-param {void *ctx}
65 %lex-param {void *ctx}
66 
67 %{
68 #ifndef _GNU_SOURCE
69 #define _GNU_SOURCE
70 #endif
71 
72 #include "amxo_parser_priv.h"
73 #include "amxo_parser_hooks_priv.h"
74 #include "amxo_parser.tab.h"
75 
76 %}
77 
78 
79 %union
80 {
81  int64_t integer;
82  int64_t bitmap;
83  amxo_txt_t cptr;
84  bool boolean;
85  amxc_var_t* var;
86  amxo_txt_regexp_t cregexp;
87  amxo_action_t action;
88 }
89 
90 %token <integer> REQUIRES
91 %token <integer> INCLUDE
92 %token <integer> IMPORT
93 %token <integer> USING
94 %token <integer> AS
95 %token <integer> INSTANCE
96 %token <integer> PARAMETER
97 %token <integer> DEFINE
98 %token <integer> CONFIG
99 %token <integer> POPULATE
100 %token <integer> OBJECT
101 %token <integer> SELECT
102 %token <integer> EXTEND
103 %token <integer> EOF_TOKEN
104 %token <integer> DIGIT
105 %token <integer> TYPE
106 %token <integer> LDFLAG
107 %token <integer> ENTRY
108 %token <integer> COUNTER
109 %token <integer> WITH
110 %token <integer> ON
111 %token <integer> DEFAULT
112 %token <integer> EVENT
113 %token <integer> FILTER
114 %token <integer> OF
115 %token <integer> GLOBAL
116 %token <integer> CALL
117 %token <integer> ACTION_KW
118 %token <cptr> STRING
119 %token <cptr> MULTILINECOMMENT
120 %token <cptr> TEXT
121 %token <cptr> RESOLVER
122 %token <boolean> BOOL
123 %token <bitmap> SET_ATTRIBUTE
124 %token <bitmap> UNSET_ATTRIBUTE
125 %token <integer> REGEXP
126 %token <integer> FLAGS
127 %token <integer> PRINT
128 %token <integer> SYNC
129 %token <integer> DIRECTION
130 %token <integer> SYNC_ATTRIBUTE
131 
132 %type <integer> stream sections section config_options config_option
133 %type <integer> requires include import ldflags entry_point print
134 %type <integer> defines populates populate object_populate event_populate event_subscribe
135 %type <integer> sync_populate sync_header
136 %type <integer> define object_def object_def_header multi object_body object_content
137 %type <integer> parameter_def counted event_def
138 %type <integer> function_def arguments argument_def add_mib
139 %type <integer> object_pop_header object_pop_body object_pop_content param_pop_head parameter
140 %type <action> action_header
141 %type <integer> action instance_id
142 %type <bitmap> attributes unset_attributes
143 %type <cptr> name path filter action_function
144 %type <cregexp> text_or_regexp
145 %type <var> flags flag value values data_option data_options data event_param event_body
146 
147 %{
148  int yylex(YYSTYPE* lvalp, YYLTYPE* llocp, void * yyscanner);
149  void yyerror(YYLTYPE* locp, void* scanner, const char* err);
150  void yywarning(YYLTYPE* locp, void* scanner, const char* err);
151  amxo_parser_t *yyget_extra ( void * yyscanner );
152 
153  void yyerror(YYLTYPE* locp, void* scanner, const char* err) {
154  amxo_parser_t *context = (amxo_parser_t *)yyget_extra(scanner);
155  if (context->status == amxd_status_ok) {
156  if (!amxc_string_is_empty(&context->msg)) {
157  amxo_parser_printf(context, "ERROR : %s@%s:line %d\n",
158  amxc_string_get(&context->msg, 0),
159  context->file,
160  locp->first_line);
161  amxc_string_reset(&context->msg);
162  } else {
163  amxo_parser_printf(context, "ERROR : %s@%s:line %d\n",
164  err,
165  context->file,
166  locp->first_line);
167  }
168  } else {
169  if (!amxc_string_is_empty(&context->msg)) {
170  amxo_parser_printf(context, "ERROR : %d - %s@%s:line %d\n",
171  context->status,
172  amxc_string_get(&context->msg, 0),
173  context->file,
174  locp->first_line);
175  amxc_string_reset(&context->msg);
176  } else {
177  amxo_parser_printf(context, "ERROR : %d - %s - %s@%s:line %d\n",
178  context->status,
179  amxd_status_string(context->status),
180  err,
181  context->file,
182  locp->first_line);
183  }
184  }
185  }
186 
187  void yywarning(YYLTYPE* locp, void* scanner, const char* err) {
188  amxo_parser_t *context = (amxo_parser_t *)yyget_extra(scanner);
189  if (!amxc_string_is_empty(&context->msg)) {
190  amxo_parser_printf(context, "WARNING: %s@%s:line %d\n",
191  amxc_string_get(&context->msg, 0),
192  context->file,
193  locp->first_line);
194  amxc_string_reset(&context->msg);
195  } else {
196  amxo_parser_printf(context, "WARNING: %s@%s:line %d\n",
197  err,
198  context->file,
199  locp->first_line);
200  }
201  }
202 
203  #define scanner x->scanner
204  #define parser_ctx ((amxo_parser_t *)yyget_extra(ctx))
205  #define YY_CHECK_ACTION(c,m,a) if(c) { yyerror(&yylloc, ctx, m); a; YYERROR; }
206  #define YY_CHECK(c,m) if(c) { yyerror(&yylloc, ctx, m); YYERROR; }
207  #define YY_WARNING(c,m) if(c) { yywarning(&yylloc, ctx, m); }
208  #define NOOP
209 
210  const uint64_t amxo_object_attrs = ((1 << attr_readonly) |
211  (1 << attr_persistent) |
212  (1 << attr_private) |
213  (1 << attr_protected));
214 
215  const uint64_t amxo_param_attrs = ((1 << attr_persistent) |
216  (1 << attr_private) |
217  (1 << attr_template) |
218  (1 << attr_instance) |
219  (1 << attr_variable) |
220  (1 << attr_readonly) |
221  (1 << attr_key) |
222  (1 << attr_unique) |
223  (1 << attr_protected) |
224  (1 << attr_mutable));
225 
226  const uint64_t amxo_func_attrs = ((1 << attr_private) |
227  (1 << attr_template) |
228  (1 << attr_instance) |
229  (1 << attr_protected) |
230  (1 << attr_asynchronous));
231 
232  const uint64_t amxo_arg_attrs = ((1 << attr_in) |
233  (1 << attr_out) |
234  (1 << attr_mandatory) |
235  (1 << attr_strict));
236 
237 %}
238 
239 %start stream
240 
241 %%
242 
243 stream: /* empty */ { NOOP; }
244  | sections
245  | EOF_TOKEN
246  ;
247 
248 sections
249  : section sections
250  | section
251  ;
252 
253 section
254  : include
255  | import
256  | requires
257  | print
258  | CONFIG '{' '}' {
259  amxo_hooks_end_section(parser_ctx, 0);
260  }
261  | CONFIG '{' config_options '}' {
262  amxo_hooks_end_section(parser_ctx, 0);
263  }
264  | DEFINE '{' '}' {
265  amxo_hooks_end_section(parser_ctx, 1);
266  }
267  | DEFINE '{' defines '}' {
268  amxo_hooks_end_section(parser_ctx, 1);
269  }
270  | POPULATE '{' '}' {
271  amxo_hooks_end_section(parser_ctx, 2);
272  }
273  | POPULATE '{' populates '}' {
274  amxo_hooks_end_section(parser_ctx, 2);
275  }
276  | define
277  ;
278 
279 config_options
280  : config_option config_options
281  | config_option
282  ;
283 
284 config_option
285  : path '=' data ';' {
286  amxc_var_t* data = NULL;
287  $1.txt[$1.length] = 0;
288  YY_CHECK_ACTION(amxo_parser_set_config(parser_ctx, $1.txt, $3) != 0,
289  $1.txt,
290  amxc_var_delete(&$3);
291  );
292  data = amxc_var_get_path(&parser_ctx->config, $1.txt, AMXC_VAR_FLAG_DEFAULT);
293  amxo_hooks_set_config(parser_ctx, $1.txt, data);
294  amxc_var_delete(&$3);
295  $$ = 0;
296  }
297  | GLOBAL path '=' data ';' {
298  amxc_var_t* data = NULL;
299  amxc_string_t *name = NULL;
300  $2.txt[$2.length] = 0;
301  YY_CHECK_ACTION(amxo_parser_set_config(parser_ctx, $2.txt, $4) != 0,
302  $2.txt,
303  amxc_var_delete(&$4);
304  );
305  amxc_string_new(&name, 0);
306  amxc_string_append(name, $2.txt, $2.length);
307  amxc_llist_append(&parser_ctx->global_config, &name->it);
308  data = amxc_var_get_path(&parser_ctx->config, $2.txt, AMXC_VAR_FLAG_DEFAULT);
309  amxo_hooks_set_config(parser_ctx, $2.txt, data);
310  amxc_var_delete(&$4);
311  $$ = 0;
312  }
313  ;
314 
315 requires
316  : REQUIRES TEXT ';' {
317  amxc_var_t* req = NULL;
318  amxc_string_t *name = NULL;
319 
320  $2.txt[$2.length] = 0;
321  amxc_string_new(&name, 0);
322  amxc_string_append(name, "requires", strlen("requires") + 1);
323  amxc_llist_append(&parser_ctx->global_config, &name->it);
324 
325  req = amxo_parser_claim_config(parser_ctx, "requires");
326  if (amxc_var_type_of(req) != AMXC_VAR_ID_LIST) {
327  amxc_var_set_type(req, AMXC_VAR_ID_LIST);
328  }
329  amxc_var_add(cstring_t, req, $2.txt);
330  $$ = 0;
331  }
332  ;
333 
334 print
335  : PRINT TEXT ';' {
336  $2.txt[$2.length] = 0;
337  amxo_parser_print(parser_ctx, $2.txt);
338  $$ = 0;
339  }
340 
341 include
342  : INCLUDE TEXT ';' {
343  int retval = 0;
344  $2.txt[$2.length] = 0;
345  if ($1 != token_post_include) {
346  retval = amxo_parser_include(parser_ctx, $2.txt);
347  if (retval == 4) {
348  // is an empty directory - not an error
349  retval = 0;
350  }
351  } else {
352  retval = amxo_parser_add_post_include(parser_ctx, $2.txt);
353  }
354  YY_CHECK(retval != 0 && !(retval == 2 && $1 == token_optional_include), $2.txt);
355  parser_ctx->status = amxd_status_ok;
356  }
357  | INCLUDE TEXT ':' TEXT ';' {
358  int retval = 0;
359  $2.txt[$2.length] = 0;
360  $4.txt[$4.length] = 0;
361  retval = amxo_parser_include(parser_ctx, $2.txt);
362  if (retval == 2 || retval == 4) {
363  // 2 = file/dir not found, 4 = empty directory
364  parser_ctx->status = amxd_status_ok;
365  retval = amxo_parser_include(parser_ctx, $4.txt);
366  if (retval == 4) {
367  retval = 0;
368  }
369  }
370  YY_CHECK(retval != 0, $2.txt);
371  }
372  ;
373 
374 import
375  : IMPORT TEXT ';' {
376  $2.txt[$2.length] = 0;
377  YY_CHECK(amxo_resolver_import_open(parser_ctx, $2.txt, $2.txt, RTLD_LAZY) != 0,
378  $2.txt);
379  }
380  | IMPORT TEXT AS name ';' {
381  $2.txt[$2.length] = 0;
382  $4.txt[$4.length] = 0;
383  YY_CHECK(amxo_resolver_import_open(parser_ctx, $2.txt, $4.txt, RTLD_LAZY) != 0,
384  $2.txt);
385  }
386  | IMPORT TEXT ldflags ';' {
387  $2.txt[$2.length] = 0;
388  YY_CHECK(amxo_resolver_import_open(parser_ctx, $2.txt, $2.txt, $3) != 0,
389  $2.txt);
390  }
391  | IMPORT TEXT ldflags AS name ';' {
392  $2.txt[$2.length] = 0;
393  $5.txt[$5.length] = 0;
394  YY_CHECK(amxo_resolver_import_open(parser_ctx, $2.txt, $5.txt, $3) != 0,
395  $2.txt);
396  }
397  ;
398 
399 ldflags
400  : LDFLAG ldflags {
401  $$ = $1 | $2;
402  }
403  | LDFLAG
404 
405 defines
406  : define defines
407  | define
408  ;
409 
410 populates
411  : populate populates
412  | populate
413  ;
414 
415 define
416  : object_def
417  | function_def
418  | entry_point
419  ;
420 
421 object_def
422  : object_def_header ';' {
423  int type = amxd_object_get_type(parser_ctx->object);
424  YY_WARNING(type == amxd_object_mib, "Empty MIB object defined");
425  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
426  }
427  | object_def_header '{' '}' {
428  int type = amxd_object_get_type(parser_ctx->object);
429  YY_WARNING(type == amxd_object_mib, "Empty MIB object defined");
430  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
431  }
432  | object_def_header '{' object_body '}' {
433  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
434  }
435  ;
436 
437 entry_point
438  : ENTRY name '.' name ';' {
439  $2.txt[$2.length] = 0;
440  $4.txt[$4.length] = 0;
441  YY_CHECK(amxo_parser_call_entry_point(parser_ctx, $2.txt, $4.txt) != 0,
442  $2.txt);
443 
444  }
445  ;
446 
447 object_def_header
448  : OBJECT name {
449  amxd_object_type_t type = ($1 == token_mib)?amxd_object_mib:amxd_object_singleton;
450  $2.txt[$2.length] = 0;
451  YY_CHECK(amxo_parser_create_object(parser_ctx, $2.txt, 0, type) < 0, $2.txt);
452  }
453  | attributes OBJECT name {
454  amxd_object_type_t type = ($2 == token_mib)?amxd_object_mib:amxd_object_singleton;
455  $3.txt[$3.length] = 0;
456  YY_WARNING(type == amxd_object_mib, "Attributes declared on mib object are ignored");
457  if (type != amxd_object_mib) {
458  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $3.txt);
459  }
460  YY_CHECK(amxo_parser_create_object(parser_ctx, $3.txt, $1, amxd_object_singleton) < 0, $3.txt);
461  }
462  | OBJECT name multi {
463  $2.txt[$2.length] = 0;
464  YY_CHECK($1 == token_mib, "Mib objects can not be multi-instance");
465  YY_CHECK(amxo_parser_create_object(parser_ctx, $2.txt, 0, amxd_object_template) < 0, $2.txt);
466  YY_WARNING(amxd_object_set_max_instances(parser_ctx->object, $3) != amxd_status_ok,
467  "Failed to set maximum instances");
468  }
469  | attributes OBJECT name multi {
470  $3.txt[$3.length] = 0;
471  YY_CHECK($2 == token_mib, "Mib objects can not be multi-instance");
472  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $3.txt);
473  YY_CHECK(amxo_parser_create_object(parser_ctx, $3.txt, $1, amxd_object_template) < 0, $3.txt);
474  YY_WARNING(amxd_object_set_max_instances(parser_ctx->object, $4) != amxd_status_ok,
475  "Failed to set maximum instances");
476  }
477  | SELECT path {
478  $2.txt[$2.length] = 0;
479  YY_CHECK(!amxo_parser_push_object(parser_ctx, $2.txt), $2.txt);
480  }
481  ;
482 
483 multi
484  : '[' DIGIT ']' {
485  $$ = $2;
486  }
487  | '[' ']' {
488  $$ = INT64_MAX;
489  }
490  ;
491 
492 object_body
493  : object_body object_content
494  | object_content
495  ;
496 
497 object_content
498  : object_def
499  | parameter_def
500  | function_def
501  | counted
502  | action
503  | add_mib
504  | event_def
505  | event_subscribe
506  ;
507 
508 parameter_def
509  : param_header ';' {
510  YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
511  }
512  | param_header '{' '}' {
513  YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
514  }
515  | param_header '{' param_body '}' {
516  YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
517  }
518  ;
519 
520 param_header
521  : TYPE name {
522  $2.txt[$2.length] = 0;
523  YY_CHECK(!amxo_parser_push_param(parser_ctx, $2.txt, 0, $1), $2.txt);
524  }
525  | attributes TYPE name {
526  $3.txt[$3.length] = 0;
527  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs), $3.txt);
528  YY_CHECK(!amxo_parser_push_param(parser_ctx, $3.txt, $1, $2), $3.txt);
529  }
530  | TYPE name '=' value {
531  int retval = 0;
532  $2.txt[$2.length] = 0;
533  YY_CHECK_ACTION(!amxo_parser_push_param(parser_ctx, $2.txt, 0, $1),
534  $2.txt,
535  amxc_var_delete(&$4));
536  retval = amxo_parser_set_param(parser_ctx, $2.txt, $4);
537  YY_CHECK_ACTION(retval < 0, $2.txt, amxc_var_delete(&$4));
538  amxc_var_delete(&$4);
539  }
540  | attributes TYPE name '=' value {
541  bool key_attr_is_set = ($1 & (1 << attr_key));
542  int retval = 0;
543  $3.txt[$3.length] = 0;
544  YY_CHECK_ACTION(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
545  $3.txt,
546  amxc_var_delete(&$5));
547  YY_CHECK_ACTION(key_attr_is_set,
548  "Key parameters can not have a default value",
549  parser_ctx->status = amxd_status_invalid_value;
550  amxc_var_delete(&$5));
551  YY_CHECK_ACTION(!amxo_parser_push_param(parser_ctx, $3.txt, $1, $2),
552  $3.txt,
553  amxc_var_delete(&$5));
554  retval = amxo_parser_set_param(parser_ctx, $3.txt, $5);
555  YY_CHECK_ACTION(retval < 0, $3.txt, amxc_var_delete(&$5));
556  amxc_var_delete(&$5);
557  }
558  ;
559 
560 param_body
561  : param_body param_content
562  | param_content
563  ;
564 
565 param_content
566  : action
567  | DEFAULT value ';' {
568  int retval = amxo_parser_set_param(parser_ctx, NULL, $2);
569  YY_CHECK_ACTION(retval < 0,
570  amxd_param_get_name(parser_ctx->param),
571  amxc_var_delete(&$2));
572  amxc_var_delete(&$2);
573  }
574  | FLAGS flags ';' {
575  YY_CHECK(!amxo_parser_set_param_flags(parser_ctx, $2), "Parameter flags");
576  }
577  ;
578 
579 action
580  : action_header action_function ';' {
581  int retval = amxo_parser_set_action(parser_ctx, $1, $2.txt, parser_ctx->data);
582  parser_ctx->data = NULL;
583  YY_CHECK(retval < 0, "Action");
584  YY_WARNING(retval > 0, "Action");
585  }
586  | action_header action_function data ';' {
587  amxc_var_t* data = parser_ctx->data == NULL?$3:parser_ctx->data;
588  int retval = 0;
589  if (parser_ctx->data != NULL) {
590  amxc_var_delete(&$3);
591  }
592  parser_ctx->data = NULL;
593  retval = amxo_parser_set_action(parser_ctx, $1, $2.txt, data);
594  YY_CHECK(retval < 0, "Action");
595  YY_WARNING(retval > 0, "Action");
596  }
597  ;
598 
599 action_header
600  : ON ACTION_KW name {
601  if ($3.length != 0) {
602  $3.txt[$3.length] = 0;
603  }
604  $$ = amxo_parser_get_action_id(parser_ctx, $3.txt);
605  YY_CHECK($$ < 0 , $3.txt);
606  }
607  | ON ACTION_KW TYPE {
608  YY_CHECK($3 != AMXC_VAR_ID_LIST , "Invalid action");
609  $$ = action_list;
610  }
611  ;
612 
613 action_function
614  : CALL name {
615  int retval = 0;
616  $2.txt[$2.length] = 0;
617  retval = amxo_parser_resolve_internal(parser_ctx, $2.txt, amxo_function_action, "auto");
618  YY_CHECK(retval < 0, $2.txt);
619  YY_WARNING(retval > 0, $2.txt);
620  $$ = $2;
621  }
622  | CALL name RESOLVER {
623  int retval = 0;
624  $2.txt[$2.length] = 0;
625  $3.txt[$3.length] = 0;
626  retval = amxo_parser_resolve_internal(parser_ctx, $2.txt, amxo_function_action, $3.txt);
627  YY_CHECK(retval < 0, $2.txt);
628  YY_WARNING(retval > 0, $2.txt);
629  $$ = $2;
630  }
631 
632 function_def
633  : function_header func_args ';' {
634  const char *func_name = amxd_function_get_name(parser_ctx->func);
635  int retval = amxo_parser_resolve_internal(parser_ctx, func_name, amxo_function_rpc, "auto");
636  YY_CHECK(retval < 0, func_name);
637  YY_WARNING(retval > 0, func_name);
638  amxo_parser_pop_func(parser_ctx);
639  }
640  | function_header func_args RESOLVER ';' {
641  const char *func_name = NULL;
642  int retval = 0;
643  if ($3.length != 0) {
644  $3.txt[$3.length] = 0;
645  }
646  func_name = amxd_function_get_name(parser_ctx->func);
647  retval = amxo_parser_resolve_internal(parser_ctx, func_name, amxo_function_rpc, $3.txt);
648  YY_CHECK(retval < 0, func_name);
649  YY_WARNING(retval > 0, func_name);
650  amxo_parser_pop_func(parser_ctx);
651  }
652  | function_header func_args '{' func_body '}' {
653  const char *func_name = amxd_function_get_name(parser_ctx->func);
654  int retval = amxo_parser_resolve_internal(parser_ctx, func_name, amxo_function_rpc, "auto");
655  YY_CHECK(retval < 0, func_name);
656  YY_WARNING(retval > 0, func_name);
657  amxo_parser_pop_func(parser_ctx);
658  }
659  | function_header func_args RESOLVER '{' func_body '}' {
660  int retval = 0;
661  const char *func_name = NULL;
662  if ($3.length != 0) {
663  $3.txt[$3.length] = 0;
664  }
665  func_name = amxd_function_get_name(parser_ctx->func);
666  retval = amxo_parser_resolve_internal(parser_ctx, func_name, amxo_function_rpc, $3.txt);
667  YY_CHECK(retval < 0, func_name);
668  YY_WARNING(retval > 0, func_name);
669  amxo_parser_pop_func(parser_ctx);
670  }
671  ;
672 
673 function_header
674  : TYPE name {
675  int retval = 0;
676  $2.txt[$2.length] = 0;
677  retval = amxo_parser_push_func(parser_ctx, $2.txt, 0, $1);
678  YY_CHECK(retval < 0, $2.txt);
679  YY_WARNING(retval > 0, $2.txt);
680  }
681  | attributes TYPE name {
682  int retval = 0;
683  $3.txt[$3.length] = 0;
684  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_func_attrs), $3.txt);
685  retval = amxo_parser_push_func(parser_ctx, $3.txt, $1, $2);
686  YY_CHECK(retval < 0, $3.txt);
687  YY_WARNING(retval > 0, $3.txt);
688  }
689  ;
690 
691 func_args
692  : '(' ')'
693  | '(' arguments ')'
694  ;
695 
696 arguments
697  : argument_def ',' arguments
698  | argument_def
699  ;
700 
701 func_body
702  : FLAGS flags ';' {
703  YY_CHECK(!amxo_parser_set_function_flags(parser_ctx, $2), "Function flags");
704  }
705  ;
706 
707 argument_def
708  : TYPE name {
709  $2.txt[$2.length] = 0;
710  YY_CHECK(!amxo_parser_add_arg(parser_ctx, $2.txt, 0, $1, NULL), $2.txt);
711  }
712  | attributes TYPE name {
713  $3.txt[$3.length] = 0;
714  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_arg_attrs), $3.txt);
715  YY_CHECK(!amxo_parser_add_arg(parser_ctx, $3.txt, $1, $2, NULL), $3.txt);
716  }
717  | TYPE name '=' value {
718  $2.txt[$2.length] = 0;
719  YY_CHECK_ACTION(!amxo_parser_add_arg(parser_ctx, $2.txt, 0, $1, $4),
720  $2.txt,
721  amxc_var_delete(&$4));
722  amxc_var_delete(&$4);
723  }
724  | attributes TYPE name '=' value {
725  $3.txt[$3.length] = 0;
726  YY_CHECK_ACTION(!amxo_parser_check_attr(parser_ctx, $1, amxo_arg_attrs),
727  $3.txt,
728  amxc_var_delete(&$5));
729  YY_CHECK_ACTION(!amxo_parser_add_arg(parser_ctx, $3.txt, $1, $2, $5),
730  $3.txt,
731  amxc_var_delete(&$5));
732  amxc_var_delete(&$5);
733  }
734  ;
735 
736 counted
737  : COUNTER WITH name ';' {
738  $3.txt[$3.length] = 0;
739  YY_CHECK(!amxo_parser_set_counter(parser_ctx, $3.txt), $3.txt);
740  }
741  ;
742 
743 add_mib
744  : EXTEND USING OBJECT name ';' {
745  $4.txt[$4.length] = 0;
746  YY_CHECK($3 != token_mib, $4.txt);
747  YY_CHECK(!amxo_parser_add_mib(parser_ctx, $4.txt), $4.txt);
748  }
749  | EXTEND WITH OBJECT name ';' {
750  $4.txt[$4.length] = 0;
751  YY_CHECK($3 != token_mib, $4.txt);
752  YY_CHECK(!amxo_parser_add_mib(parser_ctx, $4.txt), $4.txt);
753  }
754  ;
755 
756 event_def
757  : EVENT name ';' {
758  $2.txt[$2.length] = 0;
759  YY_CHECK(amxd_object_add_event(parser_ctx->object, $2.txt) != 0,
760  "Failed to add event");
761  $$ = 0;
762  }
763  | EVENT name '{' '}' {
764  $2.txt[$2.length] = 0;
765  YY_CHECK(amxd_object_add_event(parser_ctx->object, $2.txt) != 0,
766  "Failed to add event");
767  $$ = 0;
768  }
769  | EVENT name '{' event_body '}' {
770  $2.txt[$2.length] = 0;
771  YY_CHECK(amxd_object_add_event_ext(parser_ctx->object, $2.txt, $4) != 0,
772  "Failed to add event");
773  $$ = 0;
774  }
775  ;
776 
777 event_body
778  : event_param event_body {
779  amxc_var_for_each(var, $1) {
780  amxc_var_set_path($2, amxc_var_key(var), var, AMXC_VAR_FLAG_UPDATE | AMXC_VAR_FLAG_COPY | AMXC_VAR_FLAG_AUTO_ADD);
781  }
782  amxc_var_delete(&$1);
783  $$ = $2;
784  }
785  | event_param {
786  $$ = $1;
787  }
788  ;
789 
790 event_param
791  : TYPE name ';' {
792  amxc_var_t* value = NULL;
793  $2.txt[$2.length] = 0;
794  amxc_var_new(&$$);
795  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
796  value = amxc_var_add_new_key($$, $2.txt);
797  amxc_var_set_type(value, $1);
798  }
799  | TYPE name '=' value ';' {
800  $2.txt[$2.length] = 0;
801  amxc_var_new(&$$);
802  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
803  amxc_var_cast($4, $1);
804  amxc_var_set_key($$, $2.txt, $4, AMXC_VAR_FLAG_DEFAULT);
805  }
806  ;
807 
808 event_subscribe
809  : ON EVENT text_or_regexp event_func ';' {
810  int retval = amxo_parser_subscribe_object(parser_ctx,
811  $3.txt, $3.is_regexp,
812  NULL);
813  YY_CHECK(retval < 0, $3.txt);
814  YY_WARNING(retval > 0, $3.txt);
815  }
816  | ON EVENT text_or_regexp event_func filter ';' {
817  int retval = 0;
818  $5.txt[$5.length] = 0;
819  retval = amxo_parser_subscribe_object(parser_ctx,
820  $3.txt, $3.is_regexp,
821  $5.txt);
822  YY_CHECK(retval < 0, $3.txt);
823  YY_WARNING(retval > 0, $3.txt);
824  }
825  ;
826 
827 populate
828  : object_populate
829  | event_populate
830  | sync_populate
831  ;
832 
833 
834 sync_populate
835  : sync_header '{' sync_items '}'
836  ;
837 
838 sync_header
839  : SYNC path DIRECTION path {
840  int status = 0;
841  $2.txt[$2.length] = 0;
842  $4.txt[$4.length] = 0;
843  $3 = amxo_parser_sync_update_flags($3);
844  status = amxo_parser_push_sync_ctx(parser_ctx, $2.txt, $4.txt, $3);
845  YY_CHECK(status != 0, "Synchronization context");
846  }
847  | SYNC path DIRECTION path AS name {
848  int status = 0;
849  $2.txt[$2.length] = 0;
850  $4.txt[$4.length] = 0;
851  $6.txt[$6.length] = 0;
852  $3 = amxo_parser_sync_update_flags($3);
853  status = amxo_parser_push_sync_template(parser_ctx, $2.txt, $4.txt, $3, $6.txt);
854  YY_CHECK(status != 0, "Synchronization context");
855  }
856  ;
857 
858 sync_items
859  : sync_object sync_items
860  | sync_param sync_items
861  | action sync_items
862  | sync_object
863  | sync_param
864  | action
865  ;
866 
867 sync_object
868  : sync_object_header '{' sync_items '}' {
869  YY_CHECK(!amxo_parser_sync_item_contains_entries(parser_ctx), "Object synchronization");
870  amxo_parser_pop_sync_item(parser_ctx);
871  }
872  ;
873 
874 sync_object_header
875  : OBJECT path DIRECTION path {
876  int status = 0;
877  $2.txt[$2.length] = 0;
878  $4.txt[$4.length] = 0;
879  $3 = amxo_parser_sync_update_flags($3);
880  status = amxo_parser_push_sync_object(parser_ctx, $2.txt, $4.txt, $3);
881  YY_CHECK(status != 0, "Object synchronization");
882  }
883  ;
884 
885 sync_param
886  : sync_param_header ';' {
887  amxo_parser_pop_sync_item(parser_ctx);
888  }
889  | sync_param_header '{' sync_param_body '}' {
890  amxo_parser_pop_sync_item(parser_ctx);
891  }
892  ;
893 
894 sync_param_header
895  : PARAMETER name DIRECTION name {
896  int status = 0;
897  $2.txt[$2.length] = 0;
898  $4.txt[$4.length] = 0;
899  $3 = amxo_parser_sync_update_flags($3);
900  status = amxo_parser_push_sync_parameter(parser_ctx, $2.txt, $4.txt, $3);
901  YY_CHECK(status != 0, "Parameter synchronization");
902  }
903  | SYNC_ATTRIBUTE PARAMETER name DIRECTION name {
904  int status = 0;
905  $3.txt[$3.length] = 0;
906  $5.txt[$5.length] = 0;
907  $4 = amxo_parser_sync_update_flags($4);
908  status = amxo_parser_push_sync_parameter(parser_ctx, $3.txt, $5.txt, $4 | $1);
909  YY_CHECK(status != 0, "Parameter synchronization");
910  }
911  ;
912 
913 sync_param_body
914  : action sync_param_body
915  | action
916  ;
917 
918 event_populate
919  : ON EVENT text_or_regexp event_func ';' {
920  int retval = amxo_parser_subscribe(parser_ctx,
921  $3.txt, $3.is_regexp,
922  NULL);
923  YY_CHECK(retval < 0, $3.txt);
924  YY_WARNING(retval > 0, $3.txt);
925  }
926  | ON EVENT text_or_regexp OF text_or_regexp event_func';' {
927  int retval = amxo_parser_subscribe_path(parser_ctx,
928  $3.txt, $3.is_regexp,
929  $5.txt, $5.is_regexp);
930  YY_CHECK(retval < 0, $3.txt);
931  YY_WARNING(retval > 0, $3.txt);
932  }
933  | ON EVENT text_or_regexp event_func filter';' {
934  int retval = 0;
935  $5.txt[$5.length] = 0;
936  retval = amxo_parser_subscribe(parser_ctx,
937  $3.txt, $3.is_regexp,
938  $5.txt);
939  YY_CHECK(retval < 0, $3.txt);
940  YY_WARNING(retval > 0, $3.txt);
941  }
942  ;
943 
944 text_or_regexp
945  : TEXT {
946  $1.txt[$1.length] = 0;
947  $$.txt = $1.txt;
948  $$.is_regexp = false;
949  }
950  | REGEXP '(' TEXT ')' {
951  $3.txt[$3.length] = 0;
952  $$.txt = $3.txt;
953  $$.is_regexp = true;
954  }
955  ;
956 
957 event_func
958  : CALL name {
959  int retval = 0;
960  $2.txt[$2.length] = 0;
961  retval = amxo_parser_resolve_internal(parser_ctx, $2.txt, amxo_function_event, "auto");
962  YY_CHECK(retval < 0, $2.txt);
963  YY_WARNING(retval > 0, $2.txt);
964  }
965  | CALL name RESOLVER {
966  int retval = 0;
967  $2.txt[$2.length] = 0;
968  $3.txt[$3.length] = 0;
969  retval = amxo_parser_resolve_internal(parser_ctx, $2.txt, amxo_function_event, $3.txt);
970  YY_CHECK(retval < 0, $2.txt);
971  YY_WARNING(retval > 0, $2.txt);
972  }
973  ;
974 
975 filter
976  : FILTER TEXT {
977  $$ = $2;
978  }
979  ;
980 
981 object_populate
982  : object_pop_header ';' {
983  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
984  }
985  | object_pop_header '{' '}' {
986  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
987  }
988  | object_pop_header '{' object_pop_body '}' {
989  YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
990  }
991  ;
992 
993 object_pop_header
994  : OBJECT path {
995  $2.txt[$2.length] = 0;
996  YY_CHECK(!amxo_parser_push_object(parser_ctx, $2.txt), $2.txt);
997  }
998  | unset_attributes attributes OBJECT path {
999  $4.txt[$4.length] = 0;
1000  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $4.txt);
1001  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $2, amxo_object_attrs), $4.txt);
1002  YY_CHECK(!amxo_parser_push_object(parser_ctx, $4.txt), $4.txt);
1003  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $1, false), $4.txt);
1004  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $2, true), $4.txt);
1005  }
1006  | attributes unset_attributes OBJECT path {
1007  $4.txt[$4.length] = 0;
1008  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $4.txt);
1009  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $2, amxo_object_attrs), $4.txt);
1010  YY_CHECK(!amxo_parser_push_object(parser_ctx, $4.txt), $4.txt);
1011  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $1, true), $4.txt);
1012  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $2, false), $4.txt);
1013  }
1014  | unset_attributes OBJECT path {
1015  $3.txt[$3.length] = 0;
1016  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $3.txt);
1017  YY_CHECK(!amxo_parser_push_object(parser_ctx, $3.txt), $3.txt);
1018  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $1, false), $3.txt);
1019  }
1020  | attributes OBJECT path {
1021  $3.txt[$3.length] = 0;
1022  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_object_attrs), $3.txt);
1023  YY_CHECK(!amxo_parser_push_object(parser_ctx, $3.txt), $3.txt);
1024  YY_CHECK(!amxo_parser_set_object_attrs(parser_ctx, $1, true), $3.txt);
1025  }
1026  | INSTANCE OF '(' ')' {
1027  YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, NULL, NULL), "");
1028  }
1029  | INSTANCE OF '(' instance_id ')'
1030  ;
1031 
1032 instance_id
1033  : DIGIT {
1034  YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, NULL, NULL), "");
1035  }
1036  | name {
1037  $1.txt[$1.length] = 0;
1038  YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, $1.txt, NULL), "");
1039  }
1040  | DIGIT ',' name {
1041  $3.txt[$3.length] = 0;
1042  YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, $3.txt, NULL), "");
1043  }
1044  | data_options {
1045  YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, NULL, $1), "");
1046  }
1047  | DIGIT ',' data_options {
1048  YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, NULL, $3), "");
1049  }
1050  | name ',' data_options {
1051  $1.txt[$1.length] = 0;
1052  YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, $1.txt, $3), "");
1053  }
1054  | DIGIT ',' name ',' data_options {
1055  $3.txt[$3.length] = 0;
1056  YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, $3.txt, $5), "");
1057  }
1058  ;
1059 
1060 object_pop_body
1061  : object_pop_body object_pop_content
1062  | object_pop_content
1063  ;
1064 
1065 object_pop_content
1066  : param_pop_head ';' {
1067  amxo_parser_pop_param(parser_ctx);
1068  }
1069  | param_pop_head '{' '}' {
1070  amxo_parser_pop_param(parser_ctx);
1071  }
1072  | param_pop_head '{' param_pop_body '}' {
1073  amxo_parser_pop_param(parser_ctx);
1074  }
1075  | object_populate
1076  | add_mib
1077  ;
1078 
1079 param_pop_head
1080  : parameter
1081  | unset_attributes attributes parameter {
1082  if (parser_ctx->param != NULL) {
1083  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
1084  amxd_param_get_name(parser_ctx->param));
1085  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $2, amxo_param_attrs),
1086  amxd_param_get_name(parser_ctx->param));
1087  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $1, false),
1088  amxd_param_get_name(parser_ctx->param));
1089  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $2, true),
1090  amxd_param_get_name(parser_ctx->param));
1091  }
1092  }
1093  | attributes unset_attributes parameter {
1094  if (parser_ctx->param != NULL) {
1095  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
1096  amxd_param_get_name(parser_ctx->param));
1097  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $2, amxo_param_attrs),
1098  amxd_param_get_name(parser_ctx->param));
1099  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $1, true),
1100  amxd_param_get_name(parser_ctx->param));
1101  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $2, false),
1102  amxd_param_get_name(parser_ctx->param));
1103  }
1104  }
1105  | unset_attributes parameter {
1106  if (parser_ctx->param != NULL) {
1107  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
1108  amxd_param_get_name(parser_ctx->param));
1109  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $1, false),
1110  amxd_param_get_name(parser_ctx->param));
1111  }
1112  }
1113  | attributes parameter {
1114  if (parser_ctx->param != NULL) {
1115  YY_CHECK(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
1116  amxd_param_get_name(parser_ctx->param));
1117  YY_CHECK(!amxo_parser_set_param_attrs(parser_ctx, $1, true),
1118  amxd_param_get_name(parser_ctx->param));
1119  }
1120  }
1121  ;
1122 
1123 parameter
1124  : PARAMETER name '=' value {
1125  int retval = 0;
1126  $2.txt[$2.length] = 0;
1127  retval = amxo_parser_set_param(parser_ctx, $2.txt, $4);
1128  YY_CHECK_ACTION(retval < 0, $2.txt, amxc_var_delete(&$4));
1129  YY_WARNING(retval > 0, $2.txt);
1130  amxc_var_delete(&$4);
1131  }
1132  | PARAMETER name {
1133  int retval = 0;
1134  $2.txt[$2.length] = 0;
1135  retval = amxo_parser_set_param(parser_ctx, $2.txt, NULL);
1136  YY_CHECK(retval < 0, $2.txt);
1137  YY_WARNING(retval > 0, $2.txt);
1138  }
1139  ;
1140 
1141 param_pop_body
1142  : FLAGS flags ';' {
1143  YY_CHECK(!amxo_parser_set_param_flags(parser_ctx, $2), "Parameter flags");
1144  }
1145  ;
1146 
1147 path
1148  : name '.' path {
1149  $1.txt[$1.length] = '.';
1150  $$.txt = $1.txt;
1151  $$.length = strlen($1.txt);
1152  }
1153  | name {
1154  $1.txt[$1.length] = 0;
1155  }
1156  ;
1157 
1158 unset_attributes
1159  : UNSET_ATTRIBUTE unset_attributes{
1160  $$ = $1 | $2;
1161  }
1162  | UNSET_ATTRIBUTE
1163  ;
1164 
1165 attributes
1166  : SET_ATTRIBUTE attributes {
1167  $$ = $1 | $2;
1168  }
1169  | SET_ATTRIBUTE
1170  ;
1171 
1172 name
1173  : STRING
1174  | TEXT
1175  ;
1176 
1177 data
1178  : value {
1179  $$ = $1;
1180  }
1181  ;
1182 
1183 data_options
1184  : data_option ',' data_options {
1185  amxc_var_for_each(var, $1) {
1186  amxc_var_set_path($3, amxc_var_key(var), var, AMXC_VAR_FLAG_UPDATE | AMXC_VAR_FLAG_COPY | AMXC_VAR_FLAG_AUTO_ADD);
1187  }
1188  amxc_var_delete(&$1);
1189  $$ = $3;
1190  }
1191  | data_option {
1192  $$ = $1;
1193  amxc_var_for_each(var, $1) {
1194  char* key = strdup(amxc_var_key(var));
1195  amxc_var_take_it(var);
1196  amxc_var_set_path($1, key, var, AMXC_VAR_FLAG_UPDATE | AMXC_VAR_FLAG_COPY | AMXC_VAR_FLAG_AUTO_ADD);
1197  free(key);
1198  amxc_var_delete(&var);
1199  }
1200  }
1201  ;
1202 
1203 data_option
1204  : path '=' value {
1205  $1.txt[$1.length] = 0;
1206  amxc_var_new(&$$);
1207  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1208  amxc_var_set_key($$, $1.txt, $3, AMXC_VAR_FLAG_DEFAULT);
1209  }
1210  ;
1211 
1212 values
1213  : values ',' value {
1214  if (amxc_var_type_of($1) != AMXC_VAR_ID_LIST) {
1215  amxc_var_new(&$$);
1216  amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1217  amxc_var_set_index($$, -1, $1, AMXC_VAR_FLAG_DEFAULT);
1218  }
1219  amxc_var_set_index($$, -1, $3, AMXC_VAR_FLAG_DEFAULT);
1220  }
1221  | value {
1222  if (amxc_var_type_of($1) != AMXC_VAR_ID_LIST) {
1223  amxc_var_new(&$$);
1224  amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1225  amxc_var_set_index($$, -1, $1, AMXC_VAR_FLAG_DEFAULT);
1226  } else {
1227  $$ = $1;
1228  }
1229  }
1230  ;
1231 
1232 value
1233  : TEXT {
1234  amxc_string_t txt;
1235  $1.txt[$1.length] = 0;
1236  amxc_string_init(&txt, $1.length + 1);
1237  amxc_string_append(&txt, $1.txt, $1.length);
1238  amxo_parser_resolve_value(parser_ctx, &txt);
1239  amxc_var_new(&$$);
1240  amxc_var_push(cstring_t, $$, amxc_string_take_buffer(&txt));
1241  }
1242  | STRING {
1243  $1.txt[$1.length] = 0;
1244  amxc_var_new(&$$);
1245  amxc_var_set(cstring_t, $$, $1.txt);
1246  }
1247  | DIGIT {
1248  amxc_var_new(&$$);
1249  amxc_var_set(int64_t, $$, $1);
1250  }
1251  | BOOL {
1252  amxc_var_new(&$$);
1253  amxc_var_set(bool, $$, $1);
1254  }
1255  | '{' '}' {
1256  amxc_var_new(&$$);
1257  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1258  }
1259  | '[' ']' {
1260  amxc_var_new(&$$);
1261  amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1262  }
1263  | '{' data_options '}' {
1264  $$ = $2;
1265  }
1266  | '[' values ']' {
1267  $$ = $2;
1268  }
1269 
1270  ;
1271 
1272 flags
1273  : flags ',' flag {
1274  if (amxc_var_type_of($1) != AMXC_VAR_ID_HTABLE) {
1275  amxc_var_new(&$$);
1276  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1277  amxc_var_set_key($$, $1->hit.key, $1, AMXC_VAR_FLAG_DEFAULT | AMXC_VAR_FLAG_UPDATE);
1278  }
1279  amxc_var_set_key($$, $3->hit.key, $3, AMXC_VAR_FLAG_DEFAULT | AMXC_VAR_FLAG_UPDATE);
1280  }
1281  | flag {
1282  if (amxc_var_type_of($1) != AMXC_VAR_ID_HTABLE) {
1283  amxc_var_new(&$$);
1284  amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1285  amxc_var_set_key($$, $1->hit.key, $1, AMXC_VAR_FLAG_DEFAULT | AMXC_VAR_FLAG_UPDATE);
1286  } else {
1287  $$ = $1;
1288  }
1289  }
1290  ;
1291 
1292 flag
1293  : '%' STRING {
1294  $2.txt[$2.length] = 0;
1295  amxc_var_new(&$$);
1296  amxc_var_set(bool, $$, true);
1297  $$->hit.key = strdup($2.txt);
1298  }
1299  | '!' STRING {
1300  $2.txt[$2.length] = 0;
1301  amxc_var_new(&$$);
1302  amxc_var_set(bool, $$, false);
1303  $$->hit.key = strdup($2.txt);
1304  }
1305  ;
1306 
1307 %%