Merged revisions 189462 via svnmerge from
[asterisk/asterisk.git] / res / ael / ael.y
index c1f04fd..c8bc9c7 100644 (file)
@@ -31,7 +31,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <string.h>
 
 #include "asterisk/logger.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
 #include "asterisk/ael_structs.h"
+#include "asterisk/utils.h"
+
+extern struct ast_flags ast_compat;
 
 pval * linku1(pval *head, pval *tail);
 static void set_dads(pval *dad, pval *child_list);
@@ -46,7 +51,7 @@ extern char *my_file;
 #ifdef AAL_ARGCHECK
 int ael_is_funcname(char *name);
 #endif
-static char *ael_token_subst(char *mess);
+static char *ael_token_subst(const char *mess);
 
 %}
 
@@ -80,7 +85,7 @@ static pval *update_last(pval *, YYLTYPE *);
 
 
 %token KW_CONTEXT LC RC LP RP SEMI EQ COMMA COLON AMPER BAR AT
-%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT
+%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT KW_EXTEND
 %token EXTENMARK KW_GOTO KW_JUMP KW_RETURN KW_BREAK KW_CONTINUE KW_REGEXTEN KW_HINT
 %token KW_FOR KW_WHILE KW_CASE KW_PATTERN KW_DEFAULT KW_CATCH KW_SWITCHES KW_ESWITCHES
 %token KW_INCLUDES KW_LOCAL
@@ -154,7 +159,7 @@ static pval *update_last(pval *, YYLTYPE *);
 
 /* there will be two shift/reduce conflicts, they involve the if statement, where a single statement occurs not wrapped in curlies in the "true" section
    the default action to shift will attach the else to the preceeding if. */
-%expect 3
+%expect 30
 %error-verbose
 
 /*
@@ -202,22 +207,19 @@ context_name : word { $$ = $1; }
        ;
 
 context : opt_abstract KW_CONTEXT context_name LC elements RC {
-               if (!$5) {
-                        ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Warning! The empty context %s will be IGNORED!\n", 
-                               my_file, @4.first_line, @4.first_column, @4.last_column, $3 );
-                       free($3);
-
-               } else {
-                       $$ = npval2(PV_CONTEXT, &@1, &@6);
-                       $$->u1.str = $3;
-                       $$->u2.statements = $5;
-                       set_dads($$,$5);
-                       $$->u3.abstract = $1;} }
+               $$ = npval2(PV_CONTEXT, &@1, &@6);
+               $$->u1.str = $3;
+               $$->u2.statements = $5;
+               set_dads($$,$5);
+               $$->u3.abstract = $1;} 
        ;
 
 /* optional "abstract" keyword  XXX there is no regression test for this */
 opt_abstract: KW_ABSTRACT { $$ = 1; }
        | /* nothing */ { $$ = 0; }
