dect
/
asterisk
Archived
13
0
Fork 0

Merge Steve Murphy's (murf) complete re-implementation of AEL, which is now no longer considered experimental :-)

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@22273 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
kpfleming 2006-04-24 17:41:27 +00:00
parent e196b45892
commit 6baa8fbab8
43 changed files with 21298 additions and 2290 deletions

View File

@ -76,7 +76,7 @@ Olle E. Johansson - SIP RFC compliance, documentation and testing, testing, test
Steve Kann - new jitter buffer for IAX2
stevek@stevek.com
Constantine Filin - major contributions to the Asterisk Realtime Architecture
Steve Murphy - privacy support
Steve Murphy - privacy support, $[ ] parser upgrade, AEL2 parser upgrade
Claude Patry - bug fixes, feature enhancements, and bug marshalling
cpatry@gmail.com

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
/*! \file
*
* \brief Dialplan Expression Parser
* \brief Dialplan Expression Lexical Scanner
*/
#include <sys/types.h>
@ -73,6 +73,7 @@ struct parse_io
void ast_yyset_column(int column_no, yyscan_t yyscanner);
int ast_yyget_column(yyscan_t yyscanner);
static int curlycount = 0;
static char *expr2_token_subst(char *mess);
%}
%option prefix="ast_yy"
@ -89,6 +90,10 @@ static int curlycount = 0;
\| { SET_COLUMNS; SET_STRING; return TOK_OR;}
\& { SET_COLUMNS; SET_STRING; return TOK_AND;}
\= { SET_COLUMNS; SET_STRING; return TOK_EQ;}
\|\| { SET_COLUMNS; SET_STRING; return TOK_OR;}
\&\& { SET_COLUMNS; SET_STRING; return TOK_AND;}
\=\= { SET_COLUMNS; SET_STRING; return TOK_EQ;}
\=~ { SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
\> { SET_COLUMNS; SET_STRING; return TOK_GT;}
\< { SET_COLUMNS; SET_STRING; return TOK_LT;}
\>\= { SET_COLUMNS; SET_STRING; return TOK_GE;}
@ -100,6 +105,7 @@ static int curlycount = 0;
\/ { SET_COLUMNS; SET_STRING; return TOK_DIV;}
\% { SET_COLUMNS; SET_STRING; return TOK_MOD;}
\? { SET_COLUMNS; SET_STRING; return TOK_COND;}
\! { SET_COLUMNS; SET_STRING; return TOK_COMPL;}
\: { SET_COLUMNS; SET_STRING; return TOK_COLON;}
\:\: { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
\( { SET_COLUMNS; SET_STRING; return TOK_LP;}
@ -114,14 +120,15 @@ static int curlycount = 0;
[0-9]+ { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */
SET_NUMERIC_STRING;
return TOKEN;}
[a-zA-Z0-9,.';\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;}
[a-zA-Z0-9,.';\\_^$#@]+ {SET_COLUMNS; SET_STRING; return TOKEN;}
<var>[^{}]*\} {curlycount--; if(curlycount < 0){ BEGIN(trail); yymore();} else { yymore();}}
<var>[^{}]*\{ {curlycount++; yymore(); }
<trail>[^-\t\r \n$():?%/+=*<>!|&]* {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN;}
<trail>[-\t\r \n$():?%/+=*<>!|&] {char c = yytext[yyleng-1]; BEGIN(0); unput(c); SET_COLUMNS; SET_STRING; return TOKEN;}
<trail>\$\{ {curlycount = 0; BEGIN(var); yymore(); }
<trail><<EOF>> {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /* actually, if an expr is only a variable ref, this could happen a LOT */}
<trail><<EOF>> {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /*actually, if an expr is only a variable ref, this could happen a LOT */}
%%
@ -175,16 +182,129 @@ int ast_expr(char *expr, char *buf, int length)
return return_value;
}
char extra_error_message[4095];
int extra_error_message_supplied = 0;
void ast_expr_register_extra_error_info(char *message);
void ast_expr_clear_extra_error_info(void);
void ast_expr_register_extra_error_info(char *message)
{
extra_error_message_supplied=1;
strcpy(extra_error_message, message);
}
void ast_expr_clear_extra_error_info(void)
{
extra_error_message_supplied=0;
extra_error_message[0] = 0;
}
static char *expr2_token_equivs1[] =
{
"TOKEN",
"TOK_COND",
"TOK_COLONCOLON",
"TOK_OR",
"TOK_AND",
"TOK_EQ",
"TOK_GT",
"TOK_LT",
"TOK_GE",
"TOK_LE",
"TOK_NE",
"TOK_PLUS",
"TOK_MINUS",
"TOK_MULT",
"TOK_DIV",
"TOK_MOD",
"TOK_COMPL",
"TOK_COLON",
"TOK_EQTILDE",
"TOK_RP",
"TOK_LP"
};
static char *expr2_token_equivs2[] =
{
"<token>",
"?",
"::",
"|",
"&",
"=",
">",
"<",
">=",
"<=",
"!=",
"+",
"-",
"*",
"/",
"%",
"!",
":",
"=~",
")",
"("
};
static char *expr2_token_subst(char *mess)
{
/* calc a length, malloc, fill, and return; yyerror had better free it! */
int len=0,i;
char *p;
char *res, *s,*t;
int expr2_token_equivs_entries = sizeof(expr2_token_equivs1)/sizeof(char*);
for (p=mess; *p; p++) {
for (i=0; i<expr2_token_equivs_entries; i++) {
if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 )
{
len+=strlen(expr2_token_equivs2[i])+2;
p += strlen(expr2_token_equivs1[i])-1;
break;
}
}
len++;
}
res = (char*)malloc(len+1);
res[0] = 0;
s = res;
for (p=mess; *p;) {
int found = 0;
for (i=0; i<expr2_token_equivs_entries; i++) {
if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) {
*s++ = '\'';
for (t=expr2_token_equivs2[i]; *t;) {
*s++ = *t++;
}
*s++ = '\'';
p += strlen(expr2_token_equivs1[i]);
found = 1;
break;
}
}
if( !found )
*s++ = *p++;
}
*s++ = 0;
return res;
}
int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )
{
struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner);
char spacebuf[8000]; /* best safe than sorry */
char spacebuf2[8000]; /* best safe than sorry */
int i=0;
char *s2 = expr2_token_subst((char *)s);
spacebuf[0] = 0;
for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro,
which is the same thing as... get this:
which is the same thing as... get this:
yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column
I was tempted to just use yy_buf_pos in the STATE, but..., well:
a. the yy_buf_pos is the current position in the buffer, which
@ -199,14 +319,15 @@ int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )
#ifdef STANDALONE3
/* easier to read in the standalone version */
printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
s, parseio->string,spacebuf2);
printf("ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
(extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
#else
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",
s, parseio->string,spacebuf2);
ast_log(LOG_WARNING,"ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n",
(extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2);
#endif
#ifndef STANDALONE
ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n");
#endif
free(s2);
return(0);
}

View File

@ -1,7 +1,7 @@
/* A Bison parser, made by GNU Bison 2.1. */
/* A Bison parser, made by GNU Bison 2.1a. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -78,13 +78,15 @@
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 142 "ast_expr2.y"
typedef union YYSTYPE {
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 140 "ast_expr2.y"
{
struct val *val;
} YYSTYPE;
/* Line 1447 of yacc.c. */
#line 88 "ast_expr2.h"
}
/* Line 1536 of yacc.c. */
#line 89 "ast_expr2.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
@ -92,7 +94,7 @@ typedef union YYSTYPE {
#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED)
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE
{
int first_line;

View File

@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <ctype.h>
#if !defined(SOLARIS) && !defined(__CYGWIN__)
#include <err.h>
@ -51,6 +52,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define YYPARSE_PARAM parseio
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
#define YYERROR_VERBOSE 1
extern char extra_error_message[4095];
extern int extra_error_message_supplied;
enum valtype {
AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
@ -129,12 +132,7 @@ int ast_yyerror(const char *,YYLTYPE *, struct parse_io *);
some useful info about the error. Not as easy as it looks, but it
is possible. */
#define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
#define DESTROY(x) { \
if ((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) \
free((x)->u.s); \
(x)->u.s = 0; \
free(x); \
}
#define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
%}
%pure-parser
@ -165,6 +163,11 @@ extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
%token <val> TOKEN
%type <val> start expr
%destructor { free_value($$); } expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ
TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE
TOK_RP TOK_LP
%%
start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
@ -175,6 +178,11 @@ start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(st
((struct parse_io *)parseio)->val->u.s = $1->u.s;
free($1);
}
| {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
((struct parse_io *)parseio)->val->type = AST_EXPR_string;
((struct parse_io *)parseio)->val->u.s = strdup("");
}
;
expr: TOKEN { $$= $1;}
@ -427,11 +435,40 @@ void ast_log(int level, const char *file, int line, const char *function, const
int main(int argc,char **argv) {
char s[4096];
char out[4096];
FILE *infile;
if (ast_expr(argv[1], s, sizeof(s)))
printf("=====%s======\n",s);
if( !argv[1] )
exit(20);
if( access(argv[1],F_OK)== 0 )
{
int ret;
infile = fopen(argv[1],"r");
if( !infile )
{
printf("Sorry, couldn't open %s for reading!\n", argv[1]);
exit(10);
}
while( fgets(s,sizeof(s),infile) )
{
if( s[strlen(s)-1] == '\n' )
s[strlen(s)-1] = 0;
ret = ast_expr(s, out, sizeof(out));
printf("Expression: %s Result: [%d] '%s'\n",
s, ret, out);
}
fclose(infile);
}
else
printf("No result\n");
{
if (ast_expr(argv[1], s, sizeof(s)))
printf("=====%s======\n",s);
else
printf("No result\n");
}
}
#endif
@ -655,7 +692,8 @@ op_plus (struct val *a, struct val *b)
struct val *r;
if (!to_integer (a)) {
ast_log(LOG_WARNING,"non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING,"non-numeric argument\n");
if (!to_integer (b)) {
free_value(a);
free_value(b);
@ -698,7 +736,8 @@ op_minus (struct val *a, struct val *b)
struct val *r;
if (!to_integer (a)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
if (!to_integer (b)) {
free_value(a);
free_value(b);
@ -710,7 +749,8 @@ op_minus (struct val *a, struct val *b)
return (r);
}
} else if (!to_integer(b)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
free_value(b);
return (a);
}
@ -731,7 +771,8 @@ op_negate (struct val *a)
if (!to_integer (a) ) {
free_value(a);
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
return make_integer(0);
}
@ -813,7 +854,8 @@ op_times (struct val *a, struct val *b)
if (!to_integer (a) || !to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
return(make_integer(0));
}
@ -845,12 +887,14 @@ op_div (struct val *a, struct val *b)
if (!to_integer (a)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
return make_integer(0);
} else if (!to_integer (b)) {
free_value(a);
free_value(b);
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
return make_integer(INT_MAX);
}
@ -876,7 +920,8 @@ op_rem (struct val *a, struct val *b)
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
ast_log(LOG_WARNING, "non-numeric argument\n");
if( !extra_error_message_supplied )
ast_log(LOG_WARNING, "non-numeric argument\n");
free_value(a);
free_value(b);
return make_integer(0);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,307 @@
//
// Example AEL config file
//
//
// Static extension configuration file, used by
// the pbx_config module. This is where you configure all your
// inbound and outbound calls in Asterisk.
//
// This configuration file is reloaded
// - With the "extensions reload" command in the CLI
// - With the "reload" command (that reloads everything) in the CLI
// The "Globals" category contains global variables that can be referenced
// in the dialplan with ${VARIABLE} or ${ENV(VARIABLE)} for Environmental
// variables,
// ${${VARIABLE}} or ${text${VARIABLE}} or any hybrid
//
globals {
CONSOLE="Console/dsp"; // Console interface for demo
//CONSOLE=Zap/1
//CONSOLE=Phone/phone0
IAXINFO=guest; // IAXtel username/password
//IAXINFO="myuser:mypass";
TRUNK="Zap/g2"; // Trunk interface
//
// Note the 'g2' in the TRUNK variable above. It specifies which group (defined
// in zapata.conf) to dial, i.e. group 2, and how to choose a channel to use in
// the specified group. The four possible options are:
//
// g: select the lowest-numbered non-busy Zap channel
// (aka. ascending sequential hunt group).
// G: select the highest-numbered non-busy Zap channel
// (aka. descending sequential hunt group).
// r: use a round-robin search, starting at the next highest channel than last
// time (aka. ascending rotary hunt group).
// R: use a round-robin search, starting at the next lowest channel than last
// time (aka. descending rotary hunt group).
//
TRUNKMSD=1; // MSD digits to strip (usually 1 or 0)
//TRUNK=IAX2/user:pass@provider
};
//
// Any category other than "General" and "Globals" represent
// extension contexts, which are collections of extensions.
//
// Extension names may be numbers, letters, or combinations
// thereof. If an extension name is prefixed by a '_'
// character, it is interpreted as a pattern rather than a
// literal. In patterns, some characters have special meanings:
//
// X - any digit from 0-9
// Z - any digit from 1-9
// N - any digit from 2-9
// [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9)
// . - wildcard, matches anything remaining (e.g. _9011. matches
// anything starting with 9011 excluding 9011 itself)
// ! - wildcard, causes the matching process to complete as soon as
// it can unambiguously determine that no other matches are possible
//
// For example the extension _NXXXXXX would match normal 7 digit dialings,
// while _1NXXNXXXXXX would represent an area code plus phone number
// preceeded by a one.
//
// Each step of an extension is ordered by priority, which must
// always start with 1 to be considered a valid extension. The priority
// "next" or "n" means the previous priority plus one, regardless of whether
// the previous priority was associated with the current extension or not.
// The priority "same" or "s" means the same as the previously specified
// priority, again regardless of whether the previous entry was for the
// same extension. Priorities may be immediately followed by a plus sign
// and another integer to add that amount (most useful with 's' or 'n').
// Priorities may then also have an alias, or label, in
// parenthesis after their name which can be used in goto situations
//
// Contexts contain several lines, one for each step of each
// extension, which can take one of two forms as listed below,
// with the first form being preferred. One may include another
// context in the current one as well, optionally with a
// date and time. Included contexts are included in the order
// they are listed.
//
//context name {
// exten-name => {
// application(arg1,arg2,...);
//
// Timing list for includes is
//
// <time range>|<days of week>|<days of month>|<months>
//
// includes {
// daytime|9:00-17:00|mon-fri|*|*;
// };
//
// ignorepat can be used to instruct drivers to not cancel dialtone upon
// receipt of a particular pattern. The most commonly used example is
// of course '9' like this:
//
// ignorepat => 9;
//
// so that dialtone remains even after dialing a 9.
//};
//
// Sample entries for extensions.conf
//
//
context dundi-e164-canonical {
//
// List canonical entries here
//
// 12564286000 => &std-exten(6000,IAX2/foo);
// _125642860XX => Dial(IAX2/otherbox/${EXTEN:7});
};
context dundi-e164-customers {
//
// If you are an ITSP or Reseller, list your customers here.
//
//_12564286000 => Dial(SIP/customer1);
//_12564286001 => Dial(IAX2/customer2);
};
context dundi-e164-via-pstn {
//
// If you are freely delivering calls to the PSTN, list them here
//
//_1256428XXXX => Dial(Zap/g2/${EXTEN:7}); // Expose all of 256-428
//_1256325XXXX => Dial(Zap/g2/${EXTEN:7}); // Ditto for 256-325
};
context dundi-e164-local {
//
// Context to put your dundi IAX2 or SIP user in for
// full access
//
includes {
dundi-e164-canonical;
dundi-e164-customers;
dundi-e164-via-pstn;
};
};
context dundi-e164-switch {
//
// Just a wrapper for the switch
//
switches {
DUNDi/e164;
};
};
context dundi-e164-lookup {
//
// Locally to lookup, try looking for a local E.164 solution
// then try DUNDi if we don't have one.
//
includes {
dundi-e164-local;
dundi-e164-switch;
};
//
};
//
// DUNDi can also be implemented as a Macro instead of using
// the Local channel driver.
//
macro dundi-e164(exten) {
//
// ARG1 is the extension to Dial
//
goto ${exten}|1;
};
//
// Here are the entries you need to participate in the IAXTEL
// call routing system. Most IAXTEL numbers begin with 1-700, but
// there are exceptions. For more information, and to sign
// up, please go to www.gnophone.com or www.iaxtel.com
//
context iaxtel700 {
_91700XXXXXXX => Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel);
};
//
// The SWITCH statement permits a server to share the dialplain with
// another server. Use with care: Reciprocal switch statements are not
// allowed (e.g. both A -> B and B -> A), and the switched server needs
// to be on-line or else dialing can be severly delayed.
//
context iaxprovider {
switches {
// IAX2/user:[key]@myserver/mycontext;
};
};
context trunkint {
//
// International long distance through trunk
//
includes {
dundi-e164-lookup;
};
_9011. => {
&dundi-e164(${EXTEN:4});
Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
};
};
context trunkld {
//
// Long distance context accessed through trunk
//
includes {
dundi-e164-lookup;
};
_91NXXNXXXXXX => {
&dundi-e164(${EXTEN:1});
Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
};
};
context trunklocal {
//
// Local seven-digit dialing accessed through trunk interface
//
_9NXXXXXX => {
Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
};
};
context trunktollfree {
//
// Long distance context accessed through trunk interface
//
_91800NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
_91888NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
_91877NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
_91866NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}});
};
context international {
//
// Master context for international long distance
//
ignorepat => 9;
includes {
longdistance;
trunkint;
};
};
context longdistance {
//
// Master context for long distance
//
ignorepat => 9;
includes {
local;
trunkld;
};
};
context local {
//
// Master context for local, toll-free, and iaxtel calls only
//
ignorepat => 9;
includes {
default;
parkedcalls;
trunklocal;
iaxtel700;
trunktollfree;
iaxprovider;
};
};
//
// You can use an alternative switch type as well, to resolve
// extensions that are not known here, for example with remote
// IAX switching you transparently get access to the remote
// Asterisk PBX
//
// switch => IAX2/user:password@bigserver/local
//
// An "lswitch" is like a switch but is literal, in that
// variable substitution is not performed at load time
// but is passed to the switch directly (presumably to
// be substituted in the switch routine itself)
//
// lswitch => Loopback/12${EXTEN}@othercontext
//
// An "eswitch" is like a switch but the evaluation of
// variable substitution is performed at runtime before
// being passed to the switch routine.
//
// eswitch => IAX2/context@${CURSERVER}
macro std-exten-ael( ext , dev ) {
Dial(${dev}/${ext},20);
@ -21,8 +322,8 @@ context ael-demo {
s => {
Wait(1);
Answer();
TIMEOUT(digit)=5;
TIMEOUT(response)=10;
Set(TIMEOUT(digit)=5);
Set(TIMEOUT(response)=10);
restart:
Background(demo-congrats);
instructions:
@ -36,12 +337,15 @@ instructions:
goto s|instructions;
};
3 => {
LANGUAGE()=fr;
Set(LANGUAGE()=fr);
goto s|restart;
};
1000 => {
goto default|s|1;
};
500 => {
Playback(demo-abouttotry);
Dial(IAX2/guest@misery.digium.com);
Dial(IAX2/guest@misery.digium.com/s@default);
Playback(demo-nogo);
goto s|instructions;
};
@ -52,11 +356,83 @@ instructions:
goto s|instructions;
};
_1234 => &std-exten-ael(${EXTEN}, "IAX2");
8500 => {
VoicemailMain();
goto s|instructions;
};
# => {
Playback(demo-thanks);
Hangup();
};
t => jump #;
t => goto #|1;
i => Playback(invalid);
};
context default {
// By default we include the demo. In a production system, you
// probably don't want to have the demo there.
includes {
ael-demo;
};
//
// Extensions like the two below can be used for FWD, Nikotel, sipgate etc.
// Note that you must have a [sipprovider] section in sip.conf whereas
// the otherprovider.net example does not require such a peer definition
//
//_41X. => Dial(SIP/${EXTEN:2}@sipprovider,,r);
//_42X. => Dial(SIP/user:passwd@${EXTEN:2}@otherprovider.net,30,rT);
// Real extensions would go here. Generally you want real extensions to be
// 4 or 5 digits long (although there is no such requirement) and start with a
// single digit that is fairly large (like 6 or 7) so that you have plenty of
// room to overlap extensions and menu options without conflict. You can alias
// them with names, too, and use global variables
// 6245 => {
// hint(SIP/Grandstream1&SIP/Xlite1,Joe Schmoe); // Channel hints for presence
// Dial(SIP/Grandstream1,20,rt); // permit transfer
// Dial(${HINT}/5245},20,rtT); // Use hint as listed
// switch(${DIALSTATUS}) {
// case BUSY:
// Voicemail(b6245);
// return;
// default:
// Voicemail(u6245);
// return;
// };
// };
// 6361 => Dial(IAX2/JaneDoe,,rm); // ring without time limit
// 6389 => Dial(MGCP/aaln/1@192.168.0.14);
// 6394 => Dial(Local/6275/n); // this will dial ${MARK}
// 6275 => &ael-stdexten(6275,${MARK}); // assuming ${MARK} is something like Zap/2
// mark => goto 6275|1; // alias mark to 6275
// 6536 => &ael-stdexten(6236,${WIL}); // Ditto for wil
// wil => goto 6236|1;
//
// Some other handy things are an extension for checking voicemail via
// voicemailmain
//
// 8500 => {
// VoicemailMain();
// Hangup();
// };
//
// Or a conference room (you'll need to edit meetme.conf to enable this room)
//
// 8600 => Meetme(1234);
//
// Or playing an announcement to the called party, as soon it answers
//
// 8700 => Dial(${MARK},30,A(/path/to/my/announcemsg))
//
// For more information on applications, just type "show applications" at your
// friendly Asterisk CLI prompt.
//
// 'show application <command>' will show details of how you
// use that particular application in this file, the dial plan.
//
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
#if !defined(SOLARIS) && !defined(__CYGWIN__)
#include <err.h>
#else
#define quad_t int64_t
#endif
#ifdef LONG_LONG_MIN
#define QUAD_MIN LONG_LONG_MIN
#endif
#ifdef LONG_LONG_MAX
#define QUAD_MAX LONG_LONG_MAX
#endif
# if ! defined(QUAD_MIN)
# define QUAD_MIN (-0x7fffffffffffffffLL-1)
# endif
# if ! defined(QUAD_MAX)
# define QUAD_MAX (0x7fffffffffffffffLL)
# endif
typedef enum
{
PV_WORD, /* an ident, string, name, label, etc. A user-supplied string. */
PV_MACRO,
PV_CONTEXT,
PV_MACRO_CALL,
PV_APPLICATION_CALL,
PV_CASE,
PV_PATTERN,
PV_DEFAULT,
PV_CATCH,
PV_SWITCHES,
PV_ESWITCHES,
PV_INCLUDES,
PV_STATEMENTBLOCK,
PV_VARDEC, /* you know, var=val; */
PV_GOTO,
PV_LABEL,
PV_FOR,
PV_WHILE,
PV_BREAK,
PV_RETURN,
PV_CONTINUE,
PV_IF,
PV_IFTIME,
PV_RANDOM,
PV_SWITCH,
PV_EXTENSION,
PV_IGNOREPAT,
PV_GLOBALS,
} pvaltype;
/* why this horrible mess? It's always been a tradeoff-- tons of structs,
each storing it's specific lists of goodies, or a 'simple' single struct,
with lots of fields, that catches all uses at once. Either you have a long
list of struct names and subnames, or you have a long list of field names,
and where/how they are used. I'm going with a single struct, using unions
to reduce storage. Some simple generalizations, and a long list of types,
and a book about what is used with what types.... Sorry!
*/
struct pval
{
pvaltype type;
int startline;
int endline;
int startcol;
int endcol;
char *filename;
union
{
char *str; /* wow, used almost everywhere! */
struct pval *list; /* used in SWITCHES, ESWITCHES, INCLUDES, STATEMENTBLOCK, GOTO */
struct pval *statements;/* used in EXTENSION */
char *for_init; /* used in FOR */
} u1;
struct pval *u1_last; /* to build in-order lists -- looks like we only need one */
union
{
struct pval *arglist; /* used in macro_call, application_call, MACRO def, also attached to PWORD, the 4 timevals for includes */
struct pval *statements; /* used in case, default, catch, while's statement, CONTEXT elements, GLOBALS */
char *val; /* used in VARDEC */
char *for_test; /* used in FOR */
} u2;
union
{
char *for_inc; /* used in FOR */
struct pval *else_statements; /* used in IF */
struct pval *macro_statements; /* used in MACRO */
int abstract; /* used for context */
char *hints; /* used in EXTENSION */
} u3;
union
{
struct pval *for_statements; /* used in PV_FOR */
int regexten; /* used in EXTENSION */
} u4;
struct pval *next; /* the pval at the end of this ptr will ALWAYS be of the same type as this one!
EXCEPT for objects of the different types, that are in the same list, like contexts & macros, etc */
} ;
typedef struct pval pval;
pval *npval(pvaltype type, int first_line, int last_line, int first_column, int last_column);
void linku1(pval *head, pval *tail);
void print_pval_list(FILE *f, pval *item, int depth);
void print_pval(FILE *f, pval *item, int depth);
void ael2_semantic_check(pval *item, int *errs, int *warns, int *notes);
struct pval *find_label_in_current_context(char *exten, char *label);
struct pval *find_label_in_current_extension(char *label);
int count_labels_in_current_context(char *label);
struct pval *find_label_in_current_db(char *context, char *exten, char *label);
struct pval *ael2_parse(char *fname, int *errs);
void destroy_pval(pval *item);
void ael2_print(char *fname, pval *tree);
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
/* for passing info into and out of yyparse */
struct parse_io
{
struct pval *pval; /* yyparse will set this to point to the parse tree */
yyscan_t scanner; /* yylex needs a scanner. Set it up, and pass it in */
int syntax_error_count; /* the count of syntax errors encountered */
};
/* for CODE GENERATION */
typedef enum { AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_RAND_CONTROL, AEL_LABEL, AEL_RETURN } ael_priority_type;
struct ael_priority
{
int priority_num;
ael_priority_type type;
char *app;
char *appargs;
struct pval *origin;
struct ael_extension *exten;
struct ael_priority *goto_true;
struct ael_priority *goto_false;
struct ael_priority *next;
};
struct ael_extension
{
char *name;
char *hints;
int regexten;
struct ael_priority *plist;
struct ael_priority *plist_last;
struct ael_extension *next_exten;
struct ael_priority *loop_break; /* set by latest loop for breaks */
struct ael_priority *loop_continue; /* set by lastest loop for continuing */
struct ael_priority *return_target;
int return_needed;
};

640
mxml/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,23 @@ pbx_dundi.so: pbx_dundi.o dundi-parser.o
pbx_dundi.o: pbx_dundi.c
$(CC) -c -o $@ $(CFLAGS) $(Z_INCLUDE) $<
pbx_ael.o: ael/aelflex.o ael/aelbison.o ../include/asterisk/ael_structs.h
pbx_ael.so: pbx_ael.o ael/aelbison.o ael/aelflex.o
$(CC) $(SOLINK) -o $@ pbx_ael.o ael/aelbison.o ael/aelflex.o
ael/aelflex.o: ael/ael_lex.c ../include/asterisk/ael_structs.h ael/ael.tab.h
$(CC) $(CFLAGS) -c -o ael/aelflex.o ael/ael_lex.c
ael/aelbison.o: ael/ael.tab.c ael/ael.tab.h ../include/asterisk/ael_structs.h
$(CC) $(CFLAGS) -c -o ael/aelbison.o ael/ael.tab.c
ael/ael_lex.c: ael/ael.flex
(cd ael; flex ael.flex)
ael/ael.tab.c ael/ael.tab.h: ael/ael.y
(cd ael; bison -v -d ael.y)
%.moc : %.h
$(MOC) $< -o $@

View File

@ -0,0 +1,163 @@
macro testdial(number, timeout) {
Dial(IAX2/vpconnect-t02/${number},${timeout},${OG_DIAL_FLAGS});
switch (${DIALSTATUS}) {
case CHANUNAVAIL:
goto dial-trunk2;
break;
default:
NoOp(t02 Unavailable - ${DIALSTATUS});
return;
}
dial-trunk2:
Dial(IAX2/vpconnect-t01/${number},${timeout},${OG_DIAL_FLAGS});
}
macro exten-gen(name,pword)
{
if( ${DB_EXISTS(org/${GroupID}/${name}/secret)} = 0 )
goto other|nomatch|begin;
if( ${DB(org/${GroupID}/${name}/secret)}foo != ${pword}foo )
goto other|nomatch|begin;
};
context what {
who =>
{
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! );
}
}
}
}
context other {
nomatch => {
begin:
NoOp(Hello!);
switch(${DIALSTATUS})
{
case BUSY:
NoOp(wow);
case TORTURE:
NoOp(woow);
};
NoOp(woohoo);
};
};
context testloop {
includes {
other|16:00-23:59|m0n-fri|*|*;
};
1 => {
for (x=0; ${x} < 3; x=${x} + 1) {
Verbose(x is ${x} !);
if( ${x} = 1 )
continue;
if( ${x} = 2 )
break;
};
ifTime(14:00-25:00|sat-sun|*|*) {
BackGround(Hello);
} else
BackGround(Sorry);
NoOp(This is a totally useless NOOP);
};
2 => {
y=10;
while (${y} >= 0) {
Verbose(y is ${y} !);
if( ${y} = 1 )
continue;
if( ${y} = 2 )
break;
if( ${y} = 3 )
return;
y=${y}-1;
};
};
regexten hint(nasty/Thingy) 3 => {
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;
y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
y=${y}-1;
};
};
};
4 => {
y=10;
while (${y} >= 0)
{
Verbose(y is ${y} !);
if( ${y} = 4 )
break;
if( ${y} = 5 )
continue;
if( ${y} = 6 )
return;
for (x=0; ${x} < 3; x=${x} + 1)
{
Verbose(x is ${x} !);
if( ${x} = 4 )
break;
if( ${x} = 5 )
continue;
if( ${x} = 6 )
return;
for (z=0; ${z} < 17; z=${z} + 1)
{
Verbose(z is ${z} !);
Verbose(z is ${z} !);
if( ${z} = 4 )
break;
if( ${z} = 5 )
continue;
if( ${z} = 6 )
return;
Verbose(z is ${z} !);
Verbose(z is ${z} !);
};
};
y=${y}-1;
};
};
5 => {
&exten-gen(axel,brain);
};
};

