diff --git a/.cvsignore b/.cvsignore
index 19b9e692a96d29a95af118638b727c7e36f56fda..417f3ff4dead8b3bb87c2767a76465b1b27e4650 100755
--- a/.cvsignore
+++ b/.cvsignore
@@ -13,3 +13,4 @@ update.out
 .tags-sources
 tags
 TAGS
+testexpr2
diff --git a/ast_expr2.c b/ast_expr2.c
index 685276a11b235ee0e4c6bf51ae2c584fa1e65011..c841616f5ec94792563357d4d7ac69ad95a2062d 100755
--- a/ast_expr2.c
+++ b/ast_expr2.c
@@ -1734,7 +1734,7 @@ to_string (struct val *vp)
 		return;
 	}
 
-	sprintf (tmp, "%ld", vp->u.i);
+	sprintf(tmp, "%ld", (long int) vp->u.i);
 	vp->type = AST_EXPR_string;
 	vp->u.s  = tmp;
 }
@@ -1775,11 +1775,12 @@ void ast_log(int level, const char *file, int line, const char *function, const
 
 
 int main(int argc,char **argv) {
-	char *s;
-
-	s=ast_expr(argv[1]);
-
-	printf("=====%s======\n",s);
+	char s[4096];
+	
+	if (ast_expr(argv[1], s, sizeof(s)))
+		printf("=====%s======\n",s);
+	else
+		printf("No result\n");
 }
 
 #endif
diff --git a/ast_expr2.fl b/ast_expr2.fl
index a2282cdbea86d8bbe3553e206b2e48072927ecb5..39df6013b4b9fda9a5b146ad60ef6db79da443c2 100755
--- a/ast_expr2.fl
+++ b/ast_expr2.fl
@@ -15,6 +15,7 @@
 #include <limits.h>
 #include <asterisk/ast_expr.h>
 #include <asterisk/logger.h>
+#include <asterisk/strings.h>
 
 enum valtype {
 	AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
@@ -41,6 +42,8 @@ struct parse_io
 	yyscan_t scanner;
 };
  
+void ast_yyset_column(int column_no, yyscan_t yyscanner);
+int ast_yyget_column(yyscan_t yyscanner);
 
 %}
 
@@ -90,42 +93,47 @@ struct parse_io
    ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
 	UGH! that would be inappropriate. */
 
-int ast_yyparse( void *); /* need to/should define this prototype for the call to yyparse */
-char *ast_expr(char *arg); /* and this prototype for the following func */
-int		ast_yyerror(const char *,YYLTYPE *, struct parse_io *); /* likewise */
+int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
+int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
 
-char *ast_expr (char *arg)
+int ast_expr(char *expr, char *buf, int length)
 {
 	struct parse_io *io;
-	char *pirouni;
 	
-	io = (struct parse_io *)calloc(sizeof(struct parse_io),1);
-	io->string = arg;  /* to pass to the error routine */
+	io = calloc(sizeof(struct parse_io),1);
+	io->string = expr;  /* to pass to the error routine */
 	
 	ast_yylex_init(&io->scanner);
 	
-	ast_yy_scan_string(arg,io->scanner);
+	ast_yy_scan_string(expr, io->scanner);
 	
-	ast_yyparse ((void *)io);
+	ast_yyparse ((void *) io);
 
 	ast_yylex_destroy(io->scanner);
-	
 
-	if (io->val==NULL) {
-		pirouni=strdup("0");
-		return(pirouni);
+	if (io->val == NULL) {
+		if (length > 1) {
+			strcpy(buf, "0");
+			return 1;
+		}
 	} else {
 		if (io->val->type == AST_EXPR_integer) {
-			pirouni = malloc(24);
-			sprintf(pirouni, "%ld", io->val->u.i);
-		}
-		else {
-			pirouni=strdup(io->val->u.s);
+			int res_length;
+
+			res_length = snprintf(buf, length, "%ld", (long int) io->val->u.i);
+			return res_length <= length ? res_length : length;
+		} else {
+#ifdef STANDALONE
+			strncpy(buf, io->val->u.s, length - 1);
+#else /* !STANDALONE */
+			ast_copy_string(buf, io->val->u.s, length);
+#endif /* STANDALONE */
+			return strlen(buf);
 		}
 		free(io->val);
 	}
 	free(io);
-	return(pirouni);
+	return 0;
 }
 
 int ast_yyerror (const char *s,  yyltype *loc, struct parse_io *parseio )
diff --git a/ast_expr2.y b/ast_expr2.y
index 47a0c7ed128802d16ca05dff3c05d06e53e76646..b25917cc46412b3932673a9bb18006f254a88828 100755
--- a/ast_expr2.y
+++ b/ast_expr2.y
@@ -349,7 +349,7 @@ to_string (struct val *vp)
 		return;
 	}
 
