mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +00:00 
			
		
		
		
	git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6936 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			183 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
		
			Executable File
		
	
	
	
	
%{
 | 
						|
#include <sys/types.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <locale.h>
 | 
						|
#include <ctype.h>
 | 
						|
#if !defined(SOLARIS) && !defined(__CYGWIN__)
 | 
						|
#include <err.h>
 | 
						|
#else
 | 
						|
#define quad_t int64_t
 | 
						|
#endif
 | 
						|
#include <errno.h>
 | 
						|
#include <regex.h>
 | 
						|
#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
 | 
						|
} ;
 | 
						|
 | 
						|
struct val {
 | 
						|
	enum valtype type;
 | 
						|
	union {
 | 
						|
		char *s;
 | 
						|
		quad_t i;
 | 
						|
	} u;
 | 
						|
} ;
 | 
						|
 | 
						|
#include "ast_expr2.h" /* the o/p of the bison on ast_expr2.y */
 | 
						|
 | 
						|
#define SET_COLUMNS yylloc_param->first_column = (int)(yyg->yytext_r - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);yylloc_param->last_column = yylloc_param->last_column + yyleng - 1; yylloc_param->first_line = yylloc_param->last_line = 1
 | 
						|
#define SET_STRING yylval_param->val = (struct val *)calloc(sizeof(struct val),1); yylval_param->val->type = AST_EXPR_string; yylval_param->val->u.s = strdup(yytext);
 | 
						|
#define SET_NUMERIC_STRING yylval_param->val = (struct val *)calloc(sizeof(struct val),1); yylval_param->val->type = AST_EXPR_numeric_string; yylval_param->val->u.s = strdup(yytext);
 | 
						|
 | 
						|
struct parse_io
 | 
						|
{
 | 
						|
	char *string;
 | 
						|
	struct val *val;
 | 
						|
	yyscan_t scanner;
 | 
						|
};
 | 
						|
 
 | 
						|
void ast_yyset_column(int column_no, yyscan_t yyscanner);
 | 
						|
int ast_yyget_column(yyscan_t yyscanner);
 | 
						|
 | 
						|
%}
 | 
						|
 | 
						|
%option prefix="ast_yy"
 | 
						|
%option batch
 | 
						|
%option outfile="ast_expr2f.c"
 | 
						|
%option reentrant
 | 
						|
%option bison-bridge
 | 
						|
%option bison-locations
 | 
						|
%option noyywrap
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
\|	{ SET_COLUMNS; SET_STRING; return TOK_OR;}
 | 
						|
\&	{ SET_COLUMNS; SET_STRING; return TOK_AND;}
 | 
						|
\=	{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
 | 
						|
\>	{ SET_COLUMNS; SET_STRING; return TOK_GT;}
 | 
						|
\<	{ SET_COLUMNS; SET_STRING; return TOK_LT;}
 | 
						|
\>\=	{ SET_COLUMNS; SET_STRING; return TOK_GE;}
 | 
						|
\<\=	{ SET_COLUMNS; SET_STRING; return TOK_LE;}
 | 
						|
\!\=	{ SET_COLUMNS; SET_STRING; return TOK_NE;}
 | 
						|
\+	{ SET_COLUMNS; SET_STRING; return TOK_PLUS;}
 | 
						|
\-	{ SET_COLUMNS; SET_STRING; return TOK_MINUS;}
 | 
						|
\*	{ SET_COLUMNS; SET_STRING; return TOK_MULT;}
 | 
						|
\/	{ SET_COLUMNS; SET_STRING; return TOK_DIV;}
 | 
						|
\%	{ SET_COLUMNS; SET_STRING; return TOK_MOD;}
 | 
						|
\?	{ SET_COLUMNS; SET_STRING; return TOK_COND;}
 | 
						|
\:	{ SET_COLUMNS; SET_STRING; return TOK_COLON;}
 | 
						|
\:\:	{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;}
 | 
						|
\(	{ SET_COLUMNS; SET_STRING; return TOK_LP;}
 | 
						|
\)	{ SET_COLUMNS; SET_STRING; return TOK_RP;}
 | 
						|
 | 
						|
[ 	\r]		{}
 | 
						|
\"[^"]*\"   {SET_COLUMNS; SET_STRING; return TOKEN;}
 | 
						|
 | 
						|
