Add LOCAL_PEEK function, as requested by lmadsen.
authorTilghman Lesher <tilghman@meg.abyt.es>
Tue, 2 Dec 2008 18:39:12 +0000 (18:39 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Tue, 2 Dec 2008 18:39:12 +0000 (18:39 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@160344 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_stack.c

index 0a911e5..1311bad 100644 (file)
@@ -142,6 +142,27 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        <ref type="application">Return</ref>
                </see-also>
        </function>
+       <function name="LOCAL_PEEK" language="en_US">
+               <synopsis>
+                       Retrieve variables hidden by the local gosub stack frame.
+               </synopsis>
+               <syntax>
+                       <parameter name="n" required="true" />
+                       <parameter name="varname" required="true" />
+               </syntax>
+               <description>
+                       <para>Read a variable <replaceable>varname</replaceable> hidden by 
+                       <replaceable>n</replaceable> levels of gosub stack frames.  Note that ${LOCAL_PEEK(0,foo)}
+                       is the same as ${foo}, since the value of <replaceable>n</replaceable> peeks under 0 levels of
+                       stack frames; in other words, 0 is the current level.  If <replaceable>n</replaceable> exceeds
+                       the available number of stack frames, then an empty string is returned.</para>
+               </description>
+               <see-also>
+                       <ref type="application">Gosub</ref>
+                       <ref type="application">GosubIf</ref>
+                       <ref type="application">Return</ref>
+               </see-also>
+       </function>
  ***/
 
 static const char *app_gosub = "Gosub";
@@ -471,6 +492,42 @@ static struct ast_custom_function local_function = {
        .read = local_read,
 };
 
+static int peek_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+       int found = 0, n;
+       struct ast_var_t *variables;
+       AST_DECLARE_APP_ARGS(args,
+               AST_APP_ARG(n);
+               AST_APP_ARG(name);
+       );
+
+       if (!chan) {
+               ast_log(LOG_ERROR, "LOCAL_PEEK must be called on an active channel\n");
+               return -1;
+       }
+
+       AST_STANDARD_APP_ARGS(args, data);
+       n = atoi(args.n);
+       *buf = '\0';
+
+       ast_channel_lock(chan);
+       AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
+               if (!strcmp(args.name, ast_var_name(variables)) && ++found > n) {
+                       ast_copy_string(buf, ast_var_value(variables), len);
+                       break;
+               }
+       }
+       ast_channel_unlock(chan);
+       return 0;
+}
+
+static struct ast_custom_function peek_function = {
+       .name = "LOCAL_PEEK",
+       .synopsis = "Peeks at variables within the variable stack",
+       .syntax = "LOCAL_PEEK(<n>|<varname>)",
+       .read = peek_read,
+};
+
 static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, char **argv)
 {
        int old_priority, priority;
@@ -585,6 +642,7 @@ static int unload_module(void)
        ast_unregister_application(app_gosubif);
        ast_unregister_application(app_gosub);
        ast_custom_function_unregister(&local_function);
+       ast_custom_function_unregister(&peek_function);
 
        return 0;
 }
@@ -607,6 +665,7 @@ static int load_module(void)
        ast_register_application_xml(app_gosubif, gosubif_exec);
        ast_register_application_xml(app_gosub, gosub_exec);
        ast_custom_function_register(&local_function);
+       ast_custom_function_register(&peek_function);
 
        return 0;
 }