View File

@ -0,0 +1,146 @@
// this is a quick test to see how many of the apps we can spot j options in
// include this in a macro or extension
// at this moment, there are 18 apps that accept the j option.
AddQueueMember(zork,iface,20,j);
ADSIProg(sfile);
AgentCallbackLogin(agent,s,30@cont);
AgentLogin(agent,s);
AgentMonitorOutgoing(dcn);
AGI(whatever);
AlarmReceiver();
Answer(2);
AppendCDRUserField(value);
Authenticate(pword,adjmr);
BackGround(filename,snm,eng);
BackgroundDetect(filename,20,2,10);
Busy(10);
ChangeMonitor(fnamebase);
ChanIsAvail(Zap/5,sj);
ChanSpy(prefix,bg()qrv);
Congestion(5);
ControlPlayback(filename,10,6,4,0,5,7,j);
DateTime(unixtime,tz,fmt);
DBdel(fam/key);
DBdeltree(fam);
DeadAGI(command);
Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW);
Dictate(basedir);
Directory(cont,dcont,f);
DISA(68986869876,context);
DumpChan(verblev);
DUNDiLookup(90709780978,context,bj);
EAGI(command);
Echo();
EndWhile();
Exec(appname,args);
ExecIf(expr,app,data);
ExecIfTime(*,*,*,*,appname);
ExternalIVR(command,arg1);
Festival(text);
Flash();
ForkCDR(v);
GetCPEID();
Gosub(cont,exten,priority);
GosubIf(cond?label);
Goto(cont,exten,prior);
GotoIf(cond?t:f);
GotoIfTime(*,*,*,*?cont,ext,prior);
Hangup();
HasNewVoicemail(vmbox,var,j);
HasVoicemail(vmbox,var,j);
IAX2Provision(template);
ICES(xmlconfig);
ImportVar(nevar@chann,var);
Log(NOTICE,message);
LookupBlacklist(j);
LookupCIDName();
Macro(macro,arg1);
MacroExit();
MacroIf(expr?etc);
MailboxExists(mbox@cont,j);
Math(v,2+2);
MeetMe(5555,aAbcdDeimMpPqrstTovwxX);
MeetMeAdmin(5555,e,user);
MeetMeCount(5555,var);
Milliwatt();
MixMonitor(filename,abv()V()W(),command);
Monitor(file.fmt,base,mb);
MP3Player(location);
MusicOnHold(class);
NBScat();
NoCDR();
NoOp(ignored);
Page(Zap/1,dq);
Park(exten);
ParkAndAnnounce(template,5,238,retcont);
ParkedCall(exten);
PauseQueueMember(queue,zap,j);
Pickup(ext@cont);
Playback(file,j);
PlayTones(arg);
PrivacyManager(3,4,j);
Progress();
Queue(queuename,dhHnrtTwW,http://www.where.what,over,5);
Random(30,cont,ext,pri);
Read(var,fname,10,skip,2,5);
ReadFile(var=file,10);
RealTime(fam,2,val,prefix);
RealTimeUpdate(fam,2,val,2,newval);
Record(file,2,10,anqst);
RemoveQueueMember(queuename,iface,j);
ResetCDR(wav);
RetryDial(annound,4,2);
Return();
Ringing();
RxFAX(fname,caller);
SayAlpha(string);
SayDigits(string);
SayNumber(digits);
SayPhonetic(string);
SayUnixTime(unixtime,tz,fmt);
SendDTMF(digits,10);
SendImage(filename);
SendText(text,j);
SendURL(URL);
Set(a=b);
SetAMAFlags();
SetCallerID(clid,a);
SetCallerPres(allowed_passed_screen);
SetCDRUserField(value);
SetGlobalVar(var=val);
SetMusicOnHold(class);
SetTransferCapability(SPEECH);
SIPAddHeader(header);
SIPDtmfMode(inband,info,rfc);
SIPGetHeader(var@headername);
SMS(name);
SoftHangup(zap/1,a);
StackPop();
StartMusicOnHold(class);
StopMonitor();
StopMusicOnHold();
StopPlayTones();
System(command);
TestClient(testid);
TestServer();
Transfer(zap/1,j);
TrySystem(command);
TxFAX(filename,caller,debug);
UnpauseQueueMember(queuename,iface,j);
UserEvent(eventanme,body);
Verbose(5,message);
VMAuthenticate(mailbox@cont,s);
VoiceMail(mailbox@cont,bg()suj);
VoiceMailMain(mailbox@cont,pg()s);
Wait(2);
WaitExten(3,m());
WaitForRing(2);
WaitForSilence(2,y);
WaitMusicOnHold(2);
While(expr);
Zapateller(answer,5);
ZapBarge(channel);
ZapRAS(arg);
ZapScan(group);
ZapSendKeypadFacility();

View File

@ -0,0 +1,8 @@
context test1
{
s =>
{
#include "apptest.ael2";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
NoOp(Hello, this is included from include1.ael2);
#include "include2.ael2"

View File

@ -0,0 +1,4 @@
NoOp(This was included from include2.ael2);
#include "include3.ael2"
#include "include4.ael2"

View File

@ -0,0 +1,2 @@
NoOp(This is include3.ael2!);
#include "include5.ael2"

View File

@ -0,0 +1,2 @@
NoOp(This is include4.ael2! Isn't it cool!?!?!?!);
NoOp(4 doesn't include anything);

View File

@ -0,0 +1 @@
NoOp(Include5.ael2 doesn't include anything, either!);

View File

@ -0,0 +1,146 @@
// this is a quick test to see how many of the apps we can spot j options in
// include this in a macro or extension
// at this moment, there are 18 apps that accept the j option.
AddQueueMember(zork,iface,20,j);
ADSIProg(sfile);
AgentCallbackLogin(agent,s,30@cont);
AgentLogin(agent,s);
AgentMonitorOutgoing(dcn);
AGI(whatever);
AlarmReceiver();
Answer(2);
AppendCDRUserField(value);
Authenticate(pword,adjmr);
BackGround(filename,snm,eng);
BackgroundDetect(filename,20,2,10);
Busy(10);
ChangeMonitor(fnamebase);
ChanIsAvail(Zap/5,sj);
ChanSpy(prefix,bg()qrv);
Congestion(5);
ControlPlayback(filename,10,6,4,0,5,7,j);
DateTime(unixtime,tz,fmt);
DBdel(fam/key);
DBdeltree(fam);
DeadAGI(command);
Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW);
Dictate(basedir);
Directory(cont,dcont,f);
DISA(68986869876,context);
DumpChan(verblev);
DUNDiLookup(90709780978,context,bj);
EAGI(command);
Echo();
EndWhile();
Exec(appname,args);
ExecIf(expr,app,data);
ExecIfTime(*,*,*,*,appname);
ExternalIVR(command,arg1);
Festival(text);
Flash();
ForkCDR(v);
GetCPEID();
Gosub(cont,exten,priority);
GosubIf(cond?label);
Goto(cont,exten,prior);
GotoIf(cond?t:f);
GotoIfTime(*,*,*,*?cont,ext,prior);
Hangup();
HasNewVoicemail(vmbox,var,j);
HasVoicemail(vmbox,var,j);
IAX2Provision(template);
ICES(xmlconfig);
ImportVar(nevar@chann,var);
Log(NOTICE,message);
LookupBlacklist(j);
LookupCIDName();
Macro(macro,arg1);
MacroExit();
MacroIf(expr?etc);
MailboxExists(mbox@cont,j);
Math(v,2+2);
MeetMe(5555,aAbcdDeimMpPqrstTovwxX);
MeetMeAdmin(5555,e,user);
MeetMeCount(5555,var);
Milliwatt();
MixMonitor(filename,abv()V()W(),command);
Monitor(file.fmt,base,mb);
MP3Player(location);
MusicOnHold(class);
NBScat();
NoCDR();
NoOp(ignored);
Page(Zap/1,dq);
Park(exten);
ParkAndAnnounce(template,5,238,retcont);
ParkedCall(exten);
PauseQueueMember(queue,zap,j);
Pickup(ext@cont);
Playback(file,j);
PlayTones(arg);
PrivacyManager(3,4,j);
Progress();
Queue(queuename,dhHnrtTwW,http://www.where.what,over,5);
Random(30,cont,ext,pri);
Read(var,fname,10,skip,2,5);
ReadFile(var=file,10);
RealTime(fam,2,val,prefix);
RealTimeUpdate(fam,2,val,2,newval);
Record(file,2,10,anqst);
RemoveQueueMember(queuename,iface,j);
ResetCDR(wav);
RetryDial(annound,4,2);
Return();
Ringing();
RxFAX(fname,caller);
SayAlpha(string);
SayDigits(string);
SayNumber(digits);
SayPhonetic(string);
SayUnixTime(unixtime,tz,fmt);
SendDTMF(digits,10);
SendImage(filename);
SendText(text,j);
SendURL(URL);
Set(a=b);
SetAMAFlags();
SetCallerID(clid,a);
SetCallerPres(allowed_passed_screen);
SetCDRUserField(value);
SetGlobalVar(var=val);
SetMusicOnHold(class);
SetTransferCapability(SPEECH);
SIPAddHeader(header);
SIPDtmfMode(inband,info,rfc);
SIPGetHeader(var@headername);
SMS(name);
SoftHangup(zap/1,a);
StackPop();
StartMusicOnHold(class);
StopMonitor();
StopMusicOnHold();
StopPlayTones();
System(command);
TestClient(testid);
TestServer();
Transfer(zap/1,j);
TrySystem(command);
TxFAX(filename,caller,debug);
UnpauseQueueMember(queuename,iface,j);
UserEvent(eventanme,body);
Verbose(5,message);
VMAuthenticate(mailbox@cont,s);
VoiceMail(mailbox@cont,bg()suj);
VoiceMailMain(mailbox@cont,pg()s);
Wait(2);
WaitExten(3,m());
WaitForRing(2);
WaitForSilence(2,y);
WaitMusicOnHold(2);
While(expr);
Zapateller(answer,5);
ZapBarge(channel);
ZapRAS(arg);
ZapScan(group);
ZapSendKeypadFacility();

View File

@ -0,0 +1,8 @@
context test1
{
test2 =>
{
#include "apptest.ael2";
}
}

View File

@ -0,0 +1,833 @@
///////////////////////////////////////////////////////////////////////////////
// Helpdesk Queue
context hd-queue {
s => {
NoOp(Add a background sound to tell the user their options);
Queue(helpdesk|t);
NoOp(Put in options to apologize and send user to voicemail);
};
0 => goto default|0|1;
1 => {
Dial(u41950@svm1.shsu.edu);
Congestion(10);
Hangup;
};
};
context l903-calling {
_9903NXXXXXX => {
Realtime(l903_ext,exchange,${EXTEN:4:3},l903_);
if ("${l903_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from houston.conf
// Converted the extension list to the database
context houston-calling {
_9713NXXXXXX => {
Realtime(hou_713_ext,exchange,${EXTEN:4:3},hou_713_);
if ("${hou_713_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_9281NXXXXXX => {
Realtime(hou_281_ext,exchange,${EXTEN:4:3},hou_281_);
if ("${hou_281_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_9832NXXXXXX => {
Realtime(hou_832_ext,exchange,${EXTEN:4:3},hou_832_);
if ("${hou_832_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from huntsville.conf
// Converted the extension list to the database
context huntsville-calling {
_9NXXXXXX => {
Realtime(hv_ext,exchange,${EXTEN:1:3},hv_);
if ("${hv_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_NXXXXXX => {
NoOp(Stripping last four to see what extension we're dialing);
Set(LAST4=${EXTEN:3});
StripLSD(4);
};
i => Playback(pbx-invalid);
h => Hangup;
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from macros.conf
macro dialout( number ) {
Realtime(call_info,exten,${CALLERIDNUM:5},mon_);
if ("${mon_monitor}" = "YES") {
Dial(SIP/${number}@sgw1.shsu.edu,,wW);
Dial(SIP/${number}@sgw2.shsu.edu,,wW);
} else {
Dial(SIP/${number}@sgw1.shsu.edu);
Dial(SIP/${number}@sgw2.shsu.edu);
};
};
// Standard extension macro:
// ${ext} - Extension
macro stdexten( ext ) {
Realtime(sipusers,name,${ext},sip_user_);
Realtime(call_info,exten|${ext},info_);
if ("${sip_user_name}foo" = "foo") {
Wait(1);
&dialout(${ext});
Congestion(10);
Hangup;
};
NoOp(${CALLERIDNUM});
RealtimeUpdate(call_info,exten,${ext},calltrace,${CALLERIDNUM});
System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &);
&checkdnd(${ext});
&checkcf(${ext});
Realtime(call_info,exten,${CALLERIDNUM:5},mon_);
if ("${mon_monitor}" = "YES") {
Dial(SIP/${info_forwardto},25,wW);
} else {
Dial(SIP/${info_forwardto},25);
};
switch ("${DIALSTATUS}") {
case "BUSY":
&checkcfb(${ext});
break;
case "CHANUNAVAIL":
Dial(IAX2/asterisk:password@scm2.shsu.edu/${info_forwardto},25,wW);
MailboxExists(${ext});
// if ("${VMBOXEXISTSSTATUS}" = "FAILED") {
// Congestion(10);
// Hangup;
// };
&uvm(${ext});
Hangup;
break;
case "CONGESTION":
MailboxExists(${ext});
if ("${VMBOXEXISTSSTATUS}" = "FAILED") {
Congestion(10);
Hangup;
};
&bvm(${ext});
Hangup;
break;
default:
MailboxExists(${ext});
if ("${VMBOXEXISTSSTATUS}" = "FAILED") {
Congestion(10);
Hangup;
};
&uvm(${ext});
Hangup;
};
Hangup;
};
macro uvm( ext ) {
Dial(SIP/u${ext}@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Congestion(10);
Hangup;
};
macro bvm( ext ) {
Dial(SIP/b${ext}@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Congestion(10);
Hangup;
};
macro checkdnd( ext ) {
if ("${info_donotdisturb}foo" = "foo") {
NoOp(Do Not Disturb is not active);
} else
&uvm(${ext});
};
macro checkcf( ext ) {
if ("${info_forwardto}foo" = "foo")
if ("${ext}" = "43974") {
Set(info_forwardto=${ext}&SCCP/${ext});
} else {
Set(info_forwardto=${ext}&SIP/${ext}w);
};
};
macro checkcfb( ext ) {
if ("${info_forwardbusy}foo" = "foo") {
Wait(1);
MailboxExists(${ext});
if ("${VMBOXEXISTSSTATUS}" = "FAILED") {
&dialout(${ext});
Hangup;
};
&bvm(${ext});
Hangup;
};
&stdexten(${info_forwardbusy});
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from test.conf
context test-include {
includes {
test-digium;
test-sounds;
test-phinfo;
};
};
context test-digium {
*500 => {
Dial(IAX2/guest@misery.digium.com/s@default);
Playback(demo-nogo);
Hangup;
};
};
context test-sounds {
*501 => {
Answer;
Musiconhold;
Wait(1);
Hangup;
};
};
context test-phinfo {
*505 => {
Answer;
NoOp(${CALLERIDNUM:5});
SayDigits(${CALLERIDNUM:5});
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from external.conf
context long-distance {
includes {
local;
};
_91XXXXXXXXXX => &dialout(${EXTEN});
_9011. => &dialout(${EXTEN});
};
context local {
includes {
default;
};
911 => &dialout(911);
9911 => &dialout(9911);
_9NXXXXXX => goto huntsville-calling|${EXTEN}|1;
_936NXXXXXX => {
goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
_832NXXXXXX => {
goto 9${EXTEN}|1;
Congestion(10);
Hangup;
};
_713NXXXXXX => {
goto 9${EXTEN}|1 ;
Congestion(10);
Hangup;
};
_281NXXXXXX => {
goto 9${EXTEN}|1;
Congestion(10);
Hangup;
};
_NXXNXXXXXX => {
goto 9${EXTEN}|1;
goto 91${EXTEN}|1;
Congestion(10);
Hangup;
};
_91800NXXXXXX => &dialout(${EXTEN});
_91866NXXXXXX => &dialout(${EXTEN});
_91877NXXXXXX => &dialout(${EXTEN});
_91888NXXXXXX => &dialout(${EXTEN});
_91900NXXXXXX => &dialout(${EXTEN});
_91976NXXXXXX => &dialout(${EXTEN});
_9713NXXXXXX => goto houston-calling|${EXTEN}|1;
_9281NXXXXXX => goto houston-calling|${EXTEN}|1;
_9832NXXXXXX => goto houston-calling|${EXTEN}|1;
_9903NXXXXXX => goto l903-calling|${EXTEN}|1;
_31NXXNXXXXXX => &dialout(${EXTEN});
h => Hangup;
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from internal.conf
context from-scm2 {
_4XXXX => {
NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM});
Dial(SIP/${EXTEN},20,wW);
Hangup;
};
_6XXXX => {
NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM});
Dial(SIP/${EXTEN},20,wW);
Hangup;
};
};
///////////////////////////////////////////////////////////
// All internal extensions work through the default context
// Phones that can only make internal calls should be in
// this context.
///////////////////////////////////////////////////////////
context default {
// Include the contexts in the files that allow us to make these phone calls
includes {
vm-include;
apps-include;
test-include;
};
// ALWAYS have an 'h' extension
h => {
NoOp(Hangup cause was: ${HANGUPCAUSE});
Hangup;
};
// We like to hear that we dialed an invalid extension
i => Playback(pbx-invalid);
// Dial the operator
0 => &dialout(0);
// Send voicemail calls to the vm-* contexts to be handled
voicemail => goto vm-direct|s|1;
5555 => goto vm-direct|s|1;
62100 => goto vm-extension|s|1;
// These are our campus extensions, send them to the macro
_6XXXX => &stdexten(${EXTEN});
_4XXXX => &stdexten(${EXTEN});
// These are campus extensions as well, might need to take this out though.
_9294XXXX => goto _4XXXX|1;
_9496XXXX => goto _6XXXX|1;
// These allows us to dial from the directory in our phone without worrying about dialing 9
_936294XXXX => {
goto ${EXTEN:5}|1;
goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
_936496XXXX => {
goto ${EXTEN:5}|1;
goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from apps.conf
context apps-include {
includes {
app-agents;
app-dnd;
app-callforward;
app-calltrace;
app-conferences;
app-ssd;
app-psd;
app-idblock;
app-helpdesk;
app-dictate;
app-set-monitor;
};
};
context app-agents {
*54 => {
Answer;
Wait(1);
Read(agent_no|agent-user);
AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5});
Playback(agent-loginok);
Hangup;
};
*55 => {
Answer;
Wait(1);
AgentCallbackLogin(${agent_no});
Hangup;
};
};
context app-calltrace {
// caller dials this to find out the last call missed and possibly call back
*69 => goto app-calltrace-perform|s|1;
};
context app-calltrace-perform {
s => {
Answer;
Wait(1);
Background(info-about-last-call);
Background(telephone-number);
RealTime(call_info|exten|${CALLERIDNUM:5}|ct_);
if ("${ct_calltrace}foo" = "foo") {
Playback(loligo/from-unknown-caller);
Hangup;
} else {
SayDigits("${ct_calltrace}");
Set(TIMEOUT(digit)=3);
Set(TIMEOUT(response)=7);
Background(loligo/to-call-this-number);
Background(press-1);
Background(loligo/silence/5);
};
};
1 => goto local|${ct_calltrace}|1;
i => {
Playback(vm-goodbye);
Hangup;
};
t => {
Playback(vm-goodbye);
Hangup;
};
};
context app-set-monitor {
*50 => {
Realtime(call_info,exten,${CALLERIDNUM:5},mon_set_);
if ("${mon_set_monitor}" = "YES") {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor|);
System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &);
} else {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor,YES);
System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &);
};
NoOp(${mon_set_monitor});
Hangup;
};
};
context app-dnd {
*78 => {
Answer;
Wait(1);
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb,YES);
System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &);
Playback(do-not-disturb);
Playback(loligo/activated);
Hangup;
};
*79 => {
Answer;
Wait(1);
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb|);
System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &);
Playback(do-not-disturb);
Playback(loligo/de-activated);
Hangup;
};
};
context app-callforward {
// forwards calling extension to input number *72{EXTEN}
_*72. => {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,${EXTEN:3});
System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-unconditional);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${CALLERIDNUM:5});
Playback(loligo/is-set-to);
SayDigits(${EXTEN:3});
Hangup;
};
// prompts for extension to forward to
*72 => {
Answer;
Wait(1);
Playback(please-enter-your);
Playback(extension);
Background(then-press-pound);
VMAuthenticate(|s);
Background(loligo/ent-target-attendant);
Read(toext,loligo/then-press-pound);
Wait(1);
RealtimeUpdate(call_info,exten,${AUTH_MAILBOX},forwardto,${toext});
System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &);
Playback(loligo/call-fwd-unconditional);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${AUTH_MAILBOX});
Playback(loligo/is-set-to);
SayDigits(${toext});
Hangup;
};
// cancels dialed extension call forward
_*73. => {
Realtime(voicemail,mailbox,${EXTEN:3},auth_);
Answer;
Wait(1);
Authenticate(${auth_password});
RealtimeUpdate(call_info,exten,${EXTEN:3},forwardto,);
System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &);
Wait(1);
SayDigits(${EXTEN:3});
Playback(loligo/call-fwd-cancelled);
Hangup;
};
// cancels call forward for calling extension
*73 => {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,);
System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-cancelled);
Hangup;
};
// dialed call forward on busy
_*90. => {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy,${EXTEN:3});
System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-on-busy);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${CALLERIDNUM:5});
Playback(loligo/is-set-to);
SayDigits(${EXTEN:3});
Hangup;
};
// cancels call forward on busy for calling extension
*91 => {
RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy|);
System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-on-busy);
Playback(loligo/de-activated);
Hangup;
};
h => Hangup;
};
context app-idblock {
_*67. => {
Set(CALLERID(name)=Anonymous);
&stdexten(${EXTEN:3});
};
};
context app-dictate {
*1 => {
Dictate();
Hangup;
};
};
context app-ssd {
// *59 <xx> <y.> - Set system speed dial <xx> to digits <y.>
// *59 <xx> 0 - Delete system speed dial <xx>
// *59 <xx> - Review system speed dial <xx>
// *1xx - Dial speed dial <xx>
_*59XXX. => {
Answer;
RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,${EXTEN:5});
System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-set-to);
SayDigits(${EXTEN:5});
Hangup;
};
_*59XX0 => {
Answer;
RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,);
System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-cleared);
Hangup;
};
_*59XX => {
Answer;
Realtime(ssd,sd,${EXTEN:3},ssd_);
if ("${ssd_extension}foo" = "foo") {
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-not-set);
Hangup;
};
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-set-to);
SayDigits(${ssd_extension});
Hangup;
};
// NTC = number to call
_*1XX => {
Realtime(ssd,sd,${EXTEN:2},ssd_);
if ("${ssd_extension}foo" = "foo") {
Answer;
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:2});
Playback(loligo/is-not-set);
Hangup;
};
&stdexten(${ssd_extension});
Congestion(10);
Hangup;
};
};
macro check-psd-exists ( ext ) {
Realtime(psd,extension,${ext},psd_);
if ("${psd_extension}foo" = "foo") {
System(/usr/local/bin/create_psd.sh ${ext});
} else
NoOp(PSD set for ${ext});
};
context app-psd {
// *89 <xx> <y.> - Set personal speed dial <xx> to digits <y.>
// *89 <xx> 0 - Delete personal speed dial <xx>
// *89 <xx> - Review personal speed dial <xx>
// *2xx - Dial personal speed dial <xx>
_*89XXX. => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
RealtimeUpdate(psd,extension,${CALLERIDNUM:5},s${EXTEN:3:2},${EXTEN:5});
System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-set-to);
SayDigits(${EXTEN:5});
Hangup;
};
_*89XX0 => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|);
System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-cleared);
Hangup;
};
_*89XX => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
Realtime(psd|extension|${CALLERIDNUM:5}|psd_);
Wait(1);
if ("${psd_s${EXTEN:3:2}}foo" = "foo") {
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-not-set);
Hangup;
};
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-set-to);
SayDigits(${psd_s${EXTEN:3:2}});
Hangup;
};
// NTC = number to call
_*2XX => {
&check-psd-exists(${CALLERIDNUM:5});
Realtime(psd|extension|${CALLERIDNUM:5}|psd_);
if ("${psd_s${EXTEN:2}}foo" = "foo") {
Answer;
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:2});
Playback(loligo/is-not-set);
Hangup;
};
&stdexten(${psd_s${EXTEN:2}});
Congestion(10);
Hangup;
};
};
context app-helpdesk {
*4357 => {
&stdexten(41950);
Congestion;
};
};
context app-conferences {
// waiting for room number announcement
*86 => goto app-conf-hidden|s|1;
};
context app-conf-hidden {
s => {
Wait(1);
Playback(loligo/please-enter-the);
Playback(loligo/extension);
read(roomtoenter,loligo/then-press-pound);
Meetme(${roomtoenter});
Waitexten(8);
Hangup;
};
_1. => Meetme(${EXTEN});
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from vm.conf:
context vm-include {
includes {
vm-direct;
vm-extension;
vm-directory;
};
};
context vm-direct {
s => {
Dial(SIP/5555@svm1.shsu.edu,20);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};
context vm-extension {
s => {
Dial(SIP/62100@svm1.shsu.edu,20);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};
context vm-directory {
5556 => {
Dial(SIP/5556@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};

View File

@ -0,0 +1,833 @@
///////////////////////////////////////////////////////////////////////////////
// Helpdesk Queue
context hd-queue {
s => {
NoOp(Add a background sound to tell the user their options);
Queue(helpdesk|t);
NoOp(Put in options to apologize and send user to voicemail);
};
0 => goto default|0|1;
1 => {
Dial(u41950@svm1.shsu.edu);
Congestion(10);
Hangup;
};
};
context l903-calling {
_9903NXXXXXX => {
Realtime(l903_ext|exchange|${EXTEN:4:3}|l903_);
if ("${l903_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from houston.conf
// Converted the extension list to the database
context houston-calling {
_9713NXXXXXX => {
Realtime(hou_713_ext|exchange|${EXTEN:4:3}|hou_713_);
if ("${hou_713_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_9281NXXXXXX => {
Realtime(hou_281_ext|exchange|${EXTEN:4:3}|hou_281_);
if ("${hou_281_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_9832NXXXXXX => {
Realtime(hou_832_ext|exchange|${EXTEN:4:3}|hou_832_);
if ("${hou_832_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from huntsville.conf
// Converted the extension list to the database
context huntsville-calling {
_9NXXXXXX => {
Realtime(hv_ext|exchange|${EXTEN:1:3}|hv_);
if ("${hv_exchange}foo" = "foo") {
Playback(num-outside-area);
SayDigits(1);
Playback(and-area-code);
Playback(before-the-number);
Hangup;
};
&dialout(${EXTEN});
Congestion(10);
Hangup;
};
_NXXXXXX => {
NoOp(Stripping last four to see what extension we're dialing);
Set(LAST4=${EXTEN:3});
StripLSD(4);
};
i => Playback(pbx-invalid);
h => Hangup;
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from macros.conf
macro dialout( number ) {
Realtime(call_info|exten|${CALLERIDNUM:5}|mon_);
if ("${mon_monitor}" = "YES") {
Dial(SIP/${number}@sgw1.shsu.edu,,wW);
Dial(SIP/${number}@sgw2.shsu.edu,,wW);
} else {
Dial(SIP/${number}@sgw1.shsu.edu);
Dial(SIP/${number}@sgw2.shsu.edu);
};
};
// Standard extension macro:
// ${ext} - Extension
macro stdexten( ext ) {
Realtime(sipusers|name|${ext}|sip_user_);
Realtime(call_info|exten|${ext}|info_);
if ("${sip_user_name}foo" = "foo") {
Wait(1);
&dialout(${ext});
Congestion(10);
Hangup;
};
NoOp(${CALLERIDNUM});
RealtimeUpdate(call_info|exten|${ext}|calltrace|${CALLERIDNUM});
System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &);
&checkdnd(${ext});
&checkcf(${ext});
Realtime(call_info|exten|${CALLERIDNUM:5}|mon_);
if ("${mon_monitor}" = "YES") {
Dial(SIP/${info_forwardto},25,wW);
} else {
Dial(SIP/${info_forwardto},25);
};
switch ("${DIALSTATUS}") {
case "BUSY":
&checkcfb(${ext});
break;
case "CHANUNAVAIL":
Dial(IAX2/asterisk:password@scm2.shsu.edu/${info_forwardto},25,wW);
MailboxExists(${ext});
// if ("${VMBOXEXISTSSTATUS}" = "FAILED") {
// Congestion(10);
// Hangup;
// };
&uvm(${ext});
Hangup;
break;
case "CONGESTION":
MailboxExists(${ext});
if ("$(VMBOXEXISTSSTATUS}" = "FAILED") {
Congestion(10);
Hangup;
};
&bvm(${ext});
Hangup;
break;
default:
MailboxExists(${ext});
if ("$(VMBOXEXISTSSTATUS}" = "FAILED") {
Congestion(10);
Hangup;
};
&uvm(${ext});
Hangup;
};
Hangup;
};
macro uvm( ext ) {
Dial(SIP/u${ext}@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Congestion(10);
Hangup;
};
macro bvm( ext ) {
Dial(SIP/b${ext}@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Congestion(10);
Hangup;
};
macro checkdnd( ext ) {
if ("${info_donotdisturb}foo" = "foo") {
NoOp(Do Not Disturb is not active);
} else
&uvm(${ext});
};
macro checkcf( ext ) {
if ("${info_forwardto}foo" = "foo")
if ("${ext}" = "43974") {
Set(info_forwardto=${ext}&SCCP/${ext});
} else {
Set(info_forwardto=${ext}&SIP/${ext}w);
};
};
macro checkcfb( ext ) {
if ("${info_forwardbusy}foo" = "foo") {
Wait(1);
MailboxExists(${ext});
if ("$(VMBOXEXISTSSTATUS}" = "FAILED") {
&dialout(${ext});
Hangup;
};
&bvm(${ext});
Hangup;
};
&stdexten(${info_forwardbusy});
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from test.conf
context test-include {
includes {
test-digium;
test-sounds;
test-phinfo;
};
};
context test-digium {
*500 => {
Dial(IAX2/guest@misery.digium.com/s@default);
Playback(demo-nogo);
Hangup;
};
};
context test-sounds {
*501 => {
Answer;
Musiconhold;
Wait(1);
Hangup;
};
};
context test-phinfo {
*505 => {
Answer;
NoOp(${CALLERIDNUM:5});
SayDigits(${CALLERIDNUM:5});
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from external.conf
context long-distance {
includes {
local;
};
_91XXXXXXXXXX => &dialout(${EXTEN});
_9011. => &dialout(${EXTEN});
};
context local {
includes {
default;
};
911 => &dialout(911);
9911 => &dialout(9911);
_9NXXXXXX => goto huntsville-calling|${EXTEN}|1;
_936NXXXXXX => {
Goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
_832NXXXXXX => {
goto 9${EXTEN}|1;
Congestion(10);
Hangup;
};
_713NXXXXXX => {
goto 9${EXTEN}|1 ;
Congestion(10);
Hangup;
};
_281NXXXXXX => {
goto 9${EXTEN}|1;
Congestion(10);
Hangup;
};
_NXXNXXXXXX => {
goto 9${EXTEN}|1;
goto 91${EXTEN}|1;
Congestion(10);
Hangup;
};
_91800NXXXXXX => &dialout(${EXTEN});
_91866NXXXXXX => &dialout(${EXTEN});
_91877NXXXXXX => &dialout(${EXTEN});
_91888NXXXXXX => &dialout(${EXTEN});
_91900NXXXXXX => &dialout(${EXTEN});
_91976NXXXXXX => &dialout(${EXTEN});
_9713NXXXXXX => goto houston-calling|${EXTEN}|1;
_9281NXXXXXX => goto houston-calling|${EXTEN}|1;
_9832NXXXXXX => goto houston-calling|${EXTEN}|1;
_9903NXXXXXX => goto l903-calling|${EXTEN}|1;
_31NXXNXXXXXX => &dialout(${EXTEN});
h => Hangup;
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from internal.conf
context from-scm2 {
_4XXXX => {
NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM});
Dial(SIP/${EXTEN},20,wW);
Hangup;
};
_6XXXX => {
NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM});
Dial(SIP/${EXTEN},20,wW);
Hangup;
};
};
///////////////////////////////////////////////////////////
// All internal extensions work through the default context
// Phones that can only make internal calls should be in
// this context.
///////////////////////////////////////////////////////////
context default {
// Include the contexts in the files that allow us to make these phone calls
includes {
vm-include;
apps-include;
test-include;
};
// ALWAYS have an 'h' extension
h => {
NoOp(Hangup cause was: ${HANGUPCAUSE});
Hangup;
};
// We like to hear that we dialed an invalid extension
i => Playback(pbx-invalid);
// Dial the operator
0 => &dialout(0);
// Send voicemail calls to the vm-* contexts to be handled
voicemail => goto vm-direct|s|1;
5555 => goto vm-direct|s|1;
62100 => goto vm-extension|s|1;
// These are our campus extensions, send them to the macro
_6XXXX => &stdexten(${EXTEN});
_4XXXX => &stdexten(${EXTEN});
// These are campus extensions as well, might need to take this out though.
_9294XXXX => goto _4XXXX|1;
_9496XXXX => goto _6XXXX|1;
// These allows us to dial from the directory in our phone without worrying about dialing 9
_936294XXXX => {
goto ${EXTEN:5}|1;
goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
_936496XXXX => {
goto ${EXTEN:5}|1;
goto 9${EXTEN:3}|1;
Congestion(10);
Hangup;
};
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from apps.conf
context apps-include {
includes {
app-agents;
app-dnd;
app-callforward;
app-calltrace;
app-conferences;
app-ssd;
app-psd;
app-idblock;
app-helpdesk;
app-dictate;
app-set-monitor;
};
};
context app-agents {
*54 => {
Answer;
Wait(1);
Read(agent_no|agent-user);
AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5});
Playback(agent-loginok);
Hangup;
};
*55 => {
Answer;
Wait(1);
AgentCallbackLogin(${agent_no});
Hangup;
};
};
context app-calltrace {
// caller dials this to find out the last call missed and possibly call back
*69 => goto app-calltrace-perform|s|1;
};
context app-calltrace-perform {
s => {
Answer;
Wait(1);
Background(info-about-last-call);
Background(telephone-number);
RealTime(call_info|exten|${CALLERIDNUM:5}|ct_);
if ("${ct_calltrace}foo" = "foo") {
Playback(loligo/from-unknown-caller);
Hangup;
} else {
SayDigits("${ct_calltrace}");
Set(TIMEOUT(digit)=3);
Set(TIMEOUT(response)=7);
Background(loligo/to-call-this-number);
Background(press-1);
Background(loligo/silence/5);
};
};
1 => goto local|${ct_calltrace}|1;
i => {
Playback(vm-goodbye);
Hangup;
};
t => {
Playback(vm-goodbye);
Hangup;
};
};
context app-set-monitor {
*50 => {
Realtime(call_info|exten|${CALLERIDNUM:5}|mon_set_);
if ("${mon_set_monitor}" = "YES") {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|);
System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &);
} else {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|YES);
System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &);
};
NoOp(${mon_set_monitor});
Hangup;
};
};
context app-dnd {
*78 => {
Answer;
Wait(1);
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|YES);
System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &);
Playback(do-not-disturb);
Playback(loligo/activated);
Hangup;
};
*79 => {
Answer;
Wait(1);
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|);
System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &);
Playback(do-not-disturb);
Playback(loligo/de-activated);
Hangup;
};
};
context app-callforward {
// forwards calling extension to input number *72{EXTEN}
_*72. => {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|${EXTEN:3});
System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-unconditional);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${CALLERIDNUM:5});
Playback(loligo/is-set-to);
SayDigits(${EXTEN:3});
Hangup;
};
// prompts for extension to forward to
*72 => {
Answer;
Wait(1);
Playback(please-enter-your);
Playback(extension);
Background(then-press-pound);
VMAuthenticate(|s);
Background(loligo/ent-target-attendant);
Read(toext,loligo/then-press-pound);
Wait(1);
RealtimeUpdate(call_info|exten|${AUTH_MAILBOX}|forwardto|${toext});
System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &);
Playback(loligo/call-fwd-unconditional);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${AUTH_MAILBOX});
Playback(loligo/is-set-to);
SayDigits(${toext});
Hangup;
};
// cancels dialed extension call forward
_*73. => {
Realtime(voicemail|mailbox|${EXTEN:3}|auth_);
Answer;
Wait(1);
Authenticate(${auth_password});
RealtimeUpdate(call_info|exten|${EXTEN:3}|forwardto|);
System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &);
Wait(1);
SayDigits(${EXTEN:3});
Playback(loligo/call-fwd-cancelled);
Hangup;
};
// cancels call forward for calling extension
*73 => {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|);
System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-cancelled);
Hangup;
};
// dialed call forward on busy
_*90. => {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|${EXTEN:3});
System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-on-busy);
Playback(loligo/for);
Playback(loligo/extension);
SayDigits(${CALLERIDNUM:5});
Playback(loligo/is-set-to);
SayDigits(${EXTEN:3});
Hangup;
};
// cancels call forward on busy for calling extension
*91 => {
RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|);
System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &);
Answer;
Wait(1);
Playback(loligo/call-fwd-on-busy);
Playback(loligo/de-activated);
Hangup;
};
h => Hangup;
};
context app-idblock {
_*67. => {
Set(CALLERID(name)=Anonymous);
&stdexten(${EXTEN:3});
};
};
context app-dictate {
*1 => {
Dictate();
Hangup;
};
};
context app-ssd {
// *59 <xx> <y.> - Set system speed dial <xx> to digits <y.>
// *59 <xx> 0 - Delete system speed dial <xx>
// *59 <xx> - Review system speed dial <xx>
// *1xx - Dial speed dial <xx>
_*59XXX. => {
Answer;
RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|${EXTEN:5});
System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-set-to);
SayDigits(${EXTEN:5});
Hangup;
};
_*59XX0 => {
Answer;
RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|);
System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-cleared);
Hangup;
};
_*59XX => {
Answer;
Realtime(ssd|sd|${EXTEN:3}|ssd_);
if ("${ssd_extension}foo" = "foo") {
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-not-set);
Hangup;
};
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-set-to);
SayDigits(${ssd_extension});
Hangup;
};
// NTC = number to call
_*1XX => {
Realtime(ssd|sd|${EXTEN:2}|ssd_);
if ("${ssd_extension}foo" = "foo") {
Answer;
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:2});
Playback(loligo/is-not-set);
Hangup;
};
&stdexten(${ssd_extension});
Congestion(10);
Hangup;
};
};
macro check-psd-exists ( ext ) {
Realtime(psd|extension|${ext}|psd_);
if ("${psd_extension}foo" = "foo") {
System(/usr/local/bin/create_psd.sh ${ext});
} else
NoOp(PSD set for ${ext});
};
context app-psd {
// *89 <xx> <y.> - Set personal speed dial <xx> to digits <y.>
// *89 <xx> 0 - Delete personal speed dial <xx>
// *89 <xx> - Review personal speed dial <xx>
// *2xx - Dial personal speed dial <xx>
_*89XXX. => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|${EXTEN:5});
System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-set-to);
SayDigits(${EXTEN:5});
Hangup;
};
_*89XX0 => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|);
System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &);
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/has-been-cleared);
Hangup;
};
_*89XX => {
&check-psd-exists(${CALLERIDNUM:5});
Answer;
Realtime(psd|extension|${CALLERIDNUM:5}|psd_);
Wait(1);
if ("${psd_s${EXTEN:3:2}}foo" = "foo") {
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-not-set);
Hangup;
};
Playback(loligo/speed-dial);
SayDigits(${EXTEN:3:2});
Playback(loligo/is-set-to);
SayDigits(${psd_s${EXTEN:3:2}});
Hangup;
};
// NTC = number to call
_*2XX => {
&check-psd-exists(${CALLERIDNUM:5});
Realtime(psd|extension|${CALLERIDNUM:5}|psd_);
if ("${psd_s${EXTEN:2}}foo" = "foo") {
Answer;
Wait(1);
Playback(loligo/speed-dial);
SayDigits(${EXTEN:2});
Playback(loligo/is-not-set);
Hangup;
};
&stdexten(${psd_s${EXTEN:2}});
Congestion(10);
Hangup;
};
};
context app-helpdesk {
*4357 => {
&stdexten(41950);
Congestion;
};
};
context app-conferences {
// waiting for room number announcement
*86 => goto app-conf-hidden|s|1;
};
context app-conf-hidden {
s => {
Wait(1);
Playback(loligo/please-enter-the);
Playback(loligo/extension);
read(roomtoenter,loligo/then-press-pound);
Meetme(${roomtoenter});
Waitexten(8);
Hangup;
};
_1. => Meetme(${EXTEN});
};
///////////////////////////////////////////////////////////////////////////////
// Extensions pulled from vm.conf:
context vm-include {
includes {
vm-direct;
vm-extension;
vm-directory;
};
};
context vm-direct {
s => {
Dial(SIP/5555@svm1.shsu.edu,20);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};
context vm-extension {
s => {
Dial(SIP/62100@svm1.shsu.edu,20);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};
context vm-directory {
5556 => {
Dial(SIP/5556@svm1.shsu.edu);
Playback(im-sorry);
Playback(voice-mail-system);
Playback(down);
Playback(extra/pls-try-call-later);
Congestion(10);
Hangup;
};
};

View File

@ -0,0 +1,460 @@
//
// Example AEL config file
//
globals {
CONSOLE=Console/dsp;
TRUNKMSD=0; //MSD digits to strip (usually 1 or 0)
TRUNCPROTO=SIP;
TRUNK=sunrocket;
PSTN=pstn-spa3k;
PSTNPROTO=SIP;
TARIOPROTO=SIP;
TARIO=tario;
CPPROTO=SIP;
CPACKET1=callpacket1;
CPACKET2=callpacket2;
SELLVOIP=1577040314;
SVPROTO=IAX2;
};
macro stdexten (ext , dev ) {
PrivacyManager(3,10);
if("${PRIVACYMGRSTATUS}" = "FAILED") {
Playback(vm-goodbye);
Hangup();
};
AGI(calleridnamelookup.agi);
Dial(${dev}/${ext},30,t);
switch(${DIALSTATUS}) {
case BUSY:
Voicemail(b${ext});
break;
default:
Voicemail(u${ext});
};
catch a {
VoiceMailMain(${ext});
return;
};
};
macro announce_minutes(minutes) {
Playback(vm-youhave);
SayNumber(${minutes});
Playback(vm-minutes);
Wait(1);
};
// Check if given provider allows only some free minutes per month
// and announce number of free minutes remaining.
// The limit will be reset monthly by cron job.
// The macro sets the following variables:
// MINUTES_LIMIT - number of free minutes per month
// MINUTES_USED - number of free minutes used in the current month
// PROVIDER - provider name
macro checkanddial(prov,proto,ext,arg1,arg2,arg3,arg4) {
Set(MINUTES_LIMIT=0);
Set(MINUTES_USED=0);
Set(PROVIDER=${prov});
if(${DB_EXISTS(Provider/${prov}/used)})
Set(MINUTES_USED=${DB_RESULT});
country_c = 0;
switch(${LEN(${ext})}) { //assuming all international numbers are 11 digits long.
case 10: //NXXNXXXXXX
country_c=1;
break;
case 11: //XNXXNXXXXXX
country_c = ${ext:0:1};
break;
default: //011XNXXNXXXXXX
country_c = ${ext:3:1};
break;
};
if("${prov}" = "${TRUNK}" & ${country_c} != 1) { // SunRocket international calls
Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)});
&announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]);
};
if("${prov}" = "${CPACKET1}" | "${prov}" = "${CPACKET2}") { // Callpacket has a limit on domestic calls
Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)});
&announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]);
};
DeadAGI(dial.agi,${proto}/${ext}@${prov},${arg1},${arg2},${arg3},${arg4});
};
macro trunkdial(ext) { // Dial sunrocket and set correct collerid
if("${CALLERID(number)}" = "1") {
Set(CALLERID(number)=7322271653);
} else {
Set(CALLERID(number)=7326260100);
};
Set(CALLERID(name)=Sergey Okhapkin);
&checkanddial(${TRUNK},${TRUNCPROTO},${ext},60,T);
Hangup;
};
macro checklocal(ext) { // lookup the number in DB and call the number via pstn or sunrocket
Set(AREACODE=${ext:0:3});
Set(EXCHANGE=${ext:3:3});
Set(IS_LOCAL=${DB_EXISTS(localnum/${AREACODE}/${EXCHANGE})});
if(${IS_LOCAL}) {
&checkanddial(${PSTN},${PSTNPROTO},${ext},60,T);
if ("${DIALSTATUS}" = "BUSY")
&trunkdial(${ext});
} else
&trunkdial(${ext});
};
macro autodial(ext) { // Find Least Cost Route
LCDial(${ext},60,T);
if("${DIALSTATUS}" = "NOPROVIDER")
Playback(invalid);
Hangup();
};
context default { // Calls to us
s => {
Wait(1);
Answer;
start:
Set(TIMEOUT(digit)=3);
Set(TIMEOUT(response)=10);
repeat:
for (x=0; ${x} < 5; x=${x} + 1) {
Background(home/greeting);
WaitExten();
};
};
t => jump *;
i => { // invalid extension
Playback(invalid);
goto s|repeat;
};
_* => {
Playback(vm-goodbye);
Wait(1);
Hangup;
};
1 => &stdexten(1,SIP/1);
2 => &stdexten(2,SIP/2);
3 => &stdexten(3,SIP/3);
2271653 => jump 1;
7322271653 => jump 1;
17322271653 => jump 1;
6260100 => jump 2;
7326260100 => jump 2;
17326260100 => jump 2;
8058701100 => jump 2;
3103622835 => jump 2;
sos => jump 2;
1400898 => jump 2;
6260101 => jump s;
7326260101 => jump s;
17326260101 => jump s;
2271677 => jump 3;
7322271677 => jump 3;
17322271677 => jump 3;
galka => jump 3;
911 => Dial(${PSTNPROTO}/911@${PSTN},60,);
380 => Dial(SIP/topspeen@212.40.38.70,60,T);
// Fun stuff
100 => {
SayUnixTime();
goto s|start;
};
101 => { // Voicemail
VoicemailMain(${CALLERID(number)});
Hangup;
};
102 => MusicOnHold();
// 103 => {
// Wait(1);
//start:
// Read(NUMBER,vm-enter-num-to-call);
// LCDial(${NUMBER},T);
// goto start;
// };
105 => jump s@phrase-menu;
7312 => {
ForkCDR;
Set(CALLERID(name)=Sergey Okhapkin);
Set(CALLERID(number)=7326260100);
DISA(1111|home);
};
};
context goiax {
s => {
Answer();
Ringing();
Wait(1);
start:
Read(NUMBER,vm-enter-num-to-call);
Set(CALLERID(name)=Central NJ);
Dial(IAX2/14301@fwdOUT/q${NUMBER},60,T);
goto start;
};
};
context phrase-menu {
s => {
Answer; // Answer the line
TIMEOUT(digit)=2; // Set Digit Timeout to 5 seconds
TIMEOUT(response)=10; // Set Response Timeout to 10 seconds
BackGround(custom/phrase-menu); // Play main menu.
};
1 => { // Phrase Recording
Wait(1);
Read(PHRASEID|custom/enter-phrase-num);
Wait(2); // give yourself 2 secs to take a breath and wait for beep
Record(custom/${PHRASEID}:gsm);
Wait(2);
Playback(custom/${PHRASEID});
Wait(1);
jump s;
};
2 => { // Phrase review
Wait(1);
Read(PHRASEID|custom/enter-phrase-num);
Wait(1);
Playback(custom/${PHRASEID});
Wait(1);
jump s;
};
t => Hangup;
i => {
Playback(custom/invalid-option);
jump s;
};
};
context outbound {
// North America seven-, ten- and eleven digits
_NXXXXXX => &autodial(1732${EXTEN});
_NXXNXXXXXX => &autodial(1${EXTEN});
_ZNXXNXXXXX. => &autodial(${EXTEN});
// Toll free numbers via PSTN
// _1800NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T);
// _1888NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T);
// _1877NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T);
// _1866NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T);
_011. => { //International context accessed through trunk
&trunkdial(${EXTEN});
};
_012. => { //fwdOUT
Set(CALLERID(name)=Central NJ);
Dial(IAX2/14301@fwdOUT/q${EXTEN:3},60,T);
};
_013X. => { //NECC
Dial(${PSTNPROTO}/011${EXTEN:3}@${PSTN},60,T);
};
_0131. => { //NECC to US
Dial(${PSTNPROTO}/${EXTEN:3}@${PSTN},60,T);
};
_014. => { //TARIO by SIP ID
Set(CALLERID(name)=Sergey Okhapkin);
Set(CALLERID(number)=1400898);
Dial(${TARIOPROTO}/${EXTEN:3}@${TARIO},60,T);
};
_0157. => { //TARIO outbound Russia
Set(CALLERID(name)=Sergey Okhapkin);
Set(CALLERID(number)=1400898);
Dial(${TARIOPROTO}/8${EXTEN:4}@${TARIO},60,T);
};
// _015. => { //TARIO outbound international
// CALLERID(name)="Sergey Okhapkin";
// CALLERID(number)=1400898;
// Dial(${TARIOPROTO}/810${EXTEN:3}@${TARIO},60,T);
// };
_0161NXXNXXXXXX => { //Callpacket outbound USA/Canada
&checkanddial(${CPACKET1},${CPPROTO},${EXTEN:3},60,T);
};
_0171NXXNXXXXXX => { //Callpacket outbound USA/Canada
&checkanddial(${CPACKET2},${CPPROTO},${EXTEN:3},60,T);
};
_0181NXXNXXXXXX => { //sellvoip outbound USA/Canada
Dial(${SVPROTO}/${SELLVOIP}@${SELLVOIP}/${EXTEN:3},60,T);
};
_019. => { //Voipbuster
Dial(IAX2/sokhapkin@voipbuster/00${EXTEN:3},60,T);
};
};
context home { //calls from us
includes {
default;
outbound;
};
};
context sunrocket-in {
7322271653 => jump s;
7326260100 => jump 2@default;
s => {
if("${CALLERID(number)}" = "sunrocketcom")
Set(CALLERID(number)=);
switch(${CALLERID(RDNIS)}) {
case 7326260100:
jump 2@default;
break;
case 7326260101:
jump s@default;
break;
default:
jump 1@default;
break;
};
};
};
context pstn-in {
3 => {
if ("${CALLERID(number)}" = "7322271677")
Set(CALLERID(number)=);
jump 3@default;
};
};
context tario.net-in {
_X. => {
Set(CALLERID(name)=);
if("${CALLERID(number):-11:1}" = "8")
Set(CALLERID(number)=7${CALLERID(number):1});
if("${SIP_HEADER(To)}" = "<sip:2271677@sipnet.ru>") {
jump 3@default;
} else if("${SIP_HEADER(To)}" = "<sip:2271653@sipnet.ru>") {
jump 1@default;
} else
jump 2@default;
};
};
context from-callpacket {
8058701100 => jump 2@default;
3103622835 => {
Answer;
Ringing;
Wait(10);
Voicemail(b3103622835);
Hangup;
};
a => Hangup;
};
context fromfwdOUT { // make sure we only accept US and Canada calls, limit to 30 minutes
includes {
fromfwdOUT-catchbad;
fromfwdOUT-isgood;
fromfwdOUT-catchall;
};
};
context fromfwdOUT-isgood {
_17326260100 => jump 2@default;
_17326260101 => jump s@default;
_17322271653 => jump 1@default;
_17322271677 => jump 3@default;
_1NXXNXXXXXX => {
Set(CALLERID(name)=Sergey Okhapkin);
// Set(CALLERID(number)=7326260100);
// Dial(${TRUNCPROTO}/*67${EXTEN:${TRUNKMSD}}@${TRUNK},60,,L(1800000:60000));
Dial(${CPPROTO}/${EXTEN}@${CPACKET2},60,,L(1800000:60000));
};
};
context fromfwdOUT-catchbad { //block bahamas, etc
_1900. => congestion ; //N11
_1XXX976. => congestion ; //N11
_1XXX555. => congestion ; //N11
_1X11. => congestion ; //N11
_1867. => congestion ; //Yukon (sorry mike)
// exten => _1NPA Country
_1242. => congestion; //BAHAMAS
_1246. => congestion; //BARBADOS
_1264. => congestion; //ANGUILLA
_1268. => congestion; //ANTIGUA/BARBUDA
_1284. => congestion; //BRITISH VIRGIN ISLANDS
_1345. => congestion; //CAYMAN ISLANDS
_1441. => congestion; //BERMUDA
_1473. => congestion; //GRENADA
_1649. => congestion; //TURKS & CAICOS ISLANDS
_1664. => congestion; //MONTSERRAT
_1758. => congestion; //ST. LUCIA
_1767. => congestion; //DOMINICA
_1784. => congestion; //ST. VINCENT & GRENADINES
_1809. => congestion; //DOMINICAN REPUBLIC
_1829. => congestion; //DOMINICAN REPUBLIC
_1868. => congestion; //TRINIDAD AND TOBAGO
_1869. => congestion; //ST. KITTS AND NEVIS
_1876. => congestion; //JAMAICA
_1787. => congestion; //Puerto Rico 787, 939 $0.07
_1939. => congestion; //Puerto Rico 787, 939 $0.07
_1671. => congestion; //Guam 671 $0.08
_1340. => congestion; //U.S. Virgin Islands 340 $0.06
};
context fromfwdOUT-catchall {
_X. => Congestion;
h => Hangup ; //hangup event
i => Hangup ; //invalid event
t => Hangup ; //timeout event
};
context ael-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;
};
_1234 => &std-exten-ael(${EXTEN}, "IAX2");
# => {
Playback(demo-thanks);
Hangup();
};
t => jump #;
i => Playback(invalid);
};

