Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv9971

Modified Files:
        pbx.c 
Log Message:
re-factor variable/function name parsing, and add substring support to function 
results (issue #5284)


Index: pbx.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx.c,v
retrieving revision 1.281
retrieving revision 1.282
diff -u -d -r1.281 -r1.282
--- pbx.c       26 Sep 2005 19:51:58 -0000      1.281
+++ pbx.c       29 Sep 2005 04:39:14 -0000      1.282
@@ -908,60 +908,102 @@
        return NULL;
 }
 
+/* Note that it's negative -- that's important later. */
+#define DONT_HAVE_LENGTH       0x80000000
+
+static int parse_variable_name(char *var, int *offset, int *length, int 
*isfunc)
+{
+       char *varchar, *offsetchar = NULL;
+       int parens=0;
+
+       *offset = 0;
+       *length = DONT_HAVE_LENGTH;
+       *isfunc = 0;
+       for (varchar=var; *varchar; varchar++) {
+               switch (*varchar) {
+               case '(':
+                       (*isfunc)++;
+                       parens++;
+                       break;
+               case ')':
+                       parens--;
+                       break;
+               case ':':
+                       if (parens == 0) {
+                               offsetchar = varchar + 1;
+                               *varchar = '\0';
+                               goto pvn_endfor;
+                       }
+               }
+       }
+pvn_endfor:
+       if (offsetchar) {
+               sscanf(offsetchar, "%d:%d", offset, length);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+static char *substring(char *value, int offset, int length, char *workspace, 
size_t workspace_len)
+{
+       char *ret = workspace;
+
+       /* No need to do anything */
+       if (offset == 0 && length==-1) {
+               return value;
+       }
+
+       ast_copy_string(workspace, value, workspace_len);
+
+       if (abs(offset) > strlen(ret)) {        /* Offset beyond string */
+               if (offset >= 0) 
+                       offset = strlen(ret);
+               else 
+                       offset =- strlen(ret);  
+       }
+
+       /* Detect too-long length */
+       if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > 
strlen(ret))) {
+               if (offset >= 0) 
+                       length = strlen(ret)-offset;
+               else 
+                       length = strlen(ret)+offset;
+       }
+
+       /* Bounce up to the right offset */
+       if (offset >= 0)
+               ret += offset;
+       else
+               ret += strlen(ret)+offset;
+
+       /* Chop off at the requisite length */
+       if (length >= 0)
+               ret[length] = '\0';
+
+       return ret;
+}
+
 /*--- pbx_retrieve_variable: Support for Asterisk built-in variables and
       functions in the dialplan
   ---*/
 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, 
char *workspace, int workspacelen, struct varshead *headp)
 {
-       char *first,*second;
        char tmpvar[80];
        time_t thistime;
        struct tm brokentime;
-       int offset,offset2;
+       int offset, offset2, isfunc;
        struct ast_var_t *variables;
 
        if (c) 
                headp=&c->varshead;
        *ret=NULL;
-       if ((first=strchr(var,':'))) {  /* : Remove characters counting from 
end or start of string */
-               ast_copy_string(tmpvar, var, sizeof(tmpvar));
-               first = strchr(tmpvar, ':');
-               if (!first)
-                       first = tmpvar + strlen(tmpvar);
-               *first='\0';
-               pbx_retrieve_variable(c,tmpvar,ret,workspace,workspacelen - 1, 
headp);
+       ast_copy_string(tmpvar, var, sizeof(tmpvar));
+       if (parse_variable_name(tmpvar, &offset, &offset2, &isfunc)) {
+               pbx_retrieve_variable(c, tmpvar, ret, workspace, workspacelen, 
headp);
                if (!(*ret)) 
                        return;
-               offset=atoi(first+1);   /* The number of characters, 
-                                          positive: remove # of chars from 
start
-                                          negative: keep # of chars from end */
-                                               
-               if ((second=strchr(first+1,':'))) {     
-                       *second='\0';
-                       offset2 = atoi(second+1);               /* Number of 
chars to copy */
-               } else if (offset >= 0) {
-                       offset2 = strlen(*ret)-offset;  /* Rest of string */
-               } else {
-                       offset2 = abs(offset);
-               }
-
-               if (abs(offset) > strlen(*ret)) {       /* Offset beyond string 
*/
-                       if (offset >= 0) 
-                               offset = strlen(*ret);
-                       else 
-                               offset =- strlen(*ret); 
-               }
-               if ((offset < 0 && offset2 > -offset) || (offset >= 0 && 
offset+offset2 > strlen(*ret))) {
-                       if (offset >= 0) 
-                               offset2 = strlen(*ret)-offset;
-                       else 
-                               offset2 = strlen(*ret)+offset;
-               }
-               if (offset >= 0)
-                       *ret += offset;
-               else
-                       *ret += strlen(*ret)+offset;
-               (*ret)[offset2] = '\0';         /* Cut at offset2 position */
+               *ret = substring(*ret, offset, offset2, workspace, 
workspacelen);
        } else if (c && !strncmp(var, "CALL", 4)) {
                if (!strncmp(var + 4, "ER", 2)) {
                        if (!strncmp(var + 6, "ID", 2)) {
@@ -1386,7 +1428,7 @@
 {
        char *cp4;
        const char *tmp, *whereweare;
-       int length;
+       int length, offset, offset2, isfunction;
        char *workspace = NULL;
        char *ltmp = NULL, *var = NULL;
        char *nextvar, *nextexp, *nextthing;
@@ -1477,7 +1519,8 @@
 
                        workspace[0] = '\0';
 
-                       if (var[len - 1] == ')') {
+                       parse_variable_name(var, &offset, &offset2, 
&isfunction);
+                       if (isfunction) {
                                /* Evaluate function */
                                cp4 = ast_func_read(c, vars, workspace, 
VAR_BUF_SIZE);
 
@@ -1487,6 +1530,8 @@
                                pbx_retrieve_variable(c, vars, &cp4, workspace, 
VAR_BUF_SIZE, headp);
                        }
                        if (cp4) {
+                               cp4 = substring(cp4, offset, offset2, 
workspace, VAR_BUF_SIZE);
+
                                length = strlen(cp4);
                                if (length > count)
                                        length = count;

_______________________________________________
Asterisk-Cvs mailing list
[email protected]
http://lists.digium.com/mailman/listinfo/asterisk-cvs

Reply via email to