1 /****************************************************************************
3 ** Copyright (c) 2020 SoftAtHome
5 ** Redistribution and use in source and binary forms, with or
6 ** without modification, are permitted provided that the following
9 ** 1. Redistributions of source code must retain the above copyright
10 ** notice, this list of conditions and the following disclaimer.
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.
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
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
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.
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.
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.
59 ****************************************************************************/
63 %define parse.error verbose
64 %parse-param {void *ctx}
65 %lex-param {void *ctx}
72 #include "amxo_parser_priv.h"
73 #include "amxo_parser_hooks_priv.h"
74 #include "amxo_parser.tab.h"
86 amxo_txt_regexp_t cregexp;
90 %token <integer> REQUIRES
91 %token <integer> INCLUDE
92 %token <integer> IMPORT
93 %token <integer> USING
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
111 %token <integer> DEFAULT
112 %token <integer> EVENT
113 %token <integer> FILTER
115 %token <integer> GLOBAL
116 %token <integer> CALL
117 %token <integer> ACTION_KW
119 %token <cptr> MULTILINECOMMENT
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
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
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 );
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),
161 amxc_string_reset(&context->msg);
163 amxo_parser_printf(context, "ERROR : %s@%s:line %d\n",
169 if (!amxc_string_is_empty(&context->msg)) {
170 amxo_parser_printf(context, "ERROR : %d - %s@%s:line %d\n",
172 amxc_string_get(&context->msg, 0),
175 amxc_string_reset(&context->msg);
177 amxo_parser_printf(context, "ERROR : %d - %s - %s@%s:line %d\n",
179 amxd_status_string(context->status),
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),
194 amxc_string_reset(&context->msg);
196 amxo_parser_printf(context, "WARNING: %s@%s:line %d\n",
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); }
210 const uint64_t amxo_object_attrs = ((1 << attr_readonly) |
211 (1 << attr_persistent) |
212 (1 << attr_private) |
213 (1 << attr_protected));
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) |
223 (1 << attr_protected) |
224 (1 << attr_mutable));
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));
232 const uint64_t amxo_arg_attrs = ((1 << attr_in) |
234 (1 << attr_mandatory) |
243 stream: /* empty */ { NOOP; }
259 amxo_hooks_end_section(parser_ctx, 0);
261 | CONFIG '{' config_options '}' {
262 amxo_hooks_end_section(parser_ctx, 0);
265 amxo_hooks_end_section(parser_ctx, 1);
267 | DEFINE '{' defines '}' {
268 amxo_hooks_end_section(parser_ctx, 1);
271 amxo_hooks_end_section(parser_ctx, 2);
273 | POPULATE '{' populates '}' {
274 amxo_hooks_end_section(parser_ctx, 2);
280 : config_option config_options
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,
290 amxc_var_delete(&$3);
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);
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,
303 amxc_var_delete(&$4);
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);
316 : REQUIRES TEXT ';' {
317 amxc_var_t* req = NULL;
318 amxc_string_t *name = NULL;
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);
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);
329 amxc_var_add(cstring_t, req, $2.txt);
336 $2.txt[$2.length] = 0;
337 amxo_parser_print(parser_ctx, $2.txt);
344 $2.txt[$2.length] = 0;
345 if ($1 != token_post_include) {
346 retval = amxo_parser_include(parser_ctx, $2.txt);
348 // is an empty directory - not an error
352 retval = amxo_parser_add_post_include(parser_ctx, $2.txt);
354 YY_CHECK(retval != 0 && !(retval == 2 && $1 == token_optional_include), $2.txt);
355 parser_ctx->status = amxd_status_ok;
357 | INCLUDE TEXT ':' TEXT ';' {
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);
370 YY_CHECK(retval != 0, $2.txt);
376 $2.txt[$2.length] = 0;
377 YY_CHECK(amxo_resolver_import_open(parser_ctx, $2.txt, $2.txt, RTLD_LAZY) != 0,
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,
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,
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,
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");
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");
432 | object_def_header '{' object_body '}' {
433 YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
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,
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);
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);
460 YY_CHECK(amxo_parser_create_object(parser_ctx, $3.txt, $1, amxd_object_singleton) < 0, $3.txt);
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");
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");
478 $2.txt[$2.length] = 0;
479 YY_CHECK(!amxo_parser_push_object(parser_ctx, $2.txt), $2.txt);
493 : object_body object_content
510 YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
512 | param_header '{' '}' {
513 YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
515 | param_header '{' param_body '}' {
516 YY_CHECK(!amxo_parser_pop_param(parser_ctx), "Validate");
522 $2.txt[$2.length] = 0;
523 YY_CHECK(!amxo_parser_push_param(parser_ctx, $2.txt, 0, $1), $2.txt);
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);
530 | TYPE name '=' value {
532 $2.txt[$2.length] = 0;
533 YY_CHECK_ACTION(!amxo_parser_push_param(parser_ctx, $2.txt, 0, $1),
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);
540 | attributes TYPE name '=' value {
541 bool key_attr_is_set = ($1 & (1 << attr_key));
543 $3.txt[$3.length] = 0;
544 YY_CHECK_ACTION(!amxo_parser_check_attr(parser_ctx, $1, amxo_param_attrs),
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),
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);
561 : param_body param_content
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);
575 YY_CHECK(!amxo_parser_set_param_flags(parser_ctx, $2), "Parameter flags");
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");
586 | action_header action_function data ';' {
587 amxc_var_t* data = parser_ctx->data == NULL?$3:parser_ctx->data;
589 if (parser_ctx->data != NULL) {
590 amxc_var_delete(&$3);
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");
600 : ON ACTION_KW name {
601 if ($3.length != 0) {
602 $3.txt[$3.length] = 0;
604 $$ = amxo_parser_get_action_id(parser_ctx, $3.txt);
605 YY_CHECK($$ < 0 , $3.txt);
607 | ON ACTION_KW TYPE {
608 YY_CHECK($3 != AMXC_VAR_ID_LIST , "Invalid action");
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);
622 | CALL name RESOLVER {
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);
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);
640 | function_header func_args RESOLVER ';' {
641 const char *func_name = NULL;
643 if ($3.length != 0) {
644 $3.txt[$3.length] = 0;
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);
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);
659 | function_header func_args RESOLVER '{' func_body '}' {
661 const char *func_name = NULL;
662 if ($3.length != 0) {
663 $3.txt[$3.length] = 0;
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);
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);
681 | attributes TYPE name {
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);
697 : argument_def ',' arguments
703 YY_CHECK(!amxo_parser_set_function_flags(parser_ctx, $2), "Function flags");
709 $2.txt[$2.length] = 0;
710 YY_CHECK(!amxo_parser_add_arg(parser_ctx, $2.txt, 0, $1, NULL), $2.txt);
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);
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),
721 amxc_var_delete(&$4));
722 amxc_var_delete(&$4);
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),
728 amxc_var_delete(&$5));
729 YY_CHECK_ACTION(!amxo_parser_add_arg(parser_ctx, $3.txt, $1, $2, $5),
731 amxc_var_delete(&$5));
732 amxc_var_delete(&$5);
737 : COUNTER WITH name ';' {
738 $3.txt[$3.length] = 0;
739 YY_CHECK(!amxo_parser_set_counter(parser_ctx, $3.txt), $3.txt);
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);
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);
758 $2.txt[$2.length] = 0;
759 YY_CHECK(amxd_object_add_event(parser_ctx->object, $2.txt) != 0,
760 "Failed to add event");
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");
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");
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);
782 amxc_var_delete(&$1);
792 amxc_var_t* value = NULL;
793 $2.txt[$2.length] = 0;
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);
799 | TYPE name '=' value ';' {
800 $2.txt[$2.length] = 0;
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);
809 : ON EVENT text_or_regexp event_func ';' {
810 int retval = amxo_parser_subscribe_object(parser_ctx,
811 $3.txt, $3.is_regexp,
813 YY_CHECK(retval < 0, $3.txt);
814 YY_WARNING(retval > 0, $3.txt);
816 | ON EVENT text_or_regexp event_func filter ';' {
818 $5.txt[$5.length] = 0;
819 retval = amxo_parser_subscribe_object(parser_ctx,
820 $3.txt, $3.is_regexp,
822 YY_CHECK(retval < 0, $3.txt);
823 YY_WARNING(retval > 0, $3.txt);
835 : sync_header '{' sync_items '}'
839 : SYNC path DIRECTION path {
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");
847 | SYNC path DIRECTION path AS name {
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");
859 : sync_object sync_items
860 | sync_param sync_items
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);
875 : OBJECT path DIRECTION path {
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");
886 : sync_param_header ';' {
887 amxo_parser_pop_sync_item(parser_ctx);
889 | sync_param_header '{' sync_param_body '}' {
890 amxo_parser_pop_sync_item(parser_ctx);
895 : PARAMETER name DIRECTION name {
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");
903 | SYNC_ATTRIBUTE PARAMETER name DIRECTION name {
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");
914 : action sync_param_body
919 : ON EVENT text_or_regexp event_func ';' {
920 int retval = amxo_parser_subscribe(parser_ctx,
921 $3.txt, $3.is_regexp,
923 YY_CHECK(retval < 0, $3.txt);
924 YY_WARNING(retval > 0, $3.txt);
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);
933 | ON EVENT text_or_regexp event_func filter';' {
935 $5.txt[$5.length] = 0;
936 retval = amxo_parser_subscribe(parser_ctx,
937 $3.txt, $3.is_regexp,
939 YY_CHECK(retval < 0, $3.txt);
940 YY_WARNING(retval > 0, $3.txt);
946 $1.txt[$1.length] = 0;
948 $$.is_regexp = false;
950 | REGEXP '(' TEXT ')' {
951 $3.txt[$3.length] = 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);
965 | CALL name RESOLVER {
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);
982 : object_pop_header ';' {
983 YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
985 | object_pop_header '{' '}' {
986 YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
988 | object_pop_header '{' object_pop_body '}' {
989 YY_CHECK(!amxo_parser_pop_object(parser_ctx), "Validation failed");
995 $2.txt[$2.length] = 0;
996 YY_CHECK(!amxo_parser_push_object(parser_ctx, $2.txt), $2.txt);
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);
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);
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);
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);
1026 | INSTANCE OF '(' ')' {
1027 YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, NULL, NULL), "");
1029 | INSTANCE OF '(' instance_id ')'
1034 YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, NULL, NULL), "");
1037 $1.txt[$1.length] = 0;
1038 YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, $1.txt, NULL), "");
1041 $3.txt[$3.length] = 0;
1042 YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, $3.txt, NULL), "");
1045 YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, NULL, $1), "");
1047 | DIGIT ',' data_options {
1048 YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, NULL, $3), "");
1050 | name ',' data_options {
1051 $1.txt[$1.length] = 0;
1052 YY_CHECK(!amxo_parser_add_instance(parser_ctx, 0, $1.txt, $3), "");
1054 | DIGIT ',' name ',' data_options {
1055 $3.txt[$3.length] = 0;
1056 YY_CHECK(!amxo_parser_add_instance(parser_ctx, $1, $3.txt, $5), "");
1061 : object_pop_body object_pop_content
1062 | object_pop_content
1066 : param_pop_head ';' {
1067 amxo_parser_pop_param(parser_ctx);
1069 | param_pop_head '{' '}' {
1070 amxo_parser_pop_param(parser_ctx);
1072 | param_pop_head '{' param_pop_body '}' {
1073 amxo_parser_pop_param(parser_ctx);
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));
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));
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));
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));
1124 : PARAMETER name '=' value {
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);
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);
1143 YY_CHECK(!amxo_parser_set_param_flags(parser_ctx, $2), "Parameter flags");
1149 $1.txt[$1.length] = '.';
1151 $$.length = strlen($1.txt);
1154 $1.txt[$1.length] = 0;
1159 : UNSET_ATTRIBUTE unset_attributes{
1166 : SET_ATTRIBUTE attributes {
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);
1188 amxc_var_delete(&$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);
1198 amxc_var_delete(&var);
1205 $1.txt[$1.length] = 0;
1207 amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1208 amxc_var_set_key($$, $1.txt, $3, AMXC_VAR_FLAG_DEFAULT);
1213 : values ',' value {
1214 if (amxc_var_type_of($1) != AMXC_VAR_ID_LIST) {
1216 amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1217 amxc_var_set_index($$, -1, $1, AMXC_VAR_FLAG_DEFAULT);
1219 amxc_var_set_index($$, -1, $3, AMXC_VAR_FLAG_DEFAULT);
1222 if (amxc_var_type_of($1) != AMXC_VAR_ID_LIST) {
1224 amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1225 amxc_var_set_index($$, -1, $1, AMXC_VAR_FLAG_DEFAULT);
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);
1240 amxc_var_push(cstring_t, $$, amxc_string_take_buffer(&txt));
1243 $1.txt[$1.length] = 0;
1245 amxc_var_set(cstring_t, $$, $1.txt);
1249 amxc_var_set(int64_t, $$, $1);
1253 amxc_var_set(bool, $$, $1);
1257 amxc_var_set_type($$, AMXC_VAR_ID_HTABLE);
1261 amxc_var_set_type($$, AMXC_VAR_ID_LIST);
1263 | '{' data_options '}' {
1274 if (amxc_var_type_of($1) != AMXC_VAR_ID_HTABLE) {
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);
1279 amxc_var_set_key($$, $3->hit.key, $3, AMXC_VAR_FLAG_DEFAULT | AMXC_VAR_FLAG_UPDATE);
1282 if (amxc_var_type_of($1) != AMXC_VAR_ID_HTABLE) {
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);
1294 $2.txt[$2.length] = 0;
1296 amxc_var_set(bool, $$, true);
1297 $$->hit.key = strdup($2.txt);
1300 $2.txt[$2.length] = 0;
1302 amxc_var_set(bool, $$, false);
1303 $$->hit.key = strdup($2.txt);