View File

@ -0,0 +1,11 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:3 file:pbx_ael.c line:891 func: check_dow Warning: file ./extensions.ael, line 67-67: The day (m0n) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!
LOG: lev:3 file:pbx_ael.c line:849 func: check_timerange Warning: file ./extensions.ael, line 78-78: The end time (25:00) is out of range!
LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
LOG: lev:4 file:ael2_parse line:261 func: main 5 contexts, 13 extensions, 156 priorities

View File

@ -0,0 +1,15 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./apptest.ael2, 3474 chars
LOG: lev:3 file:ael.y line:405 func: ael_yyparse ==== File: ./apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL.
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 35-35: application call to EndWhile needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 37-37: application call to ExecIf needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./apptest.ael2, line 46-46: goto: no context cont could be found that matches the goto target!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 47-47: application call to GotoIf needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 48-48: application call to GotoIfTime needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 85-85: application call to Random needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 141-141: application call to While needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 1 semantic errors were detected. It doesn't make sense to compile.
LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities

View File

@ -0,0 +1,18 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include1.ael2, 78 chars
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include2.ael2, 98 chars
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include3.ael2, 57 chars
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include5.ael2, 56 chars
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include4.ael2, 87 chars
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file /etc/asterisk/telemarket_torture.ael2, 28036 chars
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 5-5: expression Console/dsp has operators, but no variables. Interesting...
LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 8-8: expression "Joe-Worker" has operators, but no variables. Interesting...
LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 10-10: expression Zap/6 has operators, but no variables. Interesting...
LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
LOG: lev:4 file:ael2_parse line:261 func: main 172 contexts, 858 extensions, 2326 priorities

