This finishes the changes for making Macro args LOCAL to the call, and allowing users to declare local variables.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@70461 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
b3e46a45e6
commit
a5df6622bc
9
CHANGES
9
CHANGES
|
@ -162,7 +162,14 @@ Miscellaneous
|
|||
recursive call depths of 100,000 without problems.
|
||||
-- in addition to this, all apps that allowed a macro
|
||||
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
|
||||
on Linux. If configure is unable to find libcap then you
|
||||
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 goto
|
||||
\item jump
|
||||
\item local
|
||||
\item return
|
||||
\item break
|
||||
\item continue
|
||||
|
@ -368,6 +369,7 @@ First, some basic objects
|
|||
| <eswitches>
|
||||
| <ignorepat>
|
||||
| <word> '=' <collected-word> ';'
|
||||
| 'local' <word> '=' <collected-word> ';'
|
||||
| ';'
|
||||
|
||||
|
||||
|
@ -400,6 +402,7 @@ First, some basic objects
|
|||
|
||||
<statement> :== '{' <statements> '}'
|
||||
| <word> '=' <collected-word> ';'
|
||||
| 'local' <word> '=' <collected-word> ';'
|
||||
| 'goto' <target> ';'
|
||||
| 'jump' <jumptarget> ';'
|
||||
| <word> ':'
|
||||
|
@ -719,6 +722,49 @@ context blah {
|
|||
}
|
||||
\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}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ typedef enum {
|
|||
PV_EXTENSION, /* 25 */
|
||||
PV_IGNOREPAT, /* 26 */
|
||||
PV_GLOBALS, /* 27 */
|
||||
PV_LOCALVARDEC, /* you know, local var=val; */ /* 28 */
|
||||
|
||||
} pvaltype;
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ context { STORE_POS; return KW_CONTEXT;}
|
|||
abstract { STORE_POS; return KW_ABSTRACT;}
|
||||
macro { STORE_POS; return KW_MACRO;};
|
||||
globals { STORE_POS; return KW_GLOBALS;}
|
||||
local { STORE_POS; return KW_LOCAL;}
|
||||
ignorepat { STORE_POS; return KW_IGNOREPAT;}
|
||||
switch { STORE_POS; return KW_SWITCH;}
|
||||
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_ESWITCHES = 294,
|
||||
KW_INCLUDES = 295,
|
||||
word = 296
|
||||
KW_LOCAL = 296,
|
||||
word = 297
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
@ -109,7 +110,8 @@
|
|||
#define KW_SWITCHES 293
|
||||
#define KW_ESWITCHES 294
|
||||
#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 */
|
||||
}
|
||||
/* Line 1536 of yacc.c. */
|
||||
#line 127 "ael.tab.h"
|
||||
#line 129 "ael.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# 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 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
|
||||
%token KW_INCLUDES KW_LOCAL
|
||||
|
||||
%right BAR COMMA
|
||||
|
||||
|
@ -114,6 +114,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
|||
%type <pval>elements
|
||||
%type <pval>arglist
|
||||
%type <pval>assignment
|
||||
%type <pval>local_assignment
|
||||
%type <pval>global_statements
|
||||
%type <pval>globals
|
||||
%type <pval>macro
|
||||
|
@ -169,7 +170,7 @@ static pval *update_last(pval *, YYLTYPE *);
|
|||
eval_arglist application_call application_call_head
|
||||
macro_call target jumptarget statement switch_statement
|
||||
if_like_head statements extension
|
||||
ignorepat element elements arglist assignment
|
||||
ignorepat element elements arglist assignment local_assignment
|
||||
global_statements globals macro context object objects
|
||||
opt_else
|
||||
timespec included_entry
|
||||
|
@ -242,6 +243,12 @@ assignment : word EQ { reset_semicount(parseio->scanner); } word SEMI {
|
|||
$$->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 ? */
|
||||
arglist : /* empty */ { $$ = NULL; }
|
||||
| word { $$ = nword($1, &@1); }
|
||||
|
@ -260,6 +267,7 @@ element : extension {$$=$1;}
|
|||
| eswitches {$$=$1;}
|
||||
| ignorepat {$$=$1;}
|
||||
| assignment {$$=$1;}
|
||||
| local_assignment {$$=$1;}
|
||||
| word error {free($1); $$=0;}
|
||||
| SEMI {$$=0;/* allow older docs to be read */}
|
||||
;
|
||||
|
@ -396,6 +404,7 @@ statement : LC statements RC {
|
|||
$$ = npval2(PV_STATEMENTBLOCK, &@1, &@3);
|
||||
$$->u1.list = $2; set_dads($$,$2);}
|
||||
| assignment { $$ = $1; }
|
||||
| local_assignment { $$ = $1; }
|
||||
| KW_GOTO target SEMI {
|
||||
$$ = npval2(PV_GOTO, &@1, &@3);
|
||||
$$->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);
|
||||
break;
|
||||
|
||||
case PV_LOCALVARDEC:
|
||||
fprintf(fin,"local %s=%s;\n", item->u1.str, item->u2.val);
|
||||
break;
|
||||
|
||||
case PV_GOTO:
|
||||
fprintf(fin,"goto %s", item->u1.list->u1.str);
|
||||
if ( item->u1.list->next )
|
||||
|
@ -565,6 +569,7 @@ void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy f
|
|||
break;
|
||||
|
||||
case PV_VARDEC:
|
||||
case PV_LOCALVARDEC:
|
||||
/* fields: item->u1.str == variable name
|
||||
item->u2.val == variable value to assign
|
||||
*/
|
||||
|
@ -2627,6 +2632,7 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals)
|
|||
break;
|
||||
|
||||
case PV_VARDEC:
|
||||
case PV_LOCALVARDEC:
|
||||
/* fields: item->u1.str == variable name
|
||||
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);
|
||||
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:
|
||||
pr = new_prio();
|
||||
pr->type = AEL_APPCALL;
|
||||
|
@ -4335,6 +4352,7 @@ void destroy_pval_item(pval *item)
|
|||
break;
|
||||
|
||||
case PV_VARDEC:
|
||||
case PV_LOCALVARDEC:
|
||||
/* fields: item->u1.str == variable name
|
||||
item->u2.val == variable value to assign
|
||||
*/
|
||||
|
|
Reference in New Issue