The contents of branch teams/murf/bug_7598 are being folded in here.
authorSteve Murphy <murf@digium.com>
Mon, 7 Aug 2006 12:59:47 +0000 (12:59 +0000)
committerSteve Murphy <murf@digium.com>
Mon, 7 Aug 2006 12:59:47 +0000 (12:59 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39151 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/ael_structs.h
pbx/ael/ael-test/ael-ntest10/extensions.ael [new file with mode: 0644]
pbx/ael/ael-test/ael-test11/extensions.ael [new file with mode: 0644]
pbx/ael/ael-test/ref.ael-ntest10 [new file with mode: 0644]
pbx/ael/ael-test/ref.ael-test11 [new file with mode: 0644]
pbx/ael/ael-test/ref.ael-test3
pbx/ael/ael-test/ref.ael-test7
pbx/ael/ael.tab.c
pbx/ael/ael.y
pbx/pbx_ael.c

index 68821fe..4bd0710 100644 (file)
 
 typedef enum 
 {
-       PV_WORD, /* an ident, string, name, label, etc. A user-supplied string. */
-       PV_MACRO,
-       PV_CONTEXT,
-       PV_MACRO_CALL,
-       PV_APPLICATION_CALL,
-       PV_CASE,
-       PV_PATTERN,
-       PV_DEFAULT,
-       PV_CATCH,
-       PV_SWITCHES,
-       PV_ESWITCHES,
-       PV_INCLUDES,
-       PV_STATEMENTBLOCK,
-       PV_VARDEC, /* you know, var=val; */
-       PV_GOTO,
-       PV_LABEL,
-       PV_FOR,
-       PV_WHILE,
-       PV_BREAK,
-       PV_RETURN,
-       PV_CONTINUE,
-       PV_IF,
-       PV_IFTIME,
-       PV_RANDOM,
-       PV_SWITCH,
-       PV_EXTENSION,
-       PV_IGNOREPAT,
-       PV_GLOBALS,
+       PV_WORD, /* an ident, string, name, label, etc. A user-supplied string. */ /* 0 */
+       PV_MACRO,             /* 1 */
+       PV_CONTEXT,           /* 2 */
+       PV_MACRO_CALL,        /* 3 */
+       PV_APPLICATION_CALL,  /* 4 */
+       PV_CASE,              /* 5 */
+       PV_PATTERN,           /* 6 */
+       PV_DEFAULT,           /* 7 */
+       PV_CATCH,             /* 8 */
+       PV_SWITCHES,          /* 9 */
+       PV_ESWITCHES,         /* 10 */
+       PV_INCLUDES,          /* 11 */
+       PV_STATEMENTBLOCK,    /* 12 */
+       PV_VARDEC, /* you know, var=val; */  /* 13 */
+       PV_GOTO,              /* 14 */
+       PV_LABEL,             /* 15 */
+       PV_FOR,               /* 16 */
+       PV_WHILE,             /* 17 */
+       PV_BREAK,             /* 18 */
+       PV_RETURN,            /* 19 */
+       PV_CONTINUE,          /* 20 */
+       PV_IF,                /* 21 */
+       PV_IFTIME,            /* 22 */
+       PV_RANDOM,            /* 23 */
+       PV_SWITCH,            /* 24 */
+       PV_EXTENSION,         /* 25 */
+       PV_IGNOREPAT,         /* 26 */
+       PV_GLOBALS,           /* 27 */
 
 } pvaltype;
 
@@ -88,7 +88,8 @@ struct pval
                struct pval *statements; /* used in case, default, catch, while's statement, CONTEXT elements, GLOBALS */
                char *val;  /* used in VARDEC */
                char *for_test; /* used in FOR */
-               
+               int label_in_case; /* a boolean for LABELs */
+               struct pval *goto_target;  /* used in GOTO */
        } u2;
        
        union
@@ -98,6 +99,8 @@ struct pval
                struct pval *macro_statements; /* used in MACRO */
                int abstract;  /* used for context */
                char *hints; /* used in EXTENSION */
+               int goto_target_in_case; /* used in GOTO */
+               struct ael_extension *compiled_label;
        } u3;
        
        union
@@ -106,11 +109,11 @@ struct pval
                int regexten;                /* used in EXTENSION */
        } u4;
        
-       
        struct pval *next; /* the pval at the end of this ptr will ALWAYS be of the same type as this one! 
                                                  EXCEPT for objects of the different types, that are in the same list, like contexts & macros, etc */
        
-       
+       struct pval *dad; /* the 'container' of this struct instance */
+       struct pval *prev; /* the opposite of the 'next' pointer */
 } ;
 
 
@@ -174,6 +177,8 @@ struct ael_extension
        char *hints;
        int regexten;
        
+       struct ast_context *context;
+       
        struct ael_priority *plist;
        struct ael_priority *plist_last;
        struct ael_extension *next_exten;
diff --git a/pbx/ael/ael-test/ael-ntest10/extensions.ael b/pbx/ael/ael-test/ael-ntest10/extensions.ael
new file mode 100644 (file)
index 0000000..4a8386c
--- /dev/null
@@ -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 (file)
index 0000000..886a51e
--- /dev/null
@@ -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 (file)
index 0000000..e74e07f
--- /dev/null
@@ -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 (file)
index 0000000..581ac60
--- /dev/null
@@ -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
index 4dcc0ce..afa17f6 100644 (file)
@@ -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
index fddd1ed..b1f5522 100644 (file)
@@ -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
index dcfca57..6cef52e 100644 (file)
@@ -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;
+}
+
+
index e581ba7..309cc93 100644 (file)
@@ -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;
+}
+
index 680d3d8..17bcada 100644 (file)
@@ -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:"<macro>"));*/
                
                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 */