View File

@ -0,0 +1,15 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./apptest.ael2, 3474 chars
LOG: lev:3 file:ael.y line:405 func: ael_yyparse ==== File: ./apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL.
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 35-35: application call to EndWhile needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 37-37: application call to ExecIf needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./apptest.ael2, line 46-46: goto: no context cont could be found that matches the goto target!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 47-47: application call to GotoIf needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 48-48: application call to GotoIfTime needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 85-85: application call to Random needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 141-141: application call to While needs to be re-written using AEL if, while, goto, etc. keywords instead!
LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 1 semantic errors were detected. It doesn't make sense to compile.
LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities

View File

@ -0,0 +1,9 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'.
LOG: lev:4 file:ael2_parse line:261 func: main 38 contexts, 90 extensions, 484 priorities

View File

@ -0,0 +1,20 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:4 file:ael.flex line:193 func: ael_yylex File=./extensions.ael, line=165, column=21: Mismatched '}' in expression!
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 165, Cols: 23-23: Error: syntax error, unexpected '=', expecting ')'
LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=174, column=63: Mismatched '}' in expression!
LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=180, column=46: Mismatched '}' in expression!
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 184, Cols: 0-4: Error: syntax error, unexpected 'macro'
LOG: lev:4 file:ael.flex line:193 func: ael_yylex File=./extensions.ael, line=222, column=21: Mismatched '}' in expression!
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 222, Cols: 23-23: Error: syntax error, unexpected '=', expecting ')'
LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=228, column=37: Mismatched '}' in expression!
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 235, Cols: 0-6: Error: syntax error, unexpected 'context'
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 344, Cols: 32-32: Error: syntax error, unexpected ';', expecting '{'
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 350, Cols: 32-32: Error: syntax error, unexpected ';', expecting '{'
LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 461, Cols: 10-13: Error: syntax error, unexpected 'else'
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./extensions.ael, line 11-11: goto: no context default could be found that matches the goto target!
LOG: lev:4 file:pbx_ael.c line:2036 func: check_pval_item Error: file ./extensions.ael, line 206-206: macro call to non-existent uvm !
LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 7 syntax errors and 2 semantic errors were detected. It doesn't make sense to compile.
LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities

