mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-26 22:30:28 +00:00 
			
		
		
		
	git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3354 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			285 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			285 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
| EXTENSION LOGIC : 
 | |
| 
 | |
| There are two levels of parameter evaluation done in asterisk in 
 | |
| extensions.conf.
 | |
| The first, and most frequently used, is the substitution of variable
 | |
| references with their values. 
 | |
| 
 | |
| Then there are the evaluations done in $[ .. ]. This will be
 | |
| discussed below.
 | |
| 
 | |
| ___________________________
 | |
| PARAMETER QUOTING: 
 | |
| ---------------------------
 | |
| 
 | |
| exten => s,5,BackGround,blabla
 | |
| 
 | |
| The parameter (blabla) can be quoted ("blabla"). In this case, a 
 | |
| comma does not terminate the field. However, the double quotes
 | |
| will be passed down to the Background command, in this example.
 | |
| 
 | |
| Also, characters special to variable substitution, expression evaluation, etc
 | |
| (see below), can be quoted. For example, to literally use a $ on the 
 | |
| string "$1231", quote it with a preceding \. Special characters that must
 | |
| be quoted to be used, are [ ] $ " \. (to write \ itself, use \\). 
 | |
| 
 | |
| These Double quotes and escapes are evaluated at the level of the
 | |
| asterisk config file parser. 
 | |
| 
 | |
| Double quotes can also be used inside expressions, as discussed below.
 | |
| 
 | |
| 
 | |
| ___________________________
 | |
| VARIABLES: 
 | |
| ---------------------------
 | |
| 
 | |
| Parameter strings can include variables. Variable names are arbitrary strings. 
 | |
| They are stored in the respective channel structure. 
 | |
| 
 | |
| To set a variable to a particular value, do : 
 | |
| 
 | |
| ;exten => 1,2,SetVar,varname=value
 | |
| 
 | |
| You can substitute the value of a variable everywhere using ${variablename}.
 | |
| For example, to stringwise append $lala to $blabla and store result in $koko, 
 | |
| do: 
 | |
| 
 | |
| ;exten => 1,2,SetVar,koko=${blabla}${lala}
 | |
| 
 | |
| There are also the following special variables: 
 | |
| 
 | |
| ${ACCOUNTCODE} 	Account code (if specified)
 | |
| ${CALLERID}	Caller ID
 | |
| ${CALLERIDNAME}	Caller ID Name only
 | |
| ${CALLERIDNUM}	Caller ID Number only
 | |
| ${CHANNEL}	Current channel name
 | |
| ${CONTEXT}      Current context
 | |
| ${DATETIME}	Current date time in the format: YYYY-MM-DD_HH:MM:SS
 | |
| ${DNID}         Dialed Number Identifier
 | |
| ${ENUM}		Result of application EnumLookup
 | |
| ${EPOCH}	Current unix style epoch
 | |
| ${EXTEN}	Current extension
 | |
| ${ENV(VAR)}	Environmental variable VAR
 | |
| ${HANGUPCAUSE}	Asterisk hangup cause
 | |
| ${INVALID_EXTEN}The invalid called extension (used in the "i" extension)
 | |
| ${LANGUAGE}	Current language
 | |
| ${LEN(VAR)}	String length of VAR (integer)
 | |
| ${MEETMESECS} 	Number of seconds a user participated in a MeetMe conference
 | |
| ${PRIORITY}	Current priority
 | |
| ${RDNIS}        Redirected Dial Number ID Service
 | |
| ${SIPCALLID} 	SIP Call-ID: header verbatim (for logging or CDR matching)
 | |
| ${SIPDOMAIN}    SIP destination domain of an inbound call (if appropriate)
 | |
| ${SIPUSERAGENT} SIP user agent 
 | |
| ${TIMESTAMP}	Current date time in the format: YYYYMMDD-HHMMSS
 | |
| ${TXTCIDNAME}	Result of application TXTCIDName
 | |
| ${UNIQUEID}	Current call unique identifier
 | |
| 
 | |
| There are two reference modes - reference by value and reference by name. 
 | |
| To refer to a variable with its name (as an argument to a function that 
 | |
| requires a variable), just write the name. To refer to the variable's value, 
 | |
| enclose it inside ${}. For example, SetVar takes as the first argument 
 | |
| (before the =) a variable name, so: 
 | |
| 
 | |
| ;exten => 1,2,SetVar,koko=lala
 | |
| ;exten => 1,3,SetVar,${koko}=blabla
 | |
| 
 | |
| stores to the variable "koko" the value "lala" and to variable "lala" the 
 | |
