aboutsummaryrefslogtreecommitdiffstats
path: root/doc/tex/ael.tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/tex/ael.tex')
-rw-r--r--doc/tex/ael.tex1305
1 files changed, 0 insertions, 1305 deletions
diff --git a/doc/tex/ael.tex b/doc/tex/ael.tex
deleted file mode 100644
index be03c2bfb..000000000
--- a/doc/tex/ael.tex
+++ /dev/null
@@ -1,1305 +0,0 @@
-\section{Introduction}
-
-AEL is a specialized language intended purely for
-describing Asterisk dial plans.
-
-The current version was written by Steve Murphy, and is a rewrite of
-the original version.
-
-This new version further extends AEL, and
-provides more flexible syntax, better error messages, and some missing
-functionality.
-
-AEL is really the merger of 4 different 'languages', or syntaxes:
-
-\begin{itemize}
- \item The first and most obvious is the AEL syntax itself. A BNF is
- provided near the end of this document.
-
- \item The second syntax is the Expression Syntax, which is normally
- handled by Asterisk extension engine, as expressions enclosed in
- \$[...]. The right hand side of assignments are wrapped in \$[ ... ]
- by AEL, and so are the if and while expressions, among others.
-
- \item The third syntax is the Variable Reference Syntax, the stuff
- enclosed in \$\{..\} curly braces. It's a bit more involved than just
- putting a variable name in there. You can include one of dozens of
- 'functions', and their arguments, and there are even some string
- manipulation notation in there.
-
- \item The last syntax that underlies AEL, and is not used
- directly in AEL, is the Extension Language Syntax. The
- extension language is what you see in extensions.conf, and AEL
- compiles the higher level AEL language into extensions and
- priorities, and passes them via function calls into
- Asterisk. Embedded in this language is the 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 AEL will compile into.
-\end{itemize}
-
-Any programmer of AEL should be familiar with its syntax, of course,
-as well as the Expression syntax, and the Variable syntax.
-
-
-\section{Asterisk in a Nutshell}
-
-Asterisk acts as a server. Devices involved in telephony, like DAHDI
-cards, or Voip phones, all indicate some context that should be
-activated in their behalf. See the config file formats for IAX, SIP,
-dahdi.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 voip phone, etc.
-
-\subsection{Contexts}
-
-Contexts 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.
-
-\subsection{Extensions and priorities}
-
-A 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 the one 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 so many seconds.).
-
-Extensions contain several priorities, which are individual
-instructions to perform. Some are as simple as setting a variable to a
-value. Others are as complex as initiating the Voicemail application,
-for instance. Priorities are executed in order.
-
-When the 's" extension completes, asterisk waits until the timeout for
-a response. If the response matches an extension's pattern in the
-context, then control is transferred to that extension. Usually the
-responses are tones emitted when a user presses a button on their
-phone. For instance, 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 matching
-extension, and begin executing it. That extension might Dial out over
-a connected telephone line for the user, and then connect the two
-lines together.
-
-The extensions can also contain "goto" or "jump" commands to skip to
-extensions in other contexts. Conditionals provide the ability to
-react to different stimuli, and there you have it.
-
-\subsection{Macros}
-
-Think of a macro as a combination of a context with one nameless
-extension, and a subroutine. It has arguments like a subroutine
-might. A macro call can be made within an extension, and the
-individual statements there are executed until it ends. At this point,
-execution returns to the next statement after the macro call. Macros
-can call other macros. And they work just like function calls.
-
-\subsection{Applications}
-
-Application calls, like "Dial()", or "Hangup()", or "Answer()", are
-available for users to use to accomplish 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 simple things, some provide amazingly complex
-services.
-
-Hopefully, the above objects will allow you do anything you need to in
-the Asterisk environment!
-
-\section{Getting Started}
-
-The AEL parser (res\_ael.so) is completely separate from the module
-that parses extensions.conf (pbx\_config.so). To use AEL, the only
-thing that has to be done is the module res\_ael.so must be loaded by
-Asterisk. This will be done automatically if using 'autoload=yes' in
-\path{/etc/asterisk/modules.conf}. When the module is loaded, it will look
-for 'extensions.ael' in \path{/etc/asterisk/}. extensions.conf and
-extensions.ael can be used in conjunction with
-each other if that is what is desired. Some users may want to keep
-extensions.conf for the features that are configured in the 'general'
-section of extensions.conf.
-
-To reload extensions.ael, the following command can be issued at the
-CLI:
-
- *CLI$>$ ael reload
-
-\section{Debugging}
-
-Right at this moment, the following commands are available, but do
-nothing:
-
-Enable AEL contexts debug
-
- *CLI$>$ ael debug contexts
-
-Enable AEL macros debug
-
- *CLI$>$ ael debug macros
-
-Enable AEL read debug
-
- *CLI$>$ ael debug read
-
-Enable AEL tokens debug
-
- *CLI$>$ ael debug tokens
-
-Disable AEL debug messages
-
- *CLI$>$ ael no debug
-
-If things are going wrong in your dialplan, you can use the following
-facilities to debug your file:
-
-1. The messages log in \path{/var/log/asterisk}. (from the checks done at load time).
-2. the "show dialplan" command in asterisk
-3. the standalone executable, "aelparse" built in the utils/ dir in the source.
-
-
-\section{About "aelparse"}
-
-You can use the "aelparse" program to check your extensions.ael
-file before feeding it to asterisk. Wouldn't it be nice to eliminate
-most errors before giving the file to asterisk?
-
-aelparse is compiled in the utils directory of the asterisk release.
-It isn't installed anywhere (yet). You can copy it to your favorite
-spot in your PATH.
-
-aelparse has two optional arguments:
-
-\begin{itemize}
- \item -d
- \begin{itemize}
- \item Override the normal location of the config file dir, (usually
- \path{/etc/asterisk}), and use the current directory instead as the
- config file dir. Aelparse will then expect to find the file
- "./extensions.ael" in the current directory, and any included
- files in the current directory as well.
- \end{itemize}
- \item -n
- \begin{itemize}
- \item don't show all the function calls to set priorities and contexts
- within asterisk. It will just show the errors and warnings from
- the parsing and semantic checking phases.
- \end{itemize}
-\end{itemize}
-
-\section{General Notes about Syntax}
-
-Note that the syntax and style are now a little more free-form. The
-opening '{' (curly-braces) do not have to be on the same line as the
-keyword that precedes them. Statements can be split across lines, as
-long as tokens are not broken by doing so. More than one statement can
-be included on a single line. Whatever you think is best!
-
-You can just as easily say,
-
-\begin{astlisting}
-\begin{verbatim}
-if(${x}=1) { NoOp(hello!); goto s,3; } else { NoOp(Goodbye!); goto s,12; }
-\end{verbatim}
-\end{astlisting}
-as you can say:
-\begin{astlisting}
-\begin{verbatim}
-if(${x}=1)
-{
- NoOp(hello!);
- goto s,3;
-}
-else
-{
- NoOp(Goodbye!);
- goto s,12;
-}
-\end{verbatim}
-\end{astlisting}
-
-or:
-
-\begin{astlisting}
-\begin{verbatim}
-if(${x}=1) {
- NoOp(hello!);
- goto s,3;
-} else {
- NoOp(Goodbye!);
- goto s,12;
-}
-\end{verbatim}
-\end{astlisting}
-
-or:
-
-\begin{astlisting}
-\begin{verbatim}
-if (${x}=1) {
- NoOp(hello!); goto s,3;
-} else {
- NoOp(Goodbye!); goto s,12;
-}
-\end{verbatim}
-\end{astlisting}
-
-\section{Keywords}
-
-The AEL keywords are case-sensitive. If an application name and a
-keyword overlap, there is probably good reason, and you should
-consider replacing the application call with an AEL statement. If you
-do not wish to do so, you can still use the application, by using a
-capitalized letter somewhere in its name. In the Asterisk extension
-language, application names are NOT case-sensitive.
-
-The following are keywords in the AEL language:
-\begin{itemize}
- \item abstract
- \item context
- \item macro
- \item globals
- \item ignorepat
- \item switch
- \item if
- \item ifTime
- \item else
- \item random
- \item goto
- \item jump
- \item local
- \item return
- \item break
- \item continue
- \item regexten
- \item hint
- \item for
- \item while
- \item case
- \item pattern
- \item default NOTE: the "default" keyword can be used as a context name,
- for those who would like to do so.
- \item catch
- \item switches
- \item eswitches
- \item includes
-\end{itemize}
-
-
-\section{Procedural Interface and Internals}
-
-AEL first parses the extensions.ael file into a memory structure representing the file.
-The entire file is represented by a tree of "pval" structures linked together.
-
-This tree is then handed to the semantic check routine.
-
-Then the tree is handed to the compiler.
-
-After that, it is freed from memory.
-
-A program could be written that could build a tree of pval structures, and
-a pretty printing function is provided, that would dump the data to a file,
-or the tree could be handed to the compiler to merge the data into the
-asterisk dialplan. The modularity of the design offers several opportunities
-for developers to simplify apps to generate dialplan data.
-
-
-\subsection{AEL version 2 BNF}
-
-(hopefully, something close to bnf).
-
-First, some basic objects
-
-\begin{astlisting}
-\begin{verbatim}
-------------------------
-<word> a lexical token consisting of characters matching this pattern: [-a-zA-Z0-9"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9"_/.!\*\+\<\>\{\}$#\[\]]*
-
-<word3-list> a concatenation of up to 3 <word>s.
-
-<collected-word> all characters encountered until the character that follows the <collected-word> in the grammar.
--------------------------
-
-<file> :== <objects>
-
-<objects> :== <object>
- | <objects> <object>
-
-
-<object> :== <context>
- | <macro>
- | <globals>
- | ';'
-
-
-<context> :== 'context' <word> '{' <elements> '}'
- | 'context' <word> '{' '}'
- | 'context' 'default' '{' <elements> '}'
- | 'context' 'default' '{' '}'
- | 'abstract' 'context' <word> '{' <elements> '}'
- | 'abstract' 'context' <word> '{' '}'
- | 'abstract' 'context' 'default' '{' <elements> '}'
- | 'abstract' 'context' 'default' '{' '}'
-
-
-<macro> :== 'macro' <word> '(' <arglist> ')' '{' <macro_statements> '}'
- | 'macro' <word> '(' <arglist> ')' '{' '}'
- | 'macro' <word> '(' ')' '{' <macro_statements> '}'
- | 'macro' <word> '(' ')' '{' '}'
-
-
-<globals> :== 'globals' '{' <global_statements> '}'
- | 'globals' '{' '}'
-
-
-<global_statements> :== <global_statement>
- | <global_statements> <global_statement>
-
-
-<global_statement> :== <word> '=' <collected-word> ';'
-
-
-<arglist> :== <word>
- | <arglist> ',' <word>
-
-
-<elements> :== <element>
- | <elements> <element>
-
-
-<element> :== <extension>
- | <includes>
- | <switches>
- | <eswitches>
- | <ignorepat>
- | <word> '=' <collected-word> ';'
- | 'local' <word> '=' <collected-word> ';'
- | ';'
-
-
-<ignorepat> :== 'ignorepat' '=>' <word> ';'
-
-
-<extension> :== <word> '=>' <statement>
- | 'regexten' <word> '=>' <statement>
- | 'hint' '(' <word3-list> ')' <word> '=>' <statement>
- | 'regexten' 'hint' '(' <word3-list> ')' <word> '=>' <statement>
-
-
-<statements> :== <statement>
- | <statements> <statement>
-
-<if_head> :== 'if' '(' <collected-word> ')'
-
-<random_head> :== 'random' '(' <collected-word> ')'
-
-<ifTime_head> :== 'ifTime' '(' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')'
- | 'ifTime' '(' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')'
-
-
-<word3-list> :== <word>
- | <word> <word>
- | <word> <word> <word>
-
-<switch_head> :== 'switch' '(' <collected-word> ')' '{'
-
-
-<statement> :== '{' <statements> '}'
- | <word> '=' <collected-word> ';'
- | 'local' <word> '=' <collected-word> ';'
- | 'goto' <target> ';'
- | 'jump' <jumptarget> ';'
- | <word> ':'
- | 'for' '(' <collected-word> ';' <collected-word> ';' <collected-word> ')' <statement>
- | 'while' '(' <collected-word> ')' <statement>
- | <switch_head> '}'
- | <switch_head> <case_statements> '}'
- | '&' macro_call ';'
- | <application_call> ';'
- | <application_call> '=' <collected-word> ';'
- | 'break' ';'
- | 'return' ';'
- | 'continue' ';'
- | <random_head> <statement>
- | <random_head> <statement> 'else' <statement>
- | <if_head> <statement>
- | <if_head> <statement> 'else' <statement>
- | <ifTime_head> <statement>
- | <ifTime_head> <statement> 'else' <statement>
- | ';'
-
-<target> :== <word>
- | <word> '|' <word>
- | <word> '|' <word> '|' <word>
- | 'default' '|' <word> '|' <word>
- | <word> ',' <word>
- | <word> ',' <word> ',' <word>
- | 'default' ',' <word> ',' <word>
-
-<jumptarget> :== <word>
- | <word> ',' <word>
- | <word> ',' <word> '@' <word>
- | <word> '@' <word>
- | <word> ',' <word> '@' 'default'
- | <word> '@' 'default'
-
-<macro_call> :== <word> '(' <eval_arglist> ')'
- | <word> '(' ')'
-
-<application_call_head> :== <word> '('
-
-<application_call> :== <application_call_head> <eval_arglist> ')'
- | <application_call_head> ')'
-
-<eval_arglist> :== <collected-word>
- | <eval_arglist> ',' <collected-word>
- | /* nothing */
- | <eval_arglist> ',' /* nothing */
-
-<case_statements> :== <case_statement>
- | <case_statements> <case_statement>
-
-
-<case_statement> :== 'case' <word> ':' <statements>
- | 'default' ':' <statements>
- | 'pattern' <word> ':' <statements>
- | 'case' <word> ':'
- | 'default' ':'
- | 'pattern' <word> ':'
-
-<macro_statements> :== <macro_statement>
- | <macro_statements> <macro_statement>
-
-<macro_statement> :== <statement>
- | 'catch' <word> '{' <statements> '}'
-
-<switches> :== 'switches' '{' <switchlist> '}'
- | 'switches' '{' '}'
-
-<eswitches> :== 'eswitches' '{' <switchlist> '}'
- | 'eswitches' '{' '}'
-
-<switchlist> :== <word> ';'
- | <switchlist> <word> ';'
-
-<includeslist> :== <includedname> ';'
- | <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
- | <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
- | <includeslist> <includedname> ';'
- | <includeslist> <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
- | <includeslist> <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';'
-
-<includedname> :== <word>
- | 'default'
-
-<includes> :== 'includes' '{' <includeslist> '}'
- | 'includes' '{' '}'
-\end{verbatim}
-\end{astlisting}
-
-\section{AEL Example USAGE}
-
-\subsection{Comments}
-
-Comments begin with // and end with the end of the line.
-
-Comments are removed by the lexical scanner, 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 terminating semicolons, or on otherwise empty lines.
-
-
-\subsection{Context}
-
-Contexts in AEL represent a set of extensions in the same way that
-they do in extensions.conf.
-\begin{astlisting}
-\begin{verbatim}
-context default {
-
-}
-\end{verbatim}
-\end{astlisting}
-
-A context can be declared to be "abstract", in which case, this
-declaration expresses the intent of the writer, that this context will
-only be included by another context, and not "stand on its own". The
-current effect of this keyword is to prevent "goto " statements from
-being checked.
-\begin{astlisting}
-\begin{verbatim}
-abstract context longdist {
- _1NXXNXXXXXX => NoOp(generic long distance dialing actions in the US);
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{Extensions}
-
-To specify an extension in a context, the following syntax is used. If
-more than one application is be called in an extension, they can be
-listed in order inside of a block.
-\begin{astlisting}
-\begin{verbatim}
-context default {
- 1234 => Playback(tt-monkeys);
- 8000 => {
- NoOp(one);
- NoOp(two);
- NoOp(three);
- };
- _5XXX => NoOp(it's a pattern!);
-}
-\end{verbatim}
-\end{astlisting}
-
-Two optional items have been added to the AEL syntax, that allow the
-specification of hints, and a keyword, regexten, that will force the
-numbering of priorities to start at 2.
-
-The ability to make extensions match by CID is preserved in
-AEL; just use '/' and the CID number in the specification. See below.
-\begin{astlisting}
-\begin{verbatim}
-context default {
-
- regexten _5XXX => NoOp(it's a pattern!);
-}
-\end{verbatim}
-\end{astlisting}
-
-\begin{astlisting}
-\begin{verbatim}
-context default {
-
- hint(Sip/1) _5XXX => NoOp(it's a pattern!);
-}
-\end{verbatim}
-\end{astlisting}
-
-\begin{astlisting}
-\begin{verbatim}
-context default {
-
- regexten hint(Sip/1) _5XXX => NoOp(it's a pattern!);
-}
-\end{verbatim}
-\end{astlisting}
-
-The regexten must come before the hint if they are both present.
-
-CID matching is done as with the extensions.conf file. Follow the extension
-name/number with a slash (/) and the number to match against the Caller ID:
-\begin{astlisting}
-\begin{verbatim}
-context zoombo
-{
- 819/7079953345 => { NoOp(hello, 3345); }
-}
-\end{verbatim}
-\end{astlisting}
-
-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 those who wish 819, that are not so lucky
-as to have 7079953345 as their CallerID!
-
-
-\subsection{Includes}
-
-Contexts can be included in other contexts. All included contexts are
-listed within a single block.
-
-\begin{astlisting}
-\begin{verbatim}
-context default {
- includes {
- local;
- longdistance;
- international;
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-Time-limited inclusions can be specified, as in extensions.conf
-format, with the fields described in the wiki page Asterisk cmd
-GotoIfTime.
-
-\begin{astlisting}
-\begin{verbatim}
-context default {
- includes {
- local;
- longdistance|16:00-23:59|mon-fri|*|*;
- international;
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{\#include}
-
-You can include other files with the \#include "filepath" construct.
-
-\begin{astlisting}
-\begin{verbatim}
- #include "/etc/asterisk/testfor.ael"
-\end{verbatim}
-\end{astlisting}
-
-An interesting property of the \#include, is that you can use it almost
-anywhere in the .ael file. It is possible to include the contents of
-a file in a macro, context, or even extension. The \#include does not
-have to occur at the beginning of a line. Included files can include
-other files, up to 50 levels deep. If the path provided in quotes is a
-relative path, the parser looks in the config file directory for the
-file (usually \path{/etc/asterisk}).
-
-
-
-\subsection{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.
-
-\begin{astlisting}
-\begin{verbatim}
-context default {
- switches {
- DUNDi/e164;
- IAX2/box5;
- };
- eswitches {
- IAX2/context@${CURSERVER};
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{Ignorepat}
-
-ignorepat can be used to instruct channel drivers to not cancel
-dialtone upon receipt of a particular pattern. The most commonly used
-example is '9'.
-\begin{astlisting}
-\begin{verbatim}
-context outgoing {
- ignorepat => 9;
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{Variables}
-
-Variables in Asterisk do not have a type, so to define a variable, it
-just has to be specified with a value.
-
-Global variables are set in their own block.
-
-\begin{astlisting}
-\begin{verbatim}
-globals {
- CONSOLE=Console/dsp;
- TRUNK=DAHDI/g2;
-}
-\end{verbatim}
-\end{astlisting}
-
-Variables can be set within extensions as well.
-
-\begin{astlisting}
-\begin{verbatim}
-context foo {
- 555 => {
- x=5;
- y=blah;
- divexample=10/2
- NoOp(x is ${x} and y is ${y} !);
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-NOTE: AEL wraps the right hand side of an assignment with \$[ ] to allow
-expressions to be used If this is unwanted, you can protect the right hand
-side from being wrapped by using the Set() 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; the middle expression in the for( x; y; z) statement
-(the y expression); Assignments - the right hand side, so a = b -$>$ Set(a=\$[b])
-
-Writing to a dialplan function is treated the same as writing to a variable.
-
-\begin{astlisting}
-\begin{verbatim}
-context blah {
- s => {
- CALLERID(name)=ChickenMan;
- NoOp(My name is ${CALLERID(name)} !);
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-You can declare variables in Macros, as so:
-
-\begin{astlisting}
-\begin{verbatim}
-Macro myroutine(firstarg, secondarg)
-{
- Myvar=1;
- NoOp(Myvar is set to ${myvar});
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{Local Variables}
-
-In 1.2, and 1.4, ALL VARIABLES are CHANNEL variables, including the function
-arguments and associated ARG1, ARG2, etc variables. Sorry.
-
-In trunk (1.6 and higher), we have made all arguments local variables to
-a macro call. They will not affect channel variables of the same name.
-This includes the ARG1, ARG2, etc variables.
-
-Users can declare their own local variables by using the keyword 'local'
-before setting them to a value;
-
-\begin{astlisting}
-\begin{verbatim}
-Macro myroutine(firstarg, secondarg)
-{
- local Myvar=1;
- NoOp(Myvar is set to ${Myvar}, and firstarg is ${firstarg}, and secondarg is ${secondarg});
-}
-\end{verbatim}
-\end{astlisting}
-
-In the above example, Myvar, firstarg, and secondarg are all local variables,
-and will not be visible to the calling code, be it an extension, or another Macro.
-
-If you need to make a local variable within the Set() application, you can do it this way:
-\begin{astlisting}
-\begin{verbatim}
-Macro myroutine(firstarg, secondarg)
-{
- Set(LOCAL(Myvar)=1);
- NoOp(Myvar is set to ${Myvar}, and firstarg is ${firstarg}, and secondarg is ${secondarg});
-}
-\end{verbatim}
-\end{astlisting}
-
-\subsection{Loops}
-
-AEL has implementations of 'for' and 'while' loops.
-\begin{astlisting}
-\begin{verbatim}
-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;
- }
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-NOTE: The conditional expression (the "\$\{y\} $>$= 0" above) is wrapped in
- \$[ ] so it can be evaluated. NOTE: The for loop test expression
- (the "\${x} $<$ 3" above) is wrapped in \$[ ] so it can be evaluated.
-
-
-
-\subsection{Conditionals}
-
-AEL supports if and switch statements, like AEL, but adds ifTime, and
-random. Unlike the original AEL, though, you do NOT need to put curly
-braces around a single statement in the "true" branch of an if(), the
-random(), or an ifTime() statement. The if(), ifTime(), and random()
-statements allow optional else clause.
-
-\begin{astlisting}
-\begin{verbatim}
-context conditional {
- _8XXX => {
- Dial(SIP/${EXTEN});
- if ("${DIALSTATUS}" = "BUSY")
- {
- NoOp(yessir);
- Voicemail(${EXTEN},b);
- }
- else
- Voicemail(${EXTEN},u);
- ifTime (14:00-25:00,sat-sun,*,*)
- 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( This should appear 30% of the 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!);
- }
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-NOTE: The conditional expression in if() statements (the
- "\$\{DIALSTATUS\}" = "BUSY" above) is wrapped by the compiler in
- \$[] for evaluation.
-
-NOTE: Neither the switch nor case values are wrapped in \$[ ]; they can
- be constants, or \$\{var\} type references only.
-
-NOTE: AEL 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: AEL introduces the ifTime keyword/statement, which works just
- like the if() statement, but the expression is a time value,
- exactly like that used by the application GotoIfTime(). See
- Asterisk cmd GotoIfTime
-
-NOTE: The pattern statement makes sure the new extension that is
- created has an '\_' preceding it to make sure asterisk recognizes
- the extension name as a pattern.
-
-NOTE: Every character enclosed by the switch expression's parenthesis
- are included verbatim in the labels generated. So watch out for
- spaces!
-
-NOTE: NEW: Previous to version 0.13, the random statement used the
- "Random()" application, which has been deprecated. It now uses
- the RAND() function instead, in the GotoIf application.
-
-
-\subsection{Break, Continue, and Return}
-
-Three keywords, break, continue, and return, are included in the
-syntax to provide flow of control 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. In the case of a for loop, the increment and
-test will then be performed. In the case of the while loop, the
-continue will jump to the test at the top of the loop.
-
-The return keyword will cause an immediate jump to the end of the
-context, or macro, and can be used anywhere.
-
-
-
-\subsection{goto, jump, and labels}
-
-This is an example of how to do a goto in AEL.
-
-\begin{astlisting}
-\begin{verbatim}
-context gotoexample {
- s => {
-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
- }
-}
-
-context gotoexample2 {
- s => {
- end:
- goto gotoexample,s,begin; // go to label in different context
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-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" in goto's or
-jumps, nor would I advise declaring a "1" label anywhere! As a matter
-of fact, it would be bad form to declare a numeric label, and it might
-conflict with the priority numbers used internally by asterisk.
-
-The syntax of the jump statement is: jump
-extension[,priority][@context] If priority is absent, it defaults to
-"1". If context is not present, it is assumed to be the same as that
-which contains the "jump".
-
-\begin{astlisting}
-\begin{verbatim}
-context gotoexample {
- s => {
-begin:
- NoOp(Infinite Loop! yay!);
- Wait(1);
- jump s; // go to first extension in same extension
- }
- 3 => {
- jump s,begin; // go to label in different extension
- }
- 4 => {
- jump s,begin@gotoexample; // overkill go to label in same context
- }
-}
-
-context gotoexample2 {
- s => {
- end:
- jump s@gotoexample; // go to label in different context
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-NOTE: goto labels follow the same requirements as the Goto()
- application, except the last value has to be a label. If the
- label does not exist, you will have run-time errors. If the
- label exists, but in 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 about using goto's in a
- switch statement below...
-
-NOTE AEL introduces the special label "1", which is the beginning
- context number for most extensions.
-
-
-\subsection{Macros}
-
-A macro is defined in its own block like this. The arguments to the
-macro are specified with the name of the macro. They are then referred
-to by that same name. A catch block can be specified to catch special
-extensions.
-
-\begin{astlisting}
-\begin{verbatim}
-macro std-exten( ext , dev ) {
- Dial(${dev}/${ext},20);
- switch(${DIALSTATUS) {
- case BUSY:
- Voicemail(${ext},b);
- break;
- default:
- Voicemail(${ext},u);
-
- }
- catch a {
- VoiceMailMain(${ext});
- return;
- }
-}
-\end{verbatim}
-\end{astlisting}
-
-A macro is then called by preceding the macro name with an
-ampersand. Empty arguments can be passed simply with nothing between
-comments(0.11).
-
-\begin{astlisting}
-\begin{verbatim}
-context example {
- _5XXX => &std-exten(${EXTEN}, "IAX2");
- _6XXX => &std-exten(, "IAX2");
- _7XXX => &std-exten(${EXTEN},);
- _8XXX => &std-exten(,);
-}
-\end{verbatim}
-\end{astlisting}
-
-
-\section{Examples}
-
-\begin{astlisting}
-\begin{verbatim}
-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 => {
- Playback(demo-abouttotry);
- Dial(IAX2/guest@misery.digium.com);
- Playback(demo-nogo);
- goto s,instructions;
- }
- 600 => {
- Playback(demo-echotest);
- Echo();
- Playback(demo-echodone);
- goto s,instructions;
- }
- # => {
-hangup:
- Playback(demo-thanks);
- Hangup();
- }
- t => goto #,hangup;
- i => Playback(invalid);
-}
-\end{verbatim}
-\end{astlisting}
-
-
-\section{Semantic Checks}
-
-
-AEL, after parsing, but before compiling, traverses the dialplan
-tree, and makes several checks:
-
-\begin{itemize}
- \item Macro calls to non-existent macros.
- \item Macro calls to contexts.
- \item Macro calls with argument count not matching the definition.
- \item application call to macro. (missing the '\&')
- \item 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.
- \item goto a label in an empty extension.
- \item goto a non-existent label, either a within-extension,
- within-context, or in a different context, or in any included
- contexts. Will even check "sister" context references.
- \item All the checks done on the time values in the dial plan, are
- done on the time values in the ifTime() 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.
- \item (0.5) If an expression is wrapped in \$[ ... ], and the compiler
- will wrap it again, a warning is issued.
- \item (0.5) If an expression had operators (you know,
- +,-,*,/,%,!,etc), but no \${ } variables, a warning is
- issued. Maybe someone forgot to wrap a variable name?
- \item (0.12) check for duplicate context names.
- \item (0.12) check for abstract contexts that are not included by any context.
- \item (0.13) Issue a warning if a label is a numeric value.
-\end{itemize}
-
-There are a subset of checks that have been removed until the proposed
-AAL (Asterisk Argument Language) is developed and incorporated into Asterisk.
-These checks will be:
-
-\begin{itemize}
- \item (if the application argument analyzer is working: the presence
- of the 'j' option is reported as error.
- \item if options are specified, that are not available in an
- application.
- \item if you specify too many arguments to an application.
- \item a required argument is not present in an application call.
- \item 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 is listed.
- \item a Switch construct is used, which is uses a known variable, and
- the application that would set that variable is not called in
- the same extension. This is a warning only...
- \item Calls to applications not in the "applist" database (installed
- in \path{/var/lib/asterisk/applist}" on most systems).
- \item In an assignment statement, if the assignment is to a function,
- the function name used is checked to see if it one of the
- currently known functions. A warning is issued if it is not.
-\end{itemize}
-
-\section{Differences with the original version of AEL}
-
-\begin{enumerate}
- \item The \$[...] expressions have been enhanced to include the ==, $|$$|$,
- and \&\& operators. These operators are exactly equivalent to the
- =, $|$, and \& operators, respectively. Why? So the C, Java, C++
- hackers feel at home here.
- \item It is more free-form. The newline character means very little,
- and is pulled out of the white-space only for line numbers in
- error messages.
- \item It generates more error messages -- by this I mean that any
- difference between the input and the grammar are reported, by
- file, line number, and column.
- \item It checks the contents of \$[ ] expressions (or what will end up
- being \$[ ] expressions!) for syntax errors. It also does
- matching paren/bracket counts.
- \item It runs several semantic checks after the parsing is over, but
- before the compiling begins, see the list above.
- \item 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 be included in
- files that are included in files, down to 50 levels of hierarchy...
- \item Local Goto's inside Switch statements automatically have the
- extension of the location of the switch statement appended to them.
- \item A pretty printer function is available within pbx\_ael.so.
- \item In the utils directory, two standalone programs are supplied for
- debugging AEL files. One is called "aelparse", and it reads in
- the \path{/etc/asterisk/extensions.ael} file, and shows the results of
- syntax and semantic checking on stdout, and also shows the
- results of compilation to stdout. The other is "aelparse1",
- which uses the original ael compiler to do the same work,
- reading in "\path{/etc/asterisk/extensions.ael}", using the original
- 'pbx\_ael.so' instead.
- \item AEL supports the "jump" statement, and the "pattern" statement
- in switch constructs. Hopefully these will be documented in the
- AEL README.
- \item Added the "return" keyword, which will jump to the end of an
- extension/Macro.
- \item Added the ifTime ($<$time range$>$$|$$<$days of week$>$$|$$<$days of
- month$>$$|$$<$months$>$ ) {} [else {}] construct, which executes much
- like an if () statement, but the decision is based on the
- 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)
- \item Added the optional time spec to the contexts in the includes
- construct. See examples above.
- \item You don't have to wrap a single "true" statement in curly
- braces, as in the original AEL. An "else" is attached to the
- closest if. As usual, be careful about nested if statements!
- When in doubt, use curlies!
- \item Added the syntax [regexten] [hint(channel)] to precede an
- extension declaration. See examples above, under
- "Extension". The regexten keyword will cause the priorities in
- the extension to begin with 2 instead of 1. The hint keyword
- will cause its arguments to be inserted in the extension under
- the hint priority. They are both optional, of course, but the
- order is fixed at the moment-- the regexten must come before the
- hint, if they are both present.
- \item Empty case/default/pattern statements will "fall thru" as
- expected. (0.6)
- \item 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)
- \item (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 be rejected as a syntax
- error, maybe.
- \item (0.9) the // comments are not recognized and removed in the
- spots where expressions are gathered, nor in application call
- arguments. You may have to move a comment if you get errors in
- existing files.
- \item (0.10) the random statement has been added. Syntax: random (
- $<$expr$>$ ) $<$lucky-statement$>$ [ else $<$unlucky-statement$>$ ]. The
- probability of the lucky-statement getting executed is $<$expr$>$,
- which should evaluate to an integer between 0 and 100. If the
- $<$lucky-statement$>$ isn't so lucky this time around, then the
- $<$unlucky-statement$>$ gets executed, if it is present.
-\end{enumerate}
-
-
-\section{Hints and Bugs}
-
- The safest way to check for a null strings is to say \$[ "\$\{x\}" =
- "" ] The old way would do as shell scripts often do, and append
- something on both sides, like this: \$[ \$\{x\}foo = foo ]. The
- trouble with the old way, is that, if x contains any spaces, then
- problems occur, usually syntax errors. It is better practice and
- safer wrap all such tests with double quotes! Also, there are now
- some functions that can be used in a variable reference,
- ISNULL(), and LEN(), that can be used to test for an empty string:
- \$\{ISNULL(\$\{x\})\} or \$[ \$\{LEN(\$\{x\})\} = 0 ].
-
- Assignment vs. Set(). Keep in mind that setting a variable to
- value can be done two different ways. If you choose say 'x=y;',
- keep in mind that AEL will wrap the right-hand-side with
- \$[]. So, when compiled into extension language format, the end
- result will be 'Set(x=\$[y])'. If you don't want this effect,
- then say "Set(x=y);" instead.
-
-
-\section{The Full Power of AEL}
-
-A newcomer to Asterisk will look at the above constructs and
-descriptions, and ask, "Where's the string manipulation functions?",
-"Where's all the cool operators that other languages have to offer?",
-etc.
-
-The answer is that the rich capabilities of Asterisk are made
-available through AEL, via:
-
-\begin{itemize}
- \item Applications: See Asterisk - documentation of application
- commands
-
- \item Functions: Functions were implemented inside \$\{ .. \} variable
- references, and supply many useful capabilities.
-
- \item Expressions: An expression evaluation engine handles items
- wrapped inside \$[...]. This includes some string manipulation
- facilities, arithmetic expressions, etc.
-
- \item Application Gateway Interface: Asterisk can fork external
- processes that communicate via pipe. AGI applications can be
- written in any language. Very powerful applications can be added
- this way.
-
- \item Variables: Channels of communication have variables associated
- with them, and asterisk provides some global variables. These can be
- manipulated and/or consulted by the above mechanisms.
-\end{itemize}