View File

@ -0,0 +1,13 @@
Executed ast_register_file_version();
LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process.
LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'.
LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'.
LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 6-6: expression Console/dsp has operators, but no variables. Interesting...
LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 10-10: expression pstn-spa3k has operators, but no variables. Interesting...
LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 98-98: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments
LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 107-107: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments
LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 284-284: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments
LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 287-287: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments
LOG: lev:4 file:pbx_ael.c line:2036 func: check_pval_item Error: file ./extensions.ael, line 452-452: macro call to non-existent std-exten-ael !
LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 5 semantic errors were detected. It doesn't make sense to compile.
LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities

14
pbx/ael/ael-test/runtests Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
for i in ael-test*; do
echo -n Test: $i..................
(cd $i; ../../../../utils/aelparse -n -d | grep -v -i 'seconds' > ../res.$i)
if (diff -q res.$i ref.$i > /dev/null 2>&1 ) then
echo PASSED
rm res.$i
else
echo %%%%%%FAILED%%%%%%
diff -u ref.$i res.$i
fi
done

7
pbx/ael/ael-test/setref Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
for i in res.*; do
refname=`echo $i | sed 's/^res/ref/'`
echo $refname
mv $i $refname
done

633
pbx/ael/ael.flex Normal file
View File

@ -0,0 +1,633 @@
%{
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2006, Digium, Inc.
*
* Steve Murphy <murf@parsetree.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Flex scanner description of tokens used in AEL2 .
*
*/#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "asterisk.h"
#include "asterisk/logger.h"
#include "ael.tab.h"
#include "asterisk/ael_structs.h"
static char pbcstack[400];
static int pbcpos = 0;
static int parencount = 0;
static int commaout = 0;
int my_lineno = 1;
int my_col = 0;
char *my_file = 0;
char *prev_word;
#define MAX_INCLUDE_DEPTH 50
void reset_parencount(yyscan_t yyscanner );
void reset_semicount(yyscan_t yyscanner );
void reset_argcount(yyscan_t yyscanner );
struct pval *ael2_parse(char *filename, int *errors);
int ael_yyget_column (yyscan_t yyscanner);
void ael_yyset_column (int column_no , yyscan_t yyscanner);
int ael_yyparse (struct parse_io *);
static void pbcpush(char x);
static int pbcpop(char x);
static void pbcwhere(char *text, int *line, int *col );
static int c_prevword(void);
struct stackelement
{
char *fname;
int lineno;
int colno;
YY_BUFFER_STATE bufstate;
};
struct stackelement include_stack[MAX_INCLUDE_DEPTH];
int include_stack_index = 0;
%}
%x paren semic argg
%option prefix="ael_yy"
%option batch
%option outfile="ael_lex.c"
%option reentrant
%option bison-bridge
%option bison-locations
/* %option yylineno I've tried hard, but haven't been able to use this */
%option noyywrap
%%
\{ {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LC;}
\} {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RC;}
\( {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LP;}
\) {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RP;}
\; {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return SEMI;}
\= {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EQ;}
\, {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COMMA;}
\: {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COLON;}
\& {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AMPER;}
\| {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return BAR;}
\=\> {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EXTENMARK;}
\@ {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AT;}
\/\/[^\n]* {/*comment*/}
context {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTEXT;}
abstract {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ABSTRACT;}
macro {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_MACRO;};
globals {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GLOBALS;}
ignorepat {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IGNOREPAT;}
switch {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCH;}
if {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IF;}
ifTime {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IFTIME;}
random {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RANDOM;}
regexten {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_REGEXTEN;}
hint {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_HINT;}
else {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ELSE;}
goto {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GOTO;}
jump {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_JUMP;}
return {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RETURN;}
break {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_BREAK;}
continue {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTINUE;}
for {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_FOR;}
while {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_WHILE;}
case {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CASE;}
default {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_DEFAULT;}
pattern {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_PATTERN;}
catch {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CATCH;}
switches {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCHES;}
eswitches {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ESWITCHES;}
includes {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_INCLUDES;}
\n {my_lineno++;my_col=0;}
[ ]+ {/* nothing */ my_col+=yyleng;}
[ ]+ {/* nothing */ int wid = 8-(my_col%8); my_col+=wid;}
[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9'"_/.!\*\+\<\>\{\}$#\[\]]* {
yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col; /* set up the ptr */
yylval->str = strdup(yytext);
/* printf("\nGot WORD %s[%d][%d:%d]\n", yylval->str, my_lineno ,yylloc->first_column,yylloc->last_column ); */
my_col+=yyleng;
prev_word = yylval->str;
return word;
}
<paren>[^()\[\]\{\}]*\) {yylloc->first_line = my_lineno; yylloc->first_column=my_col;
if ( pbcpop(')') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno+l4, c4, yytext);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
prev_word = 0;
return word;
}
parencount--;
if ( parencount >= 0) {
yymore();
} else {
int l4,c4;
pbcwhere(yytext, &l4, &c4);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
yylval->str = strdup(yytext);
*(yylval->str+strlen(yylval->str)-1)=0;
/* printf("Got paren word %s\n", yylval->str); */
unput(')');
my_col=c4;
my_lineno += l4;
BEGIN(0);
return word;
}
}
<paren>[^()\[\]\{\}]*\( {yylloc->first_line = my_lineno; yylloc->first_column=my_col;
parencount++; pbcpush('(');
yymore();
}
<paren>[^()\[\]\{\}]*\[ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); }
<paren>[^()\[\]\{\}]*\] {yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop(']') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();
}
<paren>[^()\[\]\{\}]*\{ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{'); }
<paren>[^()\[\]\{\}]*\} {yylloc->first_line = my_lineno;
yylloc->first_column=my_col;
if ( pbcpop('}') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();
}
<argg>[^(),\{\}\[\]]*\) {/* printf("ARGG:%s\n",yytext); */
int linecount = 0;
int colcount = my_col;
char *pt = yytext;
yylloc->first_line = my_lineno;
yylloc->first_column=my_col;
if ( pbcpop(')') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
while (*pt) {
if (*pt == '\n') {
linecount++;
colcount=0;
}
pt++;
colcount++;
}
yylloc->last_line = my_lineno+linecount;
yylloc->last_column=colcount;
parencount--;
if( parencount >= 0){
yymore();
} else {
yylval->str = strdup(yytext);
if(yyleng > 1 )
*(yylval->str+yyleng-1)=0;
/* printf("Got argg word '%s'\n", yylval->str); */
BEGIN(0);
if ( !strcmp(yylval->str,")") ) {
free(yylval->str);
yylval->str = 0;
my_col+=1;
return RP;
} else {
unput(')');
my_col=colcount;
my_lineno+=linecount;
return word;
}
}
}
<argg>[^(),\{\}\[\]]*\( { /* printf("ARGG:%s\n",yytext); */
/* printf("GOT AN LP!!!\n"); */
yylloc->first_line = my_lineno;
yylloc->first_column=my_col;
parencount++;
pbcpush('(');
yymore();
}
<argg>[^(),\{\}\[\]]*\, { /* printf("ARGG:%s\n",yytext); */
if( parencount != 0) {
/* printf("Folding in a comma!\n"); */
yymore();
} else {
/* printf("got a comma!\n\n"); */
int linecount = 0;
int colcount = my_col;
char *pt;
pt = yytext;
while (*pt) {
if ( *pt == '\n' ) {
linecount++;
colcount=0;
}
pt++;
colcount++;
}
yylloc->first_line = my_lineno;
yylloc->last_line = my_lineno+linecount;
yylloc->last_column=colcount;
yylloc->first_column=my_col;
if( !commaout ) {
if( !strcmp(yytext,"," ) )
{commaout = 0; my_col+=1; return COMMA;}
yylval->str = strdup(yytext); /* printf("Got argg2 word %s\n", yylval->str); */
unput(',');
commaout = 1;
if(yyleng > 1 )
*(yylval->str+yyleng-1)=0;
my_lineno+=linecount;
my_col=colcount;
return word;
} else {
commaout = 0;
my_col+=1;
return COMMA;
}
}
}
<argg>[^(),\{\}\[\]]*\{ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; pbcpush('{'); yymore(); }
<argg>[^(),\{\}\[\]]*\} {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop('}') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=my_col+c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();
}
<argg>[^(),\{\}\[\]]*\[ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); }
<argg>[^(),\{\}\[\]]*\] {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop(']') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();
}
<semic>[^;()\{\}\[\]]*\[ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); }
<semic>[^;()\{\}\[\]]*\] {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop(']') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();}
<semic>[^;()\{\}\[\]]*\{ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{');}
<semic>[^;()\{\}\[\]]*\} {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop('}') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=my_col+c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();}
<semic>[^;()\{\}\[\]]*\( {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('(');}
<semic>[^;()\{\}\[\]]*\) {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col;
if ( pbcpop(')') ) {
/* error */
int l4,c4;
pbcwhere(yytext, &l4, &c4);
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, my_col+c4);
BEGIN(0);
yylloc->last_line = my_lineno+l4;
yylloc->last_column=my_col+c4;
my_col=c4;
my_lineno += l4;
yylval->str = strdup(yytext);
return word;
}
yymore();}
<semic>[^;()\{\}\[\]]*; {
int linecount = 0;
int colcount = my_col;
char *pt = yytext;
while (*pt) {
if ( *pt == '\n' ) {
linecount++;
colcount=0;
}
pt++;
colcount++;
}
yylloc->first_line = my_lineno;
yylloc->last_line = my_lineno+linecount;
yylloc->last_column=colcount;
yylloc->first_column=my_col;
yylval->str = strdup(yytext);
if(yyleng > 1)
*(yylval->str+yyleng-1)=0;
/* printf("Got semic word %s\n", yylval->str); */
unput(';');
BEGIN(0);
my_col=colcount;
my_lineno += linecount;
return word;
}
\#include[ \t]+\"[^\"]+\" {
FILE *in1;
char fnamebuf[1024],*p1,*p2;
if ( include_stack_index >= MAX_INCLUDE_DEPTH ) {
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Includes nested too deeply! Wow!!! How did you do that?\n", my_file, my_lineno, my_col);
} else {
p1 = strchr(yytext,'"');
p2 = strrchr(yytext,'"');
if ( (int)(p2-p1) > 1023 ) {
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Filename is incredibly way too long (%d chars!). Inclusion ignored!\n", my_file, my_lineno, my_col, yyleng - 10);
} else {
int i;
int found = 0;
strncpy(fnamebuf,p1,p2-p1);
fnamebuf[p2-p1] = 0;
for (i=0; i<include_stack_index; i++) {
if ( !strcmp(fnamebuf,include_stack[i].fname )) {
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Nice Try!!! But %s has already been included (perhaps by another file), and would cause an infinite loop of file inclusions!!! Include directive ignored\n",
my_file, my_lineno, my_col, fnamebuf);
found=1;
break;
}
}
if( !found )
{
*p2 = 0;
/* relative vs. absolute */
if ( *(p1+1) != '/' )
{
strcpy(fnamebuf,ast_config_AST_CONFIG_DIR);
strcat(fnamebuf,"/");
strcat(fnamebuf,p1+1);
}
else
strcpy(fnamebuf,p1+1);
in1 = fopen( fnamebuf, "r" );
if ( ! in1 ) {
ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Couldn't find the include file: %s; ignoring the Include directive!\n", my_file, my_lineno, my_col, fnamebuf);
} else {
char *buffer;
struct stat stats;
stat(fnamebuf, &stats);
buffer = (char*)malloc(stats.st_size+1);
fread(buffer, 1, stats.st_size, in1);
buffer[stats.st_size] = 0;
ast_log(LOG_NOTICE," --Read in included file %s, %d chars\n",fnamebuf, (int)stats.st_size);
fclose(in1);
include_stack[include_stack_index].fname = my_file;
my_file = strdup(fnamebuf);
include_stack[include_stack_index].lineno = my_lineno;
include_stack[include_stack_index].colno = my_col+yyleng;
include_stack[include_stack_index++].bufstate = YY_CURRENT_BUFFER;
yy_switch_to_buffer(ael_yy_scan_string (buffer ,yyscanner),yyscanner);
free(buffer);
my_lineno = 1;
my_col = 1;
BEGIN(INITIAL);
}
}
}
}
}
<<EOF>> {
if ( --include_stack_index < 0 ) {
yyterminate();
} else {
free(my_file);
yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
yy_switch_to_buffer(include_stack[include_stack_index].bufstate, yyscanner );
my_lineno = include_stack[include_stack_index].lineno;
my_col = include_stack[include_stack_index].colno;
my_file = include_stack[include_stack_index].fname;
}
}
%%
static void pbcpush(char x)
{
pbcstack[pbcpos++] = x;
}
static int pbcpop(char x)
{
if ( ( x == ')' && pbcstack[pbcpos-1] == '(' )
|| ( x == ']' && pbcstack[pbcpos-1] == '[' )
|| ( x == '}' && pbcstack[pbcpos-1] == '{' )) {
pbcpos--;
return 0;
}
else
return 1; /* error */
}
static int c_prevword(void)
{
char *c = prev_word;
int ret = 0;
while ( c && *c ) {
switch (*c) {
case '{': pbcpush('{');break;
case '}': ret = pbcpop('}');break;
case '[':pbcpush('[');break;
case ']':ret = pbcpop(']');break;
case '(':pbcpush('(');break;
case ')':ret = pbcpop(')'); break;
}
if( ret )
return 1;
c++;
}
return 0;
}
static void pbcwhere(char *text, int *line, int *col )
{
int loc_line = 0;
int loc_col = 0;
while ( *text ) {
if ( *text == '\n' ) {
loc_line++;
loc_col = 1;
} else {
loc_col++;
}
text++;
}
*line = loc_line;
*col = loc_col;
}
void reset_parencount(yyscan_t yyscanner )
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
parencount = 0;
pbcpos = 0;
pbcpush('(');
c_prevword();
BEGIN(paren);
}
void reset_semicount(yyscan_t yyscanner )
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
pbcpos = 0;
BEGIN(semic);
}
void reset_argcount(yyscan_t yyscanner )
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
parencount = 0;
pbcpos = 0;
commaout = 0;
pbcpush('(');
c_prevword();
BEGIN(argg);
}
struct pval *ael2_parse(char *filename, int *errors)
{
struct pval *pval;
struct parse_io *io;
char *buffer;
struct stat stats;
FILE *fin;
/* extern int ael_yydebug; */
io = calloc(sizeof(struct parse_io),1);
/* reset the global counters */
prev_word = 0;
my_lineno = 1;
include_stack_index=0;
my_col = 0;
/* ael_yydebug = 1; */
ael_yylex_init(&io->scanner);
fin = fopen(filename,"r");
if ( !fin ) {
ast_log(LOG_ERROR,"File %s could not be opened\n", filename);
*errors = 1;
return 0;
}
my_file = strdup(filename);
stat(filename, &stats);
buffer = (char*)malloc(stats.st_size+2);
fread(buffer, 1, stats.st_size, fin);
buffer[stats.st_size]=0;
fclose(fin);
ael_yy_scan_string (buffer ,io->scanner);
ael_yyset_lineno(1 , io->scanner);
/* ael_yyset_in (fin , io->scanner); OLD WAY */
ael_yyparse(io);
pval = io->pval;
*errors = io->syntax_error_count;
ael_yylex_destroy(io->scanner);
free(buffer);
free(io);
return pval;
}