| value "blabla". 
 | |
| 
 | |
| In fact, everything contained ${here} is just replaced with the value of 
 | |
| the variable "here". 
 | |
| 
 | |
| ___________________________
 | |
| EXPRESSIONS: 
 | |
| ---------------------------
 | |
| 
 | |
| Everything contained inside a bracket pair prefixed by a $ (like $[this]) is 
 | |
| considered as an expression and it is evaluated. Evaluation works similar to 
 | |
| (but is done on a later stage than) variable substitution: the expression 
 | |
| (including the square brackets) is replaced by the result of the expression 
 | |
| evaluation. The arguments and operands of the expression MUST BE separated 
 | |
| by at least one space. 
 | |
| 
 | |
| 
 | |
| For example, after the sequence: 
 | |
| 
 | |
| exten => 1,1,SetVar,"lala=$[1 + 2]";
 | |
| exten => 1,2,SetVar,"koko=$[2 * ${lala}]";
 | |
| 
 | |
| the value of variable koko is "6".
 | |
| 
 | |
| And, further:
 | |
| 
 | |
| exten => 1,1,SetVar,"lala=$[1+2]";
 | |
| 
 | |
| will not work as you might have expected. Since all the chars in the single 
 | |
| token "1+2" are not numbers, it will be evaluated as the string "1+2". Again,
 | |
| please do not forget, that this is a very simple parsing engine, and it
 | |
| uses a space (at least one), to separate "tokens".
 | |
| 
 | |
| and, further:
 | |
| 
 | |
| exten => 1,1,SetVar,"lala=$[  1 +    2   ]";
 | |
| 
 | |
| will parse as intended. Extra spaces are ignored.
 | |
| 
 | |
| ___________________________
 | |
| SPACES INSIDE VARIABLE
 | |
| ---------------------------
 | |
| If the variable being evaluated contains spaces, there can be problems.
 | |
| 
 | |
| For these cases, double quotes around text that may contain spaces
 | |
| will force the surrounded text to be evaluated as a single token.
 | |
| The double quotes will be counted as part of that lexical token.
 | |
| 
 | |
| As an example:
 | |
| 
 | |
| exten => s,6,GotoIf($[ "${CALLERIDNAME}" : "Privacy Manager" ]?callerid-liar|s|1:s|7)
 | |
| 
 | |
| The variable CALLERIDNAME could evaluate to "DELOREAN MOTORS" (with a space)
 | |
| but the above will evaluate to:
 | |
| 
 | |
| "DELOREAN MOTORS" : "Privacy Manager"
 | |
| 
 | |
| and will evaluate to 0.
 | |
| 
 | |
| The above without double quotes would have evaluated to:
 | |
| 
 | |
| DELOREAN MOTORS : Privacy Manager
 | |
| 
 | |
| and will result in syntax errors, because token DELOREAN is immediately
 | |
| followed by token MOTORS and the expression parser will not know how to 
 | |
| evaluate this expression.
 | |
| 
 | |
| _____________________
 | |
| OPERATORS
 | |
| ---------------------
 | |
| Operators are listed below in order of increasing precedence.  Operators
 | |
| with equal precedence are grouped within { } symbols.
 | |
| 
 | |
|      expr1 | expr2
 | |
|              Return the evaluation of expr1 if it is neither an empty string
 | |
|              nor zero; otherwise, returns the evaluation of expr2.
 | |
| 
 | |
|      expr1 & expr2
 | |
|              Return the evaluation of expr1 if neither expression evaluates to
 | |
|              an empty string or zero; otherwise, returns zero.
 | |
| 
 | |
|      expr1 {=, >, >=, <, <=, !=} expr2
 | |
|              Return the results of integer comparison if both arguments are
 | |
|              integers; otherwise, returns the results of string comparison
 | |
|              using the locale-specific collation sequence.  The result of each
 | |
|              comparison is 1 if the specified relation is true, or 0 if the
 | |
|              relation is false.
 | |
| 
 | |
|      expr1 {+, -} expr2
 | |
|              Return the results of addition or subtraction of integer-valued
 | |
|              arguments.
 | |
| 
 | |
|      expr1 {*, /, %} expr2
 | |
|              Return the results of multiplication, integer division, or
 | |
|              remainder of integer-valued arguments.
 | |
| 
 | |
|      expr1 : expr2
 | |
|              The `:' operator matches expr1 against expr2, which must be a
 | |
|              regular expression.  The regular expression is anchored to the
 | |
|              beginning of  the string with an implicit `^'.
 | |
| 
 | |
|              If the match succeeds and the pattern contains at least one regu-
 | |
