don't make expression evaluator allocate a memory buffer for each result

to
be returned; use the buffers already present in the PBX for this purpose
update testexpr2/check_expr to allocate buffers for expression
evaluation


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6440 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin P. Fleming
2005-08-29 22:03:37 +00:00
parent 8b331ab17d
commit 0f03a734b1
9 changed files with 143 additions and 99 deletions

View File

@@ -13,3 +13,4 @@ update.out
.tags-sources .tags-sources
tags tags
TAGS TAGS
testexpr2

View File

@@ -1734,7 +1734,7 @@ to_string (struct val *vp)
return; return;
} }
sprintf (tmp, "%ld", vp->u.i); sprintf(tmp, "%ld", (long int) vp->u.i);
vp->type = AST_EXPR_string; vp->type = AST_EXPR_string;
vp->u.s = tmp; 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) { int main(int argc,char **argv) {
char *s; char s[4096];
s=ast_expr(argv[1]); if (ast_expr(argv[1], s, sizeof(s)))
printf("=====%s======\n",s);
printf("=====%s======\n",s); else
printf("No result\n");
} }
#endif #endif

View File

@@ -15,6 +15,7 @@
#include <limits.h> #include <limits.h>
#include <asterisk/ast_expr.h> #include <asterisk/ast_expr.h>
#include <asterisk/logger.h> #include <asterisk/logger.h>
#include <asterisk/strings.h>
enum valtype { enum valtype {
AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
@@ -41,6 +42,8 @@ struct parse_io
yyscan_t scanner; 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... ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
UGH! that would be inappropriate. */ UGH! that would be inappropriate. */
int ast_yyparse( void *); /* need to/should define this prototype for the call to yyparse */ 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_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; struct parse_io *io;
char *pirouni;
io = (struct parse_io *)calloc(sizeof(struct parse_io),1); io = calloc(sizeof(struct parse_io),1);
io->string = arg; /* to pass to the error routine */ io->string = expr; /* to pass to the error routine */
ast_yylex_init(&io->scanner); 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); ast_yylex_destroy(io->scanner);
if (io->val == NULL) {
if (io->val==NULL) { if (length > 1) {
pirouni=strdup("0"); strcpy(buf, "0");
return(pirouni); return 1;
}
} else { } else {
if (io->val->type == AST_EXPR_integer) { if (io->val->type == AST_EXPR_integer) {
pirouni = malloc(24); int res_length;
sprintf(pirouni, "%ld", io->val->u.i);
} res_length = snprintf(buf, length, "%ld", (long int) io->val->u.i);
else { return res_length <= length ? res_length : length;
pirouni=strdup(io->val->u.s); } 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->val);
} }
free(io); free(io);
return(pirouni); return 0;
} }
int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )

View File

@@ -349,7 +349,7 @@ to_string (struct val *vp)
return; return;
} }
sprintf (tmp, "%ld", vp->u.i); sprintf(tmp, "%ld", (long int) vp->u.i);
vp->type = AST_EXPR_string; vp->type = AST_EXPR_string;
vp->u.s = tmp; 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) { int main(int argc,char **argv) {
char *s; char s[4096];
s=ast_expr(argv[1]); if (ast_expr(argv[1], s, sizeof(s)))
printf("=====%s======\n",s);
printf("=====%s======\n",s); else
printf("No result\n");
} }
#endif #endif

View File