3192
pbx/ael/ael.tab.c Normal file

File diff suppressed because it is too large Load Diff

147
pbx/ael/ael.tab.h Normal file
View File

@ -0,0 +1,147 @@
/* A Bison parser, made by GNU Bison 2.1. */
/* Skeleton parser for Yacc-like parsing with Bison,
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* As a special exception, when this file is copied by Bison into a
Bison output file, you may use that output file without restriction.
This special exception was added by the Free Software Foundation
in version 1.24 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
KW_CONTEXT = 258,
LC = 259,
RC = 260,
LP = 261,
RP = 262,
SEMI = 263,
EQ = 264,
COMMA = 265,
COLON = 266,
AMPER = 267,
BAR = 268,
AT = 269,
KW_MACRO = 270,
KW_GLOBALS = 271,
KW_IGNOREPAT = 272,
KW_SWITCH = 273,
KW_IF = 274,
KW_IFTIME = 275,
KW_ELSE = 276,
KW_RANDOM = 277,
KW_ABSTRACT = 278,
EXTENMARK = 279,
KW_GOTO = 280,
KW_JUMP = 281,
KW_RETURN = 282,
KW_BREAK = 283,
KW_CONTINUE = 284,
KW_REGEXTEN = 285,
KW_HINT = 286,
KW_FOR = 287,
KW_WHILE = 288,
KW_CASE = 289,
KW_PATTERN = 290,
KW_DEFAULT = 291,
KW_CATCH = 292,
KW_SWITCHES = 293,
KW_ESWITCHES = 294,
KW_INCLUDES = 295,
word = 296
};
#endif
/* Tokens. */
#define KW_CONTEXT 258
#define LC 259
#define RC 260
#define LP 261
#define RP 262
#define SEMI 263
#define EQ 264
#define COMMA 265
#define COLON 266
#define AMPER 267
#define BAR 268
#define AT 269
#define KW_MACRO 270
#define KW_GLOBALS 271
#define KW_IGNOREPAT 272
#define KW_SWITCH 273
#define KW_IF 274
#define KW_IFTIME 275
#define KW_ELSE 276
#define KW_RANDOM 277
#define KW_ABSTRACT 278
#define EXTENMARK 279
#define KW_GOTO 280
#define KW_JUMP 281
#define KW_RETURN 282
#define KW_BREAK 283
#define KW_CONTINUE 284
#define KW_REGEXTEN 285
#define KW_HINT 286
#define KW_FOR 287
#define KW_WHILE 288
#define KW_CASE 289
#define KW_PATTERN 290
#define KW_DEFAULT 291
#define KW_CATCH 292
#define KW_SWITCHES 293
#define KW_ESWITCHES 294
#define KW_INCLUDES 295
#define word 296
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 47 "ael.y"
typedef union YYSTYPE {
char *str;
struct pval *pval;
} YYSTYPE;
/* Line 1447 of yacc.c. */
#line 125 "ael.tab.h"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED)
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif

705
pbx/ael/ael.y Normal file
View File

