From ae7ab1aff9544a168171def2af815e7119894c58 Mon Sep 17 00:00:00 2001 From: murf Date: Mon, 7 Aug 2006 12:59:47 +0000 Subject: The contents of branch teams/murf/bug_7598 are being folded in here. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@39151 f38db490-d61c-443f-a65b-d21fe96a405b --- pbx/ael/ael-test/ael-ntest10/extensions.ael | 131 +++++++++ pbx/ael/ael-test/ael-test11/extensions.ael | 56 ++++ pbx/ael/ael-test/ref.ael-ntest10 | 133 +++++++++ pbx/ael/ael-test/ref.ael-test11 | 11 + pbx/ael/ael-test/ref.ael-test3 | 34 +-- pbx/ael/ael-test/ref.ael-test7 | 25 +- pbx/ael/ael.tab.c | 314 +++++++++++----------- pbx/ael/ael.y | 54 ++-- pbx/pbx_ael.c | 401 +++++++++++++++++++++++----- 9 files changed, 898 insertions(+), 261 deletions(-) create mode 100644 pbx/ael/ael-test/ael-ntest10/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test11/extensions.ael create mode 100644 pbx/ael/ael-test/ref.ael-ntest10 create mode 100644 pbx/ael/ael-test/ref.ael-test11 (limited to 'pbx') diff --git a/pbx/ael/ael-test/ael-ntest10/extensions.ael b/pbx/ael/ael-test/ael-ntest10/extensions.ael new file mode 100644 index 000000000..4a8386ccf --- /dev/null +++ b/pbx/ael/ael-test/ael-ntest10/extensions.ael @@ -0,0 +1,131 @@ +macro endsess() +{ + NoOp(hithere); +} + +macro nullchk(type) +{ + NoOp(${type} is this); +} + +macro endcall(type) { + switch(${type}) { + case out: + &nullchk(callid); + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + else { +ptr1: // <-- valid label + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } +} + +macro endcall2(type) { + switch(${type}) { + case out: + &nullchk(callid); + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + case out2: + { +ptr1: // <-- valid label + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } +} + +macro endcall3(type) { + switch(${type}) { + case out: + &nullchk(callid); + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + Noop(esac) ; + } + if(${testnotnull}) { + goto ptr1; + } + switch(${type}) { + case out: + if(${testnotnull}) { +ptr1: // <-- valid label + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } +} + +macro endcall4(type) { + switch(${type}) { + case out: + &nullchk(callid); + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + Noop(esac) ; + } + if(${testnotnull}) { + goto ptr1; + } + switch(${type}) { + case out: + switch(${type}) + { + case in: + if(${testnotnull}) { +ptr1: // <-- valid label + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } + } +} + +macro endcall5(type) { + switch(${type}) { + case out: + &nullchk(callid); + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + case in: + &nullchk(callid); + ptr2: + if(${testnotnull}) { + &endsess(); + goto ptr1 ; // <-- goto call to valid label + } + Noop(esac) ; + } + if(${testnotnull}) { + goto ptr1; + } + switch(${type}) { + case out: + switch(${type}) + { + case in: + if(${testnotnull}) { +ptr1: // <-- valid label + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } + } +} diff --git a/pbx/ael/ael-test/ael-test11/extensions.ael b/pbx/ael/ael-test/ael-test11/extensions.ael new file mode 100644 index 000000000..886a51eb5 --- /dev/null +++ b/pbx/ael/ael-test/ael-test11/extensions.ael @@ -0,0 +1,56 @@ +context test1 +{ + s => + { + goto lab1; + if( ${testnotnull} ) + { + lab1: + NoOp(hello); + } + else + { + lab1: + MoOp(goodbye); + } + } + + 1 => + { + lab1: + NoOp(This one is OK.); + } +} + +macro endcall5(type) { + switch(${type}) { + case out: + if(${testnotnull}) { + NoOp(whoosh); + goto ptr1 ; // <-- goto call to valid label + } + case in: + ptr1: // The First label is the valid one... + if(${testnotnull}) { + NoOp(wow); + goto ptr1 ; // <-- goto call to valid label + } + Noop(esac) ; + } + if(${testnotnull}) { + goto ptr1; + } + switch(${type}) { + case out: + switch(${type}) + { + case in: + if(${testnotnull}) { +ptr1: // <-- duplicate label (macros are about the equiv of an extension) + Softhangup(${CHANNEL}); + break ; + } + Noop(esac) ; + } + } +} diff --git a/pbx/ael/ael-test/ref.ael-ntest10 b/pbx/ael/ael-test/ref.ael-ntest10 new file mode 100644 index 000000000..e74e07fde --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-ntest10 @@ -0,0 +1,133 @@ +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); + +(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler) + +Executed ast_cli_register_multiple(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3732 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:../pbx/pbx_ael.c line:3739 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3742 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3745 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +Executed ast_context_create(conts, name=macro-endsess, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-nullchk, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-endcall, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-endcall2, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-endcall3, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-endcall4, registrar=pbx_ael); +Executed ast_context_create(conts, name=macro-endcall5, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=NoOp, data=hithere, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=NoOp, data=${type} is this, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Goto, data=sw-1-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall-1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:6, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-1-out|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=5, label=(null), callerid=(null), appl=Goto, data=8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=6, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=7, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=8, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall-out-1-2, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=9, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-1-out, priority=10, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Goto, data=sw-3-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall2-3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out2, priority=1, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out2, priority=2, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out2, priority=3, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out2, priority=4, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-3-out2|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=5, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall2-out-3-4, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-3-out, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-3-out2|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Goto, data=sw-5-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall3-5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?5:6, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=Goto, data=sw-8-out|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall3-7, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=Goto, data=sw-8-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall3-8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=1, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?2:4, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=2, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=3, label=(null), callerid=(null), appl=Goto, data=s|8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall3-out-8-9, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=5, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-8-out, priority=6, label=(null), callerid=(null), appl=Goto, data=s|8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-8-out|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=5, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall3-out-5-6, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=6, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-5-out, priority=7, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Goto, data=sw-10-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall4-10, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?5:6, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=Goto, data=sw-14-in|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall4-12, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=Goto, data=sw-13-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall4-13, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-13-out, priority=1, label=(null), callerid=(null), appl=Goto, data=sw-14-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-13-out, priority=2, label=(null), callerid=(null), appl=NoOp, data=Finish switch-sw-endcall4-out-13-14, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-13-out, priority=3, label=(null), callerid=(null), appl=Goto, data=s|8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=1, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?2:4, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=2, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-13-out|2, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-sw-endcall4-out-13-in-14-15, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=5, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-14-in, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-13-out|2, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-14-in|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=5, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall4-out-10-11, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=6, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-10-out, priority=7, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=1, label=(null), callerid=(null), appl=Set, data=type=${ARG1}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=2, label=(null), callerid=(null), appl=Goto, data=sw-16-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=3, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall5-16, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=4, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?5:6, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=5, label=(null), callerid=(null), appl=Goto, data=sw-21-in|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=6, label=(null), callerid=(null), appl=NoOp, data=Finish if-endcall5-19, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=7, label=(null), callerid=(null), appl=Goto, data=sw-20-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=s, priority=8, label=(null), callerid=(null), appl=NoOp, data=Finish switch-endcall5-20, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-20-out, priority=1, label=(null), callerid=(null), appl=Goto, data=sw-21-${type}|1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-20-out, priority=2, label=(null), callerid=(null), appl=NoOp, data=Finish switch-sw-endcall5-out-20-21, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-20-out, priority=3, label=(null), callerid=(null), appl=Goto, data=s|8, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=1, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?2:4, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=2, label=ptr1, callerid=(null), appl=Softhangup, data=${CHANNEL}, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=3, label=(null), callerid=(null), appl=Goto, data=sw-20-out|2, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=4, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-sw-endcall5-out-20-in-21-22, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=5, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-21-in, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-20-out|2, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=2, label=ptr2, callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-21-in|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=5, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall5-in-16-18, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=6, label=(null), callerid=(null), appl=Noop, data=esac, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-in, priority=7, label=(null), callerid=(null), appl=Goto, data=s|3, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=1, label=(null), callerid=(null), appl=Macro, data=nullchk|callid, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=2, label=(null), callerid=(null), appl=GotoIf, data=$[${testnotnull}]?3:5, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=3, label=(null), callerid=(null), appl=Macro, data=endsess, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=4, label=(null), callerid=(null), appl=Goto, data=sw-21-in|ptr1, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=5, label=(null), callerid=(null), appl=NoOp, data=Finish if-sw-endcall5-out-16-17, FREE, registrar=pbx_ael); +Executed ast_add_extension2(con, rep=0, exten=sw-16-out, priority=6, label=(null), callerid=(null), appl=Goto, data=sw-16-in|1, FREE, registrar=pbx_ael); +LOG: lev:2 file:../pbx/pbx_ael.c line:3747 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +Executed ast_merge_contexts_and_delete(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3750 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +Executed ast_walk_contexts(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3753 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:253 func: main 7 contexts, 17 extensions, 104 priorities +Executed ast_unregister_file_version(); +Executed ast_unregister_file_version(); +Executed ast_unregister_file_version(); +Executed ast_unregister_file_version(); diff --git a/pbx/ael/ael-test/ref.ael-test11 b/pbx/ael/ael-test/ref.ael-test11 new file mode 100644 index 000000000..581ac6035 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test11 @@ -0,0 +1,11 @@ +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3732 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:../pbx/pbx_ael.c line:3739 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3742 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:4 file:../pbx/pbx_ael.c line:1041 func: check_label Error: file ./extensions.ael, line 13-13: Duplicate label lab1! Previously defined at file ./extensions.ael, line 8. +LOG: lev:4 file:../pbx/pbx_ael.c line:1041 func: check_label Error: file ./extensions.ael, line 49-49: Duplicate label ptr1! Previously defined at file ./extensions.ael, line 33. +LOG: lev:4 file:../pbx/pbx_ael.c line:3755 func: pbx_load_module Sorry, but 0 syntax errors and 2 semantic errors were detected. It doesn't make sense to compile. +LOG: lev:4 file:ael2_parse line:253 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/ref.ael-test3 b/pbx/ael/ael-test/ref.ael-test3 index 4dcc0ce09..afa17f6d2 100644 --- a/pbx/ael/ael-test/ref.ael-test3 +++ b/pbx/ael/ael-test/ref.ael-test3 @@ -1,18 +1,18 @@ Executed ast_register_file_version(); -LOG: lev:2 file:../pbx/pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. -LOG: lev:2 file:../pbx/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/pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. -LOG: lev:3 file:../pbx/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/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/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/pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. -LOG: lev:2 file:../pbx/pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. -LOG: lev:2 file:../pbx/pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. -LOG: lev:2 file:../pbx/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 +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3732 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:../pbx/pbx_ael.c line:3739 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file ./include1.ael2, 78 chars +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file ./include2.ael2, 98 chars +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file ./include3.ael2, 57 chars +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file ./include5.ael2, 56 chars +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file ./include4.ael2, 87 chars +LOG: lev:2 file:ael.flex line:422 func: ael_yylex --Read in included file /etc/asterisk/telemarket_torture.ael2, 28036 chars +LOG: lev:2 file:../pbx/pbx_ael.c line:3742 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3745 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3747 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3750 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3753 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:253 func: main 172 contexts, 858 extensions, 2326 priorities diff --git a/pbx/ael/ael-test/ref.ael-test7 b/pbx/ael/ael-test/ref.ael-test7 index fddd1ed28..b1f5522c1 100644 --- a/pbx/ael/ael-test/ref.ael-test7 +++ b/pbx/ael/ael-test/ref.ael-test7 @@ -1,13 +1,14 @@ Executed ast_register_file_version(); -LOG: lev:2 file:../pbx/pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. -LOG: lev:2 file:../pbx/pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. -LOG: lev:2 file:../pbx/pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. -LOG: lev:3 file:../pbx/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/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/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/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/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/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/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/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 +Executed ast_register_file_version(); +Executed ast_register_file_version(); +Executed ast_register_file_version(); +LOG: lev:2 file:../pbx/pbx_ael.c line:3732 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:../pbx/pbx_ael.c line:3739 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:../pbx/pbx_ael.c line:3742 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:4 file:../pbx/pbx_ael.c line:2229 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/pbx_ael.c line:2229 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/pbx_ael.c line:2229 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/pbx_ael.c line:2229 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/pbx_ael.c line:2210 func: check_pval_item Error: file ./extensions.ael, line 452-452: macro call to non-existent std-exten-ael ! +LOG: lev:4 file:../pbx/pbx_ael.c line:3755 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:253 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael.tab.c b/pbx/ael/ael.tab.c index dcfca5725..6cef52eed 100644 --- a/pbx/ael/ael.tab.c +++ b/pbx/ael/ael.tab.c @@ -187,7 +187,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/ael_structs.h" static pval * linku1(pval *head, pval *tail); - +static void set_dads(pval *dad, pval *child_list); void reset_parencount(yyscan_t yyscanner); void reset_semicount(yyscan_t yyscanner); void reset_argcount(yyscan_t yyscanner ); @@ -615,18 +615,18 @@ static const yytype_int8 yyrhs[] = static const yytype_uint16 yyrline[] = { 0, 185, 185, 188, 189, 190, 193, 194, 195, 196, - 199, 200, 203, 211, 212, 215, 220, 225, 226, 227, - 230, 230, 237, 238, 239, 240, 243, 244, 245, 248, - 249, 250, 251, 252, 253, 254, 255, 258, 263, 267, - 272, 277, 287, 288, 289, 295, 300, 304, 312, 312, - 316, 319, 322, 333, 334, 341, 342, 347, 355, 356, - 360, 366, 375, 378, 379, 382, 385, 388, 389, 390, - 388, 396, 400, 401, 402, 403, 406, 406, 439, 440, - 441, 442, 446, 449, 450, 453, 454, 457, 460, 464, - 468, 472, 478, 479, 483, 486, 492, 492, 497, 505, - 505, 516, 523, 526, 527, 530, 531, 534, 537, 538, - 541, 545, 549, 555, 556, 559, 560, 566, 571, 576, - 577, 578, 581, 582, 589, 590, 591, 594, 597 + 199, 200, 203, 212, 213, 216, 222, 228, 229, 230, + 233, 233, 240, 241, 242, 243, 246, 247, 248, 251, + 252, 253, 254, 255, 256, 257, 258, 261, 266, 270, + 275, 280, 290, 291, 292, 298, 303, 307, 315, 315, + 319, 322, 325, 336, 337, 344, 345, 350, 358, 359, + 363, 369, 378, 381, 382, 385, 388, 391, 392, 393, + 391, 399, 403, 404, 405, 406, 409, 409, 442, 443, + 444, 445, 449, 452, 453, 456, 457, 460, 463, 467, + 471, 475, 481, 482, 486, 489, 495, 495, 500, 508, + 508, 519, 526, 529, 530, 533, 534, 537, 540, 541, + 544, 548, 552, 558, 559, 562, 563, 569, 574, 579, + 580, 581, 584, 585, 592, 593, 594, 597, 600 }; #endif @@ -2109,55 +2109,58 @@ yyreduce: (yyval.pval) = npval2(PV_CONTEXT, &(yylsp[(1) - (6)]), &(yylsp[(6) - (6)])); (yyval.pval)->u1.str = (yyvsp[(3) - (6)].str); (yyval.pval)->u2.statements = (yyvsp[(5) - (6)].pval); + set_dads((yyval.pval),(yyvsp[(5) - (6)].pval)); (yyval.pval)->u3.abstract = (yyvsp[(1) - (6)].intval); ;} break; case 13: -#line 211 "ael.y" +#line 212 "ael.y" { (yyval.intval) = 1; ;} break; case 14: -#line 212 "ael.y" +#line 213 "ael.y" { (yyval.intval) = 0; ;} break; case 15: -#line 215 "ael.y" +#line 216 "ael.y" { (yyval.pval) = npval2(PV_MACRO, &(yylsp[(1) - (8)]), &(yylsp[(8) - (8)])); - (yyval.pval)->u1.str = (yyvsp[(2) - (8)].str); (yyval.pval)->u2.arglist = (yyvsp[(4) - (8)].pval); (yyval.pval)->u3.macro_statements = (yyvsp[(7) - (8)].pval); ;} + (yyval.pval)->u1.str = (yyvsp[(2) - (8)].str); (yyval.pval)->u2.arglist = (yyvsp[(4) - (8)].pval); (yyval.pval)->u3.macro_statements = (yyvsp[(7) - (8)].pval); + set_dads((yyval.pval),(yyvsp[(7) - (8)].pval));;} break; case 16: -#line 220 "ael.y" +#line 222 "ael.y" { (yyval.pval) = npval2(PV_GLOBALS, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); - (yyval.pval)->u1.statements = (yyvsp[(3) - (4)].pval);;} + (yyval.pval)->u1.statements = (yyvsp[(3) - (4)].pval); + set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;} break; case 17: -#line 225 "ael.y" +#line 228 "ael.y" { (yyval.pval) = NULL; ;} break; case 18: -#line 226 "ael.y" +#line 229 "ael.y" {(yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;} break; case 19: -#line 227 "ael.y" +#line 230 "ael.y" {(yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 20: -#line 230 "ael.y" +#line 233 "ael.y" { reset_semicount(parseio->scanner); ;} break; case 21: -#line 230 "ael.y" +#line 233 "ael.y" { (yyval.pval) = npval2(PV_VARDEC, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)])); (yyval.pval)->u1.str = (yyvsp[(1) - (5)].str); @@ -2165,140 +2168,140 @@ yyreduce: break; case 22: -#line 237 "ael.y" +#line 240 "ael.y" { (yyval.pval) = NULL; ;} break; case 23: -#line 238 "ael.y" +#line 241 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;} break; case 24: -#line 239 "ael.y" +#line 242 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)]))); ;} break; case 25: -#line 240 "ael.y" +#line 243 "ael.y" {(yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 26: -#line 243 "ael.y" +#line 246 "ael.y" {(yyval.pval)=0;;} break; case 27: -#line 244 "ael.y" +#line 247 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;} break; case 28: -#line 245 "ael.y" +#line 248 "ael.y" { (yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 29: -#line 248 "ael.y" +#line 251 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 30: -#line 249 "ael.y" +#line 252 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 31: -#line 250 "ael.y" +#line 253 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 32: -#line 251 "ael.y" +#line 254 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 33: -#line 252 "ael.y" +#line 255 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 34: -#line 253 "ael.y" +#line 256 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 35: -#line 254 "ael.y" +#line 257 "ael.y" {free((yyvsp[(1) - (2)].str)); (yyval.pval)=0;;} break; case 36: -#line 255 "ael.y" +#line 258 "ael.y" {(yyval.pval)=0;/* allow older docs to be read */;} break; case 37: -#line 258 "ael.y" +#line 261 "ael.y" { (yyval.pval) = npval2(PV_IGNOREPAT, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); (yyval.pval)->u1.str = (yyvsp[(3) - (4)].str);;} break; case 38: -#line 263 "ael.y" +#line 266 "ael.y" { (yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.str = (yyvsp[(1) - (3)].str); - (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval); ;} + (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval); set_dads((yyval.pval),(yyvsp[(3) - (3)].pval));;} break; case 39: -#line 267 "ael.y" +#line 270 "ael.y" { (yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); (yyval.pval)->u1.str = (yyvsp[(2) - (4)].str); - (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval); + (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval); set_dads((yyval.pval),(yyvsp[(4) - (4)].pval)); (yyval.pval)->u4.regexten=1;;} break; case 40: -#line 272 "ael.y" +#line 275 "ael.y" { (yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (7)]), &(yylsp[(7) - (7)])); (yyval.pval)->u1.str = (yyvsp[(5) - (7)].str); - (yyval.pval)->u2.statements = (yyvsp[(7) - (7)].pval); + (yyval.pval)->u2.statements = (yyvsp[(7) - (7)].pval); set_dads((yyval.pval),(yyvsp[(7) - (7)].pval)); (yyval.pval)->u3.hints = (yyvsp[(3) - (7)].str);;} break; case 41: -#line 277 "ael.y" +#line 280 "ael.y" { (yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (8)]), &(yylsp[(8) - (8)])); (yyval.pval)->u1.str = (yyvsp[(6) - (8)].str); - (yyval.pval)->u2.statements = (yyvsp[(8) - (8)].pval); + (yyval.pval)->u2.statements = (yyvsp[(8) - (8)].pval); set_dads((yyval.pval),(yyvsp[(8) - (8)].pval)); (yyval.pval)->u4.regexten=1; (yyval.pval)->u3.hints = (yyvsp[(4) - (8)].str);;} break; case 42: -#line 287 "ael.y" +#line 290 "ael.y" { (yyval.pval) = NULL; ;} break; case 43: -#line 288 "ael.y" +#line 291 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;} break; case 44: -#line 289 "ael.y" +#line 292 "ael.y" {(yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 45: -#line 295 "ael.y" +#line 298 "ael.y" { asprintf(&(yyval.str), "%s:%s:%s", (yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].str)); free((yyvsp[(1) - (5)].str)); @@ -2307,12 +2310,12 @@ yyreduce: break; case 46: -#line 300 "ael.y" +#line 303 "ael.y" { (yyval.str) = (yyvsp[(1) - (1)].str); ;} break; case 47: -#line 304 "ael.y" +#line 307 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (7)].str), &(yylsp[(1) - (7)])); (yyval.pval)->next = nword((yyvsp[(3) - (7)].str), &(yylsp[(3) - (7)])); @@ -2321,31 +2324,31 @@ yyreduce: break; case 48: -#line 312 "ael.y" +#line 315 "ael.y" { reset_parencount(parseio->scanner); ;} break; case 49: -#line 312 "ael.y" +#line 315 "ael.y" { (yyval.str) = (yyvsp[(3) - (4)].str); ;} break; case 50: -#line 316 "ael.y" +#line 319 "ael.y" { (yyval.pval)= npval2(PV_IF, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); (yyval.pval)->u1.str = (yyvsp[(2) - (2)].str); ;} break; case 51: -#line 319 "ael.y" +#line 322 "ael.y" { (yyval.pval) = npval2(PV_RANDOM, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); (yyval.pval)->u1.str=(yyvsp[(2) - (2)].str);;} break; case 52: -#line 322 "ael.y" +#line 325 "ael.y" { (yyval.pval) = npval2(PV_IFTIME, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); @@ -2353,12 +2356,12 @@ yyreduce: break; case 53: -#line 333 "ael.y" +#line 336 "ael.y" { (yyval.str) = (yyvsp[(1) - (1)].str);;} break; case 54: -#line 334 "ael.y" +#line 337 "ael.y" { asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); free((yyvsp[(1) - (2)].str)); @@ -2367,12 +2370,12 @@ yyreduce: break; case 55: -#line 341 "ael.y" +#line 344 "ael.y" { (yyval.str) = (yyvsp[(1) - (1)].str);;} break; case 56: -#line 342 "ael.y" +#line 345 "ael.y" { asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); free((yyvsp[(1) - (2)].str)); @@ -2381,7 +2384,7 @@ yyreduce: break; case 57: -#line 347 "ael.y" +#line 350 "ael.y" { asprintf(&((yyval.str)), "%s%s%s", (yyvsp[(1) - (3)].str), (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str)); free((yyvsp[(1) - (3)].str)); @@ -2391,12 +2394,12 @@ yyreduce: break; case 58: -#line 355 "ael.y" +#line 358 "ael.y" { (yyval.str) = (yyvsp[(1) - (1)].str);;} break; case 59: -#line 356 "ael.y" +#line 359 "ael.y" { asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); free((yyvsp[(1) - (2)].str)); @@ -2404,7 +2407,7 @@ yyreduce: break; case 60: -#line 360 "ael.y" +#line 363 "ael.y" { asprintf(&((yyval.str)), "%s:%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); free((yyvsp[(1) - (3)].str)); @@ -2412,108 +2415,108 @@ yyreduce: break; case 61: -#line 366 "ael.y" +#line 369 "ael.y" { (yyval.pval) = npval2(PV_SWITCH, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)])); (yyval.pval)->u1.str = (yyvsp[(2) - (5)].str); - (yyval.pval)->u2.statements = (yyvsp[(4) - (5)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(4) - (5)].pval); set_dads((yyval.pval),(yyvsp[(4) - (5)].pval));;} break; case 62: -#line 375 "ael.y" +#line 378 "ael.y" { (yyval.pval) = npval2(PV_STATEMENTBLOCK, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); - (yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval); ;} + (yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval); set_dads((yyval.pval),(yyvsp[(2) - (3)].pval));;} break; case 63: -#line 378 "ael.y" +#line 381 "ael.y" { (yyval.pval) = (yyvsp[(1) - (1)].pval); ;} break; case 64: -#line 379 "ael.y" +#line 382 "ael.y" { (yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval);;} break; case 65: -#line 382 "ael.y" +#line 385 "ael.y" { (yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval);;} break; case 66: -#line 385 "ael.y" +#line 388 "ael.y" { (yyval.pval) = npval2(PV_LABEL, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); (yyval.pval)->u1.str = (yyvsp[(1) - (2)].str); ;} break; case 67: -#line 388 "ael.y" +#line 391 "ael.y" {reset_semicount(parseio->scanner);;} break; case 68: -#line 389 "ael.y" +#line 392 "ael.y" {reset_semicount(parseio->scanner);;} break; case 69: -#line 390 "ael.y" +#line 393 "ael.y" {reset_parencount(parseio->scanner);;} break; case 70: -#line 390 "ael.y" +#line 393 "ael.y" { /* XXX word_list maybe ? */ (yyval.pval) = npval2(PV_FOR, &(yylsp[(1) - (12)]), &(yylsp[(12) - (12)])); (yyval.pval)->u1.for_init = (yyvsp[(4) - (12)].str); (yyval.pval)->u2.for_test=(yyvsp[(7) - (12)].str); (yyval.pval)->u3.for_inc = (yyvsp[(10) - (12)].str); - (yyval.pval)->u4.for_statements = (yyvsp[(12) - (12)].pval);;} + (yyval.pval)->u4.for_statements = (yyvsp[(12) - (12)].pval); set_dads((yyval.pval),(yyvsp[(12) - (12)].pval));;} break; case 71: -#line 396 "ael.y" +#line 399 "ael.y" { (yyval.pval) = npval2(PV_WHILE, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.str = (yyvsp[(2) - (3)].str); - (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval); ;} + (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval); set_dads((yyval.pval),(yyvsp[(3) - (3)].pval));;} break; case 72: -#line 400 "ael.y" +#line 403 "ael.y" { (yyval.pval) = (yyvsp[(1) - (1)].pval); ;} break; case 73: -#line 401 "ael.y" +#line 404 "ael.y" { (yyval.pval) = update_last((yyvsp[(2) - (3)].pval), &(yylsp[(2) - (3)])); ;} break; case 74: -#line 402 "ael.y" +#line 405 "ael.y" { (yyval.pval) = update_last((yyvsp[(1) - (2)].pval), &(yylsp[(2) - (2)])); ;} break; case 75: -#line 403 "ael.y" +#line 406 "ael.y" { (yyval.pval)= npval2(PV_APPLICATION_CALL, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); (yyval.pval)->u1.str = (yyvsp[(1) - (2)].str);;} break; case 76: -#line 406 "ael.y" +#line 409 "ael.y" {reset_semicount(parseio->scanner);;} break; case 77: -#line 406 "ael.y" +#line 409 "ael.y" { char *bufx; int tot=0; @@ -2550,64 +2553,64 @@ yyreduce: break; case 78: -#line 439 "ael.y" +#line 442 "ael.y" { (yyval.pval) = npval2(PV_BREAK, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;} break; case 79: -#line 440 "ael.y" +#line 443 "ael.y" { (yyval.pval) = npval2(PV_RETURN, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;} break; case 80: -#line 441 "ael.y" +#line 444 "ael.y" { (yyval.pval) = npval2(PV_CONTINUE, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;} break; case 81: -#line 442 "ael.y" +#line 445 "ael.y" { (yyval.pval) = update_last((yyvsp[(1) - (3)].pval), &(yylsp[(2) - (3)])); - (yyval.pval)->u2.statements = (yyvsp[(2) - (3)].pval); - (yyval.pval)->u3.else_statements = (yyvsp[(3) - (3)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(2) - (3)].pval); set_dads((yyval.pval),(yyvsp[(2) - (3)].pval)); + (yyval.pval)->u3.else_statements = (yyvsp[(3) - (3)].pval);set_dads((yyval.pval),(yyvsp[(3) - (3)].pval));;} break; case 82: -#line 446 "ael.y" +#line 449 "ael.y" { (yyval.pval)=0; ;} break; case 83: -#line 449 "ael.y" +#line 452 "ael.y" { (yyval.pval) = (yyvsp[(2) - (2)].pval); ;} break; case 84: -#line 450 "ael.y" +#line 453 "ael.y" { (yyval.pval) = NULL ; ;} break; case 85: -#line 453 "ael.y" +#line 456 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;} break; case 86: -#line 454 "ael.y" +#line 457 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)])); (yyval.pval)->next = nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)])); ;} break; case 87: -#line 457 "ael.y" +#line 460 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)])); (yyval.pval)->next = nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)])); ;} break; case 88: -#line 460 "ael.y" +#line 463 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (5)].str), &(yylsp[(1) - (5)])); (yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)])); @@ -2615,7 +2618,7 @@ yyreduce: break; case 89: -#line 464 "ael.y" +#line 467 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (5)].str), &(yylsp[(1) - (5)])); (yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)])); @@ -2623,7 +2626,7 @@ yyreduce: break; case 90: -#line 468 "ael.y" +#line 471 "ael.y" { (yyval.pval) = nword(strdup("default"), &(yylsp[(1) - (5)])); (yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)])); @@ -2631,7 +2634,7 @@ yyreduce: break; case 91: -#line 472 "ael.y" +#line 475 "ael.y" { (yyval.pval) = nword(strdup("default"), &(yylsp[(1) - (5)])); (yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)])); @@ -2639,24 +2642,24 @@ yyreduce: break; case 92: -#line 478 "ael.y" +#line 481 "ael.y" { (yyval.str) = strdup("1"); ;} break; case 93: -#line 479 "ael.y" +#line 482 "ael.y" { (yyval.str) = (yyvsp[(2) - (2)].str); ;} break; case 94: -#line 483 "ael.y" +#line 486 "ael.y" { /* ext[, pri] default 1 */ (yyval.pval) = nword((yyvsp[(1) - (2)].str), &(yylsp[(1) - (2)])); (yyval.pval)->next = nword((yyvsp[(2) - (2)].str), &(yylsp[(2) - (2)])); ;} break; case 95: -#line 486 "ael.y" +#line 489 "ael.y" { /* context, ext, pri */ (yyval.pval) = nword((yyvsp[(4) - (4)].str), &(yylsp[(4) - (4)])); (yyval.pval)->next = nword((yyvsp[(1) - (4)].str), &(yylsp[(1) - (4)])); @@ -2664,12 +2667,12 @@ yyreduce: break; case 96: -#line 492 "ael.y" +#line 495 "ael.y" {reset_argcount(parseio->scanner);;} break; case 97: -#line 492 "ael.y" +#line 495 "ael.y" { /* XXX original code had @2 but i think we need @5 */ (yyval.pval) = npval2(PV_MACRO_CALL, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)])); @@ -2678,19 +2681,19 @@ yyreduce: break; case 98: -#line 497 "ael.y" +#line 500 "ael.y" { (yyval.pval)= npval2(PV_MACRO_CALL, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.str = (yyvsp[(1) - (3)].str); ;} break; case 99: -#line 505 "ael.y" +#line 508 "ael.y" {reset_argcount(parseio->scanner);;} break; case 100: -#line 505 "ael.y" +#line 508 "ael.y" { if (strcasecmp((yyvsp[(1) - (3)].str),"goto") == 0) { (yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(2) - (3)])); @@ -2703,7 +2706,7 @@ yyreduce: break; case 101: -#line 516 "ael.y" +#line 519 "ael.y" { (yyval.pval) = update_last((yyvsp[(1) - (3)].pval), &(yylsp[(3) - (3)])); if( (yyval.pval)->type == PV_GOTO ) @@ -2714,130 +2717,130 @@ yyreduce: break; case 102: -#line 523 "ael.y" +#line 526 "ael.y" { (yyval.pval) = update_last((yyvsp[(1) - (2)].pval), &(yylsp[(2) - (2)])); ;} break; case 103: -#line 526 "ael.y" +#line 529 "ael.y" { (yyval.str) = (yyvsp[(1) - (1)].str) ;} break; case 104: -#line 527 "ael.y" +#line 530 "ael.y" { (yyval.str) = strdup(""); ;} break; case 105: -#line 530 "ael.y" +#line 533 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;} break; case 106: -#line 531 "ael.y" +#line 534 "ael.y" { (yyval.pval)= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/); (yyval.pval)->u1.str = strdup(""); ;} break; case 107: -#line 534 "ael.y" +#line 537 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)]))); ;} break; case 108: -#line 537 "ael.y" +#line 540 "ael.y" { (yyval.pval) = NULL; ;} break; case 109: -#line 538 "ael.y" +#line 541 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;} break; case 110: -#line 541 "ael.y" +#line 544 "ael.y" { (yyval.pval) = npval2(PV_CASE, &(yylsp[(1) - (4)]), &(yylsp[(3) - (4)])); /* XXX 3 or 4 ? */ (yyval.pval)->u1.str = (yyvsp[(2) - (4)].str); - (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval); set_dads((yyval.pval),(yyvsp[(4) - (4)].pval));;} break; case 111: -#line 545 "ael.y" +#line 548 "ael.y" { (yyval.pval) = npval2(PV_DEFAULT, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)])); (yyval.pval)->u1.str = NULL; - (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(3) - (3)].pval);set_dads((yyval.pval),(yyvsp[(3) - (3)].pval));;} break; case 112: -#line 549 "ael.y" +#line 552 "ael.y" { (yyval.pval) = npval2(PV_PATTERN, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); /* XXX@3 or @4 ? */ (yyval.pval)->u1.str = (yyvsp[(2) - (4)].str); - (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(4) - (4)].pval);set_dads((yyval.pval),(yyvsp[(4) - (4)].pval));;} break; case 113: -#line 555 "ael.y" +#line 558 "ael.y" { (yyval.pval) = NULL; ;} break; case 114: -#line 556 "ael.y" +#line 559 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;} break; case 115: -#line 559 "ael.y" +#line 562 "ael.y" {(yyval.pval)=(yyvsp[(1) - (1)].pval);;} break; case 116: -#line 560 "ael.y" +#line 563 "ael.y" { (yyval.pval) = npval2(PV_CATCH, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)])); (yyval.pval)->u1.str = (yyvsp[(2) - (5)].str); - (yyval.pval)->u2.statements = (yyvsp[(4) - (5)].pval);;} + (yyval.pval)->u2.statements = (yyvsp[(4) - (5)].pval); set_dads((yyval.pval),(yyvsp[(4) - (5)].pval));;} break; case 117: -#line 566 "ael.y" +#line 569 "ael.y" { (yyval.pval) = npval2(PV_SWITCHES, &(yylsp[(1) - (4)]), &(yylsp[(2) - (4)])); - (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); ;} + (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;} break; case 118: -#line 571 "ael.y" +#line 574 "ael.y" { (yyval.pval) = npval2(PV_ESWITCHES, &(yylsp[(1) - (4)]), &(yylsp[(2) - (4)])); - (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); ;} + (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;} break; case 119: -#line 576 "ael.y" +#line 579 "ael.y" { (yyval.pval) = NULL; ;} break; case 120: -#line 577 "ael.y" +#line 580 "ael.y" { (yyval.pval) = linku1(nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)])), (yyvsp[(3) - (3)].pval)); ;} break; case 121: -#line 578 "ael.y" +#line 581 "ael.y" {(yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 122: -#line 581 "ael.y" +#line 584 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;} break; case 123: -#line 582 "ael.y" +#line 585 "ael.y" { (yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)])); (yyval.pval)->u2.arglist = (yyvsp[(3) - (3)].pval); @@ -2845,36 +2848,36 @@ yyreduce: break; case 124: -#line 589 "ael.y" +#line 592 "ael.y" { (yyval.pval) = (yyvsp[(1) - (2)].pval); ;} break; case 125: -#line 590 "ael.y" +#line 593 "ael.y" { (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), (yyvsp[(2) - (3)].pval)); ;} break; case 126: -#line 591 "ael.y" +#line 594 "ael.y" {(yyval.pval)=(yyvsp[(1) - (2)].pval);;} break; case 127: -#line 594 "ael.y" +#line 597 "ael.y" { (yyval.pval) = npval2(PV_INCLUDES, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); - (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval);;} + (yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval);set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;} break; case 128: -#line 597 "ael.y" +#line 600 "ael.y" { (yyval.pval) = npval2(PV_INCLUDES, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));;} break; /* Line 1270 of yacc.c. */ -#line 2878 "ael.tab.c" +#line 2881 "ael.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -3093,7 +3096,7 @@ yyreturn: } -#line 602 "ael.y" +#line 605 "ael.y" static char *token_equivs1[] = @@ -3279,7 +3282,18 @@ static pval * linku1(pval *head, pval *tail) head->u1_last->next = tail; } head->u1_last = tail; + tail->prev = head; /* the dad link only points to containers */ } return head; } +/* this routine adds a dad ptr to each element in the list */ +static void set_dads(struct pval *dad, struct pval *child_list) +{ + struct pval *t; + + for(t=child_list;t;t=t->next) /* simple stuff */ + t->dad = dad; +} + + diff --git a/pbx/ael/ael.y b/pbx/ael/ael.y index e581ba71c..309cc939a 100644 --- a/pbx/ael/ael.y +++ b/pbx/ael/ael.y @@ -34,7 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/ael_structs.h" static pval * linku1(pval *head, pval *tail); - +static void set_dads(pval *dad, pval *child_list); void reset_parencount(yyscan_t yyscanner); void reset_semicount(yyscan_t yyscanner); void reset_argcount(yyscan_t yyscanner ); @@ -204,6 +204,7 @@ context : opt_abstract KW_CONTEXT context_name LC elements RC { $$ = npval2(PV_CONTEXT, &@1, &@6); $$->u1.str = $3; $$->u2.statements = $5; + set_dads($$,$5); $$->u3.abstract = $1; } ; @@ -214,12 +215,14 @@ opt_abstract: KW_ABSTRACT { $$ = 1; } macro : KW_MACRO word LP arglist RP LC macro_statements RC { $$ = npval2(PV_MACRO, &@1, &@8); - $$->u1.str = $2; $$->u2.arglist = $4; $$->u3.macro_statements = $7; } + $$->u1.str = $2; $$->u2.arglist = $4; $$->u3.macro_statements = $7; + set_dads($$,$7);} ; globals : KW_GLOBALS LC global_statements RC { $$ = npval2(PV_GLOBALS, &@1, &@4); - $$->u1.statements = $3;} + $$->u1.statements = $3; + set_dads($$,$3);} ; global_statements : { $$ = NULL; } @@ -263,21 +266,21 @@ ignorepat : KW_IGNOREPAT EXTENMARK word SEMI { extension : word EXTENMARK statement { $$ = npval2(PV_EXTENSION, &@1, &@3); $$->u1.str = $1; - $$->u2.statements = $3; } + $$->u2.statements = $3; set_dads($$,$3);} | KW_REGEXTEN word EXTENMARK statement { $$ = npval2(PV_EXTENSION, &@1, &@4); $$->u1.str = $2; - $$->u2.statements = $4; + $$->u2.statements = $4; set_dads($$,$4); $$->u4.regexten=1;} | KW_HINT LP word3_list RP word EXTENMARK statement { $$ = npval2(PV_EXTENSION, &@1, &@7); $$->u1.str = $5; - $$->u2.statements = $7; + $$->u2.statements = $7; set_dads($$,$7); $$->u3.hints = $3;} | KW_REGEXTEN KW_HINT LP word3_list RP word EXTENMARK statement { $$ = npval2(PV_EXTENSION, &@1, &@8); $$->u1.str = $6; - $$->u2.statements = $8; + $$->u2.statements = $8; set_dads($$,$8); $$->u4.regexten=1; $$->u3.hints = $4;} @@ -366,7 +369,7 @@ goto_word : word { $$ = $1;} switch_statement : KW_SWITCH test_expr LC case_statements RC { $$ = npval2(PV_SWITCH, &@1, &@5); $$->u1.str = $2; - $$->u2.statements = $4;} + $$->u2.statements = $4; set_dads($$,$4);} ; /* @@ -374,7 +377,7 @@ switch_statement : KW_SWITCH test_expr LC case_statements RC { */ statement : LC statements RC { $$ = npval2(PV_STATEMENTBLOCK, &@1, &@3); - $$->u1.list = $2; } + $$->u1.list = $2; set_dads($$,$2);} | assignment { $$ = $1; } | KW_GOTO target SEMI { $$ = npval2(PV_GOTO, &@1, &@3); @@ -392,11 +395,11 @@ statement : LC statements RC { $$->u1.for_init = $4; $$->u2.for_test=$7; $$->u3.for_inc = $10; - $$->u4.for_statements = $12;} + $$->u4.for_statements = $12; set_dads($$,$12);} | KW_WHILE test_expr statement { $$ = npval2(PV_WHILE, &@1, &@3); $$->u1.str = $2; - $$->u2.statements = $3; } + $$->u2.statements = $3; set_dads($$,$3);} | switch_statement { $$ = $1; } | AMPER macro_call SEMI { $$ = update_last($2, &@2); } | application_call SEMI { $$ = update_last($1, &@2); } @@ -441,8 +444,8 @@ statement : LC statements RC { | KW_CONTINUE SEMI { $$ = npval2(PV_CONTINUE, &@1, &@2); } | if_like_head statement opt_else { $$ = update_last($1, &@2); - $$->u2.statements = $2; - $$->u3.else_statements = $3;} + $$->u2.statements = $2; set_dads($$,$2); + $$->u3.else_statements = $3;set_dads($$,$3);} | SEMI { $$=0; } ; @@ -541,15 +544,15 @@ case_statements: /* empty */ { $$ = NULL; } case_statement: KW_CASE word COLON statements { $$ = npval2(PV_CASE, &@1, &@3); /* XXX 3 or 4 ? */ $$->u1.str = $2; - $$->u2.statements = $4;} + $$->u2.statements = $4; set_dads($$,$4);} | KW_DEFAULT COLON statements { $$ = npval2(PV_DEFAULT, &@1, &@3); $$->u1.str = NULL; - $$->u2.statements = $3;} + $$->u2.statements = $3;set_dads($$,$3);} | KW_PATTERN word COLON statements { $$ = npval2(PV_PATTERN, &@1, &@4); /* XXX@3 or @4 ? */ $$->u1.str = $2; - $$->u2.statements = $4;} + $$->u2.statements = $4;set_dads($$,$4);} ; macro_statements: /* empty */ { $$ = NULL; } @@ -560,17 +563,17 @@ macro_statement : statement {$$=$1;} | KW_CATCH word LC statements RC { $$ = npval2(PV_CATCH, &@1, &@5); $$->u1.str = $2; - $$->u2.statements = $4;} + $$->u2.statements = $4; set_dads($$,$4);} ; switches : KW_SWITCHES LC switchlist RC { $$ = npval2(PV_SWITCHES, &@1, &@2); - $$->u1.list = $3; } + $$->u1.list = $3; set_dads($$,$3);} ; eswitches : KW_ESWITCHES LC switchlist RC { $$ = npval2(PV_ESWITCHES, &@1, &@2); - $$->u1.list = $3; } + $$->u1.list = $3; set_dads($$,$3);} ; switchlist : /* empty */ { $$ = NULL; } @@ -593,7 +596,7 @@ includeslist : included_entry SEMI { $$ = $1; } includes : KW_INCLUDES LC includeslist RC { $$ = npval2(PV_INCLUDES, &@1, &@4); - $$->u1.list = $3;} + $$->u1.list = $3;set_dads($$,$3);} | KW_INCLUDES LC RC { $$ = npval2(PV_INCLUDES, &@1, &@3);} ; @@ -784,6 +787,17 @@ static pval * linku1(pval *head, pval *tail) head->u1_last->next = tail; } head->u1_last = tail; + tail->prev = head; /* the dad link only points to containers */ } return head; } + +/* this routine adds a dad ptr to each element in the list */ +static void set_dads(struct pval *dad, struct pval *child_list) +{ + struct pval *t; + + for(t=child_list;t;t=t->next) /* simple stuff */ + t->dad = dad; +} + diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c index 680d3d855..17bcada96 100644 --- a/pbx/pbx_ael.c +++ b/pbx/pbx_ael.c @@ -109,10 +109,10 @@ struct ael_priority *new_prio(void); struct ael_extension *new_exten(void); void linkprio(struct ael_extension *exten, struct ael_priority *prio); void destroy_extensions(struct ael_extension *exten); -void linkexten(struct ael_extension *exten, struct ael_extension *add); -void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten ); +static void linkexten(struct ael_extension *exten, struct ael_extension *add); +static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); void set_priorities(struct ael_extension *exten); -void add_extensions(struct ael_extension *exten, struct ast_context *context); +void add_extensions(struct ael_extension *exten); void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root); void destroy_pval(pval *item); void destroy_pval_item(pval *item); @@ -144,11 +144,18 @@ static void check_goto(pval *item); static void find_pval_goto_item(pval *item, int lev); static void find_pval_gotos(pval *item, int lev); -static struct pval *find_label_in_current_context(char *exten, char *label); +static struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_cont); +static struct pval *find_first_label_in_current_context(char *label, pval *curr_cont); static void print_pval_list(FILE *fin, pval *item, int depth); -static struct pval *find_label_in_current_extension(const char *label); +static struct pval *find_label_in_current_extension(const char *label, pval *curr_ext); static struct pval *find_label_in_current_db(const char *context, const char *exten, const char *label); +static pval *get_goto_target(pval *item); +static int label_inside_case(pval *label); +static void attach_exten(struct ael_extension **list, struct ael_extension *newmem); +static void fix_gotos_in_extensions(struct ael_extension *exten); +static pval *get_extension_or_contxt(pval *p); +static pval *get_contxt(pval *p); static void remove_spaces_before_equals(char *str); @@ -1016,6 +1023,97 @@ static void check_month(pval *MON) /* general purpose goto finder */ +static void check_label(pval *item) +{ + /* basically, ensure that a label is not repeated in a context. Period. + The method: well, for each label, find the first label in the context + with the same name. If it's not the current label, then throw an error. */ + struct pval *curr; + + /* printf("==== check_label: ====\n"); */ + if( !current_extension ) + curr = current_context; + else + curr = current_extension; + + struct pval *x = find_first_label_in_current_context((char *)item->u1.str, curr); + /* printf("Hey, check_label found with item = %x, and x is %x, and currcont is %x, label name is %s\n", item,x, current_context, (char *)item->u1.str); */ + if( x && x != item ) + { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: Duplicate label %s! Previously defined at file %s, line %d.\n", + item->filename, item->startline, item->endline, item->u1.str, x->filename, x->startline); + errs++; + } + /* printf("<<<<< check_label: ====\n"); */ +} + +static pval *get_goto_target(pval *item) +{ + /* just one item-- the label should be in the current extension */ + pval *curr_ext = get_extension_or_contxt(item); /* containing exten, or macro */ + pval *curr_cont; + + if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { + struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), curr_ext); + return x; + } + + curr_cont = get_contxt(item); + + /* TWO items */ + if (item->u1.list->next && !item->u1.list->next->next) { + if (!strstr((item->u1.list)->u1.str,"${") + && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { + struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, curr_cont); + return x; + } + } + + /* All 3 items! */ + if (item->u1.list->next && item->u1.list->next->next) { + /* all three */ + pval *first = item->u1.list; + pval *second = item->u1.list->next; + pval *third = item->u1.list->next->next; + + if (!strstr((item->u1.list)->u1.str,"${") + && !strstr(item->u1.list->next->u1.str,"${") + && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { + struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); + if (!x) { + + struct pval *p3; + struct pval *that_context = find_context(item->u1.list->u1.str); + + /* the target of the goto could be in an included context!! Fancy that!! */ + /* look for includes in the current context */ + if (that_context) { + for (p3=that_context->u2.statements; p3; p3=p3->next) { + if (p3->type == PV_INCLUDES) { + struct pval *p4; + for (p4=p3->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + char *incl_context = p4->u1.str; + /* find a matching context name */ + struct pval *that_other_context = find_context(incl_context); + if (that_other_context) { + struct pval *x3; + x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); + if (x3) { + return x3; + } + } + } + } + } + } + } + return x; + } + } + return 0; +} static void check_goto(pval *item) { @@ -1029,9 +1127,9 @@ static void check_goto(pval *item) /* just one item-- the label should be in the current extension */ if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { - struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str)); - /* printf("Calling find_label_in_current_extension with args %s\n", - (char*)((item->u1.list)->u1.str)); */ + struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str), current_extension? current_extension:current_context); /* if in macro, use current context instead */ + /* printf("Called find_label_in_current_extension with arg %s; current_extension is %x: %d\n", + (char*)((item->u1.list)->u1.str), current_extension?current_extension:current_context, current_extension?current_extension->type:current_context->type); */ if (!x) { ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", item->filename, item->startline, item->endline, item->u1.list->u1.str); @@ -1048,7 +1146,7 @@ static void check_goto(pval *item) (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ if (!strstr((item->u1.list)->u1.str,"${") && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { - struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str); + struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str, current_context); if (!x) { ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the current context, or any of its inclusions!\n", item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); @@ -1066,7 +1164,7 @@ static void check_goto(pval *item) pval *second = item->u1.list->next; pval *third = item->u1.list->next->next; - /* printf("Calling find_label_in_current_context with args %s, %s, %s\n", + /* printf("Calling find_label_in_current_db with args %s, %s, %s\n", (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ if (!strstr((item->u1.list)->u1.str,"${") && !strstr(item->u1.list->next->u1.str,"${") @@ -1090,11 +1188,8 @@ static void check_goto(pval *item) /* find a matching context name */ struct pval *that_other_context = find_context(incl_context); if (that_other_context) { - struct pval *context_save = current_context; struct pval *x3; - current_context = that_other_context; - x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str); - current_context = context_save; + x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str, that_other_context); if (x3) { found = x3; break; @@ -1138,7 +1233,7 @@ static void find_pval_goto_item(pval *item, int lev) */ /* printf("Descending into matching macro %s\n", match_context); */ - find_pval_gotos(item->u2.statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ + find_pval_gotos(item->u3.macro_statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ break; @@ -1303,16 +1398,21 @@ static struct pval *match_pval_item(pval *item) item->u3.macro_statements == pval list of statements in macro body. */ + /* printf(" matching in MACRO %s, match_context=%s; retoncontmtch=%d; \n", item->u1.str, match_context, return_on_context_match); */ if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { - if (return_on_context_match && !strcmp(item->u1.str, match_context)) { + + /* printf("MACRO: match context is: %s\n", match_context); */ + + if (return_on_context_match && !strcmp(item->u1.str, match_context)) /* if we're just searching for a context, don't bother descending into them */ { /* printf("Returning on matching macro %s\n", match_context); */ return item; } if (!return_on_context_match) { - /* printf("Descending into matching macro %s\n", match_context); */ - if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { + /* printf("Descending into matching macro %s/%s\n", match_context, item->u1.str); */ + if ((x=match_pval(item->u3.macro_statements))) { + /* printf("Responded with pval match %x\n", x); */ return x; } } @@ -1327,16 +1427,18 @@ static struct pval *match_pval_item(pval *item) item->u2.statements == pval list of statements in context body item->u3.abstract == int 1 if an abstract keyword were present */ + /* printf(" matching in CONTEXT\n"); */ if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { if (return_on_context_match && !strcmp(item->u1.str, match_context)) { /* printf("Returning on matching context %s\n", match_context); */ + /* printf("non-CONTEXT: Responded with pval match %x\n", x); */ return item; } - if (!return_on_context_match ) { /* printf("Descending into matching context %s\n", match_context); */ if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { + /* printf("CONTEXT: Responded with pval match %x\n", x); */ return x; } } @@ -1349,7 +1451,9 @@ static struct pval *match_pval_item(pval *item) /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ + /* printf(" matching in CASE\n"); */ if ((x=match_pval(item->u2.statements))) { + /* printf("CASE: Responded with pval match %x\n", x); */ return x; } break; @@ -1358,7 +1462,9 @@ static struct pval *match_pval_item(pval *item) /* fields: item->u1.str == value of case item->u2.statements == pval list of statements under the case */ + /* printf(" matching in PATTERN\n"); */ if ((x=match_pval(item->u2.statements))) { + /* printf("PATTERN: Responded with pval match %x\n", x); */ return x; } break; @@ -1367,7 +1473,9 @@ static struct pval *match_pval_item(pval *item) /* fields: item->u2.statements == pval list of statements under the case */ + /* printf(" matching in DEFAULT\n"); */ if ((x=match_pval(item->u2.statements))) { + /* printf("DEFAULT: Responded with pval match %x\n", x); */ return x; } break; @@ -1376,7 +1484,9 @@ static struct pval *match_pval_item(pval *item) /* fields: item->u1.str == name of extension to catch item->u2.statements == pval list of statements in context body */ + /* printf(" matching in CATCH\n"); */ if ((x=match_pval(item->u2.statements))) { + /* printf("CATCH: Responded with pval match %x\n", x); */ return x; } break; @@ -1384,7 +1494,9 @@ static struct pval *match_pval_item(pval *item) case PV_STATEMENTBLOCK: /* fields: item->u1.list == pval list of statements in block, one per entry in the list */ + /* printf(" matching in STATEMENTBLOCK\n"); */ if ((x=match_pval(item->u1.list))) { + /* printf("STATEMENTBLOCK: Responded with pval match %x\n", x); */ return x; } break; @@ -1393,7 +1505,7 @@ static struct pval *match_pval_item(pval *item) /* fields: item->u1.str == label name */ /* printf("PV_LABEL %s (cont=%s, exten=%s\n", - item->u1.str, current_context->u1.str, current_extension->u1.str); */ + item->u1.str, current_context->u1.str, (current_extension?current_extension->u1.str:""));*/ if (count_labels) { if (!strcmp(match_label, item->u1.str)) { @@ -1403,6 +1515,7 @@ static struct pval *match_pval_item(pval *item) } else { if (!strcmp(match_label, item->u1.str)) { + /* printf("LABEL: Responded with pval match %x\n", x); */ return item; } } @@ -1415,7 +1528,9 @@ static struct pval *match_pval_item(pval *item) item->u4.for_statements == a pval list of statements in the for () */ + /* printf(" matching in FOR\n"); */ if ((x=match_pval(item->u4.for_statements))) { + /* printf("FOR: Responded with pval match %x\n", x);*/ return x; } break; @@ -1425,7 +1540,9 @@ static struct pval *match_pval_item(pval *item) item->u2.statements == a pval list of statements in the while () */ + /* printf(" matching in WHILE\n"); */ if ((x=match_pval(item->u2.statements))) { + /* printf("WHILE: Responded with pval match %x\n", x); */ return x; } break; @@ -1452,11 +1569,13 @@ static struct pval *match_pval_item(pval *item) item->u3.else_statements == a pval list of statements in the else (could be zero) */ + /* printf(" matching in IF/IFTIME/RANDOM\n"); */ if ((x=match_pval(item->u2.statements))) { return x; } if (item->u3.else_statements) { if ((x=match_pval(item->u3.else_statements))) { + /* printf("IF/IFTIME/RANDOM: Responded with pval match %x\n", x); */ return x; } } @@ -1468,7 +1587,9 @@ static struct pval *match_pval_item(pval *item) item->u2.statements == a pval list of statements in the switch, (will be case statements, most likely!) */ - if ((x=match_pval(item->u3.else_statements))) { + /* printf(" matching in SWITCH\n"); */ + if ((x=match_pval(item->u2.statements))) { + /* printf("SWITCH: Responded with pval match %x\n", x); */ return x; } break; @@ -1480,8 +1601,9 @@ static struct pval *match_pval_item(pval *item) item->u3.hints == a char * hint argument item->u4.regexten == an int boolean. non-zero says that regexten was specified */ + /* printf(" matching in EXTENSION\n"); */ if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { - /* printf("Descending into matching exten %s\n", match_exten); */ + /* printf("Descending into matching exten %s => %s\n", match_exten, item->u1.str); */ if (strcmp(match_label,"1") == 0) { if (item->u2.statements) { struct pval *p5 = item->u2.statements; @@ -1497,6 +1619,7 @@ static struct pval *match_pval_item(pval *item) } if ((x=match_pval(item->u2.statements))) { + /* printf("EXTENSION: Responded with pval match %x\n", x); */ return x; } } else { @@ -1504,6 +1627,7 @@ static struct pval *match_pval_item(pval *item) } break; default: + /* printf(" matching in default = %d\n", item->type); */ break; } return 0; @@ -1515,9 +1639,12 @@ struct pval *match_pval(pval *item) for (i=item; i; i=i->next) { pval *x; + /* printf(" -- match pval: item %d\n", i->type); */ - if ((x = match_pval_item(i))) + if ((x = match_pval_item(i))) { + /* printf("match_pval: returning x=%x\n", (int)x); */ return x; /* cut the search short */ + } } return 0; } @@ -1534,7 +1661,47 @@ int count_labels_in_current_context(char *label) } #endif -struct pval *find_label_in_current_context(char *exten, char *label) +struct pval *find_first_label_in_current_context(char *label, pval *curr_cont) +{ + /* printf(" --- Got args %s, %s\n", exten, label); */ + struct pval *ret; + struct pval *p3; + + count_labels = 0; + return_on_context_match = 0; + match_context = "*"; + match_exten = "*"; + match_label = label; + + ret = match_pval(curr_cont); + if (ret) + return ret; + + /* the target of the goto could be in an included context!! Fancy that!! */ + /* look for includes in the current context */ + for (p3=curr_cont->u2.statements; p3; p3=p3->next) { + if (p3->type == PV_INCLUDES) { + struct pval *p4; + for (p4=p3->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + char *incl_context = p4->u1.str; + /* find a matching context name */ + struct pval *that_context = find_context(incl_context); + if (that_context) { + struct pval *x3; + x3 = find_first_label_in_current_context(label, that_context); + if (x3) { + return x3; + } + } + } + } + } + return 0; +} + +struct pval *find_label_in_current_context(char *exten, char *label, pval *curr_cont) { /* printf(" --- Got args %s, %s\n", exten, label); */ struct pval *ret; @@ -1545,13 +1712,13 @@ struct pval *find_label_in_current_context(char *exten, char *label) match_context = "*"; match_exten = exten; match_label = label; - ret = match_pval(current_context->u2.statements); + ret = match_pval(curr_cont->u2.statements); if (ret) return ret; /* the target of the goto could be in an included context!! Fancy that!! */ /* look for includes in the current context */ - for (p3=current_context->u2.statements; p3; p3=p3->next) { + for (p3=curr_cont->u2.statements; p3; p3=p3->next) { if (p3->type == PV_INCLUDES) { struct pval *p4; for (p4=p3->u1.list; p4; p4=p4->next) { @@ -1561,11 +1728,8 @@ struct pval *find_label_in_current_context(char *exten, char *label) /* find a matching context name */ struct pval *that_context = find_context(incl_context); if (that_context) { - struct pval *context_save = current_context; struct pval *x3; - current_context = that_context; - x3 = find_label_in_current_context(exten, label); - current_context = context_save; + x3 = find_label_in_current_context(exten, label, that_context); if (x3) { return x3; } @@ -1576,7 +1740,7 @@ struct pval *find_label_in_current_context(char *exten, char *label) return 0; } -static struct pval *find_label_in_current_extension(const char *label) +static struct pval *find_label_in_current_extension(const char *label, pval *curr_ext) { /* printf(" --- Got args %s\n", label); */ count_labels = 0; @@ -1584,9 +1748,7 @@ static struct pval *find_label_in_current_extension(const char *label) match_context = "*"; match_exten = "*"; match_label = label; - if (! current_extension) /* macros have no current extension, the whole thing is one extension... */ - return match_pval(current_context->u3.macro_statements); - return match_pval(current_extension->u2.statements); + return match_pval(curr_ext); } static struct pval *find_label_in_current_db(const char *context, const char *exten, const char *label) @@ -2225,6 +2387,8 @@ void check_pval_item(pval *item, struct argapp *apps, int in_globals) item->filename, item->startline, item->endline, item->u1.str); warns++; } + + check_label(item); break; case PV_FOR: @@ -2480,6 +2644,8 @@ void linkprio(struct ael_extension *exten, struct ael_priority *prio) exten->plist_last->next = prio; exten->plist_last = prio; } + if( !prio->exten ) + prio->exten = exten; /* don't override the switch value */ } void destroy_extensions(struct ael_extension *exten) @@ -2522,7 +2688,21 @@ void destroy_extensions(struct ael_extension *exten) } } -void linkexten(struct ael_extension *exten, struct ael_extension *add) +static int label_inside_case(pval *label) +{ + pval *p = label; + + while( p && p->type != PV_MACRO && p->type != PV_CONTEXT ) /* early cutout, sort of */ { + if( p->type == PV_CASE || p->type == PV_DEFAULT || p->type == PV_PATTERN ) { + return 1; + } + + p = p->dad; + } + return 0; +} + +static void linkexten(struct ael_extension *exten, struct ael_extension *add) { add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */ exten->next_exten = add; @@ -2547,7 +2727,7 @@ static void remove_spaces_before_equals(char *str) } } -void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten ) +static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *this_context ) { pval *p,*p2,*p3; struct ael_priority *pr; @@ -2584,6 +2764,11 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct case PV_GOTO: pr = new_prio(); pr->type = AEL_APPCALL; + p->u2.goto_target = get_goto_target(p); + if( p->u2.goto_target ) { + p->u3.goto_target_in_case = p->u2.goto_target->u2.label_in_case = label_inside_case(p->u2.goto_target); + } + if (!p->u1.list->next) /* just one */ { pr->app = strdup("Goto"); if (!mother_exten) @@ -2612,6 +2797,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct pr = new_prio(); pr->type = AEL_LABEL; pr->origin = p; + p->u3.compiled_label = exten; linkprio(exten, pr); break; @@ -2675,7 +2861,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct exten->loop_break = for_end; exten->loop_continue = for_test; - gen_prios(exten, new_label, p->u4.for_statements, mother_exten); /* this will link in all the statements here */ + gen_prios(exten, new_label, p->u4.for_statements, mother_exten, this_context); /* this will link in all the statements here */ linkprio(exten, for_inc); linkprio(exten, for_loop); @@ -2713,7 +2899,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct exten->loop_break = while_end; exten->loop_continue = while_test; - gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the while body statements here */ + gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the while body statements here */ linkprio(exten, while_loop); linkprio(exten, while_end); @@ -2756,6 +2942,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct if (p2->type == PV_CASE) { /* ok, generate a extension and link it in */ switch_case = new_exten(); + switch_case->context = this_context; /* the break/continue locations are inherited from parent */ switch_case->loop_break = exten->loop_break; switch_case->loop_continue = exten->loop_continue; @@ -2765,7 +2952,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct switch_case->name = strdup(buf1); snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); - gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the case body statements here */ + gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the case body statements here */ /* here is where we write code to "fall thru" to the next case... if there is one... */ for (p3=p2->u2.statements; p3; p3=p3->next) { @@ -2817,6 +3004,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct } else if (p2->type == PV_PATTERN) { /* ok, generate a extension and link it in */ switch_case = new_exten(); + switch_case->context = this_context; /* the break/continue locations are inherited from parent */ switch_case->loop_break = exten->loop_break; switch_case->loop_continue = exten->loop_continue; @@ -2826,7 +3014,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct switch_case->name = strdup(buf1); snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, local_control_statement_count); - gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the while body statements here */ + gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */ /* here is where we write code to "fall thru" to the next case... if there is one... */ for (p3=p2->u2.statements; p3; p3=p3->next) { if (!p3->next) @@ -2878,6 +3066,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct default_exists++; /* ok, generate a extension and link it in */ switch_case = new_exten(); + switch_case->context = this_context; /* the break/continue locations are inherited from parent */ switch_case->loop_break = exten->loop_break; switch_case->loop_continue = exten->loop_continue; @@ -2887,7 +3076,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct snprintf(new_label,sizeof(new_label),"sw-%s-default-%d", label, local_control_statement_count); - gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the while body statements here */ + gen_prios(switch_case, new_label, p2->u2.statements, exten, this_context); /* this will link in all the while body statements here */ /* here is where we write code to "fall thru" to the next case... if there is one... */ for (p3=p2->u2.statements; p3; p3=p3->next) { @@ -3030,12 +3219,12 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct linkprio(exten, rand_test); if (p->u3.else_statements) { - gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the else statements here */ + gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the else statements here */ } linkprio(exten, rand_skip); - gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the "true" statements here */ + gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the "true" statements here */ linkprio(exten, rand_end); @@ -3089,11 +3278,11 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct /* now, put the body of the if here */ - gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the statements here */ + gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ if (p->u3.else_statements) { linkprio(exten, if_skip); - gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the statements here */ + gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ } @@ -3136,11 +3325,11 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct /* now, put the body of the if here */ - gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the statements here */ + gen_prios(exten, new_label, p->u2.statements, mother_exten, this_context); /* this will link in all the statements here */ if (p->u3.else_statements) { linkprio(exten, if_skip); - gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the statements here */ + gen_prios(exten, new_label, p->u3.else_statements, mother_exten, this_context); /* this will link in all the statements here */ } @@ -3149,7 +3338,7 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct break; case PV_STATEMENTBLOCK: - gen_prios(exten, label, p->u1.list, mother_exten ); /* recurse into the block */ + gen_prios(exten, label, p->u1.list, mother_exten, this_context ); /* recurse into the block */ break; case PV_CATCH: @@ -3157,11 +3346,12 @@ void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct /* generate an extension with name of catch, put all catch stats into this exten! */ switch_case = new_exten(); + switch_case->context = this_context; linkexten(exten,switch_case); switch_case->name = strdup(p->u1.str); snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); - gen_prios(switch_case, new_label, p->u2.statements,mother_exten); /* this will link in all the catch body statements here */ + gen_prios(switch_case, new_label, p->u2.statements,mother_exten,this_context); /* this will link in all the catch body statements here */ if (switch_case->return_needed) { char buf[2000]; struct ael_priority *np2 = new_prio(); @@ -3204,7 +3394,7 @@ void set_priorities(struct ael_extension *exten) } while ( exten ); } -void add_extensions(struct ael_extension *exten, struct ast_context *context) +void add_extensions(struct ael_extension *exten) { struct ael_priority *pr; char *label=0; @@ -3212,12 +3402,11 @@ void add_extensions(struct ael_extension *exten, struct ast_context *context) struct ael_priority *last = 0; if (exten->hints) { - if (ast_add_extension2(context, 0 /*no replace*/, exten->name, PRIORITY_HINT, NULL, exten->cidmatch, + if (ast_add_extension2(exten->context, 0 /*no replace*/, exten->name, PRIORITY_HINT, NULL, exten->cidmatch, exten->hints, NULL, FREE, registrar)) { ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", exten->name); } - } for (pr=exten->plist; pr; pr=pr->next) { @@ -3293,8 +3482,7 @@ void add_extensions(struct ael_extension *exten, struct ast_context *context) else label = 0; - - if (ast_add_extension2(context, 0 /*no replace*/, exten->name, pr->priority_num, (label?label:NULL), exten->cidmatch, + if (ast_add_extension2(exten->context, 0 /*no replace*/, exten->name, pr->priority_num, (label?label:NULL), exten->cidmatch, app, strdup(appargs), FREE, registrar)) { ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, exten->name); @@ -3305,6 +3493,86 @@ void add_extensions(struct ael_extension *exten, struct ast_context *context) } while ( exten ); } +static void attach_exten(struct ael_extension **list, struct ael_extension *newmem) +{ + /* travel to the end of the list... */ + struct ael_extension *lptr; + if( !*list ) { + *list = newmem; + return; + } + lptr = *list; + + while( lptr->next_exten ) { + lptr = lptr->next_exten; + } + /* lptr should now pointing to the last element in the list; it has a null next_exten pointer */ + lptr->next_exten = newmem; +} + +static pval *get_extension_or_contxt(pval *p) +{ + while( p && p->type != PV_EXTENSION && p->type != PV_CONTEXT && p->type != PV_MACRO ) { + + p = p->dad; + } + + return p; +} + +static pval *get_contxt(pval *p) +{ + while( p && p->type != PV_CONTEXT && p->type != PV_MACRO ) { + + p = p->dad; + } + + return p; +} + +static void fix_gotos_in_extensions(struct ael_extension *exten) +{ + struct ael_extension *e; + for(e=exten;e;e=e->next_exten) { + + struct ael_priority *p; + for(p=e->plist;p;p=p->next) { + + if( p->origin && p->origin->type == PV_GOTO && p->origin->u3.goto_target_in_case ) { + + /* fix the extension of the goto target to the actual extension in the post-compiled dialplan */ + + pval *target = p->origin->u2.goto_target; + struct ael_extension *z = target->u3.compiled_label; + pval *pv2 = p->origin; + char buf1[500]; + char *apparg_save = p->appargs; + + p->appargs = 0; + if (!pv2->u1.list->next) /* just one -- it won't hurt to repeat the extension */ { + snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->u1.str); + p->appargs = strdup(buf1); + + } else if (pv2->u1.list->next && !pv2->u1.list->next->next) /* two */ { + snprintf(buf1,sizeof(buf1),"%s|%s", z->name, pv2->u1.list->next->u1.str); + p->appargs = strdup(buf1); + } else if (pv2->u1.list->next && pv2->u1.list->next->next) { + snprintf(buf1,sizeof(buf1),"%s|%s|%s", pv2->u1.list->u1.str, + z->name, + pv2->u1.list->next->next->u1.str); + p->appargs = strdup(buf1); + } + else + printf("WHAT? The goto doesn't fall into one of three cases for GOTO????\n"); + + if( apparg_save ) { + free(apparg_save); + } + } + } + } +} + void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) { @@ -3312,7 +3580,8 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) struct ast_context *context; char buf[2000]; struct ael_extension *exten; - + struct ael_extension *exten_list = 0; + for (p=root; p; p=p->next ) { pval *lp; int argc; @@ -3324,6 +3593,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) context = ast_context_create(local_contexts, buf, registrar); exten = new_exten(); + exten->context = context; exten->name = strdup("s"); argc = 1; for (lp=p->u2.arglist; lp; lp=lp->next) { @@ -3338,7 +3608,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) } /* CONTAINS APPCALLS, CATCH, just like extensions... */ - gen_prios(exten, p->u1.str, p->u3.macro_statements, 0 ); + gen_prios(exten, p->u1.str, p->u3.macro_statements, 0, context ); if (exten->return_needed) { struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; @@ -3350,8 +3620,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) } set_priorities(exten); - add_extensions(exten, context); - destroy_extensions(exten); + attach_exten(&exten_list, exten); break; case PV_GLOBALS: @@ -3365,7 +3634,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) case PV_CONTEXT: context = ast_context_create(local_contexts, p->u1.str, registrar); - + /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ for (p2=p->u2.statements; p2; p2=p2->next) { pval *p3; @@ -3375,6 +3644,8 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) case PV_EXTENSION: exten = new_exten(); exten->name = strdup(p2->u1.str); + exten->context = context; + if( (s3=strchr(exten->name, '/') ) != 0 ) { *s3 = 0; @@ -3384,7 +3655,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) if ( p2->u3.hints ) exten->hints = strdup(p2->u3.hints); exten->regexten = p2->u4.regexten; - gen_prios(exten, p->u1.str, p2->u2.statements, 0 ); + gen_prios(exten, p->u1.str, p2->u2.statements, 0, context ); if (exten->return_needed) { struct ael_priority *np2 = new_prio(); np2->type = AEL_APPCALL; @@ -3405,8 +3676,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) } set_priorities(exten); - add_extensions(exten, context); - destroy_extensions(exten); + attach_exten(&exten_list, exten); break; case PV_IGNOREPAT: @@ -3466,6 +3736,13 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) } } + /* moved these from being done after a macro or extension were processed, + to after all processing is done, for the sake of fixing gotos to labels inside cases... */ + /* I guess this would be considered 2nd pass of compiler now... */ + fix_gotos_in_extensions(exten_list); /* find and fix extension ref in gotos to labels that are in case statements */ + add_extensions(exten_list); /* actually makes calls to create priorities in ast_contexts -- feeds dialplan to asterisk */ + destroy_extensions(exten_list); /* all that remains is an empty husk, discard of it as is proper */ + } /* interface stuff */ -- cgit v1.2.3