@@ -460,6 +460,7 @@ static yyconst flex_int16_t yy_chk[56] =
#include <limits.h> #include <limits.h>
#include <asterisk/ast_expr.h> #include <asterisk/ast_expr.h>
#include <asterisk/logger.h> #include <asterisk/logger.h>
#include <asterisk/strings.h>
enum valtype { enum valtype {
AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string
@@ -486,8 +487,10 @@ struct parse_io
yyscan_t scanner; 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 #define INITIAL 0
@@ -720,10 +723,10 @@ YY_DECL
register int yy_act; register int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; 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; yylval = yylval_param;
@@ -808,129 +811,129 @@ do_action: /* This label is used only to access EOF actions. */
case 1: case 1:
YY_RULE_SETUP YY_RULE_SETUP
#line 57 "ast_expr2.fl" #line 60 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_OR;} { SET_COLUMNS; SET_STRING; return TOK_OR;}
YY_BREAK YY_BREAK
case 2: case 2:
YY_RULE_SETUP YY_RULE_SETUP
#line 58 "ast_expr2.fl" #line 61 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_AND;} { SET_COLUMNS; SET_STRING; return TOK_AND;}
YY_BREAK YY_BREAK
case 3: case 3:
YY_RULE_SETUP YY_RULE_SETUP
#line 59 "ast_expr2.fl" #line 62 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_EQ;} { SET_COLUMNS; SET_STRING; return TOK_EQ;}
YY_BREAK YY_BREAK
case 4: case 4:
YY_RULE_SETUP YY_RULE_SETUP
#line 60 "ast_expr2.fl" #line 63 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_GT;} { SET_COLUMNS; SET_STRING; return TOK_GT;}
YY_BREAK YY_BREAK
case 5: case 5:
YY_RULE_SETUP YY_RULE_SETUP
#line 61 "ast_expr2.fl" #line 64 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_LT;} { SET_COLUMNS; SET_STRING; return TOK_LT;}
YY_BREAK YY_BREAK
case 6: case 6:
YY_RULE_SETUP YY_RULE_SETUP
#line 62 "ast_expr2.fl" #line 65 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_GE;} { SET_COLUMNS; SET_STRING; return TOK_GE;}
YY_BREAK YY_BREAK
case 7: case 7:
YY_RULE_SETUP YY_RULE_SETUP
#line 63 "ast_expr2.fl" #line 66 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_LE;} { SET_COLUMNS; SET_STRING; return TOK_LE;}
YY_BREAK YY_BREAK
case 8: case 8:
YY_RULE_SETUP YY_RULE_SETUP
#line 64 "ast_expr2.fl" #line 67 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_NE;} { SET_COLUMNS; SET_STRING; return TOK_NE;}
YY_BREAK YY_BREAK
case 9: case 9:
YY_RULE_SETUP YY_RULE_SETUP
#line 65 "ast_expr2.fl" #line 68 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_PLUS;} { SET_COLUMNS; SET_STRING; return TOK_PLUS;}
YY_BREAK YY_BREAK
case 10: case 10:
YY_RULE_SETUP YY_RULE_SETUP
#line 66 "ast_expr2.fl" #line 69 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_MINUS;} { SET_COLUMNS; SET_STRING; return TOK_MINUS;}
YY_BREAK YY_BREAK
case 11: case 11:
YY_RULE_SETUP YY_RULE_SETUP
#line 67 "ast_expr2.fl" #line 70 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_MULT;} { SET_COLUMNS; SET_STRING; return TOK_MULT;}
YY_BREAK YY_BREAK
case 12: case 12:
YY_RULE_SETUP YY_RULE_SETUP
#line 68 "ast_expr2.fl" #line 71 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_DIV;} { SET_COLUMNS; SET_STRING; return TOK_DIV;}
YY_BREAK YY_BREAK
case 13: case 13:
YY_RULE_SETUP YY_RULE_SETUP
#line 69 "ast_expr2.fl" #line 72 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_MOD;} { SET_COLUMNS; SET_STRING; return TOK_MOD;}
YY_BREAK YY_BREAK
case 14: case 14:
YY_RULE_SETUP YY_RULE_SETUP
#line 70 "ast_expr2.fl" #line 73 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_COND;} { SET_COLUMNS; SET_STRING; return TOK_COND;}
YY_BREAK YY_BREAK
case 15: case 15:
YY_RULE_SETUP YY_RULE_SETUP
#line 71 "ast_expr2.fl" #line 74 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_COLON;} { SET_COLUMNS; SET_STRING; return TOK_COLON;}
YY_BREAK YY_BREAK
case 16: case 16:
YY_RULE_SETUP YY_RULE_SETUP
#line 72 "ast_expr2.fl" #line 75 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;} { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
YY_BREAK YY_BREAK
case 17: case 17:
YY_RULE_SETUP YY_RULE_SETUP
#line 73 "ast_expr2.fl" #line 76 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_LP;} { SET_COLUMNS; SET_STRING; return TOK_LP;}
YY_BREAK YY_BREAK
case 18: case 18:
YY_RULE_SETUP YY_RULE_SETUP
#line 74 "ast_expr2.fl" #line 77 "ast_expr2.fl"
{ SET_COLUMNS; SET_STRING; return TOK_RP;} { SET_COLUMNS; SET_STRING; return TOK_RP;}
YY_BREAK YY_BREAK
case 19: case 19:
YY_RULE_SETUP YY_RULE_SETUP
#line 76 "ast_expr2.fl" #line 79 "ast_expr2.fl"
{} {}
YY_BREAK YY_BREAK
case 20: case 20:
/* rule 20 can match eol */ /* rule 20 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 77 "ast_expr2.fl" #line 80 "ast_expr2.fl"
{SET_COLUMNS; SET_STRING; return TOKEN;} {SET_COLUMNS; SET_STRING; return TOKEN;}
YY_BREAK YY_BREAK
case 21: case 21:
/* rule 21 can match eol */ /* rule 21 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 79 "ast_expr2.fl" #line 82 "ast_expr2.fl"
{/* what to do with eol */} {/* what to do with eol */}
YY_BREAK YY_BREAK
case 22: case 22:
YY_RULE_SETUP 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_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */
SET_NUMERIC_STRING; SET_NUMERIC_STRING;
return TOKEN;} return TOKEN;}
YY_BREAK YY_BREAK
case 23: case 23:
YY_RULE_SETUP YY_RULE_SETUP
#line 83 "ast_expr2.fl" #line 86 "ast_expr2.fl"
{SET_COLUMNS; SET_STRING; return TOKEN;} {SET_COLUMNS; SET_STRING; return TOKEN;}
YY_BREAK YY_BREAK
case 24: case 24:
YY_RULE_SETUP YY_RULE_SETUP
#line 85 "ast_expr2.fl" #line 88 "ast_expr2.fl"
ECHO; ECHO;
YY_BREAK YY_BREAK
#line 934 "ast_expr2f.c" #line 937 "ast_expr2f.c"
case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(INITIAL):
yyterminate(); yyterminate();
@@ -2068,7 +2071,7 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner)
#undef YY_DECL_IS_OURS #undef YY_DECL_IS_OURS
#undef YY_DECL #undef YY_DECL
#endif #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... ast_yy_scan_string in the .y file, because then, I'd have to define YY_BUFFER_STATE there...
UGH! that would be inappropriate. */ UGH! that would be inappropriate. */
int ast_yyparse( void *); /* need to/should define this prototype for the call to yyparse */ 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_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; struct parse_io *io;
char *pirouni;
io = (struct parse_io *)calloc(sizeof(struct parse_io),1); io = calloc(sizeof(struct parse_io),1);
io->string = arg; /* to pass to the error routine */ io->string = expr; /* to pass to the error routine */
ast_yylex_init(&io->scanner); 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); ast_yylex_destroy(io->scanner);
if (io->val == NULL) {
if (io->val==NULL) { if (length > 1) {
pirouni=strdup("0"); strcpy(buf, "0");
return(pirouni); return 1;
}
} else { } else {
if (io->val->type == AST_EXPR_integer) { if (io->val->type == AST_EXPR_integer) {
pirouni = malloc(24); int res_length;
sprintf(pirouni, "%ld", io->val->u.i);
} res_length = snprintf(buf, length, "%ld", (long int) io->val->u.i);
else { return res_length <= length ? res_length : length;
pirouni=strdup(io->val->u.s); } 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->val);
} }
free(io); free(io);
return(pirouni); return 0;
} }
int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio )

View File

@@ -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 */

13
pbx.c
View File

@@ -1522,19 +1522,12 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, const ch
vars = var; vars = var;
} }
/* Evaluate expression */ length = ast_expr(vars, cp2, count);
cp4 = ast_expr(vars);
ast_log(LOG_DEBUG, "Expression is '%s'\n", cp4); if (length) {
ast_log(LOG_DEBUG, "Expression result is '%s'\n", cp2);
if (cp4) {
length = strlen(cp4);
if (length > count)
length = count;
memcpy(cp2, cp4, length);
count -= length; count -= length;
cp2 += length; cp2 += length;
free(cp4);
} }
} else } else
break; break;

View File

@@ -40,6 +40,7 @@ install:
clean: clean:
rm -f *.o astman smsq stereorize check_expr .depend rm -f *.o astman smsq stereorize check_expr .depend
rm -f ast_expr2.o ast_expr2f.o
astman: astman.o ../md5.o astman: astman.o ../md5.o
$(CC) $(CFLAGS) -o astman astman.o ../md5.o -lnewt $(CC) $(CFLAGS) -o astman astman.o ../md5.o -lnewt
@@ -47,8 +48,14 @@ astman: astman.o ../md5.o
stereorize: stereorize.o frame.o stereorize: stereorize.o frame.o
$(CC) $(CFLAGS) -o stereorize stereorize.o frame.o -lm $(CC) $(CFLAGS) -o stereorize stereorize.o frame.o -lm
check_expr : check_expr.c ../ast_expr.a ast_expr2.o: ../ast_expr2.c
$(CC) $(CFLAGS) -o check_expr check_expr.c ../ast_expr.a 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 smsq: smsq.o
$(CC) $(CFLAGS) -o smsq ${SOL} smsq.o -lpopt $(CC) $(CFLAGS) -o smsq ${SOL} smsq.o -lpopt

View File

@@ -3,6 +3,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <../include/asterisk/ast_expr.h>
int global_lineno = 1; int global_lineno = 1;
int global_expr_count = 0; 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) int check_eval(char *buffer, char *error_report)
{ {
char *cp, *ep, *xp, *s; char *cp, *ep, *xp;
char s[4096];
char evalbuf[80000]; char evalbuf[80000];
extern char *ast_expr(char *);
int oplen = 0; int oplen = 0;
int warn_found = 0; int warn_found = 0;
int result;
error_report[0] = 0; error_report[0] = 0;
ep = evalbuf; ep = evalbuf;
@@ -179,12 +181,11 @@ int check_eval(char *buffer, char *error_report)
*ep++ = 0; *ep++ = 0;
/* now, run the test */ /* now, run the test */
s = ast_expr(evalbuf); result = ast_expr(evalbuf, s, sizeof(s));
if (s) { if (result) {
sprintf(error_report,"line %d, evaluation of $[ %s ] result: %s\n", global_lineno, evalbuf, s); sprintf(error_report,"line %d, evaluation of $[ %s ] result: %s\n", global_lineno, evalbuf, s);
return 1; return 1;
} } else {
else {
sprintf(error_report,"line %d, evaluation of $[ %s ] result: ****SYNTAX ERROR****\n", global_lineno, evalbuf); sprintf(error_report,"line %d, evaluation of $[ %s ] result: ****SYNTAX ERROR****\n", global_lineno, evalbuf);
return 1; return 1;
} }