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

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@22273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin P. Fleming
2006-04-24 17:41:27 +00:00
parent bc50c527f8
commit 5f58cc8770
43 changed files with 21298 additions and 2290 deletions

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