asterisk ael2

Upload: fuyeus

Post on 06-Apr-2018

253 views

Category:

Documents


1 download

TRANSCRIPT

  • 8/3/2019 Asterisk AEL2

    1/39

    Asterisk AEL2

    Page Contents

    y Asterisk Extension Language v.2y AEL2 Announcements and Newsy The Asterisk Extension Language v.2

    o Asterisk in a Nutshello Getting Startedo Reloading extensions.ael2o Debuggingo AELPARSEo General Notes about Syntaxo Keywordso Applicationso Commentso Extensionso Includeso #includeo Dialplan Switcheso Ignorepato Variableso Loopso Conditionalso Break, Continue, and Returno goto, jump, and labelso M

    acroso Exampleso Semantic Checkso Differences with the original version of AELo Hints and Bugso The Full Power of AEL and AEL2o Exampleso AEL2 BNFo AEL2 Bug Report Historyo AEL2 Enhancement Request History

    Asterisk Extension Language v.2AEL v.2 is intended to provide an actual programming language that can be used to write anAsterisk dialplan. Itfurther extends AEL, and provides more flexible syntax, better error messages, and some missingfunctionality.AEL v.2 is a new version of the AEL compiler, written by Steve Murphy. It was originally

  • 8/3/2019 Asterisk AEL2

    2/39

    introduced as a large asterisk patch in the Asterisk bug database. See: Bug 6021.

    AEL is really the merger of 4 different 'languages', or syntaxes:

    y The first and most obvious is the AEL v.2 syntax itself. A BNF is provided near the endof t

    his document.

    y The second syntax is the Expression Syntax, which is normally handled by Asteriskextension engine, as expressions enclosed in $[...]. The right hand side of assignments arewrapped in $[ ... ] by AEL, and so are the if and while expressions, among others.

    y The third syntax is the Variable Reference Syntax, the stuff enclosed in ${..} curlybraces. It's a bit more involved than just putting a variable name in there. You can includeone of dozens of 'functions', and their arguments, and there are even some stringmanipulation notation in there.

    y The last syntax that underlies AEL/AEL2, and is not used directly in AEL/AEL2, is theExtension Language Syntax. The extension language is what you see inextensions.conf, and AEL2 compiles the higher level AEL2 language into extensions and

    priorities, and passes them via function calls into Asterisk. Embedded in t

    his language isthe Application/AGI commands, of which one application call per step, or priority can be

    made. You can think of this as a "macro assembler" language, that AEL2 will compileinto.

    Any programmer of AEL should be familiar with it's syntax, of course, as well as the Expressionsyntax, and the Variable syntax. There are references to Wiki pages covering these, down in the"The Power of AEL" section below.

    AEL2 Announcements and News

    NEW: For 1.2 users who'd like to have access to AEL2, I've got a better idea. The old way wasto "svn diffhttp://svn.digium.com/svn/asterisk/branches/1.2http://svn.digium.com/svn/asterisk/team/murf/AEL2-1.2 > AEL.patch", and then apply the patchto your current 1.2 based source with "patch -p0 < AEL.patch"; this is a bit of a hassle, as thatbranch is brought back into sync with 1.2 on a weekly or monthly basis. An easier approachwould be to:

    svn co http://svn.digium.com/svn/asterisk/team/murf/AEL2-1.2/patches

    And then, in the 1.2 source directory, you can simply:

    patch -p0 < patches/diffs.AEL2.patch

  • 8/3/2019 Asterisk AEL2

    3/39

    which will apply the changes.

    Good news for all you AEL2 fans out there! A couple of weeks ago, I dropped a bug in Murf'sear about adding an option to dump the parsed AEL code into a file, basically a "compile"option. Well, he coded it, we've both tested it, and it seems solid, so it's now in the trunk! just use

    aelparse as usual and add the -w option if you want to dump t

    he file extensions.conf.aeldump.

    Handy for coding in AEL2 but still being able to easily deliver to clients who aren't able orwilling to use AEL2 in their Asterisk implementation! -Rushowr

    AEL2 has replaced AEL in the trunkversion of Asterisk. You now get it automatically whenyou svn checkout asterisk! It's upward compatible with the original AEL, but adds severalfeatures, and removes some limitations.

    y Please note that AEL (See Asterisk AEL ) is stepping out of the "Experimental" stage.Please help us to make it solid and useful by using it!!

    The Asterisk Extension Language v.2

    Asterisk in a Nutshell

    Asterisk acts as a server. Devices involved in telephony, like Zapata cards, orVoip phones, allindicate some context that should be activated in their behalf. See the config file formats forIAX, SIP, zapata.conf, etc. They all help describe a device, and they all specify a context to

    activate when somebody picks up a phone, or a call comes in from the phone company, or a voipphone, etc.

    ContextsContexts are a grouping of extensions.

    Contexts can also include other contexts. Think of it as a sort of merge operation at runtime,whereby the included context's extensions are added to the contexts making the inclusion.

    Extensions and prioritiesA Context contains zero or more Extensions. There are several predefined extensions. The "s"

    extension is the "start" extension, and when a device activates a context the "s" extension is theone that is going to be run. Other extensions are the timeout "t" extension, the invalid response,or "i" extension, and there's a "fax" extension. For instance, a normal call will activate the "s"extension, but an incoming FAX call will come into the "fax" extension, if it exists. (BTW,asterisk can tell it's a fax call by the little "beep" that the calling fax machine emits every somany seconds.).

    Extensions contain several priorities, which are individual instructions to perform. Some are as

  • 8/3/2019 Asterisk AEL2

    4/39

    simple as setting a variable to a value. Others are as complex as initiating the Voicemailapplication, for instance. Priorities are executed in order.

    When the 's" extension completes, asterisk waits until the timeout for a response. If the responsematches an extension's pattern in the context, then control is transferred to that extension.

    Usually the responses are tones emitted w

    hen a user presses a button on t

    heir p

    hone. Forinstance, a context associated with a desk phone might not have any "s" extension. It just plays a

    dialtone until someone starts hitting numbers on the keypad, gather the number, find a matchingextension, and begin executing it. That extension might Dial out over a connected telephone linefor the user, and then connect the two lines together.

    The extensions can also contain "goto" or "jump" commands to skip to extensions in othercontexts. Conditionals provide the ability to react to different stimiuli, and there you have it.

    Macros

    Think of a macro as a combination of a context wit

    hone nameless extension, and a subroutine.

    Ithas arguments like a subroutine might. A macro call can be made within an extension, and the

    individual statements in the macro are executed until a return statement is executed. At thispoint, execution returns to the next statement after the macro call.Macros can call other macros.And they work just like function calls.

    ApplicationsApplication calls, like "Dial()", or "Hangup()", or "Answer()", are available for users to use toaccomplish the work of the dialplan. There are over 145 of them at the moment this was written,and the list grows as new needs and wants are uncovered. Some applications do fairly simplethings, some provide amazingly complex services.

    Hopefully, the above objects will allow you do anything you need to in the Asteriskenvironment!

    Getting Started

    In the following discussion, if you are using the "trunk" version of Asterisk, please note

    that AEL2 replaced the original AEL implementation.

    So, anywhere in the following discussion where "ael2" or "AEL2" is mentioned, you woulduse "ael" or "AEL" instead. For instance, in thediscussion below, you could type in the command "ael2 reload" if you are using Asterisk

    version 1.2.x; but on "trunk" versions of asterisk, you would use "ael reload".

    However, for those installing AEL2 into 1.2 versions of Asterisk, should note that 'ael2' and'AEL2' should be used as-is.

  • 8/3/2019 Asterisk AEL2

    5/39

    The AEL2 parser (pbx_ael2.so) is completely separate from the module that parsesextensions.conf (pbx_config.so). To use AEL2, the only thing that has to be done is the modulepbx_ael2.so must be loaded by Asterisk. This will be done automatically if using 'autoload=yes'in /etc/asterisk/modules.conf. When the module is loaded, it will look for 'extensions.ael2' in/etc/asterisk/. extensions.conf and extensions.ael and extensions.ael2 can be used in conjunction

    with

    each

    other if t

    hat is w

    hat is desired. Some users may want to keep extensions.conf for t

    hefeatures that are configured in the 'general' section of extensions.conf.

    Reloading extensions.ael2

    To reload extensions.ael2, the following command can be issued at the CLI.

    y CLI> ael2 reload

    Debugging

    Right at this moment, the following commands are available, but do nothing:

    Enable AEL2 contexts debug

    y CLI> ael2 debug contexts

    Enable AEL2 macros debug

    y CLI> ael2 debug macros

    Enable AEL2 read debug

    y CLI> ael2 debug read

    Enable AEL2 tokens debug

    y CLI> ael2 debug tokens

    Disable AEL2 debug messages

  • 8/3/2019 Asterisk AEL2

    6/39

    y CLI> ael2 no debug

    If things are going wrong in your dialplan, you can use the following facilities to debug your file:

    1. Th

    e messages log in /var/log/asterisk (from the c

    hecks done at load time).2. The "dialplan show" command in asterisk

    3. The standalone executable, "aelparse" built in the utils/ dir in the source.

    You can also use the "aelparse" program to check your extensions.ael2 file before feeding it toasterisk. Wouldn't it be nice to eliminate most errors before giving the file to asterisk?

    AELPARSE

    You should never place code in /etc/extensions.ael without first testing it with aelparse!!

    The aelparse program is built in the utils/ directory of the asterisk source. It is a standaloneexecutable, and accepts only the options -d, -w, -q, and -n.

    y -d: Using this option says, instead of reading the file "extensions.ael2" (in the trunkversion, that would be "extensions.ael") from /etc/asterisk (or wherever the config filesare normally kept) aelparse will instead look in the current directory. This is very useful

    for testing your dialplan somewhere other than your production directory.y -w: Convert the input dialplan file (extensions.ael2) to extensions.conf format, and dump

    the file in the current directory under the file name "extensions.conf.aeldump". Why onearth would you ever want to do this? Well, you could take that file and use it on 1.2 orearlier asterisk systems! You don't have to program dialplans in extensions.conf formatany more!

    y -n: Don't display the function calls to build the extensions in asterisk.y -q: (implies -n). Pretty much, only show warnings and errors.

    General Notes about Syntax

    Note that the syntax and style are a little more free-form. The opening '{' (curly-braces) do nothave to be on the same line as the keyword that precedes them. Statements can be split across

  • 8/3/2019 Asterisk AEL2

    7/39

    lines, as long as tokens are not broken by doing so. More than one statement can be included ona single line. Whatever you think is best!

    You can just as easily say,

    if(${x}=1){NoOp(hello!);goto s|3;}else{NoOp(

    Goodbye!);goto s|12;}

    as you can say:

    if(${x}=1){NoOp(hello!);goto s|3;}else{

    NoOp(G

    oodbye!);goto s|12;}

    or:

    if (${x}=1){NoOp(hello!);goto s|3;} else {NoOp(Goodbye!);goto s|12;}

    or:

    if (${x}=1) {NoOp(hello!); goto s|3;} else {NoOp(Goodbye!); goto s|12;}

    or even:

    if(${x}=1){NoOp(hello!);goto s|3;}

  • 8/3/2019 Asterisk AEL2

    8/39

    else{NoOp(Goodbye!);goto s|12;}

    Keywords

    The AEL keywords are case-sensitive. If an application name and a keyword overlap, there isprobably a good reason, and you should consider replacing the application call with an AEL2statement. If you do not wish to do so, you can still use the application, by using a capitalizedletter somewhere in its name. In the Asterisk extension language, application names are not case-sensitive.

    The following are keywords in the AEL2 language:

    y abstracty contexty macroy globalsy ignorepaty switchy ify ifTimey elsey randomy gotoy jumpy returny breaky continuey regexteny hinty fory whiley casey patterny default NOTE: the "default" keyword can be used as a context name, for those who

    would like to do so.y catchy switchesy eswitchesy includes

  • 8/3/2019 Asterisk AEL2

    9/39

    Applications

    The file /var/lib/asterisk/applist contains entries for over 140 applications, including arguments,the names of variables the application can or will set, the options, and the list of arguments,optional and required. If you use an application that is not in the list, you can simply add one,following the syntax of other entries.

    Don't fall in love with the specs in the applist file. The format of the file, the entries themselveswill change in time.

    CommentsComments begin with // and end with the end of the line. Comments are removed by the lexicalscanner, and will not be recognized in places where it is busy gathering expressions to wrap in $,or inside application call argument lists. The safest place to put comments is after terminatingsemicolons, or on otherwise empty lines.

    NEW! You can use C-style comments that begin with '/*' and end with '*/' in AEL files. Thesecomments can span lines, if so desired!Example:/* this is a

    multiline comment th

    atmakes little or no sense!*/

    Extensions

    To specify an extension in a context, the following syntax is used. If more than one application isbe called in an extension, they can be listed in order inside of a block.

    context default {1234 => Playback(tt-monkeys);8000 => {NoOp(one);NoOp(two);NoOp(three);};

  • 8/3/2019 Asterisk AEL2

    10/39

    _5XXX => NoOp(it's a pattern!);}

    Two optional items have been added to the AEL2 syntax, that allow the specification ofhints,

    and a keyword, regexten, that will force t

    he numbering of priorities to start at 2.

    context default {regexten _5XXX => NoOp(it's a pattern!);}

    context default {hint(Sip/1) _5XXX => NoOp(it's a pattern!);}

    context default {regexten hint(Sip/1) _5XXX => NoOp(it's a pattern!);}

    The regexten must come before the hint if they are both present.

    NEW: You can add the callerID to the extension name for matching by adding a slash (/)followed by the CallerID to match after the extension name.

    context zoombo {819/7079953345 => { NoOp(hello, 3345); }}

    In the above, the 819/7079953345 extension will only be matched if the CallerID is 7079953345,and the dialed number is 819. Hopefully you have another 819 extension defined for all thosewho wish 819, that are not so lucky as to have 7079953345 as theirCallerID!

    Includes

    Contexts can be included in other contexts. All included contexts are listed wit

    hin a single block.

    context default {includes {local;longdistance;international;

  • 8/3/2019 Asterisk AEL2

    11/39

    }}

    Time-limited inclusions can be specified, as in extensions.conf format, with the fields

    described in the wiki page Asterisk cmd

    Goto

    IfT

    ime.

    context default {includes {local;longdistance|16:00-23:59|mon-fri|*|*;international;}}

    #include

    You can include other files with the #include "filepath" construct.

    1. include "/etc/asterisk/testfor.ael2"

    An interesting property of the #include, is that you can use it almost anywhere in the .ael2 file. Itis possible to include the contents of a file in a macro, context, or even extension. The #includedoes not have to occur at the beginning of a line. Included files can include other files, up to 50levels deep. If the path provided in quotes is a relative path, the parser looks in the config filedirectory for the file (usually /etc/asterisk).

    NEW in 1.4 and trunk versions! You can use 'globbing' patterns (as in UNIX shell commands) toinclude multiple files with a single #include directive:

    1. include "t2/*.ael"2. include "t3/x[1-5]*"3. include "t4/abc?.ael"4. include "t5/{t1,t2,t3}.ael"

  • 8/3/2019 Asterisk AEL2

    12/39

    will include all the files that end with ".ael" in the t2 directory; all files in t3 that begin with x1,x2, x3, x4, or x5; and t4/abc.ael, and any other file in t4 that starts with abc, ends with ".ael", andhas one other character in between; and t1.ael, t2.ael, and t3.ael in the t5 directory.

    Dialplan Switches

    Switches are listed in their own block within a context. For clues as to what these are used for,see Asterisk - dual servers, and Asterisk config extensions.conf.

    context default {switches {

    DUNDi/e164;IAX2/box5;};eswitches {IAX2/context@${CURSERVER};}}

    Ignorepat

    ignorepat can be used to instruct channel drivers to not cancel dial tone upon receipt of aparticular pattern. The most commonly used example is '9'.

    context outgoing {ignorepat => 9;}

    Variables

    Variables in Asterisk do not have a type, so to define a variable, it just has to be specified with avalue. Global variables are set in their own block.

  • 8/3/2019 Asterisk AEL2

    13/39

    globals {CONSOLE=Console/dsp;TRUNK=Zap/g2;}

    Variables can be set within extensions as well.

    context foo {555 => {x=5;y=blah;divexample=10/2NoOp(x is ${x} and y is ${y} !);}}

    NOTE: AEL wraps the right hand side of an assignment with $[ ] to allow expressions to beused If this is unwanted, you can protect the right hand side from being wrapped by using theSet() application. Read the README.variables about the requirements and behavior of $[ ]expressions.

    NOTE:These things are wrapped up in a $[ ] expression: The while() test; the if() test; themiddle expression in the for( x; y; z) statement (the y expression); Assignments the right handside, so a = b -> Set(a=$[b])

    Writing to a dialplan function is treated the same as writing to a variable.

    context blah {s => {CALLERID(name)=ChickenMan;NoOp(My name is ${CALLERID(name)} !);}}

    Loops

    AEL has implementations of 'for' and 'while' loops.

  • 8/3/2019 Asterisk AEL2

    14/39

    context loops {1 => {for (x=0; ${x} < 3; x=${x} + 1) {Verbose(x is ${x} !);

    }}2 => {y=10;while (${y} >= 0) {

    Verbose(y is ${y} !);y=${y}-1;}}}

    NOTE:The conditional expression (the "${y} >= 0" above) is wrapped in $[ ] so it can beevaluated.NOTE:The for loop test expression (the "${x} < 3" above) is wrapped in $[ ] so it can beevaluated.NOTE:In for loops, both the init and increment expressions are embedded in a Set() call if an '='is found anywhere in the expression. Otherwise, they are treated as app calls.

    Conditionals

    AEL2 supports ifand switch statements, like AEL, but adds ifTime, and random. Unlike theoriginal AEL, though, you do NOT need to put curly braces arounda single statement in the "true" branch of an if(), the random(), or an ifTime() statement. Theif(), ifTime(), and random() statements allow optionalelse clause.

    context conditional {_8XXX => {Dial(SIP/${EXTEN});

    if ("${DIALSTATUS}" = "BUSY"){NoOp(yessir);Voicemail(${EXTEN}|b);}elseVoicemail(${EXTEN}|u);ifTime (14:00-25:00|sat-sun|*|*)

  • 8/3/2019 Asterisk AEL2

    15/39

    Voicemail(${EXTEN}|b);else{Voicemail(${EXTEN}|u);NoOp(hi, there!);

    }random(51) NoOp(This should appear 51% of the time);

    random( 60 ){NoOp( This should appear 60% of the time );}else{random(75){

    NoOp(Th

    is should appear 30% of t

    he time! );}

    else{NoOp( This should appear 10% of the time! );}}}_777X => {switch (${EXTEN}) {case 7771:NoOp(You called 7771!);break;case 7772:NoOp(You called 7772!);break;case 7773:NoOp(You called 7773!);// fall thru-pattern 777[4-9]:NoOp(You called 777 something!);default:NoOp(In the default clause!);}}}

    NOTE:The conditional expression in if() statements (the "${DIALSTATUS}" = "BUSY"above) is wrapped by the compiler in $[ ] for evaluation.

  • 8/3/2019 Asterisk AEL2

    16/39

    NOTE: Neither the switch nor case values are wrapped in $[ ]; they can be constants, or ${var}type references only.NOTE: AEL2 generates each case as a separate extension. case clauses with no terminating'break', or 'goto', have a goto inserted, to the next clause, which creates a 'fall thru' effect.NOTE: AEL2 introduces the ifTime keyword/statement, which works just like the if() statement,

    but the expression is a time value, exactly like t

    hat used by t

    he application

    Goto

    IfT

    ime(). SeeAsterisk cmd GotoIfTimeNOTE:The pattern statement makes sure the new extension that is created has an '_' preceding itto make sure asterisk recognizes the extension name as a pattern.NOTE: Every character enclosed by the switch expression's parenthesis are included verbatim inthe labels generated. So watch out for spaces!NOTE: Previous to version 0.13, the random statement used the "Random()" application, whichhas been deprecated. It now uses the RAND() function instead, in the GotoIfapplication.NOTE: NEW: if the expression in the switch(expr) is null, this will end up in the default case, ifit is specified. If there is no matching case, in a switch statement, the dialplan will most likelyterminate with a hangup.

    Break, Continue, and Return

    Three keywords, break, continue, and return, are included in the syntax to provide flow ofcontrol to loops, and switches.

    The break can be used in switches and loops, to jump to the end of the loop or switch.

    The continue can be used in loops (while and for) to immediately jump to the end of the loop. Inthe case of a for loop, the increment and test will then be performed. In the case of the whileloop, the continue will jump to the test at the top of the loop.

    Examples:

    context loops {1 => {for (x=0; ${x} < 3; x=${x} + 1) {

    Verbose(x is ${x} !);if( ${x} == 2 && ${y} == 17)break;if(${x} == 2 && ${y} == 16)continue; /*keep going */}}2 => {

  • 8/3/2019 Asterisk AEL2

    17/39

    y=10;while (${y} >= 0) {Verbose(y is ${y} !);if (${z} {begin:NoOp(Infinite Loop! yay!);Wait(1);goto begin; // go to label in same extension}3 => {goto s|begin; // go to label in different extension

    }4 => {goto gotoexample|s|begin; // overkill go to label in same context

    }}

  • 8/3/2019 Asterisk AEL2

    18/39

    context gotoexample2 {s => {end:goto gotoexample|s|begin; // go to label in different context}

    }

    You can use the special label of "1" in the goto and jump statements. It means the "first"statement in the extension. I would not advise trying to use numeric labels other than "1" ingoto's or jumps, nor would I advise declaring a "1" label anywhere! As a matter of fact, it wouldbe bad form to declare a numeric label, and it might conflict with the priority numbers usedinternally by asterisk.

    The syntax of the jump statement is: jump extension[,priority][@context] If priority is absent, itdefaults to "1". If context is not present, it is assumed to be the same as that which contains the"jump".

    context jumpexample {s => {begin:NoOp(Infinite Loop! yay!);Wait(1);jump s; // go to first priority in same extension}3 => {jump s,begin; // go to the begin label in different extension}4 => {jump s,begin@jumpexample; // overkill go to label in same context}5 => {jump 4@jumpexample; // jump to first prio in extension 4;}}

    context jumpexample2 {s => {end:

    jump s@jumpexample; // go to the s extension in different context}}

    NOTE: goto labels follow the same requirements as the Goto() application, except the last valuehas to be a label. If the label does not exist, you will have run-time errors. If the label exists, butin a different extension, you have to specify both the extension name and label in the goto, as in:goto s|z; if the label is in a different context, you specify context|extension|label. There is a note

  • 8/3/2019 Asterisk AEL2

    19/39

    about using goto's in a switch statement below...NOTE AEL2 introduces the special label "1", which is the beginning context number for mostextensions.NOTE: NEW: As of 30 Mar2006, goto syntax now accepts commas in the place of vertical bars.You must either use vertical bars as separators, or commas. You cannot mix them. Thus, either

    "goto gotoexample|s|begin" or "goto gotoexample,s,begin", but NOT

    "goto gotoexample,s|begin"

    Macros

    A macro is defined in its own block like this. The arguments to the macro are specified with thename of the macro. They are then referred to by that same name. A catch block can be specifiedto catch special extensions.

    Alittle more about 'catch'. A macro is converted to a regular context, and all its code normally

    goes into the 's' extension.

    Defining a catch allows you to define other extensions in the macro context. For example, youcan define the 'h' extensionforhangups, and 'i' for invalid input, etc. To 'catch' events that might happen during theexecution of a macro.

    macro std-exten( ext , dev ) {Dial(${dev}/${ext},20);switch(${DIALSTATUS}) {

    case BUSY:Voicemail(b${ext});break;default:Voicemail(u${ext});

    }

    catch a {VoiceMailMain(${ext});return;

    }}

    A macro is then called by preceding the macro name with an ampersand. Empty arguments canbe passed simply with nothing between comments (0.11).

  • 8/3/2019 Asterisk AEL2

    20/39

    context example {_5XXX => &std-exten(${EXTEN}, "IAX2");_6XXX => &std-exten(, "IAX2");_7XXX => &std-exten(${EXTEN},);

    _8XXX => &std-exten(,);}

    NOTE: Until release 1.4 was forked, and in 1.4 and previous, AEL2 used the Macro()application to implement this construct in the dialplan. Macros have a serious limitation, in thatone cannot recursively nest macro calls deeper than 7 levels, due to limitations on thread stackallocation sizes. To get around this limitation, from the time 1.4 is/was forked from trunk, theAEL2 compiler will implement macros withGosub() application calls, which pose no such limitson call depth. The new methodology will be available on trunk and releases 1.6 and above.

    Examples

    context demo {s => {Wait(1);Answer();TIMEOUT(digit)=5;

    TIMEOUT(response)=10;restart:Background(demo-congrats);instructions:for (x=0; ${x} < 3; x=${x} + 1) {Background(demo-instruct);WaitExten();}}2 => {Background(demo-moreinfo);

    goto s|instructions;}3 => {LANGUAGE()=fr;goto s|restart;}

    500 => {

  • 8/3/2019 Asterisk AEL2

    21/39

    Playback(demo-abouttotry);Dial(IAX2/[email protected]);Playback(demo-nogo);goto s|instructions;}

    600 => {Playback(demo-echotest);Echo();Playback(demo-echodone);goto s|instructions;}

    1. => {hangup:Playback(demo-thanks);H

    angup();}t => goto #|hangup;i => Playback(invalid);}

    Semantic Checks

    AEL2, after parsing, but before compiling, traverses the dialplan tree, and makes several checks:

    y (if the application argument analyzer is working: the presence of the 'j' option is reportedas error.

    y if options are specified, that are not available in an application.y if you specify too many arguments to an application.y a required argument is not present in an application call.y Switch-case using "known" variables that applications set, that does not cover all the

    possible values. (a "default" case will solve this problem. Each "unhandled" value islisted.

    y a Switch construct is used, which is uses a known variable, and the application that wouldset that variable is not called in the same extension. This is a warning only...

    y Macro calls to non-existent macros.y Macro calls to contexts.y Macro calls with argument count not matching the definition.y application call to macro.

  • 8/3/2019 Asterisk AEL2

    22/39

    y application calls to "GotoIf", "GotoIfTime", "while", "endwhile", "Random", and"execIf", will generate a message to consider converting the call to AEL goto, while, etc.constructs.

    y Calls to applications not in the "applist" database (installed in /var/lib/asterisk/applist" onmost systems).

    ygoto a label in an empty extension.

    y goto a non-existent label, either a within-extension, within-context, or in a differentcontext, or in any included contexts. Will even check "sister" context references.

    y All the checks done on the time values in the dial plan, are done on the time values in theifTime() and includes times:

    o the time range has to have two times separated by a dash;o the times have to be in range of 0 to 24 hours.o The weekdays have to match the internal list, if they are provided;o the day of the month, if provided, must be in range of 1 to 31;o the month name or names have to match those in the internal list.

    y In an assignment statement, if the assignment is to a function, the function name used ischecked to see if it one of t

    he currently known functions. A warning is issued if it is not.

    y (0.5) If an expression is wrapped in $[ ... ], and the compiler will wrap it again, a warningis issued.

    y (0.5) If an expression had operators (you know, +,-,*,/,%,!,etc), but no ${ } variables, awarning is issued. Maybe someone forgot to wrap a variable name?

    y (0.12) check for duplicate context names.y (0.12) check for abstract contexts that are not included by any context.y (0.13) Issue a warning if a label is a numeric value.y (New) Make sure that labels are unique within extensions/macros.y (New) Issue hard error if a break is not in a loop or switch case.y (New) Issue hard error if a continue is not in a loop.y Empty extensions will issue a warning.y In release 1.6, labels outside of extensions orMacros will generate an error.y In release 1.6, return statements will only be allowed in macro definitions.y In release 1.6, a warning is generated if a macro definition does not contain a return

    statement at the end of its contents. One is automatically inserted.y In release 1.6, a warning is generated if a goto is located in a macro, and the target is

    outside the macro.y In release 1.6, a warning is issued, if a context referenced in 'includes' can't be found.

    Differences with the original version of AEL

    1. It reads in "/etc/asterisk/extensions.ael2", instead of extensions.ael (extensions.ael in thetrunk version) (Only in the 1.2 patch)

    2. It is more free-form. The newline character means very little, and is pulled out of thewhite-space only for line numbers in error messages.

  • 8/3/2019 Asterisk AEL2

    23/39

    3. It generates more error messages by this I mean that any difference between the inputand the grammar are reported, by file, line number, and column.

    4. It checks the contents of $[ ] expressions (or what will end up being $[ ] expressions!) forsyntax errors. It also does matching paren/bracket counts.

    5. It runs several semantic checks after the parsing is over, but before the compiling begins,see t

    he list above.6. It handles #include "filepath" directives. ALMOST anywhere, in fact. You could

    easily include a file in a context, in an extension, or at the root level. Files can beincluded in files that are included in files, down to 50 levels ofhierarchy...

    7. LocalGoto's inside Switch statements automatically have the extension of the location ofthe switch statement appended to them.

    8. A pretty printer function is available within pbx_ael2.so.9. In the utils directory, two standalone programs are supplied for debugging AEL files.

    One is called "aelparse", and it reads in the /etc/asterisk/extensions.ael2 file, and showsthe results of syntax and semantic checking on stdout, and also shows the results ofcompilation to stdout. The other is "aelparse1", which uses the original ael compiler to do

    the same work, reading in "/etc/asterisk/extensions.ael", using t

    he original 'pbx_ael.so'instead.

    10.AEL2 supports the "jump" statement, and the "pattern" statement in switch constructs.Hopefully these will be documented in the AEL README.

    11.Added the "return" keyword, which will jump to the end of an extension/Macro.12.Added the ifTime (||| ) {} [else

    {}] construct, which executes much like an if () statement, but the decision is based onthe current time, and the time spec provided in the ifTime. See the example above. (Note:all the other time-dependent Applications can be used via ifTime)

    13.Added the optional time spec to the contexts in the includes construct. See examplesabove.

    14.You don't have to wrap a single "true" statement in curly braces, as in the orignal AEL.An "else" is attached to the closest if. As usual, be careful about nested if statements!When in doubt, use curlies!

    15.Added the syntax [regexten] [hint(channel)] to preceed an extension declaration. Seeexamples above, under "Extension". The regexten keyword will cause the priorities in theextension to begin with 2 instead of 1. The hint keyword will cause its arguments to beinserted in the extension under the hint priority. They are both optional, of course, but theorder is fixed at the moment-- the regexten must come before the hint, if they are bothpresent.

    16.Empty case/default/pattern statements will "fall thru" as expected. (0.6)17.A trailing label in an extension, will automatically have a NoOp() added, to make sure

    the label exists in the extension on Asterisk. (0.6)18.(0.9) the semicolon is no longer required after a closing brace! (i.e. "];" ===> "}". You

    can have them there if you like, but they are not necessary. Someday they may berejected as a syntax error, maybe.

    19.(0.9) the // comments are not recognized and removed in the spots where expressions aregathered, nor in application call arguments. You may have to move a comment if you geterrors in existing files.

  • 8/3/2019 Asterisk AEL2

    24/39

    20.(0.10) the random statement has been added. Syntax: random ( ) [ else ]. The probability of the lucky-statement gettingexecuted is , which should evaluate to an integer between 0 and 100. If the isn't so lucky this time around, then the getsexecuted, if it is present.

    21.Th

    e $[...] expressionshave been en

    hanced to inlcude t

    he ==, ||, and && operators.

    Theseoperators are exactly equivalent to the =, |, and & operators, respectively. Why? So the C,

    Java, and C++ hackers feel at home here.

    Hints and Bugs

    ''Note: Ihope that this section will end up just being "hints" by the time it is included!

    y The safest way to check for a null strings is to say $[ "${x}" = "" ] The old way would doas shell scripts often do (but shouldn't, as that will yield the same problems as here), andappend something on both sides, like this: $[ ${x}foo = foo ]. The trouble with the oldway, is that, if x contains any spaces, then problems occur, usually syntax errors. It isbetter practice and safer to wrap all such tests with double quotes! Also, there are nowsome functions that can be used in a variable referenece, ISNULL(), and LEN(), that canbe used to test for an empty string: ${ISNULL(${x})} or $[ ${LEN(${x})} = 0 ].

    y Assignment vs. Set(). Keep in mind that setting a variable to value can be done twodifferent ways. If you choose say 'x=y;', keep in mind that AEL2 will wrap the right-hand-side with $[]. So, when compiled into extension language format, the end result willbe 'Set(x=$[y])'. If you don't want this effect, then say "Set(x=y);" instead.

    y Macro recursion depth. For large dialplans, or any other application that requires macroscalling macros calling macros to 7 or more levels deep, keep in mind that there is a limitas to how deeply you can nest macro calls. That limit is 7 levels. This shortcoming in theMacro() app is not limited to usage by AEL. In general, the Macro() application has thislimitation whether used by AEL, or just called straight from extensions.conf. Thealternative is to use the Gosub application instead. One shortcoming ofGosub in releases1.4 and previous, is that it did not accept any arguments. An enhancement to the Gosub()application will allow arguments to be passed and kept on a stack. This enhancement willbe available in release 1.6, and is fundamental to AEL being able to use Gosub instead ofMacro in generated dialplan code.

    y Spaces in Set(). You can get the most unexpected and interesting errors if you put spacesin your Set() arguments. "Set( a = 1)" is not equivalent to "Set(a=1)". The variable namein the first case is " a ", and includes the spaces before and after. You will have to insurethat those spaces are present every time that variable is referenced. This is bad form!

  • 8/3/2019 Asterisk AEL2

    25/39

    The Full Power of AEL and AEL2

    A newcomer to Asterisk will look at the above constructs and descriptions, and ask, "Where's thestring manipulation functions?", "Where's all the cool operators that other languages have tooffer?", etc.

    The answer is that the rich capabilities of Asterisk are made available through AEL, via:

    y Applications: See Asterisk - documentation of application commandsy Functions: Functions were implemented inside ${ .. } variable references, and supply

    many useful capabilities. See Asterisk Functionsy Expressions: An expression evaluation engine handles items wrapped inside $[...]. This

    includes some string manipulation facilities, arithmetic expressions, etc. See AsteriskExpressions.

    y Application Gateway Interface: Asterisk can fork external processes that communicatevia pipe. AGI applications can be written in any language. Very powerful applications

    can be added this way. See Asterisk AGI.y Variables: Channels of communication have variables associated with them, and asterisk

    provides some global variables. These can be manipulated and/or consulted by the abovemechanisms. See AsteriskVariables.

    Examples

    Here you can find some examples on

    how to use AEL/AEL2 to create powerful dialplans: AELExample Snippets.

    AEL2 BNF

    First, some basic objects:

    a lexical token consisting of characters matching this pattern: [-a-zA-Z0-9"_/.\\*\+!$#\\][-a-zA-Z0-9"_/.!\*\+\\{\}$#\\]*

    a concatenation of up to 3 s.

    all characters encountered until the character that follows the in the grammar.

  • 8/3/2019 Asterisk AEL2

    26/39

    :==

    :==

    |

    :== | | | ';'

    :== 'context' '{' '}'| 'context' '{' '}'

    | 'context' 'default' '{' '}'| 'context' 'default' '{' '}'| 'abstract' 'context' '{' '}'| 'abstract' 'context' '{' '}'| 'abstract' 'context' 'default' '{' '}'| 'abstract' 'context' 'default' '{' '}'

    :== 'macro' '(' ')' '{' '}'| 'macro' '(' ')' '{' '}'| 'macro' '(' ')' '{' '}'| 'macro' '(' ')' '{' '}'

    :== 'globals' '{' '}'| 'globals' '{' '}'

    :== |

    :== '=' ';'

    :== | ','

    :==

  • 8/3/2019 Asterisk AEL2

    27/39

    |

    :== |

    | |

    | | '=' ';'| ';'

    :== 'ignorepat' '=>' ';'

    :== '=>'

    | 'regexten' '=>' | 'hint' '(' ')' '=>' | 'regexten' 'hint' '(' ')' '=>'

    :== |

    :== 'if' '(' ')'

    :== 'random' '(' ')'

    :== 'ifTime' '(' ':' ':' '|' '|' '|' ')'| 'ifTime' '(' '|' '|' '|' ')'

    :== | |

    :== 'switch' '(' ')' '{'

    :== '{' '}'| '=' ';'| 'goto' ';'| 'jump' ';'| ':'| 'for' '(' ';' ';' ')'

  • 8/3/2019 Asterisk AEL2

    28/39

    | 'while' '(' ')' | '}'| '}'| '&' macro_call ';'| ';'

    | '=' ';'| 'break' ';'| 'return' ';'| 'continue' ';'| | 'else' | | 'else' | | 'else' | ';'

    :== | '|' | '|' '|' | 'default' '|' '|' | ',' | ',' ',' | 'default' ',' ','

    :== | ',' | ',' '@' | '@' | ',' '@' 'default'| '@' 'default'

    :== '(' ')'| '(' ')'

    :== '('

    :== ')'| ')'

    :== | ',' | /* nothing */| ',' /* nothing */

    :==

  • 8/3/2019 Asterisk AEL2

    29/39

    |

    :== 'case' ':' | 'default' ':'

    | 'pattern' ':' | 'case' ':'| 'default' ':'| 'pattern' ':'

    :== |

    :== | includes| 'catch' '{' '}'

    :== 'switches' '{' '}'| 'switches' '{' '}'

    :== 'eswitches' '{' '}'| 'eswitches' '{' '}'

    :== ';'| ';'

    :== ';'| '|' ':' ':' '|' '|' '|' ';'| '|' '|' '|' '|' ';'| ';'| '|' ':' ':' '|' '|' '|' ';'| '|' '|' '|' '|' ';'

    :== | 'default'

    :== 'includes' '{' '}'| 'includes' '{' '}'

  • 8/3/2019 Asterisk AEL2

    30/39

    AEL2 Bug Report History

    (note: RFT means "Ready forTest" in the following:)

    Bug ID Category Severity Status

    Last

    Updated

    Summary

    0007721PBX/pbx_ael

    minorclosed(murf)

    08-12-06

    AEL2 can't parse hint with the andchar (Zap/4&Zap5)

    0007598PBX/pbx_ael

    minorclosed(murf)

    08-07-06

    labels for goto not working inmacros

    0007605PBX/pbx_ael

    minorclosed(murf)

    08-04-06

    AEL2 parser doesn't see macros in.conf language files

    0007635 PB

    X/pbx_ael minor closed(murf) 08-01-06 For loop increment not workingright

    0007474PBX/pbx_ael

    majorclosed(murf)

    07-06-06

    AEL2 not properly escapingcommas

    0007804PBX/pbx_ael

    minorclosed(murf)

    08-25-06

    Various AEL crashes fixed

    0008661PBX/pbx_ael

    minorclosed(murf)

    12-29-06

    delimiter

    0007714

    PBX/pbx_ae

    l tweak

    closed

    (murf)

    08-14-

    06

    proposed alternative to switch-

    case-extensions

    0007715 PBX/pbx-ael featureclosed(murf)

    08-10-06

    support gosub & macros

    0008004PBX/pbx_ael

    minorclosed(murf)

    09-22-06

    supportAST_MODULE_LOAD_DECLINE

    0008031PBX/pbx_ael

    minorclosed(murf)

    09-26-06

    AEL load on debian

    0008090 PBX/pbx_ael

    crash closed(murf)

    10-04-06

    core dump loading AEL file

    0008099PBX/pbx_ael

    crashclosed(murf)

    10-05-06

    core on empty extension

    0008128PBX/pbx_ael

    majorclosed(murf)

    10-13-06

    switch fallthru fails w/ patterns

  • 8/3/2019 Asterisk AEL2

    31/39

    0008836PBX/pbx_ael

    minorclosed(murf)

    01-22-07

    reload nukes subscription tables

    0009184PBX/pbx_ael

    majorclosed(murf)

    03-02-07

    comma/escape issues again.

    0009228PBX/pbx_ael

    majorclosed(murf)

    03-21-07

    macro vs. Gosub: what aboutmacros in Dial?

    0009316PBX/pbx_ael

    minorclosed(murf)

    03-20-07

    AEL security risk via switch-case-extensions

    00009373

    PBX/pbx_ael

    crashclosed(murf)

    2007-03-27

    A segmentation fault occurs whentwo context have the same name

    0009419PBX/pbx_ael

    minorclosed(murf)

    2007-03-29

    Global variables defined inextensions.ael not reloaded whendoing a reload, other parts of

    dialplan are.

    0009435PBX/pbx_ael

    majorclosed(murf)

    2007-04-02

    (patch) "continue" doesn't performthe increment in "for" loops

    0009452PBX/pbx_ael

    minorclosed(murf)

    2007-06-21

    AEL doesn't load default context atfirst time

    0009508PBX/pbx_ael

    minorclosed(murf)

    2007-07-03

    ast_expr2.y fails on negative realnumbers

    0009623PBX/pbx_ae

    l

    minorclosed

    (murf)

    2007-

    05-03

    AEL gives syntax error on @ in a

    switch

    0009805PBX/pbx_ael

    minorclosed(murf)

    2007-05-25

    MACRO_EXTEN, MACRO_... isempty in AEL

    0009881PBX/pbx_ael

    minorclosed(murf)

    2007-06-05

    Switch construct breaks thedialplan flow if it doesn't have adefault case

    0009883PBX/pbx_ael

    minorclosed(murf)

    2007-06-05

    AEL macros do not allow"includes" construct

    0010322

    PBX/pbx_ae

    l minor

    closed

    (murf)

    2007-

    07-27

    (patch) Switch pbx_ael to generate

    code with comma delimiters

    0010411PBX/pbx_ael

    minorclosed(murf)

    2007-08-14

    Variables in AEL2 context names

    0010472PBX/pbx_ael

    minorclosed(murf)

    2007-12-21

    conf2ael improvements

  • 8/3/2019 Asterisk AEL2

    32/39

    0010498PBX/pbx_ael

    minorclosed(murf)

    2007-08-27

    pbx_ael crashs asterisk whenunloading/loading

    0010786PBX/pbx_ael

    minorclosed(murf)

    2007-09-22

    #include directive does not work

    0010787PBX/pbx_ael

    majorclosed(murf)

    2007-11-01

    Impossible to make optional macroarguments in 1.4

    0010788PBX/pbx_ael

    majorclosed(murf)

    2007-09-22

    for loops broken

    0010789PBX/pbx_ael

    majorclosed(murf)

    2007-09-22

    No way to set a variable withoutmath

    0010834PBX/pbx_ael

    minorclosed(murf)

    2007-10-03

    (patch) Empty vars in AEL2switches lead to dropped calls

    0010870 PBX/pbx_ael

    minor closed(murf)

    2007-10-03

    AEL & CUT

    0011005PBX/pbx_ael

    tweakclosed(murf)

    2007-10-24

    glob #include uses base pathdifferent from non-glob #include

    0011009PBX/pbx_ael

    majorclosed(qwell)

    2007-10-17

    i extention not all times work

    0011037PBX/pbx_ael

    minorclosed(murf)

    2007-10-23

    hint to monitor meetme using aelsyntax

    0011086PBX/pbx_ael feature

    closed(murf)

    2007-10-30

    avoid nonexistent context warningswhen loading AEL

    0011287PBX/pbx_ael

    minorclosed(murf)

    2007-12-20

    Failed compile pbx_ael on solaris

    0011329PBX/pbx_ael

    minorclosed(murf)

    2008-01-11

    AEL macro argument variablesaren't properly quoted when set

    0011903PBX/pbx_ael

    minorclosed(murf)

    2008-03-18

    Wrong error file shown if includesused

    0012238PBX/pbx_ae

    lmajor

    closed

    (murf)

    2008-

    03-18

    include block not loaded on

    asterisk start

    0012302PBX/pbx_ael

    majorclosed(murf)

    2008-03-27

    ${EXTEN} variable is corruptedwithin switch()

    0012303PBX/pbx_ael

    minorclosed(murf)

    2008-03-26

    digit extension pattern matches alsodialed string, that looks like patternitself

  • 8/3/2019 Asterisk AEL2

    33/39

    0012467PBX/pbx_ael

    minorclosed(murf)

    2008-04-21

    Can't add 0 in front of functionresult within if() block of AEL

    0013046PBX/pbx_ael

    crashclosed(murf)

    2008-07-30

    Asterisk segfault at startup/aelreload

    0013051PBX/pbx_ael

    minorclosed(murf)

    2008-07-30

    SIPPEER isn't working insideREGEX and IF

    0013061PBX/pbx_ael

    minorclosed(mvanbaak)

    2008-07-12

    random appears to be broken

    0013090PBX/pbx_ael

    minorclosed(murf)

    2008-07-16

    multiple "infinite loop" messagesbeing output by AEL compiler.

    0013197PBX/pbx_ael

    minorclosed(murf)

    2008-07-30

    STAT() inside IF() doesn't work

    0013236PBX/pbx_ael

    majorclosed(murf)

    2008-08-07

    doesn't set ~~EXTEN~~ on therigth place when a switch statementhas been found

    0013305PBX/pbx_ael

    crashclosed(murf)

    2008-08-20

    AEL while loop - high cpu usageand crash (private)

    0013339PBX/pbx_ael

    featureclosed(murf)

    2008-09-08

    AEL parser should trim RHS of anassignment

    0013357

    PBX/pbx_ae

    l minor

    closed

    (murf)

    2008-

    09-04

    AEL doesn't like using dialplan

    function call as argument for 'jump'statement

    0013407PBX/pbx_ael

    minor closed2008-09-02

    AEL switches inside macros notworking like extensions.conf's ones

    0013416PBX/pbx_ael

    minorclosed(murf)

    2008-09-04

    Function CUT doesn't work ifpassed as parameter to macro inAEL

    0013765PBX/pbx_ael

    minorclosed(murf)

    2008-10-24

    after return from child contextARG is cleared

    AEL2 Enhancement Request History

  • 8/3/2019 Asterisk AEL2

    34/39

    1. (Originally filed as bug 7606) Generate extensions.conf format ouput from aelparse

    Status: Finished, -w option added to aelparse

    Description: Standalone AEL2 compiler

    Requested by: rushowr

    2. (Originally filed as bug 7638) Reverse compiler from extensions.conf format to AEL format

    Status: In Progress

    Description: how hard would it be to write a reverse compiler for translating existing dialplan

    files into .ael/.ael2 files?

    Requested by: rushowr

    Branch: http://svn.digium.com/svn/asterisk/team/murf/bug_7638

    Discussion:

    Murf:

    Now, as to the reverse, converting extensions.conf to AEL: it is possible, but a lot of work. Think

    of it this

    way: what you are asking for is a reverse compiler. Given, for example, an assembly file,

    produce the equivalent

    C++ code that might have produced that assembly file. It's a bit easier (relatively) if you have

    some nice constraints,

    say you know the assembly file was generated with g++, and only one particular version of it, at

    that. You could then

    pattern match certain sequences in the assembler output back into C++ structures with reasonable

    confidence.Others, you just synthesize something that would work.

    But, incoming extensions.conf code does not follow such narrow limits.It would not be

    uncommon to see subtle tricks being

    used to accomplish some goal, which would be difficult for a human to interpret, let alone a

    program. That being said, most

    extensions code **is** pretty simple, and in most cases simple heuristics could cover a great

    majority of the code. Stuff that

    it can't grok could simply be copied verbatim into the output for a human to complete. Most of

    the formatting and easy stuff

    could be done by the translator and speed up the job of conversion tremendously.

    I'm all for it. Such a program could help reduce the cost of converting to AEL, and aid the whole

    community greatly.

    29 Dec 2006; I've got the basics lined up for experiment 1 of this code, using the existing

  • 8/3/2019 Asterisk AEL2

    35/39

    asterisk config file reading code

    to pull in the extensions.conf; Experiment 2 will be to use benjk's ini file parser-- but it looks like

    that would be a heck of a

    lot more work to incorporate. So I'll go the easy route first. (And it wasn't that easy).

    22 Mar 2007; Finally, I've refactored the code to get a standalone config file processor that

    yields the internal structs

    used by asterisk. The reverse compiler generates contexts, extensions, priorities, with no real

    translation of gotos, loops,

    etc. But it's a crude start.

    3. Add a quiet option to aelparse-- it's too noisy!!!

    Status: Finished: added -q option to aelparse

    Description: I can't find the errors amid all the progress messages!

    Requested by: rushowr

    4. (originally filed as bug 7715) Replace the Gosub command with an internal AEL2 command?

    Status: Completed in Trunk (will appear in 1.6).

    Description: Replace the Gosub command with an internal AEL2 command?

    Requested by: rushowr

    Branch: team/murf/macrogosub

    Discussion:

    Rushowr:

    I like the replacement goto statement, and jump is nice, but how hard would it be to create a

    replacement forGosub?

    I've been having issues with macros needing to call other macros (I use 'em like functions) but ifthere's more than one or two

    deep, it won't work, and it's a pain. I'd love to see the ability to call a label or extension within

    another context with a return

    address saved so that when the end of the called context is hit, we return to the calling context.....

    Another thing that would be AWESOME would be to make the AEL2 version of subroutine

    handling allow supplying arguments

    to the subroutine, kind of like a merge between the Asterisk macros and Gosub called contexts....

    Basically, I'm dying for the

    ability to define something like a function that when called, will save a return address AND

    won't have the problems that Macros

    have of not always working when they're called from within anotherMacro/Function.....

    murf:

    Macro **is** the right idea for this sort of thing-- let's spend some time and see why it's not

    behaving right for you. We can open

  • 8/3/2019 Asterisk AEL2

    36/39

    a bug, and supply a test case?

    murf:

    I am modifying the code in pbx_ael.c to generate Gosub() calls instead ofMacro() calls.

    This is made possible by an upgrade provided by Corydon(Tilghman Lesher) to Gosub, so

    that it can be called with arguments. The reason? The Application Macro() uses up a fair

    amount of stack space to do its thing. If you go more than 7 levels deep in macros (via recursion

    or subdivision of tasks) then safeguards will kick in and the calls will terminate early to keep

    asterisk from crashing. Gosubs don't traverse the macro def "by hand" like Macro does, and

    will allow a bit more "headroom". We are hoping about 20 levels of depth. The only problem

    is that the coderhas to explicitly include "return" statements in their macros, or you'll have

    pretty big problems!!!

    Otherwise, there is little difference with previous usage. Macros are still declared the same

    in AEL, they are just compiled differently underneat

    hnow. Just make sure to put t

    he return;

    statement in the right spots! They will be converted to Return() application calls.

    5. (originally filed as bug 7714) Alternative to naming new extensions when building a switch

    conditionals

    Status: ON HOLD Not going to do this as yet; the current method seems better at this time.

    Description:Don't break switch cases into separate extensions?

    Requested by: rushowr

    Branch: not yet

    Discussion:Rushowr:

    The existing method of using multiple extensions to separate cases within the switch statement is

    not the best. Have you thought about

    just using n(labelname) directives? See the additional information box for my

    examples/comparisons.

    the n(label) labels are GREAT, and you can reference them just like we do within the AEL code

    :)

    AEL2's outputted code: (excess removed)

    macro-endcall

    exten => s,1,Goto(sw-10-${calltype}|1)

    exten => s,2,NoOp(Finish switch-endcall-10)

    exten => sw-10-in,1,Macro(setdispo|${callid})

    exten => sw-10-out,1,Macro(dbconn|cdr|open)

  • 8/3/2019 Asterisk AEL2

    37/39

    A suggested way to do this:

    exten => s,1,Goto(${EXTEN}|${calltype})

    exten => s,2,NoOp(Finish switch-endcall)

    exten => s,n(in),Macro(setdispo|${callid})

    exten => s,n,Return

    exten => s,n(out),Macro(dbconn|cdr|open)

    exten => s,n,Return

    Murf:

    As to the switch thing, as I call it...

    Ihave definitely thought much on this issue while I was coding up AEL2...

    but first and foremost, that was t

    he way (using separate

    extensions) the original AEL implemented switches, and

    I didn't want to rock the boat.

    Next, it does have a certain appeal. Besides the normal case and default

    statements you can put in a switch, there is also the "pattern"

    statement, which basically is just like a case, except that it prepends an

    underscore in front of the extension name, allowing a pattern extension,

    which is something you just cannot get with a simple switch...

    switch(${NUMTODIAL}){

    case 911:

    verbose("Hey, an emergency!");

    break;

    case 411:

    verbose("What, you need information?");

    break;

    pattern 307XXXXXXX:

    verbose("Why on earth would you want to call Wyoming?");

    break;

    pattern 801XXXXXXX:

    verbose("Why on earth would anyone call Utah?");

    break;

    default:

    verbose(Ah, a discriminating caller, indeed!);

  • 8/3/2019 Asterisk AEL2

    38/39

    break;

    }

    I guess if labels could define patterns, you could get the same affect.

    Until then, you have to admit, the pattern statement is a nice feature.

    Rushowr:

    Hey, you're right! I completely forgot about the pattern matching abilities.

    Your way definitely makes much more sense :)

    pkempgen (via the Mantis bug tracker, 9316, 03-19-07 15:29):

    You never know for sure that ${EXTEN} is what you

    think it is because it mig

    hthappen to be inside

    a different extension - and Dial(SIP/sw-87-user) is

    not what I expected :)

    6. Multiline Commenting

    Status: finished

    Description: Enhance the AEL2 parser to allow for a multiline comment keyword set.

    Requested by: rushowr

    Branch: already committed to trunk

    Discussion: C style comments are now supported: example: /* this is a comment */

    7. New keyword: subroutine

    Status: Will not be done, sort of... see above about Macro/Gosub

    Description: Enhancement to the context keyword, if context is prefaced by subroutine force

    'return' statements within that context to use the subroutine command Return.

    Requested by: rushowr

    Branch: not yet

    Discussion: Due to memory constraints built into asterisk, we will implement macros as gosubs

    instead. See above.

    8. #Include wildcards

    Status: Finished

    Description: Allow #including wildcards like the rest of the Asterisk configs. This allows things

    like: #include "people/*.conf"

    Requested by: Luke-Jr

    Discussion/Notes:

  • 8/3/2019 Asterisk AEL2

    39/39

    rushowr: I know that #include is already implemented, haven't personally tested wildcards

    because I wasn't aware you could wildcard includes at all. Will test or check with murph

    murf: I finished this. Is it in just trunk, or did I add it to 1.4 also?

    9. Optimize AEL generated extensions.conf code by leaving out the NoOp() markers

    Status: Not Yet Begun

    Description: The NoOps() that are output to mark the end of if, while, switch, etc statements are

    unnecc. please remove them.

    Requested by: yarns (bug 13422)

    Discussion/Notes:

    10. allow macros to have variable numbers of arguments.

    Status: Not yet begun.

    Description: Allow macros to have a variable number of arguments

    Requested by: SE

    VER

    ALDiscussion/Notes: I've been discouraging users from using ${ARG1}, ${ARG2}, etc inside

    macros, in favor of using the name of the argument instead... eg. ${name}.

    Since Gosub (in 1.6.x./trunk) is being used, users can use ${ARGx} to access such arguments,

    but the AEL parser will reject extra arguments if included,

    and complain about missing arguments if you include too few. I've been thinking about including

    a new keyword, "...", which, if included as the last

    argument in the macro definition, would turn off such checking for that and following

    arguments.