1 The Asterisk Extension Language - v 2
2 =====================================
4 AEL is a specialized language intended purely for
5 describing Asterisk dial plans.
7 The current version was written by Steve Murphy, and is a rewrite of
10 This new version further extends AEL, and
11 provides more flexible syntax, better error messages, and some missing
14 AEL is really the merger of 4 different 'languages', or syntaxes:
16 * The first and most obvious is the AEL syntax itself. A BNF is
17 provided near the end of this document.
19 * The second syntax is the Expression Syntax, which is normally
20 handled by Asterisk extension engine, as expressions enclosed in
21 $[...]. The right hand side of assignments are wrapped in $[ ... ]
22 by AEL, and so are the if and while expressions, among others.
24 * The third syntax is the Variable Reference Syntax, the stuff
25 enclosed in ${..} curly braces. It's a bit more involved than just
26 putting a variable name in there. You can include one of dozens of
27 'functions', and their arguments, and there are even some string
28 manipulation notation in there.
30 * The last syntax that underlies AEL, and is not used
31 directly in AEL, is the Extension Language Syntax. The
32 extension language is what you see in extensions.conf, and AEL
33 compiles the higher level AEL language into extensions and
34 priorities, and passes them via function calls into
35 Asterisk. Embedded in this language is the Application/AGI
36 commands, of which one application call per step, or priority
37 can be made. You can think of this as a "macro assembler"
38 language, that AEL will compile into.
41 Any programmer of AEL should be familiar with it's syntax, of course,
42 as well as the Expression syntax, and the Variable syntax.
44 **************************
45 * Asterisk in a Nutshell *
46 **************************
48 Asterisk acts as a server. Devices involved in telephony, like Zapata
49 cards, or Voip phones, all indicate some context that should be
50 activated in their behalf. See the config file formats for IAX, SIP,
51 chan_dahdi.conf, etc. They all help describe a device, and they all
52 specify a context to activate when somebody picks up a phone, or a
53 call comes in from the phone company, or a voip phone, etc.
58 Contexts are a grouping of extensions.
60 Contexts can also include other contexts. Think of it as a sort of
61 merge operation at runtime, whereby the included context's extensions
62 are added to the contexts making the inclusion.
64 Extensions and priorities
65 -------------------------
67 A Context contains zero or more Extensions. There are several
68 predefined extensions. The "s" extension is the "start" extension, and
69 when a device activates a context the "s" extension is the one that is
70 going to be run. Other extensions are the timeout "t" extension, the
71 invalid response, or "i" extension, and there's a "fax" extension. For
72 instance, a normal call will activate the "s" extension, but an
73 incoming FAX call will come into the "fax" extension, if it
74 exists. (BTW, asterisk can tell it's a fax call by the little "beep"
75 that the calling fax machine emits every so many seconds.).
77 Extensions contain several priorities, which are individual
78 instructions to perform. Some are as simple as setting a variable to a
79 value. Others are as complex as initiating the Voicemail application,
80 for instance. Priorities are executed in order.
82 When the 's" extension completes, asterisk waits until the timeout for
83 a response. If the response matches an extension's pattern in the
84 context, then control is transferred to that extension. Usually the
85 responses are tones emitted when a user presses a button on their
86 phone. For instance, a context associated with a desk phone might not
87 have any "s" extension. It just plays a dialtone until someone starts
88 hitting numbers on the keypad, gather the number, find a matching
89 extension, and begin executing it. That extension might Dial out over
90 a connected telephone line for the user, and then connect the two
93 The extensions can also contain "goto" or "jump" commands to skip to
94 extensions in other contexts. Conditionals provide the ability to
95 react to different stimuli, and there you have it.
100 Think of a macro as a combination of a context with one nameless
101 extension, and a subroutine. It has arguments like a subroutine
102 might. A macro call can be made within an extension, and the
103 individual statements there are executed until it ends. At this point,
104 execution returns to the next statement after the macro call. Macros
105 can call other macros. And they work just like function calls.
110 Application calls, like "Dial()", or "Hangup()", or "Answer()", are
111 available for users to use to accomplish the work of the
112 dialplan. There are over 145 of them at the moment this was written,
113 and the list grows as new needs and wants are uncovered. Some
114 applications do fairly simple things, some provide amazingly complex
117 Hopefully, the above objects will allow you do anything you need to in
118 the Asterisk environment!
125 The AEL parser (pbx_ael.so) is completely separate from the module
126 that parses extensions.conf (pbx_config.so). To use AEL, the only
127 thing that has to be done is the module pbx_ael.so must be loaded by
128 Asterisk. This will be done automatically if using 'autoload=yes' in
129 /etc/asterisk/modules.conf. When the module is loaded, it will look
130 for 'extensions.ael' in /etc/asterisk/. extensions.conf and
131 extensions.ael can be used in conjunction with
132 each other if that is what is desired. Some users may want to keep
133 extensions.conf for the features that are configured in the 'general'
134 section of extensions.conf.
136 ------------------------------
137 - Reloading extensions.ael -
138 ------------------------------
140 To reload extensions.ael, the following command can be issued at the
151 Right at this moment, the following commands are available, but do
154 Enable AEL contexts debug
155 *CLI> ael debug contexts
157 Enable AEL macros debug
158 *CLI> ael debug macros
160 Enable AEL read debug
163 Enable AEL tokens debug
164 *CLI> ael debug tokens
166 Disable AEL debug messages
169 If things are going wrong in your dialplan, you can use the following
170 facilities to debug your file:
172 1. The messages log in /var/log/asterisk. (from the checks done at load time).
173 2. the "show dialplan" command in asterisk
174 3. the standalone executable, "aelparse" built in the utils/ dir in the source.
177 *****************************
179 *****************************
181 You can use the "aelparse" program to check your extensions.ael
182 file before feeding it to asterisk. Wouldn't it be nice to eliminate
183 most errors before giving the file to asterisk?
185 aelparse is compiled in the utils directory of the asterisk release.
186 It isn't installed anywhere (yet). You can copy it to your favorite
189 aelparse has two optional arguments:
191 -d - Override the normal location of the config file dir, (usually
192 /etc/asterisk), and use the current directory instead as the
193 config file dir. Aelparse will then expect to find the file
194 "./extensions.ael" in the current directory, and any included
195 files in the current directory as well.
197 -n - don't show all the function calls to set priorities and contexts
198 within asterisk. It will just show the errors and warnings from
199 the parsing and semantic checking phases.
202 ******************************
203 * General Notes about Syntax *
204 ******************************
206 Note that the syntax and style are now a little more free-form. The
207 opening '{' (curly-braces) do not have to be on the same line as the
208 keyword that precedes them. Statements can be split across lines, as
209 long as tokens are not broken by doing so. More than one statement can
210 be included on a single line. Whatever you think is best!
212 You can just as easily say,
214 if(${x}=1) { NoOp(hello!); goto s|3; } else { NoOp(Goodbye!); goto s|12; }
242 NoOp(hello!); goto s|3;
244 NoOp(Goodbye!); goto s|12;
266 The AEL keywords are case-sensitive. If an application name and a
267 keyword overlap, there is probably good reason, and you should
268 consider replacing the application call with an AEL statement. If you
269 do not wish to do so, you can still use the application, by using a
270 capitalized letter somewhere in its name. In the Asterisk extension
271 language, application names are NOT case-sensitive.
273 The following are keywords in the AEL language:
296 * default NOTE: the "default" keyword can be used as a context name,
297 for those who would like to do so.
307 Procedural Interface and Internals
308 ==================================
310 AEL first parses the extensions.ael file into a memory structure representing the file.
311 The entire file is represented by a tree of "pval" structures linked together.
313 This tree is then handed to the semantic check routine.
315 Then the tree is handed to the compiler.
317 After that, it is freed from memory.
319 A program could be written that could build a tree of pval structures, and
320 a pretty printing function is provided, that would dump the data to a file,
321 or the tree could be handed to the compiler to merge the data into the
322 asterisk dialplan. The modularity of the design offers several opportunities
323 for developers to simplify apps to generate dialplan data.
327 =========================
329 =========================
333 (hopefully, something close to bnf).
335 First, some basic objects
337 ------------------------
339 <word> a lexical token consisting of characters matching this pattern: [-a-zA-Z0-9"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9"_/.!\*\+\<\>\{\}$#\[\]]*
341 <word3-list> a concatenation of up to 3 <word>s.
343 <collected-word> all characters encountered until the character that follows the <collected-word> in the grammar.
345 -------------------------
349 <objects> :== <object>
353 <object> :== <context>
359 <context> :== 'context' <word> '{' <elements> '}'
360 | 'context' <word> '{' '}'
361 | 'context' 'default' '{' <elements> '}'
362 | 'context' 'default' '{' '}'
363 | 'abstract' 'context' <word> '{' <elements> '}'
364 | 'abstract' 'context' <word> '{' '}'
365 | 'abstract' 'context' 'default' '{' <elements> '}'
366 | 'abstract' 'context' 'default' '{' '}'
369 <macro> :== 'macro' <word> '(' <arglist> ')' '{' <macro_statements> '}'
370 | 'macro' <word> '(' <arglist> ')' '{' '}'
371 | 'macro' <word> '(' ')' '{' <macro_statements> '}'
372 | 'macro' <word> '(' ')' '{' '}'
375 <globals> :== 'globals' '{' <global_statements> '}'
379 <global_statements> :== <global_statement>
380 | <global_statements> <global_statement>
383 <global_statement> :== <word> '=' <collected-word> ';'
387 | <arglist> ',' <word>
390 <elements> :== <element>
391 | <elements> <element>
394 <element> :== <extension>
399 | <word> '=' <collected-word> ';'
403 <ignorepat> :== 'ignorepat' '=>' <word> ';'
406 <extension> :== <word> '=>' <statement>
407 | 'regexten' <word> '=>' <statement>
408 | 'hint' '(' <word3-list> ')' <word> '=>' <statement>
409 | 'regexten' 'hint' '(' <word3-list> ')' <word> '=>' <statement>
412 <statements> :== <statement>
413 | <statements> <statement>
415 <if_head> :== 'if' '(' <collected-word> ')'
417 <random_head> :== 'random' '(' <collected-word> ')'
419 <ifTime_head> :== 'ifTime' '(' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')'
420 | 'ifTime' '(' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')'
423 <word3-list> :== <word>
425 | <word> <word> <word>
427 <switch_head> :== 'switch' '(' <collected-word> ')' '{'
430 <statement> :== '{' <statements> '}'
431 | <word> '=' <collected-word> ';'
432 | 'goto' <target> ';'
433 | 'jump' <jumptarget> ';'
435 | 'for' '(' <collected-word> ';' <collected-word> ';' <collected-word> ')' <statement>
436 | 'while' '(' <collected-word> ')' <statement>
438 | <switch_head> <case_statements> '}'
440 | <application_call> ';'
441 | <application_call> '=' <collected-word> ';'
445 | <random_head> <statement>
446 | <random_head> <statement> 'else' <statement>
447 | <if_head> <statement>
448 | <if_head> <statement> 'else' <statement>
449 | <ifTime_head> <statement>
450 | <ifTime_head> <statement> 'else' <statement>
455 | <word> '|' <word> '|' <word>
456 | 'default' '|' <word> '|' <word>
458 | <word> ',' <word> ',' <word>
459 | 'default' ',' <word> ',' <word>
461 <jumptarget> :== <word>
463 | <word> ',' <word> '@' <word>
465 | <word> ',' <word> '@' 'default'
466 | <word> '@' 'default'
468 <macro_call> :== <word> '(' <eval_arglist> ')'
471 <application_call_head> :== <word> '('
473 <application_call> :== <application_call_head> <eval_arglist> ')'
474 | <application_call_head> ')'
476 <eval_arglist> :== <collected-word>
477 | <eval_arglist> ',' <collected-word>
479 | <eval_arglist> ',' /* nothing */
481 <case_statements> :== <case_statement>
482 | <case_statements> <case_statement>
485 <case_statement> :== 'case' <word> ':' <statements>
486 | 'default' ':' <statements>
487 | 'pattern' <word> ':' <statements>
490 | 'pattern' <word> ':'
492 <macro_statements> :== <macro_statement>
493 | <macro_statements> <macro_statement>
495 <macro_statement> :== <statement>
496 | 'catch' <word> '{' <statements> '}'
498 <switches> :== 'switches' '{' <switchlist> '}'
501 <eswitches> :== 'eswitches' '{' <switchlist> '}'
502 | 'eswitches' '{' '}'
504 <switchlist> :== <word> ';'
505 | <switchlist> <word> ';'
507 <includeslist> :== <includedname> ';'
508 | <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
509 | <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
510 | <includeslist> <includedname> ';'
511 | <includeslist> <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
512 | <includeslist> <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
514 <includedname> :== <word>
517 <includes> :== 'includes' '{' <includeslist> '}'
521 **************************
522 * AEL Example USAGE *****
523 **************************
528 Comments begin with // and end with the end of the line.
530 Comments are removed by the lexical scanner, and will not be
531 recognized in places where it is busy gathering expressions to wrap in
532 $[] , or inside application call argument lists. The safest place to put
533 comments is after terminating semicolons, or on otherwise empty lines.
539 Contexts in AEL represent a set of extensions in the same way that
540 they do in extensions.conf.
548 A context can be declared to be "abstract", in which case, this
549 declaration expresses the intent of the writer, that this context will
550 only be included by another context, and not "stand on its own". The
551 current effect of this keyword is to prevent "goto " statements from
555 abstract context longdist {
556 _1NXXNXXXXXX => NoOp(generic long distance dialing actions in the US);
564 To specify an extension in a context, the following syntax is used. If
565 more than one application is be called in an extension, they can be
566 listed in order inside of a block.
570 1234 => Playback(tt-monkeys);
576 _5XXX => NoOp(it's a pattern!);
580 Two optional items have been added to the AEL syntax, that allow the
581 specification of hints, and a keyword, regexten, that will force the
582 numbering of priorities to start at 2.
584 The ability to make extensions match by CID is preserved in
585 AEL; just use '/' and the CID number in the specification. See below.
590 regexten _5XXX => NoOp(it's a pattern!);
597 hint(Sip/1) _5XXX => NoOp(it's a pattern!);
604 regexten hint(Sip/1) _5XXX => NoOp(it's a pattern!);
608 The regexten must come before the hint if they are both present.
610 CID matching is done as with the extensions.conf file. Follow the extension
611 name/number with a slash (/) and the number to match against the Caller ID:
615 819/7079953345 => { NoOp(hello, 3345); }
618 In the above, the 819/7079953345 extension will only be matched if the
619 CallerID is 7079953345, and the dialed number is 819. Hopefully you have
620 another 819 extension defined for all those who wish 819, that are not so lucky
621 as to have 7079953345 as their CallerID!
627 Contexts can be included in other contexts. All included contexts are
628 listed within a single block.
640 Time-limited inclusions can be specified, as in extensions.conf
641 format, with the fields described in the wiki page Asterisk cmd
648 longdistance|16:00-23:59|mon-fri|*|*;
657 You can include other files with the #include "filepath" construct.
660 #include "/etc/asterisk/testfor.ael"
663 An interesting property of the #include, is that you can use it almost
664 anywhere in the .ael file. It is possible to include the contents of
665 a file in a macro, context, or even extension. The #include does not
666 have to occur at the beginning of a line. Included files can include
667 other files, up to 50 levels deep. If the path provided in quotes is a
668 relative path, the parser looks in the config file directory for the
669 file (usually /etc/asterisk).
676 Switches are listed in their own block within a context. For clues as
677 to what these are used for, see Asterisk - dual servers, and Asterisk
678 config extensions.conf.
687 IAX2/context@${CURSERVER};
696 ignorepat can be used to instruct channel drivers to not cancel
697 dialtone upon receipt of a particular pattern. The most commonly used
711 Variables in Asterisk do not have a type, so to define a variable, it
712 just has to be specified with a value.
714 Global variables are set in their own block.
724 Variables can be set within extensions as well.
732 NoOp(x is ${x} and y is ${y} !);
737 NOTE: AEL wraps the right hand side of an assignment with $[ ] to allow
738 expressions to be used If this is unwanted, you can protect the right hand
739 side from being wrapped by using the Set() application.
740 Read the README.variables about the requirements and behavior
743 NOTE: These things are wrapped up in a $[ ] expression: The while() test;
744 the if() test; the middle expression in the for( x; y; z) statement
745 (the y expression); Assignments - the right hand side, so a = b -> Set(a=$[b])
747 Writing to a dialplan function is treated the same as writing to a variable.
752 CALLERID(name)=ChickenMan;
753 NoOp(My name is ${CALLERID(name)} !);
762 AEL has implementations of 'for' and 'while' loops.
767 for (x=0; ${x} < 3; x=${x} + 1) {
768 Verbose(x is ${x} !);
774 Verbose(y is ${y} !);
781 NOTE: The conditional expression (the "${y} >= 0" above) is wrapped in
782 $[ ] so it can be evaluated. NOTE: The for loop test expression
783 (the "${x} < 3" above) is wrapped in $[ ] so it can be evaluated.
790 AEL supports if and switch statements, like AEL, but adds ifTime, and
791 random. Unlike the original AEL, though, you do NOT need to put curly
792 braces around a single statement in the "true" branch of an if(), the
793 random(), or an ifTime() statement. The if(), ifTime(), and random()
794 statements allow optional else clause.
797 context conditional {
800 if ("${DIALSTATUS}" = "BUSY")
803 Voicemail(${EXTEN}|b);
806 Voicemail(${EXTEN}|u);
807 ifTime (14:00-25:00|sat-sun|*|*)
808 Voicemail(${EXTEN}|b);
811 Voicemail(${EXTEN}|u);
814 random(51) NoOp(This should appear 51% of the time);
818 NoOp( This should appear 60% of the time );
824 NoOp( This should appear 30% of the time! );
828 NoOp( This should appear 10% of the time! );
835 NoOp(You called 7771!);
838 NoOp(You called 7772!);
841 NoOp(You called 7773!);
844 NoOp(You called 777 something!);
846 NoOp(In the default clause!);
852 NOTE: The conditional expression in if() statements (the
853 "${DIALSTATUS}" = "BUSY" above) is wrapped by the compiler in
856 NOTE: Neither the switch nor case values are wrapped in $[ ]; they can
857 be constants, or ${var} type references only.
859 NOTE: AEL generates each case as a separate extension. case clauses
860 with no terminating 'break', or 'goto', have a goto inserted, to
861 the next clause, which creates a 'fall thru' effect.
863 NOTE: AEL introduces the ifTime keyword/statement, which works just
864 like the if() statement, but the expression is a time value,
865 exactly like that used by the application GotoIfTime(). See
866 Asterisk cmd GotoIfTime
868 NOTE: The pattern statement makes sure the new extension that is
869 created has an '_' preceding it to make sure asterisk recognizes
870 the extension name as a pattern.
872 NOTE: Every character enclosed by the switch expression's parenthesis
873 are included verbatim in the labels generated. So watch out for
876 NOTE: NEW: Previous to version 0.13, the random statement used the
877 "Random()" application, which has been deprecated. It now uses
878 the RAND() function instead, in the GotoIf application.
881 Break, Continue, and Return
882 ===========================
885 Three keywords, break, continue, and return, are included in the
886 syntax to provide flow of control to loops, and switches.
888 The break can be used in switches and loops, to jump to the end of the
891 The continue can be used in loops (while and for) to immediately jump
892 to the end of the loop. In the case of a for loop, the increment and
893 test will then be performed. In the case of the while loop, the
894 continue will jump to the test at the top of the loop.
896 The return keyword will cause an immediate jump to the end of the
897 context, or macro, and can be used anywhere.
901 goto, jump, and labels
902 ======================
904 This is an example of how to do a goto in AEL.
907 context gotoexample {
910 NoOp(Infinite Loop! yay!);
912 goto begin; // go to label in same extension
915 goto s|begin; // go to label in different extension
918 goto gotoexample|s|begin; // overkill go to label in same context
922 context gotoexample2 {
925 goto gotoexample|s|begin; // go to label in different context
929 You can use the special label of "1" in the goto and jump
930 statements. It means the "first" statement in the extension. I would
931 not advise trying to use numeric labels other than "1" in goto's or
932 jumps, nor would I advise declaring a "1" label anywhere! As a matter
933 of fact, it would be bad form to declare a numeric label, and it might
934 conflict with the priority numbers used internally by asterisk.
936 The syntax of the jump statement is: jump
937 extension[,priority][@context] If priority is absent, it defaults to
938 "1". If context is not present, it is assumed to be the same as that
939 which contains the "jump".
942 context gotoexample {
945 NoOp(Infinite Loop! yay!);
947 jump s; // go to first extension in same extension
950 jump s,begin; // go to label in different extension
953 jump s,begin@gotoexample; // overkill go to label in same context
957 context gotoexample2 {
960 jump s@gotoexample; // go to label in different context
964 NOTE: goto labels follow the same requirements as the Goto()
965 application, except the last value has to be a label. If the
966 label does not exist, you will have run-time errors. If the
967 label exists, but in a different extension, you have to specify
968 both the extension name and label in the goto, as in: goto s|z;
969 if the label is in a different context, you specify
970 context|extension|label. There is a note about using goto's in a
971 switch statement below...
973 NOTE AEL introduces the special label "1", which is the beginning
974 context number for most extensions.
976 NOTE: A NEW addition to AEL: you can now use ',' instead of '|' to
977 separate the items in the target address. You can't have a mix,
978 though, of '|' and ',' in the target. It's either one, or the other.
986 A macro is defined in its own block like this. The arguments to the
987 macro are specified with the name of the macro. They are then referred
988 to by that same name. A catch block can be specified to catch special
992 macro std-exten( ext , dev ) {
993 Dial(${dev}/${ext},20);
994 switch(${DIALSTATUS) {
1003 VoiceMailMain(${ext});
1009 A macro is then called by preceding the macro name with an
1010 ampersand. Empty arguments can be passed simply with nothing between
1015 _5XXX => &std-exten(${EXTEN}, "IAX2");
1016 _6XXX => &std-exten(, "IAX2");
1017 _7XXX => &std-exten(${EXTEN},);
1018 _8XXX => &std-exten(,);
1032 TIMEOUT(response)=10;
1034 Background(demo-congrats);
1036 for (x=0; ${x} < 3; x=${x} + 1) {
1037 Background(demo-instruct);
1042 Background(demo-moreinfo);
1043 goto s|instructions;
1051 Playback(demo-abouttotry);
1052 Dial(IAX2/guest@misery.digium.com);
1053 Playback(demo-nogo);
1054 goto s|instructions;
1057 Playback(demo-echotest);
1059 Playback(demo-echodone);
1060 goto s|instructions;
1064 Playback(demo-thanks);
1068 i => Playback(invalid);
1076 AEL, after parsing, but before compiling, traverses the dialplan
1077 tree, and makes several checks:
1079 * Macro calls to non-existent macros.
1080 * Macro calls to contexts.
1081 * Macro calls with argument count not matching the definition.
1082 * application call to macro. (missing the '&')
1083 * application calls to "GotoIf", "GotoIfTime", "while",
1084 "endwhile", "Random", and "execIf", will generate a message to
1085 consider converting the call to AEL goto, while, etc. constructs.
1086 * goto a label in an empty extension.
1087 * goto a non-existent label, either a within-extension,
1088 within-context, or in a different context, or in any included
1089 contexts. Will even check "sister" context references.
1090 * All the checks done on the time values in the dial plan, are
1091 done on the time values in the ifTime() and includes times:
1092 o the time range has to have two times separated by a dash;
1093 o the times have to be in range of 0 to 24 hours.
1094 o The weekdays have to match the internal list, if they are provided;
1095 o the day of the month, if provided, must be in range of 1 to 31;
1096 o the month name or names have to match those in the internal list.
1097 * (0.5) If an expression is wrapped in $[ ... ], and the compiler
1098 will wrap it again, a warning is issued.
1099 * (0.5) If an expression had operators (you know,
1100 +,-,*,/,%,!,etc), but no ${ } variables, a warning is
1101 issued. Maybe someone forgot to wrap a variable name?
1102 * (0.12) check for duplicate context names.
1103 * (0.12) check for abstract contexts that are not included by any context.
1104 * (0.13) Issue a warning if a label is a numeric value.
1106 There are a subset of checks that have been removed until the proposed
1107 AAL (Asterisk Argument Language) is developed and incorporated into Asterisk.
1108 These checks will be:
1110 * (if the application argument analyzer is working: the presence
1111 of the 'j' option is reported as error.
1112 * if options are specified, that are not available in an
1114 * if you specify too many arguments to an application.
1115 * a required argument is not present in an application call.
1116 * Switch-case using "known" variables that applications set, that
1117 does not cover all the possible values. (a "default" case will
1118 solve this problem. Each "unhandled" value is listed.
1119 * a Switch construct is used, which is uses a known variable, and
1120 the application that would set that variable is not called in
1121 the same extension. This is a warning only...
1122 * Calls to applications not in the "applist" database (installed
1123 in /var/lib/asterisk/applist" on most systems).
1124 * In an assignment statement, if the assignment is to a function,
1125 the function name used is checked to see if it one of the
1126 currently known functions. A warning is issued if it is not.
1130 Differences with the original version of AEL
1131 ============================================
1133 1. The $[...] expressions have been enhanced to include the ==, ||,
1134 and && operators. These operators are exactly equivalent to the
1135 =, |, and & operators, respectively. Why? So the C, Java, C++
1136 hackers feel at home here.
1137 2. It is more free-form. The newline character means very little,
1138 and is pulled out of the white-space only for line numbers in
1140 3. It generates more error messages -- by this I mean that any
1141 difference between the input and the grammar are reported, by
1142 file, line number, and column.
1143 4. It checks the contents of $[ ] expressions (or what will end up
1144 being $[ ] expressions!) for syntax errors. It also does
1145 matching paren/bracket counts.
1146 5. It runs several semantic checks after the parsing is over, but
1147 before the compiling begins, see the list above.
1148 6. It handles #include "filepath" directives. -- ALMOST
1149 anywhere, in fact. You could easily include a file in a context,
1150 in an extension, or at the root level. Files can be included in
1151 files that are included in files, down to 50 levels of hierarchy...
1152 7. Local Goto's inside Switch statements automatically have the
1153 extension of the location of the switch statement appended to them.
1154 8. A pretty printer function is available within pbx_ael.so.
1155 9. In the utils directory, two standalone programs are supplied for
1156 debugging AEL files. One is called "aelparse", and it reads in
1157 the /etc/asterisk/extensions.ael file, and shows the results of
1158 syntax and semantic checking on stdout, and also shows the
1159 results of compilation to stdout. The other is "aelparse1",
1160 which uses the original ael compiler to do the same work,
1161 reading in "/etc/asterisk/extensions.ael", using the original
1162 'pbx_ael.so' instead.
1163 10. AEL supports the "jump" statement, and the "pattern" statement
1164 in switch constructs. Hopefully these will be documented in the
1166 11. Added the "return" keyword, which will jump to the end of an
1168 12. Added the ifTime (<time range>|<days of week>|<days of
1169 month>|<months> ) {} [else {}] construct, which executes much
1170 like an if () statement, but the decision is based on the
1171 current time, and the time spec provided in the ifTime. See the
1172 example above. (Note: all the other time-dependent Applications
1173 can be used via ifTime)
1174 13. Added the optional time spec to the contexts in the includes
1175 construct. See examples above.
1176 14. You don't have to wrap a single "true" statement in curly
1177 braces, as in the original AEL. An "else" is attached to the
1178 closest if. As usual, be careful about nested if statements!
1179 When in doubt, use curlies!
1180 15. Added the syntax [regexten] [hint(channel)] to precede an
1181 extension declaration. See examples above, under
1182 "Extension". The regexten keyword will cause the priorities in
1183 the extension to begin with 2 instead of 1. The hint keyword
1184 will cause its arguments to be inserted in the extension under
1185 the hint priority. They are both optional, of course, but the
1186 order is fixed at the moment-- the regexten must come before the
1187 hint, if they are both present.
1188 16. Empty case/default/pattern statements will "fall thru" as
1190 17. A trailing label in an extension, will automatically have a
1191 NoOp() added, to make sure the label exists in the extension on
1193 18. (0.9) the semicolon is no longer required after a closing brace!
1194 (i.e. "];" ===> "}". You can have them there if you like, but
1195 they are not necessary. Someday they may be rejected as a syntax
1197 19. (0.9) the // comments are not recognized and removed in the
1198 spots where expressions are gathered, nor in application call
1199 arguments. You may have to move a comment if you get errors in
1201 20. (0.10) the random statement has been added. Syntax: random (
1202 <expr> ) <lucky-statement> [ else <unlucky-statement> ]. The
1203 probability of the lucky-statement getting executed is <expr>,
1204 which should evaluate to an integer between 0 and 100. If the
1205 <lucky-statement> isn't so lucky this time around, then the
1206 <unlucky-statement> gets executed, if it is present.
1213 * The safest way to check for a null strings is to say $[ "${x}" =
1214 "" ] The old way would do as shell scripts often do, and append
1215 something on both sides, like this: $[ ${x}foo = foo ]. The
1216 trouble with the old way, is that, if x contains any spaces, then
1217 problems occur, usually syntax errors. It is better practice and
1218 safer wrap all such tests with double quotes! Also, there are now
1219 some functions that can be used in a variable reference,
1220 ISNULL(), and LEN(), that can be used to test for an empty string:
1221 ${ISNULL(${x})} or $[ ${LEN(${x}) = 0 ].
1223 * Assignment vs. Set(). Keep in mind that setting a variable to
1224 value can be done two different ways. If you choose say 'x=y;',
1225 keep in mind that AEL will wrap the right-hand-side with
1226 $[]. So, when compiled into extension language format, the end
1227 result will be 'Set(x=$[y])'. If you don't want this effect,
1228 then say "Set(x=y);" instead.
1231 The Full Power of AEL
1232 ==============================
1234 A newcomer to Asterisk will look at the above constructs and
1235 descriptions, and ask, "Where's the string manipulation functions?",
1236 "Where's all the cool operators that other languages have to offer?",
1239 The answer is that the rich capabilities of Asterisk are made
1240 available through AEL, via:
1242 * Applications: See Asterisk - documentation of application
1245 * Functions: Functions were implemented inside ${ .. } variable
1246 references, and supply many useful capabilities.
1248 * Expressions: An expression evaluation engine handles items
1249 wrapped inside $[...]. This includes some string manipulation
1250 facilities, arithmetic expressions, etc.
1252 * Application Gateway Interface: Asterisk can fork external
1253 processes that communicate via pipe. AGI applications can be
1254 written in any language. Very powerful applications can be added
1257 * Variables: Channels of communication have variables associated
1258 with them, and asterisk provides some global variables. These can be
1259 manipulated and/or consulted by the above mechanisms.