@ -0,0 +1,705 @@
%{
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2006, Digium, Inc.
*
* Steve Murphy <murf@parsetree.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Bison Grammar description of AEL2.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asterisk/logger.h"
#include "asterisk/ael_structs.h"
extern void reset_parencount(yyscan_t yyscanner);
extern void reset_semicount(yyscan_t yyscanner);
extern void reset_argcount(yyscan_t yyscanner );
#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
#define YYERROR_VERBOSE 1
extern char *my_file;
#ifdef AAL_ARGCHECK
int ael_is_funcname(char *name);
#endif
static char *ael_token_subst(char *mess);
extern char *prev_word;
%}
%union {
char *str;
struct pval *pval;
}
%{
/* declaring these AFTER the union makes things a lot simpler! */
void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s);
int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner);
%}
%token KW_CONTEXT LC RC LP RP SEMI EQ COMMA COLON AMPER BAR AT
%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT
%token EXTENMARK KW_GOTO KW_JUMP KW_RETURN KW_BREAK KW_CONTINUE KW_REGEXTEN KW_HINT
%token KW_FOR KW_WHILE KW_CASE KW_PATTERN KW_DEFAULT KW_CATCH KW_SWITCHES KW_ESWITCHES
%token KW_INCLUDES
%token <str> word
%type <pval>includes
%type <pval>includeslist
%type <pval>switchlist
%type <pval>eswitches
%type <pval>switches
%type <pval>macro_statement
%type <pval>macro_statements
%type <pval>case_statement
%type <pval>case_statements
%type <pval>eval_arglist
%type <pval>application_call
%type <pval>application_call_head
%type <pval>macro_call
%type <pval>target jumptarget
%type <pval>statement
%type <pval>switch_head
%type <str>word_list goto_word
%type <str>word3_list
%type <str>includedname
%type <pval>if_head
%type <pval>random_head
%type <pval>iftime_head
%type <pval>statements
%type <pval>extension
%type <pval>ignorepat
%type <pval>element
%type <pval>elements
%type <pval>arglist
%type <pval>global_statement
%type <pval>global_statements
%type <pval>globals
%type <pval>macro
%type <pval>context
%type <pval>object
%type <pval>objects
%type <pval>file
/* OPTIONS */
%locations
%pure-parser
%name-prefix="ael_yy"
/* the following option does two things:
it adds the locp arg to the yyerror
and it adds the NULL to the yyerrr arg list, and calls yyerror with NULL for that arg.
You can't get the locp arg without the NULL arg, don't ask me why. */
%parse-param {struct parse_io *parseio}
/* there will be two shift/reduce conflicts, they involve the if statement, where a single statement occurs not wrapped in curlies in the "true" section
the default action to shift will attach the else to the preceeding if. */
%expect 5
%error-verbose
%destructor { if (yymsg[0] != 'C') {destroy_pval($$); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} } includes includeslist switchlist eswitches switches macro_statement macro_statements case_statement case_statements eval_arglist application_call
application_call_head macro_call target jumptarget statement switch_head if_head random_head iftime_head statements extension ignorepat element
elements arglist global_statement global_statements globals macro context object objects
%destructor { free($$);} word word_list goto_word word3_list includedname
%%
file : objects { $$ = parseio->pval = $1; }
;
objects : object {$$=$1;}
| objects object {if ( $1 && $2 ) {$$=$1; linku1($$,$2);}
else if ( $1 ) {$$=$1;}
else if ( $2 ) {$$=$2;} }
| objects error {$$=$1;}
;
object : context {$$=$1;}
| macro {$$=$1;}
| globals {$$=$1;}
| SEMI {$$=0;/* allow older docs to be read */}
;
context : KW_CONTEXT word LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $2; $$->u2.statements = $4; }
| KW_CONTEXT word LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = $2; }
| KW_CONTEXT KW_DEFAULT LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = strdup("default"); $$->u2.statements = $4; }
| KW_CONTEXT KW_DEFAULT LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = strdup("default"); }
| KW_ABSTRACT KW_CONTEXT word LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = $3; $$->u2.statements = $5; $$->u3.abstract = 1;}
| KW_ABSTRACT KW_CONTEXT word LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $3; $$->u3.abstract = 1; }
| KW_ABSTRACT KW_CONTEXT KW_DEFAULT LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = strdup("default"); $$->u2.statements = $5; $$->u3.abstract = 1; }
| KW_ABSTRACT KW_CONTEXT KW_DEFAULT LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = strdup("default"); $$->u3.abstract = 1; }
;
macro : KW_MACRO word LP arglist RP LC macro_statements RC {$$=npval(PV_MACRO,@1.first_line,@8.last_line, @1.first_column, @8.last_column);
$$->u1.str = $2; $$->u2.arglist = $4; $$->u3.macro_statements = $7; }
| KW_MACRO word LP arglist RP LC RC {$$=npval(PV_MACRO,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $2; $$->u2.arglist = $4; }
| KW_MACRO word LP RP LC macro_statements RC {$$=npval(PV_MACRO,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $2; $$->u3.macro_statements = $6; }
| KW_MACRO word LP RP LC RC {$$=npval(PV_MACRO,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = $2; /* pretty empty! */ }
;
globals : KW_GLOBALS LC global_statements RC {$$=npval(PV_GLOBALS,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.statements = $3;}
| KW_GLOBALS LC RC /* empty global is OK */ {$$=npval(PV_GLOBALS,@1.first_line,@3.last_line, @1.first_column, @3.last_column); /* and that's all */ }
;
global_statements : global_statement {$$=$1;}
| global_statements global_statement {$$=$1; linku1($$,$2);}
| global_statements error {$$=$1;}
;
global_statement : word EQ { reset_semicount(parseio->scanner); } word SEMI {$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $1;$$->u2.val = $4; }
;
arglist : word {$$= npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1; }
| arglist COMMA word {pval *z = npval(PV_WORD,@1.first_line,@3.last_line, @1.first_column, @3.last_column); z->u1.str = $3; $$=$1; linku1($$,z); }
| arglist error {$$=$1;}
;
elements : element { $$=$1;}
| error {$$=0;}
| elements element { if ( $1 && $2 ) {$$=$1; linku1($$,$2);}
else if ( $1 ) {$$=$1;}
else if ( $2 ) {$$=$2;} }
| elements error { $$=$1;}
;
element : extension {$$=$1;}
| includes {$$=$1;}
| switches {$$=$1;}
| eswitches {$$=$1;}
| ignorepat {$$=$1;}
| word EQ { reset_semicount(parseio->scanner); } word SEMI {$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $1;$$->u2.val = $4; }
| word error {free($1); $$=0;}
| SEMI {$$=0;/* allow older docs to be read */}
;
ignorepat : KW_IGNOREPAT EXTENMARK word SEMI { $$=npval(PV_IGNOREPAT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = $3;}
;
extension : word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $1; $$->u2.statements = $3; }
| KW_REGEXTEN word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@3.last_line, @1.first_column, @4.last_column); $$->u1.str = $2; $$->u2.statements = $4; $$->u4.regexten=1;}
| KW_HINT LP word3_list RP word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $5; $$->u2.statements = $7; $$->u3.hints = $3;}
| KW_REGEXTEN KW_HINT LP word3_list RP word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@4.last_line, @1.first_column, @8.last_column); $$->u1.str = $6; $$->u2.statements = $8; $$->u4.regexten=1;$$->u3.hints = $4;}
;
statements : statement {$$=$1;}
| statements statement {if ( $1 && $2 ) {$$=$1; linku1($$,$2);}
else if ( $1 ) {$$=$1;}
else if ( $2 ) {$$=$2;} }
| statements error {$$=$1;}
;
if_head : KW_IF LP { reset_parencount(parseio->scanner); } word_list RP { $$= npval(PV_IF,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $4; }
;
random_head : KW_RANDOM LP { reset_parencount(parseio->scanner); } word_list RP { $$= npval(PV_RANDOM,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str=$4;}
;
iftime_head : KW_IFTIME LP word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list RP { $$= npval(PV_IFTIME,@1.first_line,@5.last_line, @1.first_column, @5.last_column);
$$->u1.list = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->u1.list->u1.str = (char*)malloc(strlen($3)+strlen($5)+strlen($7)+4);
strcpy($$->u1.list->u1.str,$3);
strcat($$->u1.list->u1.str,":");
strcat($$->u1.list->u1.str,$5);
strcat($$->u1.list->u1.str,":");
strcat($$->u1.list->u1.str,$7);
free($3);
free($5);
free($7);
$$->u1.list->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column);
$$->u1.list->next->u1.str = $9;
$$->u1.list->next->next = npval(PV_WORD,@11.first_line,@11.last_line, @11.first_column, @11.last_column);
$$->u1.list->next->next->u1.str = $11;
$$->u1.list->next->next->next = npval(PV_WORD,@13.first_line,@13.last_line, @13.first_column, @13.last_column);
$$->u1.list->next->next->next->u1.str = $13;
prev_word = 0;
}
| KW_IFTIME LP word BAR word3_list BAR word3_list BAR word3_list RP { $$= npval(PV_IFTIME,@1.first_line,@5.last_line, @1.first_column, @5.last_column);
$$->u1.list = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->u1.list->u1.str = $3;
$$->u1.list->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->u1.list->next->u1.str = $5;
$$->u1.list->next->next = npval(PV_WORD,@7.first_line,@7.last_line, @7.first_column, @7.last_column);
$$->u1.list->next->next->u1.str = $7;
$$->u1.list->next->next->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column);
$$->u1.list->next->next->next->u1.str = $9;
prev_word = 0;
}
;
/* word_list is a hack to fix a problem with context switching between bison and flex;
by the time you register a new context with flex, you've already got a look-ahead token
from the old context, with no way to put it back and start afresh. So, we kludge this
and merge the words back together. */
word_list : word { $$ = $1;}
| word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);prev_word = $$;}
;
word3_list : word { $$ = $1;}
| word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);prev_word = $$;}
| word word word { $$ = (char*)malloc(strlen($1)+strlen($2)+strlen($3)+1); strcpy($$, $1); strcat($$, $2); strcat($$, $3); free($1); free($2); free($3);prev_word=$$;}
;
goto_word : word { $$ = $1;}
| word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);}
| word COLON word { $$ = (char*)malloc(strlen($1)+strlen($3)+2); strcpy($$, $1); strcat($$,":"); strcat($$, $3); free($1); free($3);}
;
switch_head : KW_SWITCH LP { reset_parencount(parseio->scanner); } word RP LC
{$$=npval(PV_SWITCH,@1.first_line,@6.last_line, @1.first_column, @6.last_column);
$$->u1.str = $4; }
;
statement : LC statements RC {$$=npval(PV_STATEMENTBLOCK,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2; }
| word EQ {reset_semicount(parseio->scanner);} word SEMI
{$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column);
$$->u1.str = $1; $$->u2.val = $4; }
| KW_GOTO target SEMI {$$=npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2;}
| KW_JUMP jumptarget SEMI {$$=npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2;}
| word COLON {$$=npval(PV_LABEL,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1; }
| KW_FOR LP {reset_semicount(parseio->scanner);} word SEMI
{reset_semicount(parseio->scanner);} word SEMI
{reset_parencount(parseio->scanner);} word RP statement
{ $$=npval(PV_FOR,@1.first_line,@12.last_line, @1.first_column, @12.last_column);
$$->u1.for_init = $4; $$->u2.for_test=$7; $$->u3.for_inc = $10; $$->u4.for_statements = $12;}
| KW_WHILE LP {reset_parencount(parseio->scanner);} word RP statement
{$$=npval(PV_WHILE,@1.first_line,@6.last_line, @1.first_column, @6.last_column);
$$->u1.str = $4; $$->u2.statements = $6; }
| switch_head RC /* empty list OK */ {$$=$1;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| switch_head case_statements RC {$$=$1; $$->u2.statements = $2;$$->endline = @3.last_line; $$->endcol = @3.last_column;}
| AMPER macro_call SEMI {$$ = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| application_call SEMI { $$ = $1;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| word SEMI { $$= npval(PV_APPLICATION_CALL,@1.first_line,@2.last_line, @1.first_column, @2.last_column);
$$->u1.str = $1;}
| application_call EQ {reset_semicount(parseio->scanner);} word SEMI {
char *bufx;
int tot=0;
pval *pptr;
$$ = npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column);
$$->u2.val=$4;
/* rebuild the original string-- this is not an app call, it's an unwrapped vardec, with a func call on the LHS */
/* string to big to fit in the buffer? */
tot+=strlen($1->u1.str);
for(pptr=$1->u2.arglist;pptr;pptr=pptr->next) {
tot+=strlen(pptr->u1.str);
tot++; /* for a sep like a comma */
}
tot+=4; /* for safety */
bufx = (char *)malloc(tot);
strcpy(bufx,$1->u1.str);
strcat(bufx,"(");
for (pptr=$1->u2.arglist;pptr;pptr=pptr->next) {
if ( pptr != $1->u2.arglist )
strcat(bufx,",");
strcat(bufx,pptr->u1.str);
}
strcat(bufx,")");
#ifdef AAL_ARGCHECK
if ( !ael_is_funcname($1->u1.str) )
ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Function call? The name %s is not in my internal list of function names\n",
my_file, @1.first_line, @1.first_column, @1.last_column, $1->u1.str);
#endif
$$->u1.str = bufx;
destroy_pval($1); /* the app call it is not, get rid of that chain */
prev_word = 0;
}
| KW_BREAK SEMI { $$ = npval(PV_BREAK,@1.first_line,@2.last_line, @1.first_column, @2.last_column);}
| KW_RETURN SEMI {$$ = npval(PV_RETURN,@1.first_line,@2.last_line, @1.first_column, @2.last_column);}
| KW_CONTINUE SEMI {$$ = npval(PV_CONTINUE,@1.first_line,@2.last_line, @1.first_column, @2.last_column);}
| random_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| random_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;}
| if_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| if_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;}
| iftime_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
| iftime_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;}
| SEMI { $$=0; }
;
target : goto_word { $$ = npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1;}
| goto_word BAR goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;}
| goto_word COMMA goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;}
| goto_word BAR goto_word BAR goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $5; }
| goto_word COMMA goto_word COMMA goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $5; }
| KW_DEFAULT BAR goto_word BAR goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $5; }
| KW_DEFAULT COMMA goto_word COMMA goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $5; }
;
jumptarget : goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->next->u1.str = strdup("1");} /* jump extension[,priority][@context] */
| goto_word COMMA goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $3;}
| goto_word COMMA word AT word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $5; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $1;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $3; }
| goto_word AT goto_word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = $3; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $1;
$$->next->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->next->u1.str = strdup("1"); }
| goto_word COMMA word AT KW_DEFAULT {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $1;
$$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->next->next->u1.str = $3; }
| goto_word AT KW_DEFAULT {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column);
$$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->u1.str = $1;
$$->next->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->next->next->u1.str = strdup("1"); }
;
macro_call : word LP {reset_argcount(parseio->scanner);} eval_arglist RP
{$$= npval(PV_MACRO_CALL,@1.first_line,@2.last_line, @1.first_column, @2.last_column);
$$->u1.str = $1; $$->u2.arglist = $4;}
| word LP RP {$$= npval(PV_MACRO_CALL,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $1; }
;
application_call_head: word {reset_argcount(parseio->scanner);} LP {if (strcasecmp($1,"goto") == 0) {
$$= npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column);
free($1); /* won't be using this */
ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Suggestion: Use the goto statement instead of the Goto() application call in AEL.\n", my_file, @1.first_line, @1.first_column, @1.last_column );
} else
$$= npval(PV_APPLICATION_CALL,@1.first_line,@3.last_line, @1.first_column, @3.last_column);
$$->u1.str = $1; }
;
application_call : application_call_head eval_arglist RP {$$ = $1;
if( $$->type == PV_GOTO )
$$->u1.list = $2;
else
$$->u2.arglist = $2;
$$->endline = @3.last_line; $$->endcol = @3.last_column;}
| application_call_head RP {$$=$1;$$->endline = @2.last_line; $$->endcol = @2.last_column;}
;
eval_arglist : word_list { $$= npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1;}
| /*nothing! */ { $$= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/); $$->u1.str = strdup(""); }
| eval_arglist COMMA word { pval *z = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); $$ = $1; linku1($1,z); z->u1.str = $3;}
| eval_arglist COMMA { pval *z = npval(PV_WORD,@2.first_line,@2.last_line, @2.first_column, @2.last_column); $$ = $1; linku1($1,z); z->u1.str = strdup("");}
;
case_statements: case_statement {$$=$1;}
| case_statements case_statement { if ( $1 && $2 ) {$$=$1; linku1($$,$2);}
else if ( $1 ) {$$=$1;}
else if ( $2 ) {$$=$2;} }
;
case_statement: KW_CASE word COLON statements {$$ = npval(PV_CASE,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2; $$->u2.statements = $4;}
| KW_DEFAULT COLON statements {$$ = npval(PV_DEFAULT,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = 0; $$->u2.statements = $3;}
| KW_PATTERN word COLON statements {$$ = npval(PV_PATTERN,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2; $$->u2.statements = $4;}
| KW_CASE word COLON {$$ = npval(PV_CASE,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2;}
| KW_DEFAULT COLON {$$ = npval(PV_DEFAULT,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = 0;}
| KW_PATTERN word COLON {$$ = npval(PV_PATTERN,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2;}
;
macro_statements: macro_statement {$$ = $1;}
| macro_statements macro_statement { if ( $1 && $2 ) {$$=$1; linku1($$,$2);}
else if ( $1 ) {$$=$1;}
else if ( $2 ) {$$=$2;} }
;
macro_statement : statement {$$=$1;}
| KW_CATCH word LC statements RC {$$=npval(PV_CATCH,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $2; $$->u2.statements = $4;}
;
switches : KW_SWITCHES LC switchlist RC {$$= npval(PV_SWITCHES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3; }
| KW_SWITCHES LC RC /* empty switch list OK */ {$$= npval(PV_SWITCHES,@1.first_line,@3.last_line, @1.first_column, @3.last_column);}
;
eswitches : KW_ESWITCHES LC switchlist RC {$$= npval(PV_ESWITCHES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3; }
| KW_ESWITCHES LC RC /* empty switch list OK */ {$$= npval(PV_ESWITCHES,@1.first_line,@3.last_line, @1.first_column, @3.last_column); } /* if there's nothing to declare, why include it? */
;
switchlist : word SEMI {$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1;}
| switchlist word SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column); $$=$1; z->u1.str = $2; linku1($$,z); }
| switchlist error {$$=$1;}
;
includeslist : includedname SEMI {$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1;}
| includedname BAR word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list SEMI {
$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column);
$$->u1.str = $1;
$$->u2.arglist = npval(PV_WORD,@3.first_line,@7.last_line, @3.first_column, @7.last_column);
$$->u2.arglist->u1.str = (char*)malloc(strlen($3)+strlen($5)+strlen($7)+4);
strcpy($$->u2.arglist->u1.str,$3);
strcat($$->u2.arglist->u1.str,":");
strcat($$->u2.arglist->u1.str,$5);
strcat($$->u2.arglist->u1.str,":");
strcat($$->u2.arglist->u1.str,$7);
free($3);
free($5);
free($7);
$$->u2.arglist->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column);
$$->u2.arglist->next->u1.str = $9;
$$->u2.arglist->next->next = npval(PV_WORD,@11.first_line,@11.last_line, @11.first_column, @11.last_column);
$$->u2.arglist->next->next->u1.str = $11;
$$->u2.arglist->next->next->next = npval(PV_WORD,@13.first_line,@13.last_line, @13.first_column, @13.last_column);
$$->u2.arglist->next->next->next->u1.str = $13;
prev_word=0;
}
| includedname BAR word BAR word3_list BAR word3_list BAR word3_list SEMI {
$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column);
$$->u1.str = $1;
$$->u2.arglist = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column);
$$->u2.arglist->u1.str = $3;
$$->u2.arglist->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column);
$$->u2.arglist->next->u1.str = $5;
$$->u2.arglist->next->next = npval(PV_WORD,@7.first_line,@7.last_line, @7.first_column, @7.last_column);
$$->u2.arglist->next->next->u1.str = $7;
$$->u2.arglist->next->next->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column);
$$->u2.arglist->next->next->next->u1.str = $9;
prev_word=0;
}
| includeslist includedname SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column); $$=$1; z->u1.str = $2; linku1($$,z); }
| includeslist includedname BAR word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column);
$$=$1; z->u1.str = $2; linku1($$,z);
z->u2.arglist = npval(PV_WORD,@4.first_line,@4.last_line, @4.first_column, @4.last_column);
$$->u2.arglist->u1.str = (char*)malloc(strlen($4)+strlen($6)+strlen($8)+4);
strcpy($$->u2.arglist->u1.str,$4);
strcat($$->u2.arglist->u1.str,":");
strcat($$->u2.arglist->u1.str,$6);
strcat($$->u2.arglist->u1.str,":");
strcat($$->u2.arglist->u1.str,$8);
free($4);
free($6);
free($8);
z->u2.arglist->next = npval(PV_WORD,@10.first_line,@10.last_line, @10.first_column, @10.last_column);
z->u2.arglist->next->u1.str = $10;
z->u2.arglist->next->next = npval(PV_WORD,@12.first_line,@12.last_line, @12.first_column, @12.last_column);
z->u2.arglist->next->next->u1.str = $12;
z->u2.arglist->next->next->next = npval(PV_WORD,@14.first_line,@14.last_line, @14.first_column, @14.last_column);
z->u2.arglist->next->next->next->u1.str = $14;
prev_word=0;
}
| includeslist includedname BAR word BAR word3_list BAR word3_list BAR word3_list SEMI
{pval *z = npval(PV_WORD,@2.first_line,@2.last_line, @2.first_column, @3.last_column);
$$=$1; z->u1.str = $2; linku1($$,z);
z->u2.arglist = npval(PV_WORD,@4.first_line,@4.last_line, @4.first_column, @4.last_column);
$$->u2.arglist->u1.str = $4;
z->u2.arglist->next = npval(PV_WORD,@6.first_line,@6.last_line, @6.first_column, @6.last_column);
z->u2.arglist->next->u1.str = $6;
z->u2.arglist->next->next = npval(PV_WORD,@8.first_line,@8.last_line, @8.first_column, @8.last_column);
z->u2.arglist->next->next->u1.str = $8;
z->u2.arglist->next->next->next = npval(PV_WORD,@10.first_line,@10.last_line, @10.first_column, @10.last_column);
z->u2.arglist->next->next->next->u1.str = $10;
prev_word=0;
}
| includeslist error {$$=$1;}
;
includedname : word { $$ = $1;}
| KW_DEFAULT {$$=strdup("default");}
;
includes : KW_INCLUDES LC includeslist RC {$$= npval(PV_INCLUDES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3;}
| KW_INCLUDES LC RC {$$= npval(PV_INCLUDES,@1.first_line,@3.last_line, @1.first_column, @3.last_column);}
;
%%
static char *token_equivs1[] =
{
"AMPER",
"AT",
"BAR",
"COLON",
"COMMA",
"EQ",
"EXTENMARK",
"KW_BREAK",
"KW_CASE",
"KW_CATCH",
"KW_CONTEXT",
"KW_CONTINUE",
"KW_DEFAULT",
"KW_ELSE",
"KW_ESWITCHES",
"KW_FOR",
"KW_GLOBALS",
"KW_GOTO",
"KW_HINT",
"KW_IFTIME",
"KW_IF",
"KW_IGNOREPAT",
"KW_INCLUDES"
"KW_JUMP",
"KW_MACRO",
"KW_PATTERN",
"KW_REGEXTEN",
"KW_RETURN",
"KW_SWITCHES",
"KW_SWITCH",
"KW_WHILE",
"LC",
"LP",
"RC",
"RP",
"SEMI",
};
static char *token_equivs2[] =
{
"&",
"@",
"|",
":",
",",
"=",
"=>",
"break",
"case",
"catch",
"context",
"continue",
"default",
"else",
"eswitches",
"for",
"globals",
"goto",
"hint",
"ifTime",
"if",
"ignorepat",
"includes"
"jump",
"macro",
"pattern",
"regexten",
"return",
"switches",
"switch",
"while",
"{",
"(",
"}",
")",
";",
};
static char *ael_token_subst(char *mess)
{
/* calc a length, malloc, fill, and return; yyerror had better free it! */
int len=0,i;
char *p;
char *res, *s,*t;
int token_equivs_entries = sizeof(token_equivs1)/sizeof(char*);
for (p=mess; *p; p++) {
for (i=0; i<token_equivs_entries; i++) {
if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 )
{
len+=strlen(token_equivs2[i])+2;
p += strlen(token_equivs1[i])-1;
break;
}
}
len++;
}
res = (char*)malloc(len+1);
res[0] = 0;
s = res;
for (p=mess; *p;) {
int found = 0;
for (i=0; i<token_equivs_entries; i++) {
if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) {
*s++ = '\'';
for (t=token_equivs2[i]; *t;) {
*s++ = *t++;
}
*s++ = '\'';
p += strlen(token_equivs1[i]);
found = 1;
break;
}
}
if( !found )
*s++ = *p++;
}
*s++ = 0;
return res;
}
void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s)
{
char *s2 = ael_token_subst((char *)s);
if (locp->first_line == locp->last_line) {
ast_log(LOG_ERROR, "==== File: %s, Line %d, Cols: %d-%d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_column, s2);
} else {
ast_log(LOG_ERROR, "==== File: %s, Line %d Col %d to Line %d Col %d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column, s2);
}
free(s2);
parseio->syntax_error_count++;
}
struct pval *npval(pvaltype type,int first_line, int last_line, int first_column, int last_column)
{
extern char *my_file;
pval *z = (pval *)calloc(sizeof(struct pval),1);
z->type = type;
z->startline = first_line;
z->endline = last_line;
z->startcol = first_column;
z->endcol = last_column;
z->filename = strdup(my_file);
return z;
}
void linku1(pval *head, pval *tail)
{
if (!head->next) {
head->next = tail;
head->u1_last = tail;
} else {
head->u1_last->next = tail;
head->u1_last = tail;
}
}

2996
pbx/ael/ael_lex.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -66,6 +66,22 @@ ast_expr2f.o: ../ast_expr2f.c
check_expr: check_expr.c ast_expr2.o ast_expr2f.o
$(CC) $(CFLAGS) -o $@ $^
aelparse : ../pbx/ael/aelflex.o ../pbx/ael/aelbison.o ../pbx/pbx_ael.o ael_main.o ../ast_expr2f.o ../ast_expr2.o
$(CC) $(CFLAGS) -g -o aelparse ../pbx/ael/aelflex.o ../pbx/ael/aelbison.o ael_main.o ../pbx/pbx_ael.o ../ast_expr2f.o ../ast_expr2.o
ael_main.o : ael_main.c ../include/asterisk/ael_structs.h
$(CC) $(CFLAGS) -c -g -o ael_main.o ael_main.c
ael_main1.o : ael_main.c ../include/asterisk/ael_structs.h
$(CC) $(CFLAGS) -c -g -o ael_main1.o ael_main.c
testexpr2s: ../ast_expr2f.c ../ast_expr2.c ../ast_expr2.h
gcc -g -c -I../include -DSTANDALONE ../ast_expr2f.c -o ast_expr2f.o
gcc -g -c -I../include -DSTANDALONE ../ast_expr2.c -o ast_expr2.o
gcc -g -o testexpr2s ast_expr2f.o ast_expr2.o
rm ast_expr2.o ast_expr2f.o
./testexpr2s expr2.testinput
smsq.o: smsq.c
$(CC) $(CFLAGS) -include ../include/autoconfig.h -c -o $@ $<

264
utils/ael_main.c Normal file
View File

@ -0,0 +1,264 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#if !defined(SOLARIS) && !defined(__CYGWIN__)
#include <err.h>
#else
#define quad_t int64_t
#endif
#include <errno.h>
#include <regex.h>
#include <limits.h>
#include <asterisk/ast_expr.h>
#include <asterisk/logger.h>
#include <asterisk/module.h>
#include <asterisk/channel.h>
#include <asterisk/app.h>
#include "asterisk/ael_structs.h"
#define AST_CONFIG_MAX_PATH 255
int conts=0, extens=0, priors=0;
char last_exten[18000];
char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
void ast_cli_register_multiple(void);
void ast_register_file_version(void);
void ast_unregister_file_version(void);
int ast_add_extension2(void *con,
int replace, const char *extension, int priority, const char *label, const char *callerid,
const char *application, void *data, void (*datad)(void *),
const char *registrar);
void pbx_builtin_setvar(void *chan, void *data);
void ast_context_create(void **extcontexts, const char *name, const char *registrar);
void ast_context_add_ignorepat2(void *con, const char *value, const char *registrar);
void ast_context_add_include2(void *con, const char *value, const char *registrar);
void ast_context_add_switch2(void *con, const char *value, const char *data, int eval, const char *registrar);
void ast_merge_contexts_and_delete(void);
void ast_context_verify_includes(void);
struct ast_context * ast_walk_contexts(void);
void ast_cli_unregister_multiple(void);
void ast_context_destroy(void);
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...);
char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
void ast_verbose(const char *fmt, ...);
struct ast_app *pbx_findapp(const char *app);
static int no_comp = 0;
static int use_curr_dir = 0;
struct ast_app *pbx_findapp(const char *app)
{
return (struct ast_app*)1; /* so as not to trigger an error */
}
void ast_copy_string(char *dst, const char *src, size_t size)
{
while (*src && size) {
*dst++ = *src++;
size--;
}
if (__builtin_expect(!size, 0))
dst--;
*dst = '\0';
}
void ast_cli_register_multiple(void)
{
if(!no_comp)
printf("Executed ast_cli_register_multiple();\n");
}
void ast_register_file_version(void)
{
if(!no_comp)
printf("Executed ast_register_file_version();\n");
}
void ast_unregister_file_version(void)
{
if(!no_comp)
printf("Executed ast_unregister_file_version();\n");
}
int ast_add_extension2(void *con,
int replace, const char *extension, int priority, const char *label, const char *callerid,
const char *application, void *data, void (*datad)(void *),
const char *registrar)
{
priors++;
if (strcmp(extension,last_exten) != 0) {
extens++;
strcpy(last_exten, extension);
}
if (!label) {
label = "(null)";
}
if (!callerid) {
callerid = "(null)";
}
if (!application) {
application = "(null)";
}
if(!no_comp)
printf("Executed ast_add_extension2(con, rep=%d, exten=%s, priority=%d, label=%s, callerid=%s, appl=%s, data=%s, FREE, registrar=%s);\n",
replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar);
/* since add_extension2 is responsible for the malloc'd data stuff */
if( data )
free(data);
return 0;
}
void pbx_builtin_setvar(void *chan, void *data)
{
if(!no_comp)
printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data);
}
void ast_context_create(void **extcontexts, const char *name, const char *registrar)
{
if(!no_comp)
printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar);
conts++;
}
void ast_context_add_ignorepat2(void *con, const char *value, const char *registrar)
{
if(!no_comp)
printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar);
}
void ast_context_add_include2(void *con, const char *value, const char *registrar)
{
if(!no_comp)
printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar);
}
void ast_context_add_switch2(void *con, const char *value, const char *data, int eval, const char *registrar)
{
if(!no_comp)
printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar);
}
void ast_merge_contexts_and_delete(void)
{
if(!no_comp)
printf("Executed ast_merge_contexts_and_delete();\n");
}
void ast_context_verify_includes(void)
{
if(!no_comp)
printf("Executed ast_context_verify_includes();\n");
}
struct ast_context * ast_walk_contexts(void)
{
if(!no_comp)
printf("Executed ast_walk_contexts();\n");
return 0;
}
void ast_cli_unregister_multiple(void)
{
if(!no_comp)
printf("Executed ast_cli_unregister_multiple();\n");
}
void ast_context_destroy(void)
{
printf("Executed ast_context_destroy();\n");
}
void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
{
va_list vars;
va_start(vars,fmt);
printf("LOG: lev:%d file:%s line:%d func: %s ",
level, file, line, function);
vprintf(fmt, vars);
fflush(stdout);
va_end(vars);
}
void ast_verbose(const char *fmt, ...)
{
va_list vars;
va_start(vars,fmt);
printf("VERBOSE: ");
vprintf(fmt, vars);
fflush(stdout);
va_end(vars);
}
char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
{
char *dataPut = start;
int inEscape = 0;
int inQuotes = 0;
for (; *start; start++) {
if (inEscape) {
*dataPut++ = *start; /* Always goes verbatim */
inEscape = 0;
} else {
if (*start == '\\') {
inEscape = 1; /* Do not copy \ into the data */
} else if (*start == '\'') {
inQuotes = 1-inQuotes; /* Do not copy ' into the data */
} else {
/* Replace , with |, unless in quotes */
*dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start);
}
}
}
if (start != dataPut)
*dataPut = 0;
return dataPut;
}
extern struct module_symbols mod_data;
int main(int argc, char **argv)
{
int i;
for(i=1;i<argc;i++)
{
if( argv[i][0] == '-' && argv[i][1] == 'n' )
no_comp =1;
if( argv[i][0] == '-' && argv[i][1] == 'd' )
use_curr_dir =1;
}
if( !no_comp )
printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
if( !use_curr_dir )
printf("\n(You can use the -d option if you want to use the current working directory as the CONFIG_DIR. I will look in this dir for extensions.ael* and its included files)\n\n");
if( use_curr_dir )
{
strcpy(ast_config_AST_CONFIG_DIR, ".");
}
else
{
strcpy(ast_config_AST_CONFIG_DIR, "/etc/asterisk");
}
strcpy(ast_config_AST_VAR_DIR, "/var/lib/asterisk");
mod_data.load_module(0);
ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors);
return 0;
}

