Index: pbx/argdesc.y =================================================================== --- pbx/argdesc.y (.../branches/1.2) (revision 0) +++ pbx/argdesc.y (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,268 @@ +%{ +#include +#include +#include +#include "asterisk/argdesc.h" +#include "asterisk/logger.h" + +#define YYPARSE_PARAM parseio +#define YYLEX_PARAM ((struct parse_arginfo *)parseio)->scanner +#define YYERROR_VERBOSE 1 +/* this stuff is included so I can declare the proto for yyerror */ +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) + +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; + +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef union YYSTYPE { + char *str; + struct argapp *argapp; + struct argdesc *argdesc; + struct appsetvar *appsetvar; + struct argchoice *argchoice; +} YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + static int errcnt = 0; + +void yyerror(YYLTYPE *locp,void *nothing, char const *s); +int argdesc_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); +void linkarg(struct argdesc *head, struct argdesc *tail); +static void argdesc_destroy_argdesc(struct argdesc *desc); +static void argdesc_destroy_appsetvar(struct appsetvar *var); +static void argdesc_destroy_argchoice(struct argchoice *choice); +static void argdesc_destroy_argapp(struct argapp *app); + +%} + + +%union { + char *str; + struct argapp *argapp; + struct argdesc *argdesc; + struct appsetvar *appsetvar; + struct argchoice *argchoice; +} + + +%token SEMI COMMA BAR EQ LP RP LB RB LAB RAB COLON LC RC ELLIPSES +%token KW_ARGS KW_OPTIONS KW_CHANVARS intspec fltspec strspec + +%token word str1 + +%type file appentries appentry +%type arglist argdeclist argdec argspec +%type varlist varspec varspeclist +%type choicelist vallist optionslist optionspeclist optionspec + +/* OPTIONS */ +%locations +%pure-parser +%name-prefix="argdesc_yy" +/* the following option does two things: + it adds the locp arg to the yyerror + and it adds the NULL to the yyerrr arg list, and calls yyerror with NULL for that arg. + You can't get the locp arg without the NULL arg, don't ask me why. */ +%parse-param {void *NULL} + +%error-verbose + +%% + +file : appentries {((struct parse_arginfo *)parseio)->apps = $$; ((struct parse_arginfo *)parseio)->syntax_error_count = errcnt;} + ; + +appentries: appentry {$$=$1;} + | appentries appentry {$2->next = $1; $$ = $2; } + ; + +appentry: word COLON str1 SEMI arglist optionslist varlist { + $$=(struct argapp *)calloc(sizeof(struct argapp),1); + $$->name = $1; + $$->desc = $3; + $$->args = $5; + $$->opts = $6; + $$->setvars = $7; + } + ; + +arglist : /* nothing */ {$$=0;} + | KW_ARGS EQ argdeclist SEMI {$$=$3;} + ; + +argdeclist : argdec {$$=$1;} + | argdeclist BAR argdec {$$=$1; linkarg($$,$3);} + ; + +argdec : argspec {$$=$1; $$->type=ARGD_REQUIRED;} + | LB argspec RB {$$=$2; $$->type=ARGD_OPTIONAL;} + | LB COLON argspec RB {$$=$3; $$->type=ARGD_OPTIONAL_PREV;} + | LC argspec RC {$$=$2; $$->type=ARGD_OPTIONAL_PLACEHOLD;} + ; +argspec : word {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=$1;$$->dtype=ARGD_STRING;} + | word intspec {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=$1; $$->dtype=ARGD_INT;} + | word strspec {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=$1;$$->dtype=ARGD_STRING;} + | word fltspec {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=$1;$$->dtype=ARGD_FLOAT;} + | ELLIPSES {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=0;$$->dtype=ARGD_VARARG;} + | KW_OPTIONS {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=0;$$->dtype=ARGD_OPTIONSET;} + | LAB word COLON choicelist RAB {$$=(struct argdesc*)calloc(sizeof(struct argdesc),1); $$->name=$2;$$->dtype=ARGD_ENUM;$$->choices = $4;} + ; + +choicelist : word {$$=(struct argchoice*)calloc(sizeof(struct argchoice),1); $$->name=$1;} + | choicelist COMMA word {$$=(struct argchoice*)calloc(sizeof(struct argchoice),1); $$->name=$3; $$->next = $1;} + ; + +optionslist : KW_OPTIONS EQ optionspeclist SEMI {$$=$3;} + | /* nothing */ {$$=0;} + ; + +optionspeclist : optionspec {$$=$1;} + | optionspeclist COMMA optionspec {$$=$3; $3->next = $1; } + ; + +optionspec : word {$$ = (struct argchoice *)calloc(sizeof(struct argchoice),1); $$->name=$1; $$->opttype=ARGD_OPT_NOARG;} + | word LP RP {$$ = (struct argchoice *)calloc(sizeof(struct argchoice),1); $$->name=$1; $$->opttype=ARGD_OPT_WITHARG;} + | word LB LP RP RB {$$ = (struct argchoice *)calloc(sizeof(struct argchoice),1); $$->name=$1; $$->opttype=ARGD_OPT_WITHOPTARG;} + ; + + +varlist : /* nothing */ {$$=0;} + | KW_CHANVARS EQ varspeclist SEMI {$$=$3;} + ; + +varspeclist : varspec {$$=$1;} + | varspeclist COMMA varspec {$$ = $3; $$->next = $1;} + ; + +varspec : word {$$=(struct appsetvar*)calloc(sizeof(struct appsetvar),1); $$->name=$1;} + | word COLON vallist {$$=(struct appsetvar*)calloc(sizeof(struct appsetvar),1); $$->name=$1; $$->vals=$3;} + ; + +vallist : word {$$=(struct argchoice*)calloc(sizeof(struct argchoice),1); $$->name=$1; } + | vallist BAR word {$$=(struct argchoice*)calloc(sizeof(struct argchoice),1); $$->name=$3; $$->next = $1; } + ; + + +%% + +void yyerror(YYLTYPE *locp, void *nothing, char const *s) +{ + + if (locp->first_line == locp->last_line) { + ast_log(LOG_ERROR, "==== Line %d, Cols: %d-%d: Error: %s\n", locp->first_line, locp->first_column, locp->last_column, s); + } else { + ast_log(LOG_ERROR, "==== Line %d Col %d to Line %d Col %d: Error: %s\n", locp->first_line, locp->first_column, locp->last_line, locp->last_column, s); + } + errcnt++; +} + +void linkarg(struct argdesc *head, struct argdesc *tail) +{ + if (!head->next) { + head->next = tail; + head->last_args = tail; + } else { + head->last_args->next = tail; + head->last_args = tail; + } +} + +static void argdesc_destroy_argdesc(struct argdesc *desc) +{ + struct argchoice *c, *cn; + if (desc->name) + free(desc->name); + for(c=desc->choices; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + desc->name = 0; + desc->choices = 0; + desc->next = 0; + free(desc); +} + +static void argdesc_destroy_appsetvar(struct appsetvar *var) +{ + struct argchoice *c, *cn; + if (var->name) + free(var->name); + for (c=var->vals; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + var->name = 0; + var->vals = 0; + var->next = 0; + free(var); +} + +static void argdesc_destroy_argchoice(struct argchoice *choice) +{ + if( choice->name ) + free( choice->name); + choice->name = 0; + choice->next = 0; + free(choice); +} + + +static void argdesc_destroy_argapp(struct argapp *app) +{ + struct argdesc *d,*dn; + struct appsetvar *v, *vn; + struct argchoice *c, *cn; + + for (d=app->args; d; ) { + dn = d->next; + argdesc_destroy_argdesc(d); + d = dn; + } + for (v=app->setvars; v;) { + vn = v->next; + argdesc_destroy_appsetvar(v); + v = vn; + } + for(c=app->opts; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + if (app->name) + free(app->name); + if (app->desc) + free(app->desc); + app->name = 0; + app->desc = 0; + app->next = 0; + app->args = 0; + app->setvars = 0; + app->opts = 0; + free(app); +} + +void argdesc_destroy(struct argapp *apps) +{ + struct argapp *p,*pn; + + for (p=apps; p; ) { + pn = p->next; + argdesc_destroy_argapp(p); + p = pn; + } +} Property changes on: pbx/argdesc.y ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/ael.tab.c =================================================================== --- pbx/ael.tab.c (.../branches/1.2) (revision 0) +++ pbx/ael.tab.c (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,2784 @@ +/* A Bison parser, made by GNU Bison 1.875c. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse ael_yyparse +#define yylex ael_yylex +#define yyerror ael_yyerror +#define yylval ael_yylval +#define yychar ael_yychar +#define yydebug ael_yydebug +#define yynerrs ael_yynerrs +#define yylloc ael_yylloc + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + KW_CONTEXT = 258, + LC = 259, + RC = 260, + LP = 261, + RP = 262, + SEMI = 263, + EQ = 264, + COMMA = 265, + COLON = 266, + AMPER = 267, + BAR = 268, + AT = 269, + KW_MACRO = 270, + KW_GLOBALS = 271, + KW_IGNOREPAT = 272, + KW_SWITCH = 273, + KW_IF = 274, + KW_IFTIME = 275, + KW_ELSE = 276, + KW_RANDOM = 277, + KW_ABSTRACT = 278, + EXTENMARK = 279, + KW_GOTO = 280, + KW_JUMP = 281, + KW_RETURN = 282, + KW_BREAK = 283, + KW_CONTINUE = 284, + KW_REGEXTEN = 285, + KW_HINT = 286, + KW_FOR = 287, + KW_WHILE = 288, + KW_CASE = 289, + KW_PATTERN = 290, + KW_DEFAULT = 291, + KW_CATCH = 292, + KW_SWITCHES = 293, + KW_ESWITCHES = 294, + KW_INCLUDES = 295, + word = 296 + }; +#endif +#define KW_CONTEXT 258 +#define LC 259 +#define RC 260 +#define LP 261 +#define RP 262 +#define SEMI 263 +#define EQ 264 +#define COMMA 265 +#define COLON 266 +#define AMPER 267 +#define BAR 268 +#define AT 269 +#define KW_MACRO 270 +#define KW_GLOBALS 271 +#define KW_IGNOREPAT 272 +#define KW_SWITCH 273 +#define KW_IF 274 +#define KW_IFTIME 275 +#define KW_ELSE 276 +#define KW_RANDOM 277 +#define KW_ABSTRACT 278 +#define EXTENMARK 279 +#define KW_GOTO 280 +#define KW_JUMP 281 +#define KW_RETURN 282 +#define KW_BREAK 283 +#define KW_CONTINUE 284 +#define KW_REGEXTEN 285 +#define KW_HINT 286 +#define KW_FOR 287 +#define KW_WHILE 288 +#define KW_CASE 289 +#define KW_PATTERN 290 +#define KW_DEFAULT 291 +#define KW_CATCH 292 +#define KW_SWITCHES 293 +#define KW_ESWITCHES 294 +#define KW_INCLUDES 295 +#define word 296 + + + + +/* Copy the first part of user declarations. */ +#line 1 "ael.y" + +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * 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 Bison Grammar description of AEL2. + * + */ +#include +#include +#include +#include "asterisk/logger.h" +#include "asterisk/ael_structs.h" + +extern void reset_parencount(yyscan_t yyscanner); +extern void reset_semicount(yyscan_t yyscanner); +extern void reset_argcount(yyscan_t yyscanner ); + +#define YYPARSE_PARAM parseio +#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner +#define YYERROR_VERBOSE 1 + +/* this stuff is included so I can declare the proto for yyerror */ +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +int ael_errcnt = 0; +extern char *my_file; +void yyerror(YYLTYPE *locp,void *nothing, char const *s); +int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); +int ael_is_funcname(char *name); + static char *ael_token_subst(char *mess); + extern char *prev_word; + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 72 "ael.y" +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +/* Line 191 of yacc.c. */ +#line 242 "ael.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 214 of yacc.c. */ +#line 266 "ael.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# endif +# else +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYLTYPE_IS_TRIVIAL) && YYLTYPE_IS_TRIVIAL \ + && defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + YYLTYPE yyls; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 17 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 563 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 42 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 51 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 146 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 347 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 296 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short yyprhs[] = +{ + 0, 0, 3, 5, 7, 10, 13, 15, 17, 19, + 21, 27, 32, 38, 43, 50, 56, 63, 69, 78, + 86, 94, 101, 106, 110, 112, 115, 118, 119, 125, + 127, 131, 134, 136, 139, 142, 144, 146, 148, 150, + 152, 153, 159, 161, 166, 170, 175, 183, 192, 194, + 197, 200, 201, 207, 208, 214, 229, 240, 242, 245, + 247, 250, 254, 255, 262, 266, 267, 273, 277, 281, + 284, 285, 286, 287, 300, 301, 308, 311, 315, 319, + 322, 325, 326, 332, 335, 338, 341, 344, 349, 352, + 357, 360, 365, 367, 369, 373, 377, 383, 389, 395, + 401, 403, 407, 413, 417, 423, 427, 428, 434, 438, + 439, 443, 447, 450, 452, 453, 457, 460, 462, 465, + 470, 474, 479, 483, 486, 490, 492, 495, 497, 503, + 508, 512, 517, 521, 524, 528, 531, 534, 549, 560, + 564, 580, 592, 595, 597, 599, 604 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 43, 0, -1, 44, -1, 45, -1, 44, 45, -1, + 44, 1, -1, 46, -1, 47, -1, 48, -1, 8, + -1, 3, 41, 4, 53, 5, -1, 3, 41, 4, + 5, -1, 3, 36, 4, 53, 5, -1, 3, 36, + 4, 5, -1, 23, 3, 41, 4, 53, 5, -1, + 23, 3, 41, 4, 5, -1, 23, 3, 36, 4, + 53, 5, -1, 23, 3, 36, 4, 5, -1, 15, + 41, 6, 52, 7, 4, 85, 5, -1, 15, 41, + 6, 52, 7, 4, 5, -1, 15, 41, 6, 7, + 4, 85, 5, -1, 15, 41, 6, 7, 4, 5, + -1, 16, 4, 49, 5, -1, 16, 4, 5, -1, + 50, -1, 49, 50, -1, 49, 1, -1, -1, 41, + 9, 51, 41, 8, -1, 41, -1, 52, 10, 41, + -1, 52, 1, -1, 54, -1, 53, 54, -1, 53, + 1, -1, 57, -1, 92, -1, 87, -1, 88, -1, + 56, -1, -1, 41, 9, 55, 41, 8, -1, 8, + -1, 17, 24, 41, 8, -1, 41, 24, 68, -1, + 30, 41, 24, 68, -1, 31, 6, 65, 7, 41, + 24, 68, -1, 30, 31, 6, 65, 7, 41, 24, + 68, -1, 68, -1, 58, 68, -1, 58, 1, -1, + -1, 19, 6, 60, 64, 7, -1, -1, 22, 6, + 62, 64, 7, -1, 20, 6, 65, 11, 65, 11, + 65, 13, 65, 13, 65, 13, 65, 7, -1, 20, + 6, 41, 13, 65, 13, 65, 13, 65, 7, -1, + 41, -1, 41, 41, -1, 41, -1, 41, 41, -1, + 41, 41, 41, -1, -1, 18, 6, 67, 41, 7, + 4, -1, 4, 58, 5, -1, -1, 41, 9, 69, + 41, 8, -1, 25, 75, 8, -1, 26, 76, 8, + -1, 41, 11, -1, -1, -1, -1, 32, 6, 70, + 41, 8, 71, 41, 8, 72, 41, 7, 68, -1, + -1, 33, 6, 73, 41, 7, 68, -1, 66, 5, + -1, 66, 83, 5, -1, 12, 77, 8, -1, 81, + 8, -1, 41, 8, -1, -1, 81, 9, 74, 41, + 8, -1, 28, 8, -1, 27, 8, -1, 29, 8, + -1, 61, 68, -1, 61, 68, 21, 68, -1, 59, + 68, -1, 59, 68, 21, 68, -1, 63, 68, -1, + 63, 68, 21, 68, -1, 8, -1, 41, -1, 41, + 13, 41, -1, 41, 10, 41, -1, 41, 13, 41, + 13, 41, -1, 41, 10, 41, 10, 41, -1, 36, + 13, 41, 13, 41, -1, 36, 10, 41, 10, 41, + -1, 41, -1, 41, 10, 41, -1, 41, 10, 41, + 14, 41, -1, 41, 14, 41, -1, 41, 10, 41, + 14, 36, -1, 41, 14, 36, -1, -1, 41, 6, + 78, 82, 7, -1, 41, 6, 7, -1, -1, 41, + 80, 6, -1, 79, 82, 7, -1, 79, 7, -1, + 64, -1, -1, 82, 10, 41, -1, 82, 10, -1, + 84, -1, 83, 84, -1, 34, 41, 11, 58, -1, + 36, 11, 58, -1, 35, 41, 11, 58, -1, 34, + 41, 11, -1, 36, 11, -1, 35, 41, 11, -1, + 86, -1, 85, 86, -1, 68, -1, 37, 41, 4, + 58, 5, -1, 38, 4, 89, 5, -1, 38, 4, + 5, -1, 39, 4, 89, 5, -1, 39, 4, 5, + -1, 41, 8, -1, 89, 41, 8, -1, 89, 1, + -1, 91, 8, -1, 91, 13, 65, 11, 65, 11, + 65, 13, 65, 13, 65, 13, 65, 8, -1, 91, + 13, 41, 13, 65, 13, 65, 13, 65, 8, -1, + 90, 91, 8, -1, 90, 91, 13, 65, 11, 65, + 11, 65, 13, 65, 13, 65, 13, 65, 8, -1, + 90, 91, 13, 41, 13, 65, 13, 65, 13, 65, + 8, -1, 90, 1, -1, 41, -1, 36, -1, 40, + 4, 90, 5, -1, 40, 4, 5, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 139, 139, 142, 143, 146, 149, 150, 151, 152, + 155, 156, 157, 158, 159, 160, 161, 162, 165, 167, + 168, 169, 172, 173, 176, 177, 178, 181, 181, 184, + 185, 186, 189, 190, 193, 196, 197, 198, 199, 200, + 201, 201, 202, 205, 208, 209, 210, 211, 215, 216, + 219, 222, 222, 225, 225, 228, 247, 266, 267, 269, + 270, 271, 274, 274, 279, 280, 280, 283, 284, 285, + 286, 287, 288, 286, 291, 291, 294, 295, 296, 297, + 298, 300, 300, 332, 333, 334, 335, 336, 337, 338, + 339, 340, 341, 344, 345, 348, 351, 356, 361, 366, + 373, 376, 379, 384, 389, 394, 401, 401, 404, 407, + 407, 415, 421, 424, 425, 426, 427, 430, 431, 436, + 437, 438, 439, 440, 441, 444, 445, 450, 451, 454, + 455, 458, 459, 462, 463, 464, 467, 468, 489, 502, + 503, 523, 536, 539, 540, 543, 544 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "KW_CONTEXT", "LC", "RC", "LP", "RP", + "SEMI", "EQ", "COMMA", "COLON", "AMPER", "BAR", "AT", "KW_MACRO", + "KW_GLOBALS", "KW_IGNOREPAT", "KW_SWITCH", "KW_IF", "KW_IFTIME", + "KW_ELSE", "KW_RANDOM", "KW_ABSTRACT", "EXTENMARK", "KW_GOTO", "KW_JUMP", + "KW_RETURN", "KW_BREAK", "KW_CONTINUE", "KW_REGEXTEN", "KW_HINT", + "KW_FOR", "KW_WHILE", "KW_CASE", "KW_PATTERN", "KW_DEFAULT", "KW_CATCH", + "KW_SWITCHES", "KW_ESWITCHES", "KW_INCLUDES", "word", "$accept", "file", + "objects", "object", "context", "macro", "globals", "global_statements", + "global_statement", "@1", "arglist", "elements", "element", "@2", + "ignorepat", "extension", "statements", "if_head", "@3", "random_head", + "@4", "iftime_head", "word_list", "word3_list", "switch_head", "@5", + "statement", "@6", "@7", "@8", "@9", "@10", "@11", "target", + "jumptarget", "macro_call", "@12", "application_call_head", "@13", + "application_call", "eval_arglist", "case_statements", "case_statement", + "macro_statements", "macro_statement", "switches", "eswitches", + "switchlist", "includeslist", "includedname", "includes", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 42, 43, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 46, 46, 46, 47, 47, + 47, 47, 48, 48, 49, 49, 49, 51, 50, 52, + 52, 52, 53, 53, 53, 54, 54, 54, 54, 54, + 55, 54, 54, 56, 57, 57, 57, 57, 58, 58, + 58, 60, 59, 62, 61, 63, 63, 64, 64, 65, + 65, 65, 67, 66, 68, 69, 68, 68, 68, 68, + 70, 71, 72, 68, 73, 68, 68, 68, 68, 68, + 68, 74, 68, 68, 68, 68, 68, 68, 68, 68, + 68, 68, 68, 75, 75, 75, 75, 75, 75, 75, + 76, 76, 76, 76, 76, 76, 78, 77, 77, 80, + 79, 81, 81, 82, 82, 82, 82, 83, 83, 84, + 84, 84, 84, 84, 84, 85, 85, 86, 86, 87, + 87, 88, 88, 89, 89, 89, 90, 90, 90, 90, + 90, 90, 90, 91, 91, 92, 92 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 1, 2, 2, 1, 1, 1, 1, + 5, 4, 5, 4, 6, 5, 6, 5, 8, 7, + 7, 6, 4, 3, 1, 2, 2, 0, 5, 1, + 3, 2, 1, 2, 2, 1, 1, 1, 1, 1, + 0, 5, 1, 4, 3, 4, 7, 8, 1, 2, + 2, 0, 5, 0, 5, 14, 10, 1, 2, 1, + 2, 3, 0, 6, 3, 0, 5, 3, 3, 2, + 0, 0, 0, 12, 0, 6, 2, 3, 3, 2, + 2, 0, 5, 2, 2, 2, 2, 4, 2, 4, + 2, 4, 1, 1, 3, 3, 5, 5, 5, 5, + 1, 3, 5, 3, 5, 3, 0, 5, 3, 0, + 3, 3, 2, 1, 0, 3, 2, 1, 2, 4, + 3, 4, 3, 2, 3, 1, 2, 1, 5, 4, + 3, 4, 3, 2, 3, 2, 2, 14, 10, 3, + 15, 11, 2, 1, 1, 4, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 9, 0, 0, 0, 0, 0, 3, 6, + 7, 8, 0, 0, 0, 0, 0, 1, 5, 4, + 0, 0, 0, 23, 0, 0, 24, 0, 0, 13, + 42, 0, 0, 0, 0, 0, 0, 0, 0, 32, + 39, 35, 37, 38, 36, 11, 0, 0, 29, 0, + 27, 26, 22, 25, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 40, 0, 34, 12, 33, 10, 0, + 31, 0, 0, 0, 17, 0, 15, 0, 0, 0, + 0, 59, 0, 130, 0, 0, 132, 0, 146, 144, + 143, 0, 0, 0, 0, 92, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 109, 0, + 0, 0, 0, 44, 114, 0, 21, 0, 127, 0, + 125, 0, 30, 0, 16, 14, 43, 0, 45, 60, + 0, 133, 135, 129, 0, 131, 142, 145, 0, 136, + 0, 0, 0, 48, 0, 0, 62, 51, 0, 53, + 0, 93, 0, 100, 0, 84, 83, 85, 70, 74, + 80, 65, 69, 0, 88, 86, 90, 76, 0, 0, + 0, 0, 117, 112, 57, 113, 0, 79, 81, 0, + 20, 126, 19, 0, 28, 0, 61, 0, 134, 139, + 0, 59, 0, 41, 50, 64, 49, 106, 78, 0, + 0, 59, 0, 0, 0, 0, 0, 0, 67, 0, + 0, 68, 0, 0, 0, 110, 0, 0, 0, 0, + 0, 123, 77, 118, 58, 111, 116, 0, 0, 18, + 0, 0, 59, 0, 0, 0, 108, 114, 0, 0, + 0, 0, 0, 0, 0, 95, 94, 101, 105, 103, + 0, 0, 0, 89, 87, 91, 122, 124, 0, 115, + 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, + 52, 0, 0, 54, 0, 0, 0, 0, 0, 71, + 0, 66, 0, 0, 82, 128, 47, 0, 0, 0, + 0, 107, 63, 0, 0, 99, 98, 97, 96, 104, + 102, 0, 75, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 138, 0, 56, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 0, 73, + 0, 0, 0, 0, 137, 55, 140 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short yydefgoto[] = +{ + -1, 6, 7, 8, 9, 10, 11, 25, 26, 73, + 49, 38, 39, 93, 40, 41, 142, 109, 200, 110, + 203, 111, 175, 82, 112, 199, 143, 214, 212, 301, + 323, 213, 227, 152, 154, 145, 237, 114, 163, 115, + 176, 171, 172, 119, 120, 42, 43, 85, 91, 92, + 44 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -196 +static const short yypact[] = +{ + 187, 28, -196, -31, 23, 107, 50, 486, -196, -196, + -196, -196, 124, 131, 67, 35, 70, -196, -196, -196, + 476, 480, 44, -196, 125, 1, -196, 137, 138, -196, + -196, 119, 73, 145, 159, 169, 179, 10, 203, -196, + -196, -196, -196, -196, -196, -196, 279, 201, -196, 2, + -196, -196, -196, -196, 495, 522, 165, 207, 191, 176, + 36, 38, 13, -196, 450, -196, -196, -196, -196, 346, + -196, 217, 181, 190, -196, 307, -196, 322, 228, 176, + 450, 196, 233, -196, 237, 19, -196, 51, -196, -196, + -196, 12, 142, 205, 450, -196, 210, 248, 249, 250, + 251, 130, 218, 252, 253, 255, 259, 260, 151, 450, + 450, 450, 113, -196, 52, 112, -196, 227, -196, 372, + -196, 398, -196, 261, -196, -196, -196, 263, -196, 235, + 238, -196, -196, -196, 274, -196, -196, -196, 183, -196, + 242, 278, 160, -196, 282, 281, -196, -196, 256, -196, + 164, 213, 286, 103, 295, -196, -196, -196, -196, -196, + -196, -196, -196, 284, 283, 290, 292, -196, 266, 275, + 247, 122, -196, -196, 280, -196, 174, -196, -196, 318, + -196, -196, -196, 424, -196, 285, -196, 301, -196, -196, + 287, 45, 320, -196, -196, -196, -196, 325, -196, 288, + 293, 58, 324, 293, 299, 300, 302, 303, -196, 308, + 171, -196, 314, 315, 316, -196, 450, 450, 450, 331, + 348, 450, -196, -196, -196, -196, 326, 328, 450, -196, + 309, 450, 59, 359, 176, 176, -196, 293, 329, 374, + 176, 176, 375, 376, 380, 378, 382, 371, -196, -196, + 381, 389, 399, -196, -196, -196, 450, 450, 3, -196, + 400, 273, 450, -196, 176, 176, 401, 404, 220, 407, + -196, 406, 410, -196, 392, 393, 396, 397, 173, -196, + 450, -196, 62, 104, -196, -196, -196, 409, 429, 176, + 176, -196, -196, 176, 176, -196, -196, -196, -196, -196, + -196, 414, -196, 176, 176, 428, 432, 434, 435, 451, + 447, 453, 176, 176, 176, 176, -196, 176, 176, 455, + 454, 405, 458, 423, 465, 461, -196, 176, -196, 176, + 473, -196, 176, 477, 479, 450, 482, 176, 176, -196, + 176, 488, 491, 496, -196, -196, -196 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short yypgoto[] = +{ + -196, -196, -196, 492, -196, -196, -196, -196, 483, -196, + -196, 47, 69, -196, -196, -196, -195, -196, -196, -196, + -196, -196, 32, -65, -196, -196, -64, -196, -196, -196, + -196, -196, -196, -196, -196, -196, -196, -196, -196, -196, + 268, -196, 342, 402, -118, -196, -196, 463, -196, 431, + -196 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -122 +static const short yytable[] = +{ + 113, 181, 51, 70, 194, 118, 52, 94, -120, 71, + 14, 95, 72, 136, 127, 96, 128, 137, 88, 63, + 132, 97, 98, 99, 133, 100, 258, 15, 101, 102, + 103, 104, 105, 261, 64, 106, 107, -120, -120, -120, + 23, 83, 24, 86, 108, 164, 165, 166, 89, 89, + 17, 47, 132, 90, 90, 118, 135, 118, 234, 173, + 134, 282, 283, 194, 12, 181, 94, -119, 46, 13, + 95, 240, 264, 22, 96, 192, 24, 84, 196, 84, + 97, 98, 99, 202, 100, 48, 129, 101, 102, 103, + 104, 105, 134, 174, 106, 107, -119, -119, -119, 129, + 129, 75, 77, 108, 57, 194, 27, 67, 94, -121, + 16, 28, 95, 209, 58, 67, 96, 210, 167, 118, + 177, 178, 97, 98, 99, 233, 100, 222, 20, 101, + 102, 103, 104, 105, 50, 21, 106, 107, -121, -121, + -121, 54, 55, 56, 67, 108, 67, 168, 169, 170, + 139, 59, 253, 254, 255, 140, 168, 169, 170, 160, + 161, 194, 162, 60, 94, 195, 150, 263, 95, 266, + 267, 151, 96, 61, 204, 271, 272, 205, 97, 98, + 99, 225, 100, 62, 226, 101, 102, 103, 104, 105, + 1, 189, 106, 107, 196, 2, 190, 196, 286, 287, + 288, 108, 3, 4, 65, 69, 78, 248, 66, 299, + 5, 30, 249, 79, 300, 80, 302, 81, 196, 196, + 31, 121, 122, 206, 305, 306, 207, 291, 307, 308, + 226, 123, 239, 32, 33, 242, 126, 129, 310, 311, + 130, 34, 35, 36, 37, 131, 141, 319, 320, 321, + 322, 144, 324, 325, 146, 147, 148, 149, 221, 153, + 155, 156, 333, 157, 334, 158, 159, 336, 179, 184, + 185, 339, 341, 342, 194, 343, 186, 94, 285, 187, + 65, 95, 188, 191, 68, 96, 193, 30, 197, 198, + 215, 97, 98, 99, 208, 100, 31, 201, 101, 102, + 103, 104, 105, 211, 216, 106, 107, 219, 65, 32, + 33, 217, 124, 218, 108, 30, 220, 34, 35, 36, + 37, 224, 228, 65, 31, 231, 230, 125, 232, 238, + 30, 235, 236, 262, 174, 241, 269, 32, 33, 31, + 243, 244, 256, 245, 246, 34, 35, 36, 37, 247, + 94, 116, 32, 33, 95, 250, 251, 252, 96, 257, + 34, 35, 36, 37, 97, 98, 99, 259, 100, 260, + 265, 101, 102, 103, 104, 105, 94, 180, 106, 107, + 95, 270, 273, 117, 96, 278, 274, 108, 276, 279, + 97, 98, 99, 275, 100, 277, 280, 101, 102, 103, + 104, 105, 94, 182, 106, 107, 95, 281, 284, 117, + 96, 292, 328, 108, 289, 290, 97, 98, 99, 293, + 100, 294, 303, 101, 102, 103, 104, 105, 94, 229, + 106, 107, 95, 295, 296, 117, 96, 297, 298, 108, + 304, 312, 97, 98, 99, 313, 100, 314, 315, 101, + 102, 103, 104, 105, 94, 309, 106, 107, 95, 316, + 317, 117, 96, 326, 330, 108, 318, 327, 97, 98, + 99, 329, 100, 331, 332, 101, 102, 103, 104, 105, + 335, 29, 106, 107, 30, 45, -2, 18, 30, 1, + 337, 108, 338, 31, 2, 340, 344, 31, 345, 19, + 74, 3, 4, 30, 346, 268, 32, 33, 53, 5, + 32, 33, 31, 223, 34, 35, 36, 37, 34, 35, + 36, 37, 138, 183, 87, 32, 33, 76, 0, 0, + 30, 0, 0, 34, 35, 36, 37, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 32, 33, 0, 0, 0, 0, 0, 0, + 34, 35, 36, 37 +}; + +static const short yycheck[] = +{ + 64, 119, 1, 1, 1, 69, 5, 4, 5, 7, + 41, 8, 10, 1, 79, 12, 80, 5, 5, 9, + 1, 18, 19, 20, 5, 22, 221, 4, 25, 26, + 27, 28, 29, 228, 24, 32, 33, 34, 35, 36, + 5, 5, 41, 5, 41, 109, 110, 111, 36, 36, + 0, 7, 1, 41, 41, 119, 5, 121, 13, 7, + 41, 256, 257, 1, 36, 183, 4, 5, 21, 41, + 8, 13, 13, 6, 12, 140, 41, 41, 142, 41, + 18, 19, 20, 148, 22, 41, 41, 25, 26, 27, + 28, 29, 41, 41, 32, 33, 34, 35, 36, 41, + 41, 54, 55, 41, 31, 1, 36, 38, 4, 5, + 3, 41, 8, 10, 41, 46, 12, 14, 5, 183, + 8, 9, 18, 19, 20, 190, 22, 5, 4, 25, + 26, 27, 28, 29, 9, 4, 32, 33, 34, 35, + 36, 4, 4, 24, 75, 41, 77, 34, 35, 36, + 8, 6, 216, 217, 218, 13, 34, 35, 36, 8, + 9, 1, 11, 4, 4, 5, 36, 231, 8, 234, + 235, 41, 12, 4, 10, 240, 241, 13, 18, 19, + 20, 7, 22, 4, 10, 25, 26, 27, 28, 29, + 3, 8, 32, 33, 258, 8, 13, 261, 262, 264, + 265, 41, 15, 16, 1, 4, 41, 36, 5, 36, + 23, 8, 41, 6, 41, 24, 280, 41, 282, 283, + 17, 4, 41, 10, 289, 290, 13, 7, 293, 294, + 10, 41, 200, 30, 31, 203, 8, 41, 303, 304, + 7, 38, 39, 40, 41, 8, 41, 312, 313, 314, + 315, 41, 317, 318, 6, 6, 6, 6, 11, 41, + 8, 8, 327, 8, 329, 6, 6, 332, 41, 8, + 7, 335, 337, 338, 1, 340, 41, 4, 5, 41, + 1, 8, 8, 41, 5, 12, 8, 8, 6, 8, + 6, 18, 19, 20, 8, 22, 17, 41, 25, 26, + 27, 28, 29, 8, 21, 32, 33, 41, 1, 30, + 31, 21, 5, 21, 41, 8, 41, 38, 39, 40, + 41, 41, 4, 1, 17, 24, 41, 5, 41, 41, + 8, 11, 7, 24, 41, 11, 7, 30, 31, 17, + 41, 41, 11, 41, 41, 38, 39, 40, 41, 41, + 4, 5, 30, 31, 8, 41, 41, 41, 12, 11, + 38, 39, 40, 41, 18, 19, 20, 41, 22, 41, + 11, 25, 26, 27, 28, 29, 4, 5, 32, 33, + 8, 7, 7, 37, 12, 14, 10, 41, 10, 8, + 18, 19, 20, 13, 22, 13, 7, 25, 26, 27, + 28, 29, 4, 5, 32, 33, 8, 8, 8, 37, + 12, 4, 7, 41, 13, 11, 18, 19, 20, 13, + 22, 11, 13, 25, 26, 27, 28, 29, 4, 5, + 32, 33, 8, 41, 41, 37, 12, 41, 41, 41, + 11, 13, 18, 19, 20, 13, 22, 13, 13, 25, + 26, 27, 28, 29, 4, 41, 32, 33, 8, 8, + 13, 37, 12, 8, 41, 41, 13, 13, 18, 19, + 20, 13, 22, 8, 13, 25, 26, 27, 28, 29, + 7, 5, 32, 33, 8, 5, 0, 1, 8, 3, + 13, 41, 13, 17, 8, 13, 8, 17, 7, 7, + 5, 15, 16, 8, 8, 237, 30, 31, 25, 23, + 30, 31, 17, 171, 38, 39, 40, 41, 38, 39, + 40, 41, 91, 121, 61, 30, 31, 5, -1, -1, + 8, -1, -1, 38, 39, 40, 41, -1, -1, 17, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 30, 31, -1, -1, -1, -1, -1, -1, + 38, 39, 40, 41 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 3, 8, 15, 16, 23, 43, 44, 45, 46, + 47, 48, 36, 41, 41, 4, 3, 0, 1, 45, + 4, 4, 6, 5, 41, 49, 50, 36, 41, 5, + 8, 17, 30, 31, 38, 39, 40, 41, 53, 54, + 56, 57, 87, 88, 92, 5, 53, 7, 41, 52, + 9, 1, 5, 50, 4, 4, 24, 31, 41, 6, + 4, 4, 4, 9, 24, 1, 5, 54, 5, 4, + 1, 7, 10, 51, 5, 53, 5, 53, 41, 6, + 24, 41, 65, 5, 41, 89, 5, 89, 5, 36, + 41, 90, 91, 55, 4, 8, 12, 18, 19, 20, + 22, 25, 26, 27, 28, 29, 32, 33, 41, 59, + 61, 63, 66, 68, 79, 81, 5, 37, 68, 85, + 86, 4, 41, 41, 5, 5, 8, 65, 68, 41, + 7, 8, 1, 5, 41, 5, 1, 5, 91, 8, + 13, 41, 58, 68, 41, 77, 6, 6, 6, 6, + 36, 41, 75, 41, 76, 8, 8, 8, 6, 6, + 8, 9, 11, 80, 68, 68, 68, 5, 34, 35, + 36, 83, 84, 7, 41, 64, 82, 8, 9, 41, + 5, 86, 5, 85, 8, 7, 41, 41, 8, 8, + 13, 41, 65, 8, 1, 5, 68, 6, 8, 67, + 60, 41, 65, 62, 10, 13, 10, 13, 8, 10, + 14, 8, 70, 73, 69, 6, 21, 21, 21, 41, + 41, 11, 5, 84, 41, 7, 10, 74, 4, 5, + 41, 24, 41, 65, 13, 11, 7, 78, 41, 64, + 13, 11, 64, 41, 41, 41, 41, 41, 36, 41, + 41, 41, 41, 68, 68, 68, 11, 11, 58, 41, + 41, 58, 24, 68, 13, 11, 65, 65, 82, 7, + 7, 65, 65, 7, 10, 13, 10, 13, 14, 8, + 7, 8, 58, 58, 8, 5, 68, 65, 65, 13, + 11, 7, 4, 13, 11, 41, 41, 41, 41, 36, + 41, 71, 68, 13, 11, 65, 65, 65, 65, 41, + 65, 65, 13, 13, 13, 13, 8, 13, 13, 65, + 65, 65, 65, 72, 65, 65, 8, 13, 7, 13, + 41, 8, 13, 65, 65, 7, 65, 13, 13, 68, + 13, 65, 65, 65, 8, 7, 8 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, NULL, "syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + ((Current).first_line = (Rhs)[1].first_line, \ + (Current).first_column = (Rhs)[1].first_column, \ + (Current).last_line = (Rhs)[N].last_line, \ + (Current).last_column = (Rhs)[N].last_column) +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep, yylocationp) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + (void) yylocationp; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +#else +static void +yydestruct (yytype, yyvaluep, yylocationp) + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + (void) yylocationp; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *NULL); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void *NULL) +#else +int +yyparse (NULL) + void *NULL; +#endif +#endif +{ + /* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + YYLTYPE *yylerrsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + YYSTACK_RELOCATE (yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + *++yylsp = yylloc; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, yylsp - yylen, yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 139 "ael.y" + {((struct parse_io *)parseio)->pval = yyval.pval; ((struct parse_io *)parseio)->syntax_error_count = ael_errcnt;;} + break; + + case 3: +#line 142 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 4: +#line 143 "ael.y" + {if ( yyvsp[-1].pval && yyvsp[0].pval ) {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);} + else if ( yyvsp[-1].pval ) {yyval.pval=yyvsp[-1].pval;} + else if ( yyvsp[0].pval ) {yyval.pval=yyvsp[0].pval;} ;} + break; + + case 6: +#line 149 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 7: +#line 150 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 8: +#line 151 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 9: +#line 152 "ael.y" + {yyval.pval=0;/* allow older docs to be read */;} + break; + + case 10: +#line 155 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-3].str; yyval.pval->u2.statements = yyvsp[-1].pval; ;} + break; + + case 11: +#line 156 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; ;} + break; + + case 12: +#line 157 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = strdup("default"); yyval.pval->u2.statements = yyvsp[-1].pval; ;} + break; + + case 13: +#line 158 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.str = strdup("default"); ;} + break; + + case 14: +#line 159 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-5].first_line,yylsp[0].last_line, yylsp[-5].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-3].str; yyval.pval->u2.statements = yyvsp[-1].pval; yyval.pval->u3.abstract = 1;;} + break; + + case 15: +#line 160 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u3.abstract = 1; ;} + break; + + case 16: +#line 161 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-5].first_line,yylsp[0].last_line, yylsp[-5].first_column, yylsp[0].last_column); yyval.pval->u1.str = strdup("default"); yyval.pval->u2.statements = yyvsp[-1].pval; yyval.pval->u3.abstract = 1; ;} + break; + + case 17: +#line 162 "ael.y" + {yyval.pval=npval(PV_CONTEXT,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = strdup("default"); yyval.pval->u3.abstract = 1; ;} + break; + + case 18: +#line 165 "ael.y" + {yyval.pval=npval(PV_MACRO,yylsp[-7].first_line,yylsp[0].last_line, yylsp[-7].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-6].str; yyval.pval->u2.arglist = yyvsp[-4].pval; yyval.pval->u3.macro_statements = yyvsp[-1].pval; ;} + break; + + case 19: +#line 167 "ael.y" + {yyval.pval=npval(PV_MACRO,yylsp[-6].first_line,yylsp[0].last_line, yylsp[-6].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-5].str; yyval.pval->u2.arglist = yyvsp[-3].pval; ;} + break; + + case 20: +#line 168 "ael.y" + {yyval.pval=npval(PV_MACRO,yylsp[-6].first_line,yylsp[0].last_line, yylsp[-6].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-5].str; yyval.pval->u3.macro_statements = yyvsp[-1].pval; ;} + break; + + case 21: +#line 169 "ael.y" + {yyval.pval=npval(PV_MACRO,yylsp[-5].first_line,yylsp[0].last_line, yylsp[-5].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-4].str; /* pretty empty! */ ;} + break; + + case 22: +#line 172 "ael.y" + {yyval.pval=npval(PV_GLOBALS,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.statements = yyvsp[-1].pval;;} + break; + + case 23: +#line 173 "ael.y" + {yyval.pval=npval(PV_GLOBALS,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); /* and that's all */ ;} + break; + + case 24: +#line 176 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 25: +#line 177 "ael.y" + {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);;} + break; + + case 27: +#line 181 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 28: +#line 181 "ael.y" + {yyval.pval=npval(PV_VARDEC,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-4].str;yyval.pval->u2.val = yyvsp[-1].str; ;} + break; + + case 29: +#line 184 "ael.y" + {yyval.pval= npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[0].str; ;} + break; + + case 30: +#line 185 "ael.y" + {pval *z = npval(PV_WORD,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); z->u1.str = yyvsp[0].str; yyval.pval=yyvsp[-2].pval; linku1(yyval.pval,z); ;} + break; + + case 32: +#line 189 "ael.y" + { yyval.pval=yyvsp[0].pval;;} + break; + + case 33: +#line 190 "ael.y" + { if ( yyvsp[-1].pval && yyvsp[0].pval ) {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);} + else if ( yyvsp[-1].pval ) {yyval.pval=yyvsp[-1].pval;} + else if ( yyvsp[0].pval ) {yyval.pval=yyvsp[0].pval;} ;} + break; + + case 34: +#line 193 "ael.y" + { yyval.pval=yyvsp[-1].pval;;} + break; + + case 35: +#line 196 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 36: +#line 197 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 37: +#line 198 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 38: +#line 199 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 39: +#line 200 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 40: +#line 201 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 41: +#line 201 "ael.y" + {yyval.pval=npval(PV_VARDEC,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-4].str;yyval.pval->u2.val = yyvsp[-1].str; ;} + break; + + case 42: +#line 202 "ael.y" + {yyval.pval=0;/* allow older docs to be read */;} + break; + + case 43: +#line 205 "ael.y" + { yyval.pval=npval(PV_IGNOREPAT,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 44: +#line 208 "ael.y" + {yyval.pval = npval(PV_EXTENSION,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval; ;} + break; + + case 45: +#line 209 "ael.y" + {yyval.pval = npval(PV_EXTENSION,yylsp[-3].first_line,yylsp[-1].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval; yyval.pval->u4.regexten=1;;} + break; + + case 46: +#line 210 "ael.y" + {yyval.pval = npval(PV_EXTENSION,yylsp[-6].first_line,yylsp[0].last_line, yylsp[-6].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval; yyval.pval->u3.hints = yyvsp[-4].str;;} + break; + + case 47: +#line 211 "ael.y" + {yyval.pval = npval(PV_EXTENSION,yylsp[-7].first_line,yylsp[-4].last_line, yylsp[-7].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval; yyval.pval->u4.regexten=1;yyval.pval->u3.hints = yyvsp[-4].str;;} + break; + + case 48: +#line 215 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 49: +#line 216 "ael.y" + {if ( yyvsp[-1].pval && yyvsp[0].pval ) {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);} + else if ( yyvsp[-1].pval ) {yyval.pval=yyvsp[-1].pval;} + else if ( yyvsp[0].pval ) {yyval.pval=yyvsp[0].pval;} ;} + break; + + case 51: +#line 222 "ael.y" + {reset_parencount(((struct parse_io *)parseio)->scanner);;} + break; + + case 52: +#line 222 "ael.y" + { yyval.pval= npval(PV_IF,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str; ;} + break; + + case 53: +#line 225 "ael.y" + {reset_parencount(((struct parse_io *)parseio)->scanner);;} + break; + + case 54: +#line 225 "ael.y" + { yyval.pval= npval(PV_RANDOM,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str=yyvsp[-1].str;;} + break; + + case 55: +#line 228 "ael.y" + { yyval.pval= npval(PV_IFTIME,yylsp[-13].first_line,yylsp[-9].last_line, yylsp[-13].first_column, yylsp[-9].last_column); + yyval.pval->u1.list = npval(PV_WORD,yylsp[-11].first_line,yylsp[-11].last_line, yylsp[-11].first_column, yylsp[-11].last_column); + yyval.pval->u1.list->u1.str = (char*)malloc(strlen(yyvsp[-11].str)+strlen(yyvsp[-9].str)+strlen(yyvsp[-7].str)+4); + strcpy(yyval.pval->u1.list->u1.str,yyvsp[-11].str); + strcat(yyval.pval->u1.list->u1.str,":"); + strcat(yyval.pval->u1.list->u1.str,yyvsp[-9].str); + strcat(yyval.pval->u1.list->u1.str,":"); + strcat(yyval.pval->u1.list->u1.str,yyvsp[-7].str); + free(yyvsp[-11].str); + free(yyvsp[-9].str); + free(yyvsp[-7].str); + yyval.pval->u1.list->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + yyval.pval->u1.list->next->u1.str = yyvsp[-5].str; + yyval.pval->u1.list->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + yyval.pval->u1.list->next->next->u1.str = yyvsp[-3].str; + yyval.pval->u1.list->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + yyval.pval->u1.list->next->next->next->u1.str = yyvsp[-1].str; + prev_word = 0; + ;} + break; + + case 56: +#line 247 "ael.y" + { yyval.pval= npval(PV_IFTIME,yylsp[-9].first_line,yylsp[-5].last_line, yylsp[-9].first_column, yylsp[-5].last_column); + yyval.pval->u1.list = npval(PV_WORD,yylsp[-7].first_line,yylsp[-7].last_line, yylsp[-7].first_column, yylsp[-7].last_column); + yyval.pval->u1.list->u1.str = yyvsp[-7].str; + yyval.pval->u1.list->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + yyval.pval->u1.list->next->u1.str = yyvsp[-5].str; + yyval.pval->u1.list->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + yyval.pval->u1.list->next->next->u1.str = yyvsp[-3].str; + yyval.pval->u1.list->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + yyval.pval->u1.list->next->next->next->u1.str = yyvsp[-1].str; + prev_word = 0; + ;} + break; + + case 57: +#line 266 "ael.y" + { yyval.str = yyvsp[0].str;;} + break; + + case 58: +#line 267 "ael.y" + { yyval.str = (char*)malloc(strlen(yyvsp[-1].str)+strlen(yyvsp[0].str)+1); strcpy(yyval.str, yyvsp[-1].str); strcat(yyval.str, yyvsp[0].str); free(yyvsp[-1].str); free(yyvsp[0].str);prev_word = yyval.str;;} + break; + + case 59: +#line 269 "ael.y" + { yyval.str = yyvsp[0].str;;} + break; + + case 60: +#line 270 "ael.y" + { yyval.str = (char*)malloc(strlen(yyvsp[-1].str)+strlen(yyvsp[0].str)+1); strcpy(yyval.str, yyvsp[-1].str); strcat(yyval.str, yyvsp[0].str); free(yyvsp[-1].str); free(yyvsp[0].str);prev_word = yyval.str;;} + break; + + case 61: +#line 271 "ael.y" + { yyval.str = (char*)malloc(strlen(yyvsp[-2].str)+strlen(yyvsp[-1].str)+strlen(yyvsp[0].str)+1); strcpy(yyval.str, yyvsp[-2].str); strcat(yyval.str, yyvsp[-1].str); strcat(yyval.str, yyvsp[0].str); free(yyvsp[-2].str); free(yyvsp[-1].str); free(yyvsp[0].str);prev_word=yyval.str;;} + break; + + case 62: +#line 274 "ael.y" + {reset_parencount(((struct parse_io *)parseio)->scanner);;} + break; + + case 63: +#line 275 "ael.y" + {yyval.pval=npval(PV_SWITCH,yylsp[-5].first_line,yylsp[0].last_line, yylsp[-5].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-2].str; ;} + break; + + case 64: +#line 279 "ael.y" + {yyval.pval=npval(PV_STATEMENTBLOCK,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval; ;} + break; + + case 65: +#line 280 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 66: +#line 281 "ael.y" + {yyval.pval=npval(PV_VARDEC,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-4].str; yyval.pval->u2.val = yyvsp[-1].str; ;} + break; + + case 67: +#line 283 "ael.y" + {yyval.pval=npval(PV_GOTO,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval;;} + break; + + case 68: +#line 284 "ael.y" + {yyval.pval=npval(PV_GOTO,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval;;} + break; + + case 69: +#line 285 "ael.y" + {yyval.pval=npval(PV_LABEL,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str; ;} + break; + + case 70: +#line 286 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 71: +#line 287 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 72: +#line 288 "ael.y" + {reset_parencount(((struct parse_io *)parseio)->scanner);;} + break; + + case 73: +#line 289 "ael.y" + { yyval.pval=npval(PV_FOR,yylsp[-11].first_line,yylsp[0].last_line, yylsp[-11].first_column, yylsp[0].last_column); + yyval.pval->u1.for_init = yyvsp[-8].str; yyval.pval->u2.for_test=yyvsp[-5].str; yyval.pval->u3.for_inc = yyvsp[-2].str; yyval.pval->u4.for_statements = yyvsp[0].pval;;} + break; + + case 74: +#line 291 "ael.y" + {reset_parencount(((struct parse_io *)parseio)->scanner);;} + break; + + case 75: +#line 292 "ael.y" + {yyval.pval=npval(PV_WHILE,yylsp[-5].first_line,yylsp[0].last_line, yylsp[-5].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval; ;} + break; + + case 76: +#line 294 "ael.y" + {yyval.pval=yyvsp[-1].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 77: +#line 295 "ael.y" + {yyval.pval=yyvsp[-2].pval; yyval.pval->u2.statements = yyvsp[-1].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 78: +#line 296 "ael.y" + {yyval.pval = yyvsp[-1].pval;yyval.pval->endline = yylsp[-1].last_line; yyval.pval->endcol = yylsp[-1].last_column;;} + break; + + case 79: +#line 297 "ael.y" + { yyval.pval = yyvsp[-1].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 80: +#line 298 "ael.y" + { yyval.pval= npval(PV_APPLICATION_CALL,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 81: +#line 300 "ael.y" + {reset_semicount(((struct parse_io *)parseio)->scanner);;} + break; + + case 82: +#line 300 "ael.y" + { + char *bufx; + int tot=0; + pval *pptr; + + yyval.pval = npval(PV_VARDEC,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); + yyval.pval->u2.val=yyvsp[-1].str; + /* rebuild the original string-- this is not an app call, it's an unwrapped vardec, with a func call on the LHS */ + /* string to big to fit in the buffer? */ + tot+=strlen(yyvsp[-4].pval->u1.str); + for(pptr=yyvsp[-4].pval->u2.arglist;pptr;pptr=pptr->next) { + tot+=strlen(pptr->u1.str); + tot++; /* for a sep like a comma */ + } + tot+=4; /* for safety */ + bufx = (char *)malloc(tot); + strcpy(bufx,yyvsp[-4].pval->u1.str); + strcat(bufx,"("); + for (pptr=yyvsp[-4].pval->u2.arglist;pptr;pptr=pptr->next) { + if ( pptr != yyvsp[-4].pval->u2.arglist ) + strcat(bufx,","); + strcat(bufx,pptr->u1.str); + } + strcat(bufx,")"); + + if ( !ael_is_funcname(yyvsp[-4].pval->u1.str) ) + ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Function call? The name %s is not in my internal list of function names\n", + my_file, yylsp[-4].first_line, yylsp[-4].first_column, yylsp[-4].last_column, yyvsp[-4].pval->u1.str); + yyval.pval->u1.str = bufx; + destroy_pval(yyvsp[-4].pval); /* the app call it is not, get rid of that chain */ + prev_word = 0; + ;} + break; + + case 83: +#line 332 "ael.y" + { yyval.pval = npval(PV_BREAK,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column);;} + break; + + case 84: +#line 333 "ael.y" + {yyval.pval = npval(PV_RETURN,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column);;} + break; + + case 85: +#line 334 "ael.y" + {yyval.pval = npval(PV_CONTINUE,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column);;} + break; + + case 86: +#line 335 "ael.y" + {yyval.pval=yyvsp[-1].pval; yyval.pval->u2.statements = yyvsp[0].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 87: +#line 336 "ael.y" + {yyval.pval=yyvsp[-3].pval; yyval.pval->u2.statements = yyvsp[-2].pval;yyval.pval->endline = yylsp[-2].last_line; yyval.pval->endcol = yylsp[-2].last_column; yyval.pval->u3.else_statements = yyvsp[0].pval;;} + break; + + case 88: +#line 337 "ael.y" + {yyval.pval=yyvsp[-1].pval; yyval.pval->u2.statements = yyvsp[0].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 89: +#line 338 "ael.y" + {yyval.pval=yyvsp[-3].pval; yyval.pval->u2.statements = yyvsp[-2].pval;yyval.pval->endline = yylsp[-2].last_line; yyval.pval->endcol = yylsp[-2].last_column; yyval.pval->u3.else_statements = yyvsp[0].pval;;} + break; + + case 90: +#line 339 "ael.y" + {yyval.pval=yyvsp[-1].pval; yyval.pval->u2.statements = yyvsp[0].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 91: +#line 340 "ael.y" + {yyval.pval=yyvsp[-3].pval; yyval.pval->u2.statements = yyvsp[-2].pval;yyval.pval->endline = yylsp[-2].last_line; yyval.pval->endcol = yylsp[-2].last_column; yyval.pval->u3.else_statements = yyvsp[0].pval;;} + break; + + case 92: +#line 341 "ael.y" + { yyval.pval=0; ;} + break; + + case 93: +#line 344 "ael.y" + { yyval.pval = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[0].str;;} + break; + + case 94: +#line 345 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = yyvsp[0].str;;} + break; + + case 95: +#line 348 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = yyvsp[0].str;;} + break; + + case 96: +#line 351 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = yyvsp[-4].str; yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[0].str; ;} + break; + + case 97: +#line 356 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = yyvsp[-4].str; yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[0].str; ;} + break; + + case 98: +#line 361 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = strdup("default"); yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[0].str; ;} + break; + + case 99: +#line 366 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = strdup("default"); yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[0].str; ;} + break; + + case 100: +#line 373 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[0].str; yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = strdup("1");;} + break; + + case 101: +#line 376 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = yyvsp[0].str;;} + break; + + case 102: +#line 379 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = yyvsp[0].str; yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-4].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[-2].str; ;} + break; + + case 103: +#line 384 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->u1.str = yyvsp[0].str; yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = strdup("1"); ;} + break; + + case 104: +#line 389 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-4].first_line,yylsp[-4].last_line, yylsp[-4].first_column, yylsp[-4].last_column); + yyval.pval->u1.str = strdup("default"); yyval.pval->next = npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->next->u1.str = yyvsp[-4].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = yyvsp[-2].str; ;} + break; + + case 105: +#line 394 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-2].first_line,yylsp[-2].last_line, yylsp[-2].first_column, yylsp[-2].last_column); + yyval.pval->u1.str = strdup("default"); yyval.pval->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->u1.str = yyvsp[-2].str; + yyval.pval->next->next = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); + yyval.pval->next->next->u1.str = strdup("1"); ;} + break; + + case 106: +#line 401 "ael.y" + {reset_argcount(((struct parse_io *)parseio)->scanner);;} + break; + + case 107: +#line 402 "ael.y" + {yyval.pval= npval(PV_MACRO_CALL,yylsp[-4].first_line,yylsp[-3].last_line, yylsp[-4].first_column, yylsp[-3].last_column); + yyval.pval->u1.str = yyvsp[-4].str; yyval.pval->u2.arglist = yyvsp[-1].pval;;} + break; + + case 108: +#line 404 "ael.y" + {yyval.pval= npval(PV_MACRO_CALL,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-2].str; ;} + break; + + case 109: +#line 407 "ael.y" + {reset_argcount(((struct parse_io *)parseio)->scanner);;} + break; + + case 110: +#line 407 "ael.y" + {if (strcasecmp(yyvsp[-2].str,"goto") == 0) { + yyval.pval= npval(PV_GOTO,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); + ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Suggestion: Use the goto statement instead of the Goto() application call in AEL.\n", my_file, yylsp[-2].first_line, yylsp[-2].first_column, yylsp[-2].last_column ); + } else + yyval.pval= npval(PV_APPLICATION_CALL,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); + yyval.pval->u1.str = yyvsp[-2].str; ;} + break; + + case 111: +#line 415 "ael.y" + {yyval.pval = yyvsp[-2].pval; + if( yyval.pval->type == PV_GOTO ) + yyval.pval->u1.list = yyvsp[-1].pval; + else + yyval.pval->u2.arglist = yyvsp[-1].pval; + yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 112: +#line 421 "ael.y" + {yyval.pval=yyvsp[-1].pval;yyval.pval->endline = yylsp[0].last_line; yyval.pval->endcol = yylsp[0].last_column;;} + break; + + case 113: +#line 424 "ael.y" + { yyval.pval= npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[0].str;;} + break; + + case 114: +#line 425 "ael.y" + { yyval.pval= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/); yyval.pval->u1.str = strdup(""); ;} + break; + + case 115: +#line 426 "ael.y" + { pval *z = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); yyval.pval = yyvsp[-2].pval; linku1(yyvsp[-2].pval,z); z->u1.str = yyvsp[0].str;;} + break; + + case 116: +#line 427 "ael.y" + { pval *z = npval(PV_WORD,yylsp[0].first_line,yylsp[0].last_line, yylsp[0].first_column, yylsp[0].last_column); yyval.pval = yyvsp[-1].pval; linku1(yyvsp[-1].pval,z); z->u1.str = strdup("");;} + break; + + case 117: +#line 430 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 118: +#line 431 "ael.y" + { if ( yyvsp[-1].pval && yyvsp[0].pval ) {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);} + else if ( yyvsp[-1].pval ) {yyval.pval=yyvsp[-1].pval;} + else if ( yyvsp[0].pval ) {yyval.pval=yyvsp[0].pval;} ;} + break; + + case 119: +#line 436 "ael.y" + {yyval.pval = npval(PV_CASE,yylsp[-3].first_line,yylsp[-1].last_line, yylsp[-3].first_column, yylsp[-1].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval;;} + break; + + case 120: +#line 437 "ael.y" + {yyval.pval = npval(PV_DEFAULT,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.str = 0; yyval.pval->u2.statements = yyvsp[0].pval;;} + break; + + case 121: +#line 438 "ael.y" + {yyval.pval = npval(PV_PATTERN,yylsp[-3].first_line,yylsp[-1].last_line, yylsp[-3].first_column, yylsp[-1].last_column); yyval.pval->u1.str = yyvsp[-2].str; yyval.pval->u2.statements = yyvsp[0].pval;;} + break; + + case 122: +#line 439 "ael.y" + {yyval.pval = npval(PV_CASE,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 123: +#line 440 "ael.y" + {yyval.pval = npval(PV_DEFAULT,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval->u1.str = 0;;} + break; + + case 124: +#line 441 "ael.y" + {yyval.pval = npval(PV_PATTERN,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 125: +#line 444 "ael.y" + {yyval.pval = yyvsp[0].pval;;} + break; + + case 126: +#line 445 "ael.y" + { if ( yyvsp[-1].pval && yyvsp[0].pval ) {yyval.pval=yyvsp[-1].pval; linku1(yyval.pval,yyvsp[0].pval);} + else if ( yyvsp[-1].pval ) {yyval.pval=yyvsp[-1].pval;} + else if ( yyvsp[0].pval ) {yyval.pval=yyvsp[0].pval;} ;} + break; + + case 127: +#line 450 "ael.y" + {yyval.pval=yyvsp[0].pval;;} + break; + + case 128: +#line 451 "ael.y" + {yyval.pval=npval(PV_CATCH,yylsp[-4].first_line,yylsp[0].last_line, yylsp[-4].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-3].str; yyval.pval->u2.statements = yyvsp[-1].pval;;} + break; + + case 129: +#line 454 "ael.y" + {yyval.pval= npval(PV_SWITCHES,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval; ;} + break; + + case 130: +#line 455 "ael.y" + {yyval.pval= npval(PV_SWITCHES,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column);;} + break; + + case 131: +#line 458 "ael.y" + {yyval.pval= npval(PV_ESWITCHES,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval; ;} + break; + + case 132: +#line 459 "ael.y" + {yyval.pval= npval(PV_ESWITCHES,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column); ;} + break; + + case 133: +#line 462 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 134: +#line 463 "ael.y" + {pval *z = npval(PV_WORD,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval=yyvsp[-2].pval; z->u1.str = yyvsp[-1].str; linku1(yyval.pval,z); ;} + break; + + case 136: +#line 467 "ael.y" + {yyval.pval=npval(PV_WORD,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval->u1.str = yyvsp[-1].str;;} + break; + + case 137: +#line 468 "ael.y" + { + yyval.pval=npval(PV_WORD,yylsp[-13].first_line,yylsp[-12].last_line, yylsp[-13].first_column, yylsp[-12].last_column); + yyval.pval->u1.str = yyvsp[-13].str; + yyval.pval->u2.arglist = npval(PV_WORD,yylsp[-11].first_line,yylsp[-7].last_line, yylsp[-11].first_column, yylsp[-7].last_column); + yyval.pval->u2.arglist->u1.str = (char*)malloc(strlen(yyvsp[-11].str)+strlen(yyvsp[-9].str)+strlen(yyvsp[-7].str)+4); + strcpy(yyval.pval->u2.arglist->u1.str,yyvsp[-11].str); + strcat(yyval.pval->u2.arglist->u1.str,":"); + strcat(yyval.pval->u2.arglist->u1.str,yyvsp[-9].str); + strcat(yyval.pval->u2.arglist->u1.str,":"); + strcat(yyval.pval->u2.arglist->u1.str,yyvsp[-7].str); + free(yyvsp[-11].str); + free(yyvsp[-9].str); + free(yyvsp[-7].str); + yyval.pval->u2.arglist->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + yyval.pval->u2.arglist->next->u1.str = yyvsp[-5].str; + yyval.pval->u2.arglist->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + yyval.pval->u2.arglist->next->next->u1.str = yyvsp[-3].str; + yyval.pval->u2.arglist->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + yyval.pval->u2.arglist->next->next->next->u1.str = yyvsp[-1].str; + prev_word=0; + ;} + break; + + case 138: +#line 489 "ael.y" + { + yyval.pval=npval(PV_WORD,yylsp[-9].first_line,yylsp[-8].last_line, yylsp[-9].first_column, yylsp[-8].last_column); + yyval.pval->u1.str = yyvsp[-9].str; + yyval.pval->u2.arglist = npval(PV_WORD,yylsp[-7].first_line,yylsp[-7].last_line, yylsp[-7].first_column, yylsp[-7].last_column); + yyval.pval->u2.arglist->u1.str = yyvsp[-7].str; + yyval.pval->u2.arglist->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + yyval.pval->u2.arglist->next->u1.str = yyvsp[-5].str; + yyval.pval->u2.arglist->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + yyval.pval->u2.arglist->next->next->u1.str = yyvsp[-3].str; + yyval.pval->u2.arglist->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + yyval.pval->u2.arglist->next->next->next->u1.str = yyvsp[-1].str; + prev_word=0; + ;} + break; + + case 139: +#line 502 "ael.y" + {pval *z = npval(PV_WORD,yylsp[-1].first_line,yylsp[0].last_line, yylsp[-1].first_column, yylsp[0].last_column); yyval.pval=yyvsp[-2].pval; z->u1.str = yyvsp[-1].str; linku1(yyval.pval,z); ;} + break; + + case 140: +#line 503 "ael.y" + {pval *z = npval(PV_WORD,yylsp[-13].first_line,yylsp[-12].last_line, yylsp[-13].first_column, yylsp[-12].last_column); + yyval.pval=yyvsp[-14].pval; z->u1.str = yyvsp[-13].str; linku1(yyval.pval,z); + z->u2.arglist = npval(PV_WORD,yylsp[-11].first_line,yylsp[-11].last_line, yylsp[-11].first_column, yylsp[-11].last_column); + yyval.pval->u2.arglist->u1.str = (char*)malloc(strlen(yyvsp[-11].str)+strlen(yyvsp[-9].str)+strlen(yyvsp[-7].str)+4); + strcpy(yyval.pval->u2.arglist->u1.str,yyvsp[-11].str); + strcat(yyval.pval->u2.arglist->u1.str,":"); + strcat(yyval.pval->u2.arglist->u1.str,yyvsp[-9].str); + strcat(yyval.pval->u2.arglist->u1.str,":"); + strcat(yyval.pval->u2.arglist->u1.str,yyvsp[-7].str); + free(yyvsp[-11].str); + free(yyvsp[-9].str); + free(yyvsp[-7].str); + z->u2.arglist->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + z->u2.arglist->next->u1.str = yyvsp[-5].str; + z->u2.arglist->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + z->u2.arglist->next->next->u1.str = yyvsp[-3].str; + z->u2.arglist->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + z->u2.arglist->next->next->next->u1.str = yyvsp[-1].str; + prev_word=0; + ;} + break; + + case 141: +#line 524 "ael.y" + {pval *z = npval(PV_WORD,yylsp[-9].first_line,yylsp[-9].last_line, yylsp[-9].first_column, yylsp[-8].last_column); + yyval.pval=yyvsp[-10].pval; z->u1.str = yyvsp[-9].str; linku1(yyval.pval,z); + z->u2.arglist = npval(PV_WORD,yylsp[-7].first_line,yylsp[-7].last_line, yylsp[-7].first_column, yylsp[-7].last_column); + yyval.pval->u2.arglist->u1.str = yyvsp[-7].str; + z->u2.arglist->next = npval(PV_WORD,yylsp[-5].first_line,yylsp[-5].last_line, yylsp[-5].first_column, yylsp[-5].last_column); + z->u2.arglist->next->u1.str = yyvsp[-5].str; + z->u2.arglist->next->next = npval(PV_WORD,yylsp[-3].first_line,yylsp[-3].last_line, yylsp[-3].first_column, yylsp[-3].last_column); + z->u2.arglist->next->next->u1.str = yyvsp[-3].str; + z->u2.arglist->next->next->next = npval(PV_WORD,yylsp[-1].first_line,yylsp[-1].last_line, yylsp[-1].first_column, yylsp[-1].last_column); + z->u2.arglist->next->next->next->u1.str = yyvsp[-1].str; + prev_word=0; + ;} + break; + + case 143: +#line 539 "ael.y" + { yyval.str = yyvsp[0].str;;} + break; + + case 144: +#line 540 "ael.y" + {yyval.str=strdup("default");;} + break; + + case 145: +#line 543 "ael.y" + {yyval.pval= npval(PV_INCLUDES,yylsp[-3].first_line,yylsp[0].last_line, yylsp[-3].first_column, yylsp[0].last_column); yyval.pval->u1.list = yyvsp[-1].pval;;} + break; + + case 146: +#line 544 "ael.y" + {yyval.pval= npval(PV_INCLUDES,yylsp[-2].first_line,yylsp[0].last_line, yylsp[-2].first_column, yylsp[0].last_column);;} + break; + + + } + +/* Line 1000 of yacc.c. */ +#line 2392 "ael.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + yylsp -= yylen; + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (&yylloc, NULL, yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror (&yylloc, NULL, "syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (&yylloc, NULL, "syntax error"); + } + + yylerrsp = yylsp; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp, yylsp); + } + } + else + { + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + *++yylerrsp = yylloc; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + + yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + yylerrsp = yylsp; + *++yylerrsp = yyloc; + yylsp -= yylen; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp, yylsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + YYLLOC_DEFAULT (yyloc, yylsp, yylerrsp - yylsp); + *++yylsp = yyloc; + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror (&yylloc, NULL, "parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 548 "ael.y" + + +static char *token_equivs1[] = +{ + "AMPER", + "AT", + "BAR", + "COLON", + "COMMA", + "EQ", + "EXTENMARK", + "KW_BREAK", + "KW_CASE", + "KW_CATCH", + "KW_CONTEXT", + "KW_CONTINUE", + "KW_DEFAULT", + "KW_ELSE", + "KW_ESWITCHES", + "KW_FOR", + "KW_GLOBALS", + "KW_GOTO", + "KW_HINT", + "KW_IFTIME", + "KW_IF", + "KW_IGNOREPAT", + "KW_INCLUDES" + "KW_JUMP", + "KW_MACRO", + "KW_PATTERN", + "KW_REGEXTEN", + "KW_RETURN", + "KW_SWITCHES", + "KW_SWITCH", + "KW_WHILE", + "LC", + "LP", + "RC", + "RP", + "SEMI", +}; + +static char *token_equivs2[] = +{ + "&", + "@", + "|", + ":", + ",", + "=", + "=>", + "break", + "case", + "catch", + "context", + "continue", + "default", + "else", + "eswitches", + "for", + "globals", + "goto", + "hint", + "ifTime", + "if", + "ignorepat", + "includes" + "jump", + "macro", + "pattern", + "regexten", + "return", + "switches", + "switch", + "while", + "{", + "(", + "}", + ")", + ";", +}; + + +static char *ael_token_subst(char *mess) +{ + /* calc a length, malloc, fill, and return; yyerror had better free it! */ + int len=0,i; + char *p; + char *res, *s,*t; + int token_equivs_entries = sizeof(token_equivs1)/sizeof(char*); + + for (p=mess; *p; p++) { + for (i=0; ifirst_line == locp->last_line) { + ast_log(LOG_ERROR, "==== File: %s, Line %d, Cols: %d-%d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_column, s2); + } else { + ast_log(LOG_ERROR, "==== File: %s, Line %d Col %d to Line %d Col %d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column, s2); + } + free(s2); + + ael_errcnt++; +} + +struct pval *npval(pvaltype type,int first_line, int last_line, int first_column, int last_column) +{ + extern char *my_file; + pval *z = (pval *)calloc(sizeof(struct pval),1); + z->type = type; + z->startline = first_line; + z->endline = last_line; + z->startcol = first_column; + z->endcol = last_column; + z->filename = strdup(my_file); + return z; +} + +void linku1(pval *head, pval *tail) +{ + if (!head->next) { + head->next = tail; + head->u1_last = tail; + } else { + head->u1_last->next = tail; + head->u1_last = tail; + } +} + + Property changes on: pbx/ael.tab.c ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/ael_lex.c =================================================================== --- pbx/ael_lex.c (.../branches/1.2) (revision 0) +++ pbx/ael_lex.c (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,2993 @@ +#line 2 "ael_lex.c" + +#line 4 "ael_lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 31 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +int ael_yylex_init (yyscan_t* scanner); + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE ael_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via ael_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void ael_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void ael_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE ael_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void ael_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ael_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void ael_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void ael_yypop_buffer_state (yyscan_t yyscanner ); + +static void ael_yyensure_buffer_stack (yyscan_t yyscanner ); +static void ael_yy_load_buffer_state (yyscan_t yyscanner ); +static void ael_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER ael_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE ael_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE ael_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE ael_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *ael_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *ael_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void ael_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer ael_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + ael_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ael_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + ael_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + ael_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define ael_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyg->yytext_ptr -= yyg->yy_more_len; \ + yyleng = (size_t) (yy_cp - yyg->yytext_ptr); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 65 +#define YY_END_OF_BUFFER 66 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[226] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 66, 65, + 42, 40, 41, 43, 43, 9, 3, 4, 7, 43, + 8, 5, 6, 12, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 1, + 10, 2, 65, 45, 44, 46, 47, 48, 49, 65, + 61, 62, 63, 57, 58, 59, 60, 65, 51, 50, + 52, 55, 56, 53, 54, 42, 41, 43, 43, 13, + 11, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 20, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 0, 45, 44, 46, 47, 48, 49, 0, + + 61, 62, 63, 57, 58, 59, 60, 0, 51, 50, + 52, 55, 56, 53, 54, 43, 13, 13, 43, 43, + 43, 43, 43, 43, 43, 43, 31, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 33, 43, 43, 43, 25, 43, + 43, 26, 24, 43, 43, 43, 27, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 29, 36, 43, 43, + 43, 43, 43, 43, 43, 43, 16, 43, 43, 43, + 43, 43, 32, 43, 43, 43, 43, 43, 43, 43, + 21, 43, 43, 43, 22, 43, 28, 19, 43, 43, + + 14, 43, 34, 43, 17, 43, 43, 35, 43, 43, + 43, 15, 30, 43, 43, 39, 23, 37, 0, 38, + 18, 0, 0, 64, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 7, 5, 1, 8, 5, 9, + 10, 5, 5, 11, 5, 5, 12, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 13, 14, 5, + 15, 16, 1, 17, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 18, 5, 5, 5, 5, 5, 5, + 19, 1, 20, 1, 5, 1, 21, 22, 23, 24, + + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 5, 37, 38, 39, 40, 5, 41, 42, + 5, 5, 43, 44, 45, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[46] = + { 0, + 1, 1, 2, 1, 3, 4, 3, 1, 1, 1, + 1, 3, 1, 1, 1, 3, 1, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 1, 3 + } ; + +static yyconst flex_int16_t yy_base[236] = + { 0, + 0, 0, 37, 40, 77, 114, 151, 188, 237, 507, + 234, 507, 228, 0, 201, 507, 507, 507, 507, 217, + 507, 507, 212, 507, 205, 189, 27, 200, 20, 189, + 19, 194, 37, 182, 200, 199, 40, 178, 190, 507, + 507, 507, 57, 507, 507, 507, 507, 507, 507, 225, + 507, 507, 507, 507, 507, 507, 507, 262, 507, 507, + 507, 507, 507, 507, 507, 215, 212, 0, 181, 307, + 507, 176, 188, 30, 178, 185, 172, 168, 169, 170, + 165, 169, 184, 167, 177, 162, 170, 153, 157, 45, + 161, 160, 69, 507, 507, 507, 507, 507, 507, 343, + + 507, 507, 507, 507, 507, 507, 507, 380, 507, 507, + 507, 507, 507, 507, 507, 165, 0, 425, 148, 165, + 160, 161, 144, 161, 156, 151, 0, 157, 143, 138, + 147, 140, 142, 137, 135, 130, 144, 142, 126, 126, + 132, 131, 121, 125, 0, 127, 45, 114, 0, 114, + 131, 0, 0, 118, 113, 109, 0, 113, 122, 111, + 103, 107, 120, 117, 101, 119, 0, 0, 97, 104, + 105, 113, 103, 107, 106, 106, 0, 92, 94, 87, + 91, 93, 0, 95, 95, 78, 76, 76, 85, 73, + 0, 74, 84, 74, 0, 82, 0, 81, 80, 65, + + 0, 78, 0, 76, 0, 78, 60, 0, 61, 55, + 51, 0, 0, 43, 36, 0, 0, 0, 88, 0, + 0, 0, 67, 507, 507, 469, 473, 477, 479, 483, + 487, 491, 495, 499, 503 + } ; + +static yyconst flex_int16_t yy_def[236] = + { 0, + 225, 1, 226, 226, 227, 227, 228, 228, 225, 225, + 225, 225, 225, 229, 229, 225, 225, 225, 225, 229, + 225, 225, 225, 225, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 225, + 225, 225, 230, 225, 225, 225, 225, 225, 225, 231, + 225, 225, 225, 225, 225, 225, 225, 232, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 229, 229, 233, + 225, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 230, 225, 225, 225, 225, 225, 225, 231, + + 225, 225, 225, 225, 225, 225, 225, 232, 225, 225, + 225, 225, 225, 225, 225, 229, 234, 233, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 225, 229, + 229, 235, 235, 225, 0, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225 + } ; + +static yyconst flex_int16_t yy_nxt[553] = + { 0, + 10, 11, 12, 13, 14, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 14, 24, 14, 14, 14, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 14, 14, 35, 14, 14, 36, 37, 38, 14, 14, + 39, 14, 40, 41, 42, 44, 45, 74, 44, 45, + 80, 77, 219, 81, 219, 46, 47, 78, 46, 47, + 89, 75, 83, 84, 90, 94, 95, 121, 122, 169, + 85, 138, 224, 170, 221, 96, 97, 94, 95, 48, + 220, 49, 48, 139, 49, 51, 52, 96, 97, 219, + 53, 219, 218, 222, 217, 54, 55, 216, 215, 98, + + 214, 99, 213, 212, 211, 210, 209, 208, 207, 206, + 205, 98, 204, 99, 203, 202, 201, 200, 199, 56, + 198, 57, 51, 52, 197, 196, 195, 53, 194, 193, + 192, 191, 54, 55, 190, 189, 188, 187, 186, 185, + 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, + 174, 173, 172, 171, 168, 167, 56, 166, 57, 59, + 60, 61, 165, 164, 163, 162, 161, 160, 159, 62, + 63, 158, 157, 156, 155, 154, 153, 152, 151, 150, + 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, + 137, 136, 135, 64, 134, 65, 59, 60, 61, 133, + + 132, 131, 130, 129, 128, 127, 62, 63, 126, 125, + 124, 123, 120, 119, 116, 67, 66, 92, 91, 88, + 87, 86, 82, 79, 76, 73, 72, 71, 70, 69, + 64, 67, 65, 101, 102, 66, 225, 225, 103, 225, + 225, 225, 225, 104, 105, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 106, 225, 107, + 109, 110, 111, 225, 225, 225, 225, 225, 225, 225, + 112, 113, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + + 225, 225, 225, 225, 114, 225, 115, 117, 117, 225, + 117, 225, 225, 225, 117, 117, 117, 117, 225, 117, + 117, 117, 225, 117, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 117, 101, 102, 225, 225, 225, 103, 225, 225, 225, + 225, 104, 105, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 106, 225, 107, 109, 110, + 111, 225, 225, 225, 225, 225, 225, 225, 112, 113, + + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 114, 225, 115, 117, 117, 225, 117, 225, + 225, 225, 117, 117, 117, 117, 225, 117, 117, 117, + 225, 117, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 117, 43, + 43, 43, 43, 50, 50, 50, 50, 58, 58, 58, + 58, 68, 68, 93, 93, 93, 93, 100, 100, 100, + 100, 108, 108, 108, 108, 118, 225, 118, 118, 117, + + 225, 117, 117, 223, 223, 223, 9, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225 + } ; + +static yyconst flex_int16_t yy_chk[553] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 27, 4, 4, + 31, 29, 211, 31, 211, 3, 3, 29, 4, 4, + 37, 27, 33, 33, 37, 43, 43, 74, 74, 147, + 33, 90, 223, 147, 215, 43, 43, 93, 93, 3, + 214, 3, 4, 90, 4, 5, 5, 93, 93, 219, + 5, 219, 210, 219, 209, 5, 5, 207, 206, 43, + + 204, 43, 202, 200, 199, 198, 196, 194, 193, 192, + 190, 93, 189, 93, 188, 187, 186, 185, 184, 5, + 182, 5, 6, 6, 181, 180, 179, 6, 178, 176, + 175, 174, 6, 6, 173, 172, 171, 170, 169, 166, + 165, 164, 163, 162, 161, 160, 159, 158, 156, 155, + 154, 151, 150, 148, 146, 144, 6, 143, 6, 7, + 7, 7, 142, 141, 140, 139, 138, 137, 136, 7, + 7, 135, 134, 133, 132, 131, 130, 129, 128, 126, + 125, 124, 123, 122, 121, 120, 119, 116, 92, 91, + 89, 88, 87, 7, 86, 7, 8, 8, 8, 85, + + 84, 83, 82, 81, 80, 79, 8, 8, 78, 77, + 76, 75, 73, 72, 69, 67, 66, 39, 38, 36, + 35, 34, 32, 30, 28, 26, 25, 23, 20, 15, + 8, 13, 8, 50, 50, 11, 9, 0, 50, 0, + 0, 0, 0, 50, 50, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 50, 0, 50, + 58, 58, 58, 0, 0, 0, 0, 0, 0, 0, + 58, 58, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 58, 0, 58, 70, 70, 0, + 70, 0, 0, 0, 70, 70, 70, 70, 0, 70, + 70, 70, 0, 70, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 70, 100, 100, 0, 0, 0, 100, 0, 0, 0, + 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 100, 0, 100, 108, 108, + 108, 0, 0, 0, 0, 0, 0, 0, 108, 108, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 108, 0, 108, 118, 118, 0, 118, 0, + 0, 0, 118, 118, 118, 118, 0, 118, 118, 118, + 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 118, 226, + 226, 226, 226, 227, 227, 227, 227, 228, 228, 228, + 228, 229, 229, 230, 230, 230, 230, 231, 231, 231, + 231, 232, 232, 232, 232, 233, 0, 233, 233, 234, + + 0, 234, 234, 235, 235, 235, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() (yyg->yy_more_flag = 1) +#define YY_MORE_ADJ yyg->yy_more_len +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "ael.flex" +#line 2 "ael.flex" +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * 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 . + * + */#include +#include +#include + +#include "asterisk.h" +#include "asterisk/logger.h" +#include "ael.tab.h" +#include "asterisk/ael_structs.h" + +static char pbcstack[400]; +static int pbcpos = 0; + +static int parencount = 0; +static int commaout = 0; +int my_lineno = 1; +int my_col = 0; +char *my_file = 0; +char *prev_word; +#define MAX_INCLUDE_DEPTH 50 + +void reset_parencount(yyscan_t yyscanner ); +void reset_semicount(yyscan_t yyscanner ); +void reset_argcount(yyscan_t yyscanner ); +struct pval *ael2_parse(char *filename, int *errors); +int ael_yyget_column (yyscan_t yyscanner); +void ael_yyset_column (int column_no , yyscan_t yyscanner); +int ael_yyparse (void *); +static void pbcpush(char x); +static int pbcpop(char x); +static void pbcwhere(char *text, int *line, int *col ); +static int c_prevword(void); + +struct stackelement +{ + char *fname; + int lineno; + int colno; + YY_BUFFER_STATE bufstate; +}; +struct stackelement include_stack[MAX_INCLUDE_DEPTH]; +int include_stack_index = 0; + + +/* %option yylineno I've tried hard, but haven't been able to use this */ +#line 691 "ael_lex.c" + +#define INITIAL 0 +#define paren 1 +#define semic 2 +#define argg 3 + +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + + }; /* end struct yyguts_t */ + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + + # define yylloc yyg->yylloc_r + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int ael_yylex_destroy (yyscan_t yyscanner ); + +int ael_yyget_debug (yyscan_t yyscanner ); + +void ael_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE ael_yyget_extra (yyscan_t yyscanner ); + +void ael_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *ael_yyget_in (yyscan_t yyscanner ); + +void ael_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *ael_yyget_out (yyscan_t yyscanner ); + +void ael_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int ael_yyget_leng (yyscan_t yyscanner ); + +char *ael_yyget_text (yyscan_t yyscanner ); + +int ael_yyget_lineno (yyscan_t yyscanner ); + +void ael_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * ael_yyget_lval (yyscan_t yyscanner ); + +void ael_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + + YYLTYPE *ael_yyget_lloc (yyscan_t yyscanner ); + + void ael_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int ael_yywrap (yyscan_t yyscanner ); +#else +extern int ael_yywrap (yyscan_t yyscanner ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int ael_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 77 "ael.flex" + +#line 927 "ael_lex.c" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( yyg->yy_init ) + { + yyg->yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + ael_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ael_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ael_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yyg->yy_more_len = 0; + if ( yyg->yy_more_flag ) + { + yyg->yy_more_len = yyg->yy_c_buf_p - yyg->yytext_ptr; + yyg->yy_more_flag = 0; + } + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 226 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 225 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 78 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LC;} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 79 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RC;} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 80 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LP;} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 81 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RP;} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 82 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return SEMI;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 83 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EQ;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 84 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COMMA;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 85 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COLON;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 86 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AMPER;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 87 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return BAR;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 88 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EXTENMARK;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 89 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AT;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 90 "ael.flex" +{/*comment*/} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 91 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTEXT;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 92 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ABSTRACT;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 93 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_MACRO;}; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 94 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GLOBALS;} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 95 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IGNOREPAT;} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 96 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCH;} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 97 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IF;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 98 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IFTIME;} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 99 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RANDOM;} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 100 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_REGEXTEN;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 101 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_HINT;} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 102 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ELSE;} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 103 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GOTO;} + YY_BREAK +case 27: +YY_RULE_SETUP +#line 104 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_JUMP;} + YY_BREAK +case 28: +YY_RULE_SETUP +#line 105 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RETURN;} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 106 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_BREAK;} + YY_BREAK +case 30: +YY_RULE_SETUP +#line 107 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTINUE;} + YY_BREAK +case 31: +YY_RULE_SETUP +#line 108 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_FOR;} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 109 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_WHILE;} + YY_BREAK +case 33: +YY_RULE_SETUP +#line 110 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CASE;} + YY_BREAK +case 34: +YY_RULE_SETUP +#line 111 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_DEFAULT;} + YY_BREAK +case 35: +YY_RULE_SETUP +#line 112 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_PATTERN;} + YY_BREAK +case 36: +YY_RULE_SETUP +#line 113 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CATCH;} + YY_BREAK +case 37: +YY_RULE_SETUP +#line 114 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCHES;} + YY_BREAK +case 38: +YY_RULE_SETUP +#line 115 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ESWITCHES;} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 116 "ael.flex" +{yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_INCLUDES;} + YY_BREAK +case 40: +/* rule 40 can match eol */ +YY_RULE_SETUP +#line 118 "ael.flex" +{my_lineno++;my_col=0;} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 119 "ael.flex" +{/* nothing */ my_col+=yyleng;} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 120 "ael.flex" +{/* nothing */ int wid = 8-(my_col%8); my_col+=wid;} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 122 "ael.flex" +{ + yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col; /* set up the ptr */ + yylval->str = strdup(yytext); + /* printf("\nGot WORD %s[%d][%d:%d]\n", yylval->str, my_lineno ,yylloc->first_column,yylloc->last_column ); */ + my_col+=yyleng; + prev_word = yylval->str; + return word; + } + YY_BREAK +case 44: +/* rule 44 can match eol */ +YY_RULE_SETUP +#line 131 "ael.flex" +{yylloc->first_line = my_lineno; yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno+l4, c4, yytext); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + prev_word = 0; + return word; + } + parencount--; + if ( parencount >= 0) { + yymore(); + } else { + int l4,c4; + pbcwhere(yytext, &l4, &c4); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + yylval->str = strdup(yytext); + *(yylval->str+strlen(yylval->str)-1)=0; + /* printf("Got paren word %s\n", yylval->str); */ + unput(')'); + my_col=c4; + my_lineno += l4; + BEGIN(0); + return word; + } + } + YY_BREAK +case 45: +/* rule 45 can match eol */ +YY_RULE_SETUP +#line 165 "ael.flex" +{yylloc->first_line = my_lineno; yylloc->first_column=my_col; + parencount++; pbcpush('('); + yymore(); + } + YY_BREAK +case 46: +/* rule 46 can match eol */ +YY_RULE_SETUP +#line 169 "ael.flex" +{yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } + YY_BREAK +case 47: +/* rule 47 can match eol */ +YY_RULE_SETUP +#line 170 "ael.flex" +{yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + YY_BREAK +case 48: +/* rule 48 can match eol */ +YY_RULE_SETUP +#line 186 "ael.flex" +{yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{'); } + YY_BREAK +case 49: +/* rule 49 can match eol */ +YY_RULE_SETUP +#line 187 "ael.flex" +{yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + YY_BREAK +case 50: +/* rule 50 can match eol */ +YY_RULE_SETUP +#line 206 "ael.flex" +{/* printf("ARGG:%s\n",yytext); */ + int linecount = 0; + int colcount = my_col; + char *pt = yytext; + + yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + + + while (*pt) { + if (*pt == '\n') { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + parencount--; + if( parencount >= 0){ + yymore(); + } else { + yylval->str = strdup(yytext); + if(yyleng > 1 ) + *(yylval->str+yyleng-1)=0; + /* printf("Got argg word '%s'\n", yylval->str); */ + BEGIN(0); + if ( !strcmp(yylval->str,")") ) { + free(yylval->str); + yylval->str = 0; + my_col+=1; + return RP; + } else { + unput(')'); + my_col=colcount; + my_lineno+=linecount; + return word; + } + } + } + YY_BREAK +case 51: +/* rule 51 can match eol */ +YY_RULE_SETUP +#line 260 "ael.flex" +{ /* printf("ARGG:%s\n",yytext); */ + /* printf("GOT AN LP!!!\n"); */ + yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + parencount++; + pbcpush('('); + yymore(); + } + YY_BREAK +case 52: +/* rule 52 can match eol */ +YY_RULE_SETUP +#line 269 "ael.flex" +{ /* printf("ARGG:%s\n",yytext); */ + if( parencount != 0) { + /* printf("Folding in a comma!\n"); */ + yymore(); + } else { + /* printf("got a comma!\n\n"); */ + int linecount = 0; + int colcount = my_col; + char *pt; + + pt = yytext; + while (*pt) { + if ( *pt == '\n' ) { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->first_line = my_lineno; + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + yylloc->first_column=my_col; + if( !commaout ) { + if( !strcmp(yytext,"," ) ) + {commaout = 0; my_col+=1; return COMMA;} + yylval->str = strdup(yytext); /* printf("Got argg2 word %s\n", yylval->str); */ + unput(','); + commaout = 1; + if(yyleng > 1 ) + *(yylval->str+yyleng-1)=0; + my_lineno+=linecount; + my_col=colcount; + return word; + } else { + commaout = 0; + my_col+=1; + return COMMA; + } + } + } + YY_BREAK +case 53: +/* rule 53 can match eol */ +YY_RULE_SETUP +#line 311 "ael.flex" +{/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; pbcpush('{'); yymore(); } + YY_BREAK +case 54: +/* rule 54 can match eol */ +YY_RULE_SETUP +#line 312 "ael.flex" +{/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + YY_BREAK +case 55: +/* rule 55 can match eol */ +YY_RULE_SETUP +#line 328 "ael.flex" +{/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } + YY_BREAK +case 56: +/* rule 56 can match eol */ +YY_RULE_SETUP +#line 329 "ael.flex" +{/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + YY_BREAK +case 57: +/* rule 57 can match eol */ +YY_RULE_SETUP +#line 347 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } + YY_BREAK +case 58: +/* rule 58 can match eol */ +YY_RULE_SETUP +#line 348 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} + YY_BREAK +case 59: +/* rule 59 can match eol */ +YY_RULE_SETUP +#line 363 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{');} + YY_BREAK +case 60: +/* rule 60 can match eol */ +YY_RULE_SETUP +#line 364 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} + YY_BREAK +case 61: +/* rule 61 can match eol */ +YY_RULE_SETUP +#line 379 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('(');} + YY_BREAK +case 62: +/* rule 62 can match eol */ +YY_RULE_SETUP +#line 380 "ael.flex" +{/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} + YY_BREAK +case 63: +/* rule 63 can match eol */ +YY_RULE_SETUP +#line 395 "ael.flex" +{ + int linecount = 0; + int colcount = my_col; + char *pt = yytext; + while (*pt) { + if ( *pt == '\n' ) { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->first_line = my_lineno; + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + yylloc->first_column=my_col; + yylval->str = strdup(yytext); + if(yyleng > 1) + *(yylval->str+yyleng-1)=0; + /* printf("Got semic word %s\n", yylval->str); */ + unput(';'); + BEGIN(0); + my_col=colcount; + my_lineno += linecount; + return word; + } + YY_BREAK +case 64: +/* rule 64 can match eol */ +YY_RULE_SETUP +#line 422 "ael.flex" +{ + FILE *in1; + char fnamebuf[1024],*p1,*p2; + 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 { + p1 = strchr(yytext,'"'); + p2 = strrchr(yytext,'"'); + if ( (int)(p2-p1) > 1023 ) { + 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 { + int i; + int found = 0; + for (i=0; iyytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * ael_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( ael_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of ael_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + ael_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + ael_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 226 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 226 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 225); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) +{ + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_cp = yyg->yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yyg->yy_hold_char; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yyg->yy_n_chars + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + yyg->yytext_ptr = yy_bp; + yyg->yy_hold_char = *yy_cp; + yyg->yy_c_buf_p = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + ael_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( ael_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void ael_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + ael_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + ael_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + ael_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + ael_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void ael_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * ael_yypop_buffer_state(); + * ael_yypush_buffer_state(new_buffer); + */ + ael_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + ael_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (ael_yywrap()) processing, but the only time this flag + * is looked at is after ael_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void ael_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE ael_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) ael_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ael_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) ael_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in ael_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + ael_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with ael_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void ael_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + ael_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + ael_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a ael_yyrestart() or at EOF. + */ + static void ael_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + ael_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then ael_yy_init_buffer was _probably_ + * called from ael_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void ael_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + ael_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void ael_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + ael_yyensure_buffer_stack(yyscanner); + + /* This block is copied from ael_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from ael_yy_switch_to_buffer. */ + ael_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void ael_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + ael_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + ael_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void ael_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ael_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)ael_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ael_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) ael_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in ael_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + ael_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to ael_yylex() will + * scan from a @e copy of @a str. + * @param str a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * ael_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE ael_yy_scan_string (yyconst char * str , yyscan_t yyscanner) +{ + + return ael_yy_scan_bytes(str,strlen(str) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to ael_yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE ael_yy_scan_bytes (yyconst char * bytes, int len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) ael_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in ael_yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = ael_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in ael_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE ael_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int ael_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int ael_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *ael_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *ael_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int ael_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *ael_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void ael_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void ael_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ael_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void ael_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "ael_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see ael_yy_switch_to_buffer + */ +void ael_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void ael_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int ael_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void ael_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * ael_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void ael_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *ael_yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void ael_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + This function is called once per scanner lifetime. */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 1; + yyg->yy_start = 0; + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = (int *) 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * ael_yylex_init() + */ + return 0; +} + +/* User-visible API */ + +/* ael_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int ael_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) ael_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + memset(*ptr_yy_globals,0,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* ael_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int ael_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + ael_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + ael_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + ael_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + ael_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Destroy the main struct (reentrant only). */ + ael_yyfree ( yyscanner , yyscanner ); + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *ael_yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *ael_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void ael_yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see ael_yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif +#line 499 "ael.flex" + + + +static void pbcpush(char x) +{ + pbcstack[pbcpos++] = x; +} + +static int pbcpop(char x) +{ + if ( ( x == ')' && pbcstack[pbcpos-1] == '(' ) + || ( x == ']' && pbcstack[pbcpos-1] == '[' ) + || ( x == '}' && pbcstack[pbcpos-1] == '{' )) { + pbcpos--; + return 0; + } + else + return 1; /* error */ +} + +static int c_prevword(void) +{ + char *c = prev_word; + int ret = 0; + while ( c && *c ) { + switch (*c) { + case '{': pbcpush('{');break; + case '}': ret = pbcpop('}');break; + case '[':pbcpush('[');break; + case ']':ret = pbcpop(']');break; + case '(':pbcpush('(');break; + case ')':ret = pbcpop(')'); break; + } + if( ret ) + return 1; + c++; + } + return 0; +} + +static void pbcwhere(char *text, int *line, int *col ) +{ + int loc_line = 0; + int loc_col = 0; + while ( *text ) { + if ( *text == '\n' ) { + loc_line++; + loc_col = 1; + } else { + loc_col++; + } + text++; + } + *line = loc_line; + *col = loc_col; +} + +void reset_parencount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + parencount = 0; + pbcpos = 0; + pbcpush('('); + c_prevword(); + BEGIN(paren); +} + +void reset_semicount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + pbcpos = 0; + BEGIN(semic); +} + +void reset_argcount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + parencount = 0; + pbcpos = 0; + commaout = 0; + pbcpush('('); + c_prevword(); + BEGIN(argg); +} + +#ifdef NOMORE +void parse_extensions(yyscan_t scanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)scanner; + struct pval *yy; + ael_yyparse((void*)(&yy)); + printf("Done. yy->type is %d\n", yy->type); +} +#endif + +struct pval *ael2_parse(char *filename, int *errors) +{ + struct pval *pval; + struct parse_io *io; + char *buffer; + struct stat stats; + FILE *fin; + extern int ael_errcnt; + /* 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_errcnt = 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; + } + my_file = strdup(filename); + stat(filename, &stats); + buffer = (char*)malloc(stats.st_size+2); + fread(buffer, 1, stats.st_size, fin); + 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((void *) io); + + + pval = io->pval; + *errors = io->syntax_error_count; + + ael_yylex_destroy(io->scanner); + free(buffer); + free(io); + + return pval; +} + Property changes on: pbx/ael_lex.c ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/ael.tab.h =================================================================== --- pbx/ael.tab.h (.../branches/1.2) (revision 0) +++ pbx/ael.tab.h (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,146 @@ +/* A Bison parser, made by GNU Bison 1.875c. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + KW_CONTEXT = 258, + LC = 259, + RC = 260, + LP = 261, + RP = 262, + SEMI = 263, + EQ = 264, + COMMA = 265, + COLON = 266, + AMPER = 267, + BAR = 268, + AT = 269, + KW_MACRO = 270, + KW_GLOBALS = 271, + KW_IGNOREPAT = 272, + KW_SWITCH = 273, + KW_IF = 274, + KW_IFTIME = 275, + KW_ELSE = 276, + KW_RANDOM = 277, + KW_ABSTRACT = 278, + EXTENMARK = 279, + KW_GOTO = 280, + KW_JUMP = 281, + KW_RETURN = 282, + KW_BREAK = 283, + KW_CONTINUE = 284, + KW_REGEXTEN = 285, + KW_HINT = 286, + KW_FOR = 287, + KW_WHILE = 288, + KW_CASE = 289, + KW_PATTERN = 290, + KW_DEFAULT = 291, + KW_CATCH = 292, + KW_SWITCHES = 293, + KW_ESWITCHES = 294, + KW_INCLUDES = 295, + word = 296 + }; +#endif +#define KW_CONTEXT 258 +#define LC 259 +#define RC 260 +#define LP 261 +#define RP 262 +#define SEMI 263 +#define EQ 264 +#define COMMA 265 +#define COLON 266 +#define AMPER 267 +#define BAR 268 +#define AT 269 +#define KW_MACRO 270 +#define KW_GLOBALS 271 +#define KW_IGNOREPAT 272 +#define KW_SWITCH 273 +#define KW_IF 274 +#define KW_IFTIME 275 +#define KW_ELSE 276 +#define KW_RANDOM 277 +#define KW_ABSTRACT 278 +#define EXTENMARK 279 +#define KW_GOTO 280 +#define KW_JUMP 281 +#define KW_RETURN 282 +#define KW_BREAK 283 +#define KW_CONTINUE 284 +#define KW_REGEXTEN 285 +#define KW_HINT 286 +#define KW_FOR 287 +#define KW_WHILE 288 +#define KW_CASE 289 +#define KW_PATTERN 290 +#define KW_DEFAULT 291 +#define KW_CATCH 292 +#define KW_SWITCHES 293 +#define KW_ESWITCHES 294 +#define KW_INCLUDES 295 +#define word 296 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 72 "ael.y" +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +/* Line 1275 of yacc.c. */ +#line 124 "ael.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + + + Property changes on: pbx/ael.tab.h ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/argdesc.tab.c =================================================================== --- pbx/argdesc.tab.c (.../branches/1.2) (revision 0) +++ pbx/argdesc.tab.c (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,1730 @@ +/* A Bison parser, made by GNU Bison 2.0. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + +/* Substitute the variable and function names. */ +#define yyparse argdesc_yyparse +#define yylex argdesc_yylex +#define yyerror argdesc_yyerror +#define yylval argdesc_yylval +#define yychar argdesc_yychar +#define yydebug argdesc_yydebug +#define yynerrs argdesc_yynerrs +#define yylloc argdesc_yylloc + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + SEMI = 258, + COMMA = 259, + BAR = 260, + EQ = 261, + LP = 262, + RP = 263, + LB = 264, + RB = 265, + LAB = 266, + RAB = 267, + COLON = 268, + LC = 269, + RC = 270, + ELLIPSES = 271, + KW_ARGS = 272, + KW_OPTIONS = 273, + KW_CHANVARS = 274, + intspec = 275, + fltspec = 276, + strspec = 277, + word = 278, + str1 = 279 + }; +#endif +#define SEMI 258 +#define COMMA 259 +#define BAR 260 +#define EQ 261 +#define LP 262 +#define RP 263 +#define LB 264 +#define RB 265 +#define LAB 266 +#define RAB 267 +#define COLON 268 +#define LC 269 +#define RC 270 +#define ELLIPSES 271 +#define KW_ARGS 272 +#define KW_OPTIONS 273 +#define KW_CHANVARS 274 +#define intspec 275 +#define fltspec 276 +#define strspec 277 +#define word 278 +#define str1 279 + + + + +/* Copy the first part of user declarations. */ +#line 1 "argdesc.y" + +#include +#include +#include +#include "asterisk/argdesc.h" +#include "asterisk/logger.h" + +#define YYPARSE_PARAM parseio +#define YYLEX_PARAM ((struct parse_arginfo *)parseio)->scanner +#define YYERROR_VERBOSE 1 +/* this stuff is included so I can declare the proto for yyerror */ +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) + +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; + +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef union YYSTYPE { + char *str; + struct argapp *argapp; + struct argdesc *argdesc; + struct appsetvar *appsetvar; + struct argchoice *argchoice; +} YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + static int errcnt = 0; + +void yyerror(YYLTYPE *locp,void *nothing, char const *s); +int argdesc_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); +void linkarg(struct argdesc *head, struct argdesc *tail); +static void argdesc_destroy_argdesc(struct argdesc *desc); +static void argdesc_destroy_appsetvar(struct appsetvar *var); +static void argdesc_destroy_argchoice(struct argchoice *choice); +static void argdesc_destroy_argapp(struct argapp *app); + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 52 "argdesc.y" +typedef union YYSTYPE { + char *str; + struct argapp *argapp; + struct argdesc *argdesc; + struct appsetvar *appsetvar; + struct argchoice *argchoice; +} YYSTYPE; +/* Line 190 of yacc.c. */ +#line 190 "argdesc.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 213 of yacc.c. */ +#line 214 "argdesc.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# else +# define YYSTACK_ALLOC alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYLTYPE_IS_TRIVIAL) && YYLTYPE_IS_TRIVIAL \ + && defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + YYLTYPE yyls; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 66 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 25 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 16 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 37 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 71 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 279 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 5, 7, 10, 18, 19, 24, 26, + 30, 32, 36, 41, 45, 47, 50, 53, 56, 58, + 60, 66, 68, 72, 77, 78, 80, 84, 86, 90, + 96, 97, 102, 104, 108, 110, 114, 116 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 26, 0, -1, 27, -1, 28, -1, 27, 28, -1, + 23, 13, 24, 3, 29, 34, 37, -1, -1, 17, + 6, 30, 3, -1, 31, -1, 30, 5, 31, -1, + 32, -1, 9, 32, 10, -1, 9, 13, 32, 10, + -1, 14, 32, 15, -1, 23, -1, 23, 20, -1, + 23, 22, -1, 23, 21, -1, 16, -1, 18, -1, + 11, 23, 13, 33, 12, -1, 23, -1, 33, 4, + 23, -1, 18, 6, 35, 3, -1, -1, 36, -1, + 35, 4, 36, -1, 23, -1, 23, 7, 8, -1, + 23, 9, 7, 8, 10, -1, -1, 19, 6, 38, + 3, -1, 39, -1, 38, 4, 39, -1, 23, -1, + 23, 13, 40, -1, 23, -1, 40, 5, 23, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 85, 85, 88, 89, 92, 102, 103, 106, 107, + 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, + 121, 124, 125, 128, 129, 132, 133, 136, 137, 138, + 142, 143, 146, 147, 150, 151, 154, 155 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "SEMI", "COMMA", "BAR", "EQ", "LP", "RP", + "LB", "RB", "LAB", "RAB", "COLON", "LC", "RC", "ELLIPSES", "KW_ARGS", + "KW_OPTIONS", "KW_CHANVARS", "intspec", "fltspec", "strspec", "word", + "str1", "$accept", "file", "appentries", "appentry", "arglist", + "argdeclist", "argdec", "argspec", "choicelist", "optionslist", + "optionspeclist", "optionspec", "varlist", "varspeclist", "varspec", + "vallist", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 25, 26, 27, 27, 28, 29, 29, 30, 30, + 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, + 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, + 37, 37, 38, 38, 39, 39, 40, 40 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 1, 2, 7, 0, 4, 1, 3, + 1, 3, 4, 3, 1, 2, 2, 2, 1, 1, + 5, 1, 3, 4, 0, 1, 3, 1, 3, 5, + 0, 4, 1, 3, 1, 3, 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 0, 2, 3, 0, 1, 4, 0, 6, + 0, 24, 0, 0, 30, 0, 0, 0, 18, 19, + 14, 0, 8, 10, 0, 0, 5, 0, 0, 0, + 0, 15, 17, 16, 7, 0, 27, 0, 25, 0, + 0, 11, 0, 13, 9, 0, 0, 23, 0, 34, + 0, 32, 12, 21, 0, 28, 0, 26, 0, 31, + 0, 0, 20, 0, 36, 35, 33, 22, 29, 0, + 37 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 2, 3, 4, 11, 21, 22, 23, 54, 14, + 37, 38, 26, 50, 51, 65 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -13 +static const yysigned_char yypact[] = +{ + -12, 7, 26, -12, -13, 10, -13, -13, 32, 19, + 31, 21, -9, 34, 22, -10, 15, -1, -13, -13, + 3, 16, -13, -13, 23, 36, -13, -1, 33, 35, + 30, -13, -13, -13, -13, -9, 20, 27, -13, 24, + 39, -13, 28, -13, -13, 42, 37, -13, 23, 40, + 29, -13, -13, -13, 0, -13, 44, -13, 38, -13, + 24, 41, -13, 45, -13, 49, -13, -13, -13, 43, + -13 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -13, -13, -13, 53, -13, -13, 25, 1, -13, -13, + -13, 9, -13, -13, -2, -13 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 15, 16, 16, 27, 61, 17, 18, 18, 19, 19, + 16, 1, 62, 20, 20, 18, 28, 19, 30, 34, + 5, 35, 20, 31, 32, 33, 6, 45, 40, 46, + 47, 48, 59, 60, 8, 9, 10, 12, 29, 13, + 24, 25, 39, 41, 56, 43, 36, 49, 42, 52, + 55, 53, 63, 58, 69, 68, 7, 57, 66, 0, + 44, 64, 0, 0, 67, 0, 70 +}; + +static const yysigned_char yycheck[] = +{ + 9, 11, 11, 13, 4, 14, 16, 16, 18, 18, + 11, 23, 12, 23, 23, 16, 15, 18, 17, 3, + 13, 5, 23, 20, 21, 22, 0, 7, 27, 9, + 3, 4, 3, 4, 24, 3, 17, 6, 23, 18, + 6, 19, 6, 10, 7, 15, 23, 23, 13, 10, + 8, 23, 8, 13, 5, 10, 3, 48, 60, -1, + 35, 23, -1, -1, 23, -1, 23 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 23, 26, 27, 28, 13, 0, 28, 24, 3, + 17, 29, 6, 18, 34, 9, 11, 14, 16, 18, + 23, 30, 31, 32, 6, 19, 37, 13, 32, 23, + 32, 20, 21, 22, 3, 5, 23, 35, 36, 6, + 32, 10, 13, 15, 31, 7, 9, 3, 4, 23, + 38, 39, 10, 23, 33, 8, 7, 36, 13, 3, + 4, 4, 12, 8, 23, 40, 39, 23, 10, 5, + 23 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, NULL, "syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep, yylocationp) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + (void) yylocationp; + + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + fprintf (yyoutput, ": "); + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, yylocationp) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + (void) yylocationp; + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *NULL); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void *NULL) +#else +int +yyparse (NULL) + void *NULL; +#endif +#endif +{ + /* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; +/* Location data for the look-ahead symbol. */ +YYLTYPE yylloc; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; +#if YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 0; +#endif + + + yyvsp[0] = yylval; + yylsp[0] = yylloc; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + YYSTACK_RELOCATE (yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a look-ahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to look-ahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + *++yylsp = yylloc; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, yylsp - yylen, yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 85 "argdesc.y" + {((struct parse_arginfo *)parseio)->apps = (yyval.argapp); ((struct parse_arginfo *)parseio)->syntax_error_count = errcnt;;} + break; + + case 3: +#line 88 "argdesc.y" + {(yyval.argapp)=(yyvsp[0].argapp);;} + break; + + case 4: +#line 89 "argdesc.y" + {(yyvsp[0].argapp)->next = (yyvsp[-1].argapp); (yyval.argapp) = (yyvsp[0].argapp); ;} + break; + + case 5: +#line 92 "argdesc.y" + { + (yyval.argapp)=(struct argapp *)calloc(sizeof(struct argapp),1); + (yyval.argapp)->name = (yyvsp[-6].str); + (yyval.argapp)->desc = (yyvsp[-4].str); + (yyval.argapp)->args = (yyvsp[-2].argdesc); + (yyval.argapp)->opts = (yyvsp[-1].argchoice); + (yyval.argapp)->setvars = (yyvsp[0].appsetvar); + ;} + break; + + case 6: +#line 102 "argdesc.y" + {(yyval.argdesc)=0;;} + break; + + case 7: +#line 103 "argdesc.y" + {(yyval.argdesc)=(yyvsp[-1].argdesc);;} + break; + + case 8: +#line 106 "argdesc.y" + {(yyval.argdesc)=(yyvsp[0].argdesc);;} + break; + + case 9: +#line 107 "argdesc.y" + {(yyval.argdesc)=(yyvsp[-2].argdesc); linkarg((yyval.argdesc),(yyvsp[0].argdesc));;} + break; + + case 10: +#line 110 "argdesc.y" + {(yyval.argdesc)=(yyvsp[0].argdesc); (yyval.argdesc)->type=ARGD_REQUIRED;;} + break; + + case 11: +#line 111 "argdesc.y" + {(yyval.argdesc)=(yyvsp[-1].argdesc); (yyval.argdesc)->type=ARGD_OPTIONAL;;} + break; + + case 12: +#line 112 "argdesc.y" + {(yyval.argdesc)=(yyvsp[-1].argdesc); (yyval.argdesc)->type=ARGD_OPTIONAL_PREV;;} + break; + + case 13: +#line 113 "argdesc.y" + {(yyval.argdesc)=(yyvsp[-1].argdesc); (yyval.argdesc)->type=ARGD_OPTIONAL_PLACEHOLD;;} + break; + + case 14: +#line 115 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=(yyvsp[0].str);(yyval.argdesc)->dtype=ARGD_STRING;;} + break; + + case 15: +#line 116 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=(yyvsp[-1].str); (yyval.argdesc)->dtype=ARGD_INT;;} + break; + + case 16: +#line 117 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=(yyvsp[-1].str);(yyval.argdesc)->dtype=ARGD_STRING;;} + break; + + case 17: +#line 118 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=(yyvsp[-1].str);(yyval.argdesc)->dtype=ARGD_FLOAT;;} + break; + + case 18: +#line 119 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=0;(yyval.argdesc)->dtype=ARGD_VARARG;;} + break; + + case 19: +#line 120 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=0;(yyval.argdesc)->dtype=ARGD_OPTIONSET;;} + break; + + case 20: +#line 121 "argdesc.y" + {(yyval.argdesc)=(struct argdesc*)calloc(sizeof(struct argdesc),1); (yyval.argdesc)->name=(yyvsp[-3].str);(yyval.argdesc)->dtype=ARGD_ENUM;(yyval.argdesc)->choices = (yyvsp[-1].argchoice);;} + break; + + case 21: +#line 124 "argdesc.y" + {(yyval.argchoice)=(struct argchoice*)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[0].str);;} + break; + + case 22: +#line 125 "argdesc.y" + {(yyval.argchoice)=(struct argchoice*)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[0].str); (yyval.argchoice)->next = (yyvsp[-2].argchoice);;} + break; + + case 23: +#line 128 "argdesc.y" + {(yyval.argchoice)=(yyvsp[-1].argchoice);;} + break; + + case 24: +#line 129 "argdesc.y" + {(yyval.argchoice)=0;;} + break; + + case 25: +#line 132 "argdesc.y" + {(yyval.argchoice)=(yyvsp[0].argchoice);;} + break; + + case 26: +#line 133 "argdesc.y" + {(yyval.argchoice)=(yyvsp[0].argchoice); (yyvsp[0].argchoice)->next = (yyvsp[-2].argchoice); ;} + break; + + case 27: +#line 136 "argdesc.y" + {(yyval.argchoice) = (struct argchoice *)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[0].str); (yyval.argchoice)->opttype=ARGD_OPT_NOARG;;} + break; + + case 28: +#line 137 "argdesc.y" + {(yyval.argchoice) = (struct argchoice *)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[-2].str); (yyval.argchoice)->opttype=ARGD_OPT_WITHARG;;} + break; + + case 29: +#line 138 "argdesc.y" + {(yyval.argchoice) = (struct argchoice *)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[-4].str); (yyval.argchoice)->opttype=ARGD_OPT_WITHOPTARG;;} + break; + + case 30: +#line 142 "argdesc.y" + {(yyval.appsetvar)=0;;} + break; + + case 31: +#line 143 "argdesc.y" + {(yyval.appsetvar)=(yyvsp[-1].appsetvar);;} + break; + + case 32: +#line 146 "argdesc.y" + {(yyval.appsetvar)=(yyvsp[0].appsetvar);;} + break; + + case 33: +#line 147 "argdesc.y" + {(yyval.appsetvar) = (yyvsp[0].appsetvar); (yyval.appsetvar)->next = (yyvsp[-2].appsetvar);;} + break; + + case 34: +#line 150 "argdesc.y" + {(yyval.appsetvar)=(struct appsetvar*)calloc(sizeof(struct appsetvar),1); (yyval.appsetvar)->name=(yyvsp[0].str);;} + break; + + case 35: +#line 151 "argdesc.y" + {(yyval.appsetvar)=(struct appsetvar*)calloc(sizeof(struct appsetvar),1); (yyval.appsetvar)->name=(yyvsp[-2].str); (yyval.appsetvar)->vals=(yyvsp[0].argchoice);;} + break; + + case 36: +#line 154 "argdesc.y" + {(yyval.argchoice)=(struct argchoice*)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[0].str); ;} + break; + + case 37: +#line 155 "argdesc.y" + {(yyval.argchoice)=(struct argchoice*)calloc(sizeof(struct argchoice),1); (yyval.argchoice)->name=(yyvsp[0].str); (yyval.argchoice)->next = (yyvsp[-2].argchoice); ;} + break; + + + } + +/* Line 1037 of yacc.c. */ +#line 1385 "argdesc.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + yylsp -= yylen; + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (&yylloc, NULL, yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror (&yylloc, NULL, "syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (&yylloc, NULL, "syntax error"); + } + + yyerror_range[0] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + yyerror_range[0] = *yylsp; + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp, yylsp); + } + } + else + { + yydestruct ("Error: discarding", yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + + yyerror_range[0] = yylsp[1-yylen]; + yylsp -= yylen; + yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the look-ahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, yyerror_range - 1, 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror (&yylloc, NULL, "parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 159 "argdesc.y" + + +void yyerror(YYLTYPE *locp, void *nothing, char const *s) +{ + + if (locp->first_line == locp->last_line) { + ast_log(LOG_ERROR, "==== Line %d, Cols: %d-%d: Error: %s\n", locp->first_line, locp->first_column, locp->last_column, s); + } else { + ast_log(LOG_ERROR, "==== Line %d Col %d to Line %d Col %d: Error: %s\n", locp->first_line, locp->first_column, locp->last_line, locp->last_column, s); + } + errcnt++; +} + +void linkarg(struct argdesc *head, struct argdesc *tail) +{ + if (!head->next) { + head->next = tail; + head->last_args = tail; + } else { + head->last_args->next = tail; + head->last_args = tail; + } +} + +static void argdesc_destroy_argdesc(struct argdesc *desc) +{ + struct argchoice *c, *cn; + if (desc->name) + free(desc->name); + for(c=desc->choices; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + desc->name = 0; + desc->choices = 0; + desc->next = 0; + free(desc); +} + +static void argdesc_destroy_appsetvar(struct appsetvar *var) +{ + struct argchoice *c, *cn; + if (var->name) + free(var->name); + for (c=var->vals; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + var->name = 0; + var->vals = 0; + var->next = 0; + free(var); +} + +static void argdesc_destroy_argchoice(struct argchoice *choice) +{ + if( choice->name ) + free( choice->name); + choice->name = 0; + choice->next = 0; + free(choice); +} + + +static void argdesc_destroy_argapp(struct argapp *app) +{ + struct argdesc *d,*dn; + struct appsetvar *v, *vn; + struct argchoice *c, *cn; + + for (d=app->args; d; ) { + dn = d->next; + argdesc_destroy_argdesc(d); + d = dn; + } + for (v=app->setvars; v;) { + vn = v->next; + argdesc_destroy_appsetvar(v); + v = vn; + } + for(c=app->opts; c;) { + cn = c->next; + argdesc_destroy_argchoice(c); + c = cn; + } + if (app->name) + free(app->name); + if (app->desc) + free(app->desc); + app->name = 0; + app->desc = 0; + app->next = 0; + app->args = 0; + app->setvars = 0; + app->opts = 0; + free(app); +} + +void argdesc_destroy(struct argapp *apps) +{ + struct argapp *p,*pn; + + for (p=apps; p; ) { + pn = p->next; + argdesc_destroy_argapp(p); + p = pn; + } +} + Property changes on: pbx/argdesc.tab.c ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/ael.flex =================================================================== --- pbx/ael.flex (.../branches/1.2) (revision 0) +++ pbx/ael.flex (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,642 @@ +%{ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * 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 . + * + */#include +#include +#include + +#include "asterisk.h" +#include "asterisk/logger.h" +#include "ael.tab.h" +#include "asterisk/ael_structs.h" + +static char pbcstack[400]; +static int pbcpos = 0; + +static int parencount = 0; +static int commaout = 0; +int my_lineno = 1; +int my_col = 0; +char *my_file = 0; +char *prev_word; +#define MAX_INCLUDE_DEPTH 50 + +void reset_parencount(yyscan_t yyscanner ); +void reset_semicount(yyscan_t yyscanner ); +void reset_argcount(yyscan_t yyscanner ); +struct pval *ael2_parse(char *filename, int *errors); +int ael_yyget_column (yyscan_t yyscanner); +void ael_yyset_column (int column_no , yyscan_t yyscanner); +int ael_yyparse (void *); +static void pbcpush(char x); +static int pbcpop(char x); +static void pbcwhere(char *text, int *line, int *col ); +static int c_prevword(void); + +struct stackelement +{ + char *fname; + int lineno; + int colno; + YY_BUFFER_STATE bufstate; +}; +struct stackelement include_stack[MAX_INCLUDE_DEPTH]; +int include_stack_index = 0; + +%} + +%x paren semic argg +%option prefix="ael_yy" +%option batch +%option outfile="ael_lex.c" +%option reentrant +%option bison-bridge +%option bison-locations +/* %option yylineno I've tried hard, but haven't been able to use this */ +%option noyywrap + +%% +\{ {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LC;} +\} {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RC;} +\( {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return LP;} +\) {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return RP;} +\; {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return SEMI;} +\= {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EQ;} +\, {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COMMA;} +\: {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return COLON;} +\& {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AMPER;} +\| {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return BAR;} +\=\> {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return EXTENMARK;} +\@ {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return AT;} +\/\/[^\n]* {/*comment*/} +context {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTEXT;} +abstract {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ABSTRACT;} +macro {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_MACRO;}; +globals {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GLOBALS;} +ignorepat {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IGNOREPAT;} +switch {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCH;} +if {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IF;} +ifTime {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_IFTIME;} +random {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RANDOM;} +regexten {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_REGEXTEN;} +hint {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_HINT;} +else {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ELSE;} +goto {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_GOTO;} +jump {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_JUMP;} +return {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_RETURN;} +break {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_BREAK;} +continue {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CONTINUE;} +for {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_FOR;} +while {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_WHILE;} +case {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CASE;} +default {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_DEFAULT;} +pattern {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_PATTERN;} +catch {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_CATCH;} +switches {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_SWITCHES;} +eswitches {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_ESWITCHES;} +includes {yylloc->first_line = yylloc->last_line = my_lineno; yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col;my_col+=yyleng;return KW_INCLUDES;} + +\n {my_lineno++;my_col=0;} +[ ]+ {/* nothing */ my_col+=yyleng;} +[ ]+ {/* nothing */ int wid = 8-(my_col%8); my_col+=wid;} + +[-a-zA-Z0-9'"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9'"_/.!\*\+\<\>\{\}$#\[\]]* { + yylloc->first_line = yylloc->last_line = my_lineno;yylloc->last_column=my_col+yyleng-1; yylloc->first_column=my_col; /* set up the ptr */ + yylval->str = strdup(yytext); + /* printf("\nGot WORD %s[%d][%d:%d]\n", yylval->str, my_lineno ,yylloc->first_column,yylloc->last_column ); */ + my_col+=yyleng; + prev_word = yylval->str; + return word; + } + +[^()\[\]\{\}]*\) {yylloc->first_line = my_lineno; yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression: %s !\n", my_file, my_lineno+l4, c4, yytext); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + prev_word = 0; + return word; + } + parencount--; + if ( parencount >= 0) { + yymore(); + } else { + int l4,c4; + pbcwhere(yytext, &l4, &c4); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + yylval->str = strdup(yytext); + *(yylval->str+strlen(yylval->str)-1)=0; + /* printf("Got paren word %s\n", yylval->str); */ + unput(')'); + my_col=c4; + my_lineno += l4; + BEGIN(0); + return word; + } + } + +[^()\[\]\{\}]*\( {yylloc->first_line = my_lineno; yylloc->first_column=my_col; + parencount++; pbcpush('('); + yymore(); + } +[^()\[\]\{\}]*\[ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +[^()\[\]\{\}]*\] {yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } +[^()\[\]\{\}]*\{ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{'); } +[^()\[\]\{\}]*\} {yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + + +[^(),\{\}\[\]]*\) {/* printf("ARGG:%s\n",yytext); */ + int linecount = 0; + int colcount = my_col; + char *pt = yytext; + + yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + + + while (*pt) { + if (*pt == '\n') { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + parencount--; + if( parencount >= 0){ + yymore(); + } else { + yylval->str = strdup(yytext); + if(yyleng > 1 ) + *(yylval->str+yyleng-1)=0; + /* printf("Got argg word '%s'\n", yylval->str); */ + BEGIN(0); + if ( !strcmp(yylval->str,")") ) { + free(yylval->str); + yylval->str = 0; + my_col+=1; + return RP; + } else { + unput(')'); + my_col=colcount; + my_lineno+=linecount; + return word; + } + } + } +[^(),\{\}\[\]]*\( { /* printf("ARGG:%s\n",yytext); */ + /* printf("GOT AN LP!!!\n"); */ + yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + parencount++; + pbcpush('('); + yymore(); + } + +[^(),\{\}\[\]]*\, { /* printf("ARGG:%s\n",yytext); */ + if( parencount != 0) { + /* printf("Folding in a comma!\n"); */ + yymore(); + } else { + /* printf("got a comma!\n\n"); */ + int linecount = 0; + int colcount = my_col; + char *pt; + + pt = yytext; + while (*pt) { + if ( *pt == '\n' ) { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->first_line = my_lineno; + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + yylloc->first_column=my_col; + if( !commaout ) { + if( !strcmp(yytext,"," ) ) + {commaout = 0; my_col+=1; return COMMA;} + yylval->str = strdup(yytext); /* printf("Got argg2 word %s\n", yylval->str); */ + unput(','); + commaout = 1; + if(yyleng > 1 ) + *(yylval->str+yyleng-1)=0; + my_lineno+=linecount; + my_col=colcount; + return word; + } else { + commaout = 0; + my_col+=1; + return COMMA; + } + } + } + +[^(),\{\}\[\]]*\{ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; pbcpush('{'); yymore(); } +[^(),\{\}\[\]]*\} {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } +[^(),\{\}\[\]]*\[ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +[^(),\{\}\[\]]*\] {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore(); + } + + +[^;()\{\}\[\]]*\[ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +[^;()\{\}\[\]]*\] {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(']') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ']' in expression!\n", my_file, my_lineno+l4, c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} +[^;()\{\}\[\]]*\{ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{');} +[^;()\{\}\[\]]*\} {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop('}') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched '}' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} +[^;()\{\}\[\]]*\( {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('(');} +[^;()\{\}\[\]]*\) {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; + if ( pbcpop(')') ) { + /* error */ + int l4,c4; + pbcwhere(yytext, &l4, &c4); + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Mismatched ')' in expression!\n", my_file, my_lineno+l4, my_col+c4); + BEGIN(0); + yylloc->last_line = my_lineno+l4; + yylloc->last_column=my_col+c4; + my_col=c4; + my_lineno += l4; + yylval->str = strdup(yytext); + return word; + } + yymore();} +[^;()\{\}\[\]]*; { + int linecount = 0; + int colcount = my_col; + char *pt = yytext; + while (*pt) { + if ( *pt == '\n' ) { + linecount++; + colcount=0; + } + pt++; + colcount++; + } + yylloc->first_line = my_lineno; + yylloc->last_line = my_lineno+linecount; + yylloc->last_column=colcount; + yylloc->first_column=my_col; + yylval->str = strdup(yytext); + if(yyleng > 1) + *(yylval->str+yyleng-1)=0; + /* printf("Got semic word %s\n", yylval->str); */ + unput(';'); + BEGIN(0); + my_col=colcount; + my_lineno += linecount; + return word; + } + +\#include[ \t]+\"[^\"]+\" { + FILE *in1; + char fnamebuf[1024],*p1,*p2; + 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 { + p1 = strchr(yytext,'"'); + p2 = strrchr(yytext,'"'); + if ( (int)(p2-p1) > 1023 ) { + 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 { + int i; + int found = 0; + for (i=0; i> { + if ( --include_stack_index < 0 ) { + yyterminate(); + } else { + free(my_file); + 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 = include_stack[include_stack_index].fname; + } + } + + +%% + +static void pbcpush(char x) +{ + pbcstack[pbcpos++] = x; +} + +static int pbcpop(char x) +{ + if ( ( x == ')' && pbcstack[pbcpos-1] == '(' ) + || ( x == ']' && pbcstack[pbcpos-1] == '[' ) + || ( x == '}' && pbcstack[pbcpos-1] == '{' )) { + pbcpos--; + return 0; + } + else + return 1; /* error */ +} + +static int c_prevword(void) +{ + char *c = prev_word; + int ret = 0; + while ( c && *c ) { + switch (*c) { + case '{': pbcpush('{');break; + case '}': ret = pbcpop('}');break; + case '[':pbcpush('[');break; + case ']':ret = pbcpop(']');break; + case '(':pbcpush('(');break; + case ')':ret = pbcpop(')'); break; + } + if( ret ) + return 1; + c++; + } + return 0; +} + +static void pbcwhere(char *text, int *line, int *col ) +{ + int loc_line = 0; + int loc_col = 0; + while ( *text ) { + if ( *text == '\n' ) { + loc_line++; + loc_col = 1; + } else { + loc_col++; + } + text++; + } + *line = loc_line; + *col = loc_col; +} + +void reset_parencount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + parencount = 0; + pbcpos = 0; + pbcpush('('); + c_prevword(); + BEGIN(paren); +} + +void reset_semicount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + pbcpos = 0; + BEGIN(semic); +} + +void reset_argcount(yyscan_t yyscanner ) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + parencount = 0; + pbcpos = 0; + commaout = 0; + pbcpush('('); + c_prevword(); + BEGIN(argg); +} + +#ifdef NOMORE +void parse_extensions(yyscan_t scanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)scanner; + struct pval *yy; + ael_yyparse((void*)(&yy)); + printf("Done. yy->type is %d\n", yy->type); +} +#endif + +struct pval *ael2_parse(char *filename, int *errors) +{ + struct pval *pval; + struct parse_io *io; + char *buffer; + struct stat stats; + FILE *fin; + extern int ael_errcnt; + /* 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_errcnt = 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; + } + my_file = strdup(filename); + stat(filename, &stats); + buffer = (char*)malloc(stats.st_size+2); + fread(buffer, 1, stats.st_size, fin); + 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((void *) io); + + + pval = io->pval; + *errors = io->syntax_error_count; + + ael_yylex_destroy(io->scanner); + free(buffer); + free(io); + + return pval; +} Property changes on: pbx/ael.flex ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/argdesc_lex.c =================================================================== --- pbx/argdesc_lex.c (.../branches/1.2) (revision 0) +++ pbx/argdesc_lex.c (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,2141 @@ +#line 2 "argdesc_lex.c" + +#line 4 "argdesc_lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 31 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +int argdesc_yylex_init (yyscan_t* scanner); + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE argdesc_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE argdesc_yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via argdesc_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void argdesc_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void argdesc_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE argdesc_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void argdesc_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void argdesc_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void argdesc_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void argdesc_yypop_buffer_state (yyscan_t yyscanner ); + +static void argdesc_yyensure_buffer_stack (yyscan_t yyscanner ); +static void argdesc_yy_load_buffer_state (yyscan_t yyscanner ); +static void argdesc_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER argdesc_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE argdesc_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE argdesc_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE argdesc_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *argdesc_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *argdesc_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void argdesc_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer argdesc_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + argdesc_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + argdesc_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + argdesc_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + argdesc_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define argdesc_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 26 +#define YY_END_OF_BUFFER 27 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[55] = + { 0, + 19, 19, 27, 26, 25, 23, 24, 26, 26, 19, + 3, 4, 11, 26, 12, 9, 7, 10, 8, 19, + 5, 6, 19, 19, 1, 13, 2, 25, 24, 0, + 18, 21, 20, 22, 19, 0, 19, 19, 19, 14, + 19, 19, 19, 19, 16, 19, 19, 19, 19, 19, + 19, 15, 17, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 6, 1, 1, 7, 1, 8, + 9, 1, 1, 10, 7, 11, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 12, 13, 14, + 15, 16, 7, 1, 7, 7, 17, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 18, 1, 19, 1, 7, 1, 20, 7, 7, 7, + + 7, 21, 22, 23, 24, 7, 7, 7, 7, 25, + 26, 27, 7, 28, 29, 30, 7, 31, 7, 7, + 7, 7, 32, 33, 34, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[35] = + { 0, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[57] = + { 0, + 0, 0, 65, 66, 62, 66, 59, 57, 14, 0, + 66, 66, 66, 50, 66, 66, 66, 66, 66, 37, + 66, 66, 31, 31, 66, 66, 66, 55, 52, 50, + 66, 66, 66, 66, 0, 43, 33, 30, 21, 66, + 25, 20, 24, 16, 0, 20, 22, 16, 12, 10, + 8, 0, 0, 66, 43, 34 + } ; + +static yyconst flex_int16_t yy_def[57] = + { 0, + 54, 1, 54, 54, 54, 54, 54, 55, 54, 56, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 56, + 54, 54, 56, 56, 54, 54, 54, 54, 54, 55, + 54, 54, 54, 54, 56, 54, 56, 56, 56, 54, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 0, 54, 54 + } ; + +static yyconst flex_int16_t yy_nxt[101] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 10, 10, 10, 10, 10, 24, 10, 10, 10, 10, + 10, 25, 26, 27, 32, 35, 53, 33, 52, 51, + 50, 49, 34, 30, 30, 48, 47, 46, 45, 44, + 43, 42, 41, 40, 31, 29, 28, 39, 38, 37, + 36, 31, 29, 28, 54, 3, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54 + + } ; + +static yyconst flex_int16_t yy_chk[101] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 56, 51, 9, 50, 49, + 48, 47, 9, 55, 55, 46, 44, 43, 42, 41, + 39, 38, 37, 36, 30, 29, 28, 24, 23, 20, + 14, 8, 7, 5, 3, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54 + + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[27] = + { 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, }; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "argdesc.l" +#line 2 "argdesc.l" +#include +#include +#include + +#include "asterisk/logger.h" +#include "argdesc.tab.h" +#include "asterisk/argdesc.h" +struct argapp *argdesc_parse(char *filename, int *errors); +int argdesc_my_lineno = 1; +int argdesc_my_col = 0; +int argdesc_yyget_column (yyscan_t yyscanner); +void argdesc_yyset_column (int column_no , yyscan_t yyscanner); +int argdesc_yyparse (void *); +#line 497 "argdesc_lex.c" + +#define INITIAL 0 + +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + + }; /* end struct yyguts_t */ + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + + # define yylloc yyg->yylloc_r + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int argdesc_yylex_destroy (yyscan_t yyscanner ); + +int argdesc_yyget_debug (yyscan_t yyscanner ); + +void argdesc_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE argdesc_yyget_extra (yyscan_t yyscanner ); + +void argdesc_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *argdesc_yyget_in (yyscan_t yyscanner ); + +void argdesc_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *argdesc_yyget_out (yyscan_t yyscanner ); + +void argdesc_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int argdesc_yyget_leng (yyscan_t yyscanner ); + +char *argdesc_yyget_text (yyscan_t yyscanner ); + +int argdesc_yyget_lineno (yyscan_t yyscanner ); + +void argdesc_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * argdesc_yyget_lval (yyscan_t yyscanner ); + +void argdesc_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + + YYLTYPE *argdesc_yyget_lloc (yyscan_t yyscanner ); + + void argdesc_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int argdesc_yywrap (yyscan_t yyscanner ); +#else +extern int argdesc_yywrap (yyscan_t yyscanner ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int argdesc_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner); + +#define YY_DECL int argdesc_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 25 "argdesc.l" + +#line 730 "argdesc_lex.c" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( yyg->yy_init ) + { + yyg->yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + argdesc_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + argdesc_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + argdesc_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 55 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 54 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + int yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + } + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 26 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LC;} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 27 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RC;} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 28 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LP;} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 29 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RP;} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 30 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LB;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 31 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RB;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 32 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LAB;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 33 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RAB;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 34 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return SEMI;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 35 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return EQ;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 36 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return COMMA;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 37 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return COLON;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 38 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return BAR;} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 39 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return ELLIPSES;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 40 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_OPTIONS;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 41 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_ARGS;} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 42 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_CHANVARS;} + YY_BREAK +case 18: +/* rule 18 can match eol */ +YY_RULE_SETUP +#line 44 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno;yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col; yylval->str = strdup(yytext);argdesc_my_col+=yyleng; return str1;} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 45 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno;yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col; yylval->str = strdup(yytext);argdesc_my_col+=yyleng; return word;} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 47 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return intspec;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 48 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return fltspec;} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 49 "argdesc.l" +{yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return strspec;} + YY_BREAK +case 23: +/* rule 23 can match eol */ +YY_RULE_SETUP +#line 51 "argdesc.l" +{argdesc_my_lineno++;argdesc_my_col=0;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 52 "argdesc.l" +{/* nothing */ argdesc_my_col+=yyleng;} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 53 "argdesc.l" +{/* nothing */ int wid = 8-(argdesc_my_col%8); argdesc_my_col+=wid;} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 55 "argdesc.l" +ECHO; + YY_BREAK +#line 957 "argdesc_lex.c" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * argdesc_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( argdesc_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of argdesc_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + argdesc_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + argdesc_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 55 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 55 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 54); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner) +{ + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_cp = yyg->yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yyg->yy_hold_char; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yyg->yy_n_chars + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + if ( c == '\n' ){ + --yylineno; + } + + yyg->yytext_ptr = yy_bp; + yyg->yy_hold_char = *yy_cp; + yyg->yy_c_buf_p = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + argdesc_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( argdesc_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + if ( c == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void argdesc_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + argdesc_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + argdesc_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + argdesc_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + argdesc_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void argdesc_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * argdesc_yypop_buffer_state(); + * argdesc_yypush_buffer_state(new_buffer); + */ + argdesc_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + argdesc_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (argdesc_yywrap()) processing, but the only time this flag + * is looked at is after argdesc_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void argdesc_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE argdesc_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) argdesc_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in argdesc_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) argdesc_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in argdesc_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + argdesc_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with argdesc_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void argdesc_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + argdesc_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + argdesc_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a argdesc_yyrestart() or at EOF. + */ + static void argdesc_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + argdesc_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then argdesc_yy_init_buffer was _probably_ + * called from argdesc_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void argdesc_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + argdesc_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void argdesc_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + argdesc_yyensure_buffer_stack(yyscanner); + + /* This block is copied from argdesc_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from argdesc_yy_switch_to_buffer. */ + argdesc_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void argdesc_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + argdesc_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + argdesc_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void argdesc_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)argdesc_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)argdesc_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE argdesc_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) argdesc_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in argdesc_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + argdesc_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to argdesc_yylex() will + * scan from a @e copy of @a str. + * @param str a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * argdesc_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE argdesc_yy_scan_string (yyconst char * str , yyscan_t yyscanner) +{ + + return argdesc_yy_scan_bytes(str,strlen(str) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to argdesc_yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE argdesc_yy_scan_bytes (yyconst char * bytes, int len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) argdesc_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in argdesc_yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = argdesc_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in argdesc_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE argdesc_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int argdesc_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int argdesc_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *argdesc_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *argdesc_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int argdesc_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *argdesc_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void argdesc_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void argdesc_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "argdesc_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void argdesc_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "argdesc_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see argdesc_yy_switch_to_buffer + */ +void argdesc_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void argdesc_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int argdesc_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void argdesc_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * argdesc_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void argdesc_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *argdesc_yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void argdesc_yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + This function is called once per scanner lifetime. */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 1; + yyg->yy_start = 0; + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = (int *) 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * argdesc_yylex_init() + */ + return 0; +} + +/* User-visible API */ + +/* argdesc_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int argdesc_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) argdesc_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + memset(*ptr_yy_globals,0,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* argdesc_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int argdesc_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + argdesc_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + argdesc_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + argdesc_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + argdesc_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Destroy the main struct (reentrant only). */ + argdesc_yyfree ( yyscanner , yyscanner ); + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *argdesc_yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *argdesc_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void argdesc_yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see argdesc_yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif +#line 55 "argdesc.l" + + + +struct argapp *argdesc_parse(char *filename, int *errors) +{ + struct argapp *apps; + struct parse_arginfo *io; + FILE *fin; + io = calloc(sizeof(struct parse_arginfo),1); + fin = fopen(filename,"r"); + if (!fin) { + ast_log(LOG_ERROR,"File %s could not be opened\n", filename); + free(io); + return 0; + } + argdesc_yylex_init(&io->scanner); + + /* other way argdesc_yy_scan_string (buffer ,io->scanner); */ + + argdesc_yyset_in (fin , io->scanner); + + argdesc_yyparse ((void *) io); + + fclose(fin); + + apps = io->apps; + *errors = io->syntax_error_count; + + argdesc_yylex_destroy(io->scanner); + + free(io); + + return apps; +} + + Property changes on: pbx/argdesc_lex.c ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/argdesc.l =================================================================== --- pbx/argdesc.l (.../branches/1.2) (revision 0) +++ pbx/argdesc.l (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,88 @@ +%{ +#include +#include +#include + +#include "asterisk/logger.h" +#include "argdesc.tab.h" +#include "asterisk/argdesc.h" +struct argapp *argdesc_parse(char *filename, int *errors); +int argdesc_my_lineno = 1; +int argdesc_my_col = 0; +int argdesc_yyget_column (yyscan_t yyscanner); +void argdesc_yyset_column (int column_no , yyscan_t yyscanner); +int argdesc_yyparse (void *); +%} +%option prefix="argdesc_yy" +%option batch +%option outfile="argdesc_lex.c" +%option reentrant +%option bison-bridge +%option bison-locations +%option yylineno +%option noyywrap + +%% +\{ {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LC;} +\} {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RC;} +\( {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LP;} +\) {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RP;} +\[ {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LB;} +\] {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RB;} +\< {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return LAB;} +\> {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return RAB;} +\; {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return SEMI;} +\= {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return EQ;} +\, {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return COMMA;} +\: {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return COLON;} +\| {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return BAR;} +\.\.\. {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return ELLIPSES;} +options {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_OPTIONS;} +args {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_ARGS;} +Chanvars {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return KW_CHANVARS;} + +\"[^"]*\" {yylloc->first_line = yylloc->last_line = argdesc_my_lineno;yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col; yylval->str = strdup(yytext);argdesc_my_col+=yyleng; return str1;} +[-A-Za-z0-9_&/?]* {yylloc->first_line = yylloc->last_line = argdesc_my_lineno;yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col; yylval->str = strdup(yytext);argdesc_my_col+=yyleng; return word;} + +\#i {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return intspec;} +\#f {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return fltspec;} +\#s {yylloc->first_line = yylloc->last_line = argdesc_my_lineno; yylloc->last_column=argdesc_my_col+yyleng-1; yylloc->first_column=argdesc_my_col;argdesc_my_col+=yyleng;return strspec;} + +\n {argdesc_my_lineno++;argdesc_my_col=0;} +[ ]+ {/* nothing */ argdesc_my_col+=yyleng;} +[ ]+ {/* nothing */ int wid = 8-(argdesc_my_col%8); argdesc_my_col+=wid;} + +%% + +struct argapp *argdesc_parse(char *filename, int *errors) +{ + struct argapp *apps; + struct parse_arginfo *io; + FILE *fin; + io = calloc(sizeof(struct parse_arginfo),1); + fin = fopen(filename,"r"); + if (!fin) { + ast_log(LOG_ERROR,"File %s could not be opened\n", filename); + free(io); + return 0; + } + argdesc_yylex_init(&io->scanner); + + /* other way argdesc_yy_scan_string (buffer ,io->scanner); */ + + argdesc_yyset_in (fin , io->scanner); + + argdesc_yyparse ((void *) io); + + fclose(fin); + + apps = io->apps; + *errors = io->syntax_error_count; + + argdesc_yylex_destroy(io->scanner); + + free(io); + + return apps; +} + Property changes on: pbx/argdesc.l ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/argdesc.tab.h =================================================================== --- pbx/argdesc.tab.h (.../branches/1.2) (revision 0) +++ pbx/argdesc.tab.h (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,115 @@ +/* A Bison parser, made by GNU Bison 2.0. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + SEMI = 258, + COMMA = 259, + BAR = 260, + EQ = 261, + LP = 262, + RP = 263, + LB = 264, + RB = 265, + LAB = 266, + RAB = 267, + COLON = 268, + LC = 269, + RC = 270, + ELLIPSES = 271, + KW_ARGS = 272, + KW_OPTIONS = 273, + KW_CHANVARS = 274, + intspec = 275, + fltspec = 276, + strspec = 277, + word = 278, + str1 = 279 + }; +#endif +#define SEMI 258 +#define COMMA 259 +#define BAR 260 +#define EQ 261 +#define LP 262 +#define RP 263 +#define LB 264 +#define RB 265 +#define LAB 266 +#define RAB 267 +#define COLON 268 +#define LC 269 +#define RC 270 +#define ELLIPSES 271 +#define KW_ARGS 272 +#define KW_OPTIONS 273 +#define KW_CHANVARS 274 +#define intspec 275 +#define fltspec 276 +#define strspec 277 +#define word 278 +#define str1 279 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 52 "argdesc.y" +typedef union YYSTYPE { + char *str; + struct argapp *argapp; + struct argdesc *argdesc; + struct appsetvar *appsetvar; + struct argchoice *argchoice; +} YYSTYPE; +/* Line 1318 of yacc.c. */ +#line 93 "argdesc.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + + + Property changes on: pbx/argdesc.tab.h ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/ael.y =================================================================== --- pbx/ael.y (.../branches/1.2) (revision 0) +++ pbx/ael.y (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,710 @@ +%{ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * 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 Bison Grammar description of AEL2. + * + */ +#include +#include +#include +#include "asterisk/logger.h" +#include "asterisk/ael_structs.h" + +extern void reset_parencount(yyscan_t yyscanner); +extern void reset_semicount(yyscan_t yyscanner); +extern void reset_argcount(yyscan_t yyscanner ); + +#define YYPARSE_PARAM parseio +#define YYLEX_PARAM ((struct parse_io *)parseio)->scanner +#define YYERROR_VERBOSE 1 + +/* this stuff is included so I can declare the proto for yyerror */ +#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +int ael_errcnt = 0; +extern char *my_file; +void yyerror(YYLTYPE *locp,void *nothing, char const *s); +int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); +int ael_is_funcname(char *name); + static char *ael_token_subst(char *mess); + extern char *prev_word; + +%} + + +%union { + char *str; + struct pval *pval; +} + + +%token KW_CONTEXT LC RC LP RP SEMI EQ COMMA COLON AMPER BAR AT +%token KW_MACRO KW_GLOBALS KW_IGNOREPAT KW_SWITCH KW_IF KW_IFTIME KW_ELSE KW_RANDOM KW_ABSTRACT +%token EXTENMARK KW_GOTO KW_JUMP KW_RETURN KW_BREAK KW_CONTINUE KW_REGEXTEN KW_HINT +%token KW_FOR KW_WHILE KW_CASE KW_PATTERN KW_DEFAULT KW_CATCH KW_SWITCHES KW_ESWITCHES +%token KW_INCLUDES + +%token word + +%type includes +%type includeslist +%type switchlist +%type eswitches +%type switches +%type macro_statement +%type macro_statements +%type case_statement +%type case_statements +%type eval_arglist +%type application_call +%type application_call_head +%type macro_call +%type target jumptarget +%type statement +%type switch_head +%type word_list +%type word3_list +%type includedname +%type if_head +%type random_head +%type iftime_head +%type statements +%type extension +%type ignorepat +%type element +%type elements +%type arglist +%type global_statement +%type global_statements +%type globals +%type macro +%type context +%type object +%type objects +%type file + +/* OPTIONS */ +%locations +%pure-parser +%name-prefix="ael_yy" +/* the following option does two things: + it adds the locp arg to the yyerror + and it adds the NULL to the yyerrr arg list, and calls yyerror with NULL for that arg. + You can't get the locp arg without the NULL arg, don't ask me why. */ +%parse-param {void *NULL} +/* there will be two shift/reduce conflicts, they involve the if statement, where a single statement occurs not wrapped in curlies in the "true" section + the default action to shift will attach the else to the preceeding if. */ +%expect 5 +%error-verbose + +%% + +file : objects {((struct parse_io *)parseio)->pval = $$; ((struct parse_io *)parseio)->syntax_error_count = ael_errcnt;} + ; + +objects : object {$$=$1;} + | objects object {if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + | objects error + ; + +object : context {$$=$1;} + | macro {$$=$1;} + | globals {$$=$1;} + | SEMI {$$=0;/* allow older docs to be read */} + ; + +context : KW_CONTEXT word LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $2; $$->u2.statements = $4; } + | KW_CONTEXT word LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = $2; } + | KW_CONTEXT KW_DEFAULT LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = strdup("default"); $$->u2.statements = $4; } + | KW_CONTEXT KW_DEFAULT LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = strdup("default"); } + | KW_ABSTRACT KW_CONTEXT word LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = $3; $$->u2.statements = $5; $$->u3.abstract = 1;} + | KW_ABSTRACT KW_CONTEXT word LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $3; $$->u3.abstract = 1; } + | KW_ABSTRACT KW_CONTEXT KW_DEFAULT LC elements RC {$$=npval(PV_CONTEXT,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = strdup("default"); $$->u2.statements = $5; $$->u3.abstract = 1; } + | KW_ABSTRACT KW_CONTEXT KW_DEFAULT LC RC /* empty context OK */ {$$=npval(PV_CONTEXT,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = strdup("default"); $$->u3.abstract = 1; } + ; + +macro : KW_MACRO word LP arglist RP LC macro_statements RC {$$=npval(PV_MACRO,@1.first_line,@8.last_line, @1.first_column, @8.last_column); + $$->u1.str = $2; $$->u2.arglist = $4; $$->u3.macro_statements = $7; } + | KW_MACRO word LP arglist RP LC RC {$$=npval(PV_MACRO,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $2; $$->u2.arglist = $4; } + | KW_MACRO word LP RP LC macro_statements RC {$$=npval(PV_MACRO,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $2; $$->u3.macro_statements = $6; } + | KW_MACRO word LP RP LC RC {$$=npval(PV_MACRO,@1.first_line,@6.last_line, @1.first_column, @6.last_column); $$->u1.str = $2; /* pretty empty! */ } + ; + +globals : KW_GLOBALS LC global_statements RC {$$=npval(PV_GLOBALS,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.statements = $3;} + | KW_GLOBALS LC RC /* empty global is OK */ {$$=npval(PV_GLOBALS,@1.first_line,@3.last_line, @1.first_column, @3.last_column); /* and that's all */ } + ; + +global_statements : global_statement {$$=$1;} + | global_statements global_statement {$$=$1; linku1($$,$2);} + | global_statements error + ; + +global_statement : word EQ {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI {$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $1;$$->u2.val = $4; } + ; + +arglist : word {$$= npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1; } + | arglist COMMA word {pval *z = npval(PV_WORD,@1.first_line,@3.last_line, @1.first_column, @3.last_column); z->u1.str = $3; $$=$1; linku1($$,z); } + | arglist error + ; + +elements : element { $$=$1;} + | elements element { if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + | elements error { $$=$1;} + ; + +element : extension {$$=$1;} + | includes {$$=$1;} + | switches {$$=$1;} + | eswitches {$$=$1;} + | ignorepat {$$=$1;} + | word EQ {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI {$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $1;$$->u2.val = $4; } + | SEMI {$$=0;/* allow older docs to be read */} + ; + +ignorepat : KW_IGNOREPAT EXTENMARK word SEMI { $$=npval(PV_IGNOREPAT,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.str = $3;} + ; + +extension : word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $1; $$->u2.statements = $3; } + | KW_REGEXTEN word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@3.last_line, @1.first_column, @4.last_column); $$->u1.str = $2; $$->u2.statements = $4; $$->u4.regexten=1;} + | KW_HINT LP word3_list RP word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@7.last_line, @1.first_column, @7.last_column); $$->u1.str = $5; $$->u2.statements = $7; $$->u3.hints = $3;} + | KW_REGEXTEN KW_HINT LP word3_list RP word EXTENMARK statement {$$ = npval(PV_EXTENSION,@1.first_line,@4.last_line, @1.first_column, @8.last_column); $$->u1.str = $6; $$->u2.statements = $8; $$->u4.regexten=1;$$->u3.hints = $4;} + + ; + +statements : statement {$$=$1;} + | statements statement {if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + | statements error + ; + +if_head : KW_IF LP {reset_parencount(((struct parse_io *)parseio)->scanner);} word_list RP { $$= npval(PV_IF,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $4; } + ; + +random_head : KW_RANDOM LP {reset_parencount(((struct parse_io *)parseio)->scanner);} word_list RP { $$= npval(PV_RANDOM,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str=$4;} + ; + +iftime_head : KW_IFTIME LP word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list RP { $$= npval(PV_IFTIME,@1.first_line,@5.last_line, @1.first_column, @5.last_column); + $$->u1.list = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->u1.list->u1.str = (char*)malloc(strlen($3)+strlen($5)+strlen($7)+4); + strcpy($$->u1.list->u1.str,$3); + strcat($$->u1.list->u1.str,":"); + strcat($$->u1.list->u1.str,$5); + strcat($$->u1.list->u1.str,":"); + strcat($$->u1.list->u1.str,$7); + free($3); + free($5); + free($7); + $$->u1.list->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column); + $$->u1.list->next->u1.str = $9; + $$->u1.list->next->next = npval(PV_WORD,@11.first_line,@11.last_line, @11.first_column, @11.last_column); + $$->u1.list->next->next->u1.str = $11; + $$->u1.list->next->next->next = npval(PV_WORD,@13.first_line,@13.last_line, @13.first_column, @13.last_column); + $$->u1.list->next->next->next->u1.str = $13; + prev_word = 0; + } + | KW_IFTIME LP word BAR word3_list BAR word3_list BAR word3_list RP { $$= npval(PV_IFTIME,@1.first_line,@5.last_line, @1.first_column, @5.last_column); + $$->u1.list = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->u1.list->u1.str = $3; + $$->u1.list->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->u1.list->next->u1.str = $5; + $$->u1.list->next->next = npval(PV_WORD,@7.first_line,@7.last_line, @7.first_column, @7.last_column); + $$->u1.list->next->next->u1.str = $7; + $$->u1.list->next->next->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column); + $$->u1.list->next->next->next->u1.str = $9; + prev_word = 0; + } + + ; + +/* word_list is a hack to fix a problem with context switching between bison and flex; + by the time you register a new context with flex, you've already got a look-ahead token + from the old context, with no way to put it back and start afresh. So, we kludge this + and merge the words back together. */ + +word_list : word { $$ = $1;} + | word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);prev_word = $$;} + ; +word3_list : word { $$ = $1;} + | word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);prev_word = $$;} + | word word word { $$ = (char*)malloc(strlen($1)+strlen($2)+strlen($3)+1); strcpy($$, $1); strcat($$, $2); strcat($$, $3); free($1); free($2); free($3);prev_word=$$;} + ; + +switch_head : KW_SWITCH LP {reset_parencount(((struct parse_io *)parseio)->scanner);} word RP LC + {$$=npval(PV_SWITCH,@1.first_line,@6.last_line, @1.first_column, @6.last_column); + $$->u1.str = $4; } + ; + +statement : LC statements RC {$$=npval(PV_STATEMENTBLOCK,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2; } + | word EQ {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI + {$$=npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); + $$->u1.str = $1; $$->u2.val = $4; } + | KW_GOTO target SEMI {$$=npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2;} + | KW_JUMP jumptarget SEMI {$$=npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.list = $2;} + | word COLON {$$=npval(PV_LABEL,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1; } + | KW_FOR LP {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI + {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI + {reset_parencount(((struct parse_io *)parseio)->scanner);} word RP statement + { $$=npval(PV_FOR,@1.first_line,@12.last_line, @1.first_column, @12.last_column); + $$->u1.for_init = $4; $$->u2.for_test=$7; $$->u3.for_inc = $10; $$->u4.for_statements = $12;} + | KW_WHILE LP {reset_parencount(((struct parse_io *)parseio)->scanner);} word RP statement + {$$=npval(PV_WHILE,@1.first_line,@6.last_line, @1.first_column, @6.last_column); + $$->u1.str = $4; $$->u2.statements = $6; } + | switch_head RC /* empty list OK */ {$$=$1;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | switch_head case_statements RC {$$=$1; $$->u2.statements = $2;$$->endline = @3.last_line; $$->endcol = @3.last_column;} + | AMPER macro_call SEMI {$$ = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | application_call SEMI { $$ = $1;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | word SEMI { $$= npval(PV_APPLICATION_CALL,@1.first_line,@2.last_line, @1.first_column, @2.last_column); + $$->u1.str = $1;} + | application_call EQ {reset_semicount(((struct parse_io *)parseio)->scanner);} word SEMI { + char *bufx; + int tot=0; + pval *pptr; + + $$ = npval(PV_VARDEC,@1.first_line,@5.last_line, @1.first_column, @5.last_column); + $$->u2.val=$4; + /* rebuild the original string-- this is not an app call, it's an unwrapped vardec, with a func call on the LHS */ + /* string to big to fit in the buffer? */ + tot+=strlen($1->u1.str); + for(pptr=$1->u2.arglist;pptr;pptr=pptr->next) { + tot+=strlen(pptr->u1.str); + tot++; /* for a sep like a comma */ + } + tot+=4; /* for safety */ + bufx = (char *)malloc(tot); + strcpy(bufx,$1->u1.str); + strcat(bufx,"("); + for (pptr=$1->u2.arglist;pptr;pptr=pptr->next) { + if ( pptr != $1->u2.arglist ) + strcat(bufx,","); + strcat(bufx,pptr->u1.str); + } + strcat(bufx,")"); + + if ( !ael_is_funcname($1->u1.str) ) + ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Function call? The name %s is not in my internal list of function names\n", + my_file, @1.first_line, @1.first_column, @1.last_column, $1->u1.str); + $$->u1.str = bufx; + destroy_pval($1); /* the app call it is not, get rid of that chain */ + prev_word = 0; + } + | KW_BREAK SEMI { $$ = npval(PV_BREAK,@1.first_line,@2.last_line, @1.first_column, @2.last_column);} + | KW_RETURN SEMI {$$ = npval(PV_RETURN,@1.first_line,@2.last_line, @1.first_column, @2.last_column);} + | KW_CONTINUE SEMI {$$ = npval(PV_CONTINUE,@1.first_line,@2.last_line, @1.first_column, @2.last_column);} + | random_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | random_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;} + | if_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | if_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;} + | iftime_head statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + | iftime_head statement KW_ELSE statement {$$=$1; $$->u2.statements = $2;$$->endline = @2.last_line; $$->endcol = @2.last_column; $$->u3.else_statements = $4;} + | SEMI { $$=0; } + ; + +target : word { $$ = npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1;} + | word BAR word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3;} + | word COMMA word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3;} + | word BAR word BAR word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $5; } + | word COMMA word COMMA word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $5; } + | KW_DEFAULT BAR word BAR word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $5; } + | KW_DEFAULT COMMA word COMMA word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $5; } + ; + +jumptarget : word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->next->u1.str = strdup("1");} /* jump extension[,priority][@context] */ + | word COMMA word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $1; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $3;} + | word COMMA word AT word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $5; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $1; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $3; } + | word AT word {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = $3; $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $1; + $$->next->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->next->u1.str = strdup("1"); } + | word COMMA word AT KW_DEFAULT {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $1; + $$->next->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->next->next->u1.str = $3; } + | word AT KW_DEFAULT {$$=npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); + $$->u1.str = strdup("default"); $$->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->u1.str = $1; + $$->next->next = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->next->next->u1.str = strdup("1"); } + ; + +macro_call : word LP {reset_argcount(((struct parse_io *)parseio)->scanner);} eval_arglist RP + {$$= npval(PV_MACRO_CALL,@1.first_line,@2.last_line, @1.first_column, @2.last_column); + $$->u1.str = $1; $$->u2.arglist = $4;} + | word LP RP {$$= npval(PV_MACRO_CALL,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $1; } + ; + +application_call_head: word {reset_argcount(((struct parse_io *)parseio)->scanner);} LP {if (strcasecmp($1,"goto") == 0) { + $$= npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); + ast_log(LOG_WARNING, "==== File: %s, Line %d, Cols: %d-%d: Suggestion: Use the goto statement instead of the Goto() application call in AEL.\n", my_file, @1.first_line, @1.first_column, @1.last_column ); + } else + $$= npval(PV_APPLICATION_CALL,@1.first_line,@3.last_line, @1.first_column, @3.last_column); + $$->u1.str = $1; } + ; + +application_call : application_call_head eval_arglist RP {$$ = $1; + if( $$->type == PV_GOTO ) + $$->u1.list = $2; + else + $$->u2.arglist = $2; + $$->endline = @3.last_line; $$->endcol = @3.last_column;} + | application_call_head RP {$$=$1;$$->endline = @2.last_line; $$->endcol = @2.last_column;} + ; + +eval_arglist : word_list { $$= npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1;} + | /*nothing! */ { $$= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/); $$->u1.str = strdup(""); } + | eval_arglist COMMA word { pval *z = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); $$ = $1; linku1($1,z); z->u1.str = $3;} + | eval_arglist COMMA { pval *z = npval(PV_WORD,@2.first_line,@2.last_line, @2.first_column, @2.last_column); $$ = $1; linku1($1,z); z->u1.str = strdup("");} + ; + +case_statements: case_statement {$$=$1;} + | case_statements case_statement { if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + ; + +case_statement: KW_CASE word COLON statements {$$ = npval(PV_CASE,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2; $$->u2.statements = $4;} + | KW_DEFAULT COLON statements {$$ = npval(PV_DEFAULT,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = 0; $$->u2.statements = $3;} + | KW_PATTERN word COLON statements {$$ = npval(PV_PATTERN,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2; $$->u2.statements = $4;} + | KW_CASE word COLON {$$ = npval(PV_CASE,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2;} + | KW_DEFAULT COLON {$$ = npval(PV_DEFAULT,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = 0;} + | KW_PATTERN word COLON {$$ = npval(PV_PATTERN,@1.first_line,@3.last_line, @1.first_column, @3.last_column); $$->u1.str = $2;} + ; + +macro_statements: macro_statement {$$ = $1;} + | macro_statements macro_statement { if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + ; + +macro_statement : statement {$$=$1;} + | KW_CATCH word LC statements RC {$$=npval(PV_CATCH,@1.first_line,@5.last_line, @1.first_column, @5.last_column); $$->u1.str = $2; $$->u2.statements = $4;} + ; + +switches : KW_SWITCHES LC switchlist RC {$$= npval(PV_SWITCHES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3; } + | KW_SWITCHES LC RC /* empty switch list OK */ {$$= npval(PV_SWITCHES,@1.first_line,@3.last_line, @1.first_column, @3.last_column);} + ; + +eswitches : KW_ESWITCHES LC switchlist RC {$$= npval(PV_ESWITCHES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3; } + | KW_ESWITCHES LC RC /* empty switch list OK */ {$$= npval(PV_ESWITCHES,@1.first_line,@3.last_line, @1.first_column, @3.last_column); } /* if there's nothing to declare, why include it? */ + ; + +switchlist : word SEMI {$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1;} + | switchlist word SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column); $$=$1; z->u1.str = $2; linku1($$,z); } + | switchlist error + ; + +includeslist : includedname SEMI {$$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); $$->u1.str = $1;} + | includedname BAR word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list SEMI { + $$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); + $$->u1.str = $1; + $$->u2.arglist = npval(PV_WORD,@3.first_line,@7.last_line, @3.first_column, @7.last_column); + $$->u2.arglist->u1.str = (char*)malloc(strlen($3)+strlen($5)+strlen($7)+4); + strcpy($$->u2.arglist->u1.str,$3); + strcat($$->u2.arglist->u1.str,":"); + strcat($$->u2.arglist->u1.str,$5); + strcat($$->u2.arglist->u1.str,":"); + strcat($$->u2.arglist->u1.str,$7); + free($3); + free($5); + free($7); + $$->u2.arglist->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column); + $$->u2.arglist->next->u1.str = $9; + $$->u2.arglist->next->next = npval(PV_WORD,@11.first_line,@11.last_line, @11.first_column, @11.last_column); + $$->u2.arglist->next->next->u1.str = $11; + $$->u2.arglist->next->next->next = npval(PV_WORD,@13.first_line,@13.last_line, @13.first_column, @13.last_column); + $$->u2.arglist->next->next->next->u1.str = $13; + prev_word=0; + } + | includedname BAR word BAR word3_list BAR word3_list BAR word3_list SEMI { + $$=npval(PV_WORD,@1.first_line,@2.last_line, @1.first_column, @2.last_column); + $$->u1.str = $1; + $$->u2.arglist = npval(PV_WORD,@3.first_line,@3.last_line, @3.first_column, @3.last_column); + $$->u2.arglist->u1.str = $3; + $$->u2.arglist->next = npval(PV_WORD,@5.first_line,@5.last_line, @5.first_column, @5.last_column); + $$->u2.arglist->next->u1.str = $5; + $$->u2.arglist->next->next = npval(PV_WORD,@7.first_line,@7.last_line, @7.first_column, @7.last_column); + $$->u2.arglist->next->next->u1.str = $7; + $$->u2.arglist->next->next->next = npval(PV_WORD,@9.first_line,@9.last_line, @9.first_column, @9.last_column); + $$->u2.arglist->next->next->next->u1.str = $9; + prev_word=0; + } + | includeslist includedname SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column); $$=$1; z->u1.str = $2; linku1($$,z); } + | includeslist includedname BAR word3_list COLON word3_list COLON word3_list BAR word3_list BAR word3_list BAR word3_list SEMI {pval *z = npval(PV_WORD,@2.first_line,@3.last_line, @2.first_column, @3.last_column); + $$=$1; z->u1.str = $2; linku1($$,z); + z->u2.arglist = npval(PV_WORD,@4.first_line,@4.last_line, @4.first_column, @4.last_column); + $$->u2.arglist->u1.str = (char*)malloc(strlen($4)+strlen($6)+strlen($8)+4); + strcpy($$->u2.arglist->u1.str,$4); + strcat($$->u2.arglist->u1.str,":"); + strcat($$->u2.arglist->u1.str,$6); + strcat($$->u2.arglist->u1.str,":"); + strcat($$->u2.arglist->u1.str,$8); + free($4); + free($6); + free($8); + z->u2.arglist->next = npval(PV_WORD,@10.first_line,@10.last_line, @10.first_column, @10.last_column); + z->u2.arglist->next->u1.str = $10; + z->u2.arglist->next->next = npval(PV_WORD,@12.first_line,@12.last_line, @12.first_column, @12.last_column); + z->u2.arglist->next->next->u1.str = $12; + z->u2.arglist->next->next->next = npval(PV_WORD,@14.first_line,@14.last_line, @14.first_column, @14.last_column); + z->u2.arglist->next->next->next->u1.str = $14; + prev_word=0; + } + | includeslist includedname BAR word BAR word3_list BAR word3_list BAR word3_list SEMI + {pval *z = npval(PV_WORD,@2.first_line,@2.last_line, @2.first_column, @3.last_column); + $$=$1; z->u1.str = $2; linku1($$,z); + z->u2.arglist = npval(PV_WORD,@4.first_line,@4.last_line, @4.first_column, @4.last_column); + $$->u2.arglist->u1.str = $4; + z->u2.arglist->next = npval(PV_WORD,@6.first_line,@6.last_line, @6.first_column, @6.last_column); + z->u2.arglist->next->u1.str = $6; + z->u2.arglist->next->next = npval(PV_WORD,@8.first_line,@8.last_line, @8.first_column, @8.last_column); + z->u2.arglist->next->next->u1.str = $8; + z->u2.arglist->next->next->next = npval(PV_WORD,@10.first_line,@10.last_line, @10.first_column, @10.last_column); + z->u2.arglist->next->next->next->u1.str = $10; + prev_word=0; + } + | includeslist error + ; + +includedname : word { $$ = $1;} + | KW_DEFAULT {$$=strdup("default");} + ; + +includes : KW_INCLUDES LC includeslist RC {$$= npval(PV_INCLUDES,@1.first_line,@4.last_line, @1.first_column, @4.last_column); $$->u1.list = $3;} + | KW_INCLUDES LC RC {$$= npval(PV_INCLUDES,@1.first_line,@3.last_line, @1.first_column, @3.last_column);} + ; + + +%% + +static char *token_equivs1[] = +{ + "AMPER", + "AT", + "BAR", + "COLON", + "COMMA", + "EQ", + "EXTENMARK", + "KW_BREAK", + "KW_CASE", + "KW_CATCH", + "KW_CONTEXT", + "KW_CONTINUE", + "KW_DEFAULT", + "KW_ELSE", + "KW_ESWITCHES", + "KW_FOR", + "KW_GLOBALS", + "KW_GOTO", + "KW_HINT", + "KW_IFTIME", + "KW_IF", + "KW_IGNOREPAT", + "KW_INCLUDES" + "KW_JUMP", + "KW_MACRO", + "KW_PATTERN", + "KW_REGEXTEN", + "KW_RETURN", + "KW_SWITCHES", + "KW_SWITCH", + "KW_WHILE", + "LC", + "LP", + "RC", + "RP", + "SEMI", +}; + +static char *token_equivs2[] = +{ + "&", + "@", + "|", + ":", + ",", + "=", + "=>", + "break", + "case", + "catch", + "context", + "continue", + "default", + "else", + "eswitches", + "for", + "globals", + "goto", + "hint", + "ifTime", + "if", + "ignorepat", + "includes" + "jump", + "macro", + "pattern", + "regexten", + "return", + "switches", + "switch", + "while", + "{", + "(", + "}", + ")", + ";", +}; + + +static char *ael_token_subst(char *mess) +{ + /* calc a length, malloc, fill, and return; yyerror had better free it! */ + int len=0,i; + char *p; + char *res, *s,*t; + int token_equivs_entries = sizeof(token_equivs1)/sizeof(char*); + + for (p=mess; *p; p++) { + for (i=0; ifirst_line == locp->last_line) { + ast_log(LOG_ERROR, "==== File: %s, Line %d, Cols: %d-%d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_column, s2); + } else { + ast_log(LOG_ERROR, "==== File: %s, Line %d Col %d to Line %d Col %d: Error: %s\n", my_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column, s2); + } + free(s2); + + ael_errcnt++; +} + +struct pval *npval(pvaltype type,int first_line, int last_line, int first_column, int last_column) +{ + extern char *my_file; + pval *z = (pval *)calloc(sizeof(struct pval),1); + z->type = type; + z->startline = first_line; + z->endline = last_line; + z->startcol = first_column; + z->endcol = last_column; + z->filename = strdup(my_file); + return z; +} + +void linku1(pval *head, pval *tail) +{ + if (!head->next) { + head->next = tail; + head->u1_last = tail; + } else { + head->u1_last->next = tail; + head->u1_last = tail; + } +} + Property changes on: pbx/ael.y ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/applist =================================================================== --- pbx/applist (.../branches/1.2) (revision 0) +++ pbx/applist (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,142 @@ + AddQueueMember: "Dynamically adds queue members"; args=queuename|[interface]|[:penalty#i]|[:options]; options=j; Chanvars=AQMSTATUS:ADDED | MEMBERALREADY | NOSUCHQUEUE; + ADSIProg: "Load Asterisk ADSI Scripts into phone"; args=scriptfile; + AgentCallbackLogin: "Call agent callback login"; args = [AgentNo]|[:options]|[:exten-at-context]; options=s; + AgentLogin: "Call agent login"; args = [AgentNo]|[:options]; options=s; + AgentMonitorOutgoing: "Record agent's outgoing call"; args=[options]; options=d,c,n; + AGI: "Executes an AGI compliant application"; args = command|...; + AlarmReceiver: "Provide support for receving alarm reports from a burglar or fire alarm panel"; + Answer: "Answer a channel if ringing"; args=[delay#i]; + AppendCDRUserField: "Append to the CDR user field"; args = value; + Authenticate: "Authenticate a user"; args=password|[options]; options=a,d,j,m,r; + BackGround: "Play a file while awaiting extension"; args = filenames|[options]|[:langoverride]|[:context]; options=s,n,m; + BackgroundDetect: "Background a file with talk detect"; args=filename|[sil]|[:min]|[:max]; + Busy: "Indicate the Busy condition"; args=[timeout#i]; + ChangeMonitor: "Change monitoring filename of a channel"; args=filenamebase; + ChanIsAvail: "Check channel availability"; args=Technology_resource|[options]; options=s,j; Chanvars=AVAILCHAN,AVAILORIGCHAN,AVAILSTATUS; + ChanSpy: "Listen to the audio of an active channel"; args=[chanprefix]|[:options]; options=b,g(),q,r[()],v(); + Congestion: "Indicate the Congestion condition"; args=[timeout#i]; + ControlPlayback: "Play a file with fast forward and rewind"; args=file|[skipms]|[:ff]|[:rew]|[:stop]|[:pause]|[:restart]|[:options]; options=j; Chanvars=CPLAYBACKSTATUS:SUCCESS | USERSTOPPED | ERROR; + DateTime: "Says a specified time in a custom format"; args=[unixtime]|[:timezone]|[:format]; + DBdel: "Delete a key from the database"; args=family_key; + DBdeltree: "Delete a family or keytree from the database"; args=family_keytree; + DeadAGI: "Executes AGI on a hungup channel"; args = command|...; + Dial: "Place a call and connect to the current channel"; args=Technology_resource|[timeout#i]|[:options]|[:URL]; options=A(),C,d,D(),f,g,G(),h,H,j,L(),m(),M(),n,N,o,p,P(),r,S(),t,T,w,W; Chanvars=DIALEDTIME,ANSWEREDTIME,DIALSTATUS:CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL | DONTCALL | TORTURE; + Dictate: "Virtual Dictation Machine"; args=[base_dir]; + Directory: "Provide directory of voicemail extensions"; args=vm-context|[dial-context]|[:options]; options=f; + DISA: "DISA (Direct Inward System Access)"; args=numeric_passcode|[context]; + DumpChan: "Dump Info About The Calling Channel"; args=[min_verbose_level]; + DUNDiLookup: "Look up a number with DUNDi"; args=number|[context]|[:options]; options=b,j; + EAGI: "Executes an AGI compliant application"; args = command|...; + Echo: "Echo audio, video, or DTMF back to the calling party"; + EndWhile: "End A While Loop"; + Exec: "Executes internal application"; args=appname|...; + ExecIf: "Conditional exec"; args=expr|app|data; + ExecIfTime: "Conditional application execution based on the current time"; args=times|weekdays|mdays|months_appname|...; + ExternalIVR: "Interfaces with an external IVR application"; args=command|...; + Festival: "Say text to the user"; args=text|[intkeys]; + Flash: "Flashes a Zap Trunk"; + ForkCDR: "Forks the Call Data Record"; args=[options]; options=v; + GetCPEID: "Get ADSI CPE ID"; + Gosub: "Jump to label, saving return address"; args=[context]|[exten]|priority; + GosubIf: "Jump to label, saving return address"; args=condition_labels; + Goto: "Jump to a particular priority, extension, or context"; args=[context]|[exten]|priority; + GotoIf: "Conditional goto"; args=condition_labels; + GotoIfTime: "Conditional Goto based on the current time"; args=times|weekdays|mdays|months_q_context|[exten]|priority; + Hangup: "Hang up the calling channel"; + HasNewVoicemail: "Conditionally branches to priority + 101 with the right options set"; args=vmboxspec|[varname]|[:options]; options=j; Chanvars=HASVMSTATUS; + HasVoicemail: "Conditionally branches to priority + 101 with the right options set"; args=vmboxspec|[varname]|[:options]; options=j; Chanvars=HASVMSTATUS; + IAX2Provision: "Provision a calling IAXy with a given template"; args=[template]; + ICES: "Encode and stream using 'ices'"; args = config_xml; + ImportVar: "Import a variable from a channel into a new variable"; args=newvar_channelname|variable; + Log: "Send arbitrary text to a selected log level"; args=|message; + LookupBlacklist: "Look up Caller*ID name/number from blacklist database"; args=[options]; options=j; Chanvars=LOOKUPBLSTATUS:FOUND | NOTFOUND; + LookupCIDName: "Look up CallerID Name from local database"; + Macro: "Macro Implementation"; args=macroname|...; Chanvars=MACRO_EXTEN, MACRO_CONTEXT, MACRO_PRIORITY; + MacroExit: "Exit From Macro"; + MacroIf: "Conditional Macro Implementation"; args=expr_macroname_a|[arg1]|[macroname_b]|[:arg1]; + MailboxExists: "Check to see if Voicemail mailbox exists"; args=mailbox_context|[options]; options=j; Chanvars=VMBOXEXISTSSTATUS:SUCCESS | FAILED; + Math: "Performs Mathematical Functions"; args=returnvar|simple_expr; + MeetMe: "MeetMe conference bridge"; args=[confno#i]|[:options]|[:pin]; options=a,A,b,c,d,D,e,E,i,m,M,p,P,q,r,s,t,T,o,v,w,x,X; + MeetMeAdmin: "MeetMe conference Administration"; args=confno#i||[user]; + MeetMeCount: "MeetMe participant count"; args=confno|[var]; + Milliwatt: "Generate a Constant 1000Hz tone at 0dbm (mu-law)"; + MixMonitor: "Record a call and mix the audio during the recording"; args=file|[options]|[:command]; options=a,b,v(),V(),W(); Chanvars=MIXMONITOR_FILENAME; + Monitor: "Monitor a channel"; args=[file_format]|[:fname_base]|[:options]; options=m,b; + MP3Player: "Play an MP3 file or stream"; args=location; + MusicOnHold: "Play Music On Hold indefinitely"; args=[class]; + NBScat: "Play an NBS local stream"; + NoCDR: "Tell Asterisk to not maintain a CDR for the current call"; + NoOp: "Do Nothing"; args=...; + Page: "Pages phones"; args=Technology_res|[options]; options=d,q; + Park: "Park yourself"; args=exten; + ParkAndAnnounce: "Park and Announce"; args=announce_templ|timeout#i|dial|[return_context]; + ParkedCall: "Answer a parked call"; args=exten; + PauseQueueMember: "Pauses a queue member"; args={queuename}|interface|[options]; options=j; Chanvars=PQMSTATUS:PAUSED | NOTFOUND; + Pickup: "Directed Call Pickup"; args=extension_context; + Playback: "Play a file"; args=filenames|[options]; options=skip,noanswer,j; Chanvars=PLAYBACKSTATUS:SUCCESS | FAILED; + PlayTones: "Play a tone list"; args=arg; + PrivacyManager: "Require phone number to be entered, if no CallerID sent"; args=[maxretries]|[:minlength]|[:options]; options=j; Chanvars=PRIVACYMGRSTATUS:SUCCESS | FAILED; + Progress: "Indicate progress"; + Queue: "Queue a call for a call queue"; args=queuename|[options]|[:URL]|[announceoverride]|[timeout#i]; options=d,h,H,n,r,t,T,w,W; Chanvars=QUEUESTATUS:TIMEOUT | FULL | JOINEMPTY | LEAVEEMPTY | JOINUNAVAIL | LEAVEUNAVAIL; + Random: "Conditionally branches, based upon a probability"; args=[probability]|[context]|[extension]|priority; + Read: "Read a variable"; args=variable|[:filename]|[:maxdigits#i]|[:options]|[:attempts#i]|[:timeout#i]; options=s,i,n; + ReadFile: "ReadFile(varname=file,length)"; args=varname_file|length#i; + RealTime: "Realtime Data Lookup"; args=family|colmatch|value|[prefix]; Chanvars=REALTIMECOUNT; + RealTimeUpdate: "Realtime Data Rewrite"; args=family|colmatch|value|newcol|newval; Chanvars=REALTIMECOUNT; + Record: "Record to a file"; args=filename|[silence#i]|[:maxduration#i]|[options]; options=a,n,q,s,t; + RemoveQueueMember: "Dynamically removes queue members"; args=queuename|[interface]|[:options]; options=j; Chanvars=RQMSTATUS:REMOVED|NOTINQUEUE| NOSUCHQUEUE; + ResetCDR: "Resets the Call Data Record"; args=[options]; options=w,a,v; + RetryDial: "Place a call, retrying on failure allowing optional exit extension."; args=announce|sleep|retries#i|...; + Return: "Return from gosub routine"; + Ringing: "Indicate ringing tone"; + RxFAX: "Receive a FAX to a file"; args=filename|[caller]|[:debug]; Chanvars=REMOTESTATIONID, FAXPAGES, FAXBITRATE, FAXRESOLUTION; + SayAlpha: "Say Alpha"; args=string; + SayDigits: "Say Digits"; args=digits; + SayNumber: "Say Number"; args=digits|[gender]; + SayPhonetic: "Say Phonetic"; args=string; + SayUnixTime: "Says a specified time in a custom format"; args=[unixtime]|[:timezone]|[:format]; + SendDTMF: "Sends arbitrary DTMF digits"; args=digits|[timeout_ms#i]; + SendImage: "Send an image file"; args=filename; + SendText: "Send a Text Message"; args=text|[options]; options=j; Chanvars=SENDTEXTSTATUS:SUCCESS|FAILURE|UNSUPPORTED; + SendURL: "Send a URL"; args=URL|[option]; Chanvars=SENDURLSTATUS:SUCCESS | FAILURE | NOLOAD | UNSUPPORTED; + Set: "Set channel variable(s) or function value(s)"; args=name1_value1|...|[options]; options=g; + SetAMAFlags: "Set the AMA Flags"; args=[flag]; + SetCallerID: "Set CallerID"; args=clid|[a]; + SetCallerPres: "Set CallerID Presentation"; args=; + SetCDRUserField: "Set the CDR user field"; args=value; + SetGlobalVar: "Set a global variable to a given value"; args=variable_value; + SetMusicOnHold: "Set default Music On Hold class"; args=class; + SetTransferCapability: "Set ISDN Transfer Capability"; args=; + SIPAddHeader: "Add a SIP header to the outbound call"; args=Header_Content; + SIPDtmfMode: "Change the dtmfmode for a SIP call"; args=inband|info|rfc2833; + SIPGetHeader: "Get a SIP header from an incoming call"; args=var_headername; + SMS: "Communicates with SMS service centres and SMS capable analogue phones"; args=name|[a]|[s]; + SoftHangup: "Soft Hangup Application"; args=Technology_resource|[options]; options=a; + StackPop: "Remove one address from gosub stack"; + StartMusicOnHold: "Play Music On Hold"; args=class; + StopMonitor: "Stop monitoring a channel"; + StopMusicOnHold: "Stop Playing Music On Hold"; + StopPlayTones: "Stop playing a tone list"; + System: "Execute a system command"; args=command; Chanvars=SYSTEMSTATUS:FAILURE|SUCCESS; + TestClient: "Execute Interface Test Client"; args=testid; + TestServer: "Execute Interface Test Server"; + Transfer: "Transfer caller to remote extension"; args=Tech_dest|[options]; options=j; Chanvars=TRANSFERSTATUS:SUCCESS|FAILURE|UNSUPPORTED; + TrySystem: "Try executing a system command"; args=command; Chanvars=SYSTEMSTATUS:FAILURE|SUCCESS|APPERROR; + TxFAX: "Send a FAX file"; args=filename|[caller]|[debug]; Chanvars=REMOTESTATIONID; + UnpauseQueueMember: "Unpauses a queue member"; args=[queuename]|interface|[options]; options=j; Chanvars=UPQMSTATUS:UNPAUSED|NOTFOUND; + UserEvent: "Send an arbitrary event to the manager interface"; args=eventname|[body]; + Verbose: "Send arbitrary text to verbose output"; args=[level#i]|message; + VMAuthenticate: "Authenticate with Voicemail passwords"; args=mailbox_context|[options]; options=s; + VoiceMail: "Leave a Voicemail message"; args=mailbox_context|[options]; options=b,g(),s,u,j; Chanvars=VMSTATUS:SUCCESS|USEREXIT|FAILED; + VoiceMailMain: "Check Voicemail messages"; args=[mailbox_context]|[:options]; options=p,g(),s; + Wait: "Waits for some time"; args=seconds; + WaitExten: "Waits for an extension to be entered"; args=[seconds#i]|[options]; options=m[()]; + WaitForRing: "Wait for Ring Application"; args=timeout#i; + WaitForSilence: "Waits for a specified amount of silence"; args=x#i|[y]; Chanvars=WAITSTATUS:SILENCE|TIMEOUT; + WaitMusicOnHold: "Wait, playing Music On Hold"; args=delay#i; + While: "Start A While Loop"; args=expr; + Zapateller: "Block telemarketers with SIT"; args=[answer]|[timeout#i]|[answer]|[timeout#i]; + ZapBarge: "Barge in (monitor) Zap channel"; args=[channel]; + ZapRAS: "Executes Zaptel ISDN RAS application"; args=arg; + ZapScan: "Scan Zap channels to monitor calls"; args=[group]; + ZapSendKeypadFacility: "Send digits out of band over a PRI"; Property changes on: pbx/applist ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/pbx_ael2.c =================================================================== --- pbx/pbx_ael2.c (.../branches/1.2) (revision 0) +++ pbx/pbx_ael2.c (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,3827 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * 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 Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include "asterisk/pbx.h" +#include "asterisk/config.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/cli.h" +#include "asterisk/app.h" +#include "asterisk/callerid.h" +#include "asterisk/ael_structs.h" +#include "asterisk/argdesc.h" + +static char expr_output[2096]; + +/* these functions are in ../ast_expr2.fl */ + + +#ifdef __AST_DEBUG_MALLOC +static void FREE(void *ptr) +{ + free(ptr); +} +#else +#define FREE free +#endif + +#define DEBUG_READ (1 << 0) +#define DEBUG_TOKENS (1 << 1) +#define DEBUG_MACROS (1 << 2) +#define DEBUG_CONTEXTS (1 << 3) + +static int aeldebug = 0; + +static char *dtext = "Asterisk Extension Language Compiler v2"; +static char *config = "extensions.ael2"; +static char *registrar = "pbx_ael2"; + +static int errs, warns, notes; + + +void ast_expr_register_extra_error_info(char *errmsg); +void ast_expr_clear_extra_error_info(void); +int ast_expr(char *expr, char *buf, int length); +int option_matches_j( struct argdesc *should, pval *is, struct argapp *app); +void check_switch_expr(pval *item, struct argapp *apps); +int ael_is_funcname(char *name); +struct pval *find_macro(char *name); +struct pval *find_context(char *name); +struct pval *find_context(char *name); +struct pval *find_macro(char *name); +void check_pval_item(pval *item, struct argapp *apps); +struct ael_priority *new_prio(void); +struct ael_extension *new_exten(void); +void linkprio(struct ael_extension *exten, struct ael_priority *prio); +void destroy_extensions(struct ael_extension *exten); +void linkexten(struct ael_extension *exten, struct ael_extension *add); +void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten ); +void set_priorities(struct ael_extension *exten); +void add_extensions(struct ael_extension *exten, struct ast_context *context); +void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root); +void destroy_pval(pval *item); +void destroy_pval_item(pval *item); +int is_float(char *arg ); +int is_int(char *arg ); +int is_empty(char *arg); +int option_matches( struct argdesc *should, pval *is, struct argapp *app); +int check_app_args(pval *appcall, pval *arglist, struct argapp *app); +static pval *current_db; +static pval *current_context; +static pval *current_extension; + +static char *match_context; +static char *match_exten; +static char *match_label; +static int in_abstract_context; +static int count_labels; /* true, put matcher in label counting mode */ +static int label_count; /* labels are only meant to be counted in a context or exten */ +static int return_on_context_match; +static pval *last_matched_label; +struct pval *match_pval(pval *item); +static void check_timerange(pval *p); +static void check_dow(pval *DOW); +static void check_day(pval *DAY); +static void check_month(pval *MON); +static void check_expr2_input(pval *expr, char *str); +static int extension_matches(pval *here, char *exten, char *pattern); +static void check_goto(pval *item); +static void find_pval_goto_item(pval *item, int lev); +static void find_pval_gotos(pval *item, int lev); + + +/* PRETTY PRINTER FOR AEL: ============================================================================= */ + +void print_pval(FILE *fin, pval *item, int depth) +{ + int i; + pval *lp; + + for (i=0; itype ) { + case PV_WORD: + fprintf(fin,"%s;\n", item->u1.str); /* usually, words are encapsulated in something else */ + break; + + case PV_MACRO: + fprintf(fin,"macro %s(", item->u1.str); + for (lp=item->u2.arglist; lp; lp=lp->next) { + if (lp != item->u2.arglist ) + fprintf(fin,", "); + fprintf(fin,"%s", lp->u1.str); + } + fprintf(fin,") {\n"); + print_pval_list(fin,item->u3.macro_statements,depth+1); + for (i=0; iu3.abstract ) + fprintf(fin,"abstract context %s {\n", item->u1.str); + else + fprintf(fin,"context %s {\n", item->u1.str); + print_pval_list(fin,item->u2.statements,depth+1); + for (i=0; iu1.str); + for (lp=item->u2.arglist; lp; lp=lp->next) { + if ( lp != item->u2.arglist ) + fprintf(fin,", "); + fprintf(fin,"%s", lp->u1.str); + } + fprintf(fin,");\n"); + break; + + case PV_APPLICATION_CALL: + fprintf(fin,"%s(", item->u1.str); + for (lp=item->u2.arglist; lp; lp=lp->next) { + if ( lp != item->u2.arglist ) + fprintf(fin,", "); + fprintf(fin,"%s", lp->u1.str); + } + fprintf(fin,");\n"); + break; + + case PV_CASE: + fprintf(fin,"case %s:\n", item->u1.str); + print_pval_list(fin,item->u2.statements, depth+1); + break; + + case PV_PATTERN: + fprintf(fin,"pattern %s:\n", item->u1.str); + print_pval_list(fin,item->u2.statements, depth+1); + break; + + case PV_DEFAULT: + fprintf(fin,"default:\n"); + print_pval_list(fin,item->u2.statements, depth+1); + break; + + case PV_CATCH: + fprintf(fin,"catch %s {\n", item->u1.str); + print_pval_list(fin,item->u2.statements, depth+1); + for (i=0; iu1.list,depth+1); + for (i=0; iu1.list,depth+1); + for (i=0; iu1.list; lp; lp=lp->next) { + for (i=0; iu1.str); /* usually, words are encapsulated in something else */ + if ( lp->u2.arglist ) + fprintf(fin,"|%s|%s|%s|%s", + lp->u2.arglist->u1.str, + lp->u2.arglist->next->u1.str, + lp->u2.arglist->next->next->u1.str, + lp->u2.arglist->next->next->next->u1.str + ); + fprintf(fin,";\n"); /* usually, words are encapsulated in something else */ + } + + print_pval_list(fin,item->u1.list,depth+1); + for (i=0; iu1.list, depth+1); + for (i=0; iu1.str, item->u2.val); + break; + + case PV_GOTO: + fprintf(fin,"goto %s", item->u1.list->u1.str); + if ( item->u1.list->next ) + fprintf(fin,"|%s", item->u1.list->next->u1.str); + if ( item->u1.list->next && item->u1.list->next->next ) + fprintf(fin,"|%s", item->u1.list->next->next->u1.str); + fprintf(fin,"\n"); + break; + + case PV_LABEL: + fprintf(fin,"%s:\n", item->u1.str); + break; + + case PV_FOR: + fprintf(fin,"for (%s; %s; %s)\n", item->u1.for_init, item->u2.for_test, item->u3.for_inc); + print_pval_list(fin,item->u4.for_statements,depth+1); + break; + + case PV_WHILE: + fprintf(fin,"while (%s)\n", item->u1.str); + print_pval_list(fin,item->u2.statements,depth+1); + break; + + case PV_BREAK: + fprintf(fin,"break;\n"); + break; + + case PV_RETURN: + fprintf(fin,"return;\n"); + break; + + case PV_CONTINUE: + fprintf(fin,"continue;\n"); + break; + + case PV_RANDOM: + case PV_IFTIME: + case PV_IF: + if ( item->type == PV_IFTIME ) { + + fprintf(fin,"ifTime ( %s|%s|%s|%s )\n", + item->u1.list->u1.str, + item->u1.list->next->u1.str, + item->u1.list->next->next->u1.str, + item->u1.list->next->next->next->u1.str + ); + } else if ( item->type == PV_RANDOM ) { + fprintf(fin,"random ( %s )\n", item->u1.str ); + } else + fprintf(fin,"if ( %s )\n", item->u1.str); + if ( item->u2.statements && item->u2.statements->next ) { + for (i=0; iu2.statements,depth+1); + for (i=0; iu3.else_statements ) + fprintf(fin,"}\n"); + else + fprintf(fin,"};\n"); + } else if (item->u2.statements ) { + print_pval_list(fin,item->u2.statements,depth+1); + } else { + if (item->u3.else_statements ) + fprintf(fin, " {} "); + else + fprintf(fin, " {}; "); + } + if ( item->u3.else_statements ) { + for (i=0; iu3.else_statements, depth); + } + break; + + case PV_SWITCH: + fprintf(fin,"switch( %s ) {\n", item->u1.str); + print_pval_list(fin,item->u2.statements,depth+1); + for (i=0; iu4.regexten ) + fprintf(fin, "regexten "); + if ( item->u3.hints ) + fprintf(fin,"hints(%s) ", item->u3.hints); + + fprintf(fin,"%s => \n", item->u1.str); + print_pval_list(fin,item->u2.statements,depth+1); + break; + + case PV_IGNOREPAT: + fprintf(fin,"ignorepat => %s\n", item->u1.str); + break; + + case PV_GLOBALS: + fprintf(fin,"globals {\n"); + print_pval_list(fin,item->u1.statements,depth+1); + for (i=0; inext) { + print_pval(fin, i, depth); + } +} + +void ael2_print(char *fname, pval *tree) +{ + FILE *fin = fopen(fname,"w"); + if ( !fin ) { + ast_log(LOG_ERROR, "Couldn't open %s for writing.\n", fname); + return; + } + print_pval_list(fin, tree, 0); + fclose(fin); +} + + +/* EMPTY TEMPLATE FUNCS FOR AEL TRAVERSAL: ============================================================================= */ + +void traverse_pval_template(pval *item, int depth); +void traverse_pval_item_template(pval *item, int depth); + + +void traverse_pval_item_template(pval *item, int depth)/* depth comes in handy for a pretty print (indentation), + but you may not need it */ +{ + pval *lp; + + switch ( item->type ) { + case PV_WORD: + /* fields: item->u1.str == string associated with this (word). */ + break; + + case PV_MACRO: + /* fields: item->u1.str == name of macro + item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + + item->u3.macro_statements == pval list of statements in macro body. + */ + for (lp=item->u2.arglist; lp; lp=lp->next) { + + } + traverse_pval_item_template(item->u3.macro_statements,depth+1); + break; + + case PV_CONTEXT: + /* fields: item->u1.str == name of context + item->u2.statements == pval list of statements in context body + item->u3.abstract == int 1 if an abstract keyword were present + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_MACRO_CALL: + /* fields: item->u1.str == name of macro to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + for (lp=item->u2.arglist; lp; lp=lp->next) { + } + break; + + case PV_APPLICATION_CALL: + /* fields: item->u1.str == name of application to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + for (lp=item->u2.arglist; lp; lp=lp->next) { + } + break; + + case PV_CASE: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_PATTERN: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_DEFAULT: + /* fields: + item->u2.statements == pval list of statements under the case + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_CATCH: + /* fields: item->u1.str == name of extension to catch + item->u2.statements == pval list of statements in context body + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_SWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + traverse_pval_item_template(item->u1.list,depth+1); + break; + + case PV_ESWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + traverse_pval_item_template(item->u1.list,depth+1); + break; + + case PV_INCLUDES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + item->u2.arglist == pval list of 4 PV_WORD elements for time values + */ + traverse_pval_item_template(item->u1.list,depth+1); + traverse_pval_item_template(item->u2.arglist,depth+1); + break; + + case PV_STATEMENTBLOCK: + /* fields: item->u1.list == pval list of statements in block, one per entry in the list + */ + traverse_pval_item_template(item->u1.list,depth+1); + break; + + case PV_VARDEC: + /* fields: item->u1.str == variable name + item->u2.val == variable value to assign + */ + break; + + case PV_GOTO: + /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. + item->u1.list->u1.str == where the data on a PV_WORD will always be. + */ + + if ( item->u1.list->next ) + ; + if ( item->u1.list->next && item->u1.list->next->next ) + ; + + break; + + case PV_LABEL: + /* fields: item->u1.str == label name + */ + break; + + case PV_FOR: + /* fields: item->u1.for_init == a string containing the initalizer + item->u2.for_test == a string containing the loop test + item->u3.for_inc == a string containing the loop increment + + item->u4.for_statements == a pval list of statements in the for () + */ + traverse_pval_item_template(item->u4.for_statements,depth+1); + break; + + case PV_WHILE: + /* fields: item->u1.str == the while conditional, as supplied by user + + item->u2.statements == a pval list of statements in the while () + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_BREAK: + /* fields: none + */ + break; + + case PV_RETURN: + /* fields: none + */ + break; + + case PV_CONTINUE: + /* fields: none + */ + break; + + case PV_IFTIME: + /* fields: item->u1.list == there are 4 linked PV_WORDs here. + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + traverse_pval_item_template(item->u2.statements,depth+1); + if ( item->u3.else_statements ) { + traverse_pval_item_template(item->u3.else_statements,depth+1); + } + break; + + case PV_RANDOM: + /* fields: item->u1.str == the random number expression, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + traverse_pval_item_template(item->u2.statements,depth+1); + if ( item->u3.else_statements ) { + traverse_pval_item_template(item->u3.else_statements,depth+1); + } + break; + + case PV_IF: + /* fields: item->u1.str == the if conditional, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + traverse_pval_item_template(item->u2.statements,depth+1); + if ( item->u3.else_statements ) { + traverse_pval_item_template(item->u3.else_statements,depth+1); + } + break; + + case PV_SWITCH: + /* fields: item->u1.str == the switch expression + + item->u2.statements == a pval list of statements in the switch, + (will be case statements, most likely!) + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_EXTENSION: + /* fields: item->u1.str == the extension name, label, whatever it's called + + item->u2.statements == a pval list of statements in the extension + item->u3.hints == a char * hint argument + item->u4.regexten == an int boolean. non-zero says that regexten was specified + */ + traverse_pval_item_template(item->u2.statements,depth+1); + break; + + case PV_IGNOREPAT: + /* fields: item->u1.str == the ignorepat data + */ + break; + + case PV_GLOBALS: + /* fields: item->u1.statements == pval list of statements, usually vardecs + */ + traverse_pval_item_template(item->u1.statements,depth+1); + break; + } +} + +void traverse_pval_template(pval *item, int depth) /* depth comes in handy for a pretty print (indentation), + but you may not need it */ +{ + pval *i; + + for (i=item; i; i=i->next) { + traverse_pval_item_template(i, depth); + } +} + + +/* SEMANTIC CHECKING FOR AEL: ============================================================================= */ + +/* (not all that is syntactically legal is good! */ + + + +static int extension_matches(pval *here, char *exten, char *pattern) +{ + int err1; + regex_t preg; + + if ( pattern[0] == '_' ) { + char reg1[2000]; + char *p,*r=reg1; + + if ( strlen(pattern)*5 >= 2000 ) /* safety valve */ { + ast_log(LOG_ERROR,"Error: The pattern %s is way too big. Pattern matching cancelled.\n", + pattern); + return 0; + } + /* form a regular expression from the pattern, and then match it against exten */ + for (p=pattern+1; *p; p++) { + switch ( *p ) { + case 'X': + *r++ = '['; + *r++ = '0'; + *r++ = '-'; + *r++ = '9'; + *r++ = ']'; + break; + + case 'Z': + *r++ = '['; + *r++ = '1'; + *r++ = '-'; + *r++ = '9'; + *r++ = ']'; + break; + + case 'N': + *r++ = '['; + *r++ = '2'; + *r++ = '-'; + *r++ = '9'; + *r++ = ']'; + break; + + case '[': + while ( *p && *p != ']' ) { + *r++ = *p++; + } + if ( *p != ']') { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The extension pattern '%s' is missing a closing bracket \n", + here->filename, here->startline, here->endline, pattern); + } + break; + + case '.': + case '!': + *r++ = '.'; + *r++ = '*'; + break; + default: + *r++ = *p; + break; + + } + } + *r++ = *p++; /* put in the closing null */ + err1 = regcomp(&preg, reg1, REG_NOSUB); + if ( err1 ) { + char errmess[500]; + regerror(err1,&preg,errmess,sizeof(errmess)); + regfree(&preg); + /* ast_log(LOG_WARNING, "Regcomp of %s failed, error code %d\n", + reg1, err1); */ + return 0; + } + err1 = regexec(&preg, exten, 0, 0, 0); + regfree(&preg); + + if ( err1 ) + return 0; /* no match */ + else { + /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s", + exten, pattern); */ + return 1; + } + + + } else { + if ( strcmp(exten,pattern) == 0 ) { + return 1; + } else + return 0; + } +} + + +static void check_expr2_input(pval *expr, char *str) +{ + int spaces = strspn(str,"\t \n"); + if ( !strncmp(str+spaces,"$[",2) ) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The expression '%s' is redundantly wrapped in '$[ ]'. \n", + expr->filename, expr->startline, expr->endline, str); + warns++; + } +} + +static void check_timerange(pval *p) +{ + char times[200]; + char *e; + int s1, s2; + int e1, e2; + + + strncpy(times, p->u1.str, sizeof(times)); + /* Star is all times */ + if (ast_strlen_zero(times) || !strcmp(times, "*")) { + return; + } + /* Otherwise expect a range */ + e = strchr(times, '-'); + if (!e) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) requires a '-' surrounded by two 24-hour times of day!\n", + p->filename, p->startline, p->endline, times); + warns++; + return; + } + *e = '\0'; + e++; + while (*e && !isdigit(*e)) + e++; + if (!*e) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The time range format (%s) is missing the end time!\n", + p->filename, p->startline, p->endline, p->u1.str); + warns++; + } + if (sscanf(times, "%d:%d", &s1, &s2) != 2) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) isn't quite right!\n", + p->filename, p->startline, p->endline, times); + warns++; + } + if (sscanf(e, "%d:%d", &e1, &e2) != 2) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) isn't quite right!\n", + p->filename, p->startline, p->endline, times); + warns++; + } + + s1 = s1 * 30 + s2/2; + if ((s1 < 0) || (s1 >= 24*30)) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start time (%s) is out of range!\n", + p->filename, p->startline, p->endline, times); + warns++; + } + e1 = e1 * 30 + e2/2; + if ((e1 < 0) || (e1 >= 24*30)) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end time (%s) is out of range!\n", + p->filename, p->startline, p->endline, e); + warns++; + } + return; +} + +static char *days[] = +{ + "sun", + "mon", + "tue", + "wed", + "thu", + "fri", + "sat", +}; + +/*! \brief get_dow: Get day of week */ +static void check_dow(pval *DOW) +{ + char dow[200]; + char *c; + /* The following line is coincidence, really! */ + int s, e; + + strncpy(dow,DOW->u1.str,sizeof(dow)); + + /* Check for all days */ + if (ast_strlen_zero(dow) || !strcmp(dow, "*")) + return; + /* Get start and ending days */ + c = strchr(dow, '-'); + if (c) { + *c = '\0'; + c++; + } else + c = NULL; + /* Find the start */ + s = 0; + while ((s < 7) && strcasecmp(dow, days[s])) s++; + if (s >= 7) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n", + DOW->filename, DOW->startline, DOW->endline, dow); + warns++; + } + if (c) { + e = 0; + while ((e < 7) && strcasecmp(c, days[e])) e++; + if (e >= 7) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day (%s) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'!\n", + DOW->filename, DOW->startline, DOW->endline, c); + warns++; + } + } else + e = s; +} + +static void check_day(pval *DAY) +{ + char day[200]; + char *c; + /* The following line is coincidence, really! */ + int s, e; + + strncpy(day,DAY->u1.str,sizeof(day)); + /* Check for all days */ + if (ast_strlen_zero(day) || !strcmp(day, "*")) { + return; + } + /* Get start and ending days */ + c = strchr(day, '-'); + if (c) { + *c = '\0'; + c++; + } + /* Find the start */ + if (sscanf(day, "%d", &s) != 1) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number!\n", + DAY->filename, DAY->startline, DAY->endline, day); + warns++; + } + else if ((s < 1) || (s > 31)) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start day of month (%s) must be a number in the range [1-31]!\n", + DAY->filename, DAY->startline, DAY->endline, day); + warns++; + } + s--; + if (c) { + if (sscanf(c, "%d", &e) != 1) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number!\n", + DAY->filename, DAY->startline, DAY->endline, c); + warns++; + } + else if ((e < 1) || (e > 31)) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end day of month (%s) must be a number in the range [1-31]!\n", + DAY->filename, DAY->startline, DAY->endline, day); + warns++; + } + e--; + } else + e = s; +} + +static char *months[] = +{ + "jan", + "feb", + "mar", + "apr", + "may", + "jun", + "jul", + "aug", + "sep", + "oct", + "nov", + "dec", +}; + +static void check_month(pval *MON) +{ + char mon[200]; + char *c; + /* The following line is coincidence, really! */ + int s, e; + + strncpy(mon,MON->u1.str,sizeof(mon)); + /* Check for all days */ + if (ast_strlen_zero(mon) || !strcmp(mon, "*")) + return ; + /* Get start and ending days */ + c = strchr(mon, '-'); + if (c) { + *c = '\0'; + c++; + } + /* Find the start */ + s = 0; + while ((s < 12) && strcasecmp(mon, months[s])) s++; + if (s >= 12) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The start month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", + MON->filename, MON->startline, MON->endline, mon); + warns++; + } + if (c) { + e = 0; + while ((e < 12) && strcasecmp(mon, months[e])) e++; + if (e >= 12) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The end month (%s) must be a one of: 'jan', 'feb', ..., 'dec'!\n", + MON->filename, MON->startline, MON->endline, c); + warns++; + } + } else + e = s; +} + +/* general purpose goto finder */ + + +static void check_goto(pval *item) +{ + /* check for the target of the goto-- does it exist? */ + if ( !(item->u1.list)->next && !(item->u1.list)->u1.str ) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: empty label reference found!\n", + item->filename, item->startline, item->endline); + errs++; + } + + /* just one item-- the label should be in the current extension */ + + if (item->u1.list && !item->u1.list->next && !strstr((item->u1.list)->u1.str,"${")) { + struct pval *x = find_label_in_current_extension((char*)((item->u1.list)->u1.str)); + /* printf("Calling find_label_in_current_extension with args %s\n", + (char*)((item->u1.list)->u1.str)); */ + if (!x) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s exists in the current extension!\n", + item->filename, item->startline, item->endline, item->u1.list->u1.str); + errs++; + } + else + return; + } + + /* TWO items */ + if (item->u1.list->next && !item->u1.list->next->next) { + /* two items */ + /* printf("Calling find_label_in_current_context with args %s, %s\n", + (char*)((item->u1.list)->u1.str), (char *)item->u1.list->next->u1.str); */ + if (!strstr((item->u1.list)->u1.str,"${") + && !strstr(item->u1.list->next->u1.str,"${") ) /* Don't try to match variables */ { + struct pval *x = find_label_in_current_context((char *)item->u1.list->u1.str, (char *)item->u1.list->next->u1.str); + if (!x) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the current context, or any of its inclusions!\n", + item->filename, item->startline, item->endline, item->u1.list->u1.str, item->u1.list->next->u1.str ); + errs++; + } + else + return; + } + } + + /* All 3 items! */ + if (item->u1.list->next && item->u1.list->next->next) { + /* all three */ + pval *first = item->u1.list; + pval *second = item->u1.list->next; + pval *third = item->u1.list->next->next; + + /* printf("Calling find_label_in_current_context with args %s, %s, %s\n", + (char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); */ + if (!strstr((item->u1.list)->u1.str,"${") + && !strstr(item->u1.list->next->u1.str,"${") + && !strstr(item->u1.list->next->next->u1.str,"${")) /* Don't try to match variables */ { + struct pval *x = find_label_in_current_db((char*)first->u1.str, (char*)second->u1.str, (char*)third->u1.str); + if (!x) { + struct pval *p3; + struct pval *found = 0; + struct pval *that_context = find_context(item->u1.list->u1.str); + + /* the target of the goto could be in an included context!! Fancy that!! */ + /* look for includes in the current context */ + if (that_context) { + for (p3=that_context->u2.statements; p3; p3=p3->next) { + if (p3->type == PV_INCLUDES) { + struct pval *p4; + for (p4=p3->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + char *incl_context = p4->u1.str; + /* find a matching context name */ + struct pval *that_other_context = find_context(incl_context); + if (that_other_context) { + struct pval *context_save = current_context; + current_context = that_other_context; + struct pval *x3 = find_label_in_current_context((char *)item->u1.list->next->u1.str, (char *)item->u1.list->next->next->u1.str); + current_context = context_save; + if (x3) { + found = x3; + break; + } + } + } + } + } + if (!found) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no label %s|%s exists in the context %s or its inclusions!\n", + item->filename, item->startline, item->endline, item->u1.list->next->u1.str, item->u1.list->next->next->u1.str, item->u1.list->u1.str ); + errs++; + } + } else { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: goto: no context %s could be found that matches the goto target!\n", + item->filename, item->startline, item->endline, item->u1.list->u1.str); + errs++; + } + } + } + } +} + + +static void find_pval_goto_item(pval *item, int lev) +{ + struct pval *p4; + if (lev>100) { + ast_log(LOG_ERROR,"find_pval_goto in infinite loop!\n\n"); + return; + } + + switch ( item->type ) { + case PV_MACRO: + /* fields: item->u1.str == name of macro + item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + + item->u3.macro_statements == pval list of statements in macro body. + */ + + /* printf("Descending into matching macro %s\n", match_context); */ + find_pval_gotos(item->u2.statements,lev+1); /* if we're just searching for a context, don't bother descending into them */ + + break; + + case PV_CONTEXT: + /* fields: item->u1.str == name of context + item->u2.statements == pval list of statements in context body + item->u3.abstract == int 1 if an abstract keyword were present + */ + break; + + case PV_CASE: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + find_pval_gotos(item->u2.statements,lev+1); + break; + + case PV_PATTERN: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + find_pval_gotos(item->u2.statements,lev+1); + break; + + case PV_DEFAULT: + /* fields: + item->u2.statements == pval list of statements under the case + */ + find_pval_gotos(item->u2.statements,lev+1); + break; + + case PV_CATCH: + /* fields: item->u1.str == name of extension to catch + item->u2.statements == pval list of statements in context body + */ + find_pval_gotos(item->u2.statements,lev+1); + break; + + case PV_STATEMENTBLOCK: + /* fields: item->u1.list == pval list of statements in block, one per entry in the list + */ + find_pval_gotos(item->u1.list,lev+1); + break; + + case PV_GOTO: + /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. + item->u1.list->u1.str == where the data on a PV_WORD will always be. + */ + check_goto(item); /* THE WHOLE FUNCTION OF THIS ENTIRE ROUTINE!!!! */ + break; + + case PV_INCLUDES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + for (p4=item->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + char *incl_context = p4->u1.str; + /* find a matching context name */ + struct pval *that_context = find_context(incl_context); + if (that_context) { + find_pval_gotos(that_context,lev+1); /* keep working up the includes */ + } + } + break; + + case PV_FOR: + /* fields: item->u1.for_init == a string containing the initalizer + item->u2.for_test == a string containing the loop test + item->u3.for_inc == a string containing the loop increment + + item->u4.for_statements == a pval list of statements in the for () + */ + find_pval_gotos(item->u4.for_statements,lev+1); + break; + + case PV_WHILE: + /* fields: item->u1.str == the while conditional, as supplied by user + + item->u2.statements == a pval list of statements in the while () + */ + find_pval_gotos(item->u2.statements,lev+1); + break; + + case PV_RANDOM: + /* fields: item->u1.str == the random number expression, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + fall thru to PV_IF */ + + case PV_IFTIME: + /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + fall thru to PV_IF*/ + case PV_IF: + /* fields: item->u1.str == the if conditional, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + find_pval_gotos(item->u2.statements,lev+1); + + if (item->u3.else_statements) { + find_pval_gotos(item->u3.else_statements,lev+1); + } + break; + + case PV_SWITCH: + /* fields: item->u1.str == the switch expression + + item->u2.statements == a pval list of statements in the switch, + (will be case statements, most likely!) + */ + find_pval_gotos(item->u3.else_statements,lev+1); + break; + + case PV_EXTENSION: + /* fields: item->u1.str == the extension name, label, whatever it's called + + item->u2.statements == a pval list of statements in the extension + item->u3.hints == a char * hint argument + item->u4.regexten == an int boolean. non-zero says that regexten was specified + */ + + find_pval_gotos(item->u2.statements,lev+1); + break; + + default: + break; + } +} + +static void find_pval_gotos(pval *item,int lev) +{ + pval *i; + + for (i=item; i; i=i->next) { + + find_pval_goto_item(i, lev); + } +} + + + +/* general purpose label finder */ +static struct pval *match_pval_item(pval *item) +{ + pval *x; + + switch ( item->type ) { + case PV_MACRO: + /* fields: item->u1.str == name of macro + item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + + item->u3.macro_statements == pval list of statements in macro body. + */ + if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { + if (return_on_context_match && !strcmp(item->u1.str, match_context)) { + /* printf("Returning on matching macro %s\n", match_context); */ + return item; + } + + + if (!return_on_context_match) { + /* printf("Descending into matching macro %s\n", match_context); */ + if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { + return x; + } + } + } else { + /* printf("Skipping context/macro %s\n", item->u1.str); */ + } + + break; + + case PV_CONTEXT: + /* fields: item->u1.str == name of context + item->u2.statements == pval list of statements in context body + item->u3.abstract == int 1 if an abstract keyword were present + */ + if (!strcmp(match_context,"*") || !strcmp(item->u1.str, match_context)) { + if (return_on_context_match && !strcmp(item->u1.str, match_context)) { + /* printf("Returning on matching context %s\n", match_context); */ + return item; + } + + + if (!return_on_context_match ) { + /* printf("Descending into matching context %s\n", match_context); */ + if ((x=match_pval(item->u2.statements))) /* if we're just searching for a context, don't bother descending into them */ { + return x; + } + } + } else { + /* printf("Skipping context/macro %s\n", item->u1.str); */ + } + break; + + case PV_CASE: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + break; + + case PV_PATTERN: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + break; + + case PV_DEFAULT: + /* fields: + item->u2.statements == pval list of statements under the case + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + break; + + case PV_CATCH: + /* fields: item->u1.str == name of extension to catch + item->u2.statements == pval list of statements in context body + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + break; + + case PV_STATEMENTBLOCK: + /* fields: item->u1.list == pval list of statements in block, one per entry in the list + */ + if ((x=match_pval(item->u1.list))) { + return x; + } + break; + + case PV_LABEL: + /* fields: item->u1.str == label name + */ + /* printf("PV_LABEL %s (cont=%s, exten=%s\n", + item->u1.str, current_context->u1.str, current_extension->u1.str); */ + + if (count_labels) { + if (!strcmp(match_label, item->u1.str)) { + label_count++; + last_matched_label = item; + } + + } else { + if (!strcmp(match_label, item->u1.str)) { + return item; + } + } + break; + + case PV_FOR: + /* fields: item->u1.for_init == a string containing the initalizer + item->u2.for_test == a string containing the loop test + item->u3.for_inc == a string containing the loop increment + + item->u4.for_statements == a pval list of statements in the for () + */ + if ((x=match_pval(item->u4.for_statements))) { + return x; + } + break; + + case PV_WHILE: + /* fields: item->u1.str == the while conditional, as supplied by user + + item->u2.statements == a pval list of statements in the while () + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + break; + + case PV_RANDOM: + /* fields: item->u1.str == the random number expression, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + fall thru to PV_IF */ + + case PV_IFTIME: + /* fields: item->u1.list == the time values, 4 of them, as PV_WORD structs in a list + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + fall thru to PV_IF*/ + case PV_IF: + /* fields: item->u1.str == the if conditional, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + if ((x=match_pval(item->u2.statements))) { + return x; + } + if (item->u3.else_statements) { + if ((x=match_pval(item->u3.else_statements))) { + return x; + } + } + break; + + case PV_SWITCH: + /* fields: item->u1.str == the switch expression + + item->u2.statements == a pval list of statements in the switch, + (will be case statements, most likely!) + */ + if ((x=match_pval(item->u3.else_statements))) { + return x; + } + break; + + case PV_EXTENSION: + /* fields: item->u1.str == the extension name, label, whatever it's called + + item->u2.statements == a pval list of statements in the extension + item->u3.hints == a char * hint argument + item->u4.regexten == an int boolean. non-zero says that regexten was specified + */ + if (!strcmp(match_exten,"*") || extension_matches(item, match_exten, item->u1.str) ) { + /* printf("Descending into matching exten %s\n", match_exten); */ + if (strcmp(match_label,"1") == 0) { + if (item->u2.statements) { + struct pval *p5 = item->u2.statements; + while (p5 && p5->type == PV_LABEL) /* find the first non-label statement in this context. If it exists, there's a "1" */ + p5 = p5->next; + if (p5) + return p5; + else + return 0; + } + else + return 0; + } + + if ((x=match_pval(item->u2.statements))) { + return x; + } + } else { + /* printf("Skipping exten %s\n", item->u1.str); */ + } + break; + default: + break; + } + return 0; +} + +struct pval *match_pval(pval *item) +{ + pval *i; + + for (i=item; i; i=i->next) { + pval *x; + + if ((x = match_pval_item(i))) + return x; /* cut the search short */ + } + return 0; +} + + +int count_labels_in_current_context(char *label) +{ + label_count = 0; + count_labels = 1; + return_on_context_match = 0; + match_pval(current_context->u2.statements); + + return label_count; +} + +struct pval *find_label_in_current_context(char *exten, char *label) +{ + /* printf(" --- Got args %s, %s\n", exten, label); */ + struct pval *ret; + struct pval *p3; + + count_labels = 0; + return_on_context_match = 0; + match_context = "*"; + match_exten = exten; + match_label = label; + ret = match_pval(current_context->u2.statements); + if (ret) + return ret; + + /* the target of the goto could be in an included context!! Fancy that!! */ + /* look for includes in the current context */ + for (p3=current_context->u2.statements; p3; p3=p3->next) { + if (p3->type == PV_INCLUDES) { + struct pval *p4; + for (p4=p3->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + char *incl_context = p4->u1.str; + /* find a matching context name */ + struct pval *that_context = find_context(incl_context); + if (that_context) { + struct pval *context_save = current_context; + current_context = that_context; + struct pval *x3 = find_label_in_current_context(exten, label); + current_context = context_save; + if (x3) { + return x3; + } + } + } + } + } + return 0; +} + +struct pval *find_label_in_current_extension(char *label) +{ + /* printf(" --- Got args %s\n", label); */ + count_labels = 0; + return_on_context_match = 0; + match_context = "*"; + match_exten = "*"; + match_label = label; + if (! current_extension) /* macros have no current extension, the whole thing is one extension... */ + return match_pval(current_context->u3.macro_statements); + return match_pval(current_extension->u2.statements); +} + +struct pval *find_label_in_current_db(char *context, char *exten, char *label) +{ + /* printf(" --- Got args %s, %s, %s\n", context, exten, label); */ + count_labels = 0; + return_on_context_match = 0; + + match_context = context; + match_exten = exten; + match_label = label; + + return match_pval(current_db); +} + + +struct pval *find_macro(char *name) +{ + return_on_context_match = 1; + count_labels = 0; + match_context = name; + match_exten = "*"; /* don't really need to set these, shouldn't be reached */ + match_label = "*"; + return match_pval(current_db); +} + +struct pval *find_context(char *name) +{ + return_on_context_match = 1; + count_labels = 0; + match_context = name; + match_exten = "*"; /* don't really need to set these, shouldn't be reached */ + match_label = "*"; + return match_pval(current_db); +} + +int is_float(char *arg ) +{ + char *s; + for (s=arg; *s; s++) { + if (*s != '.' && (*s < '0' || *s > '9')) + return 0; + } + return 1; +} +int is_int(char *arg ) +{ + char *s; + for (s=arg; *s; s++) { + if (*s < '0' || *s > '9') + return 0; + } + return 1; +} +int is_empty(char *arg) +{ + if (!arg) + return 1; + if (*arg == 0) + return 1; + while (*arg) { + if (*arg != ' ' && *arg != '\t') + return 0; + arg++; + } + return 1; +} + +int option_matches_j( struct argdesc *should, pval *is, struct argapp *app) +{ + struct argchoice *ac; + char opcop[400],*q,*p; + + switch (should->dtype) { + case ARGD_OPTIONSET: + if ( strstr(is->u1.str,"${") ) + return 0; /* no checking anything if there's a var reference in there! */ + + strncpy(opcop,is->u1.str,sizeof(opcop)); + + for (q=opcop;*q;q++) { /* erase the innards of X(innard) type arguments, so we don't get confused later */ + if ( *q == '(' ) { + p = q+1; + while (*p && *p != ')' ) + *p++ = '+'; + q = p+1; + } + } + + for (ac=app->opts; ac; ac=ac->next) { + if (strlen(ac->name)>1 && strchr(ac->name,'(') == 0 && strcmp(ac->name,is->u1.str) == 0) /* multichar option, no parens, and a match? */ + return 0; + } + for (ac=app->opts; ac; ac=ac->next) { + if (strlen(ac->name)==1 || strchr(ac->name,'(')) { + char *p = strchr(opcop,ac->name[0]); /* wipe out all matched options in the user-supplied string */ + + if (p && *p == 'j') { + ast_log(LOG_ERROR, "Error: file %s, line %d-%d: The j option in the %s application call is not appropriate for AEL!\n", + is->filename, is->startline, is->endline, app->name); + errs++; + } + + if (p) { + *p = '+'; + if (ac->name[1] == '(') { + if (*(p+1) != '(') { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The %c option in the %s application call should have an (argument), but doesn't!\n", + is->filename, is->startline, is->endline, ac->name[0], app->name); + warns++; + } + } + } + } + } + for (q=opcop; *q; q++) { + if ( *q != '+' && *q != '(' && *q != ')') { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: The %c option in the %s application call is not available as an option!\n", + is->filename, is->startline, is->endline, *q, app->name); + warns++; + } + } + return 1; + break; + default: + return 0; + } + +} + +int option_matches( struct argdesc *should, pval *is, struct argapp *app) +{ + struct argchoice *ac; + char opcop[400]; + + switch (should->dtype) { + case ARGD_STRING: + if (is_empty(is->u1.str) && should->type == ARGD_REQUIRED) + return 0; + if (is->u1.str && strlen(is->u1.str) > 0) /* most will match */ + return 1; + break; + + case ARGD_INT: + if (is_int(is->u1.str)) + return 1; + else + return 0; + break; + + case ARGD_FLOAT: + if (is_float(is->u1.str)) + return 1; + else + return 0; + break; + + case ARGD_ENUM: + if( !is->u1.str || strlen(is->u1.str) == 0 ) + return 1; /* a null arg in the call will match an enum, I guess! */ + for (ac=should->choices; ac; ac=ac->next) { + if (strcmp(ac->name,is->u1.str) == 0) + return 1; + } + return 0; + break; + + case ARGD_OPTIONSET: + strncpy(opcop,is->u1.str,sizeof(opcop)); + + for (ac=app->opts; ac; ac=ac->next) { + if (strlen(ac->name)>1 && strchr(ac->name,'(') == 0 && strcmp(ac->name,is->u1.str) == 0) /* multichar option, no parens, and a match? */ + return 1; + } + for (ac=app->opts; ac; ac=ac->next) { + if (strlen(ac->name)==1 || strchr(ac->name,'(')) { + char *p = strchr(opcop,ac->name[0]); /* wipe out all matched options in the user-supplied string */ + + if (p) { + *p = '+'; + if (ac->name[1] == '(') { + if (*(p+1) == '(') { + char *q = p+1; + while (*q && *q != ')') { + *q++ = '+'; + } + *q = '+'; + } + } + } + } + } + return 1; + break; + case ARGD_VARARG: + return 1; /* matches anything */ + break; + } + return 1; /* unless some for-sure match or non-match returns, then it must be close enough ... */ +} + +int check_app_args(pval* appcall, pval *arglist, struct argapp *app) +{ + struct argdesc *ad = app->args; + pval *pa; + int z; + + for (pa = arglist; pa; pa=pa->next) { + if (!ad) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Extra argument %s not in application call to %s !\n", + arglist->filename, arglist->startline, arglist->endline, pa->u1.str, app->name); + warns++; + return 1; + } else { + /* find the first entry in the ad list that will match */ + do { + if ( ad->dtype == ARGD_VARARG ) /* once we hit the VARARG, all bets are off. Discontinue the comparisons */ + break; + + z= option_matches( ad, pa, app); + if (!z) { + if ( !arglist ) + arglist=appcall; + + if (ad->type == ARGD_REQUIRED) { + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", + arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); + warns++; + return 1; + } + } else if (z && ad->dtype == ARGD_OPTIONSET) { + option_matches_j( ad, pa, app); + } + ad = ad->next; + } while (ad && !z); + } + } + /* any app nodes left, that are not optional? */ + for ( ; ad; ad=ad->next) { + if (ad->type == ARGD_REQUIRED && ad->dtype != ARGD_VARARG) { + if ( !arglist ) + arglist=appcall; + ast_log(LOG_WARNING, "Warning: file %s, line %d-%d: Required argument %s not in application call to %s !\n", + arglist->filename, arglist->startline, arglist->endline, ad->dtype==ARGD_OPTIONSET?"options":ad->name, app->name); + warns++; + return 1; + } + } + return 0; +} + +void check_switch_expr(pval *item, struct argapp *apps) +{ + /* get and clean the variable name */ + char buff1[1024],*p; + struct argapp *a,*a2; + struct appsetvar *v,*v2; + struct argchoice *c; + pval *t; + + p = item->u1.str; + while (p && *p && (*p == ' ' || *p == '\t' || *p == '$' || *p == '{' ) ) + p++; + + strncpy(buff1,p,sizeof(buff1)); + while (strlen(buff1) > 0 && ( buff1[strlen(buff1)-1] == '}' || buff1[strlen(buff1)-1] == ' ' || buff1[strlen(buff1)-1] == '\t')) + buff1[strlen(buff1)-1] = 0; + /* buff1 now contains the variable name */ + v = 0; + for (a=apps; a; a=a->next) { + for (v=a->setvars;v;v=v->next) { + if (strcmp(v->name,buff1) == 0) { + break; + } + } + if ( v ) + break; + } + if (v && v->vals) { + /* we have a match, to a variable that has a set of determined values */ + int def= 0; + int pat = 0; + int f1 = 0; + + /* first of all, does this switch have a default case ? */ + for (t=item->u2.statements; t; t=t->next) { + if (t->type == PV_DEFAULT) { + def =1; + break; + } + if (t->type == PV_PATTERN) { + pat++; + } + } + if (def || pat) /* nothing to check. All cases accounted for! */ + return; + for (c=v->vals; c; c=c->next) { + f1 = 0; + for (t=item->u2.statements; t; t=t->next) { + if (t->type == PV_CASE || t->type == PV_PATTERN) { + if (!strcmp(t->u1.str,c->name)) { + f1 = 1; + break; + } + } + } + if (!f1) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: switch with expression(%s) does not handle the case of %s !\n", + item->filename, item->startline, item->endline, item->u1.str, c->name); + warns++; + } + } + /* next, is there an app call in the current exten, that would set this var? */ + f1 = 0; + t = current_extension->u2.statements; + if ( t && t->type == PV_STATEMENTBLOCK ) + t = t->u1.statements; + for (; t && t != item; t=t->next) { + if (t->type == PV_APPLICATION_CALL) { + /* find the application that matches the u1.str */ + for (a2=apps; a2; a2=a2->next) { + if (strcasecmp(a2->name, t->u1.str)==0) { + for (v2=a2->setvars; v2; v2=v2->next) { + if (strcmp(v2->name, buff1) == 0) { + /* found an app that sets the var */ + f1 = 1; + break; + } + } + } + if (f1) + break; + } + } + if (f1) + break; + } + + /* see if it sets the var */ + if (!f1) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find an application call in this extension that sets the expression (%s) value!\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + } +} + +static void check_context_names(void) +{ + pval *i,*j; + for (i=current_db; i; i=i->next) { + if (i->type == PV_CONTEXT || i->type == PV_MACRO) { + for (j=i->next; j; j=j->next) { + if ( j->type == PV_CONTEXT || j->type == PV_MACRO ) { + if ( !strcmp(i->u1.str, j->u1.str) ) + { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: The context name (%s) is also declared in file %s, line %d-%d!\n", + i->filename, i->startline, i->endline, i->u1.str, j->filename, j->startline, j->endline); + warns++; + } + } + } + } + } +} + +static void check_abstract_reference(pval *abstract_context) +{ + pval *i,*j; + /* find some context includes that reference this context */ + + + /* otherwise, print out a warning */ + for (i=current_db; i; i=i->next) { + if (i->type == PV_CONTEXT) { + for (j=i->u2. statements; j; j=j->next) { + if ( j->type == PV_INCLUDES ) { + struct pval *p4; + for (p4=j->u1.list; p4; p4=p4->next) { + /* for each context pointed to, find it, then find a context/label that matches the + target here! */ + if ( !strcmp(p4->u1.str, abstract_context->u1.str) ) + return; /* found a match! */ + } + } + } + } + } + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: Couldn't find a reference to this abstract context (%s) in any other context!\n", + abstract_context->filename, abstract_context->startline, abstract_context->endline, abstract_context->u1.str); + warns++; +} + + +void check_pval_item(pval *item, struct argapp *apps) +{ + pval *lp; + struct argapp *app, *found; + struct pval *macro_def; + struct pval *app_def; + + char errmsg[4096]; + char *strp; + + switch (item->type) { + case PV_WORD: + /* fields: item->u1.str == string associated with this (word). + item->u2.arglist == pval list of 4 PV_WORD elements for time values (only in PV_INCLUDES) */ + break; + + case PV_MACRO: + /* fields: item->u1.str == name of macro + item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + + item->u3.macro_statements == pval list of statements in macro body. + */ + in_abstract_context = 0; + current_context = item; + current_extension = 0; + for (lp=item->u2.arglist; lp; lp=lp->next) { + + } + check_pval(item->u3.macro_statements, apps); + break; + + case PV_CONTEXT: + /* fields: item->u1.str == name of context + item->u2.statements == pval list of statements in context body + item->u3.abstract == int 1 if an abstract keyword were present + */ + current_context = item; + current_extension = 0; + if ( item->u3.abstract ) { + in_abstract_context = 1; + check_abstract_reference(item); + } else + in_abstract_context = 0; + check_pval(item->u2.statements, apps); + break; + + case PV_MACRO_CALL: + /* fields: item->u1.str == name of macro to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + macro_def = find_macro(item->u1.str); + if (!macro_def) { + ast_log(LOG_ERROR, "Error: file %s, line %d-%d: macro call to non-existent %s !\n", + item->filename, item->startline, item->endline, item->u1.str); + errs++; + } else if (macro_def->type != PV_MACRO) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: macro call to %s references a context, not a macro!\n", + item->filename, item->startline, item->endline, item->u1.str); + errs++; + } else { + /* macro_def is a MACRO, so do the args match in number? */ + int hereargs = 0; + int thereargs = 0; + + for (lp=item->u2.arglist; lp; lp=lp->next) { + hereargs++; + } + for (lp=macro_def->u2.arglist; lp; lp=lp->next) { + thereargs++; + } + if (hereargs != thereargs ) { + ast_log(LOG_ERROR, "Error: file %s, line %d-%d: The macro call to %s has %d arguments, but the macro definition has %d arguments\n", + item->filename, item->startline, item->endline, item->u1.str, hereargs, thereargs); + errs++; + } + } + break; + + case PV_APPLICATION_CALL: + /* fields: item->u1.str == name of application to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + /* Need to check to see if the application is available! */ + app_def = find_context(item->u1.str); + if (app_def && app_def->type == PV_MACRO) { + ast_log(LOG_ERROR,"Error: file %s, line %d-%d: application call to %s references an existing macro, but had no & preceding it!\n", + item->filename, item->startline, item->endline, item->u1.str); + errs++; + } + if (strcasecmp(item->u1.str,"GotoIf") == 0 + || strcasecmp(item->u1.str,"GotoIfTime") == 0 + || strcasecmp(item->u1.str,"while") == 0 + || strcasecmp(item->u1.str,"endwhile") == 0 + || strcasecmp(item->u1.str,"random") == 0 + || strcasecmp(item->u1.str,"execIf") == 0 ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s needs to be re-written using AEL if, while, goto, etc. keywords instead!\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + found = 0; + for (app=apps; app; app=app->next) { + if (strcasecmp(app->name, item->u1.str) == 0) { + found =app; + break; + } + } + if (!found) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: application call to %s not listed in applist database!\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } else + check_app_args(item, item->u2.arglist, app); + break; + + case PV_CASE: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + /* Make sure sequence of statements under case is terminated with goto, return, or break */ + /* find the last statement */ + check_pval(item->u2.statements, apps); + break; + + case PV_PATTERN: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + /* Make sure sequence of statements under case is terminated with goto, return, or break */ + /* find the last statement */ + + check_pval(item->u2.statements, apps); + break; + + case PV_DEFAULT: + /* fields: + item->u2.statements == pval list of statements under the case + */ + + check_pval(item->u2.statements, apps); + break; + + case PV_CATCH: + /* fields: item->u1.str == name of extension to catch + item->u2.statements == pval list of statements in context body + */ + check_pval(item->u2.statements, apps); + break; + + case PV_SWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + check_pval(item->u1.list, apps); + break; + + case PV_ESWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + check_pval(item->u1.list, apps); + break; + + case PV_INCLUDES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + check_pval(item->u1.list, apps); + for (lp=item->u1.list; lp; lp=lp->next){ + char *incl_context = lp->u1.str; + struct pval *that_context = find_context(incl_context); + + if ( lp->u2.arglist ) { + check_timerange(lp->u2.arglist); + check_dow(lp->u2.arglist->next); + check_day(lp->u2.arglist->next->next); + check_month(lp->u2.arglist->next->next->next); + } + + if (that_context) { + find_pval_gotos(that_context->u2.statements,0); + + } + } + break; + + case PV_STATEMENTBLOCK: + /* fields: item->u1.list == pval list of statements in block, one per entry in the list + */ + check_pval(item->u1.list, apps); + break; + + case PV_VARDEC: + /* fields: item->u1.str == variable name + item->u2.val == variable value to assign + */ + /* the RHS of a vardec is encapsulated in a $[] expr. Is it legal? */ + snprintf(errmsg,sizeof(errmsg), "file %s, line %d, columns %d-%d, variable declaration expr '%s':", config, item->startline, item->startcol, item->endcol, item->u2.val); + ast_expr_register_extra_error_info(errmsg); + ast_expr(item->u2.val, expr_output, sizeof(expr_output)); + ast_expr_clear_extra_error_info(); + if ( strpbrk(item->u2.val,"~!-+<>=*/&^") && !strstr(item->u2.val,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u2.val); + warns++; + } + check_expr2_input(item,item->u2.val); + break; + + case PV_GOTO: + /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. + item->u1.list->u1.str == where the data on a PV_WORD will always be. + */ + /* don't check goto's in abstract contexts */ + if ( in_abstract_context ) + break; + + check_goto(item); + break; + + case PV_LABEL: + /* fields: item->u1.str == label name + */ + if ( strspn(item->u1.str, "0123456789") == strlen(item->u1.str) ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: label '%s' is numeric, this is bad practice!\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + break; + + case PV_FOR: + /* fields: item->u1.for_init == a string containing the initalizer + item->u2.for_test == a string containing the loop test + item->u3.for_inc == a string containing the loop increment + + item->u4.for_statements == a pval list of statements in the for () + */ + snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, for test expr '%s':", config, item->startline, item->startcol, item->endcol, item->u2.for_test); + ast_expr_register_extra_error_info(errmsg); + + strp = strchr(item->u1.for_init, '='); + if (strp) { + ast_expr(strp+1, expr_output, sizeof(expr_output)); + } + ast_expr(item->u2.for_test, expr_output, sizeof(expr_output)); + strp = strchr(item->u3.for_inc, '='); + if (strp) { + ast_expr(strp+1, expr_output, sizeof(expr_output)); + } + if ( strpbrk(item->u2.for_test,"~!-+<>=*/&^") && !strstr(item->u2.for_test,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u2.for_test); + warns++; + } + if ( strpbrk(item->u3.for_inc,"~!-+<>=*/&^") && !strstr(item->u3.for_inc,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u3.for_inc); + warns++; + } + check_expr2_input(item,item->u2.for_test); + check_expr2_input(item,item->u3.for_inc); + + ast_expr_clear_extra_error_info(); + check_pval(item->u4.for_statements, apps); + break; + + case PV_WHILE: + /* fields: item->u1.str == the while conditional, as supplied by user + + item->u2.statements == a pval list of statements in the while () + */ + snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, while expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); + ast_expr_register_extra_error_info(errmsg); + ast_expr(item->u1.str, expr_output, sizeof(expr_output)); + ast_expr_clear_extra_error_info(); + if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression %s has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + check_expr2_input(item,item->u1.str); + check_pval(item->u2.statements, apps); + break; + + case PV_BREAK: + /* fields: none + */ + break; + + case PV_RETURN: + /* fields: none + */ + break; + + case PV_CONTINUE: + /* fields: none + */ + break; + + case PV_RANDOM: + /* fields: item->u1.str == the random number expression, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, random expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); + ast_expr_register_extra_error_info(errmsg); + ast_expr(item->u1.str, expr_output, sizeof(expr_output)); + ast_expr_clear_extra_error_info(); + if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: random expression '%s' has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + check_expr2_input(item,item->u1.str); + check_pval(item->u2.statements, apps); + if (item->u3.else_statements) { + check_pval(item->u3.else_statements, apps); + } + break; + + case PV_IFTIME: + /* fields: item->u1.list == the if time values, 4 of them, each in PV_WORD, linked list + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + if ( item->u2.arglist ) { + check_timerange(item->u1.list); + check_dow(item->u1.list->next); + check_day(item->u1.list->next->next); + check_month(item->u1.list->next->next->next); + } + + check_pval(item->u2.statements, apps); + if (item->u3.else_statements) { + check_pval(item->u3.else_statements, apps); + } + break; + + case PV_IF: + /* fields: item->u1.str == the if conditional, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + snprintf(errmsg,sizeof(errmsg),"file %s, line %d, columns %d-%d, if expr '%s':", config, item->startline, item->startcol, item->endcol, item->u1.str); + ast_expr_register_extra_error_info(errmsg); + ast_expr(item->u1.str, expr_output, sizeof(expr_output)); + ast_expr_clear_extra_error_info(); + if ( strpbrk(item->u1.str,"~!-+<>=*/&^") && !strstr(item->u1.str,"${") ) { + ast_log(LOG_WARNING,"Warning: file %s, line %d-%d: expression '%s' has operators, but no variables. Interesting...\n", + item->filename, item->startline, item->endline, item->u1.str); + warns++; + } + check_expr2_input(item,item->u1.str); + check_pval(item->u2.statements, apps); + if (item->u3.else_statements) { + check_pval(item->u3.else_statements, apps); + } + break; + + case PV_SWITCH: + /* fields: item->u1.str == the switch expression + + item->u2.statements == a pval list of statements in the switch, + (will be case statements, most likely!) + */ + /* we can check the switch expression, see if it matches any of the app variables... + if it does, then, are all the possible cases accounted for? */ + check_switch_expr(item, apps); + check_pval(item->u2.statements, apps); + break; + + case PV_EXTENSION: + /* fields: item->u1.str == the extension name, label, whatever it's called + + item->u2.statements == a pval list of statements in the extension + item->u3.hints == a char * hint argument + item->u4.regexten == an int boolean. non-zero says that regexten was specified + */ + current_extension = item ; + + check_pval(item->u2.statements, apps); + break; + + case PV_IGNOREPAT: + /* fields: item->u1.str == the ignorepat data + */ + break; + + case PV_GLOBALS: + /* fields: item->u1.statements == pval list of statements, usually vardecs + */ + in_abstract_context = 0; + check_pval(item->u1.statements, apps); + break; + default: + break; + } +} + +void check_pval(pval *item, struct argapp *apps) +{ + pval *i; + + /* checks to do: + 1. Do goto's point to actual labels? + 2. Do macro calls reference a macro? + 3. Does the number of macro args match the definition? + 4. Is a macro call missing its & at the front? + 5. Application calls-- we could check syntax for existing applications, + but I need some some sort of universal description bnf for a general + sort of method for checking arguments, in number, maybe even type, at least. + Don't want to hand code checks for hundreds of applications. + */ + + for (i=item; i; i=i->next) { + check_pval_item(i,apps); + } +} + +void ael2_semantic_check(pval *item, int *arg_errs, int *arg_warns, int *arg_notes) +{ + + int argapp_errs =0; + char *rfilename; + struct argapp *apps; + + rfilename = alloca(10 + strlen(ast_config_AST_VAR_DIR)); + sprintf(rfilename, "%s/applist", ast_config_AST_VAR_DIR); + + apps = argdesc_parse(rfilename, &argapp_errs); /* giveth */ + + current_db = item; + errs = warns = notes = 0; + + check_context_names(); + check_pval(item, apps); + + argdesc_destroy(apps); /* taketh away */ + + *arg_errs = errs; + *arg_warns = warns; + *arg_notes = notes; +} + +/* =============================================================================================== */ +/* "CODE" GENERATOR -- Convert the AEL representation to asterisk extension language */ +/* =============================================================================================== */ + +static int control_statement_count = 0; + +struct ael_priority *new_prio(void) +{ + struct ael_priority *x = (struct ael_priority *)calloc(sizeof(struct ael_priority),1); + return x; +} + +struct ael_extension *new_exten(void) +{ + struct ael_extension *x = (struct ael_extension *)calloc(sizeof(struct ael_extension),1); + return x; +} + +void linkprio(struct ael_extension *exten, struct ael_priority *prio) +{ + if (!exten->plist) { + exten->plist = prio; + exten->plist_last = prio; + } else { + exten->plist_last->next = prio; + exten->plist_last = prio; + } +} + +void destroy_extensions(struct ael_extension *exten) +{ + struct ael_extension *ne, *nen; + for (ne=exten; ne; ne=nen) { + struct ael_priority *pe, *pen; + + if (ne->name) + free(ne->name); + + if (ne->hints) + free(ne->hints); + + for (pe=ne->plist; pe; pe=pen) { + pen = pe->next; + if (pe->app) + free(pe->app); + pe->app = 0; + if (pe->appargs) + free(pe->appargs); + pe->appargs = 0; + pe->origin = 0; + pe->goto_true = 0; + pe->goto_false = 0; + free(pe); + } + nen = ne->next_exten; + ne->next_exten = 0; + ne->plist =0; + ne->plist_last = 0; + ne->next_exten = 0; + ne->loop_break = 0; + ne->loop_continue = 0; + free(ne); + } +} + +void linkexten(struct ael_extension *exten, struct ael_extension *add) +{ + add->next_exten = exten->next_exten; /* this will reverse the order. Big deal. */ + exten->next_exten = add; +} + +void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten ) +{ + pval *p,*p2,*p3; + struct ael_priority *pr; + struct ael_priority *for_init, *for_test, *for_inc, *for_loop, *for_end; + struct ael_priority *while_test, *while_loop, *while_end; + struct ael_priority *switch_test, *switch_end, *fall_thru; + struct ael_priority *if_test, *if_end, *if_skip, *if_false; +#ifdef OLD_RAND_ACTION + struct ael_priority *rand_test, *rand_end, *rand_skip; +#endif + char buf1[2000]; + char buf2[2000]; + char *strp, *strp2; + char new_label[2000]; + int default_exists; + struct ael_priority *loop_break_save; + struct ael_priority *loop_continue_save; + struct ael_extension *switch_case; + + for (p=statement; p; p=p->next) { + switch (p->type) { + case PV_VARDEC: + pr = new_prio(); + pr->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"%s=$[%s]", p->u1.str, p->u2.val); + pr->app = strdup("Set"); + pr->appargs = strdup(buf1); + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_GOTO: + pr = new_prio(); + pr->type = AEL_APPCALL; + if (!p->u1.list->next) /* just one */ { + pr->app = strdup("Goto"); + if (!mother_exten) + pr->appargs = strdup(p->u1.list->u1.str); + else { /* for the case of simple within-extension gotos in case/pattern/default statement blocks: */ + snprintf(buf1,sizeof(buf1),"%s|%s", mother_exten->name, p->u1.list->u1.str); + pr->appargs = strdup(buf1); + } + + } else if (p->u1.list->next && !p->u1.list->next->next) /* two */ { + snprintf(buf1,sizeof(buf1),"%s|%s", p->u1.list->u1.str, p->u1.list->next->u1.str); + pr->app = strdup("Goto"); + pr->appargs = strdup(buf1); + } else if (p->u1.list->next && p->u1.list->next->next) { + snprintf(buf1,sizeof(buf1),"%s|%s|%s", p->u1.list->u1.str, + p->u1.list->next->u1.str, + p->u1.list->next->next->u1.str); + pr->app = strdup("Goto"); + pr->appargs = strdup(buf1); + } + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_LABEL: + pr = new_prio(); + pr->type = AEL_LABEL; + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_FOR: + control_statement_count++; + loop_break_save = exten->loop_break; /* save them, then restore before leaving */ + loop_continue_save = exten->loop_continue; + snprintf(new_label,sizeof(new_label),"for-%s-%d", label, control_statement_count); + for_init = new_prio(); + for_inc = new_prio(); + for_test = new_prio(); + for_loop = new_prio(); + for_end = new_prio(); + for_init->type = AEL_APPCALL; + for_inc->type = AEL_APPCALL; + for_test->type = AEL_FOR_CONTROL; + for_test->goto_false = for_end; + for_loop->type = AEL_CONTROL1; /* simple goto */ + for_end->type = AEL_APPCALL; + for_init->app = strdup("Set"); + + strcpy(buf2,p->u1.for_init); + strp = strchr(buf2, '='); + strp2 = strchr(p->u1.for_init, '='); + if (strp) { + *(strp+1) = 0; + strcat(buf2,"$["); + strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); + strcat(buf2,"]"); + for_init->appargs = strdup(buf2); + } else + for_init->appargs = strdup(p->u1.for_init); + + for_inc->app = strdup("Set"); + + strcpy(buf2,p->u3.for_inc); + strp = strchr(buf2, '='); + strp2 = strchr(p->u3.for_inc, '='); + if (strp) { + *(strp+1) = 0; + strcat(buf2,"$["); + strncat(buf2,strp2+1, sizeof(buf2)-strlen(strp2+1)-2); + strcat(buf2,"]"); + for_inc->appargs = strdup(buf2); + } else + for_inc->appargs = strdup(p->u3.for_inc); + snprintf(buf1,sizeof(buf1),"$[%s]",p->u2.for_test); + for_test->app = 0; + for_test->appargs = strdup(buf1); + for_loop->goto_true = for_test; + snprintf(buf1,sizeof(buf1),"Finish for-%s-%d", label, control_statement_count); + for_end->app = strdup("NoOp"); + for_end->appargs = strdup(buf1); + /* link & load! */ + linkprio(exten, for_init); + linkprio(exten, for_test); + + /* now, put the body of the for loop here */ + exten->loop_break = for_end; + exten->loop_continue = for_test; + + gen_prios(exten, new_label, p->u4.for_statements, mother_exten); /* this will link in all the statements here */ + + linkprio(exten, for_inc); + linkprio(exten, for_loop); + linkprio(exten, for_end); + + + exten->loop_break = loop_break_save; + exten->loop_continue = loop_continue_save; + for_loop->origin = p; + break; + + case PV_WHILE: + control_statement_count++; + loop_break_save = exten->loop_break; /* save them, then restore before leaving */ + loop_continue_save = exten->loop_continue; + snprintf(new_label,sizeof(new_label),"while-%s-%d", label, control_statement_count); + while_test = new_prio(); + while_loop = new_prio(); + while_end = new_prio(); + while_test->type = AEL_FOR_CONTROL; + while_test->goto_false = while_end; + while_loop->type = AEL_CONTROL1; /* simple goto */ + while_end->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); + while_test->app = 0; + while_test->appargs = strdup(buf1); + while_loop->goto_true = while_test; + snprintf(buf1,sizeof(buf1),"Finish while-%s-%d", label, control_statement_count); + while_end->app = strdup("NoOp"); + while_end->appargs = strdup(buf1); + + linkprio(exten, while_test); + + /* now, put the body of the for loop here */ + exten->loop_break = while_end; + exten->loop_continue = while_test; + + gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the while body statements here */ + + linkprio(exten, while_loop); + linkprio(exten, while_end); + + + exten->loop_break = loop_break_save; + exten->loop_continue = loop_continue_save; + while_loop->origin = p; + break; + + case PV_SWITCH: + control_statement_count++; + loop_break_save = exten->loop_break; /* save them, then restore before leaving */ + loop_continue_save = exten->loop_continue; + snprintf(new_label,sizeof(new_label),"sw-%s-%d", label, control_statement_count); + + switch_test = new_prio(); + switch_end = new_prio(); + switch_test->type = AEL_APPCALL; + switch_end->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"sw-%d-%s|1",control_statement_count, p->u1.str); + switch_test->app = strdup("Goto"); + switch_test->appargs = strdup(buf1); + snprintf(buf1,sizeof(buf1),"Finish switch-%s-%d", label, control_statement_count); + switch_end->app = strdup("NoOp"); + switch_end->appargs = strdup(buf1); + switch_end->origin = p; + switch_end->exten = exten; + + linkprio(exten, switch_test); + linkprio(exten, switch_end); + + exten->loop_break = switch_end; + exten->loop_continue = 0; + default_exists = 0; + + for (p2=p->u2.statements; p2; p2=p2->next) { + /* now, for each case/default put the body of the for loop here */ + if (p2->type == PV_CASE) { + /* ok, generate a extension and link it in */ + switch_case = new_exten(); + /* the break/continue locations are inherited from parent */ + switch_case->loop_break = exten->loop_break; + switch_case->loop_continue = exten->loop_continue; + + linkexten(exten,switch_case); + snprintf(buf1,sizeof(buf1),"sw-%d-%s", control_statement_count, p2->u1.str); + switch_case->name = strdup(buf1); + snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, control_statement_count); + + gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the case body statements here */ + + /* here is where we write code to "fall thru" to the next case... if there is one... */ + for (p3=p2->u2.statements; p3; p3=p3->next) { + if (!p3->next) + break; + } + /* p3 now points the last statement... */ + if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN) ) { + /* is there a following CASE/PATTERN/DEFAULT? */ + if (p2->next && p2->next->type == PV_CASE) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_PATTERN) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_DEFAULT) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-.|1",control_statement_count); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (!p2->next) { + fall_thru = new_prio(); + fall_thru->type = AEL_CONTROL1; + fall_thru->goto_true = switch_end; + fall_thru->app = strdup("Goto"); + linkprio(switch_case, fall_thru); + } + } + if (switch_case->return_needed) { + char buf[2000]; + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); + np2->appargs = strdup(buf); + linkprio(switch_case, np2); + switch_case-> return_target = np2; + } + } else if (p2->type == PV_PATTERN) { + /* ok, generate a extension and link it in */ + switch_case = new_exten(); + /* the break/continue locations are inherited from parent */ + switch_case->loop_break = exten->loop_break; + switch_case->loop_continue = exten->loop_continue; + + linkexten(exten,switch_case); + snprintf(buf1,sizeof(buf1),"_sw-%d-%s", control_statement_count, p2->u1.str); + switch_case->name = strdup(buf1); + snprintf(new_label,sizeof(new_label),"sw-%s-%s-%d", label, p2->u1.str, control_statement_count); + + gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the while body statements here */ + /* here is where we write code to "fall thru" to the next case... if there is one... */ + for (p3=p2->u2.statements; p3; p3=p3->next) { + if (!p3->next) + break; + } + /* p3 now points the last statement... */ + if (!p3 || ( p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { + /* is there a following CASE/PATTERN/DEFAULT? */ + if (p2->next && p2->next->type == PV_CASE) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_PATTERN) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_DEFAULT) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-.|1",control_statement_count); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (!p2->next) { + fall_thru = new_prio(); + fall_thru->type = AEL_CONTROL1; + fall_thru->goto_true = switch_end; + fall_thru->app = strdup("Goto"); + linkprio(switch_case, fall_thru); + } + } + if (switch_case->return_needed) { + char buf[2000]; + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); + np2->appargs = strdup(buf); + linkprio(switch_case, np2); + switch_case-> return_target = np2; + } + } else if (p2->type == PV_DEFAULT) { + default_exists++; + /* ok, generate a extension and link it in */ + switch_case = new_exten(); + /* the break/continue locations are inherited from parent */ + switch_case->loop_break = exten->loop_break; + switch_case->loop_continue = exten->loop_continue; + linkexten(exten,switch_case); + snprintf(buf1,sizeof(buf1),"_sw-%d-.", control_statement_count); + switch_case->name = strdup(buf1); + + snprintf(new_label,sizeof(new_label),"sw-%s-default-%d", label, control_statement_count); + + gen_prios(switch_case, new_label, p2->u2.statements, exten); /* this will link in all the while body statements here */ + + /* here is where we write code to "fall thru" to the next case... if there is one... */ + for (p3=p2->u2.statements; p3; p3=p3->next) { + if (!p3->next) + break; + } + /* p3 now points the last statement... */ + if (!p3 || (p3->type != PV_GOTO && p3->type != PV_BREAK && p3->type != PV_RETURN)) { + /* is there a following CASE/PATTERN/DEFAULT? */ + if (p2->next && p2->next->type == PV_CASE) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_PATTERN) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-%s|1",control_statement_count, p2->next->u1.str); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (p2->next && p2->next->type == PV_DEFAULT) { + fall_thru = new_prio(); + fall_thru->type = AEL_APPCALL; + fall_thru->app = strdup("Goto"); + snprintf(buf1,sizeof(buf1),"_sw-%d-.|1",control_statement_count); + fall_thru->appargs = strdup(buf1); + linkprio(switch_case, fall_thru); + } else if (!p2->next) { + fall_thru = new_prio(); + fall_thru->type = AEL_CONTROL1; + fall_thru->goto_true = switch_end; + fall_thru->app = strdup("Goto"); + linkprio(switch_case, fall_thru); + } + } + if (switch_case->return_needed) { + char buf[2000]; + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); + np2->appargs = strdup(buf); + linkprio(switch_case, np2); + switch_case-> return_target = np2; + } + } else { + /* what could it be??? */ + } + } + + exten->loop_break = loop_break_save; + exten->loop_continue = loop_continue_save; + switch_test->origin = p; + switch_end->origin = p; + break; + + case PV_MACRO_CALL: + pr = new_prio(); + pr->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"%s", p->u1.str); + for (p2 = p->u2.arglist; p2; p2 = p2->next) { + strcat(buf1,"|"); + strcat(buf1,p2->u1.str); + } + pr->app = strdup("Macro"); + pr->appargs = strdup(buf1); + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_APPLICATION_CALL: + pr = new_prio(); + pr->type = AEL_APPCALL; + buf1[0] = 0; + for (p2 = p->u2.arglist; p2; p2 = p2->next) { + if (p2 != p->u2.arglist ) + strcat(buf1,"|"); + strcat(buf1,p2->u1.str); + } + pr->app = strdup(p->u1.str); + pr->appargs = strdup(buf1); + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_BREAK: + pr = new_prio(); + pr->type = AEL_CONTROL1; /* simple goto */ + pr->goto_true = exten->loop_break; + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_RETURN: /* hmmmm */ + pr = new_prio(); + pr->type = AEL_RETURN; /* simple goto */ + exten->return_needed++; + pr->app = strdup("Goto"); + pr->appargs = strdup(""); + pr->origin = p; + linkprio(exten, pr); + break; + + case PV_CONTINUE: + pr = new_prio(); + pr->type = AEL_CONTROL1; /* simple goto */ + pr->goto_true = exten->loop_continue; + pr->origin = p; + linkprio(exten, pr); + break; + +#ifdef OLD_RAND_ACTION + case PV_RANDOM: + control_statement_count++; + snprintf(new_label,sizeof(new_label),"rand-%s-%d", label, control_statement_count); + rand_test = new_prio(); + rand_test->type = AEL_RAND_CONTROL; + snprintf(buf1,sizeof(buf1),"$[%s]", + p->u1.str ); + rand_test->app = 0; + rand_test->appargs = strdup(buf1); + rand_test->origin = p; + + rand_end = new_prio(); + rand_end->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"Finish rand-%s-%d", label, control_statement_count); + rand_end->app = strdup("NoOp"); + rand_end->appargs = strdup(buf1); + + rand_skip = new_prio(); + rand_skip->type = AEL_CONTROL1; /* simple goto */ + rand_skip->goto_true = rand_end; + rand_skip->origin = p; + + rand_test->goto_true = rand_skip; /* +1, really */ + + linkprio(exten, rand_test); + + if (p->u3.else_statements) { + gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the else statements here */ + } + + linkprio(exten, rand_skip); + + gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the "true" statements here */ + + linkprio(exten, rand_end); + + break; +#endif + + case PV_IFTIME: + control_statement_count++; + snprintf(new_label,sizeof(new_label),"iftime-%s-%d", label, control_statement_count); + + if_test = new_prio(); + if_test->type = AEL_IFTIME_CONTROL; + snprintf(buf1,sizeof(buf1),"%s|%s|%s|%s", + p->u1.list->u1.str, + p->u1.list->next->u1.str, + p->u1.list->next->next->u1.str, + p->u1.list->next->next->next->u1.str); + if_test->app = 0; + if_test->appargs = strdup(buf1); + if_test->origin = p; + + if_end = new_prio(); + if_end->type = AEL_APPCALL; + snprintf(buf1,sizeof(buf1),"Finish iftime-%s-%d", label, control_statement_count); + if_end->app = strdup("NoOp"); + if_end->appargs = strdup(buf1); + + if (p->u3.else_statements) { + if_skip = new_prio(); + if_skip->type = AEL_CONTROL1; /* simple goto */ + if_skip->goto_true = if_end; + if_skip->origin = p; + + } else { + if_skip = 0; + + if_test->goto_false = if_end; + } + + if_false = new_prio(); + if_false->type = AEL_CONTROL1; + if (p->u3.else_statements) { + if_false->goto_true = if_skip; /* +1 */ + } else { + if_false->goto_true = if_end; + } + + /* link & load! */ + linkprio(exten, if_test); + linkprio(exten, if_false); + + /* now, put the body of the if here */ + + gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the statements here */ + + if (p->u3.else_statements) { + linkprio(exten, if_skip); + gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the statements here */ + + } + + linkprio(exten, if_end); + + break; + + case PV_RANDOM: + case PV_IF: + control_statement_count++; + snprintf(new_label,sizeof(new_label),"if-%s-%d", label, control_statement_count); + + if_test = new_prio(); + if_end = new_prio(); + if_test->type = AEL_IF_CONTROL; + if_end->type = AEL_APPCALL; + if ( p->type == PV_RANDOM ) + snprintf(buf1,sizeof(buf1),"$[${RAND(0,99)} < (%s)]",p->u1.str); + else + snprintf(buf1,sizeof(buf1),"$[%s]",p->u1.str); + if_test->app = 0; + if_test->appargs = strdup(buf1); + snprintf(buf1,sizeof(buf1),"Finish if-%s-%d", label, control_statement_count); + if_end->app = strdup("NoOp"); + if_end->appargs = strdup(buf1); + if_test->origin = p; + + if (p->u3.else_statements) { + if_skip = new_prio(); + if_skip->type = AEL_CONTROL1; /* simple goto */ + if_skip->goto_true = if_end; + if_test->goto_false = if_skip;; + } else { + if_skip = 0; + if_test->goto_false = if_end;; + } + + /* link & load! */ + linkprio(exten, if_test); + + /* now, put the body of the if here */ + + gen_prios(exten, new_label, p->u2.statements, mother_exten); /* this will link in all the statements here */ + + if (p->u3.else_statements) { + linkprio(exten, if_skip); + gen_prios(exten, new_label, p->u3.else_statements, mother_exten); /* this will link in all the statements here */ + + } + + linkprio(exten, if_end); + + break; + + case PV_STATEMENTBLOCK: + gen_prios(exten, label, p->u1.list, mother_exten ); /* recurse into the block */ + break; + + case PV_CATCH: + control_statement_count++; + /* generate an extension with name of catch, put all catch stats + into this exten! */ + switch_case = new_exten(); + linkexten(exten,switch_case); + switch_case->name = strdup(p->u1.str); + snprintf(new_label,sizeof(new_label),"catch-%s-%d",p->u1.str, control_statement_count); + + gen_prios(switch_case, new_label, p->u2.statements,mother_exten); /* this will link in all the catch body statements here */ + if (switch_case->return_needed) { + char buf[2000]; + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Extension %s", switch_case->name); + np2->appargs = strdup(buf); + linkprio(switch_case, np2); + switch_case-> return_target = np2; + } + + break; + default: + break; + } + } +} + +void set_priorities(struct ael_extension *exten) +{ + int i; + struct ael_priority *pr; + do { + if (exten->regexten) + i=2; + else + i=1; + + for (pr=exten->plist; pr; pr=pr->next) { + pr->priority_num = i; + + if (!pr->origin || (pr->origin && pr->origin->type != PV_LABEL) ) /* Labels don't show up in the dialplan, + but we want them to point to the right + priority, which would be the next line + after the label; */ + i++; + } + + exten = exten->next_exten; + } while ( exten ); +} + +void add_extensions(struct ael_extension *exten, struct ast_context *context) +{ + struct ael_priority *pr; + char *label=0; + do { + struct ael_priority *last = 0; + + if (exten->hints) { + if (ast_add_extension2(context, 0 /*no replace*/, exten->name, PRIORITY_HINT, NULL, NULL, + exten->hints, NULL, FREE, registrar)) { + ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n", + exten->name); + } + + } + + for (pr=exten->plist; pr; pr=pr->next) { + char app[2000]; + char appargs[2000]; + + /* before we can add the extension, we need to prep the app/appargs; + the CONTROL types need to be done after the priority numbers are calculated. + */ + if (pr->type == AEL_LABEL) /* don't try to put labels in the dialplan! */ { + last = pr; + continue; + } + + if (pr->app) + strcpy(app, pr->app); + else + app[0] = 0; + if (pr->appargs ) + strcpy(appargs, pr->appargs); + else + appargs[0] = 0; + switch( pr->type ) { + case AEL_APPCALL: + /* easy case. Everything is all set up */ + break; + + case AEL_CONTROL1: /* FOR loop, WHILE loop, BREAK, CONTINUE, IF, IFTIME */ + /* simple, unconditional goto. */ + strcpy(app,"Goto"); + if (pr->goto_true->origin && pr->goto_true->origin->type == PV_SWITCH ) { + snprintf(appargs,sizeof(appargs),"%s|%d", pr->goto_true->exten->name, pr->goto_true->priority_num); + } else if (pr->goto_true->origin && pr->goto_true->origin->type == PV_IFTIME && pr->goto_true->origin->u3.else_statements ) { + snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num+1); + } else + snprintf(appargs,sizeof(appargs),"%d", pr->goto_true->priority_num); + break; + + case AEL_FOR_CONTROL: /* WHILE loop test, FOR loop test */ + strcpy(app,"GotoIf"); + snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); + break; + + case AEL_IF_CONTROL: + strcpy(app,"GotoIf"); + if (pr->origin->u3.else_statements ) + snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num+1); + else + snprintf(appargs,sizeof(appargs),"%s?%d:%d", pr->appargs, pr->priority_num+1, pr->goto_false->priority_num); + break; + + case AEL_RAND_CONTROL: + strcpy(app,"Random"); + snprintf(appargs,sizeof(appargs),"%s:%d", pr->appargs, pr->goto_true->priority_num+1); + break; + + case AEL_IFTIME_CONTROL: + strcpy(app,"GotoIfTime"); + snprintf(appargs,sizeof(appargs),"%s?%d", pr->appargs, pr->priority_num+2); + break; + + case AEL_RETURN: + strcpy(app,"Goto"); + snprintf(appargs,sizeof(appargs), "%d", exten->return_target->priority_num); + break; + + default: + break; + } + if (last && last->type == AEL_LABEL ) { + label = last->origin->u1.str; + } + else + label = 0; + + + if (ast_add_extension2(context, 0 /*no replace*/, exten->name, pr->priority_num, (label?label:NULL), NULL, + app, strdup(appargs), FREE, registrar)) { + ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, + exten->name); + } + last = pr; + } + exten = exten->next_exten; + } while ( exten ); +} + + +void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) +{ + pval *p,*p2; + struct ast_context *context; + char buf[2000]; + struct ael_extension *exten; + + for (p=root; p; p=p->next ) { + pval *lp; + int argc; + + switch (p->type) { + case PV_MACRO: + strcpy(buf,"macro-"); + strcat(buf,p->u1.str); + context = ast_context_create(local_contexts, buf, registrar); + + exten = new_exten(); + exten->name = strdup("s"); + argc = 1; + for (lp=p->u2.arglist; lp; lp=lp->next) { + /* for each arg, set up a "Set" command */ + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("Set"); + snprintf(buf,sizeof(buf),"%s=${ARG%d}", lp->u1.str, argc++); + np2->appargs = strdup(buf); + linkprio(exten, np2); + } + + /* CONTAINS APPCALLS, CATCH, just like extensions... */ + gen_prios(exten, p->u1.str, p->u3.macro_statements, 0 ); + if (exten->return_needed) { + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Macro %s-%s",p->u1.str, exten->name); + np2->appargs = strdup(buf); + linkprio(exten, np2); + exten-> return_target = np2; + } + + set_priorities(exten); + add_extensions(exten, context); + destroy_extensions(exten); + break; + + case PV_GLOBALS: + /* just VARDEC elements */ + for (p2=p->u1.list; p2; p2=p2->next) { + char buf2[2000]; + snprintf(buf2,sizeof(buf2),"%s=%s", p2->u1.str, p2->u2.val); + pbx_builtin_setvar(NULL, buf2); + } + break; + + case PV_CONTEXT: + context = ast_context_create(local_contexts, p->u1.str, registrar); + + /* contexts contain: ignorepat, includes, switches, eswitches, extensions, */ + for (p2=p->u2.statements; p2; p2=p2->next) { + pval *p3; + + switch (p2->type) { + case PV_EXTENSION: + exten = new_exten(); + exten->name = strdup(p2->u1.str); + if ( p2->u3.hints ) + exten->hints = strdup(p2->u3.hints); + exten->regexten = p2->u4.regexten; + gen_prios(exten, p->u1.str, p2->u2.statements, 0 ); + if (exten->return_needed) { + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"End of Extension %s", exten->name); + np2->appargs = strdup(buf); + linkprio(exten, np2); + exten-> return_target = np2; + } + /* is the last priority in the extension a label? Then add a trailing no-op */ + if ( exten->plist_last->type == AEL_LABEL ) { + struct ael_priority *np2 = new_prio(); + np2->type = AEL_APPCALL; + np2->app = strdup("NoOp"); + snprintf(buf,sizeof(buf),"A NoOp to follow a trailing label %s", exten->plist_last->origin->u1.str); + np2->appargs = strdup(buf); + linkprio(exten, np2); + } + + set_priorities(exten); + add_extensions(exten, context); + destroy_extensions(exten); + break; + + case PV_IGNOREPAT: + ast_context_add_ignorepat2(context, p2->u1.str, registrar); + break; + + case PV_INCLUDES: + for (p3 = p2->u1.list; p3 ;p3=p3->next) { + if ( p3->u2.arglist ) { + snprintf(buf,sizeof(buf), "%s|%s|%s|%s|%s", + p3->u1.str, + p3->u2.arglist->u1.str, + p3->u2.arglist->next->u1.str, + p3->u2.arglist->next->next->u1.str, + p3->u2.arglist->next->next->next->u1.str); + ast_context_add_include2(context, buf, registrar); + } else + ast_context_add_include2(context, p3->u1.str, registrar); + } + break; + + case PV_SWITCHES: + for (p3 = p2->u1.list; p3 ;p3=p3->next) { + char *c = strchr(p3->u1.str, '/'); + if (c) { + *c = '\0'; + c++; + } else + c = ""; + + ast_context_add_switch2(context, p3->u1.str, c, 0, registrar); + } + break; + + case PV_ESWITCHES: + for (p3 = p2->u1.list; p3 ;p3=p3->next) { + char *c = strchr(p3->u1.str, '/'); + if (c) { + *c = '\0'; + c++; + } else + c = ""; + + ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); + } + break; + default: + break; + } + } + + break; + + default: + /* huh? what? */ + break; + + } + } +} + +/* interface stuff */ + +static int pbx_load_module(void) +{ + int errs, sem_err, sem_warn, sem_note; + char *rfilename; + struct ast_context *local_contexts=NULL, *con; + struct pval *parse_tree; + + ast_log(LOG_NOTICE, "Starting AEL2 load process.\n"); + if (config[0] == '/') + rfilename = (char *)config; + else { + rfilename = alloca(strlen(config) + strlen(ast_config_AST_CONFIG_DIR) + 2); + sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, config); + } + ast_log(LOG_NOTICE, "AEL2 load process: calculated config file name '%s'.\n", rfilename); + + parse_tree = ael2_parse(rfilename, &errs); + ast_log(LOG_NOTICE, "AEL2 load process: parsed config file name '%s'.\n", rfilename); + ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note); + if (errs == 0 && sem_err == 0) { + ast_log(LOG_NOTICE, "AEL2 load process: checked config file name '%s'.\n", rfilename); + ast_compile_ael2(&local_contexts, parse_tree); + ast_log(LOG_NOTICE, "AEL2 load process: compiled config file name '%s'.\n", rfilename); + + ast_merge_contexts_and_delete(&local_contexts, registrar); + ast_log(LOG_NOTICE, "AEL2 load process: merged config file name '%s'.\n", rfilename); + for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) + ast_context_verify_includes(con); + ast_log(LOG_NOTICE, "AEL2 load process: verified config file name '%s'.\n", rfilename); + } else { + ast_log(LOG_ERROR, "Sorry, but %d syntax errors and %d semantic errors were detected. It doesn't make sense to compile.\n", errs, sem_err); + } + destroy_pval(parse_tree); /* free up the memory */ + + return 0; +} + +/* CLI interface */ +static int ael2_debug_read(int fd, int argc, char *argv[]) +{ + aeldebug |= DEBUG_READ; + return 0; +} + +static int ael2_debug_tokens(int fd, int argc, char *argv[]) +{ + aeldebug |= DEBUG_TOKENS; + return 0; +} + +static int ael2_debug_macros(int fd, int argc, char *argv[]) +{ + aeldebug |= DEBUG_MACROS; + return 0; +} + +static int ael2_debug_contexts(int fd, int argc, char *argv[]) +{ + aeldebug |= DEBUG_CONTEXTS; + return 0; +} + +static int ael2_no_debug(int fd, int argc, char *argv[]) +{ + aeldebug = 0; + return 0; +} + +static int ael2_reload(int fd, int argc, char *argv[]) +{ + ast_context_destroy(NULL, registrar); + return (pbx_load_module()); +} + +static struct ast_cli_entry ael2_cli[] = { + { { "ael2", "reload", NULL }, ael2_reload, "Reload AEL2 configuration"}, + { { "ael2", "debug", "read", NULL }, ael2_debug_read, "Enable AEL2 read debug"}, + { { "ael2", "debug", "tokens", NULL }, ael2_debug_tokens, "Enable AEL2 tokens debug"}, + { { "ael2", "debug", "macros", NULL }, ael2_debug_macros, "Enable AEL2 macros debug"}, + { { "ael2", "debug", "contexts", NULL }, ael2_debug_contexts, "Enable AEL2 contexts debug"}, + { { "ael2", "no", "debug", NULL }, ael2_no_debug, "Disable AEL2 debug messages"}, +}; + +/* + * Standard module functions ... + */ +int unload_module(void) +{ + ast_context_destroy(NULL, registrar); + ast_cli_unregister_multiple(ael2_cli, sizeof(ael2_cli)/ sizeof(ael2_cli[0])); + return 0; +} + + +int load_module(void) +{ + ast_cli_register_multiple(ael2_cli, sizeof(ael2_cli)/ sizeof(ael2_cli[0])); + return (pbx_load_module()); +} + +int reload(void) +{ + ast_context_destroy(NULL, registrar); + return pbx_load_module(); +} + +int usecount(void) +{ + return 0; +} + +char *description(void) +{ + return dtext; +} + +char *key(void) +{ + return ASTERISK_GPL_KEY; +} + +/* DESTROY the PVAL tree ============================================================================ */ + + + +void destroy_pval_item(pval *item) +{ + if (item->filename) + free(item->filename); + + switch (item->type) { + case PV_WORD: + /* fields: item->u1.str == string associated with this (word). */ + if (item->u1.str ) + free(item->u1.str); + if ( item->u2.arglist ) + destroy_pval(item->u2.arglist); + break; + + case PV_MACRO: + /* fields: item->u1.str == name of macro + item->u2.arglist == pval list of PV_WORD arguments of macro, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + + item->u3.macro_statements == pval list of statements in macro body. + */ + destroy_pval(item->u2.arglist); + if (item->u1.str ) + free(item->u1.str); + destroy_pval(item->u3.macro_statements); + break; + + case PV_CONTEXT: + /* fields: item->u1.str == name of context + item->u2.statements == pval list of statements in context body + item->u3.abstract == int 1 if an abstract keyword were present + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_MACRO_CALL: + /* fields: item->u1.str == name of macro to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.arglist); + break; + + case PV_APPLICATION_CALL: + /* fields: item->u1.str == name of application to call + item->u2.arglist == pval list of PV_WORD arguments of macro call, as given by user + item->u2.arglist->u1.str == argument + item->u2.arglist->next == next arg + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.arglist); + break; + + case PV_CASE: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_PATTERN: + /* fields: item->u1.str == value of case + item->u2.statements == pval list of statements under the case + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_DEFAULT: + /* fields: + item->u2.statements == pval list of statements under the case + */ + destroy_pval(item->u2.statements); + break; + + case PV_CATCH: + /* fields: item->u1.str == name of extension to catch + item->u2.statements == pval list of statements in context body + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_SWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + destroy_pval(item->u1.list); + break; + + case PV_ESWITCHES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + */ + destroy_pval(item->u1.list); + break; + + case PV_INCLUDES: + /* fields: item->u1.list == pval list of PV_WORD elements, one per entry in the list + item->u2.arglist == pval list of 4 PV_WORD elements for time values + */ + destroy_pval(item->u1.list); + break; + + case PV_STATEMENTBLOCK: + /* fields: item->u1.list == pval list of statements in block, one per entry in the list + */ + destroy_pval(item->u1.list); + break; + + case PV_VARDEC: + /* fields: item->u1.str == variable name + item->u2.val == variable value to assign + */ + if (item->u1.str) + free(item->u1.str); + if (item->u2.val) + free(item->u2.val); + break; + + case PV_GOTO: + /* fields: item->u1.list == pval list of PV_WORD target names, up to 3, in order as given by user. + item->u1.list->u1.str == where the data on a PV_WORD will always be. + */ + + destroy_pval(item->u1.list); + break; + + case PV_LABEL: + /* fields: item->u1.str == label name + */ + if (item->u1.str) + free(item->u1.str); + break; + + case PV_FOR: + /* fields: item->u1.for_init == a string containing the initalizer + item->u2.for_test == a string containing the loop test + item->u3.for_inc == a string containing the loop increment + + item->u4.for_statements == a pval list of statements in the for () + */ + if (item->u1.for_init) + free(item->u1.for_init); + if (item->u2.for_test) + free(item->u2.for_test); + if (item->u3.for_inc) + free(item->u3.for_inc); + destroy_pval(item->u4.for_statements); + break; + + case PV_WHILE: + /* fields: item->u1.str == the while conditional, as supplied by user + + item->u2.statements == a pval list of statements in the while () + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_BREAK: + /* fields: none + */ + break; + + case PV_RETURN: + /* fields: none + */ + break; + + case PV_CONTINUE: + /* fields: none + */ + break; + + case PV_IFTIME: + /* fields: item->u1.list == the 4 time values, in PV_WORD structs, linked list + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + destroy_pval(item->u1.list); + destroy_pval(item->u2.statements); + if (item->u3.else_statements) { + destroy_pval(item->u3.else_statements); + } + break; + + case PV_RANDOM: + /* fields: item->u1.str == the random percentage, as supplied by user + + item->u2.statements == a pval list of statements in the true part () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + fall thru to If */ + case PV_IF: + /* fields: item->u1.str == the if conditional, as supplied by user + + item->u2.statements == a pval list of statements in the if () + item->u3.else_statements == a pval list of statements in the else + (could be zero) + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + if (item->u3.else_statements) { + destroy_pval(item->u3.else_statements); + } + break; + + case PV_SWITCH: + /* fields: item->u1.str == the switch expression + + item->u2.statements == a pval list of statements in the switch, + (will be case statements, most likely!) + */ + if (item->u1.str) + free(item->u1.str); + destroy_pval(item->u2.statements); + break; + + case PV_EXTENSION: + /* fields: item->u1.str == the extension name, label, whatever it's called + + item->u2.statements == a pval list of statements in the extension + item->u3.hints == a char * hint argument + item->u4.regexten == an int boolean. non-zero says that regexten was specified + */ + if (item->u1.str) + free(item->u1.str); + if (item->u3.hints) + free(item->u3.hints); + destroy_pval(item->u2.statements); + break; + + case PV_IGNOREPAT: + /* fields: item->u1.str == the ignorepat data + */ + if (item->u1.str) + free(item->u1.str); + break; + + case PV_GLOBALS: + /* fields: item->u1.statements == pval list of statements, usually vardecs + */ + destroy_pval(item->u1.statements); + break; + } + free(item); +} + +void destroy_pval(pval *item) +{ + pval *i,*nxt; + + for (i=item; i; i=nxt) { + nxt = i->next; + + destroy_pval_item(i); + } +} + +static char *ael_funclist[] = +{ + "AGENT", + "ARRAY", + "BASE64_DECODE", + "BASE64_ENCODE", + "CALLERID", + "CDR", + "CHECKSIPDOMAIN", + "CHECK_MD5", + "CURL", + "CUT", + "DB", + "DB_EXISTS", + "DUNDILOOKUP", + "ENUMLOOKUP", + "ENV", + "EVAL", + "EXISTS", + "FIELDQTY", + "FILTER", + "GROUP", + "GROUP_COUNT", + "GROUP_LIST", + "GROUP_MATCH_COUNT", + "IAXPEER", + "IF", + "IFTIME", + "ISNULL", + "LANGUAGE", + "LEN", + "MATH", + "MD5", + "MUSICCLASS", + "QUEUEAGENTCOUNT", + "RAND", + "REGEX", + "SET", + "SIPCHANINFO", + "SIPPEER", + "SIP_HEADER", + "SORT", + "STAT", + "STRFTIME", + "TIMEOUT", + "TXTCIDNAME", + "URIDECODE", + "URIENCODE", + "VMCOUNT" +}; + + +int ael_is_funcname(char *name) +{ + int s,t; + t = sizeof(ael_funclist)/sizeof(char*); + s = 0; + while ((s < t) && strcasecmp(name, ael_funclist[s])) + s++; + if ( s < t ) + return 1; + else + return 0; +} + Property changes on: pbx/pbx_ael2.c ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: pbx/Makefile =================================================================== --- pbx/Makefile (.../branches/1.2) (revision 18575) +++ pbx/Makefile (.../team/murf/AEL2-1.2) (revision 18575) @@ -12,7 +12,7 @@ # PBX_LIBS=pbx_config.so pbx_spool.so pbx_dundi.so pbx_loopback.so pbx_realtime.so \ - pbx_ael.so + pbx_ael.so pbx_ael2.so ifeq ($(findstring BSD,${OSARCH}),BSD) CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib @@ -61,6 +61,36 @@ pbx_dundi.so: dundi-parser.o pbx_dundi.o $(CC) $(SOLINK) -o $@ ${CYGSOLINK} pbx_dundi.o dundi-parser.o -lz ${CYGSOLIB} +pbx_ael2.o : aelflex.o aelbison.o ../include/asterisk/ael_structs.h argdesc.tab.o argdesc_lex.o + +pbx_ael2.so : pbx_ael2.o aelbison.o aelflex.o argdesc.tab.o argdesc_lex.o + $(CC) $(SOLINK) -o $@ pbx_ael2.o aelbison.o aelflex.o argdesc.tab.o argdesc_lex.o + +aelflex.o : ael_lex.c ../include/asterisk/ael_structs.h ael.tab.h + $(CC) $(CFLAGS) -c -o aelflex.o ael_lex.c + +aelbison.o : ael.tab.c ael.tab.h ../include/asterisk/ael_structs.h + $(CC) $(CFLAGS) -c -o aelbison.o ael.tab.c ## -DYYDEBUG + +ael_lex.c : ael.flex + flex ael.flex + +ael.tab.c ael.tab.h : ael.y + bison -v -d ael.y + +argdesc.tab.c argdesc.tab.h : argdesc.y + bison -v -d argdesc.y + +argdesc_lex.c : argdesc.l ../include/asterisk/argdesc.h + flex argdesc.l + +argdesc.tab.o : argdesc.tab.c argdesc.tab.h + $(CC) $(CFLAGS) -c -o argdesc.tab.o argdesc.tab.c ## -DYYDEBUG + +argdesc_lex.o : argdesc_lex.c ../include/asterisk/argdesc.h argdesc.tab.h + $(CC) $(CFLAGS) -c -o argdesc_lex.o argdesc_lex.c + + %.moc : %.h $(MOC) $< -o $@ @@ -73,6 +103,7 @@ install: all for x in $(PBX_LIBS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done + $(INSTALL) -m 755 applist $(DESTDIR)$(ASTVARLIBDIR)/ depend: .depend Index: doc/ael2.txt =================================================================== --- doc/ael2.txt (.../branches/1.2) (revision 0) +++ doc/ael2.txt (.../team/murf/AEL2-1.2) (revision 18575) @@ -0,0 +1,1229 @@ +The Asterisk Extension Language - v 2 +===================================== + +AEL2 is a new version of the AEL compiler, written by Steve Murphy. + +AEL2 (like AEL) is considered an EXPERIMENTAL Version. (yet is being +used in the field with success) + +AEL2 is intended to provide an actual programming language that can be +used to write an Asterisk dialplan. It further extends AEL, and +provides more flexible syntax, better error messages, and some missing +functionality. + +AEL/AEL2 is really the merger of 4 different 'languages', or syntaxes: + + * The first and most obvious is the AEL2 syntax itselft. A BNF is + provided near the end of this document. + + * The second syntax is the Expression Syntax, which is normally + handled by Asterisk extension engine, as expressions enclosed in + $[...]. The right hand side of assignments are wrapped in $[ ... ] + by AEL, and so are the if and while expressions, among others. + + * The third syntax is the Variable Reference Syntax, the stuff + enclosed in ${..} curly braces. It's a bit more involved than just + putting a variable name in there. You can include one of dozens of + 'functions', and their arguments, and there are even some string + manipulation notation in there. + + * The last syntax that underlies AEL/AEL2, and is not used + directly in AEL/AEL2, is the Extension Language Syntax. The + extension language is what you see in extensions.conf, and AEL2 + compiles the higher level AEL2 language into extensions and + priorities, and passes them via function calls into + Asterisk. Embedded in this language is the Application/AGI + commands, of which one application call per step, or priority + can be made. You can think of this as a "macro assembler" + language, that AEL2 will compile into. + + +Any programmer of AEL2 should be familiar with it's syntax, of course, +as well as the Expression syntax, and the Variable syntax. + +************************** +* Asterisk in a Nutshell * +************************** + +Asterisk acts as a server. Devices involved in telephony, like Zapata +cards, or Voip phones, all indicate some context that should be +activated in their behalf. See the config file formats for IAX, SIP, +zapata.conf, etc. They all help describe a device, and they all +specify a context to activate when somebody picks up a phone, or a +call comes in from the phone company, or a voip phone, etc. + +Contexts +-------- + +Contexts are a grouping of extensions. + +Contexts can also include other contexts. Think of it as a sort of +merge operation at runtime, whereby the included context's extensions +are added to the contexts making the inclusion. + +Extensions and priorities +------------------------- + +A Context contains zero or more Extensions. There are several +predefined extensions. The "s" extension is the "start" extension, and +when a device activates a context the "s" extension is the one that is +going to be run. Other extensions are the timeout "t" extension, the +invalid response, or "i" extension, and there's a "fax" extension. For +instance, a normal call will activate the "s" extension, but an +incoming FAX call will come into the "fax" extension, if it +exists. (BTW, asterisk can tell it's a fax call by the little "beep" +that the calling fax machine emits every so many seconds.). + +Extensions contain several priorities, which are individual +instructions to perform. Some are as simple as setting a variable to a +value. Others are as complex as initiating the Voicemail application, +for instance. Priorities are executed in order. + +When the 's" extension completes, asterisk waits until the timeout for +a response. If the response matches an extension's pattern in the +context, then control is transferred to that extension. Usually the +responses are tones emitted when a user presses a button on their +phone. For instance, a context associated with a desk phone might not +have any "s" extension. It just plays a dialtone until someone starts +hitting numbers on the keypad, gather the number, find a matching +extension, and begin executing it. That extension might Dial out over +a connected telephone line for the user, and then connect the two +lines together. + +The extensions can also contain "goto" or "jump" commands to skip to +extensions in other contexts. Conditionals provide the ability to +react to different stimiuli, and there you have it. + +Macros +------ + +Think of a macro as a combination of a context with one nameless +extension, and a subroutine. It has arguments like a subroutine +might. A macro call can be made within an extension, and the +individual statements there are executed until it ends. At this point, +execution returns to the next statement after the macro call. Macros +can call other macros. And they work just like function calls. + +Applications +------------ + +Application calls, like "Dial()", or "Hangup()", or "Answer()", are +available for users to use to accomplish the work of the +dialplan. There are over 145 of them at the moment this was written, +and the list grows as new needs and wants are uncovered. Some +applications do fairly simple things, some provide amazingly complex +services. + +Hopefully, the above objects will allow you do anything you need to in +the Asterisk environment! + + +******************* +* Getting Started * +******************* + +The AEL2 parser (pbx_ael2.so) is completely separate from the module +that parses extensions.conf (pbx_config.so). To use AEL2, the only +thing that has to be done is the module pbx_ael2.so must be loaded by +Asterisk. This will be done automatically if using 'autoload=yes' in +/etc/asterisk/modules.conf. When the module is loaded, it will look +for 'extensions.ael2' in /etc/asterisk/. extensions.conf and +extensions.ael and extensions.ael2 can be used in conjunction with +each other if that is what is desired. Some users may want to keep +extensions.conf for the features that are configured in the 'general' +section of extensions.conf. + +------------------------------ +- Reloading extensions.ael2 - +------------------------------ + +To reload extensions.ael2, the following command can be issued at the +CLI: + + *CLI> ael2 reload + + + +************* +* Debugging * +************* + +Right at this moment, the following commands are available, but do +nothing: + +Enable AEL2 contexts debug + *CLI> ael2 debug contexts + +Enable AEL2 macros debug + *CLI> ael2 debug macros + +Enable AEL2 read debug + *CLI> ael2 debug read + +Enable AEL2 tokens debug + *CLI> ael2 debug tokens + +Disable AEL2 debug messages + *CLI> ael2 no debug + +If things are going wrong in your dialplan, you can use the following +facilities to debug your file: + +1. The messages log in /var/log/asterisk. (from the checks done at load time). +2. the "show dialplan" command in asterisk +3. the standalone executable, "aelparse" built in the utils/ dir in the source. + +You can also use the "aelparse" program to check your extensions.ael2 +file before feeding it to asterisk. Wouldn't it be nice to eliminate +most errors before giving the file to asterisk? + + + +****************************** +* General Notes about Syntax * +****************************** + +Note that the syntax and style are a little more free-form. The +opening '{' (curly-braces) do not have to be on the same line as the +keyword that precedes them. Statements can be split across lines, as +long as tokens are not broken by doing so. More than one statement can +be included on a single line. Whatever you think is best! + +You can just as easily say, + +if(${x}=1) { NoOp(hello!); goto s|3; } else { NoOp(Goodbye!); goto s|12; } + +as you can say: + +if(${x}=1) +{ + NoOp(hello!); + goto s|3; +} +else +{ + NoOp(Goodbye!); + goto s|12; +} + +or: + +if(${x}=1) { + NoOp(hello!); + goto s|3; +} else { + NoOp(Goodbye!); + goto s|12; +} + +or: + +if (${x}=1) { + NoOp(hello!); goto s|3; +} else { + NoOp(Goodbye!); goto s|12; +} + +or even: + +if +(${x}=1) +{ +NoOp(hello!); +goto s|3; +} +else +{ +NoOp(Goodbye!); +goto s|12; +} + + +************ +* Keywords * +************ + +The AEL keywords are case-sensitive. If an application name and a +keyword overlap, there is probably good reason, and you should +consider replacing the application call with an AEL2 statement. If you +do not wish to do so, you can still use the application, by using a +capitalized letter somewhere in its name. In the Asterisk extension +language, application names are NOT case-sensitive. + +The following are keywords in the AEL2 language: + + * abstract + * context + * macro + * globals + * ignorepat + * switch + * if + * ifTime + * else + * random + * goto + * jump + * return + * break + * continue + * regexten + * hint + * for + * while + * case + * pattern + * default NOTE: the "default" keyword can be used as a context name, + for those who would like to do so. + * catch + * switches + * eswitches + * includes + + + +***************** +* Applications * +***************** + +The file /var/lib/asterisk/applist contains entries for over 140 +applications, including arguments, the names of variables the +application can or will set, the options, and the list of arguments, +optional and required. If you use an application that is not in the +list, you can simply add one, following the syntax of other entries. + +Don't fall in love with the specs in the applist file. The format of +the file, the entries themselves will change in time. + + + + +Procedural Interface and Internals +================================== + +AEL2 first parses the .ael2 file into a memory structure representing the file. +The entire file is represented by a tree of "pval" structures linked together. + +This tree is then handed to the semantic check routine. + +Then the tree is handed to the compiler. + +After that, it is freed from memory. + +A program could be written that could build a tree of pval structures, and +a pretty printing function is provided, that would dump the data to a file, +or the tree could be handed to the compiler to merge the data into the +asterisk dialplan. The modularity of the design offers several opportunities +for developers to simplify apps to generate dialplan data. + + + +========================= + AEL2 BNF +========================= + + + +(hopefully, something close to bnf). + +First, some basic objects + +------------------------ + + a lexical token consisting of characters matching this pattern: [-a-zA-Z0-9"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9"_/.!\*\+\<\>\{\}$#\[\]]* + + a concatenation of up to 3 s. + + all characters encountered until the character that follows the in the grammar. + +------------------------- + + :== + + :== + | + + + :== + | + | + | ';' + + + :== 'context' '{' '}' + | 'context' '{' '}' + | 'context' 'default' '{' '}' + | 'context' 'default' '{' '}' + | 'abstract' 'context' '{' '}' + | 'abstract' 'context' '{' '}' + | 'abstract' 'context' 'default' '{' '}' + | 'abstract' 'context' 'default' '{' '}' + + + :== 'macro' '(' ')' '{' '}' + | 'macro' '(' ')' '{' '}' + | 'macro' '(' ')' '{' '}' + | 'macro' '(' ')' '{' '}' + + + :== 'globals' '{' '}' + | 'globals' '{' '}' + + + :== + | + + + :== '=' ';' + + + :== + | ',' + + + :== + | + + + :== + | + | + | + | + | '=' ';' + | ';' + + + :== 'ignorepat' '=>' ';' + + + :== '=>' + | 'regexten' '=>' + | 'hint' '(' ')' '=>' + | 'regexten' 'hint' '(' ')' '=>' + + + :== + | + + :== 'if' '(' ')' + + :== 'random' '(' ')' + + :== 'ifTime' '(' ':' ':' '|' '|' '|' ')' + | 'ifTime' '(' '|' '|' '|' ')' + + + :== + | + | + + :== 'switch' '(' ')' '{' + + + :== '{' '}' + | '=' ';' + | 'goto' ';' + | 'jump' ';' + | ':' + | 'for' '(' ';' ';' ')' + | 'while' '(' ')' + | '}' + | '}' + | '&' macro_call ';' + | ';' + | '=' ';' + | 'break' ';' + | 'return' ';' + | 'continue' ';' + | + | 'else' + | + | 'else' + | + | 'else' + | ';' + + :== + | '|' + | '|' '|' + | 'default' '|' '|' + | ',' + | ',' ',' + | 'default' ',' ',' + + :== + | ',' + | ',' '@' + | '@' + | ',' '@' 'default' + | '@' 'default' + + :== '(' ')' + | '(' ')' + + :== '(' + + :== ')' + | ')' + + :== + | ',' + | /* nothing */ + | ',' /* nothing */ + + :== + | + + + :== 'case' ':' + | 'default' ':' + | 'pattern' ':' + | 'case' ':' + | 'default' ':' + | 'pattern' ':' + + :== + | + + :== + | 'catch' '{' '}' + + :== 'switches' '{' '}' + | 'switches' '{' '}' + + :== 'eswitches' '{' '}' + | 'eswitches' '{' '}' + + :== ';' + | ';' + + :== ';' + | '|' ':' ':' '|' '|' '|' ';' + | '|' '|' '|' '|' ';' + | ';' + | '|' ':' ':' '|' '|' '|' ';' + | '|' '|' '|' '|' ';' + + :== + | 'default' + + :== 'includes' '{' '}' + | 'includes' '{' '}' + + +************************** +* AEL2 Example USAGE ***** +************************** + +Comments +======== + +Comments begin with // and end with the end of the line. + +Comments are removed by the lexical scanner, and will not be +recognized in places where it is busy gathering expressions to wrap in +$ , or inside application call argument lists. The safest place to put +comments is after terminating semicolons, or on otherwise empty lines. + + +Context +======= + +Contexts in AEL represent a set of extensions in the same way that +they do in extensions.conf. + + +context default { + +} + + +A context can be declared to be "abstract", in which case, this +declaration expresses the intent of the writer, that this context will +only be included by another context, and not "stand on its own". The +current effect of this keyword is to prevent "goto " statements from +being checked. + + +abstract context longdist { + _1NXXNXXXXXX => NoOp(generic long distance dialing actions in the US); +} + + + +Extensions +========== + +To specify an extension in a context, the following syntax is used. If +more than one application is be called in an extension, they can be +listed in order inside of a block. + + +context default { + 1234 => Playback(tt-monkeys); + 8000 => { + NoOp(one); + NoOp(two); + NoOp(three); + }; + _5XXX => NoOp(it's a pattern!); +} + + +Two optional items have been added to the AEL2 syntax, that allow the +specification of hints, and a keyword, regexten, that will force the +numbering of priorities to start at 2. + + +context default { + + regexten _5XXX => NoOp(it's a pattern!); +} + + + +context default { + + hint(Sip/1) _5XXX => NoOp(it's a pattern!); +} + + + +context default { + + regexten hint(Sip/1) _5XXX => NoOp(it's a pattern!); +} + + +The regexten must come before the hint if they are both present. + + + +Includes +======== + +Contexts can be included in other contexts. All included contexts are +listed within a single block. + + +context default { + includes { + local; + longdistance; + international; + } +} + + +Time-limited inclusions can be specified, as in extensions.conf +format, with the fields described in the wiki page Asterisk cmd +GotoIfTime. + + +context default { + includes { + local; + longdistance|16:00-23:59|mon-fri|*|*; + international; + } +} + + +#include +======== + +You can include other files with the #include "filepath" construct. + + + #include "/etc/asterisk/testfor.ael2" + + +An interesting property of the #include, is that you can use it almost +anywhere in the .ael2 file. It is possible to include the contents of +a file in a macro, context, or even extension. The #include does not +have to occur at the beginning of a line. Included files can include +other files, up to 50 levels deep. If the path provided in quotes is a +relative path, the parser looks in the config file directory for the +file (usually /etc/asterisk). + + + +Dialplan Switches +================= + +Switches are listed in their own block within a context. For clues as +to what these are used for, see Asterisk - dual servers, and Asterisk +config extensions.conf. + + +context default { + switches { + DUNDi/e164; + IAX2/box5; + }; + eswitches { + IAX2/context@${CURSERVER}; + } +} + + + +Ignorepat +========= + +ignorepat can be used to instruct channel drivers to not cancel +dialtone upon receipt of a particular pattern. The most commonly used +example is '9'. + + +context outgoing { + ignorepat => 9; +} + + + + +Variables +========= + +Variables in Asterisk do not have a type, so to define a variable, it +just has to be specified with a value. + +Global variables are set in their own block. + + +globals { + CONSOLE=Console/dsp; + TRUNK=Zap/g2; +} + + + +Variables can be set within extensions as well. + + +context foo { + 555 => { + x=5; + y=blah; + divexample=10/2 + NoOp(x is ${x} and y is ${y} !); + } +} + + +NOTE: AEL wraps the right hand side of an assignment with $[ ] to allow expressions to be used If this is unwanted, you can protect the right hand side from being wrapped by using the Set() application. Read the README.variables about the requirements and behavior of $[ ] expressions. + +NOTE: These things are wrapped up in a $[ ] expression: The while() test; the if() test; the middle expression in the for( x; y; z) statement (the y expression); Assignments \u2014 the right hand side, so a = b -> Set(a=$[b]) + +Writing to a dialplan function is treated the same as writing to a variable. + + +context blah { + s => { + CALLERID(name)=ChickenMan; + NoOp(My name is ${CALLERID(name)} !); + } +} + + + +Loops +===== + +AEL has implementations of 'for' and 'while' loops. + + +context loops { + 1 => { + for (x=0; ${x} < 3; x=${x} + 1) { + Verbose(x is ${x} !); + } + } + 2 => { + y=10; + while (${y} >= 0) { + Verbose(y is ${y} !); + y=${y}-1; + } + } +} + + +NOTE: The conditional expression (the "${y} >= 0" above) is wrapped in + $[ ] so it can be evaluated. NOTE: The for loop test expression + (the "${x} < 3" above) is wrapped in $[ ] so it can be evaluated. + + + +Conditionals +============ + +AEL2 supports if and switch statements, like AEL, but adds ifTime, and +random. Unlike the original AEL, though, you do NOT need to put curly +braces around a single statement in the "true" branch of an if(), the +random(), or an ifTime() statement. The if(), ifTime(), and random() +statements allow optional else clause. + + +context conditional { + _8XXX => { + Dial(SIP/${EXTEN}); + if ("${DIALSTATUS}" = "BUSY") + { + NoOp(yessir); + Voicemail(${EXTEN}|b); + } + else + Voicemail(${EXTEN}|u); + ifTime (14:00-25:00|sat-sun|*|*) + Voicemail(${EXTEN}|b); + else + { + Voicemail(${EXTEN}|u); + NoOp(hi, there!); + } + random(51) NoOp(This should appear 51% of the time); + + random( 60 ) + { + NoOp( This should appear 60% of the time ); + } + else + { + random(75) + { + NoOp( This should appear 30% of the time! ); + } + else + { + NoOp( This should appear 10% of the time! ); + } + } + } + _777X => { + switch (${EXTEN}) { + case 7771: + NoOp(You called 7771!); + break; + case 7772: + NoOp(You called 7772!); + break; + case 7773: + NoOp(You called 7773!); + // fall thru- + pattern 777[4-9]: + NoOp(You called 777 something!); + default: + NoOp(In the default clause!); + } + } +} + + +NOTE: The conditional expression in if() statements (the + "${DIALSTATUS}" = "BUSY" above) is wrapped by the compiler in + $[] for evaluation. + +NOTE: Neither the switch nor case values are wrapped in $[ ]; they can + be constants, or ${var} type references only. + +NOTE: AEL2 generates each case as a separate extension. case clauses + with no terminating 'break', or 'goto', have a goto inserted, to + the next clause, which creates a 'fall thru' effect. + +NOTE: AEL2 introduces the ifTime keyword/statement, which works just + like the if() statement, but the expression is a time value, + exactly like that used by the application GotoIfTime(). See + Asterisk cmd GotoIfTime + +NOTE: The pattern statement makes sure the new extension that is + created has an '_' preceding it to make sure asterisk recognizes + the extension name as a pattern. + +NOTE: Every character enclosed by the switch expression's parenthesis + are included verbatim in the labels generated. So watch out for + spaces! + +NOTE: NEW: Previous to version 0.13, the random statement used the + "Random()" application, which has been deprecated. It now uses + the RAND() function instead, in the GotoIf application. + + +Break, Continue, and Return +=========================== + + +Three keywords, break, continue, and return, are included in the +syntax to provide flow of control to loops, and switches. + +The break can be used in switches and loops, to jump to the end of the +loop or switch. + +The continue can be used in loops (while and for) to immediately jump +to the end of the loop. In the case of a for loop, the increment and +test will then be performed. In the case of the while loop, the +continue will jump to the test at the top of the loop. + +The return keyword will cause an immediate jump to the end of the +context, or macro, and can be used anywhere. + + + +goto, jump, and labels +====================== + +This is an example of how to do a goto in AEL. + + +context gotoexample { + s => { +begin: + NoOp(Infinite Loop! yay!); + Wait(1); + goto begin; // go to label in same extension + } + 3 => { + goto s|begin; // go to label in different extension + } + 4 => { + goto gotoexample|s|begin; // overkill go to label in same context + } +} + +context gotoexample2 { + s => { + end: + goto gotoexample|s|begin; // go to label in different context + } +} + +You can use the special label of "1" in the goto and jump +statements. It means the "first" statement in the extension. I would +not advise trying to use numeric labels other than "1" in goto's or +jumps, nor would I advise declaring a "1" label anywhere! As a matter +of fact, it would be bad form to declare a numeric label, and it might +confllict with the priority numbers used internally by asterisk. + +The syntax of the jump statement is: jump +extension[,priority][@context] If priority is absent, it defaults to +"1". If context is not present, it is assumed to be the same as that +which contains the "jump". + + +context gotoexample { + s => { +begin: + NoOp(Infinite Loop! yay!); + Wait(1); + jump s; // go to first extension in same extension + } + 3 => { + jump s,begin; // go to label in different extension + } + 4 => { + jump s,begin@gotoexample; // overkill go to label in same context + } +} + +context gotoexample2 { + s => { + end: + jump s@gotoexample; // go to label in different context + } +} + +NOTE: goto labels follow the same requirements as the Goto() + application, except the last value has to be a label. If the + label does not exist, you will have run-time errors. If the + label exists, but in a different extension, you have to specify + both the extension name and label in the goto, as in: goto s|z; + if the label is in a different context, you specify + context|extension|label. There is a note about using goto's in a + switch statement below... + +NOTE AEL2 introduces the special label "1", which is the beginning + context number for most extensions. + +NOTE: A NEW addition to AEL2: you can now use ',' instead of '|' to + separate the items in the target address. You can't have a mix, + though, of '|' and ',' in the target. It's either one, or the other. + + + + +Macros +====== + +A macro is defined in its own block like this. The arguments to the +macro are specified with the name of the macro. They are then referred +to by that same name. A catch block can be specified to catch special +extensions. + + +macro std-exten( ext , dev ) { + Dial(${dev}/${ext},20); + switch(${DIALSTATUS) { + case BUSY: + Voicemail(b${ext}); + break; + default: + Voicemail(u${ext}); + + } + catch a { + VoiceMailMain(${ext}); + return; + } +} + + +A macro is then called by preceeding the macro name with an +ampersand. Empty arguments can be passed simply with nothing between +comments(0.11). + + +context example { + _5XXX => &std-exten(${EXTEN}, "IAX2"); + _6XXX => &std-exten(, "IAX2"); + _7XXX => &std-exten(${EXTEN},); + _8XXX => &std-exten(,); +} + + + +Examples +======== + + +context demo { + s => { + Wait(1); + Answer(); + TIMEOUT(digit)=5; + TIMEOUT(response)=10; +restart: + Background(demo-congrats); +instructions: + for (x=0; ${x} < 3; x=${x} + 1) { + Background(demo-instruct); + WaitExten(); + } + } + 2 => { + Background(demo-moreinfo); + goto s|instructions; + } + 3 => { + LANGUAGE()=fr; + goto s|restart; + } + + 500 => { + Playback(demo-abouttotry); + Dial(IAX2/guest@misery.digium.com); + Playback(demo-nogo); + goto s|instructions; + } + 600 => { + Playback(demo-echotest); + Echo(); + Playback(demo-echodone); + goto s|instructions; + } + # => { +hangup: + Playback(demo-thanks); + Hangup(); + } + t => goto #|hangup; + i => Playback(invalid); +} + + +Semantic Checks +=============== + + +AEL2, after parsing, but before compiling, traverses the dialplan +tree, and makes several checks: + + * (if the application argument analyzer is working: the presence + of the 'j' option is reported as error. + * if options are specified, that are not available in an + application. + * if you specify too many arguments to an application. + * a required argument is not present in an application call. + * Switch-case using "known" variables that applications set, that + does not cover all the possible values. (a "default" case will + solve this problem. Each "unhandled" value is listed. + * a Switch construct is used, which is uses a known variable, and + the application that would set that variable is not called in + the same extension. This is a warning only... + * Macro calls to non-existent macros. + * Macro calls to contexts. + * Macro calls with argument count not matching the definition. + * application call to macro. + * application calls to "GotoIf", "GotoIfTime", "while", + "endwhile", "Random", and "execIf", will generate a message to + consider converting the call to AEL goto, while, etc. constructs. + * Calls to applications not in the "applist" database (installed + in /var/lib/asterisk/applist" on most systems). + * goto a label in an empty extension. + * goto a non-existent label, either a within-extension, + within-context, or in a different context, or in any included + contexts. Will even check "sister" context references. + * All the checks done on the time values in the dial plan, are + done on the time values in the ifTime() and includes times: + o the time range has to have two times separated by a dash; + o the times have to be in range of 0 to 24 hours. + o The weekdays have to match the internal list, if they are provided; + o the day of the month, if provided, must be in range of 1 to 31; + o the month name or names have to match those in the internal list. + * In an assignment statement, if the assignment is to a function, + the function name used is checked to see if it one of the + currently known functions. A warning is issued if it is not. + * (0.5) If an expression is wrapped in $[ ... ], and the compiler + will wrap it again, a warning is issued. + * (0.5) If an expression had operators (you know, + +,-,*,/,%,!,etc), but no ${ } variables, a warning is + issued. Maybe someone forgot to wrap a variable name? + * (0.12) check for duplicate context names. + * (0.12) check for abstract contexts that are not included by any context. + * (0.13) Issue a warning if a label is a numeric value. + + +Differences with the original version of AEL +============================================ + + 1. It reads in "/etc/asterisk/extensions.ael2", instead of + extensions.ael + 2. It is more free-form. The newline character means very little, + and is pulled out of the white-space only for line numbers in + error messages. + 3. It generates more error messages \u2014 by this I mean that any + difference between the input and the grammar are reported, by + file, line number, and column. + 4. It checks the contents of $[ ] expressions (or what will end up + being $[ ] expressions!) for syntax errors. It also does + matching paren/bracket counts. + 5. It runs several semantic checks after the parsing is over, but + before the compiling begins, see the list above. + 6. It handles #include "filepath" directives. \u2014 ALMOST + anywhere, in fact. You could easily include a file in a context, + in an extension, or at the root level. Files can be included in + files that are included in files, down to 50 levels of hierarchy... + 7. Local Goto's inside Switch statements automatically have the + extension of the location of the switch statement appended to them. + 8. A pretty printer function is available within pbx_ael2.so. + 9. In the utils directory, two standalone programs are supplied for + debugging AEL files. One is called "aelparse", and it reads in + the /etc/asterisk/extensions.ael2 file, and shows the results of + syntax and semantic checking on stdout, and also shows the + results of compilation to stdout. The other is "aelparse1", + which uses the original ael compiler to do the same work, + reading in "/etc/asterisk/extensions.ael", using the original + 'pbx_ael.so' instead. + 10. AEL2 supports the "jump" statement, and the "pattern" statement + in switch constructs. Hopefully these will be documented in the + AEL README. + 11. Added the "return" keyword, which will jump to the end of an + extension/Macro. + 12. Added the ifTime (