[\n]	{/* what to do with eol */}
 | 
						|
[0-9]+		{   SET_COLUMNS;  /* the original behavior of the expression parser was to bring in numbers as a numeric string */
 | 
						|
				SET_NUMERIC_STRING;
 | 
						|
				return TOKEN;}
 | 
						|
[a-zA-Z0-9,.';{}\\_^%$#@!]+	{SET_COLUMNS; SET_STRING; return TOKEN;}
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
/* I'm putting the interface routine to the whole parse here in the flexer input file
 | 
						|
   mainly because of all the flexer initialization that has to be done. Shouldn't matter
 | 
						|
   where it is, as long as it's somewhere. I didn't want to define a prototype for the
 | 
						|
   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 */
 | 
						|
int ast_yyerror(const char *, YYLTYPE *, struct parse_io *); /* likewise */
 | 
						|
 | 
						|
int ast_expr(char *expr, char *buf, int length)
 | 
						|
{
 | 
						|
	struct parse_io *io;
 | 
						|
	
 | 
						|
	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(expr, io->scanner);
 | 
						|
	
 | 
						|
	ast_yyparse ((void *) io);
 | 
						|
 | 
						|
	ast_yylex_destroy(io->scanner);
 | 
						|
 | 
						|
	if (io->val == NULL) {
 | 
						|
		if (length > 1) {
 | 
						|
			strcpy(buf, "0");
 | 
						|
			return 1;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (io->val->type == AST_EXPR_integer) {
 | 
						|
			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 0;
 | 
						|
}
 | 
						|
 | 
						|
int ast_yyerror (const char *s,  yyltype *loc, struct parse_io *parseio )
 | 
						|
{	
 | 
						|
	struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner);
 | 
						|
	char spacebuf[8000]; /* best safe than sorry */
 | 
						|
	char spacebuf2[8000]; /* best safe than sorry */
 | 
						|
	int i=0;
 | 
						|
	spacebuf[0] = 0;
 | 
						|
	
 | 
						|
#ifdef WHEN_LOC_MEANS_SOMETHING
 | 
						|
	if( loc->first_column > 7990 ) /* if things get out of whack, why crash? */
 | 
						|
		loc->first_column = 7990;
 | 
						|
	if( loc->last_column > 7990 )
 | 
						|
		loc->last_column = 7990;
 | 
						|
	for(i=0;i<loc->first_column;i++) spacebuf[i] = ' ';
 | 
						|
	for(   ;i<loc->last_column;i++) spacebuf[i] = '^';
 | 
						|
	spacebuf[i] = 0;
 | 
						|
#endif
 | 
						|
	for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' ';  /* uh... assuming yyg is defined, then I can use the yycolumn macro,
 | 
						|
													which is the same thing as... get this:
 | 
						|
													yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column
 | 
						|
													I was tempted to just use yy_buf_pos in the STATE, but..., well:
 | 
						|
														a. the yy_buf_pos is the current position in the buffer, which
 | 
						|
															may not relate to the entire string/buffer because of the
 | 
						|
															buffering.
 | 
						|
														b. but, analysis of the situation is that when you use the
 | 
						|
															yy_scan_string func, it creates a single buffer the size of
 | 
						|
															string, so the two would be the same... 
 | 
						|
													so, in the end, the yycolumn macro is available, shorter, therefore easier. */
 | 
						|
	spacebuf2[i++]='^';
 | 
						|
	spacebuf2[i]= 0;
 | 
						|
 | 
						|
#ifdef STANDALONE3
 | 
						|
	/* easier to read in the standalone version */
 | 
						|
	printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",  
 | 
						|
			s, parseio->string,spacebuf2);
 | 
						|
#else
 | 
						|
	ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n",  
 | 
						|
			s, parseio->string,spacebuf2);
 | 
						|
#endif
 | 
						|
#ifndef STANDALONE
 | 
						|
	ast_log(LOG_WARNING,"If you have questions, please refer to doc/README.variables in the asterisk source.\n");
 | 
						|
#endif
 | 
						|
	return(0);
 | 
						|
}
 |