92
utils/expr2.testinput Normal file
View File

@ -0,0 +1,92 @@
2 + 2
2 + 2
2 - 4
4 - 2
-4 - -2
4 + 2 * 8
(4 + 2) * 8
4 + (2 * 8)
4 + (2 * 8) ? 3 :: 6
4 + 8 / 2
4 + 8 / 3
(4+8) / 3
4 + 8 % 3
4 + 9 % 3
(4+9) %3
(4+8) %3
(4+9) %3
(4+8) %3
(4+9) % 3
(4+8) % 3
(4+9) % 3
(4+8) % 3
(4+9)% 3
(4+8)% 3
(4+9)% 3
(4+8)% 3
4 & 4
0 & 4
0 & 0
2 | 0
2 | 4
0 | 0
!0 | 0
!4 | 0
4 | !0
!4 | !0
3 < 4
4 < 3
3 > 4
4 > 3
3 = 3
3 = 4
3 != 3
3 != 4
3 >= 4
3 >= 3
4 >= 3
3 <= 4
4 <= 3
4 <= 4
3 > 4 & 4 < 3
4 > 3 & 3 < 4
x = x
y = x
x != y
x != x
"Something interesting" =~ interesting
"Something interesting" =~ Something
"Something interesting" : Something
"Something interesting" : interesting
"Something interesting" =~ "interesting"
"Something interesting" =~ "Something"
"Something interesting" : "Something"
"Something interesting" : "interesting"
"Something interesting" =~ (interesting)
"Something interesting" =~ (Something)
"Something interesting" : (Something)
"Something interesting" : (interesting)
"Something interesting" =~ "\(interesting\)"
"Something interesting" =~ "\(Something\)"
"Something interesting" : "\(Something\)"
"Something interesting" : "\(interesting\)"
"011043567857575" : "011\(..\)"
"9011043567857575" : "011\(..\)"
"011043567857575" =~ "011\(..\)"
"9011043567857575" =~ "011\(..\)"
"Something interesting" =~ (interesting)
"Something interesting" =~ (Something)
"Something interesting" : (Something)
"Something interesting" : (interesting)
"Something interesting" =~ "(interesting)"
"Something interesting" =~ "(Something)"
"Something interesting" : "(Something)"
"Something interesting" : "(interesting)"
"011043567857575" : "011(..)"
"9011043567857575" : "011(..)"
"011043567857575" =~ "011(..)"
"9011043567857575" =~ "011(..)"
3
something
043