-	sprintf (tmp, "%ld", vp->u.i);
+	sprintf(tmp, "%ld", (long int) vp->u.i);
 	vp->type = AST_EXPR_string;
 	vp->u.s  = tmp;
 }
@@ -390,11 +390,12 @@ void ast_log(int level, const char *file, int line, const char *function, const
 
 
 int main(int argc,char **argv) {
-	char *s;
-
-	s=ast_expr(argv[1]);
-
-	printf("=====%s======\n",s);
+	char s[4096];
+	
+	if (ast_expr(argv[1], s, sizeof(s)))
+		printf("=====%s======\n",s);
+	else
+		printf("No result\n");
 }
 
 #endif
diff --git a/ast_expr2f.c b/ast_expr2f.c
index fce65a2a023b5c5c852a3964001074adf96f0b51..c343c43139c1da79f7ab121d43ad2d79a35b01cd 100755
--- a/ast_expr2f.c
+++ b/ast_expr2f.c
@@ -460,6 +460,7 @@ static yyconst flex_int16_t yy_chk[56] =
 #include <limits.h>
 #include <asterisk/ast_expr.h>
 #include <asterisk/logger.h>
+#include <asterisk/strings.h>
 
 enum valtype {
 	AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
@@ -486,8 +487,10 @@ struct parse_io
 	yyscan_t scanner;
 };
  
+void ast_yyset_column(int column_no, yyscan_t yyscanner);
+int ast_yyget_column(yyscan_t yyscanner);
 
-#line 491 "ast_expr2f.c"
+#line 494 "ast_expr2f.c"
 
 #define INITIAL 0
 
@@ -720,10 +723,10 @@ YY_DECL
 	register int yy_act;
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
-#line 55 "ast_expr2.fl"
+#line 58 "ast_expr2.fl"
 
 
-#line 727 "ast_expr2f.c"
+#line 730 "ast_expr2f.c"
 
     yylval = yylval_param;
 
@@ -808,129 +811,129 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 57 "ast_expr2.fl"
+#line 60 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_OR;}
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 58 "ast_expr2.fl"
+#line 61 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_AND;}
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 59 "ast_expr2.fl"
+#line 62 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_EQ;}
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 60 "ast_expr2.fl"
+#line 63 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_GT;}
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 61 "ast_expr2.fl"
+#line 64 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_LT;}
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 62 "ast_expr2.fl"
+#line 65 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_GE;}
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 63 "ast_expr2.fl"
+#line 66 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_LE;}
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 64 "ast_expr2.fl"
+#line 67 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_NE;}
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 65 "ast_expr2.fl"
+#line 68 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 66 "ast_expr2.fl"
+#line 69 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_MINUS;}
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 67 "ast_expr2.fl"
+#line 70 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_MULT;}
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 68 "ast_expr2.fl"
+#line 71 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_DIV;}
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 69 "ast_expr2.fl"
+#line 72 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_MOD;}
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 70 "ast_expr2.fl"
+#line 73 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_COND;}
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 71 "ast_expr2.fl"
+#line 74 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_COLON;}
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 72 "ast_expr2.fl"
+#line 75 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 73 "ast_expr2.fl"
+#line 76 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_LP;}
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 74 "ast_expr2.fl"
+#line 77 "ast_expr2.fl"
 { SET_COLUMNS; SET_STRING; return TOK_RP;}
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 76 "ast_expr2.fl"
+#line 79 "ast_expr2.fl"
 {}
 	YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 77 "ast_expr2.fl"
+#line 80 "ast_expr2.fl"
 {SET_COLUMNS; SET_STRING; return TOKEN;}
 	YY_BREAK
 case 21:
 /* rule 21 can match eol */
 YY_RULE_SETUP
-#line 79 "ast_expr2.fl"
+#line 82 "ast_expr2.fl"
 {/* what to do with eol */}
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 80 "ast_expr2.fl"
+#line 83 "ast_expr2.fl"
 {   SET_COLUMNS;  /* the original behavior of the expression parser was to bring in numbers as a numeric string */
 				SET_NUMERIC_STRING;
 				return TOKEN;}
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 83 "ast_expr2.fl"
+#line 86 "ast_expr2.fl"
 {SET_COLUMNS; SET_STRING; return TOKEN;}
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 85 "ast_expr2.fl"
+#line 88 "ast_expr2.fl"
 ECHO;
 	YY_BREAK
-#line 934 "ast_expr2f.c"
+#line 937 "ast_expr2f.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -2068,7 +2071,7 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner)
 #undef YY_DECL_IS_OURS
 #undef YY_DECL
 #endif
-#line 85 "ast_expr2.fl"
+#line 88 "ast_expr2.fl"
 
 
 
@@ -2078,42 +2081,47 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner)
    ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
 	UGH! that would be inappropriate. */
 