|              lar expression subexpression `\(...\)', the string correspond-
 | |
|              ing to `\1' is returned; otherwise the matching operator
 | |
|              returns the number of characters matched.  If the match fails and
 | |
|              the pattern contains a regular expression subexpression the null
 | |
|              string is returned; otherwise 0.
 | |
| 
 | |
| Parentheses are used for grouping in the usual manner.
 | |
| 
 | |
| The parser must be parsed with bison (bison is REQUIRED - yacc cannot 
 | |
| produce pure parsers, which are reentrant) 
 | |
| 
 | |
| ___________________________
 | |
| CONDITIONALS
 | |
| ---------------------------
 | |
| 
 | |
| There is one conditional operator - the conditional goto : 
 | |
| 
 | |
| ;exten => 1,2,gotoif,condition?label1:label2
 | |
| 
 | |
| If condition is true go to label1, else go to label2. Labels are interpreted
 | |
| exactly as in the normal goto command.
 | |
| 
 | |
| "condition" is just a string. If the string is empty or "0", the condition
 | |
| is considered to be false, if it's anything else, the condition is true. 
 | |
| This is designed to be used together with the expression syntax described 
 | |
| above, eg : 
 | |
| 
 | |
| exten => 1,2,gotoif,$[${CALLERID} = 123456]?2|1:3|1
 | |
| 
 | |
| 
 | |
| Example of use : 
 | |
| 
 | |
| exten => s,2,SetVar,"vara=1"
 | |
| exten => s,3,SetVar,"varb=$[${vara} + 2]"
 | |
| exten => s,4,SetVar,"varc=$[${varb} * 2]"
 | |
| exten => s,5,GotoIf,"$[${varc} = 6]?99|1:s|6";
 | |
| 
 | |
| ___________________________
 | |
| PARSE ERRORS
 | |
| ---------------------------
 | |
| 
 | |
| Syntax errors are now output with 3 lines.
 | |
| 
 | |
| If the extensions.conf file contains a line like:
 | |
| 
 | |
| exten => s,6,GotoIf($[ "${CALLERIDNUM}"  = "3071234567" & "${CALLERIDNAME}" : "Privacy Manager" ]?callerid-liar|s|1:s|7)
 | |
| 
 | |
| You may see an error in /var/log/asterisk/messages like this:
 | |
| 
 | |
| May  3 15:58:53 WARNING[1234455344]: ast_yyerror(): syntax error: parse error; Input:
 | |
|  "3072312154"  : "3071234567" & & "Steves Extension" : "Privacy Manager"
 | |
|  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | |
|                                   ^
 | |
| 
 | |
| The first line shows the string passed to the expression parser. This
 | |
| string is the result of the variable replacements, etc. This way, you
 | |
| can see the actual string that went into the parser.
 | |
| 
 | |
| The second line usually shows a string of '^' chars, that show what's
 | |
| been legally parsed so far.
 | |
| 
 | |
| And the third line shows where the parser was (lookahead token lexing,
 | |
| etc), when the parse hit the rocks. A single '^' here. The error is
 | |
| going to be somewhere between the last '^' on the second line, and the
 | |
| '^' on the third line. That's right, in the example above, there are two
 | |
| '&' chars, separated by a space, and this is a definite no-no!
 | |
| 
 | |
| 
 | |
| ___________________________
 | |
| NULL STRINGS
 | |
| ---------------------------
 | |
| 
 | |
| Testing to see if a string is null can be done in one of two different ways:
 | |
| 
 | |
| exten => _XX.,1,GotoIf($["${calledid}" != ""]?3) 
 | |
| 
 | |
| exten => _XX.,1,GotoIf($[foo${calledid} != foo]?3) 
 | |
| 
 | |
| 
 | |
| The second example above is the way suggested by the WIKI. It will 
 | |
| work as long as there are no spaces in the evaluated value.
 | |
| 
 | |
| The first way should work in all cases, and indeed, might now
 | |
| be the safest way to handle this situation.
 | |
| 
 | |
| ___________________________
 | |
| WARNING
 | |
| ---------------------------
 | |
| 
 | |
| If you need to do complicated things with strings, asterisk expressions
 | |
| is most likely NOT the best way to go about it. AGI scripts are an
 | |
| excellent option to this need, and make available the full power of
 | |
| whatever language you desire, be it Perl, C, C++, Cobol, RPG, Java,
 | |
| Snobol, PL/I, Scheme, Common Lisp, Shell scripts, Tcl, Forth, Modula,
 | |
| Pascal, APL, assembler, etc.
 | |
| 
 |