From 5f58cc8770b028174797748c71d0f74feff6f786 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" <kpfleming@digium.com> Date: Mon, 24 Apr 2006 17:41:27 +0000 Subject: [PATCH] Merge Steve Murphy's (murf) complete re-implementation of AEL, which is now no longer considered experimental :-) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@22273 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CREDITS | 2 +- ast_expr2.c | 1230 ++++-- ast_expr2.fl | 137 +- ast_expr2.h | 20 +- ast_expr2.y | 79 +- ast_expr2f.c | 841 ++-- configs/extensions.ael.sample | 386 +- doc/ael.txt | 1359 +++++- include/asterisk/ael_structs.h | 178 + mxml/configure | 640 ++- pbx/Makefile | 17 + pbx/ael/ael-test/ael-test1/extensions.ael | 163 + pbx/ael/ael-test/ael-test2/apptest.ael2 | 146 + pbx/ael/ael-test/ael-test2/extensions.ael | 8 + pbx/ael/ael-test/ael-test3/extensions.ael | 3183 ++++++++++++++ pbx/ael/ael-test/ael-test3/include1.ael2 | 3 + pbx/ael/ael-test/ael-test3/include2.ael2 | 4 + pbx/ael/ael-test/ael-test3/include3.ael2 | 2 + pbx/ael/ael-test/ael-test3/include4.ael2 | 2 + pbx/ael/ael-test/ael-test3/include5.ael2 | 1 + pbx/ael/ael-test/ael-test4/apptest.ael2 | 146 + pbx/ael/ael-test/ael-test4/extensions.ael | 8 + pbx/ael/ael-test/ael-test5/extensions.ael | 833 ++++ pbx/ael/ael-test/ael-test6/extensions.ael | 833 ++++ pbx/ael/ael-test/ael-test7/extensions.ael | 460 ++ pbx/ael/ael-test/ref.ael-test1 | 11 + pbx/ael/ael-test/ref.ael-test2 | 15 + pbx/ael/ael-test/ref.ael-test3 | 18 + pbx/ael/ael-test/ref.ael-test4 | 15 + pbx/ael/ael-test/ref.ael-test5 | 9 + pbx/ael/ael-test/ref.ael-test6 | 20 + pbx/ael/ael-test/ref.ael-test7 | 13 + pbx/ael/ael-test/runtests | 14 + pbx/ael/ael-test/setref | 7 + pbx/ael/ael.flex | 633 +++ pbx/ael/ael.tab.c | 3192 ++++++++++++++ pbx/ael/ael.tab.h | 147 + pbx/ael/ael.y | 705 +++ pbx/ael/ael_lex.c | 2996 +++++++++++++ pbx/pbx_ael.c | 4708 ++++++++++++++++----- utils/Makefile | 16 + utils/ael_main.c | 264 ++ utils/expr2.testinput | 92 + 43 files changed, 21282 insertions(+), 2274 deletions(-) create mode 100644 include/asterisk/ael_structs.h create mode 100644 pbx/ael/ael-test/ael-test1/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test2/apptest.ael2 create mode 100644 pbx/ael/ael-test/ael-test2/extensions.ael create mode 100755 pbx/ael/ael-test/ael-test3/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test3/include1.ael2 create mode 100644 pbx/ael/ael-test/ael-test3/include2.ael2 create mode 100644 pbx/ael/ael-test/ael-test3/include3.ael2 create mode 100644 pbx/ael/ael-test/ael-test3/include4.ael2 create mode 100644 pbx/ael/ael-test/ael-test3/include5.ael2 create mode 100644 pbx/ael/ael-test/ael-test4/apptest.ael2 create mode 100644 pbx/ael/ael-test/ael-test4/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test5/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test6/extensions.ael create mode 100644 pbx/ael/ael-test/ael-test7/extensions.ael create mode 100644 pbx/ael/ael-test/ref.ael-test1 create mode 100644 pbx/ael/ael-test/ref.ael-test2 create mode 100644 pbx/ael/ael-test/ref.ael-test3 create mode 100644 pbx/ael/ael-test/ref.ael-test4 create mode 100644 pbx/ael/ael-test/ref.ael-test5 create mode 100644 pbx/ael/ael-test/ref.ael-test6 create mode 100644 pbx/ael/ael-test/ref.ael-test7 create mode 100755 pbx/ael/ael-test/runtests create mode 100755 pbx/ael/ael-test/setref create mode 100644 pbx/ael/ael.flex create mode 100644 pbx/ael/ael.tab.c create mode 100644 pbx/ael/ael.tab.h create mode 100644 pbx/ael/ael.y create mode 100644 pbx/ael/ael_lex.c create mode 100644 utils/ael_main.c create mode 100644 utils/expr2.testinput diff --git a/CREDITS b/CREDITS index 809e7b44e3..4a24a7af8d 100644 --- a/CREDITS +++ b/CREDITS @@ -76,7 +76,7 @@ Olle E. Johansson - SIP RFC compliance, documentation and testing, testing, test Steve Kann - new jitter buffer for IAX2 stevek@stevek.com Constantine Filin - major contributions to the Asterisk Realtime Architecture -Steve Murphy - privacy support +Steve Murphy - privacy support, $[ ] parser upgrade, AEL2 parser upgrade Claude Patry - bug fixes, feature enhancements, and bug marshalling cpatry@gmail.com diff --git a/ast_expr2.c b/ast_expr2.c index 6b2bd603b3..0ddb1e4ff9 100644 --- a/ast_expr2.c +++ b/ast_expr2.c @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 2.1. */ +/* A Bison parser, made by GNU Bison 2.1a. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 @@ -23,8 +23,8 @@ 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. */ +/* C LALR(1) parser skeleton 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 @@ -37,7 +37,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.1" +#define YYBISON_VERSION "2.1a" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -134,6 +134,7 @@ #include <stdlib.h> #include <string.h> #include <locale.h> +#include <unistd.h> #include <ctype.h> #if !defined(SOLARIS) && !defined(__CYGWIN__) #include <err.h> @@ -168,6 +169,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define YYPARSE_PARAM parseio #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner #define YYERROR_VERBOSE 1 +extern char extra_error_message[4095]; +extern int extra_error_message_supplied; enum valtype { AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string @@ -246,12 +249,7 @@ int ast_yyerror(const char *,YYLTYPE *, struct parse_io *); some useful info about the error. Not as easy as it looks, but it is possible. */ #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio) -#define DESTROY(x) { \ -if ((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) \ - free((x)->u.s); \ - (x)->u.s = 0; \ - free(x); \ -} +#define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);} /* Enabling traces. */ @@ -272,19 +270,21 @@ if ((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) \ # define YYTOKEN_TABLE 0 #endif -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 142 "ast_expr2.y" -typedef union YYSTYPE { +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 140 "ast_expr2.y" +{ struct val *val; -} YYSTYPE; -/* Line 196 of yacc.c. */ -#line 277 "ast_expr2.c" +} +/* Line 198 of yacc.c. */ +#line 276 "ast_expr2.c" + YYSTYPE; # 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) +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED typedef struct YYLTYPE { int first_line; @@ -299,28 +299,61 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -#line 146 "ast_expr2.y" +#line 144 "ast_expr2.y" extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t)); -/* Line 219 of yacc.c. */ +/* Line 221 of yacc.c. */ #line 304 "ast_expr2.c" -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; #endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; #endif -#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; #endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif #endif +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS @@ -333,7 +366,32 @@ extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t)); # endif #endif -#if ! defined (yyoverflow) || YYERROR_VERBOSE +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -341,46 +399,56 @@ extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t)); # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if defined (__STDC__) || defined (__cplusplus) +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# define YYINCLUDED_STDLIB_H +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # ifdef __cplusplus extern "C" { # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -388,18 +456,18 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ } # endif # endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (defined (YYLTYPE_IS_TRIVIAL) && YYLTYPE_IS_TRIVIAL \ - && defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) +#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; + yytype_int16 yyss; YYSTYPE yyvs; YYLTYPE yyls; }; @@ -410,13 +478,13 @@ union yyalloc /* 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)) \ + ((N) * (sizeof (yytype_int16) + 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__ +# if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else @@ -427,7 +495,7 @@ union yyalloc for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ - while (0) + while (YYID (0)) # endif # endif @@ -445,28 +513,22 @@ union yyalloc yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (0) - -#endif + while (YYID (0)) -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short int yysigned_char; #endif -/* YYFINAL -- State number of the termination state. */ +/* YYFINAL -- State number of the termination state. */ #define YYFINAL 10 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 140 -/* YYNTOKENS -- Number of terminals. */ +/* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 24 -/* YYNNTS -- Number of nonterminals. */ +/* YYNNTS -- Number of nonterminals. */ #define YYNNTS 3 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 22 -/* YYNRULES -- Number of states. */ +/* YYNRULES -- Number of rules. */ +#define YYNRULES 23 +/* YYNRULES -- Number of states. */ #define YYNSTATES 46 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ @@ -477,7 +539,7 @@ union yyalloc ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -512,39 +574,39 @@ static const unsigned char yytranslate[] = #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const unsigned char yyprhs[] = +static const yytype_uint8 yyprhs[] = { - 0, 0, 3, 5, 7, 11, 15, 19, 23, 27, - 31, 35, 39, 43, 47, 51, 54, 57, 61, 65, - 69, 73, 77 + 0, 0, 3, 5, 6, 8, 12, 16, 20, 24, + 28, 32, 36, 40, 44, 48, 52, 55, 58, 62, + 66, 70, 74, 78 }; -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yysigned_char yyrhs[] = +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = { - 25, 0, -1, 26, -1, 23, -1, 21, 26, 22, - -1, 26, 5, 26, -1, 26, 6, 26, -1, 26, - 12, 26, -1, 26, 11, 26, -1, 26, 10, 26, - -1, 26, 9, 26, -1, 26, 8, 26, -1, 26, - 7, 26, -1, 26, 14, 26, -1, 26, 13, 26, - -1, 13, 26, -1, 18, 26, -1, 26, 17, 26, - -1, 26, 16, 26, -1, 26, 15, 26, -1, 26, - 20, 26, -1, 26, 19, 26, -1, 26, 4, 26, - 3, 26, -1 + 25, 0, -1, 26, -1, -1, 23, -1, 21, 26, + 22, -1, 26, 5, 26, -1, 26, 6, 26, -1, + 26, 12, 26, -1, 26, 11, 26, -1, 26, 10, + 26, -1, 26, 9, 26, -1, 26, 8, 26, -1, + 26, 7, 26, -1, 26, 14, 26, -1, 26, 13, + 26, -1, 13, 26, -1, 18, 26, -1, 26, 17, + 26, -1, 26, 16, 26, -1, 26, 15, 26, -1, + 26, 20, 26, -1, 26, 19, 26, -1, 26, 4, + 26, 3, 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned char yyrline[] = +static const yytype_uint16 yyrline[] = { - 0, 165, 165, 175, 176, 180, 184, 188, 192, 196, - 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, - 240, 244, 248 + 0, 168, 168, 176, 183, 184, 188, 192, 196, 200, + 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, + 244, 248, 252, 256 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "TOK_COLONCOLON", "TOK_COND", "TOK_OR", @@ -558,7 +620,7 @@ static const char *const yytname[] = # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ -static const unsigned short int yytoknum[] = +static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -567,35 +629,35 @@ static const unsigned short int yytoknum[] = # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned char yyr1[] = +static const yytype_uint8 yyr1[] = { - 0, 24, 25, 26, 26, 26, 26, 26, 26, 26, + 0, 24, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26 + 26, 26, 26, 26 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = +static const yytype_uint8 yyr2[] = { - 0, 2, 1, 1, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, - 3, 3, 5 + 0, 2, 1, 0, 1, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, + 3, 3, 3, 5 }; /* 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[] = +static const yytype_uint8 yydefact[] = { - 0, 0, 0, 0, 3, 0, 2, 15, 16, 0, + 3, 0, 0, 0, 4, 0, 2, 16, 17, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4, 0, 5, - 6, 12, 11, 10, 9, 8, 7, 14, 13, 19, - 18, 17, 21, 20, 0, 22 + 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, + 7, 13, 12, 11, 10, 9, 8, 15, 14, 20, + 19, 18, 22, 21, 0, 23 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yysigned_char yydefgoto[] = +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { -1, 5, 6 }; @@ -603,7 +665,7 @@ static const yysigned_char yydefgoto[] = /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -13 -static const yysigned_char yypact[] = +static const yytype_int8 yypact[] = { 109, 109, 109, 109, -13, 6, 59, 106, 106, 22, -13, 109, 109, 109, 109, 109, 109, 109, 109, 109, @@ -613,7 +675,7 @@ static const yysigned_char yypact[] = }; /* YYPGOTO[NTERM-NUM]. */ -static const yysigned_char yypgoto[] = +static const yytype_int8 yypgoto[] = { -13, -13, -1 }; @@ -623,7 +685,7 @@ static const yysigned_char yypgoto[] = number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 -static const unsigned char yytable[] = +static const yytype_uint8 yytable[] = { 7, 8, 9, 22, 23, 24, 10, 25, 26, 0, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -642,7 +704,7 @@ static const unsigned char yytable[] = 26 }; -static const yysigned_char yycheck[] = +static const yytype_int8 yycheck[] = { 1, 2, 3, 15, 16, 17, 0, 19, 20, -1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, @@ -663,7 +725,7 @@ static const yysigned_char yycheck[] = /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ -static const unsigned char yystos[] = +static const yytype_uint8 yystos[] = { 0, 13, 18, 21, 23, 25, 26, 26, 26, 26, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, @@ -697,7 +759,7 @@ do \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ + YYPOPSTACK (1); \ goto yybackup; \ } \ else \ @@ -705,7 +767,7 @@ do \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (0) +while (YYID (0)) #define YYTERROR 1 @@ -720,7 +782,7 @@ while (0) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ - if (N) \ + if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ @@ -734,7 +796,7 @@ while (0) (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ - while (0) + while (YYID (0)) #endif @@ -746,8 +808,8 @@ while (0) # 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) + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif @@ -774,36 +836,101 @@ while (0) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (0) +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (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) + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp) + FILE *yyoutput; + int yytype; + const YYSTYPE * const yyvaluep; + const YYLTYPE * const yylocationp; +#endif +{ + if (!yyvaluep) + return; + YYUSE (yylocationp); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp) + FILE *yyoutput; + int yytype; + const YYSTYPE * const yyvaluep; + const YYLTYPE * const yylocationp; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp); + YYFPRINTF (yyoutput, ")"); +} /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (short int *bottom, short int *top) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) - short int *bottom; - short int *top; + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) + for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -812,37 +939,47 @@ yy_stack_print (bottom, top) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (0) +} while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) #else static void -yy_reduce_print (yyrule) +yy_reduce_print (yyvsp, yylsp, yyrule + ) + YYSTYPE *yyvsp; + YYLTYPE *yylsp; int yyrule; #endif { + int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", - 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]]); + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) ); + fprintf (stderr, "\n"); + } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (Rule); \ -} while (0) + yy_reduce_print (yyvsp, yylsp, Rule); \ +} while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -876,42 +1013,44 @@ int yydebug; #if YYERROR_VERBOSE # ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) +# if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) -# else +#else +static YYSIZE_T yystrlen (yystr) - const char *yystr; -# endif + const char *yystr; +#endif { - const char *yys = yystr; - - while (*yys++ != '\0') + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) continue; - - return yys - yystr - 1; + return yylen; } # endif # endif # ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# 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. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static char * -# if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) -# else +#else +static char * yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif + char *yydest; + const char *yysrc; +#endif { char *yyd = yydest; const char *yys = yysrc; @@ -972,57 +1111,123 @@ yytnamerr (char *yyres, const char *yystr) } # 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 +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - (void) yylocationp; + int yyn = yypact[yystate]; - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + if (! (YYPACT_NINF < yyn && yyn < YYLAST)) + return 0; else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* 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 = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - switch (yytype) - { - default: - break; + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - YYFPRINTF (yyoutput, ")"); } +#endif /* YYERROR_VERBOSE */ + -#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) #else @@ -1034,9 +1239,8 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp) YYLTYPE *yylocationp; #endif { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - (void) yylocationp; + YYUSE (yyvaluep); + YYUSE (yylocationp); if (!yymsg) yymsg = "Deleting"; @@ -1044,9 +1248,119 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp) switch (yytype) { + case 3: /* "TOK_COLONCOLON" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1250 "ast_expr2.c" + break; + case 4: /* "TOK_COND" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1255 "ast_expr2.c" + break; + case 5: /* "TOK_OR" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1260 "ast_expr2.c" + break; + case 6: /* "TOK_AND" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1265 "ast_expr2.c" + break; + case 7: /* "TOK_NE" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1270 "ast_expr2.c" + break; + case 8: /* "TOK_LE" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1275 "ast_expr2.c" + break; + case 9: /* "TOK_GE" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1280 "ast_expr2.c" + break; + case 10: /* "TOK_LT" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1285 "ast_expr2.c" + break; + case 11: /* "TOK_GT" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1290 "ast_expr2.c" + break; + case 12: /* "TOK_EQ" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1295 "ast_expr2.c" + break; + case 13: /* "TOK_MINUS" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1300 "ast_expr2.c" + break; + case 14: /* "TOK_PLUS" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1305 "ast_expr2.c" + break; + case 15: /* "TOK_MOD" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1310 "ast_expr2.c" + break; + case 16: /* "TOK_DIV" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1315 "ast_expr2.c" + break; + case 17: /* "TOK_MULT" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1320 "ast_expr2.c" + break; + case 18: /* "TOK_COMPL" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1325 "ast_expr2.c" + break; + case 19: /* "TOK_EQTILDE" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1330 "ast_expr2.c" + break; + case 20: /* "TOK_COLON" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1335 "ast_expr2.c" + break; + case 21: /* "TOK_LP" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1340 "ast_expr2.c" + break; + case 22: /* "TOK_RP" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1345 "ast_expr2.c" + break; + case 23: /* "TOKEN" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1350 "ast_expr2.c" + break; + case 26: /* "expr" */ +#line 162 "ast_expr2.y" + { free_value((yyvaluep->val)); }; +#line 1355 "ast_expr2.c" + break; default: - break; + break; } } @@ -1054,13 +1368,13 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp) /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); -# else +#else int yyparse (); -# endif +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); @@ -1077,20 +1391,24 @@ int yyparse (); `----------*/ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () - ; + #endif #endif { @@ -1112,6 +1430,12 @@ YYLTYPE yylloc; int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif /* Three stacks and their tools: `yyss': related to states, @@ -1122,9 +1446,9 @@ YYLTYPE yylloc; to reallocate them elsewhere. */ /* The state stack. */ - short int yyssa[YYINITDEPTH]; - short int *yyss = yyssa; - short int *yyssp; + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -1135,10 +1459,10 @@ YYLTYPE yylloc; YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; - /* The locations where the error started and ended. */ + /* The locations where the error started and ended. */ YYLTYPE yyerror_range[2]; -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; @@ -1147,9 +1471,9 @@ YYLTYPE yylloc; YYSTYPE yyval; YYLTYPE yyloc; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1179,8 +1503,7 @@ YYLTYPE yylloc; `------------------------------------------------------------*/ 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. - */ + have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: @@ -1193,11 +1516,11 @@ YYLTYPE yylloc; #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of + /* 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; + yytype_int16 *yyss1 = yyss; YYLTYPE *yyls1 = yyls; /* Each stack pointer address is followed by the size of the @@ -1225,7 +1548,7 @@ YYLTYPE yylloc; yystacksize = YYMAXDEPTH; { - short int *yyss1 = yyss; + yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) @@ -1260,12 +1583,10 @@ YYLTYPE yylloc; `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a look-ahead token if we need one and don't already have one. */ -/* yyresume: */ + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ - yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; @@ -1307,22 +1628,21 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the token being shifted unless it is eof. */ + /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; + yystate = yyn; *++yyvsp = yylval; *++yylsp = yylloc; - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - yystate = yyn; goto yynewstate; @@ -1353,192 +1673,198 @@ yyreduce: GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; - /* Default location. */ - YYLLOC_DEFAULT (yyloc, yylsp - yylen, yylen); + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: -#line 165 "ast_expr2.y" +#line 168 "ast_expr2.y" { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1); - ((struct parse_io *)parseio)->val->type = (yyvsp[0].val)->type; - if( (yyvsp[0].val)->type == AST_EXPR_integer ) - ((struct parse_io *)parseio)->val->u.i = (yyvsp[0].val)->u.i; + ((struct parse_io *)parseio)->val->type = (yyvsp[(1) - (1)].val)->type; + if( (yyvsp[(1) - (1)].val)->type == AST_EXPR_integer ) + ((struct parse_io *)parseio)->val->u.i = (yyvsp[(1) - (1)].val)->u.i; else - ((struct parse_io *)parseio)->val->u.s = (yyvsp[0].val)->u.s; - free((yyvsp[0].val)); + ((struct parse_io *)parseio)->val->u.s = (yyvsp[(1) - (1)].val)->u.s; + free((yyvsp[(1) - (1)].val)); ;} break; case 3: -#line 175 "ast_expr2.y" - { (yyval.val)= (yyvsp[0].val);;} +#line 176 "ast_expr2.y" + {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1); + ((struct parse_io *)parseio)->val->type = AST_EXPR_string; + ((struct parse_io *)parseio)->val->u.s = strdup(""); + ;} break; case 4: -#line 176 "ast_expr2.y" - { (yyval.val) = (yyvsp[-1].val); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0; - DESTROY((yyvsp[-2].val)); DESTROY((yyvsp[0].val)); ;} +#line 183 "ast_expr2.y" + { (yyval.val)= (yyvsp[(1) - (1)].val);;} break; case 5: -#line 180 "ast_expr2.y" - { (yyval.val) = op_or ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 184 "ast_expr2.y" + { (yyval.val) = (yyvsp[(2) - (3)].val); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0; + DESTROY((yyvsp[(1) - (3)].val)); DESTROY((yyvsp[(3) - (3)].val)); ;} break; case 6: -#line 184 "ast_expr2.y" - { (yyval.val) = op_and ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 188 "ast_expr2.y" + { (yyval.val) = op_or ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 7: -#line 188 "ast_expr2.y" - { (yyval.val) = op_eq ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 192 "ast_expr2.y" + { (yyval.val) = op_and ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 8: -#line 192 "ast_expr2.y" - { (yyval.val) = op_gt ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 196 "ast_expr2.y" + { (yyval.val) = op_eq ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 9: -#line 196 "ast_expr2.y" - { (yyval.val) = op_lt ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 200 "ast_expr2.y" + { (yyval.val) = op_gt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 10: -#line 200 "ast_expr2.y" - { (yyval.val) = op_ge ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 204 "ast_expr2.y" + { (yyval.val) = op_lt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 11: -#line 204 "ast_expr2.y" - { (yyval.val) = op_le ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 208 "ast_expr2.y" + { (yyval.val) = op_ge ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 12: -#line 208 "ast_expr2.y" - { (yyval.val) = op_ne ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 212 "ast_expr2.y" + { (yyval.val) = op_le ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 13: -#line 212 "ast_expr2.y" - { (yyval.val) = op_plus ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 216 "ast_expr2.y" + { (yyval.val) = op_ne ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 14: -#line 216 "ast_expr2.y" - { (yyval.val) = op_minus ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 220 "ast_expr2.y" + { (yyval.val) = op_plus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 15: -#line 220 "ast_expr2.y" - { (yyval.val) = op_negate ((yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-1]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 224 "ast_expr2.y" + { (yyval.val) = op_minus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 16: -#line 224 "ast_expr2.y" - { (yyval.val) = op_compl ((yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-1]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 228 "ast_expr2.y" + { (yyval.val) = op_negate ((yyvsp[(2) - (2)].val)); + DESTROY((yyvsp[(1) - (2)].val)); + (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 17: -#line 228 "ast_expr2.y" - { (yyval.val) = op_times ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 232 "ast_expr2.y" + { (yyval.val) = op_compl ((yyvsp[(2) - (2)].val)); + DESTROY((yyvsp[(1) - (2)].val)); + (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 18: -#line 232 "ast_expr2.y" - { (yyval.val) = op_div ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 236 "ast_expr2.y" + { (yyval.val) = op_times ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 19: -#line 236 "ast_expr2.y" - { (yyval.val) = op_rem ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 240 "ast_expr2.y" + { (yyval.val) = op_div ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 20: -#line 240 "ast_expr2.y" - { (yyval.val) = op_colon ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; - (yyloc).first_line=0; (yyloc).last_line=0;;} +#line 244 "ast_expr2.y" + { (yyval.val) = op_rem ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 21: -#line 244 "ast_expr2.y" - { (yyval.val) = op_eqtilde ((yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-2]).first_column; (yyloc).last_column = (yylsp[0]).last_column; +#line 248 "ast_expr2.y" + { (yyval.val) = op_colon ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; case 22: -#line 248 "ast_expr2.y" - { (yyval.val) = op_cond ((yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[0].val)); - DESTROY((yyvsp[-3].val)); - DESTROY((yyvsp[-1].val)); - (yyloc).first_column = (yylsp[-4]).first_column; (yyloc).last_column = (yylsp[-2]).last_column; +#line 252 "ast_expr2.y" + { (yyval.val) = op_eqtilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); + DESTROY((yyvsp[(2) - (3)].val)); + (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; + (yyloc).first_line=0; (yyloc).last_line=0;;} + break; + + case 23: +#line 256 "ast_expr2.y" + { (yyval.val) = op_cond ((yyvsp[(1) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(5) - (5)].val)); + DESTROY((yyvsp[(2) - (5)].val)); + DESTROY((yyvsp[(4) - (5)].val)); + (yyloc).first_column = (yylsp[(1) - (5)]).first_column; (yyloc).last_column = (yylsp[(3) - (5)]).last_column; (yyloc).first_line=0; (yyloc).last_line=0;;} break; +/* Line 1270 of yacc.c. */ +#line 1857 "ast_expr2.c" default: break; } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); -/* Line 1126 of yacc.c. */ -#line 1532 "ast_expr2.c" - - yyvsp -= yylen; - yyssp -= yylen; - yylsp -= yylen; - + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; @@ -1567,110 +1893,41 @@ yyerrlab: if (!yyerrstatus) { ++yynerrs; -#if YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (YYPACT_NINF < yyn && yyn < YYLAST) - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - char *yymsg = 0; -# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -#if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -#endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* 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 = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; } + } - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - - if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yymsg; - int yyi = 0; - while ((*yyp = *yyf)) - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); - } - else - { - yyerror (YY_("syntax error")); + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) goto yyexhaustedlab; - } - } - else -#endif /* YYERROR_VERBOSE */ - yyerror (YY_("syntax error")); + } + } +#endif } yyerror_range[0] = yylloc; @@ -1681,14 +1938,15 @@ yyerrlab: error, discard it. */ if (yychar <= YYEOF) - { + { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; - } + } else { - yydestruct ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc); yychar = YYEMPTY; } } @@ -1706,13 +1964,15 @@ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ - if (0) + if (/*CONSTCOND*/ 0) goto yyerrorlab; yyerror_range[0] = yylsp[1-yylen]; - yylsp -= yylen; - yyvsp -= yylen; - yyssp -= yylen; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; @@ -1742,8 +2002,9 @@ yyerrlab1: YYABORT; yyerror_range[0] = *yylsp; - yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp); - YYPOPSTACK; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp); + YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } @@ -1755,11 +2016,11 @@ yyerrlab1: 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); + the look-ahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); *++yylsp = yyloc; - /* Shift the error token. */ + /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; @@ -1794,21 +2055,29 @@ yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp, yylsp); - YYPOPSTACK; + YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); #endif return yyresult; } -#line 255 "ast_expr2.y" +#line 263 "ast_expr2.y" static struct val * @@ -1979,11 +2248,40 @@ void ast_log(int level, const char *file, int line, const char *function, const int main(int argc,char **argv) { char s[4096]; + char out[4096]; + FILE *infile; - if (ast_expr(argv[1], s, sizeof(s))) - printf("=====%s======\n",s); + if( !argv[1] ) + exit(20); + + if( access(argv[1],F_OK)== 0 ) + { + int ret; + + infile = fopen(argv[1],"r"); + if( !infile ) + { + printf("Sorry, couldn't open %s for reading!\n", argv[1]); + exit(10); + } + while( fgets(s,sizeof(s),infile) ) + { + if( s[strlen(s)-1] == '\n' ) + s[strlen(s)-1] = 0; + + ret = ast_expr(s, out, sizeof(out)); + printf("Expression: %s Result: [%d] '%s'\n", + s, ret, out); + } + fclose(infile); + } else - printf("No result\n"); + { + if (ast_expr(argv[1], s, sizeof(s))) + printf("=====%s======\n",s); + else + printf("No result\n"); + } } #endif @@ -2207,7 +2505,8 @@ op_plus (struct val *a, struct val *b) struct val *r; if (!to_integer (a)) { - ast_log(LOG_WARNING,"non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING,"non-numeric argument\n"); if (!to_integer (b)) { free_value(a); free_value(b); @@ -2250,7 +2549,8 @@ op_minus (struct val *a, struct val *b) struct val *r; if (!to_integer (a)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); if (!to_integer (b)) { free_value(a); free_value(b); @@ -2262,7 +2562,8 @@ op_minus (struct val *a, struct val *b) return (r); } } else if (!to_integer(b)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); free_value(b); return (a); } @@ -2283,7 +2584,8 @@ op_negate (struct val *a) if (!to_integer (a) ) { free_value(a); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(0); } @@ -2365,7 +2667,8 @@ op_times (struct val *a, struct val *b) if (!to_integer (a) || !to_integer (b)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return(make_integer(0)); } @@ -2397,12 +2700,14 @@ op_div (struct val *a, struct val *b) if (!to_integer (a)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(0); } else if (!to_integer (b)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(INT_MAX); } @@ -2428,7 +2733,8 @@ op_rem (struct val *a, struct val *b) struct val *r; if (!to_integer (a) || !to_integer (b)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); free_value(a); free_value(b); return make_integer(0); diff --git a/ast_expr2.fl b/ast_expr2.fl index 8eaea639fa..6273bc8b1c 100644 --- a/ast_expr2.fl +++ b/ast_expr2.fl @@ -19,7 +19,7 @@ /*! \file * - * \brief Dialplan Expression Parser + * \brief Dialplan Expression Lexical Scanner */ #include <sys/types.h> @@ -73,6 +73,7 @@ struct parse_io void ast_yyset_column(int column_no, yyscan_t yyscanner); int ast_yyget_column(yyscan_t yyscanner); static int curlycount = 0; +static char *expr2_token_subst(char *mess); %} %option prefix="ast_yy" @@ -89,6 +90,10 @@ static int curlycount = 0; \| { SET_COLUMNS; SET_STRING; return TOK_OR;} \& { SET_COLUMNS; SET_STRING; return TOK_AND;} \= { SET_COLUMNS; SET_STRING; return TOK_EQ;} +\|\| { SET_COLUMNS; SET_STRING; return TOK_OR;} +\&\& { SET_COLUMNS; SET_STRING; return TOK_AND;} +\=\= { SET_COLUMNS; SET_STRING; return TOK_EQ;} +\=~ { SET_COLUMNS; SET_STRING; return TOK_EQTILDE;} \> { SET_COLUMNS; SET_STRING; return TOK_GT;} \< { SET_COLUMNS; SET_STRING; return TOK_LT;} \>\= { SET_COLUMNS; SET_STRING; return TOK_GE;} @@ -100,6 +105,7 @@ static int curlycount = 0; \/ { SET_COLUMNS; SET_STRING; return TOK_DIV;} \% { SET_COLUMNS; SET_STRING; return TOK_MOD;} \? { SET_COLUMNS; SET_STRING; return TOK_COND;} +\! { SET_COLUMNS; SET_STRING; return TOK_COMPL;} \: { SET_COLUMNS; SET_STRING; return TOK_COLON;} \:\: { SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;} \( { SET_COLUMNS; SET_STRING; return TOK_LP;} @@ -114,14 +120,15 @@ static int curlycount = 0; [0-9]+ { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */ SET_NUMERIC_STRING; return TOKEN;} -[a-zA-Z0-9,.';\\_^%$#@!]+ {SET_COLUMNS; SET_STRING; return TOKEN;} + +[a-zA-Z0-9,.';\\_^$#@]+ {SET_COLUMNS; SET_STRING; return TOKEN;} <var>[^{}]*\} {curlycount--; if(curlycount < 0){ BEGIN(trail); yymore();} else { yymore();}} <var>[^{}]*\{ {curlycount++; yymore(); } <trail>[^-\t\r \n$():?%/+=*<>!|&]* {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN;} <trail>[-\t\r \n$():?%/+=*<>!|&] {char c = yytext[yyleng-1]; BEGIN(0); unput(c); SET_COLUMNS; SET_STRING; return TOKEN;} <trail>\$\{ {curlycount = 0; BEGIN(var); yymore(); } -<trail><<EOF>> {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /* actually, if an expr is only a variable ref, this could happen a LOT */} +<trail><<EOF>> {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /*actually, if an expr is only a variable ref, this could happen a LOT */} %% @@ -175,16 +182,129 @@ int ast_expr(char *expr, char *buf, int length) return return_value; } + +char extra_error_message[4095]; +int extra_error_message_supplied = 0; +void ast_expr_register_extra_error_info(char *message); +void ast_expr_clear_extra_error_info(void); + +void ast_expr_register_extra_error_info(char *message) +{ + extra_error_message_supplied=1; + strcpy(extra_error_message, message); +} + +void ast_expr_clear_extra_error_info(void) +{ + extra_error_message_supplied=0; + extra_error_message[0] = 0; +} + +static char *expr2_token_equivs1[] = +{ + "TOKEN", + "TOK_COND", + "TOK_COLONCOLON", + "TOK_OR", + "TOK_AND", + "TOK_EQ", + "TOK_GT", + "TOK_LT", + "TOK_GE", + "TOK_LE", + "TOK_NE", + "TOK_PLUS", + "TOK_MINUS", + "TOK_MULT", + "TOK_DIV", + "TOK_MOD", + "TOK_COMPL", + "TOK_COLON", + "TOK_EQTILDE", + "TOK_RP", + "TOK_LP" +}; + +static char *expr2_token_equivs2[] = +{ + "<token>", + "?", + "::", + "|", + "&", + "=", + ">", + "<", + ">=", + "<=", + "!=", + "+", + "-", + "*", + "/", + "%", + "!", + ":", + "=~", + ")", + "(" +}; + + +static char *expr2_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 expr2_token_equivs_entries = sizeof(expr2_token_equivs1)/sizeof(char*); + + for (p=mess; *p; p++) { + for (i=0; i<expr2_token_equivs_entries; i++) { + if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) + { + len+=strlen(expr2_token_equivs2[i])+2; + p += strlen(expr2_token_equivs1[i])-1; + break; + } + } + len++; + } + res = (char*)malloc(len+1); + res[0] = 0; + s = res; + for (p=mess; *p;) { + int found = 0; + for (i=0; i<expr2_token_equivs_entries; i++) { + if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) { + *s++ = '\''; + for (t=expr2_token_equivs2[i]; *t;) { + *s++ = *t++; + } + *s++ = '\''; + p += strlen(expr2_token_equivs1[i]); + found = 1; + break; + } + } + if( !found ) + *s++ = *p++; + } + *s++ = 0; + return res; +} + int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) { struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner); char spacebuf[8000]; /* best safe than sorry */ char spacebuf2[8000]; /* best safe than sorry */ int i=0; + char *s2 = expr2_token_subst((char *)s); spacebuf[0] = 0; for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro, - which is the same thing as... get this: + which is the same thing as... get this: yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column I was tempted to just use yy_buf_pos in the STATE, but..., well: a. the yy_buf_pos is the current position in the buffer, which @@ -199,14 +319,15 @@ int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) #ifdef STANDALONE3 /* easier to read in the standalone version */ - printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n", - s, parseio->string,spacebuf2); + printf("ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n", + (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2); #else - ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n", - s, parseio->string,spacebuf2); + ast_log(LOG_WARNING,"ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n", + (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2); #endif #ifndef STANDALONE ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n"); #endif + free(s2); return(0); } diff --git a/ast_expr2.h b/ast_expr2.h index f90139c8e7..190ef975c2 100644 --- a/ast_expr2.h +++ b/ast_expr2.h @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 2.1. */ +/* A Bison parser, made by GNU Bison 2.1a. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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 @@ -78,13 +78,15 @@ -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 142 "ast_expr2.y" -typedef union YYSTYPE { +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 140 "ast_expr2.y" +{ struct val *val; -} YYSTYPE; -/* Line 1447 of yacc.c. */ -#line 88 "ast_expr2.h" +} +/* Line 1536 of yacc.c. */ +#line 89 "ast_expr2.h" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -92,7 +94,7 @@ typedef union YYSTYPE { -#if ! defined (YYLTYPE) && ! defined (YYLTYPE_IS_DECLARED) +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED typedef struct YYLTYPE { int first_line; diff --git a/ast_expr2.y b/ast_expr2.y index 58295c9f63..6886cf7c40 100644 --- a/ast_expr2.y +++ b/ast_expr2.y @@ -17,6 +17,7 @@ #include <stdlib.h> #include <string.h> #include <locale.h> +#include <unistd.h> #include <ctype.h> #if !defined(SOLARIS) && !defined(__CYGWIN__) #include <err.h> @@ -51,6 +52,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define YYPARSE_PARAM parseio #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner #define YYERROR_VERBOSE 1 +extern char extra_error_message[4095]; +extern int extra_error_message_supplied; enum valtype { AST_EXPR_integer, AST_EXPR_numeric_string, AST_EXPR_string @@ -129,12 +132,7 @@ int ast_yyerror(const char *,YYLTYPE *, struct parse_io *); some useful info about the error. Not as easy as it looks, but it is possible. */ #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio) -#define DESTROY(x) { \ -if ((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) \ - free((x)->u.s); \ - (x)->u.s = 0; \ - free(x); \ -} +#define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);} %} %pure-parser @@ -165,6 +163,11 @@ extern int ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t)); %token <val> TOKEN %type <val> start expr + +%destructor { free_value($$); } expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ + TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE + TOK_RP TOK_LP + %% start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1); @@ -175,6 +178,11 @@ start: expr { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(st ((struct parse_io *)parseio)->val->u.s = $1->u.s; free($1); } + | {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1); + ((struct parse_io *)parseio)->val->type = AST_EXPR_string; + ((struct parse_io *)parseio)->val->u.s = strdup(""); + } + ; expr: TOKEN { $$= $1;} @@ -427,11 +435,40 @@ void ast_log(int level, const char *file, int line, const char *function, const int main(int argc,char **argv) { char s[4096]; + char out[4096]; + FILE *infile; - if (ast_expr(argv[1], s, sizeof(s))) - printf("=====%s======\n",s); + if( !argv[1] ) + exit(20); + + if( access(argv[1],F_OK)== 0 ) + { + int ret; + + infile = fopen(argv[1],"r"); + if( !infile ) + { + printf("Sorry, couldn't open %s for reading!\n", argv[1]); + exit(10); + } + while( fgets(s,sizeof(s),infile) ) + { + if( s[strlen(s)-1] == '\n' ) + s[strlen(s)-1] = 0; + + ret = ast_expr(s, out, sizeof(out)); + printf("Expression: %s Result: [%d] '%s'\n", + s, ret, out); + } + fclose(infile); + } else - printf("No result\n"); + { + if (ast_expr(argv[1], s, sizeof(s))) + printf("=====%s======\n",s); + else + printf("No result\n"); + } } #endif @@ -655,7 +692,8 @@ op_plus (struct val *a, struct val *b) struct val *r; if (!to_integer (a)) { - ast_log(LOG_WARNING,"non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING,"non-numeric argument\n"); if (!to_integer (b)) { free_value(a); free_value(b); @@ -698,7 +736,8 @@ op_minus (struct val *a, struct val *b) struct val *r; if (!to_integer (a)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); if (!to_integer (b)) { free_value(a); free_value(b); @@ -710,7 +749,8 @@ op_minus (struct val *a, struct val *b) return (r); } } else if (!to_integer(b)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); free_value(b); return (a); } @@ -731,7 +771,8 @@ op_negate (struct val *a) if (!to_integer (a) ) { free_value(a); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(0); } @@ -813,7 +854,8 @@ op_times (struct val *a, struct val *b) if (!to_integer (a) || !to_integer (b)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return(make_integer(0)); } @@ -845,12 +887,14 @@ op_div (struct val *a, struct val *b) if (!to_integer (a)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(0); } else if (!to_integer (b)) { free_value(a); free_value(b); - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); return make_integer(INT_MAX); } @@ -876,7 +920,8 @@ op_rem (struct val *a, struct val *b) struct val *r; if (!to_integer (a) || !to_integer (b)) { - ast_log(LOG_WARNING, "non-numeric argument\n"); + if( !extra_error_message_supplied ) + ast_log(LOG_WARNING, "non-numeric argument\n"); free_value(a); free_value(b); return make_integer(0); diff --git a/ast_expr2f.c b/ast_expr2f.c index ed87455960..bc0dcb34f1 100644 --- a/ast_expr2f.c +++ b/ast_expr2f.c @@ -523,34 +523,34 @@ static yyconst flex_int16_t yy_nxt[][128] = 7, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, - -11, -11, -11, 36, -11, 36, 36, 36, -11, 36, - -11, -11, -11, -11, 36, -11, 36, -11, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, -11, 36, - -11, 37, -11, -11, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -11, 36, -11, 36, 36, -11, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, -11, -11, -11, -11, -11 + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, 36, -11, -11, -11, -11, -11, -11, -11, -11, + + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11 }, { - 7, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, - - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38 + 7, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 38, 37, 37, 37, 37, 37, + + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37 }, { @@ -558,51 +558,51 @@ static yyconst flex_int16_t yy_nxt[][128] = -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, -13, - -13, -13, -13, 36, -13, 36, 36, 36, -13, 36, - -13, -13, -13, -13, 36, -13, 36, -13, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, -13, 36, - -13, -13, -13, -13, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -13, 36, -13, 36, 36, -13, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, -13, -13, -13, -13, -13 + -13, -13, -13, -13, -13, 39, 39, -13, -13, 39, + -13, -13, -13, -13, 39, -13, 39, -13, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, -13, 39, + -13, -13, -13, -13, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, -13, 39, -13, 39, 39, -13, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, -13, -13, -13, -13, -13 }, { 7, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, -14, - -14, -14, -14, 36, -14, 36, 36, 36, -14, 36, - -14, -14, -14, -14, 36, -14, 36, -14, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, -14, 36, - -14, -14, -14, -14, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -14, 36, -14, 36, 36, -14, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 40, -14, -14, -14, -14 + -14, -14, -14, -14, -14, 39, 39, -14, -14, 39, + -14, -14, -14, -14, 39, -14, 39, -14, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, -14, 39, + -14, -14, -14, -14, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, -14, 39, -14, 39, 39, -14, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 40, -14, -14, -14, -14 }, { 7, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, - -15, -15, -15, 36, -15, 36, 36, 36, -15, 36, - -15, -15, -15, -15, 36, -15, 36, -15, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, -15, 36, - -15, -15, -15, -15, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -15, 36, -15, 36, 36, -15, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, -15, -15, -15, -15, -15 + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, + -15, -15, -15, -15, -15, -15, -15, -15 }, { @@ -610,7 +610,7 @@ static yyconst flex_int16_t yy_nxt[][128] = -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, - -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16, -16, 41, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, @@ -731,17 +731,17 @@ static yyconst flex_int16_t yy_nxt[][128] = -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, -23, - -23, -23, -23, 36, -23, 36, 36, 36, -23, 36, - -23, -23, -23, -23, 36, -23, 36, -23, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, -23, 36, - -23, -23, -23, -23, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -23, 36, -23, 36, 36, -23, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, -23, -23, -23, -23, -23 + -23, -23, -23, -23, -23, 39, 39, -23, -23, 39, + -23, -23, -23, -23, 39, -23, 39, -23, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, -23, 39, + -23, -23, -23, -23, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, -23, 39, -23, 39, 39, -23, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, -23, -23, -23, -23, -23 }, { @@ -750,7 +750,7 @@ static yyconst flex_int16_t yy_nxt[][128] = -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, - -24, -24, -24, -24, -24, -24, -24, -24, 42, -24, + -24, -24, -24, -24, -24, -24, -24, -24, 43, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, @@ -769,7 +769,7 @@ static yyconst flex_int16_t yy_nxt[][128] = -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, 43, -25, -25, -25, -25, -25, -25, -25, -25, + -25, 44, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, @@ -786,14 +786,14 @@ static yyconst flex_int16_t yy_nxt[][128] = -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, 45, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, - -26, -26, -26, -26, -26, -26, -26, -26 + -26, -26, -26, -26, -26, -26, 46, -26 }, { @@ -803,7 +803,7 @@ static yyconst flex_int16_t yy_nxt[][128] = -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, - -27, 44, -27, -27, -27, -27, -27, -27, -27, -27, + -27, 47, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, -27, @@ -844,25 +844,25 @@ static yyconst flex_int16_t yy_nxt[][128] = -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, -29, - -29, -29, -29, -29, -29, -29, -29, -29 + -29, -29, -29, -29, 48, -29, -29, -29 }, { - 7, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 46, 45, 47, 45, 45 + 7, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 50, 49, 51, 49, 49 }, { @@ -900,21 +900,21 @@ static yyconst flex_int16_t yy_nxt[][128] = }, { - 7, 48, 48, 48, 48, 48, 48, 48, 48, -33, - - -33, 48, 48, -33, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, -33, -33, 48, 48, -33, -33, -33, 48, - -33, -33, -33, -33, 48, -33, 48, -33, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, -33, 48, - -33, -33, -33, -33, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, -33, 48, 48, 48 + 7, 52, 52, 52, 52, 52, 52, 52, 52, -33, + + -33, 52, 52, -33, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, -33, -33, 52, 52, -33, -33, -33, 52, + -33, -33, -33, -33, 52, -33, 52, -33, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, -33, 52, + -33, -33, -33, -33, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, -33, 52, 52, 52 }, { @@ -948,7 +948,7 @@ static yyconst flex_int16_t yy_nxt[][128] = -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, -35, - -35, -35, -35, 49, -35, -35, -35, -35 + -35, -35, -35, 53, -35, -35, -35, -35 }, { @@ -956,51 +956,51 @@ static yyconst flex_int16_t yy_nxt[][128] = -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, - -36, -36, -36, 36, -36, 36, 36, 36, -36, 36, - -36, -36, -36, -36, 36, -36, 36, -36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, -36, 36, - -36, -36, -36, -36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -36, 36, -36, 36, 36, -36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, -36, -36, -36, -36, -36 + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + + -36, -36, -36, -36, -36, -36, -36, -36 }, { - 7, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, - -37, -37, -37, -37, -37, -37, -37, -37 + 7, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 38, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37 }, { - 7, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 39, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38 + 7, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38 }, { @@ -1008,16 +1008,16 @@ static yyconst flex_int16_t yy_nxt[][128] = -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -39, -39 + -39, -39, -39, -39, -39, 39, 39, -39, -39, 39, + -39, -39, -39, -39, 39, -39, 39, -39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, -39, 39, + -39, -39, -39, -39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, -39, 39, -39, 39, 39, -39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, -39, -39, -39, -39, -39 }, @@ -1042,34 +1042,34 @@ static yyconst flex_int16_t yy_nxt[][128] = 7, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, - -41, -41, -41, 36, -41, 36, 36, 36, -41, 36, - -41, -41, -41, -41, 36, -41, 36, -41, 41, 41, - 41, 41, 41, 41, 41, 41, 41, 41, -41, 36, - -41, -41, -41, -41, 36, 36, 36, 36, 36, 36, - - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, -41, 36, -41, 36, 36, -41, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, -41, -41, -41, -41, -41 + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41, -41, -41, + -41, -41, -41, -41, -41, -41, -41, -41 }, { 7, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, - -42, -42, -42, -42, -42, -42, -42, -42 + -42, -42, -42, -42, -42, 39, 39, -42, -42, 39, + + -42, -42, -42, -42, 39, -42, 39, -42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, -42, 39, + -42, -42, -42, -42, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, -42, 39, -42, 39, 39, -42, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, -42, -42, -42, -42, -42 }, { @@ -1108,20 +1108,20 @@ static yyconst flex_int16_t yy_nxt[][128] = }, { - 7, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 46, 45, 47, 45, 45 + 7, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45, -45, -45, + -45, -45, -45, -45, -45, -45, -45, -45 }, { @@ -1160,38 +1160,107 @@ static yyconst flex_int16_t yy_nxt[][128] = }, { - 7, 48, 48, 48, 48, 48, 48, 48, 48, -48, - -48, 48, 48, -48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, -48, -48, 48, 48, -48, -48, -48, 48, - -48, -48, -48, -48, 48, -48, 48, -48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, -48, 48, - - -48, -48, -48, -48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, - 48, 48, 48, 48, -48, 48, 48, 48 + 7, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48 }, { - 7, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49, -49, -49, - -49, -49, -49, -49, -49, -49, -49, -49 + 7, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 50, 49, 51, 49, 49 + + }, + { + 7, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50, -50 + }, + + { + 7, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51, -51 + }, + + { + 7, 52, 52, 52, 52, 52, 52, 52, 52, -52, + -52, 52, 52, -52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, -52, -52, 52, 52, -52, -52, -52, 52, + + -52, -52, -52, -52, 52, -52, 52, -52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, -52, 52, + -52, -52, -52, -52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, -52, 52, 52, 52 + }, + + { + 7, -53, -53, -53, -53, -53, -53, -53, -53, -53, + + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + + -53, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53, -53 }, } ; @@ -1212,8 +1281,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 30 -#define YY_END_OF_BUFFER 31 +#define YY_NUM_RULES 35 +#define YY_END_OF_BUFFER 36 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -1221,22 +1290,24 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[50] = +static yyconst flex_int16_t yy_accept[54] = { 0, - 0, 0, 0, 0, 27, 27, 31, 30, 20, 22, - 24, 30, 24, 24, 13, 2, 17, 18, 11, 9, - 10, 12, 23, 15, 5, 3, 4, 14, 1, 30, - 26, 25, 27, 28, 28, 24, 8, 0, 21, 19, - 23, 16, 7, 6, 0, 26, 25, 27, 29 + 0, 0, 0, 0, 32, 32, 36, 35, 25, 27, + 19, 35, 29, 29, 17, 2, 22, 23, 15, 13, + 14, 16, 28, 20, 9, 3, 8, 18, 1, 35, + 31, 30, 32, 33, 33, 12, 0, 26, 29, 24, + 5, 28, 21, 11, 6, 7, 10, 4, 0, 31, + 30, 32, 34 } ; -static yyconst yy_state_type yy_NUL_trans[50] = +static yyconst yy_state_type yy_NUL_trans[54] = { 0, 8, 8, 30, 30, 33, 33, 0, 0, 0, 0, - 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, - 0, 0, 48, 0, 0, 0, 0, 38, 0, 0, - 0, 0, 0, 0, 45, 0, 0, 48, 0 + 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 0, 0, 52, 0, 0, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, + 0, 52, 0 } ; /* The intent behind this definition is that it'll catch @@ -1248,9 +1319,27 @@ static yyconst yy_state_type yy_NUL_trans[50] = #define YY_RESTORE_YY_MORE_OFFSET #line 1 "ast_expr2.fl" #line 2 "ast_expr2.fl" +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 1999 - 2006, Digium, Inc. + * + * Mark Spencer <markster@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + /*! \file * - * \brief Dialplan Expression Parser + * \brief Dialplan Expression Lexical Scanner */ #include <sys/types.h> @@ -1304,8 +1393,9 @@ struct parse_io void ast_yyset_column(int column_no, yyscan_t yyscanner); int ast_yyget_column(yyscan_t yyscanner); static int curlycount = 0; +static char *expr2_token_subst(char *mess); -#line 1304 "ast_expr2f.c" +#line 1394 "ast_expr2f.c" #define INITIAL 0 #define var 1 @@ -1522,10 +1612,10 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 64 "ast_expr2.fl" +#line 83 "ast_expr2.fl" -#line 1524 "ast_expr2f.c" +#line 1614 "ast_expr2f.c" yylval = yylval_param; @@ -1608,167 +1698,192 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 66 "ast_expr2.fl" +#line 85 "ast_expr2.fl" { SET_COLUMNS; SET_STRING; return TOK_OR;} YY_BREAK case 2: YY_RULE_SETUP -#line 67 "ast_expr2.fl" +#line 86 "ast_expr2.fl" { SET_COLUMNS; SET_STRING; return TOK_AND;} YY_BREAK case 3: YY_RULE_SETUP -#line 68 "ast_expr2.fl" +#line 87 "ast_expr2.fl" { SET_COLUMNS; SET_STRING; return TOK_EQ;} YY_BREAK case 4: YY_RULE_SETUP -#line 69 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_GT;} +#line 88 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_OR;} YY_BREAK case 5: YY_RULE_SETUP -#line 70 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_LT;} +#line 89 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_AND;} YY_BREAK case 6: YY_RULE_SETUP -#line 71 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_GE;} +#line 90 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_EQ;} YY_BREAK case 7: YY_RULE_SETUP -#line 72 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_LE;} +#line 91 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_EQTILDE;} YY_BREAK case 8: YY_RULE_SETUP -#line 73 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_NE;} +#line 92 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_GT;} YY_BREAK case 9: YY_RULE_SETUP -#line 74 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_PLUS;} +#line 93 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_LT;} YY_BREAK case 10: YY_RULE_SETUP -#line 75 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_MINUS;} +#line 94 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_GE;} YY_BREAK case 11: YY_RULE_SETUP -#line 76 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_MULT;} +#line 95 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_LE;} YY_BREAK case 12: YY_RULE_SETUP -#line 77 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_DIV;} +#line 96 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_NE;} YY_BREAK case 13: YY_RULE_SETUP -#line 78 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_MOD;} +#line 97 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_PLUS;} YY_BREAK case 14: YY_RULE_SETUP -#line 79 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_COND;} +#line 98 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_MINUS;} YY_BREAK case 15: YY_RULE_SETUP -#line 80 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_COLON;} +#line 99 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_MULT;} YY_BREAK case 16: YY_RULE_SETUP -#line 81 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;} +#line 100 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_DIV;} YY_BREAK case 17: YY_RULE_SETUP -#line 82 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_LP;} +#line 101 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_MOD;} YY_BREAK case 18: YY_RULE_SETUP -#line 83 "ast_expr2.fl" -{ SET_COLUMNS; SET_STRING; return TOK_RP;} +#line 102 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_COND;} YY_BREAK case 19: YY_RULE_SETUP -#line 84 "ast_expr2.fl" +#line 103 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_COMPL;} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 104 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_COLON;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 105 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_COLONCOLON;} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 106 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_LP;} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 107 "ast_expr2.fl" +{ SET_COLUMNS; SET_STRING; return TOK_RP;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 108 "ast_expr2.fl" {/* gather the contents of ${} expressions, with trailing stuff, into a single TOKEN. They are much more complex now than they used to be */ curlycount = 0; BEGIN(var); yymore();} YY_BREAK -case 20: +case 25: YY_RULE_SETUP -#line 87 "ast_expr2.fl" +#line 111 "ast_expr2.fl" {} YY_BREAK -case 21: -/* rule 21 can match eol */ +case 26: +/* rule 26 can match eol */ YY_RULE_SETUP -#line 88 "ast_expr2.fl" +#line 112 "ast_expr2.fl" {SET_COLUMNS; SET_STRING; return TOKEN;} YY_BREAK -case 22: -/* rule 22 can match eol */ +case 27: +/* rule 27 can match eol */ YY_RULE_SETUP -#line 90 "ast_expr2.fl" +#line 114 "ast_expr2.fl" {/* what to do with eol */} YY_BREAK -case 23: +case 28: YY_RULE_SETUP -#line 91 "ast_expr2.fl" +#line 115 "ast_expr2.fl" { SET_COLUMNS; /* the original behavior of the expression parser was to bring in numbers as a numeric string */ SET_NUMERIC_STRING; return TOKEN;} YY_BREAK -case 24: +case 29: YY_RULE_SETUP -#line 94 "ast_expr2.fl" +#line 119 "ast_expr2.fl" {SET_COLUMNS; SET_STRING; return TOKEN;} YY_BREAK -case 25: -/* rule 25 can match eol */ +case 30: +/* rule 30 can match eol */ YY_RULE_SETUP -#line 96 "ast_expr2.fl" +#line 121 "ast_expr2.fl" {curlycount--; if(curlycount < 0){ BEGIN(trail); yymore();} else { yymore();}} YY_BREAK -case 26: -/* rule 26 can match eol */ +case 31: +/* rule 31 can match eol */ YY_RULE_SETUP -#line 97 "ast_expr2.fl" +#line 122 "ast_expr2.fl" {curlycount++; yymore(); } YY_BREAK -case 27: +case 32: YY_RULE_SETUP -#line 98 "ast_expr2.fl" +#line 123 "ast_expr2.fl" {BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN;} YY_BREAK -case 28: -/* rule 28 can match eol */ +case 33: +/* rule 33 can match eol */ YY_RULE_SETUP -#line 99 "ast_expr2.fl" +#line 124 "ast_expr2.fl" {char c = yytext[yyleng-1]; BEGIN(0); unput(c); SET_COLUMNS; SET_STRING; return TOKEN;} YY_BREAK -case 29: +case 34: YY_RULE_SETUP -#line 100 "ast_expr2.fl" +#line 125 "ast_expr2.fl" {curlycount = 0; BEGIN(var); yymore(); } YY_BREAK case YY_STATE_EOF(trail): -#line 101 "ast_expr2.fl" -{BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /* actually, if an expr is only a variable ref, this could happen a LOT */} +#line 126 "ast_expr2.fl" +{BEGIN(0); SET_COLUMNS; SET_STRING; return TOKEN; /*actually, if an expr is only a variable ref, this could happen a LOT */} YY_BREAK -case 30: +case 35: YY_RULE_SETUP -#line 103 "ast_expr2.fl" +#line 128 "ast_expr2.fl" ECHO; YY_BREAK -#line 1767 "ast_expr2f.c" +#line 1882 "ast_expr2f.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(var): yyterminate(); @@ -2901,7 +3016,7 @@ void ast_yyfree (void * ptr , yyscan_t yyscanner) #undef YY_DECL_IS_OURS #undef YY_DECL #endif -#line 103 "ast_expr2.fl" +#line 128 "ast_expr2.fl" @@ -2955,16 +3070,129 @@ int ast_expr(char *expr, char *buf, int length) return return_value; } + +char extra_error_message[4095]; +int extra_error_message_supplied = 0; +void ast_expr_register_extra_error_info(char *message); +void ast_expr_clear_extra_error_info(void); + +void ast_expr_register_extra_error_info(char *message) +{ + extra_error_message_supplied=1; + strcpy(extra_error_message, message); +} + +void ast_expr_clear_extra_error_info(void) +{ + extra_error_message_supplied=0; + extra_error_message[0] = 0; +} + +static char *expr2_token_equivs1[] = +{ + "TOKEN", + "TOK_COND", + "TOK_COLONCOLON", + "TOK_OR", + "TOK_AND", + "TOK_EQ", + "TOK_GT", + "TOK_LT", + "TOK_GE", + "TOK_LE", + "TOK_NE", + "TOK_PLUS", + "TOK_MINUS", + "TOK_MULT", + "TOK_DIV", + "TOK_MOD", + "TOK_COMPL", + "TOK_COLON", + "TOK_EQTILDE", + "TOK_RP", + "TOK_LP" +}; + +static char *expr2_token_equivs2[] = +{ + "<token>", + "?", + "::", + "|", + "&", + "=", + ">", + "<", + ">=", + "<=", + "!=", + "+", + "-", + "*", + "/", + "%", + "!", + ":", + "=~", + ")", + "(" +}; + + +static char *expr2_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 expr2_token_equivs_entries = sizeof(expr2_token_equivs1)/sizeof(char*); + + for (p=mess; *p; p++) { + for (i=0; i<expr2_token_equivs_entries; i++) { + if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) + { + len+=strlen(expr2_token_equivs2[i])+2; + p += strlen(expr2_token_equivs1[i])-1; + break; + } + } + len++; + } + res = (char*)malloc(len+1); + res[0] = 0; + s = res; + for (p=mess; *p;) { + int found = 0; + for (i=0; i<expr2_token_equivs_entries; i++) { + if ( strncmp(p,expr2_token_equivs1[i],strlen(expr2_token_equivs1[i])) == 0 ) { + *s++ = '\''; + for (t=expr2_token_equivs2[i]; *t;) { + *s++ = *t++; + } + *s++ = '\''; + p += strlen(expr2_token_equivs1[i]); + found = 1; + break; + } + } + if( !found ) + *s++ = *p++; + } + *s++ = 0; + return res; +} + int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) { struct yyguts_t * yyg = (struct yyguts_t*)(parseio->scanner); char spacebuf[8000]; /* best safe than sorry */ char spacebuf2[8000]; /* best safe than sorry */ int i=0; + char *s2 = expr2_token_subst((char *)s); spacebuf[0] = 0; for(i=0;i< (int)(yytext - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf);i++) spacebuf2[i] = ' '; /* uh... assuming yyg is defined, then I can use the yycolumn macro, - which is the same thing as... get this: + which is the same thing as... get this: yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]->yy_bs_column I was tempted to just use yy_buf_pos in the STATE, but..., well: a. the yy_buf_pos is the current position in the buffer, which @@ -2979,15 +3207,16 @@ int ast_yyerror (const char *s, yyltype *loc, struct parse_io *parseio ) #ifdef STANDALONE3 /* easier to read in the standalone version */ - printf("ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n", - s, parseio->string,spacebuf2); + printf("ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n", + (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2); #else - ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n", - s, parseio->string,spacebuf2); + ast_log(LOG_WARNING,"ast_yyerror(): %s syntax error: %s; Input:\n%s\n%s\n", + (extra_error_message_supplied?extra_error_message:""), s2, parseio->string,spacebuf2); #endif #ifndef STANDALONE ast_log(LOG_WARNING,"If you have questions, please refer to doc/channelvariables.txt in the asterisk source.\n"); #endif + free(s2); return(0); } diff --git a/configs/extensions.ael.sample b/configs/extensions.ael.sample index 87fe580394..39e0e191d5 100644 --- a/configs/extensions.ael.sample +++ b/configs/extensions.ael.sample @@ -1,6 +1,307 @@ // // Example AEL config file // +// +// Static extension configuration file, used by +// the pbx_config module. This is where you configure all your +// inbound and outbound calls in Asterisk. +// +// This configuration file is reloaded +// - With the "extensions reload" command in the CLI +// - With the "reload" command (that reloads everything) in the CLI + +// The "Globals" category contains global variables that can be referenced +// in the dialplan with ${VARIABLE} or ${ENV(VARIABLE)} for Environmental +// variables, +// ${${VARIABLE}} or ${text${VARIABLE}} or any hybrid +// + +globals { + CONSOLE="Console/dsp"; // Console interface for demo + //CONSOLE=Zap/1 + //CONSOLE=Phone/phone0 + IAXINFO=guest; // IAXtel username/password + //IAXINFO="myuser:mypass"; + TRUNK="Zap/g2"; // Trunk interface + // + // Note the 'g2' in the TRUNK variable above. It specifies which group (defined + // in zapata.conf) to dial, i.e. group 2, and how to choose a channel to use in + // the specified group. The four possible options are: + // + // g: select the lowest-numbered non-busy Zap channel + // (aka. ascending sequential hunt group). + // G: select the highest-numbered non-busy Zap channel + // (aka. descending sequential hunt group). + // r: use a round-robin search, starting at the next highest channel than last + // time (aka. ascending rotary hunt group). + // R: use a round-robin search, starting at the next lowest channel than last + // time (aka. descending rotary hunt group). + // + TRUNKMSD=1; // MSD digits to strip (usually 1 or 0) + //TRUNK=IAX2/user:pass@provider +}; + +// +// Any category other than "General" and "Globals" represent +// extension contexts, which are collections of extensions. +// +// Extension names may be numbers, letters, or combinations +// thereof. If an extension name is prefixed by a '_' +// character, it is interpreted as a pattern rather than a +// literal. In patterns, some characters have special meanings: +// +// X - any digit from 0-9 +// Z - any digit from 1-9 +// N - any digit from 2-9 +// [1235-9] - any digit in the brackets (in this example, 1,2,3,5,6,7,8,9) +// . - wildcard, matches anything remaining (e.g. _9011. matches +// anything starting with 9011 excluding 9011 itself) +// ! - wildcard, causes the matching process to complete as soon as +// it can unambiguously determine that no other matches are possible +// +// For example the extension _NXXXXXX would match normal 7 digit dialings, +// while _1NXXNXXXXXX would represent an area code plus phone number +// preceeded by a one. +// +// Each step of an extension is ordered by priority, which must +// always start with 1 to be considered a valid extension. The priority +// "next" or "n" means the previous priority plus one, regardless of whether +// the previous priority was associated with the current extension or not. +// The priority "same" or "s" means the same as the previously specified +// priority, again regardless of whether the previous entry was for the +// same extension. Priorities may be immediately followed by a plus sign +// and another integer to add that amount (most useful with 's' or 'n'). +// Priorities may then also have an alias, or label, in +// parenthesis after their name which can be used in goto situations +// +// Contexts contain several lines, one for each step of each +// extension, which can take one of two forms as listed below, +// with the first form being preferred. One may include another +// context in the current one as well, optionally with a +// date and time. Included contexts are included in the order +// they are listed. +// +//context name { +// exten-name => { +// application(arg1,arg2,...); +// +// Timing list for includes is +// +// <time range>|<days of week>|<days of month>|<months> +// +// includes { +// daytime|9:00-17:00|mon-fri|*|*; +// }; +// +// ignorepat can be used to instruct drivers to not cancel dialtone upon +// receipt of a particular pattern. The most commonly used example is +// of course '9' like this: +// +// ignorepat => 9; +// +// so that dialtone remains even after dialing a 9. +//}; + + +// +// Sample entries for extensions.conf +// +// +context dundi-e164-canonical { + // + // List canonical entries here + // + // 12564286000 => &std-exten(6000,IAX2/foo); + // _125642860XX => Dial(IAX2/otherbox/${EXTEN:7}); +}; + +context dundi-e164-customers { + // + // If you are an ITSP or Reseller, list your customers here. + // + //_12564286000 => Dial(SIP/customer1); + //_12564286001 => Dial(IAX2/customer2); +}; + +context dundi-e164-via-pstn { + // + // If you are freely delivering calls to the PSTN, list them here + // + //_1256428XXXX => Dial(Zap/g2/${EXTEN:7}); // Expose all of 256-428 + //_1256325XXXX => Dial(Zap/g2/${EXTEN:7}); // Ditto for 256-325 +}; + +context dundi-e164-local { + // + // Context to put your dundi IAX2 or SIP user in for + // full access + // + includes { + dundi-e164-canonical; + dundi-e164-customers; + dundi-e164-via-pstn; + }; +}; + +context dundi-e164-switch { + // + // Just a wrapper for the switch + // + + switches { + DUNDi/e164; + }; +}; + +context dundi-e164-lookup { + // + // Locally to lookup, try looking for a local E.164 solution + // then try DUNDi if we don't have one. + // + includes { + dundi-e164-local; + dundi-e164-switch; + }; + // +}; + +// +// DUNDi can also be implemented as a Macro instead of using +// the Local channel driver. +// +macro dundi-e164(exten) { +// +// ARG1 is the extension to Dial +// + goto ${exten}|1; +}; + +// +// Here are the entries you need to participate in the IAXTEL +// call routing system. Most IAXTEL numbers begin with 1-700, but +// there are exceptions. For more information, and to sign +// up, please go to www.gnophone.com or www.iaxtel.com +// +context iaxtel700 { + _91700XXXXXXX => Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel); +}; + +// +// The SWITCH statement permits a server to share the dialplain with +// another server. Use with care: Reciprocal switch statements are not +// allowed (e.g. both A -> B and B -> A), and the switched server needs +// to be on-line or else dialing can be severly delayed. +// +context iaxprovider { + switches { + // IAX2/user:[key]@myserver/mycontext; + }; +}; + +context trunkint { + // + // International long distance through trunk + // + includes { + dundi-e164-lookup; + }; + _9011. => { + &dundi-e164(${EXTEN:4}); + Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + }; +}; + +context trunkld { + // + // Long distance context accessed through trunk + // + includes { + dundi-e164-lookup; + }; + _91NXXNXXXXXX => { + &dundi-e164(${EXTEN:1}); + Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + }; +}; + +context trunklocal { + // + // Local seven-digit dialing accessed through trunk interface + // + _9NXXXXXX => { + Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + }; +}; + +context trunktollfree { + // + // Long distance context accessed through trunk interface + // + + _91800NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + _91888NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + _91877NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); + _91866NXXXXXX => Dial(${TRUNK}/${EXTEN:${TRUNKMSD}}); +}; + +context international { + // + // Master context for international long distance + // + ignorepat => 9; + includes { + longdistance; + trunkint; + }; +}; + +context longdistance { + // + // Master context for long distance + // + ignorepat => 9; + includes { + local; + trunkld; + }; +}; + +context local { + // + // Master context for local, toll-free, and iaxtel calls only + // + ignorepat => 9; + includes { + default; + parkedcalls; + trunklocal; + iaxtel700; + trunktollfree; + iaxprovider; + }; +}; + +// +// You can use an alternative switch type as well, to resolve +// extensions that are not known here, for example with remote +// IAX switching you transparently get access to the remote +// Asterisk PBX +// +// switch => IAX2/user:password@bigserver/local +// +// An "lswitch" is like a switch but is literal, in that +// variable substitution is not performed at load time +// but is passed to the switch directly (presumably to +// be substituted in the switch routine itself) +// +// lswitch => Loopback/12${EXTEN}@othercontext +// +// An "eswitch" is like a switch but the evaluation of +// variable substitution is performed at runtime before +// being passed to the switch routine. +// +// eswitch => IAX2/context@${CURSERVER} + macro std-exten-ael( ext , dev ) { Dial(${dev}/${ext},20); @@ -21,8 +322,8 @@ context ael-demo { s => { Wait(1); Answer(); - TIMEOUT(digit)=5; - TIMEOUT(response)=10; + Set(TIMEOUT(digit)=5); + Set(TIMEOUT(response)=10); restart: Background(demo-congrats); instructions: @@ -36,12 +337,15 @@ instructions: goto s|instructions; }; 3 => { - LANGUAGE()=fr; + Set(LANGUAGE()=fr); goto s|restart; }; + 1000 => { + goto default|s|1; + }; 500 => { Playback(demo-abouttotry); - Dial(IAX2/guest@misery.digium.com); + Dial(IAX2/guest@misery.digium.com/s@default); Playback(demo-nogo); goto s|instructions; }; @@ -52,11 +356,83 @@ instructions: goto s|instructions; }; _1234 => &std-exten-ael(${EXTEN}, "IAX2"); + 8500 => { + VoicemailMain(); + goto s|instructions; + }; # => { Playback(demo-thanks); Hangup(); }; - t => jump #; + t => goto #|1; i => Playback(invalid); }; +context default { + +// By default we include the demo. In a production system, you +// probably don't want to have the demo there. + + includes { + ael-demo; + }; +// +// Extensions like the two below can be used for FWD, Nikotel, sipgate etc. +// Note that you must have a [sipprovider] section in sip.conf whereas +// the otherprovider.net example does not require such a peer definition +// +//_41X. => Dial(SIP/${EXTEN:2}@sipprovider,,r); +//_42X. => Dial(SIP/user:passwd@${EXTEN:2}@otherprovider.net,30,rT); + +// Real extensions would go here. Generally you want real extensions to be +// 4 or 5 digits long (although there is no such requirement) and start with a +// single digit that is fairly large (like 6 or 7) so that you have plenty of +// room to overlap extensions and menu options without conflict. You can alias +// them with names, too, and use global variables + +// 6245 => { +// hint(SIP/Grandstream1&SIP/Xlite1,Joe Schmoe); // Channel hints for presence +// Dial(SIP/Grandstream1,20,rt); // permit transfer +// Dial(${HINT}/5245},20,rtT); // Use hint as listed +// switch(${DIALSTATUS}) { +// case BUSY: +// Voicemail(b6245); +// return; +// default: +// Voicemail(u6245); +// return; +// }; +// }; + +// 6361 => Dial(IAX2/JaneDoe,,rm); // ring without time limit +// 6389 => Dial(MGCP/aaln/1@192.168.0.14); +// 6394 => Dial(Local/6275/n); // this will dial ${MARK} + +// 6275 => &ael-stdexten(6275,${MARK}); // assuming ${MARK} is something like Zap/2 +// mark => goto 6275|1; // alias mark to 6275 +// 6536 => &ael-stdexten(6236,${WIL}); // Ditto for wil +// wil => goto 6236|1; +// +// Some other handy things are an extension for checking voicemail via +// voicemailmain +// +// 8500 => { +// VoicemailMain(); +// Hangup(); +// }; +// +// Or a conference room (you'll need to edit meetme.conf to enable this room) +// +// 8600 => Meetme(1234); +// +// Or playing an announcement to the called party, as soon it answers +// +// 8700 => Dial(${MARK},30,A(/path/to/my/announcemsg)) +// +// For more information on applications, just type "show applications" at your +// friendly Asterisk CLI prompt. +// +// 'show application <command>' will show details of how you +// use that particular application in this file, the dial plan. +// +}; diff --git a/doc/ael.txt b/doc/ael.txt index e2014a4e19..54d68c658b 100644 --- a/doc/ael.txt +++ b/doc/ael.txt @@ -1,273 +1,1248 @@ -The Asterisk Extension Language -=================================== +The Asterisk Extension Language - v 2 +===================================== -Over time, people have been pushing to add features to extensions.conf to make -it more like a programming language. AEL is intended to provide an actual -programming language that can be used to write an Asterisk dialplan. +AEL is a specialized language intended purely for +describing Asterisk dial plans. -Getting Started +The current version was written by Steve Murphy, and is a rewrite of +the original version. + +AEL is considered an EXPERIMENTAL Version. (yet is being +used in the field with success) + +This new version further extends AEL, and +provides more flexible syntax, better error messages, and some missing +functionality. + +AEL is really the merger of 4 different 'languages', or syntaxes: + + * The first and most obvious is the AEL 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, and is not used + directly in AEL, is the Extension Language Syntax. The + extension language is what you see in extensions.conf, and AEL + compiles the higher level AEL 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 AEL 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 AEL parser (pbx_ael.so) is completely separate from the module -that parses extensions.conf (pbx_config.so). To use AEL, the only thing that -has to be done is the module pbx_ael.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.ael' in /etc/asterisk/. -Both extensions.conf and extensions.ael 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. +that parses extensions.conf (pbx_config.so). To use AEL, the only +thing that has to be done is the module pbx_ael.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.ael' in /etc/asterisk/. extensions.conf and +extensions.ael 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.ael - +------------------------------ -Reloading extensions.ael -------------------------- -To reload extensions.ael, the following command can be issued at the CLI. +To reload extensions.ael, the following command can be issued at the +CLI: - *CLI> reload pbx_ael.so + *CLI> ael reload -Contexts + +************* +* Debugging * +************* + +Right at this moment, the following commands are available, but do +nothing: + +Enable AEL contexts debug + *CLI> ael debug contexts + +Enable AEL macros debug + *CLI> ael debug macros + +Enable AEL read debug + *CLI> ael debug read + +Enable AEL tokens debug + *CLI> ael debug tokens + +Disable AEL debug messages + *CLI> ael 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. + + +***************************** +* About "aelparse" * +***************************** + +You can also use the "aelparse" program to check your extensions.ael +file before feeding it to asterisk. Wouldn't it be nice to eliminate +most errors before giving the file to asterisk? + +aelparse is compiled in the utils directory of the asterisk release. +It isn't installed anywhere (yet). You can copy it to your favorite +spot in your PATH. + +aelparse has two optional arguments: + +-d - Override the normal location of the config file dir, (usually + /etc/asterisk), and use the current directory instead as the + config file dir. Aelparse will then expect to find the file + "./extensions.ael" in the current directory, and any included + files in the current directory as well. + +-n - don't show all the function calls to set priorities and contexts + within asterisk. It will just show the errors and warnings from + the parsing and semantic checking phases. + + +****************************** +* General Notes about Syntax * +****************************** + +Note that the syntax and style are now 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 AEL 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 + + + + + +Procedural Interface and Internals +================================== + +AEL first parses the extensions.ael 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. + + + +========================= + AEL version 2 BNF +========================= + + + +(hopefully, something close to bnf). + +First, some basic objects + +------------------------ + +<word> a lexical token consisting of characters matching this pattern: [-a-zA-Z0-9"_/.\<\>\*\+!$#\[\]][-a-zA-Z0-9"_/.!\*\+\<\>\{\}$#\[\]]* + +<word3-list> a concatenation of up to 3 <word>s. + +<collected-word> all characters encountered until the character that follows the <collected-word> in the grammar. + ------------------------- -Contexts in AEL represent a set of extensions in the same way that they do -in extensions.conf. + +<file> :== <objects> + +<objects> :== <object> + | <objects> <object> + + +<object> :== <context> + | <macro> + | <globals> + | ';' + + +<context> :== 'context' <word> '{' <elements> '}' + | 'context' <word> '{' '}' + | 'context' 'default' '{' <elements> '}' + | 'context' 'default' '{' '}' + | 'abstract' 'context' <word> '{' <elements> '}' + | 'abstract' 'context' <word> '{' '}' + | 'abstract' 'context' 'default' '{' <elements> '}' + | 'abstract' 'context' 'default' '{' '}' + + +<macro> :== 'macro' <word> '(' <arglist> ')' '{' <macro_statements> '}' + | 'macro' <word> '(' <arglist> ')' '{' '}' + | 'macro' <word> '(' ')' '{' <macro_statements> '}' + | 'macro' <word> '(' ')' '{' '}' + + +<globals> :== 'globals' '{' <global_statements> '}' + | 'globals' '{' '}' + + +<global_statements> :== <global_statement> + | <global_statements> <global_statement> + + +<global_statement> :== <word> '=' <collected-word> ';' + + +<arglist> :== <word> + | <arglist> ',' <word> + + +<elements> :== <element> + | <elements> <element> + + +<element> :== <extension> + | <includes> + | <switches> + | <eswitches> + | <ignorepat> + | <word> '=' <collected-word> ';' + | ';' + + +<ignorepat> :== 'ignorepat' '=>' <word> ';' + + +<extension> :== <word> '=>' <statement> + | 'regexten' <word> '=>' <statement> + | 'hint' '(' <word3-list> ')' <word> '=>' <statement> + | 'regexten' 'hint' '(' <word3-list> ')' <word> '=>' <statement> + + +<statements> :== <statement> + | <statements> <statement> + +<if_head> :== 'if' '(' <collected-word> ')' + +<random_head> :== 'random' '(' <collected-word> ')' + +<ifTime_head> :== 'ifTime' '(' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')' + | 'ifTime' '(' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ')' + + +<word3-list> :== <word> + | <word> <word> + | <word> <word> <word> + +<switch_head> :== 'switch' '(' <collected-word> ')' '{' + + +<statement> :== '{' <statements> '}' + | <word> '=' <collected-word> ';' + | 'goto' <target> ';' + | 'jump' <jumptarget> ';' + | <word> ':' + | 'for' '(' <collected-word> ';' <collected-word> ';' <collected-word> ')' <statement> + | 'while' '(' <collected-word> ')' <statement> + | <switch_head> '}' + | <switch_head> <case_statements> '}' + | '&' macro_call ';' + | <application_call> ';' + | <application_call> '=' <collected-word> ';' + | 'break' ';' + | 'return' ';' + | 'continue' ';' + | <random_head> <statement> + | <random_head> <statement> 'else' <statement> + | <if_head> <statement> + | <if_head> <statement> 'else' <statement> + | <ifTime_head> <statement> + | <ifTime_head> <statement> 'else' <statement> + | ';' + +<target> :== <word> + | <word> '|' <word> + | <word> '|' <word> '|' <word> + | 'default' '|' <word> '|' <word> + | <word> ',' <word> + | <word> ',' <word> ',' <word> + | 'default' ',' <word> ',' <word> + +<jumptarget> :== <word> + | <word> ',' <word> + | <word> ',' <word> '@' <word> + | <word> '@' <word> + | <word> ',' <word> '@' 'default' + | <word> '@' 'default' + +<macro_call> :== <word> '(' <eval_arglist> ')' + | <word> '(' ')' + +<application_call_head> :== <word> '(' + +<application_call> :== <application_call_head> <eval_arglist> ')' + | <application_call_head> ')' + +<eval_arglist> :== <collected-word> + | <eval_arglist> ',' <collected-word> + | /* nothing */ + | <eval_arglist> ',' /* nothing */ + +<case_statements> :== <case_statement> + | <case_statements> <case_statement> + + +<case_statement> :== 'case' <word> ':' <statements> + | 'default' ':' <statements> + | 'pattern' <word> ':' <statements> + | 'case' <word> ':' + | 'default' ':' + | 'pattern' <word> ':' + +<macro_statements> :== <macro_statement> + | <macro_statements> <macro_statement> + +<macro_statement> :== <statement> + | 'catch' <word> '{' <statements> '}' + +<switches> :== 'switches' '{' <switchlist> '}' + | 'switches' '{' '}' + +<eswitches> :== 'eswitches' '{' <switchlist> '}' + | 'eswitches' '{' '}' + +<switchlist> :== <word> ';' + | <switchlist> <word> ';' + +<includeslist> :== <includedname> ';' + | <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';' + | <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';' + | <includeslist> <includedname> ';' + | <includeslist> <includedname> '|' <word3-list> ':' <word3-list> ':' <word3-list> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';' + | <includeslist> <includedname> '|' <word> '|' <word3-list> '|' <word3-list> '|' <word3-list> ';' + +<includedname> :== <word> + | 'default' + +<includes> :== 'includes' '{' <includeslist> '}' + | 'includes' '{' '}' + + +************************** +* AEL 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. +========== + +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!); -}; + 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 AEL 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. +======== + +Contexts can be included in other contexts. All included contexts are +listed within a single block. + context default { - includes { - local; - longdistance; - international; - }; -}; + 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.ael" + + +An interesting property of the #include, is that you can use it almost +anywhere in the .ael 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. +================= + +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}; - }; -}; + 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'. +========= + +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; -}; + 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. +========= + +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; -}; + CONSOLE=Console/dsp; + TRUNK=Zap/g2; +} + + Variables can be set within extensions as well. + context foo { - 555 => { - x=5; - y=blah; - NoOp(x is ${x} and y is ${y} !); - }; -}; + 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 - 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)} !); - }; -}; + 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; - }; - }; -}; + 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 -------------------------- -AEL supports if and switch statements. Note that if you have an else -clause, you MUST place braces around the non-else portion of the if -statement. +============ + +AEL 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") { - Voicemail(${EXTEN}|b); - } else - Voicemail(${EXTEN}|u); - }; - _777X => { - switch (${EXTEN}) { - case 7771: - NoOp(You called 7771!); - break; - case 7772: - NoOp(You called 7772!); - break; - case 7773: - NoOp(You called 7773!); - // fall through - default: - NoOp(In the default clause!); - }; - }; -}; - - -goto and labels -------------------------- + _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: AEL 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: AEL 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 => { + s => { begin: - NoOp(Infinite Loop! yay!); - Wait(1); - goto 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 AEL introduces the special label "1", which is the beginning + context number for most extensions. + +NOTE: A NEW addition to AEL: 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 reffered to by that same -name. A catch block can be specified to catch special extensions. +====== + +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. + 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"); -}; + _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; + s => { + Wait(1); + Answer(); + TIMEOUT(digit)=5; + TIMEOUT(response)=10; restart: - Background(demo-congrats); + 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; - }; - # => { + 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); -}; + Playback(demo-thanks); + Hangup(); + } + t => goto #|hangup; + i => Playback(invalid); +} -Syntax Note ------------------------- -Please note that all opening {'s are on the same line as the keyword. For -the time being, that syntax is mandatory. We are looking at ways to allow -other syntax in the future for flexibility, but for now, that is the way -you must write AEL clauses. +Semantic Checks +=============== + + +AEL, after parsing, but before compiling, traverses the dialplan +tree, and makes several checks: + + * Macro calls to non-existent macros. + * Macro calls to contexts. + * Macro calls with argument count not matching the definition. + * application call to macro. (missing the '&') + * 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. + * 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. + * (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. + +There are a subset of checks that have been removed until the proposed +AAL (Asterisk Argument Language) is developed and incorporated into Asterisk. +These checks will be: + + * (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... + * Calls to applications not in the "applist" database (installed + in /var/lib/asterisk/applist" on most systems). + * 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. + + + +Differences with the original version of AEL +============================================ + + 1. The $[...] expressions have been enhanced to inlcude the ==, ||, + and && operators. These operators are exactly equivalent to the + =, |, and & operators, respectively. Why? So the C, Java, C++ + hackers feel at home here. + 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 -- 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. -- 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_ael.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.ael 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. AEL 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 (<time range>|<days of week>|<days of + month>|<months> ) {} [else {}] construct, which executes much + like an if () statement, but the decision is based on the + current time, and the time spec provided in the ifTime. See the + example above. (Note: all the other time-dependent Applications + can be used via ifTime) + 13. Added the optional time spec to the contexts in the includes + construct. See examples above. + 14. You don't have to wrap a single "true" statement in curly + braces, as in the orignal AEL. An "else" is attached to the + closest if. As usual, be careful about nested if statements! + When in doubt, use curlies! + 15. Added the syntax [regexten] [hint(channel)] to preceed an + extension declaration. See examples above, under + "Extension". The regexten keyword will cause the priorities in + the extension to begin with 2 instead of 1. The hint keyword + will cause its arguments to be inserted in the extension under + the hint priority. They are both optional, of course, but the + order is fixed at the moment-- the regexten must come before the + hint, if they are both present. + 16. Empty case/default/pattern statements will "fall thru" as + expected. (0.6) + 17. A trailing label in an extension, will automatically have a + NoOp() added, to make sure the label exists in the extension on + Asterisk. (0.6) + 18. (0.9) the semicolon is no longer required after a closing brace! + (i.e. "];" ===> "}". You can have them there if you like, but + they are not necessary. Someday they may be rejected as a syntax + error, maybe. + 19. (0.9) the // comments are not recognized and removed in the + spots where expressions are gathered, nor in application call + arguments. You may have to move a comment if you get errors in + existing files. + 20. (0.10) the random statement has been added. Syntax: random ( + <expr> ) <lucky-statement> [ else <unlucky-statement> ]. The + probability of the lucky-statement getting executed is <expr>, + which should evaluate to an integer between 0 and 100. If the + <lucky-statement> isn't so lucky this time around, then the + <unlucky-statement> gets executed, if it is present. + + + +Hints and Bugs +============== + + * The safest way to check for a null strings is to say $[ "${x}" = + "" ] The old way would do as shell scripts often do, and append + something on both sides, like this: $[ ${x}foo = foo ]. The + trouble with the old way, is that, if x contains any spaces, then + problems occur, usually syntax errors. It is better practice and + safer wrap all such tests with double quotes! Also, there are now + some functions that can be used in a variable referenece, + ISNULL(), and LEN(), that can be used to test for an empty string: + ${ISNULL(${x})} or $[ ${LEN(${x}) = 0 ]. + + * Assignment vs. Set(). Keep in mind that setting a variable to + value can be done two different ways. If you choose say 'x=y;', + keep in mind that AEL will wrap the right-hand-side with + $[]. So, when compiled into extension language format, the end + result will be 'Set(x=$[y])'. If you don't want this effect, + then say "Set(x=y);" instead. + + +The Full Power of AEL +============================== + +A newcomer to Asterisk will look at the above constructs and +descriptions, and ask, "Where's the string manipulation functions?", +"Where's all the cool operators that other languages have to offer?", +etc. + +The answer is that the rich capabilities of Asterisk are made +available through AEL, via: + + * Applications: See Asterisk - documentation of application + commands + + * Functions: Functions were implemented inside ${ .. } variable + references, and supply many useful capabilities. + + * Expressions: An expression evaluation engine handles items + wrapped inside $[...]. This includes some string manipulation + facilities, arithmetic expressions, etc. + + * Application Gateway Interface: Asterisk can fork external + processes that communicate via pipe. AGI applications can be + written in any language. Very powerful applications can be added + this way. + + * Variables: Channels of communication have variables associated + with them, and asterisk provides some global variables. These can be + manipulated and/or consulted by the above mechanisms. diff --git a/include/asterisk/ael_structs.h b/include/asterisk/ael_structs.h new file mode 100644 index 0000000000..ea10df9b28 --- /dev/null +++ b/include/asterisk/ael_structs.h @@ -0,0 +1,178 @@ +#if !defined(SOLARIS) && !defined(__CYGWIN__) +#include <err.h> +#else +#define quad_t int64_t +#endif + +#ifdef LONG_LONG_MIN +#define QUAD_MIN LONG_LONG_MIN +#endif +#ifdef LONG_LONG_MAX +#define QUAD_MAX LONG_LONG_MAX +#endif + +# if ! defined(QUAD_MIN) +# define QUAD_MIN (-0x7fffffffffffffffLL-1) +# endif +# if ! defined(QUAD_MAX) +# define QUAD_MAX (0x7fffffffffffffffLL) +# endif + + +typedef enum +{ + PV_WORD, /* an ident, string, name, label, etc. A user-supplied string. */ + PV_MACRO, + PV_CONTEXT, + PV_MACRO_CALL, + PV_APPLICATION_CALL, + PV_CASE, + PV_PATTERN, + PV_DEFAULT, + PV_CATCH, + PV_SWITCHES, + PV_ESWITCHES, + PV_INCLUDES, + PV_STATEMENTBLOCK, + PV_VARDEC, /* you know, var=val; */ + PV_GOTO, + PV_LABEL, + PV_FOR, + PV_WHILE, + PV_BREAK, + PV_RETURN, + PV_CONTINUE, + PV_IF, + PV_IFTIME, + PV_RANDOM, + PV_SWITCH, + PV_EXTENSION, + PV_IGNOREPAT, + PV_GLOBALS, + +} pvaltype; + +/* why this horrible mess? It's always been a tradeoff-- tons of structs, + each storing it's specific lists of goodies, or a 'simple' single struct, + with lots of fields, that catches all uses at once. Either you have a long + list of struct names and subnames, or you have a long list of field names, + and where/how they are used. I'm going with a single struct, using unions + to reduce storage. Some simple generalizations, and a long list of types, + and a book about what is used with what types.... Sorry! +*/ + +struct pval +{ + pvaltype type; + int startline; + int endline; + int startcol; + int endcol; + char *filename; + + union + { + char *str; /* wow, used almost everywhere! */ + struct pval *list; /* used in SWITCHES, ESWITCHES, INCLUDES, STATEMENTBLOCK, GOTO */ + struct pval *statements;/* used in EXTENSION */ + char *for_init; /* used in FOR */ + } u1; + struct pval *u1_last; /* to build in-order lists -- looks like we only need one */ + + union + { + struct pval *arglist; /* used in macro_call, application_call, MACRO def, also attached to PWORD, the 4 timevals for includes */ + struct pval *statements; /* used in case, default, catch, while's statement, CONTEXT elements, GLOBALS */ + char *val; /* used in VARDEC */ + char *for_test; /* used in FOR */ + + } u2; + + union + { + char *for_inc; /* used in FOR */ + struct pval *else_statements; /* used in IF */ + struct pval *macro_statements; /* used in MACRO */ + int abstract; /* used for context */ + char *hints; /* used in EXTENSION */ + } u3; + + union + { + struct pval *for_statements; /* used in PV_FOR */ + int regexten; /* used in EXTENSION */ + } u4; + + + struct pval *next; /* the pval at the end of this ptr will ALWAYS be of the same type as this one! + EXCEPT for objects of the different types, that are in the same list, like contexts & macros, etc */ + + +} ; + + +typedef struct pval pval; + +pval *npval(pvaltype type, int first_line, int last_line, int first_column, int last_column); +void linku1(pval *head, pval *tail); +void print_pval_list(FILE *f, pval *item, int depth); +void print_pval(FILE *f, pval *item, int depth); +void ael2_semantic_check(pval *item, int *errs, int *warns, int *notes); +struct pval *find_label_in_current_context(char *exten, char *label); +struct pval *find_label_in_current_extension(char *label); +int count_labels_in_current_context(char *label); +struct pval *find_label_in_current_db(char *context, char *exten, char *label); +struct pval *ael2_parse(char *fname, int *errs); +void destroy_pval(pval *item); +void ael2_print(char *fname, pval *tree); +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* for passing info into and out of yyparse */ +struct parse_io +{ + struct pval *pval; /* yyparse will set this to point to the parse tree */ + yyscan_t scanner; /* yylex needs a scanner. Set it up, and pass it in */ + int syntax_error_count; /* the count of syntax errors encountered */ +}; + +/* for CODE GENERATION */ + +typedef enum { AEL_APPCALL, AEL_CONTROL1, AEL_FOR_CONTROL, AEL_IF_CONTROL, AEL_IFTIME_CONTROL, AEL_RAND_CONTROL, AEL_LABEL, AEL_RETURN } ael_priority_type; + + +struct ael_priority +{ + int priority_num; + ael_priority_type type; + + char *app; + char *appargs; + + struct pval *origin; + struct ael_extension *exten; + + struct ael_priority *goto_true; + struct ael_priority *goto_false; + struct ael_priority *next; +}; + +struct ael_extension +{ + char *name; + char *hints; + int regexten; + + struct ael_priority *plist; + struct ael_priority *plist_last; + struct ael_extension *next_exten; + + struct ael_priority *loop_break; /* set by latest loop for breaks */ + struct ael_priority *loop_continue; /* set by lastest loop for continuing */ + struct ael_priority *return_target; + int return_needed; +}; + + diff --git a/mxml/configure b/mxml/configure index bd4aaedc67..3a725707fd 100755 --- a/mxml/configure +++ b/mxml/configure @@ -1,9 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.57. +# Generated by GNU Autoconf 2.59. # -# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -# Free Software Foundation, Inc. +# Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## @@ -20,9 +19,10 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi +DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false @@ -41,7 +41,7 @@ for as_var in \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var @@ -218,16 +218,17 @@ rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else + test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS @@ -630,7 +631,7 @@ done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir + localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in @@ -670,10 +671,10 @@ if test -z "$srcdir"; then # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -769,9 +770,9 @@ _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] + [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] + [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify @@ -862,12 +863,45 @@ case $srcdir in ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. @@ -878,13 +912,13 @@ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then + test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd $ac_popdir + cd "$ac_popdir" done fi @@ -892,8 +926,7 @@ test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -Free Software Foundation, Inc. +Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -905,7 +938,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.57. Invocation command line was +generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -982,19 +1015,19 @@ do 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. + ac_must_keep_next=false # Got value, back to normal. else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. @@ -1028,12 +1061,12 @@ _ASBOX case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } @@ -1062,7 +1095,7 @@ _ASBOX for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi @@ -1081,7 +1114,7 @@ _ASBOX echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 - rm -f core core.* *.core && + rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 @@ -1161,7 +1194,7 @@ fi # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" @@ -1178,13 +1211,13 @@ echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: + ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. @@ -1631,7 +1664,6 @@ ac_compiler=`set X $ac_compile; echo $2` (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -1651,8 +1683,8 @@ ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -echo "$as_me:$LINENO: checking for C compiler default output" >&5 -echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 @@ -1672,23 +1704,23 @@ do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; + ;; conftest.$ac_ext ) - # This is the source file. - ;; + # This is the source file. + ;; [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; + # We found the default executable, but exeext='' is most + # certainly right. + break;; *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; * ) - break;; + break;; esac done else @@ -1762,8 +1794,8 @@ for ac_file in conftest.exe conftest conftest.*; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; + export ac_cv_exeext + break;; * ) break;; esac done @@ -1788,7 +1820,6 @@ if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -1839,7 +1870,6 @@ if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -1859,11 +1889,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -1876,7 +1915,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi @@ -1892,7 +1931,6 @@ if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -1909,11 +1947,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -1926,7 +1973,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 @@ -1953,7 +2000,6 @@ else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -1981,6 +2027,16 @@ static char *f (char * (*g) (char **, int), char **p, ...) va_end (v); return s; } + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; @@ -2007,11 +2063,20 @@ do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2024,7 +2089,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext +rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC @@ -2052,19 +2117,27 @@ cat >conftest.$ac_ext <<_ACEOF _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ - ''\ - '#include <stdlib.h>' \ + '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ @@ -2072,14 +2145,13 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <stdlib.h> $ac_declaration +#include <stdlib.h> int main () { @@ -2090,11 +2162,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2107,9 +2188,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 continue fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2126,11 +2206,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2142,7 +2231,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then @@ -2156,7 +2245,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2282,7 +2371,6 @@ if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2302,11 +2390,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2319,7 +2416,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi @@ -2335,7 +2432,6 @@ if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2352,11 +2448,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2369,7 +2474,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 @@ -2389,8 +2494,7 @@ else fi fi for ac_declaration in \ - ''\ - '#include <stdlib.h>' \ + '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ @@ -2398,14 +2502,13 @@ for ac_declaration in \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include <stdlib.h> $ac_declaration +#include <stdlib.h> int main () { @@ -2416,11 +2519,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2433,9 +2545,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 continue fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2452,11 +2563,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 + (eval $ac_compile) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2468,7 +2588,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then @@ -2519,6 +2639,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 @@ -2535,6 +2656,7 @@ do case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -2542,20 +2664,20 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi done done ;; @@ -2973,21 +3095,28 @@ if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ + #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif + +#undef $ac_func + /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" @@ -3018,11 +3147,20 @@ return f != $ac_func; _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3035,7 +3173,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 @@ -3060,21 +3199,28 @@ if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ + #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif + +#undef $ac_func + /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" @@ -3105,11 +3251,20 @@ return f != $ac_func; _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 2>conftest.er1 ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && - { ac_try='test -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3122,7 +3277,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 @@ -3346,13 +3502,13 @@ _ACEOF # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | @@ -3382,13 +3538,13 @@ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ + ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; +s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; -s/^[^=]*=[ ]*$//; +s/^[^=]*=[ ]*$//; }' fi @@ -3399,7 +3555,7 @@ ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' @@ -3443,9 +3599,10 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi +DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false @@ -3464,7 +3621,7 @@ for as_var in \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var @@ -3643,16 +3800,17 @@ rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else + test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS @@ -3679,7 +3837,7 @@ _ASBOX cat >&5 <<_CSEOF This file was extended by $as_me, which was -generated by GNU Autoconf 2.57. Invocation command line was +generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -3723,9 +3881,9 @@ Usage: $0 [OPTIONS] [FILE]... -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] - instantiate the configuration file FILE + instantiate the configuration file FILE --header=FILE[:TEMPLATE] - instantiate the configuration header FILE + instantiate the configuration header FILE Configuration files: $config_files @@ -3739,11 +3897,10 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.57, +configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir @@ -3997,9 +4154,9 @@ _ACEOF (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end @@ -4017,21 +4174,21 @@ for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -4047,10 +4204,10 @@ echo X"$ac_file" | as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -4088,12 +4245,45 @@ case $srcdir in ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac case $INSTALL in @@ -4101,11 +4291,6 @@ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -4115,7 +4300,7 @@ echo "$as_me: creating $ac_file" >&6;} configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." + sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. @@ -4124,26 +4309,32 @@ echo "$as_me: creating $ac_file" >&6;} case $f in -) echo $tmp/stdin ;; [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - echo $f;; + echo "$f";; *) # Relative - if test -f "$f"; then - # Build tree - echo $f - elif test -f "$srcdir/$f"; then - # Source tree - echo $srcdir/$f - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - fi;; + fi;; esac done` || { (exit 1); exit 1; } + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub @@ -4183,12 +4374,12 @@ cat >>$CONFIG_STATUS <<\_ACEOF # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' @@ -4197,11 +4388,11 @@ for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac @@ -4215,28 +4406,29 @@ echo "$as_me: creating $ac_file" >&6;} case $f in -) echo $tmp/stdin ;; [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - echo $f;; + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; *) # Relative - if test -f "$f"; then - # Build tree - echo $f - elif test -f "$srcdir/$f"; then - # Source tree - echo $srcdir/$f - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - fi;; + fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF @@ -4259,9 +4451,9 @@ s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times @@ -4275,13 +4467,13 @@ rm -f confdef2sed.sed # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail @@ -4290,7 +4482,7 @@ do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS @@ -4317,7 +4509,7 @@ do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS @@ -4351,10 +4543,10 @@ echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -4370,10 +4562,10 @@ echo X"$ac_file" | as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } diff --git a/pbx/Makefile b/pbx/Makefile index 60b965c292..99846a23da 100644 --- a/pbx/Makefile +++ b/pbx/Makefile @@ -48,6 +48,23 @@ pbx_dundi.so: pbx_dundi.o dundi-parser.o pbx_dundi.o: pbx_dundi.c $(CC) -c -o $@ $(CFLAGS) $(Z_INCLUDE) $< +pbx_ael.o: ael/aelflex.o ael/aelbison.o ../include/asterisk/ael_structs.h + +pbx_ael.so: pbx_ael.o ael/aelbison.o ael/aelflex.o + $(CC) $(SOLINK) -o $@ pbx_ael.o ael/aelbison.o ael/aelflex.o + +ael/aelflex.o: ael/ael_lex.c ../include/asterisk/ael_structs.h ael/ael.tab.h + $(CC) $(CFLAGS) -c -o ael/aelflex.o ael/ael_lex.c + +ael/aelbison.o: ael/ael.tab.c ael/ael.tab.h ../include/asterisk/ael_structs.h + $(CC) $(CFLAGS) -c -o ael/aelbison.o ael/ael.tab.c + +ael/ael_lex.c: ael/ael.flex + (cd ael; flex ael.flex) + +ael/ael.tab.c ael/ael.tab.h: ael/ael.y + (cd ael; bison -v -d ael.y) + %.moc : %.h $(MOC) $< -o $@ diff --git a/pbx/ael/ael-test/ael-test1/extensions.ael b/pbx/ael/ael-test/ael-test1/extensions.ael new file mode 100644 index 0000000000..d25ddd3235 --- /dev/null +++ b/pbx/ael/ael-test/ael-test1/extensions.ael @@ -0,0 +1,163 @@ + +macro testdial(number, timeout) { + Dial(IAX2/vpconnect-t02/${number},${timeout},${OG_DIAL_FLAGS}); + switch (${DIALSTATUS}) { + case CHANUNAVAIL: + goto dial-trunk2; + break; + default: + NoOp(t02 Unavailable - ${DIALSTATUS}); + return; + } + +dial-trunk2: + Dial(IAX2/vpconnect-t01/${number},${timeout},${OG_DIAL_FLAGS}); + +} + +macro exten-gen(name,pword) +{ + if( ${DB_EXISTS(org/${GroupID}/${name}/secret)} = 0 ) + goto other|nomatch|begin; + if( ${DB(org/${GroupID}/${name}/secret)}foo != ${pword}foo ) + goto other|nomatch|begin; + +}; + +context what { + who => + { + 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! ); + } + } + } +} + +context other { + nomatch => { + begin: + NoOp(Hello!); + switch(${DIALSTATUS}) + { + case BUSY: + NoOp(wow); + case TORTURE: + NoOp(woow); + }; + NoOp(woohoo); + }; +}; + +context testloop { + includes { + other|16:00-23:59|m0n-fri|*|*; + }; + + 1 => { + for (x=0; ${x} < 3; x=${x} + 1) { + Verbose(x is ${x} !); + if( ${x} = 1 ) + continue; + if( ${x} = 2 ) + break; + }; + ifTime(14:00-25:00|sat-sun|*|*) { + BackGround(Hello); + } else + BackGround(Sorry); + NoOp(This is a totally useless NOOP); + }; + 2 => { + y=10; + while (${y} >= 0) { + Verbose(y is ${y} !); + if( ${y} = 1 ) + continue; + if( ${y} = 2 ) + break; + if( ${y} = 3 ) + return; + y=${y}-1; + }; + }; + regexten hint(nasty/Thingy) 3 => { + for (x=0; ${x} < 3; x=${x} + 1) + { + Verbose(x is ${x} !); + if( ${x} = 4 ) + break; + if( ${x} = 5 ) + continue; + if( ${x} = 6 ) + return; + + y=10; + while (${y} >= 0) + { + Verbose(y is ${y} !); + if( ${y} = 4 ) + break; + if( ${y} = 5 ) + continue; + if( ${y} = 6 ) + return; + y=${y}-1; + }; + }; + }; + 4 => { + y=10; + while (${y} >= 0) + { + Verbose(y is ${y} !); + if( ${y} = 4 ) + break; + if( ${y} = 5 ) + continue; + if( ${y} = 6 ) + return; + for (x=0; ${x} < 3; x=${x} + 1) + { + Verbose(x is ${x} !); + if( ${x} = 4 ) + break; + if( ${x} = 5 ) + continue; + if( ${x} = 6 ) + return; + for (z=0; ${z} < 17; z=${z} + 1) + { + Verbose(z is ${z} !); + Verbose(z is ${z} !); + if( ${z} = 4 ) + break; + if( ${z} = 5 ) + continue; + if( ${z} = 6 ) + return; + Verbose(z is ${z} !); + Verbose(z is ${z} !); + }; + + }; + y=${y}-1; + }; + }; + 5 => { + &exten-gen(axel,brain); + }; +}; diff --git a/pbx/ael/ael-test/ael-test2/apptest.ael2 b/pbx/ael/ael-test/ael-test2/apptest.ael2 new file mode 100644 index 0000000000..c477d8531b --- /dev/null +++ b/pbx/ael/ael-test/ael-test2/apptest.ael2 @@ -0,0 +1,146 @@ +// this is a quick test to see how many of the apps we can spot j options in +// include this in a macro or extension +// at this moment, there are 18 apps that accept the j option. + + AddQueueMember(zork,iface,20,j); + ADSIProg(sfile); + AgentCallbackLogin(agent,s,30@cont); + AgentLogin(agent,s); + AgentMonitorOutgoing(dcn); + AGI(whatever); + AlarmReceiver(); + Answer(2); + AppendCDRUserField(value); + Authenticate(pword,adjmr); + BackGround(filename,snm,eng); + BackgroundDetect(filename,20,2,10); + Busy(10); + ChangeMonitor(fnamebase); + ChanIsAvail(Zap/5,sj); + ChanSpy(prefix,bg()qrv); + Congestion(5); + ControlPlayback(filename,10,6,4,0,5,7,j); + DateTime(unixtime,tz,fmt); + DBdel(fam/key); + DBdeltree(fam); + DeadAGI(command); + Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW); + Dictate(basedir); + Directory(cont,dcont,f); + DISA(68986869876,context); + DumpChan(verblev); + DUNDiLookup(90709780978,context,bj); + EAGI(command); + Echo(); + EndWhile(); + Exec(appname,args); + ExecIf(expr,app,data); + ExecIfTime(*,*,*,*,appname); + ExternalIVR(command,arg1); + Festival(text); + Flash(); + ForkCDR(v); + GetCPEID(); + Gosub(cont,exten,priority); + GosubIf(cond?label); + Goto(cont,exten,prior); + GotoIf(cond?t:f); + GotoIfTime(*,*,*,*?cont,ext,prior); + Hangup(); + HasNewVoicemail(vmbox,var,j); + HasVoicemail(vmbox,var,j); + IAX2Provision(template); + ICES(xmlconfig); + ImportVar(nevar@chann,var); + Log(NOTICE,message); + LookupBlacklist(j); + LookupCIDName(); + Macro(macro,arg1); + MacroExit(); + MacroIf(expr?etc); + MailboxExists(mbox@cont,j); + Math(v,2+2); + MeetMe(5555,aAbcdDeimMpPqrstTovwxX); + MeetMeAdmin(5555,e,user); + MeetMeCount(5555,var); + Milliwatt(); + MixMonitor(filename,abv()V()W(),command); + Monitor(file.fmt,base,mb); + MP3Player(location); + MusicOnHold(class); + NBScat(); + NoCDR(); + NoOp(ignored); + Page(Zap/1,dq); + Park(exten); + ParkAndAnnounce(template,5,238,retcont); + ParkedCall(exten); + PauseQueueMember(queue,zap,j); + Pickup(ext@cont); + Playback(file,j); + PlayTones(arg); + PrivacyManager(3,4,j); + Progress(); + Queue(queuename,dhHnrtTwW,http://www.where.what,over,5); + Random(30,cont,ext,pri); + Read(var,fname,10,skip,2,5); + ReadFile(var=file,10); + RealTime(fam,2,val,prefix); + RealTimeUpdate(fam,2,val,2,newval); + Record(file,2,10,anqst); + RemoveQueueMember(queuename,iface,j); + ResetCDR(wav); + RetryDial(annound,4,2); + Return(); + Ringing(); + RxFAX(fname,caller); + SayAlpha(string); + SayDigits(string); + SayNumber(digits); + SayPhonetic(string); + SayUnixTime(unixtime,tz,fmt); + SendDTMF(digits,10); + SendImage(filename); + SendText(text,j); + SendURL(URL); + Set(a=b); + SetAMAFlags(); + SetCallerID(clid,a); + SetCallerPres(allowed_passed_screen); + SetCDRUserField(value); + SetGlobalVar(var=val); + SetMusicOnHold(class); + SetTransferCapability(SPEECH); + SIPAddHeader(header); + SIPDtmfMode(inband,info,rfc); + SIPGetHeader(var@headername); + SMS(name); + SoftHangup(zap/1,a); + StackPop(); + StartMusicOnHold(class); + StopMonitor(); + StopMusicOnHold(); + StopPlayTones(); + System(command); + TestClient(testid); + TestServer(); + Transfer(zap/1,j); + TrySystem(command); + TxFAX(filename,caller,debug); + UnpauseQueueMember(queuename,iface,j); + UserEvent(eventanme,body); + Verbose(5,message); + VMAuthenticate(mailbox@cont,s); + VoiceMail(mailbox@cont,bg()suj); + VoiceMailMain(mailbox@cont,pg()s); + Wait(2); + WaitExten(3,m()); + WaitForRing(2); + WaitForSilence(2,y); + WaitMusicOnHold(2); + While(expr); + Zapateller(answer,5); + ZapBarge(channel); + ZapRAS(arg); + ZapScan(group); + ZapSendKeypadFacility(); diff --git a/pbx/ael/ael-test/ael-test2/extensions.ael b/pbx/ael/ael-test/ael-test2/extensions.ael new file mode 100644 index 0000000000..1763388727 --- /dev/null +++ b/pbx/ael/ael-test/ael-test2/extensions.ael @@ -0,0 +1,8 @@ +context test1 +{ + s => + { + #include "apptest.ael2"; + } +} + diff --git a/pbx/ael/ael-test/ael-test3/extensions.ael b/pbx/ael/ael-test/ael-test3/extensions.ael new file mode 100755 index 0000000000..ae3b4bedfb --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/extensions.ael @@ -0,0 +1,3183 @@ +globals +{ + static=yes; + writeprotect=yes; + CONSOLE=Console/dsp; // Console interface for demo + IAXINFO=murf:tlhfckoct; // IAXtel username/password + FWDNUMBER=544788 ; // your calling number + FWDCIDNAME="Joe-Worker"; // your caller id + FWDPASSWORD=zingledoodle ; // your password + FWDRINGS=Zap/6 ; // the phone to ring + FWDVMBOX=1 ; // the VM box for this user +} + +macro std-exten( ext , dev ) +{ + Dial(${dev}/${ext},20); + switch(${DIALSTATUS}) + { + case BUSY: + Voicemail(b${ext}); + break; + case NOANSWER: + Voicemail(u${ext}); + break; + case ANSWER: + break; + default: + Voicemail(u${ext}); + } + catch a { + VoiceMailMain(${ext}); + } +} + +macro std-priv-exten_1( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_2( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_3( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_4( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_5( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_6( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_7( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_8( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_9( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_10( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_11( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_12( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_13( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_14( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_15( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_16( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_17( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_18( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_19( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_20( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_21( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_22( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_23( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_24( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_25( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_26( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_27( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_28( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_29( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_30( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_31( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_32( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_33( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_34( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_35( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_36( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_37( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_38( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_39( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_40( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_41( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_42( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_43( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_44( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_45( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_46( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_47( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_48( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_49( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_50( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_51( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_52( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_53( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_54( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_55( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_56( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_57( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_58( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_59( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_60( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_61( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_62( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_63( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_64( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_65( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_66( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_67( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_68( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_69( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_70( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_71( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_72( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten_73( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + + +macro std-priv-exten( dev, ext , timeout, opts, torcont, dontcont ) +{ + Dial(${dev},${timeout},${opts}); + NoOp(${DIALSTATUS} was chosen); + switch(${DIALSTATUS}) + { + case TORTURE: + goto ${torcont}|s|begin; + break; + case DONTCALL: + goto ${dontcont}|s|begin; + break; + case BUSY: + Voicemail(b${ext}); + break; + case ANSWER: + break; + case NOANSWER: + Voicemail(u${ext}); + break; + default: + Voicemail(u${ext}); + } +} + +macro fillcidname() +{ + if( "${CALLERID(number)}" = "" ) // nothing to work with, quit!!! + return; + Set(cidn=${DB(cidname/${CALLERID(num)})}); + if( "${CALLERID(name)}" != "" ) + { + if( ("${cidn}" = "Privacy Manager" & "${CALLERID(name)}" != "Privacy Manager") | "${cidn}" = "" ) // if the entry isn't in the database, + // or if an entry exists, and it's "Privacy Manager", empty, (or add other useless possibilities). + { + Set(DB(cidname/${CALLERID(number)})=${CALLERID(name)}); // then set or override what's in the DB + } + } + // Now, we fill in the callerid info from the incoming entry, if it's stuff worth using + // Ignore fundamentally semi-anonymous information from local cell phones + // if the db has an entry for this number, and it's not a canned string from a cell phone company + if( ( "${cidn}" != "" ) & ( "${CALLERID(name)}" = "" + | "${CALLERID(name)}" = "CODY,WY " + | "${CALLERID(name)}" = "POWELL,WY " + | "${CALLERID(name)}" = "WIRELESS CALLER" + | "${CALLERID(name)}" = "SUBSCRIBER,WIRE" + | "${CALLERID(name)}" = "CELLULAR ONE" + | "${CALLERID(name)}" = "Cellular One Customer" + | "${CALLERID(name)}" = "CELLULAR ONE " + | "${CALLERID(name)}" = "Privacy Manager" + | "${CALLERID(name)}" = "RIVERTON,WY " + | "${CALLERID(name)}" = "BASIN,WY " + | "${CALLERID(name)}" = "BILLINGS,MT " + | "${CALLERID(name)}" = "PROVO,UT " + | "${CALLERID(name)}" = "TOLL FREE " ) ) // put stuff in the above, that the phone company tends to put in your callerid, + // that you would rather override with DB info + // there's no way to guess them all, but you can get the most popular ones... + // why cell phones can't do CID like everybody else, ....? + { + Set(CALLERID(name)=${cidn}); // Override what the phone company provides with what's in the DB for this number. + } +} + +macro ciddial(dialnum, lookup, waittime, dialopts, ddev) +{ + Set(cidnu=${CALLERID(num)}); + Set(cidn=${DB(cidname/${lookup})}); + Set(CALLERID(name)=${cidn}); + Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); + if( "${DIALSTATUS}" = "CHANUNAVAIL" ) + { + BackGround(try_voip); + CALLERID(num)=7075679201; + Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); + if( "${DIALSTATUS}" = "CHANUNAVAIL" ) + { + BackGround(try_cell); + CALLERID(num)=${cidnu}; // put the original number back + Dial(Zap/2/${lookup},${waittime},${dialopts}); + } + } +} + +macro ciddial3(dialnum, lookup, waittime, dialopts, ddev) +{ + Set(cidnu=${CALLERID(num)}); + Set(cidn=${DB(cidname/${lookup})}); + Set(CALLERID(name)=${cidn}); + Dial(${ddev}/${dialnum}|${waittime}|${dialopts}); + if( "${DIALSTATUS}" = "CHANUNAVAIL" ) + { + BackGround(try_cell); + Dial(Zap/2/${lookup},${waittime},${dialopts}); + } +} + +macro ciddial2(dialnum, lookup, waittime, dialopts, ddev) // give priority to tctwest, then the ZAP in emergencies +{ + Set(cidn=${DB(cidname/${lookup})}); + Set(cidnu=${CALLERID(num)}); + Set(CALLERID(name)=${cidn}); + Set(CALLERID(num)=7075679201); + Dial(SIP/1${lookup}@tctwest,${waittime},${dialopts}); + if( "${DIALSTATUS}" = "CHANUNAVAIL" ) + { + Set(CALLERID(num)=${cidnu}); // put the original number back + BackGround(try_zap); + Dial(${ddev}/${dialnum},${waittime}|${dialopts}); + if( "${DIALSTATUS}" = "CHANUNAVAIL" ) + { + BackGround(try_cell); + Dial(Zap/2/${lookup},${waittime},${dialopts}); + } + } +} + +macro callerid-liar() +{ + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/priv-callerintros/LIAR.gsm&); + Background(priv-liar); // Script: OOOps! Sorry! I don't allow men with ski masks pulled over their + // faces to get in the front door, and unidentified callers won't fair + // any better. You entered *MY* phone number. That won't work. + // If you are telemarketing, cross me off the list, and don't call again. + // If you did this by mistake, forgive my defenses, and call again. + // Alternate: (priv-liar2) + // Script: You have chosen to try to deceive my system and withold your CallerID, + // by entering my own phone number as YOUR CallerID. I find this + // offensive because you are being dishonest. I will not do business nor + // waste my time talking to anyone who is less than honest and forthcoming. + // Take me off your call list and do not call me again. + Hangup(); +} + +macro callerid-bad() +{ + mycid=${CALLERID(num)}:"1([0-9]+)"; + Set(CALLERID(num)=${mycid}); + Wait(0); +} + +context privacyManagerFailed { + s => { + begin: + Background(PrivManInstructions); // Script: OOps, that didn't go well. You need to enter *your* area code, and *your* 7 digit + // phone number, for a total of 10 digits, or you'll be handed over to the monkeys. Let's + // try this again, and hopefully you can get past our front-line defenses! + PrivacyManager(); + if( "${PRIVACYMGRSTATUS}" = "FAILED" ) + { + Background(tt-allbusy); + Background(tt-somethingwrong); + Background(tt-monkeysintro); + Background(tt-monkeys); + Background(tt-weasels); + Hangup(); + } + else + { + goto homeline|s|postPriv; + } + } +} + +// Some comments +// Some more comments + +context homeline { + s => { + begin: + Answer(); + Set(repeatcount=0); + Zapateller(nocallerid); + PrivacyManager(); + if( "${PRIVACYMGRSTATUS}" = "FAILED" ) + { + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/privmanfailed.gsm); + &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); + Hangup(); + return; +// goto privacyManagerFailed|s|begin; + } + postPriv: + &fillcidname(); + Set(CONFCIDNA=${CALLERID(name)}); + Set(CONFCIDNU=${CALLERID(num)}); + AGI(callall); + AGI(submit-announce.agi); + if( "${CALLERID(num)}" : "1" ) + { + &callerid-bad(); + } + if( "${CALLERID(num)}" = "7077577685" & "${CALLERID(name)}" : "Privacy Manager" ) + { + &callerid-liar(); + } + TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); + Set(lds=${DB(playlds/${CALLERID(num)})}); + if( "${lds}" = "1" ) + { + SetMusicOnHold(mohlds); + } + direct=${DB(DirectCall/${CALLERID(num)})}; + if( "${direct}" != "" & ${direct} != 0 ) + { + verbose(direct is XXX#${direct}XXXX); + Playback(greetings/direct); // Welcome to the Murphy residence. This system will automatically try to connect you to... + Playback(/var/spool/asterisk/voicemail/default/${direct}/greet); + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/${direct}/greet.wav&); + switch(${direct}) + { + case 1: //Steve + &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); + goto s|loopback; + case 2: //Sonya + &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); + goto s|loopback; + default: // all the kids + Set(z=${direct}-2); + goto homeline-kids|${z}|1; + } + } + loopback: + ifTime(*|*|20-25|dec) + { + Playback(greetings/christmas); + } + else ifTime(*|*|31|dec) + { + Playback(greetings/newyear); + } + else ifTime(*|*|1|jan) + { + Playback(greetings/newyear); + } + else ifTime(*|*|14|feb) + { + Playback(greetings/valentines); + } + else ifTime(*|*|17|mar) + { + Playback(greetings/stPat); + } + else ifTime(*|*|31|oct) + { + Playback(greetings/halloween); + } + else ifTime(*|mon|15-21|jan) + { + Playback(greetings/mlkDay); + } + else ifTime(*|thu|22-28|nov) + { + Playback(greetings/thanksgiving); + } + else ifTime(*|mon|25-31|may) + { + Playback(greetings/memorial); + } + else ifTime(*|mon|1-7|sep) + { + Playback(greetings/labor); + } + else ifTime(*|mon|15-21|feb) + { + Playback(greetings/president); + } + else ifTime(*|sun|8-14|may) + { + Playback(greetings/mothers); + } + else ifTime(*|sun|15-21|jun) + { + Playback(greetings/fathers); + } + else + { + Playback(greetings/hello); // None of the above? Just a plain hello will do + } + Background(murphy-homeline-intro1); // Script: Hello-- Welcome to the Murphy's! If you already know what + // option you want, you don't have to wait for this entire spiel-- just + // have at it. + // If you are calling because this number is on a list of some sort, dial 6. + // If you want Sonya, dial 1. + // If you want one of the kids, dial 2. + // If you want Steve, dial 3. + // to play with your introduction, dial 5. + // If we don't seem to be giving you the time of day, try 7. + // Have a good day! + + } + 1 => { // Sonya + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/2/greet.wav&); + &std-priv-exten(Zap/3r1&Zap/5r1,2,25,mtw,telemarket,telemarket); + goto s|loopback; + } + 2 => { // Kids + goto homeline-kids|s|begin; + } + 21 => { + Dial(IAX2/seaniax,20,T); + } + 3 => { // Steve + &std-priv-exten(Zap/6r3&Sip/murf,1,25,mpA(beep)tw,telemarket,telemarket); + goto s|loopback; + } + 4 => { // Voicemail + VoicemailMain(); + goto s|loopback; + } + 5 => { // play with intro + goto home-introduction|s|begin; + } + 6 => { // Telemarketers + goto telemarket|s|begin; + } + 7 => { // time of day, riddle + agi(tts-riddle.agi); + Background(gsm/what-time-it-is2); + SayUnixTime(); + goto s|loopback; + } + 792 => { // Page All + goto pageall|s|begin; + } + 793 => { // check the tone recognition + Read(zz,,0,,1,0); + SayDigits(${zz}); + } + t => { + Set(repeatcount=${repeatcount} + 1); + if( ${repeatcount} < 3 ) + { + goto s|loopback; // just loopback isn't enough + } + Hangup(); + } + i => { + Background(invalid); + goto s|loopback; + } + o => { + Congestion(); + } + fax => { + Dial(Zap/4); + } +} + +// Some comments +// Some more comments + +context pageall { + s => { + begin: + AGI(callall); + MeetMe(5555,dtqp); + MeetMeAdmin(5555,K); + Hangup(); + } + + h => { + begin: + MeetMeAdmin(5555,K); + Background(conf-muted); + Hangup(); + } +} + +// Some comments +// Some more comments + +context add-to-conference { + start => { + NoCDR(); + MeetMe(5555,dmqp); + } + h => { + Hangup(); + } +} + +context home-introduction { + s => { + begin: + Background(intro-options); // Script: To hear your Introduction, dial 1. + // to record a new introduction, dial 2. + // to return to the main menu, dial 3. + // to hear what this is all about, dial 4. + } + 1 => { + Playback(priv-callerintros/${CALLERID(num)}); + goto s|begin; + } + 2 => { + goto home-introduction-record|s|begin; + } + 3 => { + goto homeline|s|loopback; + } + 4 => { + Playback(intro-intro); // Script: + // This may seem a little strange, but it really is a neat + // thing, both for you and for us. I've taped a short introduction + // for many of the folks who normally call us. Using the Caller ID + // from each incoming call, the system plays the introduction + // for that phone number over a speaker, just as the call comes in. + // This helps the folks + // here in the house more quickly determine who is calling. + // and gets the right ones to gravitate to the phone. + // You can listen to, and record a new intro for your phone number + // using this menu. + goto s|begin; + } + t => { + goto s|begin; + } + i => { + Background(invalid); + goto s|begin; + } + o => { + goto s|begin; + } +} + +context home-introduction-record { + s => { + begin: + Background(intro-record-choices); // Script: + // If you want some advice about recording your + // introduction, dial 1. + // otherwise, dial 2, and introduce yourself after + // the beep. + } + 1 => { + Playback(intro-record); + // Your introduction should be short and sweet and crisp. + // Your introduction will be limited to 10 seconds. + // This is NOT meant to be a voice mail message, so + // please, don't say anything about why you are calling. + // After we are done making the recording, your introduction + // will be saved for playback. + // If you are the only person that would call from this number, + // please state your name. Otherwise, state your business + // or residence name instead. For instance, if you are + // friend of the family, say, Olie McPherson, and both + // you and your kids might call here a lot, you might + // say: "This is the distinguished Olie McPherson Residence!" + // If you are the only person calling, you might say this: + // "This is the illustrious Kermit McFrog! Pick up the Phone, someone!!" + // If you are calling from a business, you might pronounce a more sedate introduction,like, + // "Fritz from McDonalds calling.", or perhaps the more original introduction: + // "John, from the Park County Morgue. You stab 'em, we slab 'em!". + // Just one caution: the kids will hear what you record every time + // you call. So watch your language! + // I will begin recording after the tone. + // When you are done, hit the # key. Gather your thoughts and get + // ready. Remember, the # key will end the recording, and play back + // your intro. Good Luck, and Thank you!" + goto 2|begin; + } + 2 => { + begin: + Background(intro-start); + // OK, here we go! After the beep, please give your introduction. + Background(beep); + Record(priv-callerintros/${CALLERID(num)}:gsm,3); + Background(priv-callerintros/${CALLERID(num)}); + goto home-introduction|s|begin; + } + t => { + goto s|begin; + } + i => { + Background(invalid); + goto s|begin; + } + o => { + goto s|begin; + } +} + +context homeline-kids { + s => { + begin: + Background(murphy-homeline-kids); // Which Kid? 1=Sean, 2:Eric, 3:Ryan, 4:Kyle, 5:Amber, 6:Alex, 7:Neal + } + 1 => { // SEAN + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/3/greet.wav&); + // &std-priv-exten(Zap/3r2&Zap/5r2,3,35,mtw,telemarket,telemarket); + &std-priv-exten(IAX2/seaniax&Zap/5r2,3,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + } + 2 => { // ERIC + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); + Voicemail(u4); + goto homeline|s|loopback; + + // SetMusicOnHold(erics); + // TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + // TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/4/greet.wav&); + // &std-priv-exten(Zap/3r2&Zap/5r2,4,35,mtw,telemarket,telemarket); + // goto homeline|s|loopback; + } + 3 => { // RYAN + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/5/greet.wav&); + &std-priv-exten(Zap/3r2&Zap/5r2,5,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + } + 4 => { // KYLE + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/6/greet.wav&); + &std-priv-exten(Zap/3r2&Zap/5r2,6,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + } + 5 => { + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/7/greet.wav&); + &std-priv-exten(Zap/3r2&Zap/5r2,7,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + + } + 6 => { + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/8/greet.wav&); + &std-priv-exten(Zap/3r2&Zap/5r2,8,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + } + 7 => { + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/9/greet.wav&); + &std-priv-exten(Zap/3r2&Zap/5r2,9,35,mtw,telemarket,telemarket); + goto homeline|s|loopback; + } + t => { + goto s|begin; + } + i => { + Background(invalid); + goto s|begin; + } + o => { + goto s|begin; + } +} + +context voipworkline { + s => { + begin: + Answer(); + TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); + goto workline|s|loopback; + } + 7075679201 => { + Answer(); + TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); + goto workline|s|loopback; + } +} + +context workline { + s => { + begin: + Answer(); + Wait(1); + Set(repeatcount=0); + Zapateller(nocallerid); +// PrivacyManager(); +// if( "${PRIVACYMGRSTATUS}" = "FAILED" ) +// { +// goto privacyManagerFailed|s|begin; +// } + &fillcidname(); + TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); + loopback: + Background(greetings/greeting); //script: Hello + Background(murphy-office-intro1); //script: welcome to Steve Murphy's office. If you are dialing + // this number because it was on a calling list of any sort, dial 6. + // Otherwise, dial 1, and hopefully, you will reach Steve. + } + 1 => { + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/call-for.gsm); + TrySystem(/usr/bin/play /var/spool/asterisk/voicemail/default/1/greet.wav&); + + &std-priv-exten(Zap/6&Sip/murf,1,30,mtw,telemarket,telemarket); + goto s|loopback; + } + 4 => { + VoicemailMain(); + goto s|loopback; + } + 6 => { + goto telemarket|s|begin; + } + 793 => { // check the tone recognition + Read(zz,,0,,1,0); + SayDigits(${zz}); + } + t => { + repeatcount=${repeatcount} + 1; + if( ${repeatcount} < 3 ) + { + goto s|loopback; // just loopback isn't enough + } + Hangup(); + } + i => { + Background(invalid); + goto s|loopback; + } + o => { + Congestion(); + } + fax => { + Answer(); + Dial(Zap/4); + } +} + +context dialFWD { + ignorepat => 8; + ignorepat => 9; + _83. => { + Set(CALLERID(name)=${FWDCIDNAME}); + Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); + Congestion(); + } + _82NXX => { + Set(CALLERID(name)=${FWDCIDNAME}); + Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); + Congestion(); + } + _92NXX => { + Set(CALLERID(name)=${FWDCIDNAME}); + Dial(IAX2/${FWDNUMBER}:${FWDPASSWORD}@iax2.fwdnet.net/${EXTEN:2},60,r); + Congestion(); + } +} + +context dialiaxtel { + ignorepat => 8; + ignorepat => 9; + _81700NXXXXXX => { + Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); + } + _81800NXXXXXX => { + Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); + } + _91700NXXXXXX => { + Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); + } + _91800NXXXXXX => { + Dial(IAX2/zorch:zilchnoodle@iaxtel.com/${EXTEN:1}@iaxtel); + } + +} + +context dialgoiax { + ignorepat => 9; + _93. => { + Set(CALLERID(name)="Joe Worker"); + Dial(IAX2/878201007658:stickyfinger295@server1.goiax.com/${EXTEN:2},60,r); + Congestion(); + } + +} + +context homefirst { + ignorepat => 9; + _91NXXNXXXXXX => { + &ciddial(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); + } + _9754XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9574XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9202XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9219XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9254XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9716XXXX => { + &ciddial(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9NXXXXXX => { + &ciddial(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9011. => { + &ciddial(${EXTEN:1},${EXTEN:1},30,TW,Zap/1); + } + _9911 => { + Dial(Zap/1/911,30,T); + } + _9411 => { + Dial(Zap/1/411,30,T); + } +} + +context workfirst { + ignorepat => 9; + _91NXXNXXXXXX => { + &ciddial2(${EXTEN:1},${EXTEN:2},30,TW,Zap/1); + } + _9754XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9574XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9202XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9219XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9254XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9716XXXX => { + &ciddial2(${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9NXXXXXX => { + &ciddial2(1707${EXTEN:1},707${EXTEN:1},30,TW,Zap/1); + } + _9911 => { + Dial(Zap/1/911,30,T); + } + _9411 => { + Dial(Zap/1/411,30,T); + } +} + +context force_cell { + ignorepat => 8; + _81NXXNXXXXXX => { + &ciddial(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/2); + } + _8754XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8574XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8202XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8219XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8254XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8716XXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8NXXXXXX => { + &ciddial(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/2); + } + _8911 => { + Dial(Zap/1/911|30|T); + } + _8411 => { + Dial(Zap/1/411|30|T); + } +} + +context force_home { + ignorepat => 8; + _81NXXNXXXXXX => { + &ciddial3(${EXTEN:1}#,${EXTEN:2},30,TW,Zap/1); + } + _8754XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8574XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8202XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8219XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8254XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8716XXXX => { + &ciddial3(${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8NXXXXXX => { + &ciddial3(1707${EXTEN:1}#,707${EXTEN:1},30,TW,Zap/1); + } + _8911 => { + Dial(Zap/1/911|30|T); + } + _8411 => { + Dial(Zap/1/411|30|T); + } +} + +context homeext { + ignorepat => 8; + ignorepat => 9; + includes { + parkedcalls; + homefirst; + force_cell; + } + s => { + loopback: + Wait(0); + } + 1 => { + &std-priv-exten(Zap/3&Zap/5,2,35,mtw,telemarket,telemarket); + goto s|loopback; + } + 2 => { + &std-priv-exten(Zap/6&Zap/5,1,35,mpA(beep3)Tt,telemarket,telemarket); + goto s|loopback; + } + 4 => { + VoicemailMain(); + } + 5 => { + Record(recording:gsm); + Background(recording); + } + 6 => { + Background(recording); + } + 760 => { + DateTime(); + goto s|loopback; + } + 761 => { + Record(announcement:gsm); + TrySystem(/usr/bin/play /var/lib/asterisk/sounds/announcement.gsm&); + goto s|loopback; + } + 762 => { + agi(tts-riddle.agi); + Background(gsm/what-time-it-is2); + SayUnixTime(); + goto s|loopback; + } + 763 => { + Set(CALLERID(num)=); + Dial(Zap/6r3,35,mptA(beep3)); //results: it should ALWAYS ask for an intro; the intro should not be left behind + Hangup(); + } + 764 => { + Set(CALLERID(num)=); + Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; shouldn't anyway if no callerid + Hangup(); + } + 765 => { + Set(CALLERID(num)=); + Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. + Hangup(); + } + 766 => { + Dial(Zap/6r3,35,mptNA(beep3)); //results: Don't screen if there's CALLERID; it should screen the call. + Hangup(); + } + 767 => { + Dial(Zap/6r3,35,mptnA(beep3)); //results: Don't save the intro; the interesting case, because callerID should be present. + Hangup(); + } + 769 => { + Playtones(dial); + Wait(2); + Playtones(busy); + Wait(2); + Playtones(ring); + Wait(2); + Playtones(congestion); + Wait(2); + Playtones(callwaiting); + Wait(2); + Playtones(dialrecall); + Wait(2); + Playtones(record); + Wait(2); + Playtones(info); + Wait(5); + Hangup(); + } + 790 => { + MeetMe(790,p); + } + 792 => { + goto pageall|s|begin; + } + 795 => { + AGI(wakeup.agi);Congestion(); + } + 544716 => { // Incoming call from FWD + TrySystem(/usr/local/bin/who-is-it ${CALLERID(num)} "${CALLERID(name)}"&); + goto s|loopback; + } + + i => { + Background(invalid); + goto s|loopback; + } + o => { + goto s|loopback; + } + t => { + Congestion(); + } +} + +context fromvmhome { + 1 => { + Dial(Zap/6&Sip/murf|20|Tt); + } + 2 => { + Dial(Zap/3&Zap/5|20|Tt); + } + _707202XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707219XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707254XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707716XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707754XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707574XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _NXXNXXXXXX => { + &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); + } + _1NXXNXXXXXX => { // HAND DIALING + &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); + } + _754XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _574XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _NXXXXXX => { + &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _911 => { + &ciddial(911,911,30,TW,Zap/1); + } + _411 => { + &ciddial(411,411,30,TW,Zap/1); + } +} + +context fromvmwork { + 1 => { + Dial(Zap/6&Sip/murf|20|Tt); + } + 2 => { + Dial(Zap/3&Zap/5|20|Tt); + } + _707202XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707219XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707254XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707716XXXX => { + &ciddial(1${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707754XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707574XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _NXXNXXXXXX => { + &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); + } + _1NXXNXXXXXX => { // HAND DIALING + &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); + } + _754XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _574XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _NXXXXXX => { + &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); + } + 911 => { + &ciddial(911,911,30,TW,Zap/1); + } + 411 => { + &ciddial(411,411,30,TW,Zap/1); + } +} + +context fromSeanUniden { + includes + { + parkedcalls; + } + 21 => { + Dial(IAX2/seaniax,20,T); + } + _707202XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707219XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707254XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707716XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707754XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _707574XXXX => { + &ciddial(${EXTEN:3},${EXTEN},30,TW,Zap/1); + } + _NXXNXXXXXX => { + &ciddial(1${EXTEN},${EXTEN},30,TW,Zap/1); + } + _1NXXNXXXXXX => { + &ciddial(${EXTEN},${EXTEN:1},30,TW,Zap/1); + } + _754XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _574XXXX => { + &ciddial(${EXTEN},707${EXTEN},30,TW,Zap/1); + } + _NXXXXXX => { + &ciddial(1707${EXTEN},707${EXTEN},30,TW,Zap/1); + } + 911 => { + &ciddial(911,911,30,TW,Zap/1); + } + 411 => { + &ciddial(411,411,30,TW,Zap/1); + } +} + +context workext { + ignorepat => 8; + ignorepat => 9; + includes { + parkedcalls; + workfirst; + force_home; + dialFWD; + dialiaxtel; + dialgoiax; + } + s => { + loopback: + Wait(0); + } + 1 => { + Dial(Zap/3&Zap/5,20,tT); + } + 2 => { + Dial(Zap/5&Zap/6,20,tT); + } + 21 => { + Dial(IAX2/seaniax,20,T); + } + 22 => { + Set(CALLERID(num)=1234567890); + Set(CALLERID(name)=TestCaller); + Dial(Zap/5,20,mP()A(beep)tw); + NoOp(here is dialstatus: ${DIALSTATUS}...); + goto s|loopback; + } + 4 => { + VoicemailMain(); + goto s|loopback; + } + 5 => { + Record(recording:gsm); + Background(recording); + } + 6 => { + ZapBarge(); + } + 760 => { + DateTime(); + goto s|loopback; + } + 761 => { + ZapBarge(); + goto s|loopback; + } + 765 => { + Playback(demo-echotest); + Echo(); + Playback(demo-echodone); + goto s|loopback; + } + 766 => { + Festival(The other thing to watch is neuro-electronics: the ability to interface technology with our neural system: My wife: Sigrid: has had a cochlear implant since 1996. This once profoundly deaf person now uses the phone: recognizes accents: and listens to movies and recorded books.); + goto s|loopback; + } + 767 => { + agi(tts-riddle.agi); + Background(gsm/what-time-it-is2); + SayUnixTime(); + goto s|loopback; + } + 768 => { + agi(tts-computer.agi); + } + 771 => { + eagi(eagi-test); + agi(my-agi-test); + } + 772 => { + agi(wakeup.agi); + } + 775 => { + if( ${EXTEN}=${EXTEN} ) + { + BackGround(digits/1); + } + else + { + BackGround(digits/0); + } + if( ${EXTEN}=${LANGUAGE} ) + { + BackGround(digits/1); + } + else + { + BackGround(digits/0); + } + BackGround(digits/2); + } + 776 => { + Set(TEST=00359889811777); + if( ${TEST}= 00359889811777 ) + { + BackGround(digits/1); + } + else + { + BackGround(digits/0); + } + if( ${TEST}= 00359889811888 ) + { + BackGround(digits/1); + } + else + { + BackGround(digits/0); + } + Hangup(); + } + 790 => { + MeetMe(790,p); + } + 792 => { + goto pageall|s|begin; + } + 793 => { + #include "include1.ael2" + } + 795 => { + AGI(wakeup.agi); + Congestion(); + } + 797 => { + Set(CONFCIDNA=${CALLERID(name)}); + Set(CONFCIDNU=${CALLERID(num)}); + AGI(callall); + AGI(submit-announce.agi); + Hangup(); + } +} + +context wakeup { + 3 => { + Dial(Zap/3|30); + } + 4 => { + Dial(Zap/4|30); + + } + 5 => { + Dial(Zap/5|30); + + } + 6 => { + Dial(Zap/6|30); + + } + 99 => { + Dial(IAX2/murfiaxphone|30); + } + 97 => { + Dial(IAX2/ryaniax|30); + } + 94 => { + Dial(IAX2/seaniax|30); + } +} + +context announce-all { + s => { + begin: + MeetMe(5555,dtqp); + MeetMeAdmin(5555,K); + Hangup(); + } + h => { + MeetMeAdmin(5555,K); + Hangup(); + } +} + +// now include the telemarketer torture scripts! + +#include "/etc/asterisk/telemarket_torture.ael2" + + diff --git a/pbx/ael/ael-test/ael-test3/include1.ael2 b/pbx/ael/ael-test/ael-test3/include1.ael2 new file mode 100644 index 0000000000..80c562cb23 --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/include1.ael2 @@ -0,0 +1,3 @@ + NoOp(Hello, this is included from include1.ael2); + #include "include2.ael2" + diff --git a/pbx/ael/ael-test/ael-test3/include2.ael2 b/pbx/ael/ael-test/ael-test3/include2.ael2 new file mode 100644 index 0000000000..8d892fb0c2 --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/include2.ael2 @@ -0,0 +1,4 @@ + NoOp(This was included from include2.ael2); + #include "include3.ael2" + #include "include4.ael2" + diff --git a/pbx/ael/ael-test/ael-test3/include3.ael2 b/pbx/ael/ael-test/ael-test3/include3.ael2 new file mode 100644 index 0000000000..3c6c1e3dd2 --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/include3.ael2 @@ -0,0 +1,2 @@ + NoOp(This is include3.ael2!); + #include "include5.ael2" diff --git a/pbx/ael/ael-test/ael-test3/include4.ael2 b/pbx/ael/ael-test/ael-test3/include4.ael2 new file mode 100644 index 0000000000..7d3703a5e8 --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/include4.ael2 @@ -0,0 +1,2 @@ + NoOp(This is include4.ael2! Isn't it cool!?!?!?!); + NoOp(4 doesn't include anything); diff --git a/pbx/ael/ael-test/ael-test3/include5.ael2 b/pbx/ael/ael-test/ael-test3/include5.ael2 new file mode 100644 index 0000000000..0e18983efa --- /dev/null +++ b/pbx/ael/ael-test/ael-test3/include5.ael2 @@ -0,0 +1 @@ + NoOp(Include5.ael2 doesn't include anything, either!); diff --git a/pbx/ael/ael-test/ael-test4/apptest.ael2 b/pbx/ael/ael-test/ael-test4/apptest.ael2 new file mode 100644 index 0000000000..c477d8531b --- /dev/null +++ b/pbx/ael/ael-test/ael-test4/apptest.ael2 @@ -0,0 +1,146 @@ +// this is a quick test to see how many of the apps we can spot j options in +// include this in a macro or extension +// at this moment, there are 18 apps that accept the j option. + + AddQueueMember(zork,iface,20,j); + ADSIProg(sfile); + AgentCallbackLogin(agent,s,30@cont); + AgentLogin(agent,s); + AgentMonitorOutgoing(dcn); + AGI(whatever); + AlarmReceiver(); + Answer(2); + AppendCDRUserField(value); + Authenticate(pword,adjmr); + BackGround(filename,snm,eng); + BackgroundDetect(filename,20,2,10); + Busy(10); + ChangeMonitor(fnamebase); + ChanIsAvail(Zap/5,sj); + ChanSpy(prefix,bg()qrv); + Congestion(5); + ControlPlayback(filename,10,6,4,0,5,7,j); + DateTime(unixtime,tz,fmt); + DBdel(fam/key); + DBdeltree(fam); + DeadAGI(command); + Dial(zap/1,45,A()CdD()fgG()hHjL()m()M()nNoprS()tTwW); + Dictate(basedir); + Directory(cont,dcont,f); + DISA(68986869876,context); + DumpChan(verblev); + DUNDiLookup(90709780978,context,bj); + EAGI(command); + Echo(); + EndWhile(); + Exec(appname,args); + ExecIf(expr,app,data); + ExecIfTime(*,*,*,*,appname); + ExternalIVR(command,arg1); + Festival(text); + Flash(); + ForkCDR(v); + GetCPEID(); + Gosub(cont,exten,priority); + GosubIf(cond?label); + Goto(cont,exten,prior); + GotoIf(cond?t:f); + GotoIfTime(*,*,*,*?cont,ext,prior); + Hangup(); + HasNewVoicemail(vmbox,var,j); + HasVoicemail(vmbox,var,j); + IAX2Provision(template); + ICES(xmlconfig); + ImportVar(nevar@chann,var); + Log(NOTICE,message); + LookupBlacklist(j); + LookupCIDName(); + Macro(macro,arg1); + MacroExit(); + MacroIf(expr?etc); + MailboxExists(mbox@cont,j); + Math(v,2+2); + MeetMe(5555,aAbcdDeimMpPqrstTovwxX); + MeetMeAdmin(5555,e,user); + MeetMeCount(5555,var); + Milliwatt(); + MixMonitor(filename,abv()V()W(),command); + Monitor(file.fmt,base,mb); + MP3Player(location); + MusicOnHold(class); + NBScat(); + NoCDR(); + NoOp(ignored); + Page(Zap/1,dq); + Park(exten); + ParkAndAnnounce(template,5,238,retcont); + ParkedCall(exten); + PauseQueueMember(queue,zap,j); + Pickup(ext@cont); + Playback(file,j); + PlayTones(arg); + PrivacyManager(3,4,j); + Progress(); + Queue(queuename,dhHnrtTwW,http://www.where.what,over,5); + Random(30,cont,ext,pri); + Read(var,fname,10,skip,2,5); + ReadFile(var=file,10); + RealTime(fam,2,val,prefix); + RealTimeUpdate(fam,2,val,2,newval); + Record(file,2,10,anqst); + RemoveQueueMember(queuename,iface,j); + ResetCDR(wav); + RetryDial(annound,4,2); + Return(); + Ringing(); + RxFAX(fname,caller); + SayAlpha(string); + SayDigits(string); + SayNumber(digits); + SayPhonetic(string); + SayUnixTime(unixtime,tz,fmt); + SendDTMF(digits,10); + SendImage(filename); + SendText(text,j); + SendURL(URL); + Set(a=b); + SetAMAFlags(); + SetCallerID(clid,a); + SetCallerPres(allowed_passed_screen); + SetCDRUserField(value); + SetGlobalVar(var=val); + SetMusicOnHold(class); + SetTransferCapability(SPEECH); + SIPAddHeader(header); + SIPDtmfMode(inband,info,rfc); + SIPGetHeader(var@headername); + SMS(name); + SoftHangup(zap/1,a); + StackPop(); + StartMusicOnHold(class); + StopMonitor(); + StopMusicOnHold(); + StopPlayTones(); + System(command); + TestClient(testid); + TestServer(); + Transfer(zap/1,j); + TrySystem(command); + TxFAX(filename,caller,debug); + UnpauseQueueMember(queuename,iface,j); + UserEvent(eventanme,body); + Verbose(5,message); + VMAuthenticate(mailbox@cont,s); + VoiceMail(mailbox@cont,bg()suj); + VoiceMailMain(mailbox@cont,pg()s); + Wait(2); + WaitExten(3,m()); + WaitForRing(2); + WaitForSilence(2,y); + WaitMusicOnHold(2); + While(expr); + Zapateller(answer,5); + ZapBarge(channel); + ZapRAS(arg); + ZapScan(group); + ZapSendKeypadFacility(); diff --git a/pbx/ael/ael-test/ael-test4/extensions.ael b/pbx/ael/ael-test/ael-test4/extensions.ael new file mode 100644 index 0000000000..838aa24892 --- /dev/null +++ b/pbx/ael/ael-test/ael-test4/extensions.ael @@ -0,0 +1,8 @@ +context test1 +{ + test2 => + { + #include "apptest.ael2"; + } +} + diff --git a/pbx/ael/ael-test/ael-test5/extensions.ael b/pbx/ael/ael-test/ael-test5/extensions.ael new file mode 100644 index 0000000000..304275a006 --- /dev/null +++ b/pbx/ael/ael-test/ael-test5/extensions.ael @@ -0,0 +1,833 @@ +/////////////////////////////////////////////////////////////////////////////// +// Helpdesk Queue + +context hd-queue { + s => { + NoOp(Add a background sound to tell the user their options); + Queue(helpdesk|t); + NoOp(Put in options to apologize and send user to voicemail); + }; + + 0 => goto default|0|1; + 1 => { + Dial(u41950@svm1.shsu.edu); + Congestion(10); + Hangup; + }; +}; + + +context l903-calling { + _9903NXXXXXX => { + Realtime(l903_ext,exchange,${EXTEN:4:3},l903_); + if ("${l903_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; +}; +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from houston.conf +// Converted the extension list to the database + +context houston-calling { + _9713NXXXXXX => { + Realtime(hou_713_ext,exchange,${EXTEN:4:3},hou_713_); + if ("${hou_713_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _9281NXXXXXX => { + Realtime(hou_281_ext,exchange,${EXTEN:4:3},hou_281_); + if ("${hou_281_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _9832NXXXXXX => { + Realtime(hou_832_ext,exchange,${EXTEN:4:3},hou_832_); + if ("${hou_832_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from huntsville.conf +// Converted the extension list to the database + +context huntsville-calling { + _9NXXXXXX => { + Realtime(hv_ext,exchange,${EXTEN:1:3},hv_); + if ("${hv_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _NXXXXXX => { + NoOp(Stripping last four to see what extension we're dialing); + Set(LAST4=${EXTEN:3}); + StripLSD(4); + }; + + i => Playback(pbx-invalid); + h => Hangup; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from macros.conf + +macro dialout( number ) { + Realtime(call_info,exten,${CALLERIDNUM:5},mon_); + if ("${mon_monitor}" = "YES") { + Dial(SIP/${number}@sgw1.shsu.edu,,wW); + Dial(SIP/${number}@sgw2.shsu.edu,,wW); + } else { + Dial(SIP/${number}@sgw1.shsu.edu); + Dial(SIP/${number}@sgw2.shsu.edu); + }; +}; + +// Standard extension macro: +// ${ext} - Extension +macro stdexten( ext ) { + Realtime(sipusers,name,${ext},sip_user_); + Realtime(call_info,exten|${ext},info_); + if ("${sip_user_name}foo" = "foo") { + Wait(1); + &dialout(${ext}); + Congestion(10); + Hangup; + }; + NoOp(${CALLERIDNUM}); + RealtimeUpdate(call_info,exten,${ext},calltrace,${CALLERIDNUM}); + System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &); + &checkdnd(${ext}); + &checkcf(${ext}); + Realtime(call_info,exten,${CALLERIDNUM:5},mon_); + if ("${mon_monitor}" = "YES") { + Dial(SIP/${info_forwardto},25,wW); + } else { + Dial(SIP/${info_forwardto},25); + }; + switch ("${DIALSTATUS}") { + case "BUSY": + &checkcfb(${ext}); + break; + case "CHANUNAVAIL": + Dial(IAX2/asterisk:password@scm2.shsu.edu/${info_forwardto},25,wW); + MailboxExists(${ext}); +// if ("${VMBOXEXISTSSTATUS}" = "FAILED") { +// Congestion(10); +// Hangup; +// }; + &uvm(${ext}); + Hangup; + break; + case "CONGESTION": + MailboxExists(${ext}); + if ("${VMBOXEXISTSSTATUS}" = "FAILED") { + Congestion(10); + Hangup; + }; + &bvm(${ext}); + Hangup; + break; + default: + MailboxExists(${ext}); + if ("${VMBOXEXISTSSTATUS}" = "FAILED") { + Congestion(10); + Hangup; + }; + &uvm(${ext}); + Hangup; + }; + Hangup; +}; + +macro uvm( ext ) { + Dial(SIP/u${ext}@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Congestion(10); + Hangup; +}; + +macro bvm( ext ) { + Dial(SIP/b${ext}@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Congestion(10); + Hangup; +}; + +macro checkdnd( ext ) { + if ("${info_donotdisturb}foo" = "foo") { + NoOp(Do Not Disturb is not active); + } else + &uvm(${ext}); +}; + +macro checkcf( ext ) { + if ("${info_forwardto}foo" = "foo") + if ("${ext}" = "43974") { + Set(info_forwardto=${ext}&SCCP/${ext}); + } else { + Set(info_forwardto=${ext}&SIP/${ext}w); + }; +}; + +macro checkcfb( ext ) { + if ("${info_forwardbusy}foo" = "foo") { + Wait(1); + MailboxExists(${ext}); + if ("${VMBOXEXISTSSTATUS}" = "FAILED") { + &dialout(${ext}); + Hangup; + }; + &bvm(${ext}); + Hangup; + }; + &stdexten(${info_forwardbusy}); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from test.conf + +context test-include { + includes { + test-digium; + test-sounds; + test-phinfo; + }; +}; + +context test-digium { + *500 => { + Dial(IAX2/guest@misery.digium.com/s@default); + Playback(demo-nogo); + Hangup; + }; +}; + +context test-sounds { + *501 => { + Answer; + Musiconhold; + Wait(1); + Hangup; + }; +}; + +context test-phinfo { + *505 => { + Answer; + NoOp(${CALLERIDNUM:5}); + SayDigits(${CALLERIDNUM:5}); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from external.conf + +context long-distance { + includes { + local; + }; + + _91XXXXXXXXXX => &dialout(${EXTEN}); + _9011. => &dialout(${EXTEN}); +}; + +context local { + includes { + default; + }; + + 911 => &dialout(911); + 9911 => &dialout(9911); + + _9NXXXXXX => goto huntsville-calling|${EXTEN}|1; + _936NXXXXXX => { + goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; + + _832NXXXXXX => { + goto 9${EXTEN}|1; + Congestion(10); + Hangup; + }; + + _713NXXXXXX => { + goto 9${EXTEN}|1 ; + Congestion(10); + Hangup; + }; + + _281NXXXXXX => { + goto 9${EXTEN}|1; + Congestion(10); + Hangup; + + }; + + _NXXNXXXXXX => { + goto 9${EXTEN}|1; + goto 91${EXTEN}|1; + Congestion(10); + Hangup; + }; + + _91800NXXXXXX => &dialout(${EXTEN}); + _91866NXXXXXX => &dialout(${EXTEN}); + _91877NXXXXXX => &dialout(${EXTEN}); + _91888NXXXXXX => &dialout(${EXTEN}); + _91900NXXXXXX => &dialout(${EXTEN}); + _91976NXXXXXX => &dialout(${EXTEN}); + _9713NXXXXXX => goto houston-calling|${EXTEN}|1; + _9281NXXXXXX => goto houston-calling|${EXTEN}|1; + _9832NXXXXXX => goto houston-calling|${EXTEN}|1; + _9903NXXXXXX => goto l903-calling|${EXTEN}|1; + + _31NXXNXXXXXX => &dialout(${EXTEN}); + + h => Hangup; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from internal.conf + +context from-scm2 { + _4XXXX => { + NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); + Dial(SIP/${EXTEN},20,wW); + Hangup; + }; + + _6XXXX => { + NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); + Dial(SIP/${EXTEN},20,wW); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////// +// All internal extensions work through the default context +// Phones that can only make internal calls should be in +// this context. +/////////////////////////////////////////////////////////// + +context default { +// Include the contexts in the files that allow us to make these phone calls + includes { + vm-include; + apps-include; + test-include; + }; + +// ALWAYS have an 'h' extension + h => { + NoOp(Hangup cause was: ${HANGUPCAUSE}); + Hangup; + }; + +// We like to hear that we dialed an invalid extension + i => Playback(pbx-invalid); + +// Dial the operator + 0 => &dialout(0); + +// Send voicemail calls to the vm-* contexts to be handled + voicemail => goto vm-direct|s|1; + 5555 => goto vm-direct|s|1; + 62100 => goto vm-extension|s|1; + +// These are our campus extensions, send them to the macro + _6XXXX => &stdexten(${EXTEN}); + _4XXXX => &stdexten(${EXTEN}); +// These are campus extensions as well, might need to take this out though. + _9294XXXX => goto _4XXXX|1; + _9496XXXX => goto _6XXXX|1; + +// These allows us to dial from the directory in our phone without worrying about dialing 9 + _936294XXXX => { + goto ${EXTEN:5}|1; + goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; + + _936496XXXX => { + goto ${EXTEN:5}|1; + goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from apps.conf + +context apps-include { + includes { + app-agents; + app-dnd; + app-callforward; + app-calltrace; + app-conferences; + app-ssd; + app-psd; + app-idblock; + app-helpdesk; + app-dictate; + app-set-monitor; + }; +}; + +context app-agents { + *54 => { + Answer; + Wait(1); + Read(agent_no|agent-user); + AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5}); + Playback(agent-loginok); + Hangup; + }; + + *55 => { + Answer; + Wait(1); + AgentCallbackLogin(${agent_no}); + Hangup; + }; +}; + +context app-calltrace { +// caller dials this to find out the last call missed and possibly call back + *69 => goto app-calltrace-perform|s|1; +}; + +context app-calltrace-perform { + s => { + Answer; + Wait(1); + Background(info-about-last-call); + Background(telephone-number); + RealTime(call_info|exten|${CALLERIDNUM:5}|ct_); + if ("${ct_calltrace}foo" = "foo") { + Playback(loligo/from-unknown-caller); + Hangup; + } else { + SayDigits("${ct_calltrace}"); + Set(TIMEOUT(digit)=3); + Set(TIMEOUT(response)=7); + Background(loligo/to-call-this-number); + Background(press-1); + Background(loligo/silence/5); + }; + }; + + 1 => goto local|${ct_calltrace}|1; + + i => { + Playback(vm-goodbye); + Hangup; + }; + + t => { + Playback(vm-goodbye); + Hangup; + }; +}; + +context app-set-monitor { + *50 => { + Realtime(call_info,exten,${CALLERIDNUM:5},mon_set_); + if ("${mon_set_monitor}" = "YES") { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor|); + System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &); + } else { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor,YES); + System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &); + }; + NoOp(${mon_set_monitor}); + Hangup; + }; +}; + +context app-dnd { + *78 => { + Answer; + Wait(1); + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb,YES); + System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &); + Playback(do-not-disturb); + Playback(loligo/activated); + Hangup; + }; + + *79 => { + Answer; + Wait(1); + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},donotdisturb|); + System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &); + Playback(do-not-disturb); + Playback(loligo/de-activated); + Hangup; + }; +}; + +context app-callforward { + // forwards calling extension to input number *72{EXTEN} + _*72. => { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,${EXTEN:3}); + System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-unconditional); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${CALLERIDNUM:5}); + Playback(loligo/is-set-to); + SayDigits(${EXTEN:3}); + Hangup; + }; + + // prompts for extension to forward to + *72 => { + Answer; + Wait(1); + Playback(please-enter-your); + Playback(extension); + Background(then-press-pound); + VMAuthenticate(|s); + Background(loligo/ent-target-attendant); + Read(toext,loligo/then-press-pound); + Wait(1); + RealtimeUpdate(call_info,exten,${AUTH_MAILBOX},forwardto,${toext}); + System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &); + Playback(loligo/call-fwd-unconditional); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${AUTH_MAILBOX}); + Playback(loligo/is-set-to); + SayDigits(${toext}); + Hangup; + }; + + // cancels dialed extension call forward + _*73. => { + Realtime(voicemail,mailbox,${EXTEN:3},auth_); + Answer; + Wait(1); + Authenticate(${auth_password}); + RealtimeUpdate(call_info,exten,${EXTEN:3},forwardto,); + System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &); + Wait(1); + SayDigits(${EXTEN:3}); + Playback(loligo/call-fwd-cancelled); + Hangup; + }; + + // cancels call forward for calling extension + *73 => { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardto,); + System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-cancelled); + Hangup; + }; + + // dialed call forward on busy + _*90. => { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy,${EXTEN:3}); + System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-on-busy); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${CALLERIDNUM:5}); + Playback(loligo/is-set-to); + SayDigits(${EXTEN:3}); + Hangup; + }; + + // cancels call forward on busy for calling extension + *91 => { + RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},forwardbusy|); + System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-on-busy); + Playback(loligo/de-activated); + Hangup; + }; + + h => Hangup; +}; + +context app-idblock { + _*67. => { + Set(CALLERID(name)=Anonymous); + &stdexten(${EXTEN:3}); + }; +}; + +context app-dictate { + *1 => { + Dictate(); + Hangup; + }; +}; + +context app-ssd { +// *59 <xx> <y.> - Set system speed dial <xx> to digits <y.> +// *59 <xx> 0 - Delete system speed dial <xx> +// *59 <xx> - Review system speed dial <xx> +// *1xx - Dial speed dial <xx> + _*59XXX. => { + Answer; + RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,${EXTEN:5}); + System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-set-to); + SayDigits(${EXTEN:5}); + Hangup; + }; + + _*59XX0 => { + Answer; + RealtimeUpdate(ssd,sd,${EXTEN:3:2},extension,); + System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-cleared); + Hangup; + }; + + _*59XX => { + Answer; + Realtime(ssd,sd,${EXTEN:3},ssd_); + if ("${ssd_extension}foo" = "foo") { + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-not-set); + Hangup; + }; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-set-to); + SayDigits(${ssd_extension}); + Hangup; + }; + + // NTC = number to call + _*1XX => { + Realtime(ssd,sd,${EXTEN:2},ssd_); + if ("${ssd_extension}foo" = "foo") { + Answer; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:2}); + Playback(loligo/is-not-set); + Hangup; + }; + &stdexten(${ssd_extension}); + Congestion(10); + Hangup; + }; +}; + +macro check-psd-exists ( ext ) { + Realtime(psd,extension,${ext},psd_); + if ("${psd_extension}foo" = "foo") { + System(/usr/local/bin/create_psd.sh ${ext}); + } else + NoOp(PSD set for ${ext}); +}; + +context app-psd { +// *89 <xx> <y.> - Set personal speed dial <xx> to digits <y.> +// *89 <xx> 0 - Delete personal speed dial <xx> +// *89 <xx> - Review personal speed dial <xx> +// *2xx - Dial personal speed dial <xx> + _*89XXX. => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + RealtimeUpdate(psd,extension,${CALLERIDNUM:5},s${EXTEN:3:2},${EXTEN:5}); + System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-set-to); + SayDigits(${EXTEN:5}); + Hangup; + }; + + _*89XX0 => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|); + System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-cleared); + Hangup; + }; + + _*89XX => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + Realtime(psd|extension|${CALLERIDNUM:5}|psd_); + Wait(1); + if ("${psd_s${EXTEN:3:2}}foo" = "foo") { + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-not-set); + Hangup; + }; + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-set-to); + SayDigits(${psd_s${EXTEN:3:2}}); + Hangup; + }; + + // NTC = number to call + _*2XX => { + &check-psd-exists(${CALLERIDNUM:5}); + Realtime(psd|extension|${CALLERIDNUM:5}|psd_); + if ("${psd_s${EXTEN:2}}foo" = "foo") { + Answer; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:2}); + Playback(loligo/is-not-set); + Hangup; + }; + &stdexten(${psd_s${EXTEN:2}}); + Congestion(10); + Hangup; + }; +}; + +context app-helpdesk { + *4357 => { + &stdexten(41950); + Congestion; + }; +}; + +context app-conferences { +// waiting for room number announcement + *86 => goto app-conf-hidden|s|1; +}; + +context app-conf-hidden { + s => { + Wait(1); + Playback(loligo/please-enter-the); + Playback(loligo/extension); + read(roomtoenter,loligo/then-press-pound); + Meetme(${roomtoenter}); + Waitexten(8); + Hangup; + }; + + _1. => Meetme(${EXTEN}); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from vm.conf: + +context vm-include { + includes { + vm-direct; + vm-extension; + vm-directory; + }; +}; + +context vm-direct { + s => { + Dial(SIP/5555@svm1.shsu.edu,20); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; + +context vm-extension { + s => { + Dial(SIP/62100@svm1.shsu.edu,20); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; + +context vm-directory { + 5556 => { + Dial(SIP/5556@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; diff --git a/pbx/ael/ael-test/ael-test6/extensions.ael b/pbx/ael/ael-test/ael-test6/extensions.ael new file mode 100644 index 0000000000..890c7111cc --- /dev/null +++ b/pbx/ael/ael-test/ael-test6/extensions.ael @@ -0,0 +1,833 @@ +/////////////////////////////////////////////////////////////////////////////// +// Helpdesk Queue + +context hd-queue { + s => { + NoOp(Add a background sound to tell the user their options); + Queue(helpdesk|t); + NoOp(Put in options to apologize and send user to voicemail); + }; + + 0 => goto default|0|1; + 1 => { + Dial(u41950@svm1.shsu.edu); + Congestion(10); + Hangup; + }; +}; + + +context l903-calling { + _9903NXXXXXX => { + Realtime(l903_ext|exchange|${EXTEN:4:3}|l903_); + if ("${l903_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; +}; +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from houston.conf +// Converted the extension list to the database + +context houston-calling { + _9713NXXXXXX => { + Realtime(hou_713_ext|exchange|${EXTEN:4:3}|hou_713_); + if ("${hou_713_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _9281NXXXXXX => { + Realtime(hou_281_ext|exchange|${EXTEN:4:3}|hou_281_); + if ("${hou_281_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _9832NXXXXXX => { + Realtime(hou_832_ext|exchange|${EXTEN:4:3}|hou_832_); + if ("${hou_832_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from huntsville.conf +// Converted the extension list to the database + +context huntsville-calling { + _9NXXXXXX => { + Realtime(hv_ext|exchange|${EXTEN:1:3}|hv_); + if ("${hv_exchange}foo" = "foo") { + Playback(num-outside-area); + SayDigits(1); + Playback(and-area-code); + Playback(before-the-number); + Hangup; + }; + &dialout(${EXTEN}); + Congestion(10); + Hangup; + }; + + _NXXXXXX => { + NoOp(Stripping last four to see what extension we're dialing); + Set(LAST4=${EXTEN:3}); + StripLSD(4); + }; + + i => Playback(pbx-invalid); + h => Hangup; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from macros.conf + +macro dialout( number ) { + Realtime(call_info|exten|${CALLERIDNUM:5}|mon_); + if ("${mon_monitor}" = "YES") { + Dial(SIP/${number}@sgw1.shsu.edu,,wW); + Dial(SIP/${number}@sgw2.shsu.edu,,wW); + } else { + Dial(SIP/${number}@sgw1.shsu.edu); + Dial(SIP/${number}@sgw2.shsu.edu); + }; +}; + +// Standard extension macro: +// ${ext} - Extension +macro stdexten( ext ) { + Realtime(sipusers|name|${ext}|sip_user_); + Realtime(call_info|exten|${ext}|info_); + if ("${sip_user_name}foo" = "foo") { + Wait(1); + &dialout(${ext}); + Congestion(10); + Hangup; + }; + NoOp(${CALLERIDNUM}); + RealtimeUpdate(call_info|exten|${ext}|calltrace|${CALLERIDNUM}); + System(/usr/local/bin/db_update.sh call_info calltrace ${CALLERIDNUM} exten ${ext} &); + &checkdnd(${ext}); + &checkcf(${ext}); + Realtime(call_info|exten|${CALLERIDNUM:5}|mon_); + if ("${mon_monitor}" = "YES") { + Dial(SIP/${info_forwardto},25,wW); + } else { + Dial(SIP/${info_forwardto},25); + }; + switch ("${DIALSTATUS}") { + case "BUSY": + &checkcfb(${ext}); + break; + case "CHANUNAVAIL": + Dial(IAX2/asterisk:password@scm2.shsu.edu/${info_forwardto},25,wW); + MailboxExists(${ext}); +// if ("${VMBOXEXISTSSTATUS}" = "FAILED") { +// Congestion(10); +// Hangup; +// }; + &uvm(${ext}); + Hangup; + break; + case "CONGESTION": + MailboxExists(${ext}); + if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { + Congestion(10); + Hangup; + }; + &bvm(${ext}); + Hangup; + break; + default: + MailboxExists(${ext}); + if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { + Congestion(10); + Hangup; + }; + &uvm(${ext}); + Hangup; + }; + Hangup; +}; + +macro uvm( ext ) { + Dial(SIP/u${ext}@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Congestion(10); + Hangup; +}; + +macro bvm( ext ) { + Dial(SIP/b${ext}@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Congestion(10); + Hangup; +}; + +macro checkdnd( ext ) { + if ("${info_donotdisturb}foo" = "foo") { + NoOp(Do Not Disturb is not active); + } else + &uvm(${ext}); +}; + +macro checkcf( ext ) { + if ("${info_forwardto}foo" = "foo") + if ("${ext}" = "43974") { + Set(info_forwardto=${ext}&SCCP/${ext}); + } else { + Set(info_forwardto=${ext}&SIP/${ext}w); + }; +}; + +macro checkcfb( ext ) { + if ("${info_forwardbusy}foo" = "foo") { + Wait(1); + MailboxExists(${ext}); + if ("$(VMBOXEXISTSSTATUS}" = "FAILED") { + &dialout(${ext}); + Hangup; + }; + &bvm(${ext}); + Hangup; + }; + &stdexten(${info_forwardbusy}); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from test.conf + +context test-include { + includes { + test-digium; + test-sounds; + test-phinfo; + }; +}; + +context test-digium { + *500 => { + Dial(IAX2/guest@misery.digium.com/s@default); + Playback(demo-nogo); + Hangup; + }; +}; + +context test-sounds { + *501 => { + Answer; + Musiconhold; + Wait(1); + Hangup; + }; +}; + +context test-phinfo { + *505 => { + Answer; + NoOp(${CALLERIDNUM:5}); + SayDigits(${CALLERIDNUM:5}); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from external.conf + +context long-distance { + includes { + local; + }; + + _91XXXXXXXXXX => &dialout(${EXTEN}); + _9011. => &dialout(${EXTEN}); +}; + +context local { + includes { + default; + }; + + 911 => &dialout(911); + 9911 => &dialout(9911); + + _9NXXXXXX => goto huntsville-calling|${EXTEN}|1; + _936NXXXXXX => { + Goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; + + _832NXXXXXX => { + goto 9${EXTEN}|1; + Congestion(10); + Hangup; + }; + + _713NXXXXXX => { + goto 9${EXTEN}|1 ; + Congestion(10); + Hangup; + }; + + _281NXXXXXX => { + goto 9${EXTEN}|1; + Congestion(10); + Hangup; + + }; + + _NXXNXXXXXX => { + goto 9${EXTEN}|1; + goto 91${EXTEN}|1; + Congestion(10); + Hangup; + }; + + _91800NXXXXXX => &dialout(${EXTEN}); + _91866NXXXXXX => &dialout(${EXTEN}); + _91877NXXXXXX => &dialout(${EXTEN}); + _91888NXXXXXX => &dialout(${EXTEN}); + _91900NXXXXXX => &dialout(${EXTEN}); + _91976NXXXXXX => &dialout(${EXTEN}); + _9713NXXXXXX => goto houston-calling|${EXTEN}|1; + _9281NXXXXXX => goto houston-calling|${EXTEN}|1; + _9832NXXXXXX => goto houston-calling|${EXTEN}|1; + _9903NXXXXXX => goto l903-calling|${EXTEN}|1; + + _31NXXNXXXXXX => &dialout(${EXTEN}); + + h => Hangup; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from internal.conf + +context from-scm2 { + _4XXXX => { + NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); + Dial(SIP/${EXTEN},20,wW); + Hangup; + }; + + _6XXXX => { + NoOp(DIALING SIP EXTENSION ${EXTEN} - FROM ${CALLERIDNUM}); + Dial(SIP/${EXTEN},20,wW); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////// +// All internal extensions work through the default context +// Phones that can only make internal calls should be in +// this context. +/////////////////////////////////////////////////////////// + +context default { +// Include the contexts in the files that allow us to make these phone calls + includes { + vm-include; + apps-include; + test-include; + }; + +// ALWAYS have an 'h' extension + h => { + NoOp(Hangup cause was: ${HANGUPCAUSE}); + Hangup; + }; + +// We like to hear that we dialed an invalid extension + i => Playback(pbx-invalid); + +// Dial the operator + 0 => &dialout(0); + +// Send voicemail calls to the vm-* contexts to be handled + voicemail => goto vm-direct|s|1; + 5555 => goto vm-direct|s|1; + 62100 => goto vm-extension|s|1; + +// These are our campus extensions, send them to the macro + _6XXXX => &stdexten(${EXTEN}); + _4XXXX => &stdexten(${EXTEN}); +// These are campus extensions as well, might need to take this out though. + _9294XXXX => goto _4XXXX|1; + _9496XXXX => goto _6XXXX|1; + +// These allows us to dial from the directory in our phone without worrying about dialing 9 + _936294XXXX => { + goto ${EXTEN:5}|1; + goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; + + _936496XXXX => { + goto ${EXTEN:5}|1; + goto 9${EXTEN:3}|1; + Congestion(10); + Hangup; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from apps.conf + +context apps-include { + includes { + app-agents; + app-dnd; + app-callforward; + app-calltrace; + app-conferences; + app-ssd; + app-psd; + app-idblock; + app-helpdesk; + app-dictate; + app-set-monitor; + }; +}; + +context app-agents { + *54 => { + Answer; + Wait(1); + Read(agent_no|agent-user); + AgentCallbackLogin(${agent_no}|s${CALLERIDNUM:5}); + Playback(agent-loginok); + Hangup; + }; + + *55 => { + Answer; + Wait(1); + AgentCallbackLogin(${agent_no}); + Hangup; + }; +}; + +context app-calltrace { +// caller dials this to find out the last call missed and possibly call back + *69 => goto app-calltrace-perform|s|1; +}; + +context app-calltrace-perform { + s => { + Answer; + Wait(1); + Background(info-about-last-call); + Background(telephone-number); + RealTime(call_info|exten|${CALLERIDNUM:5}|ct_); + if ("${ct_calltrace}foo" = "foo") { + Playback(loligo/from-unknown-caller); + Hangup; + } else { + SayDigits("${ct_calltrace}"); + Set(TIMEOUT(digit)=3); + Set(TIMEOUT(response)=7); + Background(loligo/to-call-this-number); + Background(press-1); + Background(loligo/silence/5); + }; + }; + + 1 => goto local|${ct_calltrace}|1; + + i => { + Playback(vm-goodbye); + Hangup; + }; + + t => { + Playback(vm-goodbye); + Hangup; + }; +}; + +context app-set-monitor { + *50 => { + Realtime(call_info|exten|${CALLERIDNUM:5}|mon_set_); + if ("${mon_set_monitor}" = "YES") { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|); + System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &); + } else { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|YES); + System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &); + }; + NoOp(${mon_set_monitor}); + Hangup; + }; +}; + +context app-dnd { + *78 => { + Answer; + Wait(1); + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|YES); + System(/usr/local/bin/db_update.sh call_info donotdisturb YES exten ${CALLERIDNUM:5} &); + Playback(do-not-disturb); + Playback(loligo/activated); + Hangup; + }; + + *79 => { + Answer; + Wait(1); + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|donotdisturb|); + System(/usr/local/bin/db_update.sh call_info donotdisturb '' exten ${CALLERIDNUM:5} &); + Playback(do-not-disturb); + Playback(loligo/de-activated); + Hangup; + }; +}; + +context app-callforward { + // forwards calling extension to input number *72{EXTEN} + _*72. => { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|${EXTEN:3}); + System(/usr/local/bin/db_update.sh call_info forwardto ${EXTEN:3} exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-unconditional); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${CALLERIDNUM:5}); + Playback(loligo/is-set-to); + SayDigits(${EXTEN:3}); + Hangup; + }; + + // prompts for extension to forward to + *72 => { + Answer; + Wait(1); + Playback(please-enter-your); + Playback(extension); + Background(then-press-pound); + VMAuthenticate(|s); + Background(loligo/ent-target-attendant); + Read(toext,loligo/then-press-pound); + Wait(1); + RealtimeUpdate(call_info|exten|${AUTH_MAILBOX}|forwardto|${toext}); + System(/usr/local/bin/db_update.sh call_info forwardto ${toext} exten ${AUTH_MAILBOX} &); + Playback(loligo/call-fwd-unconditional); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${AUTH_MAILBOX}); + Playback(loligo/is-set-to); + SayDigits(${toext}); + Hangup; + }; + + // cancels dialed extension call forward + _*73. => { + Realtime(voicemail|mailbox|${EXTEN:3}|auth_); + Answer; + Wait(1); + Authenticate(${auth_password}); + RealtimeUpdate(call_info|exten|${EXTEN:3}|forwardto|); + System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${EXTEN:3} &); + Wait(1); + SayDigits(${EXTEN:3}); + Playback(loligo/call-fwd-cancelled); + Hangup; + }; + + // cancels call forward for calling extension + *73 => { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardto|); + System(/usr/local/bin/db_update.sh call_info forwardto '' exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-cancelled); + Hangup; + }; + + // dialed call forward on busy + _*90. => { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|${EXTEN:3}); + System(/usr/local/bin/db_update.sh call_info forwardbusy ${EXTEN:3} exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-on-busy); + Playback(loligo/for); + Playback(loligo/extension); + SayDigits(${CALLERIDNUM:5}); + Playback(loligo/is-set-to); + SayDigits(${EXTEN:3}); + Hangup; + }; + + // cancels call forward on busy for calling extension + *91 => { + RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|forwardbusy|); + System(/usr/local/bin/db_update.sh call_info forwardbusy '' exten ${CALLERIDNUM:5} &); + Answer; + Wait(1); + Playback(loligo/call-fwd-on-busy); + Playback(loligo/de-activated); + Hangup; + }; + + h => Hangup; +}; + +context app-idblock { + _*67. => { + Set(CALLERID(name)=Anonymous); + &stdexten(${EXTEN:3}); + }; +}; + +context app-dictate { + *1 => { + Dictate(); + Hangup; + }; +}; + +context app-ssd { +// *59 <xx> <y.> - Set system speed dial <xx> to digits <y.> +// *59 <xx> 0 - Delete system speed dial <xx> +// *59 <xx> - Review system speed dial <xx> +// *1xx - Dial speed dial <xx> + _*59XXX. => { + Answer; + RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|${EXTEN:5}); + System(/usr/local/bin/db_update.sh systemsd extension ${EXTEN:5} sd ${EXTEN:3:2} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-set-to); + SayDigits(${EXTEN:5}); + Hangup; + }; + + _*59XX0 => { + Answer; + RealtimeUpdate(ssd|sd|${EXTEN:3:2}|extension|); + System(/usr/local/bin/db_update.sh systemsd extension '' sd ${EXTEN:3:2} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-cleared); + Hangup; + }; + + _*59XX => { + Answer; + Realtime(ssd|sd|${EXTEN:3}|ssd_); + if ("${ssd_extension}foo" = "foo") { + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-not-set); + Hangup; + }; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-set-to); + SayDigits(${ssd_extension}); + Hangup; + }; + + // NTC = number to call + _*1XX => { + Realtime(ssd|sd|${EXTEN:2}|ssd_); + if ("${ssd_extension}foo" = "foo") { + Answer; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:2}); + Playback(loligo/is-not-set); + Hangup; + }; + &stdexten(${ssd_extension}); + Congestion(10); + Hangup; + }; +}; + +macro check-psd-exists ( ext ) { + Realtime(psd|extension|${ext}|psd_); + if ("${psd_extension}foo" = "foo") { + System(/usr/local/bin/create_psd.sh ${ext}); + } else + NoOp(PSD set for ${ext}); +}; + +context app-psd { +// *89 <xx> <y.> - Set personal speed dial <xx> to digits <y.> +// *89 <xx> 0 - Delete personal speed dial <xx> +// *89 <xx> - Review personal speed dial <xx> +// *2xx - Dial personal speed dial <xx> + _*89XXX. => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|${EXTEN:5}); + System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} ${EXTEN:5} extension ${CALLERIDNUM:5} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-set-to); + SayDigits(${EXTEN:5}); + Hangup; + }; + + _*89XX0 => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + RealtimeUpdate(psd|extension|${CALLERIDNUM:5}|s${EXTEN:3:2}|); + System(/usr/local/bin/db_update.sh personalsd s${EXTEN:3:2} '' extension ${CALLERIDNUM:5} &); + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/has-been-cleared); + Hangup; + }; + + _*89XX => { + &check-psd-exists(${CALLERIDNUM:5}); + Answer; + Realtime(psd|extension|${CALLERIDNUM:5}|psd_); + Wait(1); + if ("${psd_s${EXTEN:3:2}}foo" = "foo") { + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-not-set); + Hangup; + }; + Playback(loligo/speed-dial); + SayDigits(${EXTEN:3:2}); + Playback(loligo/is-set-to); + SayDigits(${psd_s${EXTEN:3:2}}); + Hangup; + }; + + // NTC = number to call + _*2XX => { + &check-psd-exists(${CALLERIDNUM:5}); + Realtime(psd|extension|${CALLERIDNUM:5}|psd_); + if ("${psd_s${EXTEN:2}}foo" = "foo") { + Answer; + Wait(1); + Playback(loligo/speed-dial); + SayDigits(${EXTEN:2}); + Playback(loligo/is-not-set); + Hangup; + }; + &stdexten(${psd_s${EXTEN:2}}); + Congestion(10); + Hangup; + }; +}; + +context app-helpdesk { + *4357 => { + &stdexten(41950); + Congestion; + }; +}; + +context app-conferences { +// waiting for room number announcement + *86 => goto app-conf-hidden|s|1; +}; + +context app-conf-hidden { + s => { + Wait(1); + Playback(loligo/please-enter-the); + Playback(loligo/extension); + read(roomtoenter,loligo/then-press-pound); + Meetme(${roomtoenter}); + Waitexten(8); + Hangup; + }; + + _1. => Meetme(${EXTEN}); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Extensions pulled from vm.conf: + +context vm-include { + includes { + vm-direct; + vm-extension; + vm-directory; + }; +}; + +context vm-direct { + s => { + Dial(SIP/5555@svm1.shsu.edu,20); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; + +context vm-extension { + s => { + Dial(SIP/62100@svm1.shsu.edu,20); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; + +context vm-directory { + 5556 => { + Dial(SIP/5556@svm1.shsu.edu); + Playback(im-sorry); + Playback(voice-mail-system); + Playback(down); + Playback(extra/pls-try-call-later); + Congestion(10); + Hangup; + }; +}; diff --git a/pbx/ael/ael-test/ael-test7/extensions.ael b/pbx/ael/ael-test/ael-test7/extensions.ael new file mode 100644 index 0000000000..52f9a077ac --- /dev/null +++ b/pbx/ael/ael-test/ael-test7/extensions.ael @@ -0,0 +1,460 @@ +// +// Example AEL config file +// + +globals { + CONSOLE=Console/dsp; + TRUNKMSD=0; //MSD digits to strip (usually 1 or 0) + TRUNCPROTO=SIP; + TRUNK=sunrocket; + PSTN=pstn-spa3k; + PSTNPROTO=SIP; + TARIOPROTO=SIP; + TARIO=tario; + CPPROTO=SIP; + CPACKET1=callpacket1; + CPACKET2=callpacket2; + SELLVOIP=1577040314; + SVPROTO=IAX2; +}; + + +macro stdexten (ext , dev ) { + PrivacyManager(3,10); + if("${PRIVACYMGRSTATUS}" = "FAILED") { + Playback(vm-goodbye); + Hangup(); + }; + + AGI(calleridnamelookup.agi); + Dial(${dev}/${ext},30,t); + switch(${DIALSTATUS}) { + case BUSY: + Voicemail(b${ext}); + break; + default: + Voicemail(u${ext}); + }; + catch a { + VoiceMailMain(${ext}); + return; + }; +}; + +macro announce_minutes(minutes) { + Playback(vm-youhave); + SayNumber(${minutes}); + Playback(vm-minutes); + Wait(1); +}; + +// Check if given provider allows only some free minutes per month +// and announce number of free minutes remaining. +// The limit will be reset monthly by cron job. +// The macro sets the following variables: +// MINUTES_LIMIT - number of free minutes per month +// MINUTES_USED - number of free minutes used in the current month +// PROVIDER - provider name + +macro checkanddial(prov,proto,ext,arg1,arg2,arg3,arg4) { + Set(MINUTES_LIMIT=0); + Set(MINUTES_USED=0); + Set(PROVIDER=${prov}); + + if(${DB_EXISTS(Provider/${prov}/used)}) + Set(MINUTES_USED=${DB_RESULT}); + + country_c = 0; + switch(${LEN(${ext})}) { //assuming all international numbers are 11 digits long. + case 10: //NXXNXXXXXX + country_c=1; + break; + case 11: //XNXXNXXXXXX + country_c = ${ext:0:1}; + break; + default: //011XNXXNXXXXXX + country_c = ${ext:3:1}; + break; + }; + + if("${prov}" = "${TRUNK}" & ${country_c} != 1) { // SunRocket international calls + Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)}); + &announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]); + }; + if("${prov}" = "${CPACKET1}" | "${prov}" = "${CPACKET2}") { // Callpacket has a limit on domestic calls + Set(MINUTES_LIMIT=${DB(Provider/${prov}/limit)}); + &announce_minutes($[${MINUTES_LIMIT} - ${MINUTES_USED}]); + }; + DeadAGI(dial.agi,${proto}/${ext}@${prov},${arg1},${arg2},${arg3},${arg4}); +}; + +macro trunkdial(ext) { // Dial sunrocket and set correct collerid + if("${CALLERID(number)}" = "1") { + Set(CALLERID(number)=7322271653); + } else { + Set(CALLERID(number)=7326260100); + }; + Set(CALLERID(name)=Sergey Okhapkin); + &checkanddial(${TRUNK},${TRUNCPROTO},${ext},60,T); + Hangup; +}; + +macro checklocal(ext) { // lookup the number in DB and call the number via pstn or sunrocket + Set(AREACODE=${ext:0:3}); + Set(EXCHANGE=${ext:3:3}); + Set(IS_LOCAL=${DB_EXISTS(localnum/${AREACODE}/${EXCHANGE})}); + if(${IS_LOCAL}) { + &checkanddial(${PSTN},${PSTNPROTO},${ext},60,T); + if ("${DIALSTATUS}" = "BUSY") + &trunkdial(${ext}); + } else + &trunkdial(${ext}); +}; + +macro autodial(ext) { // Find Least Cost Route + LCDial(${ext},60,T); + if("${DIALSTATUS}" = "NOPROVIDER") + Playback(invalid); + Hangup(); +}; + +context default { // Calls to us + s => { + Wait(1); + Answer; +start: + Set(TIMEOUT(digit)=3); + Set(TIMEOUT(response)=10); +repeat: + for (x=0; ${x} < 5; x=${x} + 1) { + Background(home/greeting); + WaitExten(); + }; + }; + t => jump *; + i => { // invalid extension + Playback(invalid); + goto s|repeat; + }; + _* => { + Playback(vm-goodbye); + Wait(1); + Hangup; + }; + 1 => &stdexten(1,SIP/1); + 2 => &stdexten(2,SIP/2); + 3 => &stdexten(3,SIP/3); + + 2271653 => jump 1; + 7322271653 => jump 1; + 17322271653 => jump 1; + + 6260100 => jump 2; + 7326260100 => jump 2; + 17326260100 => jump 2; + 8058701100 => jump 2; + 3103622835 => jump 2; + sos => jump 2; + 1400898 => jump 2; + + 6260101 => jump s; + 7326260101 => jump s; + 17326260101 => jump s; + + 2271677 => jump 3; + 7322271677 => jump 3; + 17322271677 => jump 3; + galka => jump 3; + 911 => Dial(${PSTNPROTO}/911@${PSTN},60,); + 380 => Dial(SIP/topspeen@212.40.38.70,60,T); + + // Fun stuff + 100 => { + SayUnixTime(); + goto s|start; + }; + 101 => { // Voicemail + VoicemailMain(${CALLERID(number)}); + Hangup; + }; + 102 => MusicOnHold(); +// 103 => { +// Wait(1); +//start: +// Read(NUMBER,vm-enter-num-to-call); +// LCDial(${NUMBER},T); +// goto start; +// }; + 105 => jump s@phrase-menu; + 7312 => { + ForkCDR; + Set(CALLERID(name)=Sergey Okhapkin); + Set(CALLERID(number)=7326260100); + DISA(1111|home); + }; +}; + +context goiax { + s => { + Answer(); + Ringing(); + Wait(1); +start: + Read(NUMBER,vm-enter-num-to-call); + Set(CALLERID(name)=Central NJ); + Dial(IAX2/14301@fwdOUT/q${NUMBER},60,T); + goto start; + }; + +}; + +context phrase-menu { + + s => { + Answer; // Answer the line + TIMEOUT(digit)=2; // Set Digit Timeout to 5 seconds + TIMEOUT(response)=10; // Set Response Timeout to 10 seconds + BackGround(custom/phrase-menu); // Play main menu. + }; + 1 => { // Phrase Recording + Wait(1); + Read(PHRASEID|custom/enter-phrase-num); + Wait(2); // give yourself 2 secs to take a breath and wait for beep + Record(custom/${PHRASEID}:gsm); + Wait(2); + Playback(custom/${PHRASEID}); + Wait(1); + jump s; + }; + 2 => { // Phrase review + Wait(1); + Read(PHRASEID|custom/enter-phrase-num); + Wait(1); + Playback(custom/${PHRASEID}); + Wait(1); + jump s; + }; + t => Hangup; + i => { + Playback(custom/invalid-option); + jump s; + }; +}; + +context outbound { + // North America seven-, ten- and eleven digits + _NXXXXXX => &autodial(1732${EXTEN}); + _NXXNXXXXXX => &autodial(1${EXTEN}); + _ZNXXNXXXXX. => &autodial(${EXTEN}); + // Toll free numbers via PSTN +// _1800NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); +// _1888NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); +// _1877NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); +// _1866NXXXXXX => &checkanddial(${PSTN},${PSTNPROTO},${EXTEN},60,T); + + _011. => { //International context accessed through trunk + &trunkdial(${EXTEN}); + }; + _012. => { //fwdOUT + Set(CALLERID(name)=Central NJ); + Dial(IAX2/14301@fwdOUT/q${EXTEN:3},60,T); + }; + _013X. => { //NECC + Dial(${PSTNPROTO}/011${EXTEN:3}@${PSTN},60,T); + }; + _0131. => { //NECC to US + Dial(${PSTNPROTO}/${EXTEN:3}@${PSTN},60,T); + }; + _014. => { //TARIO by SIP ID + Set(CALLERID(name)=Sergey Okhapkin); + Set(CALLERID(number)=1400898); + Dial(${TARIOPROTO}/${EXTEN:3}@${TARIO},60,T); + }; + _0157. => { //TARIO outbound Russia + Set(CALLERID(name)=Sergey Okhapkin); + Set(CALLERID(number)=1400898); + Dial(${TARIOPROTO}/8${EXTEN:4}@${TARIO},60,T); + }; +// _015. => { //TARIO outbound international +// CALLERID(name)="Sergey Okhapkin"; +// CALLERID(number)=1400898; +// Dial(${TARIOPROTO}/810${EXTEN:3}@${TARIO},60,T); +// }; + _0161NXXNXXXXXX => { //Callpacket outbound USA/Canada + &checkanddial(${CPACKET1},${CPPROTO},${EXTEN:3},60,T); + }; + _0171NXXNXXXXXX => { //Callpacket outbound USA/Canada + &checkanddial(${CPACKET2},${CPPROTO},${EXTEN:3},60,T); + }; + _0181NXXNXXXXXX => { //sellvoip outbound USA/Canada + Dial(${SVPROTO}/${SELLVOIP}@${SELLVOIP}/${EXTEN:3},60,T); + }; + _019. => { //Voipbuster + Dial(IAX2/sokhapkin@voipbuster/00${EXTEN:3},60,T); + }; +}; + +context home { //calls from us + includes { + default; + outbound; + }; +}; + +context sunrocket-in { + 7322271653 => jump s; + 7326260100 => jump 2@default; + s => { + if("${CALLERID(number)}" = "sunrocketcom") + Set(CALLERID(number)=); + switch(${CALLERID(RDNIS)}) { + case 7326260100: + jump 2@default; + break; + case 7326260101: + jump s@default; + break; + default: + jump 1@default; + break; + }; + }; +}; + +context pstn-in { + 3 => { + if ("${CALLERID(number)}" = "7322271677") + Set(CALLERID(number)=); + jump 3@default; + }; +}; + +context tario.net-in { + _X. => { + Set(CALLERID(name)=); + if("${CALLERID(number):-11:1}" = "8") + Set(CALLERID(number)=7${CALLERID(number):1}); + if("${SIP_HEADER(To)}" = "<sip:2271677@sipnet.ru>") { + jump 3@default; + } else if("${SIP_HEADER(To)}" = "<sip:2271653@sipnet.ru>") { + jump 1@default; + } else + jump 2@default; + }; +}; + +context from-callpacket { + 8058701100 => jump 2@default; + 3103622835 => { + Answer; + Ringing; + Wait(10); + Voicemail(b3103622835); + Hangup; + }; + a => Hangup; +}; + +context fromfwdOUT { // make sure we only accept US and Canada calls, limit to 30 minutes + includes { + fromfwdOUT-catchbad; + fromfwdOUT-isgood; + fromfwdOUT-catchall; + }; +}; + +context fromfwdOUT-isgood { + _17326260100 => jump 2@default; + _17326260101 => jump s@default; + _17322271653 => jump 1@default; + _17322271677 => jump 3@default; + _1NXXNXXXXXX => { + Set(CALLERID(name)=Sergey Okhapkin); +// Set(CALLERID(number)=7326260100); +// Dial(${TRUNCPROTO}/*67${EXTEN:${TRUNKMSD}}@${TRUNK},60,,L(1800000:60000)); + Dial(${CPPROTO}/${EXTEN}@${CPACKET2},60,,L(1800000:60000)); + }; +}; + +context fromfwdOUT-catchbad { //block bahamas, etc + _1900. => congestion ; //N11 + _1XXX976. => congestion ; //N11 + _1XXX555. => congestion ; //N11 + _1X11. => congestion ; //N11 + _1867. => congestion ; //Yukon (sorry mike) + + // exten => _1NPA Country + _1242. => congestion; //BAHAMAS + _1246. => congestion; //BARBADOS + _1264. => congestion; //ANGUILLA + _1268. => congestion; //ANTIGUA/BARBUDA + _1284. => congestion; //BRITISH VIRGIN ISLANDS + _1345. => congestion; //CAYMAN ISLANDS + _1441. => congestion; //BERMUDA + _1473. => congestion; //GRENADA + _1649. => congestion; //TURKS & CAICOS ISLANDS + _1664. => congestion; //MONTSERRAT + _1758. => congestion; //ST. LUCIA + _1767. => congestion; //DOMINICA + _1784. => congestion; //ST. VINCENT & GRENADINES + _1809. => congestion; //DOMINICAN REPUBLIC + _1829. => congestion; //DOMINICAN REPUBLIC + _1868. => congestion; //TRINIDAD AND TOBAGO + _1869. => congestion; //ST. KITTS AND NEVIS + _1876. => congestion; //JAMAICA + _1787. => congestion; //Puerto Rico 787, 939 $0.07 + _1939. => congestion; //Puerto Rico 787, 939 $0.07 + _1671. => congestion; //Guam 671 $0.08 + _1340. => congestion; //U.S. Virgin Islands 340 $0.06 +}; + +context fromfwdOUT-catchall { + _X. => Congestion; + h => Hangup ; //hangup event + i => Hangup ; //invalid event + t => Hangup ; //timeout event +}; + +context ael-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; + }; + _1234 => &std-exten-ael(${EXTEN}, "IAX2"); + # => { + Playback(demo-thanks); + Hangup(); + }; + t => jump #; + i => Playback(invalid); +}; + diff --git a/pbx/ael/ael-test/ref.ael-test1 b/pbx/ael/ael-test/ref.ael-test1 new file mode 100644 index 0000000000..28d5c4bc4a --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test1 @@ -0,0 +1,11 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:3 file:pbx_ael.c line:891 func: check_dow Warning: file ./extensions.ael, line 67-67: The day (m0n) must be one of 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', or 'sat'! +LOG: lev:3 file:pbx_ael.c line:849 func: check_timerange Warning: file ./extensions.ael, line 78-78: The end time (25:00) is out of range! +LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:261 func: main 5 contexts, 13 extensions, 156 priorities diff --git a/pbx/ael/ael-test/ref.ael-test2 b/pbx/ael/ael-test/ref.ael-test2 new file mode 100644 index 0000000000..77ba08cfb1 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test2 @@ -0,0 +1,15 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./apptest.ael2, 3474 chars +LOG: lev:3 file:ael.y line:405 func: ael_yyparse ==== File: ./apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL. +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 35-35: application call to EndWhile needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 37-37: application call to ExecIf needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./apptest.ael2, line 46-46: goto: no context cont could be found that matches the goto target! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 47-47: application call to GotoIf needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 48-48: application call to GotoIfTime needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 85-85: application call to Random needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 141-141: application call to While needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 1 semantic errors were detected. It doesn't make sense to compile. +LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/ref.ael-test3 b/pbx/ael/ael-test/ref.ael-test3 new file mode 100644 index 0000000000..161fd4f5ec --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test3 @@ -0,0 +1,18 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include1.ael2, 78 chars +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include2.ael2, 98 chars +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include3.ael2, 57 chars +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include5.ael2, 56 chars +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./include4.ael2, 87 chars +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file /etc/asterisk/telemarket_torture.ael2, 28036 chars +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 5-5: expression Console/dsp has operators, but no variables. Interesting... +LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 8-8: expression "Joe-Worker" has operators, but no variables. Interesting... +LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 10-10: expression Zap/6 has operators, but no variables. Interesting... +LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:261 func: main 172 contexts, 858 extensions, 2326 priorities diff --git a/pbx/ael/ael-test/ref.ael-test4 b/pbx/ael/ael-test/ref.ael-test4 new file mode 100644 index 0000000000..77ba08cfb1 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test4 @@ -0,0 +1,15 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:ael.flex line:467 func: ael_yylex --Read in included file ./apptest.ael2, 3474 chars +LOG: lev:3 file:ael.y line:405 func: ael_yyparse ==== File: ./apptest.ael2, Line 46, Cols: 8-11: Suggestion: Use the goto statement instead of the Goto() application call in AEL. +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 35-35: application call to EndWhile needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 37-37: application call to ExecIf needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./apptest.ael2, line 46-46: goto: no context cont could be found that matches the goto target! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 47-47: application call to GotoIf needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 48-48: application call to GotoIfTime needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 85-85: application call to Random needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:3 file:pbx_ael.c line:2081 func: check_pval_item Warning: file ./apptest.ael2, line 141-141: application call to While needs to be re-written using AEL if, while, goto, etc. keywords instead! +LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 1 semantic errors were detected. It doesn't make sense to compile. +LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/ref.ael-test5 b/pbx/ael/ael-test/ref.ael-test5 new file mode 100644 index 0000000000..25ad9b9189 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test5 @@ -0,0 +1,9 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3441 func: pbx_load_module AEL load process: checked config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3443 func: pbx_load_module AEL load process: compiled config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3446 func: pbx_load_module AEL load process: merged config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3449 func: pbx_load_module AEL load process: verified config file name './extensions.ael'. +LOG: lev:4 file:ael2_parse line:261 func: main 38 contexts, 90 extensions, 484 priorities diff --git a/pbx/ael/ael-test/ref.ael-test6 b/pbx/ael/ael-test/ref.ael-test6 new file mode 100644 index 0000000000..28ff7ad051 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test6 @@ -0,0 +1,20 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:4 file:ael.flex line:193 func: ael_yylex File=./extensions.ael, line=165, column=21: Mismatched '}' in expression! +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 165, Cols: 23-23: Error: syntax error, unexpected '=', expecting ')' +LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=174, column=63: Mismatched '}' in expression! +LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=180, column=46: Mismatched '}' in expression! +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 184, Cols: 0-4: Error: syntax error, unexpected 'macro' +LOG: lev:4 file:ael.flex line:193 func: ael_yylex File=./extensions.ael, line=222, column=21: Mismatched '}' in expression! +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 222, Cols: 23-23: Error: syntax error, unexpected '=', expecting ')' +LOG: lev:4 file:ael.flex line:317 func: ael_yylex File=./extensions.ael, line=228, column=37: Mismatched '}' in expression! +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 235, Cols: 0-6: Error: syntax error, unexpected 'context' +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 344, Cols: 32-32: Error: syntax error, unexpected ';', expecting '{' +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 350, Cols: 32-32: Error: syntax error, unexpected ';', expecting '{' +LOG: lev:4 file:ael.y line:674 func: ael_yyerror ==== File: ./extensions.ael, Line 461, Cols: 10-13: Error: syntax error, unexpected 'else' +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:4 file:pbx_ael.c line:1100 func: check_goto Error: file ./extensions.ael, line 11-11: goto: no context default could be found that matches the goto target! +LOG: lev:4 file:pbx_ael.c line:2036 func: check_pval_item Error: file ./extensions.ael, line 206-206: macro call to non-existent uvm ! +LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 7 syntax errors and 2 semantic errors were detected. It doesn't make sense to compile. +LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/ref.ael-test7 b/pbx/ael/ael-test/ref.ael-test7 new file mode 100644 index 0000000000..b95eaf4983 --- /dev/null +++ b/pbx/ael/ael-test/ref.ael-test7 @@ -0,0 +1,13 @@ +Executed ast_register_file_version(); +LOG: lev:2 file:pbx_ael.c line:3428 func: pbx_load_module Starting AEL load process. +LOG: lev:2 file:pbx_ael.c line:3435 func: pbx_load_module AEL load process: calculated config file name './extensions.ael'. +LOG: lev:2 file:pbx_ael.c line:3438 func: pbx_load_module AEL load process: parsed config file name './extensions.ael'. +LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 6-6: expression Console/dsp has operators, but no variables. Interesting... +LOG: lev:3 file:pbx_ael.c line:2186 func: check_pval_item Warning: file ./extensions.ael, line 10-10: expression pstn-spa3k has operators, but no variables. Interesting... +LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 98-98: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments +LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 107-107: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments +LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 284-284: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments +LOG: lev:4 file:pbx_ael.c line:2055 func: check_pval_item Error: file ./extensions.ael, line 287-287: The macro call to checkanddial has 5 arguments, but the macro definition has 7 arguments +LOG: lev:4 file:pbx_ael.c line:2036 func: check_pval_item Error: file ./extensions.ael, line 452-452: macro call to non-existent std-exten-ael ! +LOG: lev:4 file:pbx_ael.c line:3451 func: pbx_load_module Sorry, but 0 syntax errors and 5 semantic errors were detected. It doesn't make sense to compile. +LOG: lev:4 file:ael2_parse line:261 func: main 0 contexts, 0 extensions, 0 priorities diff --git a/pbx/ael/ael-test/runtests b/pbx/ael/ael-test/runtests new file mode 100755 index 0000000000..c0d148de48 --- /dev/null +++ b/pbx/ael/ael-test/runtests @@ -0,0 +1,14 @@ +#!/bin/bash + +for i in ael-test*; do + echo -n Test: $i.................. + (cd $i; ../../../../utils/aelparse -n -d | grep -v -i 'seconds' > ../res.$i) + if (diff -q res.$i ref.$i > /dev/null 2>&1 ) then + echo PASSED + rm res.$i + else + echo %%%%%%FAILED%%%%%% + diff -u ref.$i res.$i + fi + +done diff --git a/pbx/ael/ael-test/setref b/pbx/ael/ael-test/setref new file mode 100755 index 0000000000..b483f05ae1 --- /dev/null +++ b/pbx/ael/ael-test/setref @@ -0,0 +1,7 @@ +#!/bin/bash + +for i in res.*; do + refname=`echo $i | sed 's/^res/ref/'` + echo $refname + mv $i $refname +done diff --git a/pbx/ael/ael.flex b/pbx/ael/ael.flex new file mode 100644 index 0000000000..bcc2cf90e3 --- /dev/null +++ b/pbx/ael/ael.flex @@ -0,0 +1,633 @@ +%{ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy <murf@parsetree.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ +/*! \file + * + * \brief Flex scanner description of tokens used in AEL2 . + * + */#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#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 (struct parse_io *); +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; + } + +<paren>[^()\[\]\{\}]*\) {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; + } + } + +<paren>[^()\[\]\{\}]*\( {yylloc->first_line = my_lineno; yylloc->first_column=my_col; + parencount++; pbcpush('('); + yymore(); + } +<paren>[^()\[\]\{\}]*\[ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +<paren>[^()\[\]\{\}]*\] {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(); + } +<paren>[^()\[\]\{\}]*\{ {yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{'); } +<paren>[^()\[\]\{\}]*\} {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(); + } + + +<argg>[^(),\{\}\[\]]*\) {/* 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; + } + } + } +<argg>[^(),\{\}\[\]]*\( { /* printf("ARGG:%s\n",yytext); */ + /* printf("GOT AN LP!!!\n"); */ + yylloc->first_line = my_lineno; + yylloc->first_column=my_col; + parencount++; + pbcpush('('); + yymore(); + } + +<argg>[^(),\{\}\[\]]*\, { /* 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; + } + } + } + +<argg>[^(),\{\}\[\]]*\{ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; pbcpush('{'); yymore(); } +<argg>[^(),\{\}\[\]]*\} {/*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(); + } +<argg>[^(),\{\}\[\]]*\[ {/*printf("ARGG:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +<argg>[^(),\{\}\[\]]*\] {/*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(); + } + + +<semic>[^;()\{\}\[\]]*\[ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('['); } +<semic>[^;()\{\}\[\]]*\] {/*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();} +<semic>[^;()\{\}\[\]]*\{ {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('{');} +<semic>[^;()\{\}\[\]]*\} {/*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();} +<semic>[^;()\{\}\[\]]*\( {/*printf("SEMIC:%s\n",yytext);*/yylloc->first_line = my_lineno;yylloc->first_column=my_col; yymore(); pbcpush('(');} +<semic>[^;()\{\}\[\]]*\) {/*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();} +<semic>[^;()\{\}\[\]]*; { + 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; + strncpy(fnamebuf,p1,p2-p1); + fnamebuf[p2-p1] = 0; + for (i=0; i<include_stack_index; i++) { + if ( !strcmp(fnamebuf,include_stack[i].fname )) { + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Nice Try!!! But %s has already been included (perhaps by another file), and would cause an infinite loop of file inclusions!!! Include directive ignored\n", + my_file, my_lineno, my_col, fnamebuf); + found=1; + break; + } + } + if( !found ) + { + *p2 = 0; + /* relative vs. absolute */ + if ( *(p1+1) != '/' ) + { + strcpy(fnamebuf,ast_config_AST_CONFIG_DIR); + strcat(fnamebuf,"/"); + strcat(fnamebuf,p1+1); + } + else + strcpy(fnamebuf,p1+1); + in1 = fopen( fnamebuf, "r" ); + if ( ! in1 ) { + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Couldn't find the include file: %s; ignoring the Include directive!\n", my_file, my_lineno, my_col, fnamebuf); + } else { + char *buffer; + struct stat stats; + stat(fnamebuf, &stats); + buffer = (char*)malloc(stats.st_size+1); + fread(buffer, 1, stats.st_size, in1); + buffer[stats.st_size] = 0; + ast_log(LOG_NOTICE," --Read in included file %s, %d chars\n",fnamebuf, (int)stats.st_size); + fclose(in1); + + include_stack[include_stack_index].fname = my_file; + my_file = strdup(fnamebuf); + include_stack[include_stack_index].lineno = my_lineno; + include_stack[include_stack_index].colno = my_col+yyleng; + include_stack[include_stack_index++].bufstate = YY_CURRENT_BUFFER; + + yy_switch_to_buffer(ael_yy_scan_string (buffer ,yyscanner),yyscanner); + free(buffer); + my_lineno = 1; + my_col = 1; + BEGIN(INITIAL); + } + } + } + } + } + +<<EOF>> { + 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); +} + + +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_yydebug; */ + + io = calloc(sizeof(struct parse_io),1); + /* reset the global counters */ + prev_word = 0; + my_lineno = 1; + include_stack_index=0; + my_col = 0; + /* ael_yydebug = 1; */ + ael_yylex_init(&io->scanner); + fin = fopen(filename,"r"); + if ( !fin ) { + ast_log(LOG_ERROR,"File %s could not be opened\n", filename); + *errors = 1; + return 0; + } + 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(io); + + + pval = io->pval; + *errors = io->syntax_error_count; + + ael_yylex_destroy(io->scanner); + free(buffer); + free(io); + + return pval; +} diff --git a/pbx/ael/ael.tab.c b/pbx/ael/ael.tab.c new file mode 100644 index 0000000000..4f00b05a61 --- /dev/null +++ b/pbx/ael/ael.tab.c @@ -0,0 +1,3192 @@ +/* A Bison parser, made by GNU Bison 2.1. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, 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 + +/* Bison version. */ +#define YYBISON_VERSION "2.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 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 +/* Tokens. */ +#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 <murf@parsetree.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ +/*! \file + * + * \brief Bison Grammar description of AEL2. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#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 YYLEX_PARAM ((struct parse_io *)parseio)->scanner +#define YYERROR_VERBOSE 1 + +extern char *my_file; +#ifdef AAL_ARGCHECK +int ael_is_funcname(char *name); +#endif + 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 + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 47 "ael.y" +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +/* Line 196 of yacc.c. */ +#line 225 "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 52 "ael.y" + + /* declaring these AFTER the union makes things a lot simpler! */ +void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s); +int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); + + + +/* Line 219 of yacc.c. */ +#line 255 "ael.tab.c" + +#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) && (defined (__STDC__) || defined (__cplusplus)) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* 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 +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYINCLUDED_STDLIB_H +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# endif +# ifdef __cplusplus +extern "C" { +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifdef __cplusplus +} +# endif +# 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 \ + { \ + 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 17 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 584 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 42 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 52 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 151 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 354 + +/* 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 int 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, 138, 141, 144, 146, 148, 150, + 152, 154, 155, 161, 164, 166, 171, 175, 180, 188, + 197, 199, 202, 205, 206, 212, 213, 219, 234, 245, + 247, 250, 252, 255, 259, 261, 264, 268, 269, 276, + 280, 281, 287, 291, 295, 298, 299, 300, 301, 314, + 315, 322, 325, 329, 333, 336, 339, 340, 346, 349, + 352, 355, 358, 363, 366, 371, 374, 379, 381, 383, + 387, 391, 397, 403, 409, 415, 417, 421, 427, 431, + 437, 441, 442, 448, 452, 453, 457, 461, 464, 466, + 467, 471, 474, 476, 479, 484, 488, 493, 497, 500, + 504, 506, 509, 511, 517, 522, 526, 531, 535, 538, + 542, 545, 548, 563, 574, 578, 594, 606, 609, 611, + 613, 618 +}; + +/* 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, 86, 5, -1, 15, 41, + 6, 52, 7, 4, 5, -1, 15, 41, 6, 7, + 4, 86, 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, 1, -1, 53, 54, + -1, 53, 1, -1, 57, -1, 93, -1, 88, -1, + 89, -1, 56, -1, -1, 41, 9, 55, 41, 8, + -1, 41, 1, -1, 8, -1, 17, 24, 41, 8, + -1, 41, 24, 69, -1, 30, 41, 24, 69, -1, + 31, 6, 65, 7, 41, 24, 69, -1, 30, 31, + 6, 65, 7, 41, 24, 69, -1, 69, -1, 58, + 69, -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, 41, + -1, 41, 41, -1, 41, 11, 41, -1, -1, 18, + 6, 68, 41, 7, 4, -1, 4, 58, 5, -1, + -1, 41, 9, 70, 41, 8, -1, 25, 76, 8, + -1, 26, 77, 8, -1, 41, 11, -1, -1, -1, + -1, 32, 6, 71, 41, 8, 72, 41, 8, 73, + 41, 7, 69, -1, -1, 33, 6, 74, 41, 7, + 69, -1, 67, 5, -1, 67, 84, 5, -1, 12, + 78, 8, -1, 82, 8, -1, 41, 8, -1, -1, + 82, 9, 75, 41, 8, -1, 28, 8, -1, 27, + 8, -1, 29, 8, -1, 61, 69, -1, 61, 69, + 21, 69, -1, 59, 69, -1, 59, 69, 21, 69, + -1, 63, 69, -1, 63, 69, 21, 69, -1, 8, + -1, 66, -1, 66, 13, 66, -1, 66, 10, 66, + -1, 66, 13, 66, 13, 66, -1, 66, 10, 66, + 10, 66, -1, 36, 13, 66, 13, 66, -1, 36, + 10, 66, 10, 66, -1, 66, -1, 66, 10, 66, + -1, 66, 10, 41, 14, 41, -1, 66, 14, 66, + -1, 66, 10, 41, 14, 36, -1, 66, 14, 36, + -1, -1, 41, 6, 79, 83, 7, -1, 41, 6, + 7, -1, -1, 41, 81, 6, -1, 80, 83, 7, + -1, 80, 7, -1, 64, -1, -1, 83, 10, 41, + -1, 83, 10, -1, 85, -1, 84, 85, -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, 87, -1, 86, 87, -1, 69, + -1, 37, 41, 4, 58, 5, -1, 38, 4, 90, + 5, -1, 38, 4, 5, -1, 39, 4, 90, 5, + -1, 39, 4, 5, -1, 41, 8, -1, 90, 41, + 8, -1, 90, 1, -1, 92, 8, -1, 92, 13, + 65, 11, 65, 11, 65, 13, 65, 13, 65, 13, + 65, 8, -1, 92, 13, 41, 13, 65, 13, 65, + 13, 65, 8, -1, 91, 92, 8, -1, 91, 92, + 13, 65, 11, 65, 11, 65, 13, 65, 13, 65, + 13, 65, 8, -1, 91, 92, 13, 41, 13, 65, + 13, 65, 13, 65, 8, -1, 91, 1, -1, 41, + -1, 36, -1, 40, 4, 91, 5, -1, 40, 4, + 5, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 126, 126, 129, 130, 133, 136, 137, 138, 139, + 142, 143, 144, 145, 146, 147, 148, 149, 152, 154, + 155, 156, 159, 160, 163, 164, 165, 168, 168, 171, + 172, 173, 176, 177, 178, 181, 184, 185, 186, 187, + 188, 189, 189, 190, 191, 194, 197, 198, 199, 200, + 204, 205, 208, 211, 211, 214, 214, 217, 236, 255, + 256, 258, 259, 260, 263, 264, 265, 268, 268, 273, + 274, 274, 277, 278, 279, 280, 281, 282, 280, 285, + 285, 288, 289, 290, 291, 292, 294, 294, 327, 328, + 329, 330, 331, 332, 333, 334, 335, 336, 339, 340, + 343, 346, 351, 356, 361, 368, 371, 374, 379, 384, + 389, 396, 396, 399, 402, 402, 411, 417, 420, 421, + 422, 423, 426, 427, 432, 433, 434, 435, 436, 437, + 440, 441, 446, 447, 450, 451, 454, 455, 458, 459, + 460, 463, 464, 485, 498, 499, 519, 532, 535, 536, + 539, 540 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[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", "goto_word", + "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 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, 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, 53, 54, 54, 54, 54, + 54, 55, 54, 54, 54, 56, 57, 57, 57, 57, + 58, 58, 58, 60, 59, 62, 61, 63, 63, 64, + 64, 65, 65, 65, 66, 66, 66, 68, 67, 69, + 70, 69, 69, 69, 69, 71, 72, 73, 69, 74, + 69, 69, 69, 69, 69, 69, 75, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 76, 76, + 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, + 77, 79, 78, 78, 81, 80, 82, 82, 83, 83, + 83, 83, 84, 84, 85, 85, 85, 85, 85, 85, + 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, + 90, 91, 91, 91, 91, 91, 91, 91, 92, 92, + 93, 93 +}; + +/* 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, 1, 2, 2, 1, 1, 1, 1, + 1, 0, 5, 2, 1, 4, 3, 4, 7, 8, + 1, 2, 2, 0, 5, 0, 5, 14, 10, 1, + 2, 1, 2, 3, 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, 33, + 13, 44, 0, 0, 0, 0, 0, 0, 0, 0, + 32, 40, 36, 38, 39, 37, 11, 0, 0, 29, + 0, 27, 26, 22, 25, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 43, 41, 0, 35, 12, 34, + 10, 0, 31, 0, 0, 0, 17, 0, 15, 0, + 0, 0, 0, 61, 0, 135, 0, 0, 137, 0, + 151, 149, 148, 0, 0, 0, 0, 97, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 114, 0, 0, 0, 0, 46, 119, 0, 21, 0, + 132, 0, 130, 0, 30, 0, 16, 14, 45, 0, + 47, 62, 0, 138, 140, 134, 0, 136, 147, 150, + 0, 141, 0, 0, 0, 50, 0, 0, 67, 53, + 0, 55, 0, 64, 98, 0, 105, 0, 89, 88, + 90, 75, 79, 85, 70, 74, 0, 93, 91, 95, + 81, 0, 0, 0, 0, 122, 117, 59, 118, 0, + 84, 86, 0, 20, 131, 19, 0, 28, 0, 63, + 0, 139, 144, 0, 61, 0, 42, 52, 69, 51, + 111, 83, 0, 0, 61, 0, 0, 0, 0, 0, + 65, 0, 0, 72, 0, 0, 73, 0, 0, 0, + 115, 0, 0, 0, 0, 0, 128, 82, 123, 60, + 116, 121, 0, 0, 18, 0, 0, 61, 0, 0, + 0, 113, 119, 0, 0, 0, 0, 0, 0, 0, + 66, 100, 99, 64, 106, 110, 108, 0, 0, 0, + 94, 92, 96, 127, 129, 0, 120, 0, 0, 0, + 48, 0, 0, 0, 0, 0, 0, 54, 0, 0, + 56, 0, 0, 0, 0, 0, 76, 0, 71, 0, + 0, 87, 133, 49, 0, 0, 0, 0, 112, 68, + 0, 0, 104, 103, 102, 101, 109, 107, 0, 80, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 143, 0, 58, 0, 0, 146, 0, + 0, 0, 0, 0, 0, 0, 78, 0, 0, 0, + 0, 142, 57, 145 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 6, 7, 8, 9, 10, 11, 25, 26, 75, + 50, 39, 40, 95, 41, 42, 144, 111, 203, 112, + 206, 113, 178, 84, 154, 114, 202, 145, 219, 217, + 308, 330, 218, 232, 155, 157, 147, 242, 116, 166, + 117, 179, 174, 175, 121, 122, 43, 44, 87, 93, + 94, 45 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -215 +static const short int yypact[] = +{ + 212, 127, -215, -35, 55, 23, 85, 561, -215, -215, + -215, -215, 64, 118, 112, 13, 128, -215, -215, -215, + 157, 208, 2, -215, 123, 19, -215, 130, 137, -215, + -215, -215, 143, 43, 169, 181, 182, 189, 126, 284, + -215, -215, -215, -215, -215, -215, -215, 337, 196, -215, + 141, -215, -215, -215, -215, 342, 357, 135, 188, 177, + 170, 22, 36, 29, -215, -215, 527, -215, -215, -215, + -215, 423, -215, 206, 191, 195, -215, 384, -215, 399, + 210, 170, 527, 200, 215, -215, 242, 51, -215, 57, + -215, -215, -215, 12, 158, 220, 527, -215, 223, 245, + 250, 259, 262, 148, 229, 263, 265, 266, 269, 275, + 251, 527, 527, 527, 156, -215, 26, 145, -215, 243, + -215, 449, -215, 475, -215, 279, -215, -215, -215, 281, + -215, 252, 253, -215, -215, -215, 283, -215, -215, -215, + 204, -215, 254, 291, 278, -215, 296, 300, -215, -215, + 276, -215, 69, 40, 95, 310, 114, 313, -215, -215, + -215, -215, -215, -215, -215, -215, 323, 311, 318, 325, + -215, 290, 303, 340, 172, -215, -215, 307, -215, 230, + -215, -215, 348, -215, -215, -215, 501, -215, 312, -215, + 331, -215, -215, 315, 58, 346, -215, -215, -215, -215, + 353, -215, 320, 322, 76, 355, 322, 229, 229, 328, + -215, 229, 229, -215, 329, 178, -215, 330, 338, 343, + -215, 527, 527, 527, 375, 379, 527, -215, -215, -215, + -215, 350, 352, 527, -215, 370, 527, 108, 388, 170, + 170, -215, 322, 395, 396, 170, 170, 398, 354, 393, + -215, 400, 404, 50, -215, -215, -215, 401, 405, 403, + -215, -215, -215, 527, 527, 3, -215, 410, 308, 527, + -215, 170, 170, 406, 397, 235, 409, -215, 407, 415, + -215, 229, 229, 229, 229, 190, -215, 527, -215, 68, + 111, -215, -215, -215, 408, 421, 170, 170, -215, -215, + 170, 170, -215, -215, -215, -215, -215, -215, 392, -215, + 170, 170, 431, 433, 434, 445, 426, 446, 450, 170, + 170, 170, 170, -215, 170, 170, 428, 452, 455, 453, + 429, 464, 460, -215, 170, -215, 170, 477, -215, 170, + 472, 476, 527, 478, 170, 170, -215, 170, 480, 485, + 488, -215, -215, -215 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short int yypgoto[] = +{ + -215, -215, -215, 491, -215, -215, -215, -215, 474, -215, + -215, 104, -37, -215, -215, -215, -214, -215, -215, -215, + -215, -215, 60, -67, -101, -215, -215, -66, -215, -215, + -215, -215, -215, -215, -215, -215, -215, -215, -215, -215, + -215, 268, -215, 341, 391, -120, -215, -215, 456, -215, + 418, -215 +}; + +/* 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 -127 +static const short int yytable[] = +{ + 115, 184, 69, 156, 197, 120, 14, 96, -125, 48, + 69, 97, 265, 138, 129, 98, 130, 139, 23, 268, + 52, 99, 100, 101, 53, 102, 16, 85, 103, 104, + 105, 106, 107, 176, 90, 108, 109, -125, -125, -125, + 69, 88, 69, 49, 110, 167, 168, 169, 91, 289, + 290, 209, 134, 92, 24, 120, 135, 120, 134, 15, + 24, 209, 137, 86, 285, 91, 184, 177, 20, 197, + 92, 239, 96, -124, 58, 195, 97, 86, 199, 207, + 98, 210, 208, 205, 59, 17, 99, 100, 101, 245, + 102, 210, 136, 103, 104, 105, 106, 107, 136, 131, + 108, 109, -124, -124, -124, 211, 248, 249, 212, 110, + 251, 252, 197, 254, 256, 96, -126, 131, 22, 97, + 120, 271, 21, 98, 214, 47, 238, 64, 215, 99, + 100, 101, 51, 102, 55, 65, 103, 104, 105, 106, + 107, 56, 72, 108, 109, -126, -126, -126, 73, 131, + 66, 74, 110, 180, 181, 260, 261, 262, 29, 77, + 79, 170, 30, 12, 27, 31, 141, 57, 13, 28, + 270, 142, 273, 274, 32, 60, 80, 227, 278, 279, + 302, 303, 304, 305, 152, 61, 62, 33, 34, 153, + 171, 172, 173, 63, 81, 35, 36, 37, 38, 199, + 71, 82, 199, 293, 294, 295, 171, 172, 173, 29, + 123, 83, 192, 46, 255, 1, 31, 193, 128, 153, + 2, 309, 132, 199, 199, 32, 306, 3, 4, 312, + 313, 307, 124, 314, 315, 5, 125, 230, 33, 34, + 231, 131, 298, 317, 318, 231, 35, 36, 37, 38, + 133, 148, 326, 327, 328, 329, 149, 331, 332, 163, + 164, 143, 165, 244, 146, 150, 247, 340, 151, 341, + 153, 158, 343, 159, 160, 161, 346, 348, 349, 197, + 350, 162, 96, 198, 182, 67, 97, 187, 188, 68, + 98, 191, 31, 189, 190, 194, 99, 100, 101, 196, + 102, 32, 200, 103, 104, 105, 106, 107, 201, 197, + 108, 109, 96, 292, 33, 34, 97, 204, 213, 110, + 98, 216, 35, 36, 37, 38, 99, 100, 101, 220, + 102, 224, 221, 103, 104, 105, 106, 107, 67, 222, + 108, 109, 70, 29, 225, 31, 223, 76, 229, 110, + 31, 226, 233, 235, 32, 236, 237, 240, 29, 32, + 241, 243, 78, 177, 281, 31, 246, 33, 34, 250, + 253, 257, 33, 34, 32, 35, 36, 37, 38, 258, + 35, 36, 37, 38, 259, 67, 263, 33, 34, 126, + 264, 266, 31, 267, 269, 35, 36, 37, 38, 272, + 67, 32, 276, 277, 127, 280, 282, 31, 297, 286, + 283, 288, 287, 299, 33, 34, 32, 284, 291, 296, + 300, 310, 35, 36, 37, 38, 301, 96, 118, 33, + 34, 97, 311, 316, 323, 98, 333, 35, 36, 37, + 38, 99, 100, 101, 319, 102, 320, 321, 103, 104, + 105, 106, 107, 96, 183, 108, 109, 97, 322, 324, + 119, 98, 335, 325, 110, 334, 336, 99, 100, 101, + 337, 102, 338, 339, 103, 104, 105, 106, 107, 96, + 185, 108, 109, 97, 342, 344, 119, 98, 351, 345, + 110, 347, 352, 99, 100, 101, 353, 102, 19, 54, + 103, 104, 105, 106, 107, 96, 234, 108, 109, 97, + 275, 140, 119, 98, 186, 228, 110, 0, 89, 99, + 100, 101, 0, 102, 0, 0, 103, 104, 105, 106, + 107, 96, 0, 108, 109, 97, 0, 0, 119, 98, + 0, 0, 110, 0, 0, 99, 100, 101, 0, 102, + 0, 0, 103, 104, 105, 106, 107, 0, 0, 108, + 109, -2, 18, 0, 1, 0, 0, 0, 110, 2, + 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, + 0, 0, 0, 0, 5 +}; + +static const short int yycheck[] = +{ + 66, 121, 39, 104, 1, 71, 41, 4, 5, 7, + 47, 8, 226, 1, 81, 12, 82, 5, 5, 233, + 1, 18, 19, 20, 5, 22, 3, 5, 25, 26, + 27, 28, 29, 7, 5, 32, 33, 34, 35, 36, + 77, 5, 79, 41, 41, 111, 112, 113, 36, 263, + 264, 11, 1, 41, 41, 121, 5, 123, 1, 4, + 41, 11, 5, 41, 14, 36, 186, 41, 4, 1, + 41, 13, 4, 5, 31, 142, 8, 41, 144, 10, + 12, 41, 13, 150, 41, 0, 18, 19, 20, 13, + 22, 41, 41, 25, 26, 27, 28, 29, 41, 41, + 32, 33, 34, 35, 36, 10, 207, 208, 13, 41, + 211, 212, 1, 214, 215, 4, 5, 41, 6, 8, + 186, 13, 4, 12, 10, 21, 193, 1, 14, 18, + 19, 20, 9, 22, 4, 9, 25, 26, 27, 28, + 29, 4, 1, 32, 33, 34, 35, 36, 7, 41, + 24, 10, 41, 8, 9, 221, 222, 223, 1, 55, + 56, 5, 5, 36, 36, 8, 8, 24, 41, 41, + 236, 13, 239, 240, 17, 6, 41, 5, 245, 246, + 281, 282, 283, 284, 36, 4, 4, 30, 31, 41, + 34, 35, 36, 4, 6, 38, 39, 40, 41, 265, + 4, 24, 268, 269, 271, 272, 34, 35, 36, 1, + 4, 41, 8, 5, 36, 3, 8, 13, 8, 41, + 8, 287, 7, 289, 290, 17, 36, 15, 16, 296, + 297, 41, 41, 300, 301, 23, 41, 7, 30, 31, + 10, 41, 7, 310, 311, 10, 38, 39, 40, 41, + 8, 6, 319, 320, 321, 322, 6, 324, 325, 8, + 9, 41, 11, 203, 41, 6, 206, 334, 6, 336, + 41, 8, 339, 8, 8, 6, 342, 344, 345, 1, + 347, 6, 4, 5, 41, 1, 8, 8, 7, 5, + 12, 8, 8, 41, 41, 41, 18, 19, 20, 8, + 22, 17, 6, 25, 26, 27, 28, 29, 8, 1, + 32, 33, 4, 5, 30, 31, 8, 41, 8, 41, + 12, 8, 38, 39, 40, 41, 18, 19, 20, 6, + 22, 41, 21, 25, 26, 27, 28, 29, 1, 21, + 32, 33, 5, 1, 41, 8, 21, 5, 41, 41, + 8, 11, 4, 41, 17, 24, 41, 11, 1, 17, + 7, 41, 5, 41, 10, 8, 11, 30, 31, 41, + 41, 41, 30, 31, 17, 38, 39, 40, 41, 41, + 38, 39, 40, 41, 41, 1, 11, 30, 31, 5, + 11, 41, 8, 41, 24, 38, 39, 40, 41, 11, + 1, 17, 7, 7, 5, 7, 13, 8, 11, 8, + 10, 8, 7, 4, 30, 31, 17, 13, 8, 13, + 13, 13, 38, 39, 40, 41, 11, 4, 5, 30, + 31, 8, 11, 41, 8, 12, 8, 38, 39, 40, + 41, 18, 19, 20, 13, 22, 13, 13, 25, 26, + 27, 28, 29, 4, 5, 32, 33, 8, 13, 13, + 37, 12, 7, 13, 41, 13, 13, 18, 19, 20, + 41, 22, 8, 13, 25, 26, 27, 28, 29, 4, + 5, 32, 33, 8, 7, 13, 37, 12, 8, 13, + 41, 13, 7, 18, 19, 20, 8, 22, 7, 25, + 25, 26, 27, 28, 29, 4, 5, 32, 33, 8, + 242, 93, 37, 12, 123, 174, 41, -1, 62, 18, + 19, 20, -1, 22, -1, -1, 25, 26, 27, 28, + 29, 4, -1, 32, 33, 8, -1, -1, 37, 12, + -1, -1, 41, -1, -1, 18, 19, 20, -1, 22, + -1, -1, 25, 26, 27, 28, 29, -1, -1, 32, + 33, 0, 1, -1, 3, -1, -1, -1, 41, 8, + -1, -1, -1, -1, -1, -1, 15, 16, -1, -1, + -1, -1, -1, -1, 23 +}; + +/* 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, 1, + 5, 8, 17, 30, 31, 38, 39, 40, 41, 53, + 54, 56, 57, 88, 89, 93, 5, 53, 7, 41, + 52, 9, 1, 5, 50, 4, 4, 24, 31, 41, + 6, 4, 4, 4, 1, 9, 24, 1, 5, 54, + 5, 4, 1, 7, 10, 51, 5, 53, 5, 53, + 41, 6, 24, 41, 65, 5, 41, 90, 5, 90, + 5, 36, 41, 91, 92, 55, 4, 8, 12, 18, + 19, 20, 22, 25, 26, 27, 28, 29, 32, 33, + 41, 59, 61, 63, 67, 69, 80, 82, 5, 37, + 69, 86, 87, 4, 41, 41, 5, 5, 8, 65, + 69, 41, 7, 8, 1, 5, 41, 5, 1, 5, + 92, 8, 13, 41, 58, 69, 41, 78, 6, 6, + 6, 6, 36, 41, 66, 76, 66, 77, 8, 8, + 8, 6, 6, 8, 9, 11, 81, 69, 69, 69, + 5, 34, 35, 36, 84, 85, 7, 41, 64, 83, + 8, 9, 41, 5, 87, 5, 86, 8, 7, 41, + 41, 8, 8, 13, 41, 65, 8, 1, 5, 69, + 6, 8, 68, 60, 41, 65, 62, 10, 13, 11, + 41, 10, 13, 8, 10, 14, 8, 71, 74, 70, + 6, 21, 21, 21, 41, 41, 11, 5, 85, 41, + 7, 10, 75, 4, 5, 41, 24, 41, 65, 13, + 11, 7, 79, 41, 64, 13, 11, 64, 66, 66, + 41, 66, 66, 41, 66, 36, 66, 41, 41, 41, + 69, 69, 69, 11, 11, 58, 41, 41, 58, 24, + 69, 13, 11, 65, 65, 83, 7, 7, 65, 65, + 7, 10, 13, 10, 13, 14, 8, 7, 8, 58, + 58, 8, 5, 69, 65, 65, 13, 11, 7, 4, + 13, 11, 66, 66, 66, 66, 36, 41, 72, 69, + 13, 11, 65, 65, 65, 65, 41, 65, 65, 13, + 13, 13, 13, 8, 13, 13, 65, 65, 65, 65, + 73, 65, 65, 8, 13, 7, 13, 41, 8, 13, + 65, 65, 7, 65, 13, 13, 69, 13, 65, 65, + 65, 8, 7, 8 +}; + +#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, parseio, YY_("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 <stdio.h> /* 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 long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", + 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 + YYSTACK_ALLOC_MAXIMUM < 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 +{ + 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 +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + size_t yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# 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); + YYFPRINTF (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) + { + case 41: /* "word" */ +#line 121 "ael.y" + { free((yyvaluep->str));}; +#line 1309 "ael.tab.c" + break; + case 44: /* "objects" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1314 "ael.tab.c" + break; + case 45: /* "object" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1319 "ael.tab.c" + break; + case 46: /* "context" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1324 "ael.tab.c" + break; + case 47: /* "macro" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1329 "ael.tab.c" + break; + case 48: /* "globals" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1334 "ael.tab.c" + break; + case 49: /* "global_statements" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1339 "ael.tab.c" + break; + case 50: /* "global_statement" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1344 "ael.tab.c" + break; + case 52: /* "arglist" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1349 "ael.tab.c" + break; + case 53: /* "elements" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1354 "ael.tab.c" + break; + case 54: /* "element" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1359 "ael.tab.c" + break; + case 56: /* "ignorepat" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1364 "ael.tab.c" + break; + case 57: /* "extension" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1369 "ael.tab.c" + break; + case 58: /* "statements" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1374 "ael.tab.c" + break; + case 59: /* "if_head" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1379 "ael.tab.c" + break; + case 61: /* "random_head" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1384 "ael.tab.c" + break; + case 63: /* "iftime_head" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1389 "ael.tab.c" + break; + case 64: /* "word_list" */ +#line 121 "ael.y" + { free((yyvaluep->str));}; +#line 1394 "ael.tab.c" + break; + case 65: /* "word3_list" */ +#line 121 "ael.y" + { free((yyvaluep->str));}; +#line 1399 "ael.tab.c" + break; + case 66: /* "goto_word" */ +#line 121 "ael.y" + { free((yyvaluep->str));}; +#line 1404 "ael.tab.c" + break; + case 67: /* "switch_head" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1409 "ael.tab.c" + break; + case 69: /* "statement" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1414 "ael.tab.c" + break; + case 76: /* "target" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1419 "ael.tab.c" + break; + case 77: /* "jumptarget" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1424 "ael.tab.c" + break; + case 78: /* "macro_call" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1429 "ael.tab.c" + break; + case 80: /* "application_call_head" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1434 "ael.tab.c" + break; + case 82: /* "application_call" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1439 "ael.tab.c" + break; + case 83: /* "eval_arglist" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1444 "ael.tab.c" + break; + case 84: /* "case_statements" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1449 "ael.tab.c" + break; + case 85: /* "case_statement" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1454 "ael.tab.c" + break; + case 86: /* "macro_statements" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1459 "ael.tab.c" + break; + case 87: /* "macro_statement" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1464 "ael.tab.c" + break; + case 88: /* "switches" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1469 "ael.tab.c" + break; + case 89: /* "eswitches" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1474 "ael.tab.c" + break; + case 90: /* "switchlist" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1479 "ael.tab.c" + break; + case 91: /* "includeslist" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1484 "ael.tab.c" + break; + case 92: /* "includedname" */ +#line 121 "ael.y" + { free((yyvaluep->str));}; +#line 1489 "ael.tab.c" + break; + case 93: /* "includes" */ +#line 118 "ael.y" + { if (yymsg[0] != 'C') {destroy_pval((yyvaluep->pval)); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} }; +#line 1494 "ael.tab.c" + break; + + 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 (struct parse_io *parseio); +#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 (struct parse_io *parseio) +#else +int +yyparse (parseio) + struct parse_io *parseio; +#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; + + int yystate; + 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; + short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + 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 + + 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 (YY_("memory exhausted"), + &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 yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + 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 126 "ael.y" + { (yyval.pval) = parseio->pval = (yyvsp[0].pval); ;} + break; + + case 3: +#line 129 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 4: +#line 130 "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 5: +#line 133 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 6: +#line 136 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 7: +#line 137 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 8: +#line 138 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 9: +#line 139 "ael.y" + {(yyval.pval)=0;/* allow older docs to be read */;} + break; + + case 10: +#line 142 "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 143 "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 144 "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 145 "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 146 "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 147 "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 148 "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 149 "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 152 "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 154 "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 155 "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 156 "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 159 "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 160 "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 163 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 25: +#line 164 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval); linku1((yyval.pval),(yyvsp[0].pval));;} + break; + + case 26: +#line 165 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 27: +#line 168 "ael.y" + { reset_semicount(parseio->scanner); ;} + break; + + case 28: +#line 168 "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 171 "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 172 "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 31: +#line 173 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 32: +#line 176 "ael.y" + { (yyval.pval)=(yyvsp[0].pval);;} + break; + + case 33: +#line 177 "ael.y" + {(yyval.pval)=0;;} + break; + + case 34: +#line 178 "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 35: +#line 181 "ael.y" + { (yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 36: +#line 184 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 37: +#line 185 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 38: +#line 186 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 39: +#line 187 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 40: +#line 188 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 41: +#line 189 "ael.y" + { reset_semicount(parseio->scanner); ;} + break; + + case 42: +#line 189 "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 43: +#line 190 "ael.y" + {free((yyvsp[-1].str)); (yyval.pval)=0;;} + break; + + case 44: +#line 191 "ael.y" + {(yyval.pval)=0;/* allow older docs to be read */;} + break; + + case 45: +#line 194 "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 46: +#line 197 "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 47: +#line 198 "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 48: +#line 199 "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 49: +#line 200 "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 50: +#line 204 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 51: +#line 205 "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 52: +#line 208 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 53: +#line 211 "ael.y" + { reset_parencount(parseio->scanner); ;} + break; + + case 54: +#line 211 "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 55: +#line 214 "ael.y" + { reset_parencount(parseio->scanner); ;} + break; + + case 56: +#line 214 "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 57: +#line 217 "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 58: +#line 236 "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 59: +#line 255 "ael.y" + { (yyval.str) = (yyvsp[0].str);;} + break; + + case 60: +#line 256 "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 258 "ael.y" + { (yyval.str) = (yyvsp[0].str);;} + break; + + case 62: +#line 259 "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 63: +#line 260 "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 64: +#line 263 "ael.y" + { (yyval.str) = (yyvsp[0].str);;} + break; + + case 65: +#line 264 "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));;} + break; + + case 66: +#line 265 "ael.y" + { (yyval.str) = (char*)malloc(strlen((yyvsp[-2].str))+strlen((yyvsp[0].str))+2); strcpy((yyval.str), (yyvsp[-2].str)); strcat((yyval.str),":"); strcat((yyval.str), (yyvsp[0].str)); free((yyvsp[-2].str)); free((yyvsp[0].str));;} + break; + + case 67: +#line 268 "ael.y" + { reset_parencount(parseio->scanner); ;} + break; + + case 68: +#line 269 "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 69: +#line 273 "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 70: +#line 274 "ael.y" + {reset_semicount(parseio->scanner);;} + break; + + case 71: +#line 275 "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 72: +#line 277 "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 73: +#line 278 "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 74: +#line 279 "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 75: +#line 280 "ael.y" + {reset_semicount(parseio->scanner);;} + break; + + case 76: +#line 281 "ael.y" + {reset_semicount(parseio->scanner);;} + break; + + case 77: +#line 282 "ael.y" + {reset_parencount(parseio->scanner);;} + break; + + case 78: +#line 283 "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 79: +#line 285 "ael.y" + {reset_parencount(parseio->scanner);;} + break; + + case 80: +#line 286 "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 81: +#line 288 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);(yyval.pval)->endline = (yylsp[0]).last_line; (yyval.pval)->endcol = (yylsp[0]).last_column;;} + break; + + case 82: +#line 289 "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 83: +#line 290 "ael.y" + {(yyval.pval) = (yyvsp[-1].pval);(yyval.pval)->endline = (yylsp[-1]).last_line; (yyval.pval)->endcol = (yylsp[-1]).last_column;;} + break; + + case 84: +#line 291 "ael.y" + { (yyval.pval) = (yyvsp[-1].pval);(yyval.pval)->endline = (yylsp[0]).last_line; (yyval.pval)->endcol = (yylsp[0]).last_column;;} + break; + + case 85: +#line 292 "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 86: +#line 294 "ael.y" + {reset_semicount(parseio->scanner);;} + break; + + case 87: +#line 294 "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,")"); +#ifdef AAL_ARGCHECK + 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); +#endif + (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 88: +#line 327 "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 89: +#line 328 "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 90: +#line 329 "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 91: +#line 330 "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 92: +#line 331 "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 93: +#line 332 "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 94: +#line 333 "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 95: +#line 334 "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 96: +#line 335 "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 97: +#line 336 "ael.y" + { (yyval.pval)=0; ;} + break; + + case 98: +#line 339 "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 99: +#line 340 "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 100: +#line 343 "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 101: +#line 346 "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 102: +#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 103: +#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 = 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 104: +#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 105: +#line 368 "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 106: +#line 371 "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 107: +#line 374 "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 108: +#line 379 "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 109: +#line 384 "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 110: +#line 389 "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 111: +#line 396 "ael.y" + {reset_argcount(parseio->scanner);;} + break; + + case 112: +#line 397 "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 113: +#line 399 "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 114: +#line 402 "ael.y" + {reset_argcount(parseio->scanner);;} + break; + + case 115: +#line 402 "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); + free((yyvsp[-2].str)); /* won't be using this */ + 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 116: +#line 411 "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 117: +#line 417 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);(yyval.pval)->endline = (yylsp[0]).last_line; (yyval.pval)->endcol = (yylsp[0]).last_column;;} + break; + + case 118: +#line 420 "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 119: +#line 421 "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 120: +#line 422 "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 121: +#line 423 "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 122: +#line 426 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 123: +#line 427 "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 124: +#line 432 "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 125: +#line 433 "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 126: +#line 434 "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 127: +#line 435 "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 128: +#line 436 "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 129: +#line 437 "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 130: +#line 440 "ael.y" + {(yyval.pval) = (yyvsp[0].pval);;} + break; + + case 131: +#line 441 "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 132: +#line 446 "ael.y" + {(yyval.pval)=(yyvsp[0].pval);;} + break; + + case 133: +#line 447 "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 134: +#line 450 "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 135: +#line 451 "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 136: +#line 454 "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 137: +#line 455 "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 138: +#line 458 "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 139: +#line 459 "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 460 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 141: +#line 463 "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 142: +#line 464 "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 143: +#line 485 "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 144: +#line 498 "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 145: +#line 499 "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 146: +#line 520 "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 147: +#line 532 "ael.y" + {(yyval.pval)=(yyvsp[-1].pval);;} + break; + + case 148: +#line 535 "ael.y" + { (yyval.str) = (yyvsp[0].str);;} + break; + + case 149: +#line 536 "ael.y" + {(yyval.str)=strdup("default");;} + break; + + case 150: +#line 539 "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 151: +#line 540 "ael.y" + {(yyval.pval)= npval(PV_INCLUDES,(yylsp[-2]).first_line,(yylsp[0]).last_line, (yylsp[-2]).first_column, (yylsp[0]).last_column);;} + break; + + + default: break; + } + +/* Line 1126 of yacc.c. */ +#line 2755 "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) + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + char *yymsg = 0; +# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +#if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +#endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* 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 = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + + if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yymsg; + int yyi = 0; + while ((*yyp = *yyf)) + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + yyerror (&yylloc, parseio, yymsg); + YYSTACK_FREE (yymsg); + } + else + { + yyerror (&yylloc, parseio, YY_("syntax error")); + goto yyexhaustedlab; + } + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (&yylloc, parseio, YY_("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) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + 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: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (0) + goto yyerrorlab; + + 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: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, parseio, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp); + YYPOPSTACK; + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 544 "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; i<token_equivs_entries; i++) { + if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) + { + len+=strlen(token_equivs2[i])+2; + p += strlen(token_equivs1[i])-1; + break; + } + } + len++; + } + res = (char*)malloc(len+1); + res[0] = 0; + s = res; + for (p=mess; *p;) { + int found = 0; + for (i=0; i<token_equivs_entries; i++) { + if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) { + *s++ = '\''; + for (t=token_equivs2[i]; *t;) { + *s++ = *t++; + } + *s++ = '\''; + p += strlen(token_equivs1[i]); + found = 1; + break; + } + } + if( !found ) + *s++ = *p++; + } + *s++ = 0; + return res; +} + +void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s) +{ + char *s2 = ael_token_subst((char *)s); + if (locp->first_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); + parseio->syntax_error_count++; +} + +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; + } +} + + diff --git a/pbx/ael/ael.tab.h b/pbx/ael/ael.tab.h new file mode 100644 index 0000000000..48459ee7ce --- /dev/null +++ b/pbx/ael/ael.tab.h @@ -0,0 +1,147 @@ +/* A Bison parser, made by GNU Bison 2.1. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, 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 +/* Tokens. */ +#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 47 "ael.y" +typedef union YYSTYPE { + char *str; + struct pval *pval; +} YYSTYPE; +/* Line 1447 of yacc.c. */ +#line 125 "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 + + + + diff --git a/pbx/ael/ael.y b/pbx/ael/ael.y new file mode 100644 index 0000000000..5a9d9805a0 --- /dev/null +++ b/pbx/ael/ael.y @@ -0,0 +1,705 @@ +%{ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy <murf@parsetree.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ +/*! \file + * + * \brief Bison Grammar description of AEL2. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#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 YYLEX_PARAM ((struct parse_io *)parseio)->scanner +#define YYERROR_VERBOSE 1 + +extern char *my_file; +#ifdef AAL_ARGCHECK +int ael_is_funcname(char *name); +#endif + static char *ael_token_subst(char *mess); + extern char *prev_word; + +%} + + +%union { + char *str; + struct pval *pval; +} + +%{ + /* declaring these AFTER the union makes things a lot simpler! */ +void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s); +int ael_yylex (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void * yyscanner); + +%} + + +%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 <str> word + +%type <pval>includes +%type <pval>includeslist +%type <pval>switchlist +%type <pval>eswitches +%type <pval>switches +%type <pval>macro_statement +%type <pval>macro_statements +%type <pval>case_statement +%type <pval>case_statements +%type <pval>eval_arglist +%type <pval>application_call +%type <pval>application_call_head +%type <pval>macro_call +%type <pval>target jumptarget +%type <pval>statement +%type <pval>switch_head +%type <str>word_list goto_word +%type <str>word3_list +%type <str>includedname +%type <pval>if_head +%type <pval>random_head +%type <pval>iftime_head +%type <pval>statements +%type <pval>extension +%type <pval>ignorepat +%type <pval>element +%type <pval>elements +%type <pval>arglist +%type <pval>global_statement +%type <pval>global_statements +%type <pval>globals +%type <pval>macro +%type <pval>context +%type <pval>object +%type <pval>objects +%type <pval>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 {struct parse_io *parseio} +/* 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 +%destructor { if (yymsg[0] != 'C') {destroy_pval($$); prev_word=0;} else {printf("Cleanup destructor called for pvals\n");} } includes includeslist switchlist eswitches switches macro_statement macro_statements case_statement case_statements eval_arglist application_call + application_call_head macro_call target jumptarget statement switch_head if_head random_head iftime_head statements extension ignorepat element + elements arglist global_statement global_statements globals macro context object objects +%destructor { free($$);} word word_list goto_word word3_list includedname + + +%% + +file : objects { $$ = parseio->pval = $1; } + ; + +objects : object {$$=$1;} + | objects object {if ( $1 && $2 ) {$$=$1; linku1($$,$2);} + else if ( $1 ) {$$=$1;} + else if ( $2 ) {$$=$2;} } + | objects error {$$=$1;} + ; + +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 {$$=$1;} + ; + +global_statement : word EQ { reset_semicount(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 {$$=$1;} + ; + +elements : element { $$=$1;} + | error {$$=0;} + | 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(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; } + | word error {free($1); $$=0;} + | 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 {$$=$1;} + ; + +if_head : KW_IF LP { reset_parencount(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(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=$$;} + ; + +goto_word : word { $$ = $1;} + | word word { $$ = (char*)malloc(strlen($1)+strlen($2)+1); strcpy($$, $1); strcat($$, $2); free($1); free($2);} + | word COLON word { $$ = (char*)malloc(strlen($1)+strlen($3)+2); strcpy($$, $1); strcat($$,":"); strcat($$, $3); free($1); free($3);} + ; + +switch_head : KW_SWITCH LP { reset_parencount(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(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(parseio->scanner);} word SEMI + {reset_semicount(parseio->scanner);} word SEMI + {reset_parencount(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(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(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,")"); +#ifdef AAL_ARGCHECK + 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); +#endif + $$->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 : goto_word { $$ = npval(PV_WORD,@1.first_line,@1.last_line, @1.first_column, @1.last_column); $$->u1.str = $1;} + | goto_word BAR goto_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;} + | goto_word COMMA goto_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;} + | goto_word BAR goto_word BAR goto_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; } + | goto_word COMMA goto_word COMMA goto_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 goto_word BAR goto_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 goto_word COMMA goto_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 : goto_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] */ + | goto_word COMMA goto_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;} + | goto_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; } + | goto_word AT goto_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"); } + | goto_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; } + | goto_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(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(parseio->scanner);} LP {if (strcasecmp($1,"goto") == 0) { + $$= npval(PV_GOTO,@1.first_line,@3.last_line, @1.first_column, @3.last_column); + free($1); /* won't be using this */ + 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 {$$=$1;} + ; + +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 {$$=$1;} + ; + +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; i<token_equivs_entries; i++) { + if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) + { + len+=strlen(token_equivs2[i])+2; + p += strlen(token_equivs1[i])-1; + break; + } + } + len++; + } + res = (char*)malloc(len+1); + res[0] = 0; + s = res; + for (p=mess; *p;) { + int found = 0; + for (i=0; i<token_equivs_entries; i++) { + if ( strncmp(p,token_equivs1[i],strlen(token_equivs1[i])) == 0 ) { + *s++ = '\''; + for (t=token_equivs2[i]; *t;) { + *s++ = *t++; + } + *s++ = '\''; + p += strlen(token_equivs1[i]); + found = 1; + break; + } + } + if( !found ) + *s++ = *p++; + } + *s++ = 0; + return res; +} + +void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s) +{ + char *s2 = ael_token_subst((char *)s); + if (locp->first_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); + parseio->syntax_error_count++; +} + +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; + } +} + diff --git a/pbx/ael/ael_lex.c b/pbx/ael/ael_lex.c new file mode 100644 index 0000000000..9e5894de55 --- /dev/null +++ b/pbx/ael/ael_lex.c @@ -0,0 +1,2996 @@ +#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 33 +#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 <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +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 + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#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 <murf@parsetree.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ +/*! \file + * + * \brief Flex scanner description of tokens used in AEL2 . + * + */#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#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 (struct parse_io *); +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 703 "ael_lex.c" + +#define INITIAL 0 +#define paren 1 +#define semic 2 +#define argg 3 + +#ifndef YY_NO_UNISTD_H +/* 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 <unistd.h> +#endif + +#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 */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* 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 945 "ael_lex.c" + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#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; + strncpy(fnamebuf,p1,p2-p1); + fnamebuf[p2-p1] = 0; + for (i=0; i<include_stack_index; i++) { + if ( !strcmp(fnamebuf,include_stack[i].fname )) { + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Nice Try!!! But %s has already been included (perhaps by another file), and would cause an infinite loop of file inclusions!!! Include directive ignored\n", + my_file, my_lineno, my_col, fnamebuf); + found=1; + break; + } + } + if( !found ) + { + *p2 = 0; + /* relative vs. absolute */ + if ( *(p1+1) != '/' ) + { + strcpy(fnamebuf,ast_config_AST_CONFIG_DIR); + strcat(fnamebuf,"/"); + strcat(fnamebuf,p1+1); + } + else + strcpy(fnamebuf,p1+1); + in1 = fopen( fnamebuf, "r" ); + if ( ! in1 ) { + ast_log(LOG_ERROR,"File=%s, line=%d, column=%d: Couldn't find the include file: %s; ignoring the Include directive!\n", my_file, my_lineno, my_col, fnamebuf); + } else { + char *buffer; + struct stat stats; + stat(fnamebuf, &stats); + buffer = (char*)malloc(stats.st_size+1); + fread(buffer, 1, stats.st_size, in1); + buffer[stats.st_size] = 0; + ast_log(LOG_NOTICE," --Read in included file %s, %d chars\n",fnamebuf, (int)stats.st_size); + fclose(in1); + + include_stack[include_stack_index].fname = my_file; + my_file = strdup(fnamebuf); + include_stack[include_stack_index].lineno = my_lineno; + include_stack[include_stack_index].colno = my_col+yyleng; + include_stack[include_stack_index++].bufstate = YY_CURRENT_BUFFER; + + ael_yy_switch_to_buffer(ael_yy_scan_string (buffer ,yyscanner),yyscanner); + free(buffer); + my_lineno = 1; + my_col = 1; + BEGIN(INITIAL); + } + } + } + } + } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(paren): +case YY_STATE_EOF(semic): +case YY_STATE_EOF(argg): +#line 487 "ael.flex" +{ + if ( --include_stack_index < 0 ) { + yyterminate(); + } else { + free(my_file); + ael_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner ); + ael_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; + } + } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 501 "ael.flex" +ECHO; + YY_BREAK +#line 1732 "ael_lex.c" + + 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 + * 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 + { + int 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; /* This var may be unused depending upon options. */ + 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 yystr 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 * yystr , yyscan_t yyscanner) +{ + + return ael_yy_scan_bytes(yystr,strlen(yystr) ,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 * yybytes, int _yybytes_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 = _yybytes_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 < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_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; +} + +/* 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; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +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 from ael_yylex_destroy(), so don't allocate here. + */ + + 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 = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* 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; +} + +/* 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; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * ael_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + ael_yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + 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; + 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; + 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" + +#line 501 "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); +} + + +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_yydebug; */ + + io = calloc(sizeof(struct parse_io),1); + /* reset the global counters */ + prev_word = 0; + my_lineno = 1; + include_stack_index=0; + my_col = 0; + /* ael_yydebug = 1; */ + ael_yylex_init(&io->scanner); + fin = fopen(filename,"r"); + if ( !fin ) { + ast_log(LOG_ERROR,"File %s could not be opened\n", filename); + *errors = 1; + return 0; + } + 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(io); + + + pval = io->pval; + *errors = io->syntax_error_count; + + ael_yylex_destroy(io->scanner); + free(buffer); + free(io); + + return pval; +} + diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c index e16b7f6941..8ecacfb13d 100644 --- a/pbx/pbx_ael.c +++ b/pbx/pbx_ael.c @@ -1,9 +1,9 @@ /* * Asterisk -- An open source telephony toolkit. * - * Copyright (C) 1999 - 2005, Digium, Inc. + * Copyright (C) 2006, Digium, Inc. * - * Mark Spencer <markster@digium.com> + * Steve Murphy <murf@parsetree.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact @@ -18,7 +18,7 @@ /*! \file * - * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions + * \brief Compile symbolic Asterisk Extension Logic into Asterisk extensions, version 2. * */ @@ -28,6 +28,7 @@ #include <string.h> #include <ctype.h> #include <errno.h> +#include <regex.h> #include "asterisk.h" @@ -38,23 +39,18 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #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" +#ifdef AAL_ARGCHECK +#include "asterisk/argdesc.h" +#endif -struct stringlink { - struct stringlink *next; - char data[0]; -}; - -#define FILLIN_BREAK 1 -#define FILLIN_CONTINUE 2 +static char expr_output[2096]; -struct fillin { - struct fillin *next; - char exten[AST_MAX_EXTENSION]; - int priority; - int type; -}; +/* these functions are in ../ast_expr2.fl */ + #ifdef __AST_DEBUG_MALLOC static void FREE(void *ptr) { @@ -71,1177 +67,3438 @@ static void FREE(void *ptr) static int aeldebug = 0; +static char *dtext = "Asterisk Extension Language Compiler v2"; static char *config = "extensions.ael"; static char *registrar = "pbx_ael"; -static char *__grab_token(char *src, const char *filename, int lineno, int link) +static int errs, warns, notes; + +#ifndef AAL_ARGCHECK +/* for the time being, short circuit all the AAL related structures + without permanently removing the code; after/during the AAL + development, this code can be properly re-instated +*/ + +/* null definitions for structs passed down the infrastructure */ +struct argapp { - char *c; - char *b; - char *a; - int level = 0; - char *ret; -#if 0 - if (aeldebug || DEBUG_TOKENS) - ast_verbose("Searching for token in '%s'!\n", src); + struct argapp *next; +}; + +#endif + +#ifdef AAL_ARGCHECK +int option_matches_j( struct argdesc *should, pval *is, struct argapp *app); +int option_matches( struct argdesc *should, pval *is, struct argapp *app); +int ael_is_funcname(char *name); #endif - c = src; - while(*c) { - if ((*c == '\\')) { - c++; - if (!*c) - c--; + +int check_app_args(pval *appcall, pval *arglist, struct argapp *app); +void check_pval(pval *item, struct argapp *apps); +void check_pval_item(pval *item, struct argapp *apps); +void check_switch_expr(pval *item, struct argapp *apps); +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); +struct pval *find_macro(char *name); +struct pval *find_context(char *name); +struct pval *find_context(char *name); +struct pval *find_macro(char *name); +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); +static pval *current_db; +static pval *current_context; +static pval *current_extension; +static const char *description(void); +static const char *key(void); + +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; i<depth; i++) { + fprintf(fin, "\t"); /* depth == indentation */ + } + + switch ( item->type ) { + 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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n\n"); + break; + + case PV_CONTEXT: + if ( item->u3.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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n\n"); + break; + + case PV_MACRO_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_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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n"); + break; + + case PV_SWITCHES: + fprintf(fin,"switches {\n"); + print_pval_list(fin,item->u1.list,depth+1); + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n"); + break; + + case PV_ESWITCHES: + fprintf(fin,"eswitches {\n"); + print_pval_list(fin,item->u1.list,depth+1); + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n"); + break; + + case PV_INCLUDES: + fprintf(fin,"includes {\n"); + for (lp=item->u1.list; lp; lp=lp->next) { + for (i=0; i<depth+1; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"%s", lp->u1.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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n"); + break; + + case PV_STATEMENTBLOCK: + fprintf(fin,"{\n"); + print_pval_list(fin,item->u1.list, depth+1); + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"};\n"); + break; + + case PV_VARDEC: + fprintf(fin,"%s=%s;\n", item->u1.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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"{\n"); + print_pval_list(fin,item->u2.statements,depth+1); + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + if ( item->u3.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 ((*c == '{') || (*c == '(')) { - level++; - } else if ((*c == '}') || (*c == ')')) { - if (level) - level--; - else - ast_log(LOG_WARNING, "Syntax error at line %d of '%s', too many closing braces!\n", lineno, filename); - } else if ((*c == ';') && !level) { - /* Got a token! */ - *c = '\0'; - b = c; - b--; - c++; - while((b > src) && (*b < 33)) { - *b = '\0'; - b--; - } - a = ast_skip_blanks(src); - if (link) { - ret = malloc(strlen(a) + sizeof(struct stringlink) + 1); - if (ret) - strcpy(ret + sizeof(struct stringlink), a); - } else - ret = strdup(a); - /* Save remainder */ - memmove(src, c, strlen(c) + 1); - return ret; + if (item->u3.else_statements ) + fprintf(fin, " {} "); + else + fprintf(fin, " {}; "); + } + if ( item->u3.else_statements ) { + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ } + fprintf(fin,"else\n"); + print_pval_list(fin,item->u3.else_statements, depth); } - c++; + break; + + case PV_SWITCH: + fprintf(fin,"switch( %s ) {\n", item->u1.str); + print_pval_list(fin,item->u2.statements,depth+1); + for (i=0; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"}\n"); + break; + + case PV_EXTENSION: + if ( item->u4.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; i<depth; i++) { + fprintf(fin,"\t"); /* depth == indentation */ + } + fprintf(fin,"}\n"); + break; } - return NULL; } -static char *grab_token(char *src, const char *filename, int lineno) +void print_pval_list(FILE *fin, pval *item, int depth) { - return __grab_token(src, filename, lineno, 0); + pval *i; + + for (i=item; i; i=i->next) { + print_pval(fin, i, depth); + } } -static struct stringlink *arg_parse(char *args, const char *filename, int lineno) +void ael2_print(char *fname, pval *tree) { - struct stringlink *cur, *prev=NULL, *root=NULL; - if (args) { - if (aeldebug & DEBUG_TOKENS) - ast_verbose("Parsing args '%s'!\n", args); - if (args[0] == '{') { - /* Strip mandatory '}' from end */ - args[strlen(args) - 1] = '\0'; - while ((cur = (struct stringlink *)__grab_token(args + 1, filename, lineno, 1))) { - cur->next = NULL; - if (prev) - prev->next = cur; - else - root = cur; - prev = cur; - } - } else if (*args) { - root = malloc(sizeof(struct stringlink) + strlen(args) + 1); - if (root) { - strcpy(root->data, args); - root->next = NULL; - } + 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; } - return root; } -static char *grab_else(char *args, const char *filename, int lineno) +void traverse_pval_template(pval *item, int depth) /* depth comes in handy for a pretty print (indentation), + but you may not need it */ { - char *ret = NULL; - int level=0; - char *c; - if (args) { - if (args[0] == '{') { - c = args; - while(*c) { - if (*c == '{') - level++; - else if (*c == '}') { - level--; - if (!level) { - c++; - while(*c && (*c < 33)) { *c = '\0'; c++; }; - if (!strncasecmp(c, "else", 4) && - ((c[4] == '{') || (c[4] < 33))) { - /* Ladies and gentlemen, we have an else clause */ - *c = '\0'; - c += 4; - c = ast_skip_blanks(c); - ret = c; - if (aeldebug & DEBUG_TOKENS) - ast_verbose("Returning else clause '%s'\n", c); - } - break; - } + 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; + + /* simple case, they match exactly, the pattern and exten name */ + if( !strcmp(pattern,exten) == 0 ) + return 1; + + 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 */ + *r++ = '^'; /* what if the extension is a pattern ?? */ + *r++ = '_'; /* what if the extension is a pattern ?? */ + *r++ = '?'; + for (p=pattern+1; *p; p++) { + switch ( *p ) { + case 'X': + *r++ = '['; + *r++ = '0'; + *r++ = '-'; + *r++ = '9'; + *r++ = 'X'; + *r++ = ']'; + break; + + case 'Z': + *r++ = '['; + *r++ = '1'; + *r++ = '-'; + *r++ = '9'; + *r++ = 'Z'; + *r++ = ']'; + break; + + case 'N': + *r++ = '['; + *r++ = '2'; + *r++ = '-'; + *r++ = '9'; + *r++ = 'N'; + *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); } - c++; + break; + + case '.': + case '!': + *r++ = '.'; + *r++ = '*'; + break; + case '*': + *r++ = '\\'; + *r++ = '*'; + break; + default: + *r++ = *p; + break; + } } + *r++ = '$'; /* what if the extension is a pattern ?? */ + *r++ = *p++; /* put in the closing null */ + err1 = regcomp(&preg, reg1, REG_NOSUB|REG_EXTENDED); + 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 ) { + /* ast_log(LOG_NOTICE,"*****************************[%d]Extension %s did not match %s(%s)\n", + err1,exten, pattern, reg1); */ + return 0; /* no match */ + } else { + /* ast_log(LOG_NOTICE,"*****************************Extension %s matched %s\n", + exten, pattern); */ + return 1; + } + + + } else { + if ( strcmp(exten,pattern) == 0 ) { + return 1; + } else + return 0; } - return ret; } -static struct stringlink *param_parse(char *parms, const char *macro, const char *filename, int lineno) + +static void check_expr2_input(pval *expr, char *str) { - char *s, *e; - struct stringlink *root = NULL, *prev=NULL, *cur; - if (!parms || !*parms) - return NULL; - if (*parms != '(') { - ast_log(LOG_NOTICE, "Syntax error in parameter list for macro '%s' at about line %d of %s: Expecting '(' but got '%c'\n", macro, lineno, filename, *parms); - return NULL; + 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++; } - s = parms + 1; - while(*s) { - s = ast_skip_blanks(s); - e = s; - while(*e && (*e != ')') && (*e != ',')) { - if (*e < 33) - *e = '\0'; - e++; - } - if (*e) { - /* Strip token */ - *e = '\0'; - e++; - /* Skip over whitespace */ - e = ast_skip_blanks(e); - /* Link */ - cur = malloc(strlen(s) + sizeof(struct stringlink) + 1); - if (cur) { - cur->next = NULL; - strcpy(cur->data, s); - if (prev) - prev->next = cur; - else - root = cur; - prev = cur; - } - s = e; - } +} + +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 root; + return; } -static void arg_free(struct stringlink *cur) +static char *days[] = { - struct stringlink *last; - while(cur) { - last = cur; - cur = cur->next; - free(last); + "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 handle_globals(struct stringlink *vars) +static void check_day(pval *DAY) { - while(vars) { - pbx_builtin_setvar(NULL, vars->data); - vars = vars->next; + 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 struct stringlink *split_token(char *token, const char *filename, int lineno) +static char *months[] = { - char *args, *p; - struct stringlink *argv; - args = token; - while (*args && (*args > 32) && (*args != '{') && (*args != '(')) args++; - if (*args) { - p = args; - args = ast_skip_blanks(args); - if (*args != '(') { - *p = '\0'; - } else { - while (*args && (*args != ')')) args++; - if (*args == ')') { - args++; - args = ast_skip_blanks(args); - } + "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++; } - if (!*args) - args = NULL; - } else args = NULL; - argv = arg_parse(args, filename, lineno); - if (args) - *args = '\0'; - return argv; + } else + e = s; } -static int matches_keyword(const char *data, const char *keyword) +/* general purpose goto finder */ + + +static void check_goto(pval *item) { - char c; - if (!strncasecmp(data, keyword, strlen(keyword))) { - c = data[strlen(keyword)]; - if ((c < 33) || (c == '(') || (c == '{')) - return 1; + /* 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++; + } + } + } } - return 0; } + + +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; +} + +#ifdef AAL_ARGCHECK +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 ... */ +} +#endif + +int check_app_args(pval* appcall, pval *arglist, struct argapp *app) +{ +#ifdef AAL_ARGCHECK + 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; +#else + return 0; +#endif +} + +void check_switch_expr(pval *item, struct argapp *apps) +{ +#ifdef AAL_ARGCHECK + /* 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++; + } + } +#endif +} + +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; +#ifdef AAL_ARGCHECK + struct argapp *app, *found; +#endif + 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++; + } +#ifdef AAL_ARGCHECK + 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); +#endif + 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) +{ + +#ifdef AAL_ARGCHECK + int argapp_errs =0; + char *rfilename; +#endif + struct argapp *apps=0; + +#ifdef AAL_ARGCHECK + 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 */ +#endif + current_db = item; + errs = warns = notes = 0; + + check_context_names(); + check_pval(item, apps); + +#ifdef AAL_ARGCHECK + argdesc_destroy(apps); /* taketh away */ +#endif + current_db = 0; + + *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 */ -static struct stringlink *split_params(char *token, const char *filename, int lineno) -{ - char *params; - struct stringlink *paramv; - params = token; - while(*params && (*params > 32) && (*params != '(')) params++; - if (*params) { - if (*params != '(') { - *params = '\0'; - params++; - params = ast_skip_blanks(params); - } - if (!*params) - params = NULL; - } else params = NULL; - paramv = param_parse(params, token, filename, lineno); - if (params) - *params = '\0'; - return paramv; -} + 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 */ -static const char *get_case(char *s, char **restout, int *pattern) -{ - char *newcase=NULL; - char *rest=NULL; - if (!strncasecmp(s, "case", 4) && s[4] && ((s[4] < 33) || (s[4] == ':'))) { - newcase = s + 4; - newcase = ast_skip_blanks(newcase); - rest = newcase; - *pattern = 0; - } else if (!strncasecmp(s, "pattern", 7) && s[7] && ((s[7] < 33) || (s[7] == ':'))) { - newcase = s + 8; - newcase = ast_skip_blanks(newcase); - rest = newcase; - *pattern = 1; - } else if (!strncasecmp(s, "default", 7) && ((s[7] < 33) || (s[7] == ':'))) { - newcase = "."; - rest = s + 7; - rest = ast_skip_blanks(rest); - *pattern = 1; - } + linkprio(exten, rand_end); + + break; +#endif - if (rest) { - while (*rest && (*rest > 32) && (*rest != ':')) rest++; - if (*rest) { - *rest = 0; - rest++; - while (*rest && ((*rest == ':') || (*rest < 33))) rest++; - *restout = rest; - } else { - *restout = ""; - } - } else - *restout = s; - if (aeldebug & DEBUG_TOKENS) - ast_verbose("GETCASE: newcase is '%s', rest = '%s'\n", newcase, *restout); - return newcase; -} + 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; -static void fillin_free(struct fillin *fillin) -{ - struct fillin *cur, *next; - cur = fillin; - while(cur) { - next = cur->next; - free(cur); - cur = next; - } -} + 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; -static void fillin_process(struct ast_context *con, struct fillin *fillin, const char *filename, int lineno, const char *breakexten, int breakprio, const char *contexten, int contprio) -{ - struct fillin *cur; - char *app; - char mdata[AST_MAX_EXTENSION + 20]; - cur = fillin; - while(cur) { - if (cur->type == FILLIN_BREAK) { - if (breakexten && breakprio) { - app = "Goto"; - snprintf(mdata, sizeof(mdata), "%s|%d", breakexten, breakprio); } else { - app = "NoOp"; - snprintf(mdata, sizeof(mdata), "Invalid break"); - ast_log(LOG_NOTICE, "Ignoring inappropriate break around line %d of %s\n", lineno, filename); + if_skip = 0; + + if_test->goto_false = if_end; } - if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of break '%s'\n", cur->priority, cur->exten); - } else if (cur->type == FILLIN_CONTINUE) { - if (contexten && contprio) { - app = "Goto"; - snprintf(mdata, sizeof(mdata), "%s|%d", contexten, contprio); + + if_false = new_prio(); + if_false->type = AEL_CONTROL1; + if (p->u3.else_statements) { + if_false->goto_true = if_skip; /* +1 */ } else { - app = "NoOp"; - snprintf(mdata, sizeof(mdata), "Invalid continue"); - ast_log(LOG_NOTICE, "Ignoring inappropriate continue around line %d of %s\n", lineno, filename); + if_false->goto_true = if_end; } - if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of continue '%s'\n", cur->priority, cur->exten); - } else { - ast_log(LOG_WARNING, "Whoa, unknown fillin type '%d'\n", cur->type); - } - cur = cur->next; - } -} + + /* 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 */ -static int match_assignment(char *variable, char **value) -{ - char *c; - char *ws; - int inpar = 0; - c = variable; - - while (*c) { - if(*c == ')' && (inpar > 0)) { - inpar--; - } else if(*c == '(' && (inpar >= 0)) { - inpar++; - } else if(*c == '=' && (inpar == 0)) { + } + + linkprio(exten, if_end); + break; - } - c++; - } - ws = c; - c = ast_skip_blanks(c); - if (*c == '=') { - *ws = '\0'; - *c = '\0'; - c++; - c = ast_skip_blanks(c); - *value = c; - return 1; - } - return 0; -} -static int matches_label(char *data, char **rest) -{ - char last = 0; - char *start = data; - while (*data > 32) { - last = *data; - data++; - } - if (last != ':') { - data = ast_skip_blanks(data); - last = *data; - data++; - } - if (last == ':') { - *rest = data; - /* Go back and trim up the label */ - while(*start && ((*start > 32) && (*start != ':'))) start++; - *start = '\0'; - return 1; - } - return 0; -} + 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 */ -static char *argument_end(char *str) -{ - int level=0; - while(*++str) { - switch(*str) { - case '(': - level++; + } + + linkprio(exten, if_end); + break; - case ')': - if(level) - level--; - else - return str; + + 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; } } - return NULL; } -static int build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label); -static int __build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label) +void set_priorities(struct ael_extension *exten) { - char *app; - char *args; - char *c; - char *margs=NULL; - char *oargs; - char *rest; - const char *curcase, *newcase; - struct stringlink *swargs, *cur; - int cpos; - int mlen; - int pattern = 0; - struct fillin *fillin; - - data = ast_skip_blanks(data); - if (matches_label(data, &c)) { - *label = data; - data = c; - data = ast_skip_blanks(data); - } - if (ast_strlen_zero(data)) - return 0; - if (matches_keyword(data, "switch")) { - fillin = NULL; - /* Switch */ - args = data + strlen("switch"); - while ((*args < 33) && (*args != '(')) args++; - if ((*args == '(') && (c = argument_end(args))) { - args++; - *c = '\0'; - c++; - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--SWITCH on : %s\n", args); - mlen = strlen(exten) + 128 + strlen(args) + strlen(name); - margs = alloca(mlen); - app = "Goto"; - sprintf(margs, "sw-%d-%s|1", *pos, args); - ast_process_quotes_and_slashes(margs, ',', '|'); - oargs = args; - args = margs; - if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - else { - *label = NULL; - (*pos)++; - } - app = "NoOp"; - sprintf(margs, "Finish switch-%d", *pos - 1); - if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - else { - *label = NULL; - (*pos)++; - } - c = ast_skip_blanks(c); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("ARG Parsing '%s'\n", c); - swargs = arg_parse(c, filename, lineno); - cur = swargs; - curcase = NULL; - while(cur) { - if ((newcase = get_case(cur->data, &rest, &pattern))) { - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--NEWCASE: '%s'!\n", newcase); - if (curcase) { - /* Handle fall through */ - char tmp[strlen(newcase) + strlen(name) + 40]; - sprintf(tmp, "sw-%d-%s|%d", *pos - 2, newcase, 1); - ast_add_extension2(con, 0, margs, cpos, NULL, NULL, "Goto", strdup(tmp), FREE, registrar); - } - curcase = newcase; - cpos = 1; - if (pattern) - snprintf(margs, mlen, "_sw-%d-%s", *pos - 2, curcase); - else - snprintf(margs, mlen, "sw-%d-%s", *pos - 2, curcase); - if (!strcasecmp(rest, "break")) { - char tmp[strlen(exten) + 10]; - sprintf(tmp, "%s|%d", exten, *pos - 1); - ast_add_extension2(con, 0, exten, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar); - curcase = NULL; - *label = NULL; - } else - build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label); - } else if (curcase) { - if (aeldebug & DEBUG_TOKENS) - ast_verbose("Building statement from '%s'\n", rest); - if (!strcasecmp(rest, "break")) { - char tmp[strlen(exten) + 10]; - sprintf(tmp, "%s|%d", exten, *pos - 1); - ast_add_extension2(con, 0, margs, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar); - curcase = NULL; - *label = NULL; - } else - build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label); - } else - ast_log(LOG_WARNING, "Unreachable code in switch at about line %d of %s\n", lineno, filename); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--SWARG: %s\n", cur->data); - cur = cur->next; - } - /* Can't do anything with these */ - fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0); - fillin_free(fillin); - arg_free(swargs); - } else - ast_log(LOG_WARNING, "Syntax error in switch declaration in %s around line %d!\n", filename, lineno); - - } else if (matches_keyword(data, "if")) { - /* If... */ - args = data + strlen("if"); - while ((*args < 33) && (*args != '(')) args++; - if ((*args == '(') && (c = argument_end(args))) { - int ifblock; - int ifstart; - int elsestart; - int ifend; - int ifskip; - char *elses; - char *iflabel; - args++; - *c = '\0'; - c++; - c = ast_skip_blanks(c); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--IF on : '%s' : '%s'\n", args, c); - mlen = strlen(exten) + 128 + strlen(args) + strlen(name); - margs = alloca(mlen); - /* Remember where the ifblock starts, and skip over */ - ifblock = (*pos)++; - iflabel = *label; - *label = NULL; - /* Remember where the start of the ifblock is */ - ifstart = *pos; - snprintf(margs, mlen, "if-%s-%d", name, ifblock); - /* Now process the block of the if */ - if (aeldebug & DEBUG_TOKENS) - ast_verbose("Searching for elses in '%s'\n", c); - elses = grab_else(c, filename, lineno); - build_step("if", margs, filename, lineno, con, exten, pos, c, fillout, label); - if (elses) { - /* Reserve a goto to exit the if */ - ifskip = *pos; - (*pos)++; - elsestart = *pos; - build_step("else", margs, filename, lineno, con, exten, pos, elses, fillout, label); - } else { - elsestart = *pos; - ifskip = 0; - } - ifend = *pos; - (*pos)++; - app = "NoOp"; - snprintf(margs, mlen, "Finish if-%s-%d", name, ifblock); - if (ast_add_extension2(con, 0, exten, ifend, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - app = "GotoIf"; - snprintf(margs, mlen, "$[ %s ]?%d:%d", args, ifstart, elsestart); - if (ast_add_extension2(con, 0, exten, ifblock, iflabel, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - if (ifskip) { - /* Skip as appropriate around else clause */ - snprintf(margs, mlen, "%d", ifend); - if (ast_add_extension2(con, 0, exten, ifskip, NULL, NULL, "Goto", strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - } - } else - ast_log(LOG_WARNING, "Syntax error in if declaration in %s around line %d!\n", filename, lineno); - } else if (matches_keyword(data, "while")) { - /* While... */ - fillin = NULL; - args = data + strlen("while"); - while ((*args < 33) && (*args != '(')) args++; - if ((*args == '(') && (c = argument_end(args))) { - int whileblock; - int whilestart; - int whileend; - char *whilelabel; - args++; - *c = '\0'; - c++; - c = ast_skip_blanks(c); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--WHILE on : '%s' : '%s'\n", args, c); - mlen = strlen(exten) + 128 + strlen(args) + strlen(name); - margs = alloca(mlen); - /* Remember where to put the conditional, and keep its position */ - whilestart = (*pos); - whilelabel = *label; - *label = NULL; - (*pos)++; - /* Remember where the whileblock starts */ - whileblock = (*pos); - snprintf(margs, mlen, "while-%s-%d", name, whilestart); - build_step("while", margs, filename, lineno, con, exten, pos, c, &fillin, label); - /* Close the loop */ - app = "Goto"; - snprintf(margs, mlen, "%d", whilestart); - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - whileend = (*pos); - /* Place trailer */ - app = "NoOp"; - snprintf(margs, mlen, "Finish while-%s-%d", name, whilestart); - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - app = "GotoIf"; - snprintf(margs, mlen, "$[ %s ]?%d:%d", args, whileblock, whileend); - if (ast_add_extension2(con, 0, exten, whilestart, whilelabel, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - fillin_process(con, fillin, filename, lineno, exten, whileend, exten, whilestart); - fillin_free(fillin); - } else - ast_log(LOG_WARNING, "Syntax error in while declaration in %s around line %d!\n", filename, lineno); - } else if (matches_keyword(data, "jump")) { - char *p; - /* Jump... */ - fillin = NULL; - args = data + strlen("jump"); - args = ast_skip_blanks(args); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--JUMP to : '%s'\n", args); - p = strchr(args, ','); - if (p) { - *p = '\0'; - p++; - } else - p = "1"; - c = strchr(args, '@'); - if (c) { - *c = '\0'; - c++; - } - mlen = strlen(exten) + 128 + strlen(args) + strlen(name) + (c ? strlen(c) : 0); - margs = alloca(mlen); - if (c) - snprintf(margs, mlen, "%s|%s|%s", c,args, p); + int i; + struct ael_priority *pr; + do { + if (exten->regexten) + i=2; else - snprintf(margs, mlen, "%s|%s", args, p); - app = "Goto"; - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - } else if (matches_keyword(data, "goto")) { - /* Jump... */ - fillin = NULL; - args = data + strlen("goto"); - args = ast_skip_blanks(args); - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--GOTO to : '%s'\n", args); - app = "Goto"; - if (args[0] == '(' && args[strlen(args) - 1] == ')') { - args[0] = '\0'; - args++; - args[strlen(args) - 1] = '\0'; - } - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(args), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - } else if (matches_keyword(data, "for")) { - /* While... */ - fillin = NULL; - args = data + strlen("for"); - while ((*args < 33) && (*args != '(')) args++; - if ((*args == '(') && (c = argument_end(args))) { - int forblock; - int forprep; - int forstart; - int forend; - struct stringlink *fields; - char *tmp; - char *forlabel = NULL; - args++; - *c = '\0'; - c++; - c = ast_skip_blanks(c); - /* Parse arguments first */ - tmp = alloca(strlen(args) + 10); - if (tmp) { - snprintf(tmp, strlen(args) + 10, "{%s;}", args); - fields = arg_parse(tmp, filename, lineno); - } else - fields = NULL; - if (fields && fields->next && fields->next->next) { - if (aeldebug & DEBUG_TOKENS) - ast_verbose("--FOR ('%s' ; '%s' ; '%s') : '%s'\n", fields->data, fields->next->data, fields->next->next->data, c); - mlen = strlen(exten) + 128 + strlen(args) + strlen(name); - margs = alloca(mlen); - forprep = *pos; - snprintf(margs, mlen, "for-%s-%d", name, forprep); - fillin = NULL; - build_step("while", margs, filename, lineno, con, exten, pos, fields->data, &fillin, label); - /* Remember where to put the conditional, and keep its position */ - forstart = (*pos); - forlabel = *label; - (*pos)++; - *label = NULL; - /* Remember where the whileblock starts */ - forblock = (*pos); - build_step("for", margs, filename, lineno, con, exten, pos, c, &fillin, label); - build_step("for", margs, filename, lineno, con, exten, pos, fields->next->next->data, &fillin, label); - /* Close the loop */ - app = "Goto"; - snprintf(margs, mlen, "%d", forstart); - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - forend = (*pos); - /* Place trailer */ - app = "NoOp"; - snprintf(margs, mlen, "Finish for-%s-%d", name, forprep); - if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - *label = NULL; - app = "GotoIf"; - snprintf(margs, mlen, "$[ %s ]?%d:%d", fields->next->data, forblock, forend); - if (ast_add_extension2(con, 0, exten, forstart, forlabel, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", forstart, what, name); - fillin_process(con, fillin, filename, lineno, exten, forend, exten, forstart); - fillin_free(fillin); - } else - ast_log(LOG_NOTICE, "Improper for declaration in %s around line %d!\n", filename, lineno); - arg_free(fields); - } else - ast_log(LOG_WARNING, "Syntax error in for declaration in %s around line %d!\n", filename, lineno); - - } else if (!strcasecmp(data, "break") || !strcasecmp(data, "continue")) { - struct fillin *fi; - fi = malloc(sizeof(struct fillin)); - if (fi) { - memset(fi, 0, sizeof(struct fillin)); - if (!strcasecmp(data, "break")) - fi->type = FILLIN_BREAK; - else - fi->type = FILLIN_CONTINUE; - ast_copy_string(fi->exten, exten, sizeof(fi->exten)); - fi->priority = (*pos)++; - fi->next = *fillout; - *fillout = fi; - } - } else if (match_assignment(data, &rest)) { - if (aeldebug & DEBUG_TOKENS) - ast_verbose("ASSIGN '%s' = '%s'\n", data, rest); - mlen = strlen(rest) + strlen(data) + 20; - margs = alloca(mlen); - snprintf(margs, mlen, "%s=$[ %s ]", data, rest); - app = "Set"; - if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(margs), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add assignment at priority '%d' of %s '%s'\n", *pos, what, name); - else { - *label = NULL; - (*pos)++; - } - } else { - app = data; - args = app; - while (*args && (*args > 32) && (*args != '(')) args++; - if (*args != '(') { - while(*args && (*args != '(')) { *args = '\0'; args++; }; - } - if (*args == '(') { - *args = '\0'; - args++; - /* Got arguments, trim trailing ')' */ - c = args + strlen(args) - 1; - while((c >= args) && (*c < 33) && (*c != ')')) { *c = '\0'; c--; }; - if ((c >= args) && (*c == ')')) *c = '\0'; - } else - args = ""; - ast_process_quotes_and_slashes(args, ',', '|'); - if (app[0] == '&') { - app++; - margs = alloca(strlen(args) + strlen(app) + 10); - sprintf(margs, "%s|%s", app, args); - args = margs; - app = "Macro"; - } - if (aeldebug & DEBUG_TOKENS) - ast_verbose("-- APP: '%s', ARGS: '%s'\n", app, args); - if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name); - else { - (*pos)++; - *label = NULL; + 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++; } - } - return 0; -} - -static int build_step(const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label) -{ - struct stringlink *args, *cur; - int res=0; - struct fillin *fillin=NULL; - int dropfill = 0; - char *labelin = NULL; - if (!fillout) { - fillout = &fillin; - dropfill = 1; - } - if (!label) { - label = &labelin; - }; - args = arg_parse(data, filename, lineno); - cur = args; - while(cur) { - res |= __build_step(what, name, filename, lineno, con, exten, pos, cur->data, fillout, label); - cur = cur->next; - } - arg_free(args); - if (dropfill) { - fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0); - fillin_free(fillin); - } - return res; + + exten = exten->next_exten; + } while ( exten ); } -static int parse_catch(char *data, char **catch, char **rest) +void add_extensions(struct ael_extension *exten, struct ast_context *context) { - /* Skip the word 'catch' */ - data += 5; - data = ast_skip_blanks(data); - /* Here's the extension */ - *catch = data; - if (!*data) - return 0; - while (*data && (*data > 32)) data++; - if (!*data) - return 0; - /* Trim any trailing spaces */ - *data = '\0'; - data++; - data = ast_skip_blanks(data); - if (!*data) - return 0; - *rest = data; - return 1; -} + 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]; -static void handle_macro(struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno) -{ - struct stringlink *argv; - struct stringlink *paramv; - struct stringlink *cur; - struct ast_context *con; - struct fillin *fillin; - char *catch, *rest; - char name[256]; - int pos; - int cpos; - - if (aeldebug & DEBUG_MACROS) - ast_verbose("Root macro def is '%s'\n", vars->data); - argv = split_token(vars->data, filename, lineno); - paramv = split_params(vars->data, filename, lineno); - if (aeldebug & DEBUG_MACROS) - ast_verbose("Found macro '%s'\n", vars->data); - snprintf(name, sizeof(name), "macro-%s", vars->data); - con = ast_context_create(local_contexts, name, registrar); - if (con) { - pos = 1; - cur = paramv; - while(cur) { - if (aeldebug & DEBUG_MACROS) - ast_verbose(" PARAM => '%s'\n", cur->data); - snprintf(name, sizeof(name), "%s=${ARG%d}", cur->data, pos); - if (ast_add_extension2(con, 0, "s", pos, NULL, NULL, "Set", strdup(name), FREE, registrar)) - ast_log(LOG_WARNING, "Unable to add step at priority '%d' of macro '%s'\n", pos, vars->data); + /* 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 - pos++; - cur = cur->next; - } - cur = argv; - while(cur) { - if (aeldebug & DEBUG_MACROS) - ast_verbose(" STEP => '%s'\n", cur->data); - if (matches_keyword(cur->data, "catch")) { - if (aeldebug & DEBUG_MACROS) - ast_verbose("--CATCH: '%s'\n", cur->data); - if (parse_catch(cur->data, &catch, &rest)) { - cpos = 1; - build_step("catch", catch, filename, lineno, con, catch, &cpos, rest, NULL, NULL); + 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 - ast_log(LOG_NOTICE, "Parse error for catch at about line %d of %s\n", lineno, filename); - } else { - fillin = NULL; - build_step("macro", vars->data, filename, lineno, con, "s", &pos, cur->data, NULL, NULL); + 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; } - cur = cur->next; + 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; } - } else - ast_log(LOG_WARNING, "Unable to create context '%s'\n", name); - arg_free(paramv); - arg_free(argv); - if (vars->next) - ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename); + exten = exten->next_exten; + } while ( exten ); } -static int matches_extension(char *exten, char **extout) + +void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root) { - char *c; - *extout = NULL; - c = exten; - while(*c && (*c > 32)) c++; - if (*c) { - *c = '\0'; - c++; - c = ast_skip_blanks(c); - if (*c) { - if (*c == '=') { - *c = '\0'; - c++; - if (*c == '>') - c++; - c = ast_skip_blanks(c); - *extout = c; - return 1; + 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); } - } - } - return 0; -} + + /* 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); -static void parse_keyword(char *s, char **o) -{ - char *c; - c = s; - while((*c) && (*c > 32)) c++; - if (*c) { - *c = '\0'; - c++; - c = ast_skip_blanks(c); - *o = c; - } else - *o = NULL; -} + /* 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); + } -static void handle_context(struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno) -{ - struct stringlink *argv; - struct stringlink *cur2; - struct stringlink *argv2; - struct stringlink *cur; - struct ast_context *con; - char *rest; - char *c; - char name[256]; - int pos; - - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("Root context def is '%s'\n", vars->data); - argv = split_token(vars->data, filename, lineno); - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("Found context '%s'\n", vars->data); - snprintf(name, sizeof(name), "%s", vars->data); - con = ast_context_create(local_contexts, name, registrar); - if (con) { - cur = argv; - while(cur) { - if (matches_keyword(cur->data, "includes")) { - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("--INCLUDES: '%s'\n", cur->data); - parse_keyword(cur->data, &rest); - if (rest) { - argv2 = arg_parse(rest, filename, lineno); - cur2 = argv2; - while(cur2) { - ast_context_add_include2(con, cur2->data, registrar); - cur2 = cur2->next; + 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); } - arg_free(argv2); - } - } else if (matches_keyword(cur->data, "ignorepat")) { - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("--IGNOREPAT: '%s'\n", cur->data); - parse_keyword(cur->data, &rest); - if (rest) { - argv2 = arg_parse(rest, filename, lineno); - cur2 = argv2; - while(cur2) { - ast_context_add_ignorepat2(con, cur2->data, registrar); - cur2 = cur2->next; + 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); } - arg_free(argv2); - } - } else if (matches_keyword(cur->data, "switches") || matches_keyword(cur->data, "eswitches")) { - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("--[E]SWITCH: '%s'\n", cur->data); - parse_keyword(cur->data, &rest); - if (rest) { - argv2 = arg_parse(rest, filename, lineno); - cur2 = argv2; - while(cur2) { - c = strchr(cur2->data, '/'); + 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(con, cur2->data, c, (cur->data[0] == 'e'), registrar); - cur2 = cur2->next; + + ast_context_add_switch2(context, p3->u1.str, c, 1, registrar); } - arg_free(argv2); + break; + default: + break; } - } else if (matches_extension(cur->data, &rest)) { - if (aeldebug & DEBUG_CONTEXTS) - ast_verbose("Extension: '%s' => '%s'\n", cur->data, rest); - pos = 1; - build_step("extension", cur->data, filename, lineno, con, cur->data, &pos, rest, NULL, NULL); } - cur = cur->next; - } - } else - ast_log(LOG_WARNING, "Unable to create context '%s'\n", name); - arg_free(argv); - if (vars->next) - ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename); -} - -static int handle_root_token(struct ast_context **local_contexts, char *token, int level, const char *filename, int lineno) -{ - struct stringlink *argv, *cur; - argv = split_token(token, filename, lineno); - if (aeldebug & DEBUG_TOKENS) { - ast_verbose("Found root token '%s' at level %d (%s:%d)!\n", token, level, filename, lineno); - cur = argv; - while(cur) { - ast_verbose(" ARG => '%s'\n", cur->data); - cur = cur->next; + + break; + + default: + /* huh? what? */ + break; + } } - if (!strcasecmp(token, "globals")) { - handle_globals(argv); - } else if (!strcasecmp(token, "macro")) { - handle_macro(local_contexts, argv, filename, lineno); - } else if (!strcasecmp(token, "context")) { - handle_context(local_contexts, argv, filename, lineno); - } else { - ast_log(LOG_NOTICE, "Unknown root token '%s'\n", token); - } - arg_free(argv); - return 0; } +/* interface stuff */ -static int ast_ael_compile(struct ast_context **local_contexts, const char *filename) +static int pbx_load_module(void) { + int errs, sem_err, sem_warn, sem_note; char *rfilename; - char *buf, *tbuf; - int bufsiz; - FILE *f; - char *c; - char *token; - int lineno=0; + struct ast_context *local_contexts=NULL, *con; + struct pval *parse_tree; - if (filename[0] == '/') - rfilename = (char *)filename; + ast_log(LOG_NOTICE, "Starting AEL load process.\n"); + if (config[0] == '/') + rfilename = (char *)config; else { - rfilename = alloca(strlen(filename) + strlen(ast_config_AST_CONFIG_DIR) + 2); - sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, filename); + 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, "AEL load process: calculated config file name '%s'.\n", rfilename); - f = fopen(rfilename, "r"); - if (!f) { - ast_log(LOG_WARNING, "Unable to open '%s': %s\n", rfilename, strerror(errno)); - return -1; - } - buf = malloc(4096); - if (!buf) { - ast_log(LOG_WARNING, "Out of memory!\n"); - fclose(f); - return -1; + parse_tree = ael2_parse(rfilename, &errs); + ast_log(LOG_NOTICE, "AEL 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, "AEL load process: checked config file name '%s'.\n", rfilename); + ast_compile_ael2(&local_contexts, parse_tree); + ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename); + + ast_merge_contexts_and_delete(&local_contexts, registrar); + ast_log(LOG_NOTICE, "AEL 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, "AEL 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); } - buf[0] = 0; - bufsiz = 4096; - while(!feof(f)) { - if (bufsiz - strlen(buf) < 2048) { - bufsiz += 4096; - tbuf = realloc(buf, bufsiz); - if (tbuf) { - buf = tbuf; - } else { - free(buf); - ast_log(LOG_WARNING, "Out of memory!\n"); - fclose(f); - } - } - if (fgets(buf + strlen(buf), bufsiz - strlen(buf), f)) { - lineno++; - while(*buf && buf[strlen(buf) - 1] < 33) - buf[strlen(buf) - 1] = '\0'; - c = strstr(buf, "//"); - if (c) - *c = '\0'; - if (*buf) { - if (aeldebug & DEBUG_READ) - ast_verbose("Newly composed line '%s'\n", buf); - while((token = grab_token(buf, filename, lineno))) { - handle_root_token(local_contexts, token, 0, filename, lineno); - free(token); - } - } - } - }; - free(buf); - fclose(f); - return 0; -} - -static int pbx_load_module(void) -{ - struct ast_context *local_contexts=NULL, *con; - ast_ael_compile(&local_contexts, config); - ast_merge_contexts_and_delete(&local_contexts, registrar); - for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con)) - ast_context_verify_includes(con); - + destroy_pval(parse_tree); /* free up the memory */ + return 0; } /* CLI interface */ -static int ael_debug_read(int fd, int argc, char *argv[]) +static int ael2_debug_read(int fd, int argc, char *argv[]) { aeldebug |= DEBUG_READ; return 0; } -static int ael_debug_tokens(int fd, int argc, char *argv[]) +static int ael2_debug_tokens(int fd, int argc, char *argv[]) { aeldebug |= DEBUG_TOKENS; return 0; } -static int ael_debug_macros(int fd, int argc, char *argv[]) +static int ael2_debug_macros(int fd, int argc, char *argv[]) { aeldebug |= DEBUG_MACROS; return 0; } -static int ael_debug_contexts(int fd, int argc, char *argv[]) +static int ael2_debug_contexts(int fd, int argc, char *argv[]) { aeldebug |= DEBUG_CONTEXTS; return 0; } -static int ael_no_debug(int fd, int argc, char *argv[]) +static int ael2_no_debug(int fd, int argc, char *argv[]) { aeldebug = 0; return 0; } -static int ael_reload(int fd, int argc, char *argv[]) +static int ael2_reload(int fd, int argc, char *argv[]) { ast_context_destroy(NULL, registrar); return (pbx_load_module()); } -static struct ast_cli_entry ael_cli[] = { - { { "ael", "reload", NULL }, ael_reload, "Reload AEL configuration"}, - { { "ael", "debug", "read", NULL }, ael_debug_read, "Enable AEL read debug"}, - { { "ael", "debug", "tokens", NULL }, ael_debug_tokens, "Enable AEL tokens debug"}, - { { "ael", "debug", "macros", NULL }, ael_debug_macros, "Enable AEL macros debug"}, - { { "ael", "debug", "contexts", NULL }, ael_debug_contexts, "Enable AEL contexts debug"}, - { { "ael", "no", "debug", NULL }, ael_no_debug, "Disable AEL debug messages"}, +static struct ast_cli_entry ael2_cli[] = { + { { "ael2", "reload", NULL }, ael2_reload, "Reload AEL configuration"}, + { { "ael2", "debug", "read", NULL }, ael2_debug_read, "Enable AEL read debug (does nothing)"}, + { { "ael2", "debug", "tokens", NULL }, ael2_debug_tokens, "Enable AEL tokens debug (does nothing)"}, + { { "ael2", "debug", "macros", NULL }, ael2_debug_macros, "Enable AEL macros debug (does nothing)"}, + { { "ael2", "debug", "contexts", NULL }, ael2_debug_contexts, "Enable AEL contexts debug (does nothing)"}, + { { "ael2", "no", "debug", NULL }, ael2_no_debug, "Disable AEL debug messages"}, }; /* @@ -1250,14 +3507,14 @@ static struct ast_cli_entry ael_cli[] = { static int unload_module(void *mod) { ast_context_destroy(NULL, registrar); - ast_cli_unregister_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0])); + ast_cli_unregister_multiple(ael2_cli, sizeof(ael2_cli)/ sizeof(ael2_cli[0])); return 0; } static int load_module(void *mod) { - ast_cli_register_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0])); + ast_cli_register_multiple(ael2_cli, sizeof(ael2_cli)/ sizeof(ael2_cli[0])); return (pbx_load_module()); } @@ -1269,7 +3526,7 @@ static int reload(void *mod) static const char *description(void) { - return "Asterisk Extension Language Compiler"; + return dtext; } static const char *key(void) @@ -1278,3 +3535,354 @@ static const char *key(void) } STD_MOD(MOD_1 | NO_USECOUNT, reload, NULL, NULL); + +/* 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); + } +} + +#ifdef AAL_ARGCHECK +static char *ael_funclist[] = +{ + "AGENT", + "ARRAY", + "BASE64_DECODE", + "BASE64_ENCODE", + "CALLERID", + "CDR", + "CHANNEL", + "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", + "KEYPADHASH", + "LANGUAGE", + "LEN", + "MATH", + "MD5", + "MUSICCLASS", + "QUEUEAGENTCOUNT", + "QUEUE_MEMBER_COUNT", + "QUEUE_MEMBER_LIST", + "QUOTE", + "RAND", + "REGEX", + "SET", + "SHA1", + "SIPCHANINFO", + "SIPPEER", + "SIP_HEADER", + "SORT", + "STAT", + "STRFTIME", + "STRPTIME", + "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; +} +#endif diff --git a/utils/Makefile b/utils/Makefile index 57cbb6200d..d88beee832 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -66,6 +66,22 @@ ast_expr2f.o: ../ast_expr2f.c check_expr: check_expr.c ast_expr2.o ast_expr2f.o $(CC) $(CFLAGS) -o $@ $^ +aelparse : ../pbx/ael/aelflex.o ../pbx/ael/aelbison.o ../pbx/pbx_ael.o ael_main.o ../ast_expr2f.o ../ast_expr2.o + $(CC) $(CFLAGS) -g -o aelparse ../pbx/ael/aelflex.o ../pbx/ael/aelbison.o ael_main.o ../pbx/pbx_ael.o ../ast_expr2f.o ../ast_expr2.o + +ael_main.o : ael_main.c ../include/asterisk/ael_structs.h + $(CC) $(CFLAGS) -c -g -o ael_main.o ael_main.c + +ael_main1.o : ael_main.c ../include/asterisk/ael_structs.h + $(CC) $(CFLAGS) -c -g -o ael_main1.o ael_main.c + +testexpr2s: ../ast_expr2f.c ../ast_expr2.c ../ast_expr2.h + gcc -g -c -I../include -DSTANDALONE ../ast_expr2f.c -o ast_expr2f.o + gcc -g -c -I../include -DSTANDALONE ../ast_expr2.c -o ast_expr2.o + gcc -g -o testexpr2s ast_expr2f.o ast_expr2.o + rm ast_expr2.o ast_expr2f.o + ./testexpr2s expr2.testinput + smsq.o: smsq.c $(CC) $(CFLAGS) -include ../include/autoconfig.h -c -o $@ $< diff --git a/utils/ael_main.c b/utils/ael_main.c new file mode 100644 index 0000000000..ee6e815bdc --- /dev/null +++ b/utils/ael_main.c @@ -0,0 +1,264 @@ +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <ctype.h> +#if !defined(SOLARIS) && !defined(__CYGWIN__) +#include <err.h> +#else +#define quad_t int64_t +#endif +#include <errno.h> +#include <regex.h> +#include <limits.h> +#include <asterisk/ast_expr.h> +#include <asterisk/logger.h> +#include <asterisk/module.h> +#include <asterisk/channel.h> +#include <asterisk/app.h> +#include "asterisk/ael_structs.h" +#define AST_CONFIG_MAX_PATH 255 + +int conts=0, extens=0, priors=0; +char last_exten[18000]; +char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH]; +char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH]; + +void ast_cli_register_multiple(void); +void ast_register_file_version(void); +void ast_unregister_file_version(void); +int ast_add_extension2(void *con, + int replace, const char *extension, int priority, const char *label, const char *callerid, + const char *application, void *data, void (*datad)(void *), + const char *registrar); +void pbx_builtin_setvar(void *chan, void *data); +void ast_context_create(void **extcontexts, const char *name, const char *registrar); +void ast_context_add_ignorepat2(void *con, const char *value, const char *registrar); +void ast_context_add_include2(void *con, const char *value, const char *registrar); +void ast_context_add_switch2(void *con, const char *value, const char *data, int eval, const char *registrar); +void ast_merge_contexts_and_delete(void); +void ast_context_verify_includes(void); +struct ast_context * ast_walk_contexts(void); +void ast_cli_unregister_multiple(void); +void ast_context_destroy(void); +void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...); +char *ast_process_quotes_and_slashes(char *start, char find, char replace_with); +void ast_verbose(const char *fmt, ...); +struct ast_app *pbx_findapp(const char *app); +static int no_comp = 0; +static int use_curr_dir = 0; + + +struct ast_app *pbx_findapp(const char *app) +{ + return (struct ast_app*)1; /* so as not to trigger an error */ +} + + +void ast_copy_string(char *dst, const char *src, size_t size) +{ + while (*src && size) { + *dst++ = *src++; + size--; + } + if (__builtin_expect(!size, 0)) + dst--; + *dst = '\0'; +} + +void ast_cli_register_multiple(void) +{ + if(!no_comp) + printf("Executed ast_cli_register_multiple();\n"); +} + +void ast_register_file_version(void) +{ + if(!no_comp) + printf("Executed ast_register_file_version();\n"); +} + +void ast_unregister_file_version(void) +{ + if(!no_comp) + printf("Executed ast_unregister_file_version();\n"); + +} +int ast_add_extension2(void *con, + int replace, const char *extension, int priority, const char *label, const char *callerid, + const char *application, void *data, void (*datad)(void *), + const char *registrar) +{ + priors++; + if (strcmp(extension,last_exten) != 0) { + extens++; + strcpy(last_exten, extension); + } + if (!label) { + label = "(null)"; + } + if (!callerid) { + callerid = "(null)"; + } + if (!application) { + application = "(null)"; + } + if(!no_comp) + printf("Executed ast_add_extension2(con, rep=%d, exten=%s, priority=%d, label=%s, callerid=%s, appl=%s, data=%s, FREE, registrar=%s);\n", + replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar); + + /* since add_extension2 is responsible for the malloc'd data stuff */ + if( data ) + free(data); + return 0; +} + +void pbx_builtin_setvar(void *chan, void *data) +{ + if(!no_comp) + printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data); +} + + +void ast_context_create(void **extcontexts, const char *name, const char *registrar) +{ + if(!no_comp) + printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar); + conts++; +} + +void ast_context_add_ignorepat2(void *con, const char *value, const char *registrar) +{ + if(!no_comp) + printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar); +} + +void ast_context_add_include2(void *con, const char *value, const char *registrar) +{ + if(!no_comp) + printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar); +} + +void ast_context_add_switch2(void *con, const char *value, const char *data, int eval, const char *registrar) +{ + if(!no_comp) + printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar); +} + +void ast_merge_contexts_and_delete(void) +{ + if(!no_comp) + printf("Executed ast_merge_contexts_and_delete();\n"); +} + +void ast_context_verify_includes(void) +{ + if(!no_comp) + printf("Executed ast_context_verify_includes();\n"); +} + +struct ast_context * ast_walk_contexts(void) +{ + if(!no_comp) + printf("Executed ast_walk_contexts();\n"); + return 0; +} + +void ast_cli_unregister_multiple(void) +{ + if(!no_comp) + printf("Executed ast_cli_unregister_multiple();\n"); +} + +void ast_context_destroy(void) +{ + printf("Executed ast_context_destroy();\n"); +} + +void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) +{ + va_list vars; + va_start(vars,fmt); + + printf("LOG: lev:%d file:%s line:%d func: %s ", + level, file, line, function); + vprintf(fmt, vars); + fflush(stdout); + va_end(vars); +} + +void ast_verbose(const char *fmt, ...) +{ + va_list vars; + va_start(vars,fmt); + + printf("VERBOSE: "); + vprintf(fmt, vars); + fflush(stdout); + va_end(vars); +} + +char *ast_process_quotes_and_slashes(char *start, char find, char replace_with) +{ + char *dataPut = start; + int inEscape = 0; + int inQuotes = 0; + + for (; *start; start++) { + if (inEscape) { + *dataPut++ = *start; /* Always goes verbatim */ + inEscape = 0; + } else { + if (*start == '\\') { + inEscape = 1; /* Do not copy \ into the data */ + } else if (*start == '\'') { + inQuotes = 1-inQuotes; /* Do not copy ' into the data */ + } else { + /* Replace , with |, unless in quotes */ + *dataPut++ = inQuotes ? *start : ((*start==find) ? replace_with : *start); + } + } + } + if (start != dataPut) + *dataPut = 0; + return dataPut; +} + +extern struct module_symbols mod_data; + + +int main(int argc, char **argv) +{ + int i; + + for(i=1;i<argc;i++) + { + if( argv[i][0] == '-' && argv[i][1] == 'n' ) + no_comp =1; + if( argv[i][0] == '-' && argv[i][1] == 'd' ) + use_curr_dir =1; + } + + + if( !no_comp ) + printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n"); + if( !use_curr_dir ) + printf("\n(You can use the -d option if you want to use the current working directory as the CONFIG_DIR. I will look in this dir for extensions.ael* and its included files)\n\n"); + + if( use_curr_dir ) + { + strcpy(ast_config_AST_CONFIG_DIR, "."); + } + else + { + strcpy(ast_config_AST_CONFIG_DIR, "/etc/asterisk"); + } + strcpy(ast_config_AST_VAR_DIR, "/var/lib/asterisk"); + + mod_data.load_module(0); + + ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors); + + return 0; +} diff --git a/utils/expr2.testinput b/utils/expr2.testinput new file mode 100644 index 0000000000..948baaf94e --- /dev/null +++ b/utils/expr2.testinput @@ -0,0 +1,92 @@ +2 + 2 + 2 + 2 + +2 - 4 +4 - 2 +-4 - -2 +4 + 2 * 8 +(4 + 2) * 8 +4 + (2 * 8) +4 + (2 * 8) ? 3 :: 6 +4 + 8 / 2 +4 + 8 / 3 +(4+8) / 3 +4 + 8 % 3 +4 + 9 % 3 +(4+9) %3 +(4+8) %3 +(4+9) %3 +(4+8) %3 +(4+9) % 3 +(4+8) % 3 +(4+9) % 3 +(4+8) % 3 +(4+9)% 3 +(4+8)% 3 +(4+9)% 3 +(4+8)% 3 +4 & 4 +0 & 4 +0 & 0 +2 | 0 +2 | 4 +0 | 0 +!0 | 0 +!4 | 0 +4 | !0 +!4 | !0 +3 < 4 +4 < 3 +3 > 4 +4 > 3 +3 = 3 +3 = 4 +3 != 3 +3 != 4 +3 >= 4 +3 >= 3 +4 >= 3 +3 <= 4 +4 <= 3 +4 <= 4 +3 > 4 & 4 < 3 +4 > 3 & 3 < 4 +x = x +y = x +x != y +x != x +"Something interesting" =~ interesting +"Something interesting" =~ Something +"Something interesting" : Something +"Something interesting" : interesting +"Something interesting" =~ "interesting" +"Something interesting" =~ "Something" +"Something interesting" : "Something" +"Something interesting" : "interesting" +"Something interesting" =~ (interesting) +"Something interesting" =~ (Something) +"Something interesting" : (Something) +"Something interesting" : (interesting) +"Something interesting" =~ "\(interesting\)" +"Something interesting" =~ "\(Something\)" +"Something interesting" : "\(Something\)" +"Something interesting" : "\(interesting\)" +"011043567857575" : "011\(..\)" +"9011043567857575" : "011\(..\)" +"011043567857575" =~ "011\(..\)" +"9011043567857575" =~ "011\(..\)" +"Something interesting" =~ (interesting) +"Something interesting" =~ (Something) +"Something interesting" : (Something) +"Something interesting" : (interesting) +"Something interesting" =~ "(interesting)" +"Something interesting" =~ "(Something)" +"Something interesting" : "(Something)" +"Something interesting" : "(interesting)" +"011043567857575" : "011(..)" +"9011043567857575" : "011(..)" +"011043567857575" =~ "011(..)" +"9011043567857575" =~ "011(..)" +3 +something +043 -- GitLab