-int ast_yyparse( void *); /* need to/should define this prototype for the call to yyparse */
-char *ast_expr(char *arg); /* and this prototype for the following func */
-int		ast_yyerror(const char *,YYLTYPE *, struct parse_io *); /* likewise */
+int ast_yyparse(void *); /* need to/should define this prototype for the call to yyparse */
+int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
 
-char *ast_expr (char *arg)
+int ast_expr(char *expr, char *buf, int length)
 {
 	struct parse_io *io;
-	char *pirouni;
 	
-	io = (struct parse_io *)calloc(sizeof(struct parse_io),1);
-	io->string = arg;  /* to pass to the error routine */
+	io = calloc(sizeof(struct parse_io),1);
+	io->string = expr;  /* to pass to the error routine */
 	
 	ast_yylex_init(&io->scanner);
 	
-	ast_yy_scan_string(arg,io->scanner);
+	ast_yy_scan_string(expr, io->scanner);
 	
-	ast_yyparse ((void *)io);
+	ast_yyparse ((void *) io);
 
 	ast_yylex_destroy(io->scanner);
-	
 
-	if (io->val==NULL) {
-		pirouni=strdup("0");
-		return(pirouni);
+	if (io->val == NULL) {
+		if (length > 1) {
+			strcpy(buf, "0");
+			return 1;
+		}
 	} else {
 		if (io->val->type == AST_EXPR_integer) {
-			pirouni = malloc(24);
-			sprintf(pirouni, "%ld", io->val->u.i);
-		}
-		else {
-			pirouni=strdup(io->val->u.s);
+			int res_length;
+
+			res_length = snprintf(buf, length, "%ld", (long int) io->val->u.i);
+			return res_length <= length ? res_length : length;
+		} else {
+#ifdef STANDALONE
+			strncpy(buf, io->val->u.s, length - 1);
+#else /* !STANDALONE */
+			ast_copy_string(buf, io->val->u.s, length);
+#endif /* STANDALONE */
+			return strlen(buf);
 		}
 		free(io->val);
 	}
 	free(io);
-	return(pirouni);
+	return 0;
 }
 
 int ast_yyerror (const char *s,  yyltype *loc, struct parse_io *parseio )
diff --git a/include/asterisk/ast_expr.h b/include/asterisk/ast_expr.h
index 3739acb7e7b001ca9e87825c691b4120e3849c2a..c5981a2044f9b5dc5d0781c07e2f84a44d6b48e2 100755
--- a/include/asterisk/ast_expr.h
+++ b/include/asterisk/ast_expr.h
@@ -1 +1,25 @@
-extern char *ast_expr (char *arg);
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Copyright (C) 2005, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2
+ */
+
+#ifndef _ASTERISK_EXPR_H
+#define _ASTERISK_EXPR_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+int ast_expr(char *expr, char *buf, int length);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_EXPR_H */
diff --git a/pbx.c b/pbx.c
index 75c94ab766f2e8926be251ad658adf2bbd16fc3b..48892cbb2c00e308fc6bbf7f9594f48b62c4cd89 100755
--- a/pbx.c
+++ b/pbx.c
@@ -1522,19 +1522,12 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
 				vars = var;
 			}
 
