123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- /*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2006, Digium, Inc.
- *
- * Steve Murphy <murf@parsetree.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
- /*! \file
- *
- * \brief Flex scanner description of tokens used in AEL2 .
- *
- */
- /*
- * Start with flex options:
- *
- * %x describes the contexts we have: paren, semic and argg, plus INITIAL
- */
- %x paren semic argg comment curlystate wordstate brackstate
- /* prefix used for various globally-visible functions and variables.
- * This renames also yywrap, but since we do not use it, we just
- * add option noyywrap to remove it.
- */
- %option prefix="ael_yy"
- %option noyywrap 8bit
- /* I specify this option to suppress flex generating code with ECHO
- in it. This generates compiler warnings in some systems; We've
- seen the fwrite generate Unused variable warnings with 4.1.2 gcc.
- Some systems have tweaked flex ECHO macro to keep the compiler
- happy. To keep the warning message from getting output, I added
- a default rule at the end of the patterns section */
- %option nodefault
- /* yyfree normally just frees its arg. It can be null sometimes,
- which some systems will complain about, so, we'll define our own version */
- %option noyyfree
- /* batch gives a bit more performance if we are using it in
- * a non-interactive mode. We probably don't care much.
- */
- %option batch
- /* outfile is the filename to be used instead of lex.yy.c */
- %option outfile="ael_lex.c"
- /*
- * These are not supported in flex 2.5.4, but we need them
- * at the moment:
- * reentrant produces a thread-safe parser. Not 100% sure that
- * we require it, though.
- * bison-bridge passes an additional yylval argument to yylex().
- * bison-locations is probably not needed.
- */
- %option reentrant
- %option bison-bridge
- %option bison-locations
- %{
- #include "asterisk.h"
- ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <glob.h>
- #if !defined(GLOB_ABORTED)
- #define GLOB_ABORTED GLOB_ABEND
- #endif
- #include "asterisk/logger.h"
- #include "asterisk/utils.h"
- #include "asterisk/lock.h"
- #include "asterisk/hashtab.h"
- #include "ael/ael.tab.h"
- #include "asterisk/ael_structs.h"
- /*
- * A stack to keep track of matching brackets ( [ { } ] )
- */
- static char pbcstack[400]; /* XXX missing size checks */
- static int pbcpos = 0;
- static void pbcpush(char x);
- static int pbcpop(char x);
- static int parencount = 0;
- /*
- * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by ${ ... }
- */
- static char pbcstack2[400]; /* XXX missing size checks */
- static int pbcpos2 = 0;
- static void pbcpush2(char x);
- static int pbcpop2(char x);
- static int parencount2 = 0;
- /*
- * A similar stack to keep track of matching brackets ( [ { } ] ) in word tokens surrounded by $[ ... ]
- */
- static char pbcstack3[400]; /* XXX missing size checks */
- static int pbcpos3 = 0;
- static void pbcpush3(char x);
- static int pbcpop3(char x);
- static int parencount3 = 0;
- /*
- * current line, column and filename, updated as we read the input.
- */
- static int my_lineno = 1; /* current line in the source */
- static int my_col = 1; /* current column in the source */
- char *my_file = 0; /* used also in the bison code */
- char *prev_word; /* XXX document it */
- #define MAX_INCLUDE_DEPTH 50
- /*
- * flex is not too smart, and generates global functions
- * without prototypes so the compiler may complain.
- * To avoid that, we declare the prototypes here,
- * even though these functions are not used.
- */
- int ael_yyget_column (yyscan_t yyscanner);
- void ael_yyset_column (int column_no , yyscan_t yyscanner);
- int ael_yyparse (struct parse_io *);
- /*
- * A stack to process include files.
- * As we switch into the new file we need to store the previous
- * state to restore it later.
- */
- struct stackelement {
- char *fname;
- int lineno;
- int colno;
- glob_t globbuf; /* the current globbuf */
- int globbuf_pos; /* where we are in the current globbuf */
- YY_BUFFER_STATE bufstate;
- };
- static struct stackelement include_stack[MAX_INCLUDE_DEPTH];
- static int include_stack_index = 0;
- static void setup_filestack(char *fnamebuf, int fnamebuf_siz, glob_t *globbuf, int globpos, yyscan_t xscan, int create);
- /*
- * if we use the @n feature of bison, we must supply the start/end
- * location of tokens in the structure pointed by yylloc.
- * Simple tokens are just assumed to be on the same line, so
- * the line number is constant, and the column is incremented
- * by the length of the token.
- */
- #ifdef FLEX_BETA /* set for 2.5.33 */
- /* compute the total number of lines and columns in the text
- * passed as argument.
- */
- static void pbcwhere(const char *text, int *line, int *col )
- {
- int loc_line = *line;
- int loc_col = *col;
- char c;
- while ( (c = *text++) ) {
- if ( c == '\t' ) {
- loc_col += 8 - (loc_col % 8);
- } else if ( c == '\n' ) {
- loc_line++;
- loc_col = 1;
- } else
- loc_col++;
- }
- *line = loc_line;
- *col = loc_col;
- }
- #define STORE_POS do { \
- yylloc->first_line = yylloc->last_line = my_lineno; \
- yylloc->first_column=my_col; \
- yylloc->last_column=my_col+yyleng-1; \
- my_col+=yyleng; \
- } while (0)
- #define STORE_LOC do { \
- yylloc->first_line = my_lineno; \
- yylloc->first_column=my_col; \
- pbcwhere(yytext, &my_lineno, &my_col); \
- yylloc->last_line = my_lineno; \
- yylloc->last_column = my_col - 1; \
- } while (0)
- #else
- #define STORE_POS
- #define STORE_LOC
- #endif
- %}
- KEYWORD (context|abstract|extend|macro|globals|local|ignorepat|switch|if|ifTime|random|regexten|hint|else|goto|jump|return|break|continue|for|while|case|default|pattern|catch|switches|eswitches|includes)
- NOPARENS ([^()\[\]\{\}]|\\[()\[\]\{\}])*
- NOARGG ([^(),\{\}\[\]]|\\[,()\[\]\{\}])*
- NOSEMIC ([^;()\{\}\[\]]|\\[;()\[\]\{\}])*
- HIBIT [\x80-\xff]
- %%
- \{ { STORE_POS; return LC;}
- \} { STORE_POS; return RC;}
- \( { STORE_POS; return LP;}
- \) { STORE_POS; return RP;}
- \; { STORE_POS; return SEMI;}
- \= { STORE_POS; return EQ;}
- \, { STORE_POS; return COMMA;}
- \: { STORE_POS; return COLON;}
- \& { STORE_POS; return AMPER;}
- \| { STORE_POS; return BAR;}
- \=\> { STORE_POS; return EXTENMARK;}
- \@ { STORE_POS; return AT;}
- \/\/[^\n]* {/*comment*/}
- context { STORE_POS; return KW_CONTEXT;}
- abstract { STORE_POS; return KW_ABSTRACT;}
- extend { STORE_POS; return KW_EXTEND;}
- macro { STORE_POS; return KW_MACRO;};
- globals { STORE_POS; return KW_GLOBALS;}
- local { STORE_POS; return KW_LOCAL;}
- ignorepat { STORE_POS; return KW_IGNOREPAT;}
- switch { STORE_POS; return KW_SWITCH;}
- if { STORE_POS; return KW_IF;}
- ifTime { STORE_POS; return KW_IFTIME;}
- random { STORE_POS; return KW_RANDOM;}
- regexten { STORE_POS; return KW_REGEXTEN;}
- hint { STORE_POS; return KW_HINT;}
- else { STORE_POS; return KW_ELSE;}
- goto { STORE_POS; return KW_GOTO;}
- jump { STORE_POS; return KW_JUMP;}
- return { STORE_POS; return KW_RETURN;}
- break { STORE_POS; return KW_BREAK;}
- continue { STORE_POS; return KW_CONTINUE;}
- for { STORE_POS; return KW_FOR;}
- while { STORE_POS; return KW_WHILE;}
- case { STORE_POS; return KW_CASE;}
- default { STORE_POS; return KW_DEFAULT;}
- pattern { STORE_POS; return KW_PATTERN;}
- catch { STORE_POS; return KW_CATCH;}
- switches { STORE_POS; return KW_SWITCHES;}
- eswitches { STORE_POS; return KW_ESWITCHES;}
- includes { STORE_POS; return KW_INCLUDES;}
- "/*" { BEGIN(comment); my_col += 2; }
- <comment>[^*\n]* { my_col += yyleng; }
- <comment>[^*\n]*\n { ++my_lineno; my_col=1;}
- <comment>"*"+[^*/\n]* { my_col += yyleng; }
- <comment>"*"+[^*/\n]*\n { ++my_lineno; my_col=1;}
- <comment>"*/" { my_col += 2; BEGIN(INITIAL); } /* the nice thing about comments is that you know exactly what ends them */
- \n { my_lineno++; my_col = 1; }
- [ ]+ { my_col += yyleng; }
- [\t]+ { my_col += (yyleng*8)-(my_col%8); }
- ({KEYWORD}?[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]]|{HIBIT}|(\\.)|(\$\{)|(\$\[)) {
- /* boy did I open a can of worms when I changed the lexical token "word".
- all the above keywords can be used as a beginning to a "word".-
- before, a "word" would match a longer sequence than the above
- keywords, and all would be well. But now "word" is a single char
- and feeds into a statemachine sort of sequence from there on. So...
- I added the {KEYWORD}? to the beginning of the word match sequence */
- if (!strcmp(yytext,"${")) {
- parencount2 = 0;
- pbcpos2 = 0;
- pbcpush2('{'); /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
- BEGIN(curlystate);
- yymore();
- } else if (!strcmp(yytext,"$[")) {
- parencount3 = 0;
- pbcpos3 = 0;
- pbcpush3('['); /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
- BEGIN(brackstate);
- yymore();
- } else {
- BEGIN(wordstate);
- yymore();
- }
- }
- <wordstate>[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]] { yymore(); /* Keep going */ }
- <wordstate>{HIBIT} { yymore(); /* Keep going */ }
- <wordstate>(\\.) { yymore(); /* Keep Going */ }
- <wordstate>(\$\{) { /* the beginning of a ${} construct. prepare and pop into curlystate */
- parencount2 = 0;
- pbcpos2 = 0;
- pbcpush2('{'); /* push '{' so the last pcbpop (parencount2 = -1) will succeed */
- BEGIN(curlystate);
- yymore();
- }
- <wordstate>(\$\[) { /* the beginning of a $[] construct. prepare and pop into brackstate */
- parencount3 = 0;
- pbcpos3 = 0;
- pbcpush3('['); /* push '[' so the last pcbpop (parencount3 = -1) will succeed */
- BEGIN(brackstate);
- yymore();
- }
- <wordstate>([^a-zA-Z0-9\x80-\xff\x2d'"_/.\<\>\*\+!$#\[\]]) {
- /* a non-word constituent char, like a space, tab, curly, paren, etc */
- char c = yytext[yyleng-1];
- STORE_POS;
- yylval->str = malloc(yyleng);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng-1] = 0;
- unput(c); /* put this ending char back in the stream */
- BEGIN(0);
- return word;
- }
- <curlystate>{NOPARENS}\} {
- if ( pbcpop2('}') ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- parencount2--;
- if ( parencount2 >= 0) {
- yymore();
- } else {
- BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
- yymore();
- }
- }
- <curlystate>{NOPARENS}[\(\[\{] {
- char c = yytext[yyleng-1];
- if (c == '{')
- parencount2++;
- pbcpush2(c);
- yymore();
- }
- <curlystate>{NOPARENS}[\]\)] {
- char c = yytext[yyleng-1];
- if ( pbcpop2(c)) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
- my_file, my_lineno, my_col, c);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- yymore();
- }
- <brackstate>{NOPARENS}\] {
- if ( pbcpop3(']') ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- parencount3--;
- if ( parencount3 >= 0) {
- yymore();
- } else {
- BEGIN(wordstate); /* Finished with the current ${} construct. Return to word gathering state */
- yymore();
- }
- }
- <brackstate>{NOPARENS}[\(\[\{] {
- char c = yytext[yyleng-1];
- if (c == '[')
- parencount3++;
- pbcpush3(c);
- yymore();
- }
- <brackstate>{NOPARENS}[\}\)] {
- char c = yytext[yyleng-1];
- if ( pbcpop3(c)) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
- my_file, my_lineno, my_col, c);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- yymore();
- }
- /*
- * context used for arguments of if_head, random_head, switch_head,
- * for (last statement), while (XXX why not iftime_head ?).
- * End with the matching parentheses.
- * A comma at the top level is valid here, unlike in argg where it
- * is an argument separator so it must be returned as a token.
- */
- <paren>{NOPARENS}\) {
- if ( pbcpop(')') ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno, my_col, yytext);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- prev_word = 0;
- return word;
- }
- parencount--;
- if ( parencount >= 0) {
- yymore();
- } else {
- STORE_LOC;
- yylval->str = malloc(yyleng);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng-1] = 0;
- unput(')');
- BEGIN(0);
- return word;
- }
- }
- <paren>{NOPARENS}[\(\[\{] {
- char c = yytext[yyleng-1];
- if (c == '(')
- parencount++;
- pbcpush(c);
- yymore();
- }
- <paren>{NOPARENS}[\]\}] {
- char c = yytext[yyleng-1];
- if ( pbcpop(c)) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n",
- my_file, my_lineno, my_col, c);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- yymore();
- }
- /*
- * handlers for arguments to a macro or application calls.
- * We enter this context when we find the initial '(' and
- * stay here until we close all matching parentheses,
- * and find the comma (argument separator) or the closing ')'
- * of the (external) call, which happens when parencount == 0
- * before the decrement.
- */
- <argg>{NOARGG}[\(\[\{] {
- char c = yytext[yyleng-1];
- if (c == '(')
- parencount++;
- pbcpush(c);
- yymore();
- }
- <argg>{NOARGG}\) {
- if ( pbcpop(')') ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno, my_col);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = 0;
- return word;
- }
- parencount--;
- if( parencount >= 0){
- yymore();
- } else {
- STORE_LOC;
- BEGIN(0);
- if ( !strcmp(yytext, ")") )
- return RP;
- yylval->str = malloc(yyleng);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng-1] = '\0'; /* trim trailing ')' */
- unput(')');
- return word;
- }
- }
- <argg>{NOARGG}\, {
- if( parencount != 0) { /* ast_log(LOG_NOTICE,"Folding in a comma!\n"); */
- yymore();
- } else {
- STORE_LOC;
- if( !strcmp(yytext,"," ) )
- return COMMA;
- yylval->str = malloc(yyleng);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng-1] = '\0'; /* trim trailing ',' */
- unput(',');
- return word;
- }
- }
- <argg>{NOARGG}[\]\}] {
- char c = yytext[yyleng-1];
- if ( pbcpop(c) ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n", my_file, my_lineno, my_col, c);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = '\0';
- return word;
- }
- yymore();
- }
- /*
- * context used to find tokens in the right hand side of assignments,
- * or in the first and second operand of a 'for'. As above, match
- * commas and use ';' as a separator (hence return it as a separate token).
- */
- <semic>{NOSEMIC}[\(\[\{] {
- char c = yytext[yyleng-1];
- yymore();
- pbcpush(c);
- }
- <semic>{NOSEMIC}[\)\]\}] {
- char c = yytext[yyleng-1];
- if ( pbcpop(c) ) { /* error */
- STORE_LOC;
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '%c' in expression!\n", my_file, my_lineno, my_col, c);
- BEGIN(0);
- yylval->str = malloc(yyleng+1);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng] = '\0';
- return word;
- }
- yymore();
- }
- <semic>{NOSEMIC}; {
- STORE_LOC;
- yylval->str = malloc(yyleng);
- strncpy(yylval->str, yytext, yyleng);
- yylval->str[yyleng-1] = '\0'; /* trim trailing ';' */
- unput(';');
- BEGIN(0);
- return word;
- }
- \#include[ \t]+\"[^\"]+\" {
- char fnamebuf[1024],*p1,*p2;
- int glob_ret;
- glob_t globbuf; /* the current globbuf */
- int globbuf_pos = -1; /* where we are in the current globbuf */
- globbuf.gl_offs = 0; /* initialize it to silence gcc */
- p1 = strchr(yytext,'"');
- p2 = strrchr(yytext,'"');
- if ( include_stack_index >= MAX_INCLUDE_DEPTH ) {
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Includes nested too deeply! Wow!!! How did you do that?\n", my_file, my_lineno, my_col);
- } else if ( (int)(p2-p1) > sizeof(fnamebuf) - 1 ) {
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Filename is incredibly way too long (%d chars!). Inclusion ignored!\n", my_file, my_lineno, my_col, yyleng - 10);
- } else {
- strncpy(fnamebuf, p1+1, p2-p1-1);
- fnamebuf[p2-p1-1] = 0;
- if (fnamebuf[0] != '/') {
- char fnamebuf2[1024];
- snprintf(fnamebuf2,sizeof(fnamebuf2), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, fnamebuf);
- ast_copy_string(fnamebuf,fnamebuf2,sizeof(fnamebuf));
- }
- #ifdef SOLARIS
- glob_ret = glob(fnamebuf, GLOB_NOCHECK, NULL, &globbuf);
- #else
- glob_ret = glob(fnamebuf, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
- #endif
- if (glob_ret == GLOB_NOSPACE) {
- ast_log(LOG_WARNING,
- "Glob Expansion of pattern '%s' failed: Not enough memory\n", fnamebuf);
- } else if (glob_ret == GLOB_ABORTED) {
- ast_log(LOG_WARNING,
- "Glob Expansion of pattern '%s' failed: Read error\n", fnamebuf);
- } else if (glob_ret == GLOB_NOMATCH) {
- ast_log(LOG_WARNING,
- "Glob Expansion of pattern '%s' failed: No matches!\n", fnamebuf);
- } else {
- globbuf_pos = 0;
- }
- }
- if (globbuf_pos > -1) {
- setup_filestack(fnamebuf, sizeof(fnamebuf), &globbuf, 0, yyscanner, 1);
- }
- }
- <<EOF>> {
- char fnamebuf[2048];
- if (include_stack_index > 0 && include_stack[include_stack_index-1].globbuf_pos < include_stack[include_stack_index-1].globbuf.gl_pathc-1) {
- yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
- include_stack[include_stack_index-1].globbuf_pos++;
- setup_filestack(fnamebuf, sizeof(fnamebuf), &include_stack[include_stack_index-1].globbuf, include_stack[include_stack_index-1].globbuf_pos, yyscanner, 0);
- /* finish this */
- } else {
- if (include_stack[include_stack_index].fname) {
- free(include_stack[include_stack_index].fname);
- include_stack[include_stack_index].fname = 0;
- }
- if (my_file) {
- free(my_file);
- my_file = 0;
- }
- if ( --include_stack_index < 0 ) {
- yyterminate();
- } else {
- globfree(&include_stack[include_stack_index].globbuf);
- include_stack[include_stack_index].globbuf_pos = -1;
- yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
- yy_switch_to_buffer(include_stack[include_stack_index].bufstate, yyscanner );
- my_lineno = include_stack[include_stack_index].lineno;
- my_col = include_stack[include_stack_index].colno;
- my_file = strdup(include_stack[include_stack_index].fname);
- }
- }
- }
- <*>.|\n { /* default rule */ ast_log(LOG_ERROR,"Unhandled char(s): %s\n", yytext); }
- %%
- static void pbcpush(char x)
- {
- pbcstack[pbcpos++] = x;
- }
- void ael_yyfree(void *ptr, yyscan_t yyscanner)
- {
- if (ptr)
- free( (char*) ptr );
- }
- static int pbcpop(char x)
- {
- if ( ( x == ')' && pbcstack[pbcpos-1] == '(' )
- || ( x == ']' && pbcstack[pbcpos-1] == '[' )
- || ( x == '}' && pbcstack[pbcpos-1] == '{' )) {
- pbcpos--;
- return 0;
- }
- return 1; /* error */
- }
- static void pbcpush2(char x)
- {
- pbcstack2[pbcpos2++] = x;
- }
- static int pbcpop2(char x)
- {
- if ( ( x == ')' && pbcstack2[pbcpos2-1] == '(' )
- || ( x == ']' && pbcstack2[pbcpos2-1] == '[' )
- || ( x == '}' && pbcstack2[pbcpos2-1] == '{' )) {
- pbcpos2--;
- return 0;
- }
- return 1; /* error */
- }
- static void pbcpush3(char x)
- {
- pbcstack3[pbcpos3++] = x;
- }
- static int pbcpop3(char x)
- {
- if ( ( x == ')' && pbcstack3[pbcpos3-1] == '(' )
- || ( x == ']' && pbcstack3[pbcpos3-1] == '[' )
- || ( x == '}' && pbcstack3[pbcpos3-1] == '{' )) {
- pbcpos3--;
- return 0;
- }
- return 1; /* error */
- }
- static int c_prevword(void)
- {
- char *c = prev_word;
- if (c == NULL)
- return 0;
- while ( *c ) {
- switch (*c) {
- case '{':
- case '[':
- case '(':
- pbcpush(*c);
- break;
- case '}':
- case ']':
- case ')':
- if (pbcpop(*c))
- return 1;
- break;
- }
- c++;
- }
- return 0;
- }
- /*
- * The following three functions, reset_*, are used in the bison
- * code to switch context. As a consequence, we need to
- * declare them global and add a prototype so that the
- * compiler does not complain.
- *
- * NOTE: yyg is declared because it is used in the BEGIN macros,
- * though that should be hidden as the macro changes
- * depending on the flex options that we use - in particular,
- * %reentrant changes the way the macro is declared;
- * without %reentrant, BEGIN uses yystart instead of yyg
- */
- void reset_parencount(yyscan_t yyscanner );
- void reset_parencount(yyscan_t yyscanner )
- {
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- parencount = 0;
- pbcpos = 0;
- pbcpush('('); /* push '(' so the last pcbpop (parencount= -1) will succeed */
- c_prevword();
- BEGIN(paren);
- }
- void reset_semicount(yyscan_t yyscanner );
- void reset_semicount(yyscan_t yyscanner )
- {
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- pbcpos = 0;
- BEGIN(semic);
- }
- void reset_argcount(yyscan_t yyscanner );
- void reset_argcount(yyscan_t yyscanner )
- {
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- parencount = 0;
- pbcpos = 0;
- pbcpush('('); /* push '(' so the last pcbpop (parencount= -1) will succeed */
- c_prevword();
- BEGIN(argg);
- }
- /* used elsewhere, but some local vars */
- struct pval *ael2_parse(char *filename, int *errors)
- {
- struct pval *pvalue;
- struct parse_io *io;
- char *buffer;
- struct stat stats;
- FILE *fin;
- /* extern int ael_yydebug; */
- io = calloc(sizeof(struct parse_io),1);
- /* reset the global counters */
- prev_word = 0;
- my_lineno = 1;
- include_stack_index=0;
- my_col = 0;
- /* ael_yydebug = 1; */
- ael_yylex_init(&io->scanner);
- fin = fopen(filename,"r");
- if ( !fin ) {
- ast_log(LOG_ERROR,"File %s could not be opened\n", filename);
- *errors = 1;
- return 0;
- }
- if (my_file)
- free(my_file);
- my_file = strdup(filename);
- if (stat(filename, &stats)) {
- ast_log(LOG_WARNING, "failed to populate stats from file '%s'\n", filename);
- }
- buffer = (char*)malloc(stats.st_size+2);
- if (fread(buffer, 1, stats.st_size, fin) != stats.st_size) {
- ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
- buffer[stats.st_size]=0;
- fclose(fin);
- ael_yy_scan_string (buffer ,io->scanner);
- ael_yyset_lineno(1 , io->scanner);
- /* ael_yyset_in (fin , io->scanner); OLD WAY */
- ael_yyparse(io);
- pvalue = io->pval;
- *errors = io->syntax_error_count;
- ael_yylex_destroy(io->scanner);
- free(buffer);
- free(io);
- return pvalue;
- }
- static void setup_filestack(char *fnamebuf2, int fnamebuf_siz, glob_t *globbuf, int globpos, yyscan_t yyscanner, int create)
- {
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- int error, i;
- FILE *in1;
- char fnamebuf[2048];
- if (globbuf && globbuf->gl_pathv && globbuf->gl_pathc > 0)
- #if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL)
- strncpy(fnamebuf, globbuf->gl_pathv[globpos], fnamebuf_siz);
- #else
- ast_copy_string(fnamebuf, globbuf->gl_pathv[globpos], fnamebuf_siz);
- #endif
- else {
- ast_log(LOG_ERROR,"Include file name not present!\n");
- return;
- }
- for (i=0; i<include_stack_index; i++) {
- if ( !strcmp(fnamebuf,include_stack[i].fname )) {
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Nice Try!!! But %s has already been included (perhaps by another file), and would cause an infinite loop of file inclusions!!! Include directive ignored\n",
- my_file, my_lineno, my_col, fnamebuf);
- break;
- }
- }
- error = 1;
- if (i == include_stack_index)
- error = 0; /* we can use this file */
- if ( !error ) { /* valid file name */
- /* relative vs. absolute */
- if (fnamebuf[0] != '/')
- snprintf(fnamebuf2, fnamebuf_siz, "%s/%s", ast_config_AST_CONFIG_DIR, fnamebuf);
- else
- #if defined(STANDALONE) || defined(LOW_MEMORY) || defined(STANDALONE_AEL)
- strncpy(fnamebuf2, fnamebuf, fnamebuf_siz);
- #else
- ast_copy_string(fnamebuf2, fnamebuf, fnamebuf_siz);
- #endif
- in1 = fopen( fnamebuf2, "r" );
- if ( ! in1 ) {
- ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Couldn't find the include file: %s; ignoring the Include directive!\n", my_file, my_lineno, my_col, fnamebuf2);
- } else {
- char *buffer;
- struct stat stats;
- if (stat(fnamebuf2, &stats)) {
- ast_log(LOG_WARNING, "Failed to populate stats from file '%s'\n", fnamebuf2);
- }
- buffer = (char*)malloc(stats.st_size+1);
- if (fread(buffer, 1, stats.st_size, in1) != stats.st_size) {
- ast_log(LOG_ERROR, "fread() failed: %s\n", strerror(errno));
- }
- buffer[stats.st_size] = 0;
- ast_debug(1, " --Read in included file %s, %d chars\n",fnamebuf2, (int)stats.st_size);
- fclose(in1);
- if (include_stack[include_stack_index].fname) {
- free(include_stack[include_stack_index].fname);
- include_stack[include_stack_index].fname = 0;
- }
- include_stack[include_stack_index].fname = strdup(S_OR(my_file, "<none>"));
- include_stack[include_stack_index].lineno = my_lineno;
- include_stack[include_stack_index].colno = my_col+yyleng;
- if (my_file)
- free(my_file);
- my_file = strdup(fnamebuf2);
- if (create)
- include_stack[include_stack_index].globbuf = *globbuf;
- include_stack[include_stack_index].globbuf_pos = 0;
- include_stack[include_stack_index].bufstate = YY_CURRENT_BUFFER;
- if (create)
- include_stack_index++;
- yy_switch_to_buffer(ael_yy_scan_string (buffer ,yyscanner),yyscanner);
- free(buffer);
- my_lineno = 1;
- my_col = 1;
- BEGIN(INITIAL);
- }
- }
- }
|