[Asterisk-cvs] asterisk pbx.c,1.281,1.282

kpfleming kpfleming
Thu Sep 29 00:42:38 CDT 2005


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;




More information about the svn-commits mailing list