+       | KW_EXTEND { $$ = 2; }
+       | KW_EXTEND KW_ABSTRACT { $$=3; }
+       | KW_ABSTRACT KW_EXTEND { $$=3; }
        ;
 
 macro : KW_MACRO word LP arglist RP LC macro_statements RC {
@@ -233,7 +235,7 @@ globals : KW_GLOBALS LC global_statements RC {
        ;
 
 global_statements : { $$ = NULL; }
-       | assignment global_statements {$$ = linku1($1, $2); }
+       | global_statements assignment {$$ = linku1($1, $2); }
        | error global_statements {$$=$2;}
        ;
 
@@ -257,7 +259,7 @@ arglist : /* empty */ { $$ = NULL; }
        ;
 
 elements : {$$=0;}
-       | element elements { $$ = linku1($1, $2); }
+       | elements element { $$ = linku1($1, $2); }
        | error elements  { $$=$2;}
        ;
 
@@ -281,6 +283,14 @@ extension : word EXTENMARK statement {
                $$ = npval2(PV_EXTENSION, &@1, &@3);
                $$->u1.str = $1;
                $$->u2.statements = $3; set_dads($$,$3);}
+       | word AT word EXTENMARK statement {
+               $$ = npval2(PV_EXTENSION, &@1, &@3);
+               $$->u1.str = malloc(strlen($1)+strlen($3)+2);
+               strcpy($$->u1.str,$1);
+               strcat($$->u1.str,"@");
+               strcat($$->u1.str,$3);
+               free($1);
+               $$->u2.statements = $5; set_dads($$,$5);}
        | KW_REGEXTEN word EXTENMARK statement {
                $$ = npval2(PV_EXTENSION, &@1, &@4);
                $$->u1.str = $2;
@@ -297,12 +307,11 @@ extension : word EXTENMARK statement {
                $$->u2.statements = $8; set_dads($$,$8);
                $$->u4.regexten=1;
                $$->u3.hints = $4;}
-
        ;
 
 /* list of statements in a block or after a case label - can be empty */
 statements : /* empty */ { $$ = NULL; }
-       | statement statements { $$ = linku1($1, $2); }
+       | statements statement { $$ = linku1($1, $2); }
        | error statements {$$=$2;}
        ;
 
@@ -310,10 +319,15 @@ statements : /* empty */ { $$ = NULL; }
  * detect the '-' but only the ':' as separator
  */
 timerange: word3_list COLON word3_list COLON word3_list {
-               asprintf(&$$, "%s:%s:%s", $1, $3, $5);
-               free($1);
-               free($3);
-               free($5); }
+               if (asprintf(&$$, "%s:%s:%s", $1, $3, $5) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($3);
+                       free($5);
+               }
+       }
        | word { $$ = $1; }
        ;
 
@@ -349,46 +363,99 @@ if_like_head : KW_IF test_expr {
 
 word_list : word { $$ = $1;}
        | word word {
-               asprintf(&($$), "%s%s", $1, $2);
-               free($1);
-               free($2);
-               prev_word = $$;}
+               if (asprintf(&($$), "%s%s", $1, $2) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($2);
+                       prev_word = $$;
+               }
+       }
        ;
 
 hint_word : word { $$ = $1; }
        | hint_word word {
-               asprintf(&($$), "%s %s", $1, $2);
-               free($1);
-               free($2); }
+               if (asprintf(&($$), "%s %s", $1, $2) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($2);
+               }
+       }
+       | hint_word COLON word {
+               if (asprintf(&($$), "%s:%s", $1, $3) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($3);
+               }
+       }
        | hint_word AMPER word {  /* there are often '&' in hints */
-               asprintf(&($$), "%s&%s", $1, $3);
-               free($1);
-               free($3);}
-
+               if (asprintf(&($$), "%s&%s", $1, $3) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($3);
+               }
+       }
+       | hint_word AT word {
+               if (asprintf(&($$), "%s@%s", $1, $3) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($3);
+               }
+       }
+       ;
 
 word3_list : word { $$ = $1;}
        | word word {
-               asprintf(&($$), "%s%s", $1, $2);
-               free($1);
-               free($2);
-               prev_word = $$;}
+               if (asprintf(&($$), "%s%s", $1, $2) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($2);
+                       prev_word = $$;
+               }                       
+       }
        | word word word {
-               asprintf(&($$), "%s%s%s", $1, $2, $3);
-               free($1);
-               free($2);
-               free($3);
-               prev_word=$$;}
+               if (asprintf(&($$), "%s%s%s", $1, $2, $3) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($2);
+                       free($3);
+                       prev_word=$$;
+               }
+       }
        ;
 
 goto_word : word { $$ = $1;}
        | word word {
-               asprintf(&($$), "%s%s", $1, $2);
-               free($1);
-               free($2);}
+               if (asprintf(&($$), "%s%s", $1, $2) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($2);
+               }
+       }
        | goto_word COLON word {
-               asprintf(&($$), "%s:%s", $1, $3);
-               free($1);
-               free($3);}
+               if (asprintf(&($$), "%s:%s", $1, $3) < 0) {
+                       ast_log(LOG_WARNING, "asprintf() failed\n");
+                       $$ = NULL;
+               } else {
+                       free($1);
+                       free($3);
+               }
+       }
        ;
 
 switch_statement : KW_SWITCH test_expr LC case_statements RC {
@@ -564,7 +631,7 @@ eval_arglist :  word_list { $$ = nword($1, &@1); }
        ;
 
 case_statements: /* empty */ { $$ = NULL; }
-       | case_statement case_statements { $$ = linku1($1, $2); }
+       | case_statements case_statement { $$ = linku1($1, $2); }
        ;
 
 case_statement: KW_CASE word COLON statements {
@@ -582,7 +649,7 @@ case_statement: KW_CASE word COLON statements {
        ;
 
 macro_statements: /* empty */ { $$ = NULL; }
-       | macro_statement macro_statements { $$ = linku1($1, $2); }
+       | macro_statements macro_statement { $$ = linku1($1, $2); }
        ;
 
 macro_statement : statement {$$=$1;}
@@ -604,9 +671,18 @@ eswitches : KW_ESWITCHES LC switchlist RC {
        ;
 
 switchlist : /* empty */ { $$ = NULL; }
-       | word SEMI switchlist { $$ = linku1(nword($1, &@1), $3); }
-       | word AT word SEMI switchlist { char *x; asprintf(&x,"%s@%s", $1,$3); free($1); free($3);
-                                                                         $$ = linku1(nword(x, &@1), $5);}
+       | switchlist word SEMI { $$ = linku1($1,nword($2, &@2)); }
+       | switchlist word AT word SEMI {
+         char *x;
+         if (asprintf(&x,"%s@%s", $2, $4) < 0) {
+               ast_log(LOG_WARNING, "asprintf() failed\n");
+               $$ = NULL;
+         } else {
+               free($2);
+               free($4);
+               $$ = linku1($1,nword(x, &@2));
+         }
+       }
        | error switchlist {$$=$2;}
        ;
 
@@ -714,11 +790,11 @@ static char *token_equivs2[] =
 };
 
 
-static char *ael_token_subst(char *mess)
+static char *ael_token_subst(const char *mess)
 {
        /* calc a length, malloc, fill, and return; yyerror had better free it! */
        int len=0,i;
-       char *p;
+       const char *p;
        char *res, *s,*t;
        int token_equivs_entries = sizeof(token_equivs1)/sizeof(char*);