-			/* Evaluate expression */			
-			cp4 = ast_expr(vars);
-			
-			ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4);
-			
-			if (cp4) {
-				length = strlen(cp4);
-				if (length > count)
-					length = count;
-				memcpy(cp2, cp4, length);
+			length = ast_expr(vars, cp2, count);
+
+			if (length) {
+				ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
 				count -= length;
 				cp2 += length;
-				free(cp4);
 			}
 		} else
 			break;
diff --git a/utils/Makefile b/utils/Makefile
index 137b0b748c250126f1603e2f5ff2043ab202da72..2ee6a5901e3bc8d5c217ed05a4c930eed463ff51 100755
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -40,6 +40,7 @@ install:
 
 clean:
 	rm -f *.o astman smsq stereorize check_expr .depend
+	rm -f ast_expr2.o ast_expr2f.o
 
 astman: astman.o ../md5.o
 	$(CC) $(CFLAGS) -o astman astman.o ../md5.o -lnewt
@@ -47,8 +48,14 @@ astman: astman.o ../md5.o
 stereorize: stereorize.o frame.o
 	$(CC) $(CFLAGS) -o stereorize stereorize.o frame.o -lm
 
-check_expr : check_expr.c ../ast_expr.a
-	$(CC) $(CFLAGS) -o check_expr check_expr.c ../ast_expr.a
+ast_expr2.o: ../ast_expr2.c
+	gcc -g -c -o $@ $<
+
+ast_expr2f.o: ../ast_expr2f.c
+	gcc -g -c -DSTANDALONE -o $@ $<
+
+check_expr: check_expr.c ast_expr2.o ast_expr2f.o
+	$(CC) $(CFLAGS) -o $@ $^
 
 smsq: smsq.o
 	$(CC) $(CFLAGS) -o smsq ${SOL} smsq.o -lpopt
diff --git a/utils/check_expr.c b/utils/check_expr.c
index 0814f1dae28b0aa61a78c8cd8a8aa9580bf4171a..89ff155b9155d044dfca424452e14ddd13910ebb 100755
--- a/utils/check_expr.c
+++ b/utils/check_expr.c
@@ -3,6 +3,7 @@
 #include <stdarg.h>
 #include <string.h>
 #include <stdlib.h>
+#include <../include/asterisk/ast_expr.h>
 
 int global_lineno = 1;
 int global_expr_count = 0;
@@ -120,11 +121,12 @@ int check_expr(char *buffer, char *error_report)
 
 int check_eval(char *buffer, char *error_report)
 {
-	char *cp, *ep, *xp, *s;
+	char *cp, *ep, *xp;
+	char s[4096];
 	char evalbuf[80000];
-	extern char *ast_expr(char *);
 	int oplen = 0;
 	int warn_found = 0;
+	int result;
 
 	error_report[0] = 0;
 	ep = evalbuf;
@@ -179,12 +181,11 @@ int check_eval(char *buffer, char *error_report)
 	*ep++ = 0;
 
 	/* now, run the test */
-	s = ast_expr(evalbuf);
-	if (s) {
+	result = ast_expr(evalbuf, s, sizeof(s));
+	if (result) {
 		sprintf(error_report,"line %d, evaluation of $[ %s ] result: %s\n", global_lineno, evalbuf, s);
 		return 1;
-	}
-	else {
+	} else {
 		sprintf(error_report,"line %d, evaluation of $[ %s ] result: ****SYNTAX ERROR****\n", global_lineno, evalbuf);
 		return 1;
 	}