mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-06 05:02:29 +00:00
This finishes the changes for making Macro args LOCAL to the call, and allowing users to declare local variables.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@70461 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
9
CHANGES
9
CHANGES
@@ -162,7 +162,14 @@ Miscellaneous
|
|||||||
recursive call depths of 100,000 without problems.
|
recursive call depths of 100,000 without problems.
|
||||||
-- in addition to this, all apps that allowed a macro
|
-- in addition to this, all apps that allowed a macro
|
||||||
to be called, as in Dial, queues, etc, are now allowing
|
to be called, as in Dial, queues, etc, are now allowing
|
||||||
a gosub call in similar fashion also.
|
a gosub call in similar fashion.
|
||||||
|
* AEL now generates LOCAL(argname) declarations when it
|
||||||
|
Set()'s the each arg name to the value of ${ARG1}, ${ARG2),
|
||||||
|
etc. That makes the arguments local in scope. The user
|
||||||
|
can define their own local variables in macros, now,
|
||||||
|
by saying "local myvar=someval;" or using Set() in this
|
||||||
|
fashion: Set(LOCAL(myvar)=someval); ("local" is now
|
||||||
|
an AEL keyword).
|
||||||
* Ability to use libcap to set high ToS bits when non-root
|
* Ability to use libcap to set high ToS bits when non-root
|
||||||
on Linux. If configure is unable to find libcap then you
|
on Linux. If configure is unable to find libcap then you
|
||||||
can use --with-cap to specify the path.
|
can use --with-cap to specify the path.
|
||||||
|
46
doc/ael.tex
46
doc/ael.tex
@@ -264,6 +264,7 @@ The following are keywords in the AEL language:
|
|||||||
\item random
|
\item random
|
||||||
\item goto
|
\item goto
|
||||||
\item jump
|
\item jump
|
||||||
|
\item local
|
||||||
\item return
|
\item return
|
||||||
\item break
|
\item break
|
||||||
\item continue
|
\item continue
|
||||||
@@ -368,6 +369,7 @@ First, some basic objects
|
|||||||
| <eswitches>
|
| <eswitches>
|
||||||
| <ignorepat>
|
| <ignorepat>
|
||||||
| <word> '=' <collected-word> ';'
|
| <word> '=' <collected-word> ';'
|
||||||
|
| 'local' <word> '=' <collected-word> ';'
|
||||||
| ';'
|
| ';'
|
||||||
|
|
||||||
|
|
||||||
@@ -400,6 +402,7 @@ First, some basic objects
|
|||||||
|
|
||||||
<statement> :== '{' <statements> '}'
|
<statement> :== '{' <statements> '}'
|
||||||
| <word> '=' <collected-word> ';'
|
| <word> '=' <collected-word> ';'
|
||||||
|
| 'local' <word> '=' <collected-word> ';'
|
||||||
| 'goto' <target> ';'
|
| 'goto' <target> ';'
|
||||||
| 'jump' <jumptarget> ';'
|
| 'jump' <jumptarget> ';'
|
||||||
| <word> ':'
|
| <word> ':'
|
||||||
@@ -719,6 +722,49 @@ context blah {
|
|||||||
}
|
}
|
||||||
\end{verbatim}
|
\end{verbatim}
|
||||||
|
|
||||||
|
You can declare variables in Macros, as so:
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
Macro myroutine(firstarg, secondarg)
|
||||||
|
{
|
||||||
|
Myvar=1;
|
||||||
|
NoOp(Myvar is set to ${myvar});
|
||||||
|
}
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\subsection{Local Variables}
|
||||||
|
|
||||||
|
In 1.2, and 1.4, ALL VARIABLES are CHANNEL variables, including the function
|
||||||
|
arguments and associated ARG1, ARG2, etc variables. Sorry.
|
||||||
|
|
||||||
|
In trunk (1.6 and higher), we have made all arguments local variables to
|
||||||
|
a macro call. They will not affect channel variables of the same name.
|
||||||
|
This includes the ARG1, ARG2, etc variables.
|
||||||
|
|
||||||
|
Users can declare their own local variables by using the keyword 'local'
|
||||||
|
before setting them to a value;
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
Macro myroutine(firstarg, secondarg)
|
||||||
|
{
|
||||||
|
local Myvar=1;
|
||||||
|
NoOp(Myvar is set to ${Myvar}, and firstarg is ${firstarg}, and secondarg is ${secondarg});
|
||||||
|
}
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
In the above example, Myvar, firstarg, and secondarg are all local variables,
|
||||||
|
and will not be visible to the calling code, be it an extension, or another Macro.
|
||||||
|
|
||||||
|
If you need to make a local variable within the Set() application, you can do it this way:
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
Macro myroutine(firstarg, secondarg)
|
||||||
|
{
|
||||||
|
Set(LOCAL(Myvar)=1);
|
||||||
|
NoOp(Myvar is set to ${Myvar}, and firstarg is ${firstarg}, and secondarg is ${secondarg});
|
||||||
|
}
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
|
||||||
\subsection{Loops}
|
\subsection{Loops}
|
||||||
|
|
||||||
|
@@ -75,6 +75,7 @@ typedef enum {
|
|||||||
PV_EXTENSION, /* 25 */
|
PV_EXTENSION, /* 25 */
|
||||||
PV_IGNOREPAT, /* 26 */
|
PV_IGNOREPAT, /* 26 */
|
||||||
PV_GLOBALS, /* 27 */
|
PV_GLOBALS, /* 27 */
|
||||||
|
PV_LOCALVARDEC, /* you know, local var=val; */ /* 28 */
|
||||||
|
|
||||||
} pvaltype;
|
} pvaltype;
|
||||||
|
|
||||||
|
@@ -189,6 +189,7 @@ context { STORE_POS; return KW_CONTEXT;}
|
|||||||
abstract { STORE_POS; return KW_ABSTRACT;}
|
abstract { STORE_POS; return KW_ABSTRACT;}
|
||||||
macro { STORE_POS; return KW_MACRO;};
|
macro { STORE_POS; return KW_MACRO;};
|
||||||
globals { STORE_POS; return KW_GLOBALS;}
|
globals { STORE_POS; return KW_GLOBALS;}
|
||||||
|
local { STORE_POS; return KW_LOCAL;}
|
||||||
ignorepat { STORE_POS; return KW_IGNOREPAT;}
|
ignorepat { STORE_POS; return KW_IGNOREPAT;}
|
||||||
switch { STORE_POS; return KW_SWITCH;}
|
switch { STORE_POS; return KW_SWITCH;}
|
||||||
if { STORE_POS; return KW_IF;}
|
if { STORE_POS; return KW_IF;}
|
||||||
|
1474
pbx/ael/ael.tab.c
1474
pbx/ael/ael.tab.c
File diff suppressed because it is too large
Load Diff
@@ -67,7 +67,8 @@
|
|||||||
KW_SWITCHES = 293,
|
KW_SWITCHES = 293,
|
||||||
KW_ESWITCHES = 294,
|
KW_ESWITCHES = 294,
|
||||||
KW_INCLUDES = 295,
|
KW_INCLUDES = 295,
|
||||||
word = 296
|
KW_LOCAL = 296,
|
||||||
|
word = 297
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/* Tokens. */
|
/* Tokens. */
|
||||||
@@ -109,7 +110,8 @@
|
|||||||
#define KW_SWITCHES 293
|
#define KW_SWITCHES 293
|
||||||
#define KW_ESWITCHES 294
|
#define KW_ESWITCHES 294
|
||||||
#define KW_INCLUDES 295
|
#define KW_INCLUDES 295
|
||||||
#define word 296
|
#define KW_LOCAL 296
|
||||||
|
#define word 297
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -123,7 +125,7 @@ typedef union YYSTYPE
|
|||||||
struct pval *pval; /* full objects */
|
struct pval *pval; /* full objects */
|
||||||
}
|
}
|
||||||
/* Line 1536 of yacc.c. */
|
/* Line 1536 of yacc.c. */
|
||||||
#line 127 "ael.tab.h"
|
#line 129 "ael.tab.h"
|
||||||
YYSTYPE;
|
YYSTYPE;
|
||||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||||
# define YYSTYPE_IS_DECLARED 1
|
# define YYSTYPE_IS_DECLARED 1
|
||||||
|
@@ -83,7 +83,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
|||||||
%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
|
||||||
%token EXTENMARK KW_GOTO KW_JUMP KW_RETURN KW_BREAK KW_CONTINUE KW_REGEXTEN KW_HINT
|
%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_FOR KW_WHILE KW_CASE KW_PATTERN KW_DEFAULT KW_CATCH KW_SWITCHES KW_ESWITCHES
|
||||||
%token KW_INCLUDES
|
%token KW_INCLUDES KW_LOCAL
|
||||||
|
|
||||||
%right BAR COMMA
|
%right BAR COMMA
|
||||||
|
|
||||||
@@ -114,6 +114,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
|||||||
%type <pval>elements
|
%type <pval>elements
|
||||||
%type <pval>arglist
|
%type <pval>arglist
|
||||||
%type <pval>assignment
|
%type <pval>assignment
|
||||||
|
%type <pval>local_assignment
|
||||||
%type <pval>global_statements
|
%type <pval>global_statements
|
||||||
%type <pval>globals
|
%type <pval>globals
|
||||||
%type <pval>macro
|
%type <pval>macro
|
||||||
@@ -169,7 +170,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
|||||||
eval_arglist application_call application_call_head
|
eval_arglist application_call application_call_head
|
||||||
macro_call target jumptarget statement switch_statement
|
macro_call target jumptarget statement switch_statement
|
||||||
if_like_head statements extension
|
if_like_head statements extension
|
||||||
ignorepat element elements arglist assignment
|
ignorepat element elements arglist assignment local_assignment
|
||||||
global_statements globals macro context object objects
|
global_statements globals macro context object objects
|
||||||
opt_else
|
opt_else
|
||||||
timespec included_entry
|
timespec included_entry
|
||||||
@@ -242,6 +243,12 @@ assignment : word EQ { reset_semicount(parseio->scanner); } word SEMI {
|
|||||||
$$->u2.val = $4; }
|
$$->u2.val = $4; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
local_assignment : KW_LOCAL word EQ { reset_semicount(parseio->scanner); } word SEMI {
|
||||||
|
$$ = npval2(PV_LOCALVARDEC, &@1, &@6);
|
||||||
|
$$->u1.str = $2;
|
||||||
|
$$->u2.val = $5; }
|
||||||
|
;
|
||||||
|
|
||||||
/* XXX this matches missing arguments, is this desired ? */
|
/* XXX this matches missing arguments, is this desired ? */
|
||||||
arglist : /* empty */ { $$ = NULL; }
|
arglist : /* empty */ { $$ = NULL; }
|
||||||
| word { $$ = nword($1, &@1); }
|
| word { $$ = nword($1, &@1); }
|
||||||
@@ -260,6 +267,7 @@ element : extension {$$=$1;}
|
|||||||
| eswitches {$$=$1;}
|
| eswitches {$$=$1;}
|
||||||
| ignorepat {$$=$1;}
|
| ignorepat {$$=$1;}
|
||||||
| assignment {$$=$1;}
|
| assignment {$$=$1;}
|
||||||
|
| local_assignment {$$=$1;}
|
||||||
| word error {free($1); $$=0;}
|
| word error {free($1); $$=0;}
|
||||||
| SEMI {$$=0;/* allow older docs to be read */}
|
| SEMI {$$=0;/* allow older docs to be read */}
|
||||||
;
|
;
|
||||||
@@ -396,6 +404,7 @@ statement : LC statements RC {
|
|||||||
$$ = npval2(PV_STATEMENTBLOCK, &@1, &@3);
|
$$ = npval2(PV_STATEMENTBLOCK, &@1, &@3);
|
||||||
$$->u1.list = $2; set_dads($$,$2);}
|
$$->u1.list = $2; set_dads($$,$2);}
|
||||||
| assignment { $$ = $1; }
|
| assignment { $$ = $1; }
|
||||||
|
| local_assignment { $$ = $1; }
|
||||||
| KW_GOTO target SEMI {
|
| KW_GOTO target SEMI {
|
||||||
$$ = npval2(PV_GOTO, &@1, &@3);
|
$$ = npval2(PV_GOTO, &@1, &@3);
|
||||||
$$->u1.list = $2;}
|
$$->u1.list = $2;}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -315,6 +315,10 @@ static void print_pval(FILE *fin, pval *item, int depth)
|
|||||||
fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
|
fprintf(fin,"%s=%s;\n", item->u1.str, item->u2.val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PV_LOCALVARDEC:
|
||||||
|
fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
|
||||||
|
break;
|
||||||
|
|
||||||
case PV_GOTO:
|
case PV_GOTO:
|
||||||
fprintf(fin,"goto %s", item->u1.list->u1.str);
|
fprintf(fin,"goto %s", item->u1.list->u1.str);
|
||||||
if ( item->u1.list->next )
|
if ( item->u1.list->next )
|
||||||
@@ -565,6 +569,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PV_VARDEC:
|
case PV_VARDEC:
|
||||||
|
case PV_LOCALVARDEC:
|
||||||
/* fields: item->u1.str == variable name
|
/* fields: item->u1.str == variable name
|
||||||
item->u2.val == variable value to assign
|
item->u2.val == variable value to assign
|
||||||
*/
|
*/
|
||||||
@@ -2627,6 +2632,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PV_VARDEC:
|
case PV_VARDEC:
|
||||||
|
case PV_LOCALVARDEC:
|
||||||
/* fields: item->u1.str == variable name
|
/* fields: item->u1.str == variable name
|
||||||
item->u2.val == variable value to assign
|
item->u2.val == variable value to assign
|
||||||
*/
|
*/
|
||||||
@@ -3064,6 +3070,17 @@ static void gen_prios(struct ael_extension *exten, char *label, pval *statement,
|
|||||||
linkprio(exten, pr);
|
linkprio(exten, pr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PV_LOCALVARDEC:
|
||||||
|
pr = new_prio();
|
||||||
|
pr->type = AEL_APPCALL;
|
||||||
|
snprintf(buf1,sizeof(buf1),"LOCAL(%s)=$[%s]", p->u1.str, p->u2.val);
|
||||||
|
pr->app = strdup("Set");
|
||||||
|
remove_spaces_before_equals(buf1);
|
||||||
|
pr->appargs = strdup(buf1);
|
||||||
|
pr->origin = p;
|
||||||
|
linkprio(exten, pr);
|
||||||
|
break;
|
||||||
|
|
||||||
case PV_GOTO:
|
case PV_GOTO:
|
||||||
pr = new_prio();
|
pr = new_prio();
|
||||||
pr->type = AEL_APPCALL;
|
pr->type = AEL_APPCALL;
|
||||||
@@ -4335,6 +4352,7 @@ void destroy_pval_item(pval *item)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PV_VARDEC:
|
case PV_VARDEC:
|
||||||
|
case PV_LOCALVARDEC:
|
||||||
/* fields: item->u1.str == variable name
|
/* fields: item->u1.str == variable name
|
||||||
item->u2.val == variable value to assign
|
item->u2.val == variable value to assign
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user