/* A Bison parser, made from awkgram.y by GNU Bison version 1.28 */ #define YYBISON 1 /* Identify Bison output. */ #define FUNC_CALL 257 #define NAME 258 #define REGEXP 259 #define ERROR 260 #define YNUMBER 261 #define YSTRING 262 #define RELOP 263 #define APPEND_OP 264 #define ASSIGNOP 265 #define MATCHOP 266 #define NEWLINE 267 #define CONCAT_OP 268 #define LEX_BEGIN 269 #define LEX_END 270 #define LEX_IF 271 #define LEX_ELSE 272 #define LEX_RETURN 273 #define LEX_DELETE 274 #define LEX_WHILE 275 #define LEX_DO 276 #define LEX_FOR 277 #define LEX_BREAK 278 #define LEX_CONTINUE 279 #define LEX_PRINT 280 #define LEX_PRINTF 281 #define LEX_NEXT 282 #define LEX_EXIT 283 #define LEX_FUNCTION 284 #define LEX_GETLINE 285 #define LEX_NEXTFILE 286 #define LEX_IN 287 #define LEX_AND 288 #define LEX_OR 289 #define INCREMENT 290 #define DECREMENT 291 #define LEX_BUILTIN 292 #define LEX_LENGTH 293 #define TWOWAYIO 294 #define UNARY 295 #line 26 "awkgram.y" #ifdef GAWKDEBUG #define YYDEBUG 12 #endif #include "awk.h" #define CAN_FREE TRUE #define DONT_FREE FALSE #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ static void yyerror(const char *m, ...) ; #else static void yyerror(); /* va_alist */ #endif static char *get_src_buf P((void)); static int yylex P((void)); static NODE *node_common P((NODETYPE op)); static NODE *snode P((NODE *subn, NODETYPE op, int sindex)); static NODE *mkrangenode P((NODE *cpair)); static NODE *make_for_loop P((NODE *init, NODE *cond, NODE *incr)); static NODE *append_right P((NODE *list, NODE *new)); static void func_install P((NODE *params, NODE *def)); static void pop_var P((NODE *np, int freeit)); static void pop_params P((NODE *params)); static NODE *make_param P((char *name)); static NODE *mk_rexp P((NODE *exp)); static int dup_parms P((NODE *func)); static void param_sanity P((NODE *arglist)); static void parms_shadow P((const char *fname, NODE *func)); static int isnoeffect P((NODETYPE t)); static int isassignable P((NODE *n)); static void dumpintlstr P((char *str, size_t len)); static void count_args P((NODE *n)); enum defref { FUNC_DEFINE, FUNC_USE }; static void func_use P((char *name, enum defref how)); static void check_funcs P((void)); static int want_assign; /* lexical scanning kludge */ static int want_regexp; /* lexical scanning kludge */ static int can_return; /* lexical scanning kludge */ static int io_allowed = TRUE; /* lexical scanning kludge */ static int parsing_end_rule = FALSE; /* for warnings */ static char *lexptr; /* pointer to next char during parsing */ static char *lexend; static char *lexptr_begin; /* keep track of where we were for error msgs */ static char *lexeme; /* beginning of lexeme for debugging */ static char *thisline = NULL; #define YYDEBUG_LEXER_TEXT (lexeme) static int param_counter; static char *tokstart = NULL; static char *tok = NULL; static char *tokend; static long func_count; /* total number of functions */ #define HASHSIZE 1021 /* this constant only used here */ NODE *variables[HASHSIZE]; static int var_count; /* total number of global variables */ extern char *source; extern int sourceline; extern struct src *srcfiles; extern int numfiles; extern int errcount; extern NODE *begin_block; extern NODE *end_block; #line 96 "awkgram.y" typedef union { long lval; AWKNUM fval; NODE *nodeval; NODETYPE nodetypeval; char *sval; NODE *(*ptrval)(); } YYSTYPE; #include #ifndef __cplusplus #ifndef __STDC__ #define const #endif #endif #define YYFINAL 320 #define YYFLAG -32768 #define YYNTBASE 63 #define YYTRANSLATE(x) ((unsigned)(x) <= 295 ? yytranslate[x] : 108) static const 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, 52, 2, 2, 55, 51, 2, 2, 56, 57, 49, 47, 42, 48, 2, 50, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 41, 62, 43, 2, 44, 40, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 2, 59, 54, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 60, 45, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 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, 46, 53 }; #if YYDEBUG != 0 static const short yyprhs[] = { 0, 0, 4, 6, 9, 11, 14, 15, 16, 20, 21, 25, 28, 31, 34, 36, 39, 42, 44, 46, 48, 50, 52, 53, 61, 67, 72, 74, 78, 79, 84, 90, 95, 97, 100, 102, 105, 107, 110, 113, 116, 120, 122, 129, 138, 147, 160, 172, 175, 178, 185, 190, 193, 196, 200, 201, 206, 213, 217, 220, 222, 224, 231, 241, 243, 246, 247, 249, 250, 253, 254, 257, 260, 263, 266, 267, 269, 271, 275, 277, 280, 284, 285, 287, 288, 290, 292, 296, 298, 301, 305, 309, 310, 312, 314, 318, 320, 323, 327, 331, 332, 337, 343, 348, 353, 357, 361, 365, 369, 371, 374, 378, 382, 386, 390, 396, 398, 401, 402, 407, 411, 415, 419, 421, 424, 428, 432, 436, 442, 444, 447, 449, 453, 457, 461, 465, 469, 473, 476, 479, 482, 486, 491, 496, 498, 503, 505, 508, 511, 513, 515, 518, 521, 522, 524, 526, 531, 534, 537, 540, 542, 543, 545, 547 }; static const short yyrhs[] = { 84, 64, 84, 0, 65, 0, 64, 65, 0, 1, 0, 64, 1, 0, 0, 0, 15, 66, 76, 0, 0, 16, 67, 76, 0, 15, 78, 0, 16, 78, 0, 73, 76, 0, 76, 0, 73, 78, 0, 70, 72, 0, 4, 0, 3, 0, 69, 0, 38, 0, 39, 0, 0, 30, 71, 68, 56, 87, 104, 84, 0, 102, 77, 103, 105, 84, 0, 102, 103, 105, 84, 0, 94, 0, 94, 42, 94, 0, 0, 50, 75, 5, 50, 0, 102, 77, 103, 105, 84, 0, 102, 103, 105, 84, 0, 79, 0, 77, 79, 0, 1, 0, 77, 1, 0, 83, 0, 106, 84, 0, 106, 84, 0, 102, 103, 0, 102, 77, 103, 0, 82, 0, 21, 56, 94, 104, 84, 79, 0, 22, 84, 79, 21, 56, 94, 104, 84, 0, 23, 56, 4, 33, 4, 104, 84, 79, 0, 23, 56, 89, 106, 84, 94, 106, 84, 89, 104, 84, 79, 0, 23, 56, 89, 106, 84, 106, 84, 89, 104, 84, 79, 0, 24, 78, 0, 25, 78, 0, 81, 56, 93, 104, 86, 78, 0, 81, 90, 86, 78, 0, 28, 78, 0, 32, 78, 0, 29, 89, 78, 0, 0, 19, 80, 89, 78, 0, 20, 4, 58, 93, 59, 78, 0, 20, 4, 78, 0, 94, 78, 0, 26, 0, 27, 0, 17, 56, 94, 104, 84, 79, 0, 17, 56, 94, 104, 84, 79, 18, 84, 79, 0, 13, 0, 83, 13, 0, 0, 83, 0, 0, 43, 98, 0, 0, 44, 94, 0, 10, 94, 0, 45, 94, 0, 46, 94, 0, 0, 88, 0, 4, 0, 88, 107, 4, 0, 1, 0, 88, 1, 0, 88, 107, 1, 0, 0, 94, 0, 0, 91, 0, 96, 0, 91, 107, 96, 0, 1, 0, 91, 1, 0, 91, 1, 96, 0, 91, 107, 1, 0, 0, 93, 0, 94, 0, 93, 107, 94, 0, 1, 0, 93, 1, 0, 93, 1, 94, 0, 93, 107, 1, 0, 0, 101, 11, 95, 94, 0, 56, 93, 104, 33, 4, 0, 94, 45, 31, 100, 0, 94, 46, 31, 100, 0, 31, 100, 85, 0, 94, 34, 94, 0, 94, 35, 94, 0, 94, 12, 94, 0, 74, 0, 52, 74, 0, 94, 33, 4, 0, 94, 9, 94, 0, 94, 43, 94, 0, 94, 44, 94, 0, 94, 40, 94, 41, 94, 0, 98, 0, 94, 98, 0, 0, 101, 11, 97, 96, 0, 96, 34, 96, 0, 96, 35, 96, 0, 31, 100, 85, 0, 74, 0, 52, 74, 0, 96, 12, 96, 0, 96, 33, 4, 0, 96, 9, 96, 0, 96, 40, 96, 41, 96, 0, 98, 0, 96, 98, 0, 99, 0, 98, 54, 98, 0, 98, 49, 98, 0, 98, 50, 98, 0, 98, 51, 98, 0, 98, 47, 98, 0, 98, 48, 98, 0, 101, 36, 0, 101, 37, 0, 52, 98, 0, 56, 94, 104, 0, 38, 56, 92, 104, 0, 39, 56, 92, 104, 0, 39, 0, 3, 56, 92, 104, 0, 101, 0, 36, 101, 0, 37, 101, 0, 7, 0, 8, 0, 48, 98, 0, 47, 98, 0, 0, 101, 0, 4, 0, 4, 58, 93, 59, 0, 55, 99, 0, 60, 84, 0, 61, 84, 0, 57, 0, 0, 106, 0, 62, 0, 42, 84, 0 }; #endif #if YYDEBUG != 0 static const short yyrline[] = { 0, 157, 165, 173, 189, 190, 191, 195, 197, 211, 213, 228, 234, 240, 242, 244, 257, 266, 268, 270, 280, 281, 285, 289, 304, 309, 318, 320, 329, 331, 349, 351, 356, 362, 370, 372, 377, 378, 382, 384, 386, 388, 390, 392, 394, 422, 426, 431, 434, 437, 443, 465, 473, 492, 494, 499, 501, 503, 517, 522, 524, 529, 534, 541, 543, 547, 548, 552, 554, 559, 561, 563, 565, 567, 577, 579, 584, 586, 588, 590, 592, 598, 600, 605, 607, 612, 614, 620, 622, 624, 626, 631, 633, 638, 640, 646, 648, 650, 652, 657, 660, 665, 667, 672, 677, 683, 685, 687, 693, 703, 711, 713, 719, 721, 723, 725, 727, 732, 735, 736, 738, 740, 746, 748, 750, 752, 754, 756, 758, 760, 765, 767, 769, 771, 773, 775, 777, 779, 781, 786, 788, 790, 793, 795, 803, 810, 811, 813, 815, 817, 820, 828, 839, 841, 846, 848, 858, 863, 867, 871, 875, 876, 880, 883 }; #endif #if YYDEBUG != 0 || defined (YYERROR_VERBOSE) static const char * const yytname[] = { "$","error","$undefined.","FUNC_CALL", "NAME","REGEXP","ERROR","YNUMBER","YSTRING","RELOP","APPEND_OP","ASSIGNOP","MATCHOP", "NEWLINE","CONCAT_OP","LEX_BEGIN","LEX_END","LEX_IF","LEX_ELSE","LEX_RETURN", "LEX_DELETE","LEX_WHILE","LEX_DO","LEX_FOR","LEX_BREAK","LEX_CONTINUE","LEX_PRINT", "LEX_PRINTF","LEX_NEXT","LEX_EXIT","LEX_FUNCTION","LEX_GETLINE","LEX_NEXTFILE", "LEX_IN","LEX_AND","LEX_OR","INCREMENT","DECREMENT","LEX_BUILTIN","LEX_LENGTH", "'?'","':'","','","'<'","'>'","'|'","TWOWAYIO","'+'","'-'","'*'","'/'","'%'", "'!'","UNARY","'^'","'$'","'('","')'","'['","']'","'{'","'}'","';'","start", "program","rule","@1","@2","func_name","lex_builtin","function_prologue","@3", "function_body","pattern","regexp","@4","action","statements","statement_term", "statement","@5","print","if_statement","nls","opt_nls","input_redir","output_redir", "opt_param_list","param_list","opt_exp","opt_rexpression_list","rexpression_list", "opt_expression_list","expression_list","exp","@6","rexp","@7","simp_exp","non_post_simp_exp", "opt_variable","variable","l_brace","r_brace","r_paren","opt_semi","semi","comma", NULL }; #endif static const short yyr1[] = { 0, 63, 64, 64, 64, 64, 64, 66, 65, 67, 65, 65, 65, 65, 65, 65, 65, 68, 68, 68, 69, 69, 71, 70, 72, 72, 73, 73, 75, 74, 76, 76, 77, 77, 77, 77, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 80, 79, 79, 79, 79, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 86, 86, 86, 87, 87, 88, 88, 88, 88, 88, 89, 89, 90, 90, 91, 91, 91, 91, 91, 91, 92, 92, 93, 93, 93, 93, 93, 93, 95, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 97, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 101, 101, 101, 102, 103, 104, 105, 105, 106, 107 }; static const short yyr2[] = { 0, 3, 1, 2, 1, 2, 0, 0, 3, 0, 3, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1, 1, 0, 7, 5, 4, 1, 3, 0, 4, 5, 4, 1, 2, 1, 2, 1, 2, 2, 2, 3, 1, 6, 8, 8, 12, 11, 2, 2, 6, 4, 2, 2, 3, 0, 4, 6, 3, 2, 1, 1, 6, 9, 1, 2, 0, 1, 0, 2, 0, 2, 2, 2, 2, 0, 1, 1, 3, 1, 2, 3, 0, 1, 0, 1, 1, 3, 1, 2, 3, 3, 0, 1, 1, 3, 1, 2, 3, 3, 0, 4, 5, 4, 4, 3, 3, 3, 3, 1, 2, 3, 3, 3, 3, 5, 1, 2, 0, 4, 3, 3, 3, 1, 2, 3, 3, 3, 5, 1, 2, 1, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 4, 4, 1, 4, 1, 2, 2, 1, 1, 2, 2, 0, 1, 1, 4, 2, 2, 2, 1, 0, 1, 1, 2 }; static const short yydefact[] = { 65, 63, 66, 0, 64, 4, 0, 154, 148, 149, 7, 9, 22, 152, 0, 0, 0, 143, 0, 0, 28, 0, 0, 0, 65, 0, 2, 0, 0, 108, 14, 26, 115, 130, 145, 0, 0, 0, 162, 0, 11, 36, 65, 0, 12, 0, 67, 153, 146, 147, 0, 0, 0, 0, 151, 145, 150, 0, 109, 139, 156, 145, 95, 0, 93, 157, 5, 3, 1, 16, 0, 13, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 99, 137, 138, 34, 0, 54, 0, 0, 65, 0, 0, 0, 59, 60, 0, 81, 0, 65, 0, 32, 0, 41, 0, 0, 160, 65, 0, 0, 93, 0, 8, 37, 10, 18, 17, 20, 21, 0, 19, 0, 104, 0, 0, 0, 0, 96, 65, 159, 0, 0, 140, 0, 160, 111, 107, 110, 105, 106, 0, 27, 112, 113, 152, 152, 135, 136, 132, 133, 134, 131, 0, 0, 81, 0, 0, 0, 81, 47, 48, 51, 0, 82, 52, 158, 35, 33, 160, 87, 152, 0, 0, 122, 69, 0, 85, 128, 145, 58, 0, 39, 65, 161, 38, 144, 155, 0, 68, 141, 142, 29, 97, 163, 0, 98, 94, 160, 65, 0, 102, 103, 100, 0, 0, 0, 57, 0, 0, 154, 0, 53, 65, 67, 123, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 129, 117, 40, 31, 78, 76, 0, 0, 101, 65, 25, 114, 65, 55, 0, 65, 0, 0, 65, 30, 121, 69, 71, 70, 72, 73, 50, 89, 90, 86, 126, 124, 125, 119, 120, 0, 0, 65, 79, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 118, 23, 80, 77, 61, 56, 42, 0, 65, 0, 65, 49, 127, 65, 65, 0, 65, 81, 0, 43, 44, 81, 0, 62, 0, 65, 65, 0, 0, 46, 45, 0, 0, 0 }; static const short yydefgoto[] = { 318, 25, 26, 39, 43, 128, 129, 27, 45, 69, 28, 29, 57, 30, 109, 40, 110, 163, 111, 112, 2, 3, 131, 229, 244, 245, 171, 183, 184, 117, 118, 113, 161, 185, 274, 32, 33, 46, 34, 114, 115, 141, 191, 42, 140 }; static const short yypact[] = { 2, -32768, 4, 840,-32768,-32768, -33, -32,-32768,-32768, -4, -4,-32768, -1, -1, -1, -27, 34, 1832, 1832,-32768, 1811, 1832, 1158, 2, 898,-32768, 29, 33,-32768,-32768, 1322, 103,-32768, 72, 630, 1136, 1158,-32768, 29,-32768, 4, 2, 29,-32768, 84, 54,-32768,-32768,-32768, 1136, 1136, 1832, 1715, 53, 31, 53, 120,-32768, 53,-32768, -32768,-32768, 39, 1267,-32768,-32768,-32768,-32768,-32768, 630, -32768,-32768, 1715, 1715, 128, 1715, 1715, 1715, 1715, 1715, 1715, 104, 105, 103, 1832, 1832, 1832, 1832, 1832, 1832, -32768,-32768,-32768,-32768, 88,-32768, 130, 89, 2, 90, -4, -4,-32768,-32768, -4, 1715, -4, 2, 721,-32768, 783,-32768, 1008, 630, 86, 2, 111, 43, 1422, 10, -32768,-32768,-32768,-32768,-32768,-32768,-32768, 100,-32768, 1832, -32768, 111, 111, 1267, 119, 1715, 2,-32768, 122, 1208, -32768, 721, 86, 1886, 1869,-32768, 1522, 1472, 1372, 1422, 1886, 1886, -1, -1, 116, 116, 53, 53, 53, 53, 1715, 1715, 1715, 36, 1715, 948, 1752,-32768,-32768,-32768, -4, 1422,-32768,-32768,-32768,-32768, 86,-32768, -1, 1811, 1158,-32768, 95, 17, 1614, 103, 93,-32768, 721,-32768, 2,-32768,-32768,-32768,-32768, 9, 103,-32768,-32768,-32768, 1422,-32768, 167,-32768, 1422, 86, 2, 1715,-32768,-32768, 1422, 1267, -4, 1158,-32768, 1267, 151, -5, 86,-32768, 2, 54,-32768, 39, 1715, 1715, 1715, 1715, -4, 1774, 1230, 1774, 1774, 169, 1774, 1774, 1774, 103,-32768,-32768, -32768,-32768,-32768, 111, 44,-32768, 2,-32768, 1422, 2, -32768, 13, 2, 121, 171, 2,-32768,-32768, 95, 1422, 1422, 1422, 1422,-32768, 1614,-32768, 1614, 1280, 390,-32768, 1693, 1656, 1572, 1774, 2,-32768, 20,-32768, 948, -4, 948, 1715, 111, 1086, -4, 1774, 1614,-32768,-32768,-32768, 158,-32768,-32768, 1267, 2, 1064, 2,-32768, 1614, 2, 2, 948, 2, 1715, 948,-32768,-32768, 1715, 111,-32768, 111, 2, 2, 948, 948,-32768,-32768, 179, 180,-32768 }; static const short yypgoto[] = {-32768, -32768, 156,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 245,-32768, 78, -54, 403, 98,-32768,-32768,-32768, 210, -17, -34, -70,-32768,-32768, -161,-32768,-32768, 63, -18, -3,-32768, -194,-32768, 321, 170, -122, 97, 99, -58, 204, -142, 421, -180 }; #define YYLAST 1942 static const short yytable[] = { 31, 207, 213, 7, 231, 63, 219, 65, 68, 1, 242, 136, 143, 243, 136, 1, 142, 4, 230, 120, 64, 289, 31, 36, 290, 122, 37, -84, 255, 50, -84, 209, 210, 119, 119, 221, 265, 267, 268, 269, 136, 271, 272, 273, 136, 276, 1, 119, 119, 1, 134, 177, 137, 37, 22, 137, 190, 222, 38, 137, 189, -84, -84, -84, 247, 277, -74, 92, 93, 195, 144, 145, 280, 147, 148, 149, 150, 151, 152, -84, 287, 137, 166, 91, 206, 137, 137, 124, 125, 24, 51, 174, 299, 24, 214, 38, 138, 130, 38, 193, -92, -75, 35, 172, 239, 225, 71, 90, 92, 93, 47, 48, 49, 132, 133, 55, 55, 121, 55, 61, 202, 123, 126, 127, 35, 135, 70, 35, 55, 92, 93, 240, 146, 201, 164, 153, 154, 205, 35, 226, 227, 228, 35, 309, 162, 165, 167, 311, 38, 55, 85, 86, 87, 88, 89, 203, 196, 90, 211, 212, 172, 55, 216, 224, 172, 87, 88, 89, 138, 200, 90, 246, 254, 270, 241, 283, 300, 282, 64, 319, 320, 67, 55, 55, 55, 55, 55, 55, 258, 285, 248, 0, 60, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 257, 249, 0, 176, 187, 0, 55, 119, 0, 0, 0, 0, 55, 0, 0, 0, 41, 41, 260, 261, 262, 263, 0, 55, 0, 0, 278, 55, 0, 279, 0, 0, 281, 0, 41, 284, 176, 55, 55, 0, 55, 55, 55, 55, 55, 55, 47, 47, 0, 0, 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, 217, 0, 58, 139, 0, 55, 0, 0, 0, 0, 0, 0, 47, 55, 302, 294, 304, 296, 55, 305, 306, 0, 308, 176, 0, 0, 0, 0, 0, 0, 0, 314, 315, 0, 55, 0, 0, 172, 55, 0, 0, 172, 0, 0, 55, 55, 0, 41, 41, 55, 0, 41, 0, 41, 0, 0, 0, 194, 0, 41, 0, 0, 0, 187, 187, 187, 187, 0, 187, 187, 187, 0, 198, 199, 0, 54, 56, 0, 59, 0, 0, 0, 55, 0, 0, 0, 0, 0, 84, 0, 0, 0, 182, 55, 55, 55, 55, 0, 55, 0, 55, 55, 55, 0, 55, 55, 55, 187, 0, 59, 41, 0, 0, 291, 0, 293, 0, 41, 0, 187, 55, 84, 0, 0, 0, 0, 0, 55, 0, 55, 7, 0, 55, 8, 9, 232, 307, 0,-32768, 310, 0, 0, 155, 156, 157, 158, 159, 160, 316, 317, 44, 0, 250, 0, 0, 0, 253, 0, 0, 41, 0, 223, 14, 15, 259, 0, 0, 72, 186, 0, 84, 0, 0, 18, 19, 41, 84, 0, 52, 0, 0, 22, 53, 0, 275, 0, 0, 197, 0, 0, 0, 84, 116, 0, 0, 0, 0, 0, 0, 0, 0, 84, 84, 0, 84, 84, 84, 84, 84, 84, 0, 182, 182, 182, 182, 0, 182, 182, 182, 0, 0, 0, 0, 295, 0, 0, 41, 116, 0, 84, 0, 41, 0, 0, 301, 0, 0, 59, 0, 0, 168, 169, 238, 0, 170, 0, 173, 0, 0, 312, 0, 313, 188, 0, 0, 182, 0, 0, 84, 0, 0, 0, 84, 0, 0, 0, 116, 182, 84, 84, 0, 116, 192, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186, 186, 186, 186, 0, 186, 186, 186, 0, 0, 0, 0, 116, 192, 0, 0, 215, 0, 0, 84, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 84, 84, 84, 84, 0, 238, 116, 238, 238, 238, 0, 238, 238, 238, 186, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 186, 238, 0, 116, 0, 0, 0, 0, 84, 251, 84, 0, 0, 238, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 94, 264, 6, 7, 0, 0, 8, 9, 0, 256, 0, 0, 0, 0, 0, 0, 95, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 0, 13, 107, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 292, 0, 22, 23, 0, 298, 0, 24, 108, 38, 0, 0, 0, 0, 0, 0, 0, 116, 0, 116, 0, 0, 297, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 303, 0, 0, 0, 0, 175, 116, 6, 7, 116, 0, 8, 9, 0, 0, 0, 0, 0, 116, 116, 0, 95, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 0, 13, 107, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 0, 0, 22, 23, 0, 0, 0, 24, 108, 38, 178, 0, 6, 7, 0, 0, 8, 9, 0, -83, 0, 0, -83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 179, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, -83, -83, -83, 18, 19, 0, 20, 0, 180, 0, 0, 22, 181, -6, 5, 0, 6, 7, -83, 0, 8, 9, 0, 0, 0, 0, -6, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 0, 0, 22, 23, 0, -65, 66, 24, 6, 7, 0, 0, 8, 9, 0, 0, 0, 0, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 6, 7, 22, 23, 8, 9, 0, 24, 0, 0, 0, 0, 0, 0, 95, 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 0, 13, 107, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 0, 0, 22, 23, 0, 0, 0, 24, 0, 38, 6, 7, 0, 0, 8, 9, 73, 0, 0, 74, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 0, 0, 22, 53, 0, 0, 6, 7, 0, 38, 8, 9, 73, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 9, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 13, 0, 22, 53, 0, 14, 15, 16, 17, 38, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 62, 21, 6, 7, 22, 23, 8, 9, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 6, 7, 0, 0, 8, 9, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 13, 0, 22, 23, -91, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 204, 21, 6, 7, 22, 23, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 266, 0, 6, 7, 0, 0, 8, 9, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 179, 0, 22, 23, 0, 14, 15, 16, 17, 6, 7, 0, 0, 8, 9, 73, 18, 19, 74, 20, 0, 180, 0, 7, 22, 53, 8, 9,-32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 0, 0, 80, 81, 82, 83, 18, 19, 14, 15, 0, 52, 0, 0, 22, 53, 138, 6, 7, 18, 19, 8, 9, 73, 52, 0, 74, 22, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 0, 79, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 6, 7, 22, 53, 8, 9, 73, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 208, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 6, 7, 22, 53, 8, 9, 73, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 77, 14, 15, 16, 17, 78, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 6, 7, 22, 53, 8, 9, 73, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 76, 0, 14, 15, 16, 17, 0, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 6, 7, 22, 53, 8, 9, 73, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 14, 15, 16, 17, 0, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 6, 7, 22, 53, 8, 9, 232, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 235, 236, 14, 15, 16, 17, 237, 286, 0, 0, 0, 6, 7, 18, 19, 8, 9, 232, 52, 0, 233, 22, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 235, 236, 14, 15, 16, 17, 237, 0, 0, 0, 0, 6, 7, 18, 19, 8, 9, 232, 52, 0, 233, 22, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 235, 0, 14, 15, 16, 17, 6, 7, 0, 0, 8, 9, 232, 18, 19, 233, 0, 0, 52, 0, 0, 22, 53, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 9, 0, 0, 234, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 0, 0, 52, 13, 0, 22, 53, 0, 14, 15, 16, 17, 6, 218, 0, 0, 8, 9, 0, 18, 19, 0, 20, 0, 21, 0, 0, 22, 23, 0, 0, 0, 0, 0, 6, 7, 0, 0, 8, 9, 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 21, 179, 0, 22, 23, 0, 14, 15, 16, 17, 6, 7, 0, 0, 8, 9, 0, 18, 19, 0, 20, 0, 180, 0, 0, 22, 53, 0, 0, 0, 0, 6, 7, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, 0, 0, 18, 19, 0, 20, 0, 52, 0, 0, 22, 53, 14, 15, 16, 17, 0, 7, 0, 0, 8, 9, 73, 18, 19, -32768, 0, 0, 52, 0, 0, 22, 53, 0, 7, 0, 0, 8, 9,-32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 0, 0, 0, 0, 0, 80, 81, 82, 83, 18, 19, 0, 0, 0, 52, 14, 15, 22, 53, 0, 0, 0,-32768,-32768, -32768,-32768, 18, 19, 0, 0, 0, 52, 0, 0, 22, 53 }; static const short yycheck[] = { 3, 143, 163, 4, 184, 23, 167, 24, 25, 13, 1, 1, 70, 4, 1, 13, 70, 13, 1, 37, 23, 1, 25, 56, 4, 42, 58, 10, 33, 56, 13, 153, 154, 36, 37, 177, 230, 231, 232, 233, 1, 235, 236, 237, 1, 1, 13, 50, 51, 13, 53, 109, 42, 58, 55, 42, 114, 179, 62, 42, 114, 44, 45, 46, 206, 245, 57, 36, 37, 59, 73, 74, 59, 76, 77, 78, 79, 80, 81, 62, 274, 42, 99, 11, 142, 42, 42, 3, 4, 60, 56, 108, 286, 60, 58, 62, 57, 43, 62, 116, 57, 57, 3, 106, 11, 10, 28, 54, 36, 37, 13, 14, 15, 50, 51, 18, 19, 39, 21, 22, 137, 43, 38, 39, 25, 5, 27, 28, 31, 36, 37, 189, 4, 136, 4, 31, 31, 140, 39, 44, 45, 46, 43, 304, 56, 56, 56, 308, 62, 52, 47, 48, 49, 50, 51, 33, 56, 54, 161, 162, 163, 64, 165, 181, 167, 49, 50, 51, 57, 50, 54, 4, 21, 4, 191, 4, 18, 56, 181, 0, 0, 25, 85, 86, 87, 88, 89, 90, 222, 259, 207, -1, 22, -1, -1, -1, 214, -1, -1, -1, -1, -1, -1, -1, 221, 208, -1, 109, 111, -1, 113, 214, -1, -1, -1, -1, 119, -1, -1, -1, 10, 11, 225, 226, 227, 228, -1, 130, -1, -1, 247, 134, -1, 250, -1, -1, 253, -1, 28, 256, 142, 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, -1, -1, -1, -1, -1, -1, 275, -1, -1, -1, -1, -1, 166, -1, 21, 63, -1, 172, -1, -1, -1, -1, -1, -1, 179, 180, 295, 282, 297, 284, 185, 300, 301, -1, 303, 189, -1, -1, -1, -1, -1, -1, -1, 312, 313, -1, 201, -1, -1, 304, 205, -1, -1, 308, -1, -1, 211, 212, -1, 101, 102, 216, -1, 105, -1, 107, -1, -1, -1, 117, -1, 113, -1, -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, -1, 132, 133, -1, 18, 19, -1, 21, -1, -1, -1, 249, -1, -1, -1, -1, -1, 31, -1, -1, -1, 111, 260, 261, 262, 263, -1, 265, -1, 267, 268, 269, -1, 271, 272, 273, 274, -1, 52, 164, -1, -1, 279, -1, 281, -1, 171, -1, 286, 287, 64, -1, -1, -1, -1, -1, 294, -1, 296, 4, -1, 299, 7, 8, 9, 302, -1, 12, 305, -1, -1, 85, 86, 87, 88, 89, 90, 314, 315, 11, -1, 212, -1, -1, -1, 216, -1, -1, 213, -1, 180, 36, 37, 224, -1, -1, 28, 111, -1, 113, -1, -1, 47, 48, 229, 119, -1, 52, -1, -1, 55, 56, -1, 244, -1, -1, 130, -1, -1, -1, 134, 35, -1, -1, -1, -1, -1, -1, -1, -1, 144, 145, -1, 147, 148, 149, 150, 151, 152, -1, 230, 231, 232, 233, -1, 235, 236, 237, -1, -1, -1, -1, 283, -1, -1, 280, 70, -1, 172, -1, 285, -1, -1, 294, -1, -1, 180, -1, -1, 101, 102, 185, -1, 105, -1, 107, -1, -1, 309, -1, 311, 113, -1, -1, 274, -1, -1, 201, -1, -1, -1, 205, -1, -1, -1, 109, 286, 211, 212, -1, 114, 115, 216, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, -1, -1, -1, -1, 142, 143, -1, -1, 164, -1, -1, 249, -1, -1, -1, 171, -1, -1, -1, -1, -1, -1, 260, 261, 262, 263, -1, 265, 166, 267, 268, 269, -1, 271, 272, 273, 274, -1, -1, 177, -1, -1, -1, -1, -1, -1, -1, -1, 286, 287, -1, 189, -1, -1, -1, -1, 294, 213, 296, -1, -1, 299, -1, -1, -1, -1, -1, -1, 206, -1, -1, -1, 1, 229, 3, 4, -1, -1, 7, 8, -1, 219, -1, -1, -1, -1, -1, -1, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, 280, -1, 55, 56, -1, 285, -1, 60, 61, 62, -1, -1, -1, -1, -1, -1, -1, 279, -1, 281, -1, -1, 284, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 296, -1, -1, -1, -1, 1, 302, 3, 4, 305, -1, 7, 8, -1, -1, -1, -1, -1, 314, 315, -1, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, -1, -1, -1, 60, 61, 62, 1, -1, 3, 4, -1, -1, 7, 8, -1, 10, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, 44, 45, 46, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, 0, 1, -1, 3, 4, 62, -1, 7, 8, -1, -1, -1, -1, 13, -1, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, -1, 0, 1, 60, 3, 4, -1, -1, 7, 8, -1, -1, -1, -1, 13, -1, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, 3, 4, 55, 56, 7, 8, -1, 60, -1, -1, -1, -1, -1, -1, 17, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -1, 31, 32, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, -1, -1, -1, 60, -1, 62, 3, 4, -1, -1, 7, 8, 9, -1, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, -1, -1, 55, 56, -1, -1, 3, 4, -1, 62, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, 8, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 31, -1, 55, 56, -1, 36, 37, 38, 39, 62, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, 1, 52, 3, 4, 55, 56, 7, 8, -1, -1, -1, 62, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, -1, -1, 7, 8, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, 31, -1, 55, 56, 57, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, 1, 52, 3, 4, 55, 56, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 3, 4, -1, -1, 7, 8, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, 31, -1, 55, 56, -1, 36, 37, 38, 39, 3, 4, -1, -1, 7, 8, 9, 47, 48, 12, 50, -1, 52, -1, 4, 55, 56, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, 48, 36, 37, -1, 52, -1, -1, 55, 56, 57, 3, 4, 47, 48, 7, 8, 9, 52, -1, 12, 55, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, 42, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 3, 4, 55, 56, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 3, 4, 55, 56, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 3, 4, 55, 56, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, -1, 36, 37, 38, 39, -1, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 3, 4, 55, 56, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, 36, 37, 38, 39, -1, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 3, 4, 55, 56, 7, 8, 9, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, 3, 4, 47, 48, 7, 8, 9, 52, -1, 12, 55, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, 3, 4, 47, 48, 7, 8, 9, 52, -1, 12, 55, 56, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 34, -1, 36, 37, 38, 39, 3, 4, -1, -1, 7, 8, 9, 47, 48, 12, -1, -1, 52, -1, -1, 55, 56, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, 8, -1, -1, 33, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, -1, -1, 52, 31, -1, 55, 56, -1, 36, 37, 38, 39, 3, 4, -1, -1, 7, 8, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, 8, 31, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, 31, -1, 55, 56, -1, 36, 37, 38, 39, 3, 4, -1, -1, 7, 8, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, -1, -1, -1, -1, 3, 4, -1, -1, 7, 8, -1, -1, -1, -1, -1, -1, 36, 37, 38, 39, -1, -1, -1, -1, -1, -1, -1, 47, 48, -1, 50, -1, 52, -1, -1, 55, 56, 36, 37, 38, 39, -1, 4, -1, -1, 7, 8, 9, 47, 48, 12, -1, -1, 52, -1, -1, 55, 56, -1, 4, -1, -1, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, 37, -1, -1, -1, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, 36, 37, 55, 56, -1, -1, -1, 43, 44, 45, 46, 47, 48, -1, -1, -1, 52, -1, -1, 55, 56 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ #line 3 "/usr/lib/bison.simple" /* This file comes from bison-1.28. */ /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* This is the parser code that is written into each bison parser when the %semantic_parser declaration is not specified in the grammar. It was written by Richard Stallman by simplifying the hairy parser used when %semantic_parser is specified. */ #ifndef YYSTACK_USE_ALLOCA #ifdef alloca #define YYSTACK_USE_ALLOCA #else /* alloca not defined */ #ifdef __GNUC__ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #else /* not GNU C. */ #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) #define YYSTACK_USE_ALLOCA #include #else /* not sparc */ /* We think this test detects Watcom and Microsoft C. */ /* This used to test MSDOS, but that is a bad idea since that symbol is in the user namespace. */ #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) #if 0 /* No need for malloc.h, which pollutes the namespace; instead, just don't use alloca. */ #include #endif #else /* not MSDOS, or __TURBOC__ */ #if defined(_AIX) /* I don't know what this was needed for, but it pollutes the namespace. So I turned it off. rms, 2 May 1997. */ /* #include */ #pragma alloca #define YYSTACK_USE_ALLOCA #else /* not MSDOS, or __TURBOC__, or _AIX */ #if 0 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, and on HPUX 10. Eventually we can turn this on. */ #define YYSTACK_USE_ALLOCA #define alloca __builtin_alloca #endif /* __hpux */ #endif #endif /* not _AIX */ #endif /* not MSDOS, or __TURBOC__ */ #endif /* not sparc */ #endif /* not GNU C */ #endif /* alloca not defined */ #endif /* YYSTACK_USE_ALLOCA not defined */ #undef YYSTACK_USE_ALLOCA /* Gawk: nuke alloca once and for all */ #ifdef YYSTACK_USE_ALLOCA #define YYSTACK_ALLOC alloca #else #define YYSTACK_ALLOC malloc #endif /* Note: there must be only one dollar sign in this file. It is replaced by the list of actions, each action as one case of the switch. */ #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 yyerrlab1 /* 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); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 #ifndef YYPURE #define YYLEX yylex() #endif #ifdef YYPURE #ifdef YYLSP_NEEDED #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) #else #define YYLEX yylex(&yylval, &yylloc) #endif #else /* not YYLSP_NEEDED */ #ifdef YYLEX_PARAM #define YYLEX yylex(&yylval, YYLEX_PARAM) #else #define YYLEX yylex(&yylval) #endif #endif /* not YYLSP_NEEDED */ #endif /* If nonreentrant, generate the variables here */ #ifndef YYPURE int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ #ifdef YYLSP_NEEDED YYLTYPE yylloc; /* location data for the lookahead */ /* symbol */ #endif int yynerrs; /* number of parse errors so far */ #endif /* not YYPURE */ #if YYDEBUG != 0 int yydebug; /* nonzero means print parse trace */ /* Since this is uninitialized, it does not stop multiple parsers from coexisting. */ #endif /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #if YYMAXDEPTH == 0 #undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH #define YYMAXDEPTH 10000 #endif /* Define __yy_memcpy. Note that the size argument should be passed with type unsigned int, because that is what the non-GCC definitions require. With GCC, __builtin_memcpy takes an arg of type size_t, but it can handle unsigned int. */ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) #else /* not GNU C or C++ */ #ifndef __cplusplus /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (to, from, count) char *to; char *from; unsigned int count; { register char *f = from; register char *t = to; register int i = count; while (i-- > 0) *t++ = *f++; } #else /* __cplusplus */ /* This is the most reliable way to avoid incompatibilities in available built-in functions on various systems. */ static void __yy_memcpy (char *to, char *from, unsigned int count) { register char *t = to; register char *f = from; register int i = count; while (i-- > 0) *t++ = *f++; } #endif #endif #line 217 "/usr/lib/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. It should actually point to an object. Grammar actions can access the variable by casting it to the proper pointer type. */ #ifdef YYPARSE_PARAM #ifdef __cplusplus #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM #define YYPARSE_PARAM_DECL #else /* not __cplusplus */ #define YYPARSE_PARAM_ARG YYPARSE_PARAM #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; #endif /* not __cplusplus */ #else /* not YYPARSE_PARAM */ #define YYPARSE_PARAM_ARG #define YYPARSE_PARAM_DECL #endif /* not YYPARSE_PARAM */ /* Prevent warning if -Wstrict-prototypes. */ #ifdef __GNUC__ #ifdef YYPARSE_PARAM int yyparse (void *); #else int yyparse (void); #endif #endif int yyparse(YYPARSE_PARAM_ARG) YYPARSE_PARAM_DECL { register int yystate; register int yyn; register short *yyssp; register YYSTYPE *yyvsp; int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yychar1 = 0; /* lookahead token as an internal (translated) token number */ short yyssa[YYINITDEPTH]; /* the state stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ short *yyss = yyssa; /* refer to the stacks thru separate pointers */ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ #ifdef YYLSP_NEEDED YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ YYLTYPE *yyls = yylsa; YYLTYPE *yylsp; #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) #else #define YYPOPSTACK (yyvsp--, yyssp--) #endif int yystacksize = YYINITDEPTH; int yyfree_stacks = 0; #ifdef YYPURE int yychar; YYSTYPE yylval; int yynerrs; #ifdef YYLSP_NEEDED YYLTYPE yylloc; #endif #endif YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Starting parse\n"); #endif 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 - 1; yyvsp = yyvs; #ifdef YYLSP_NEEDED yylsp = yyls; #endif /* Push a new state, which is found in yystate . */ /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yynewstate: *++yyssp = yystate; if (yyssp >= yyss + yystacksize - 1) { /* Give user a chance to reallocate the stack */ /* Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; #ifdef YYLSP_NEEDED YYLTYPE *yyls1 = yyls; #endif /* Get the current used size of the three stacks, in elements. */ int size = yyssp - yyss + 1; #ifdef yyoverflow /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. */ #ifdef YYLSP_NEEDED /* This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yyls1, size * sizeof (*yylsp), &yystacksize); #else yyoverflow("parser stack overflow", &yyss1, size * sizeof (*yyssp), &yyvs1, size * sizeof (*yyvsp), &yystacksize); #endif yyss = yyss1; yyvs = yyvs1; #ifdef YYLSP_NEEDED yyls = yyls1; #endif #else /* no yyoverflow */ /* Extend the stack our own way. */ if (yystacksize >= YYMAXDEPTH) { yyerror("parser stack overflow"); if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 2; } yystacksize *= 2; if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; #ifndef YYSTACK_USE_ALLOCA yyfree_stacks = 1; #endif yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); __yy_memcpy ((char *)yyss, (char *)yyss1, size * (unsigned int) sizeof (*yyssp)); yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * (unsigned int) sizeof (*yyvsp)); #ifdef YYLSP_NEEDED yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); __yy_memcpy ((char *)yyls, (char *)yyls1, size * (unsigned int) sizeof (*yylsp)); #endif #endif /* no yyoverflow */ yyssp = yyss + size - 1; yyvsp = yyvs + size - 1; #ifdef YYLSP_NEEDED yylsp = yyls + size - 1; #endif #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Stack size increased to %d\n", yystacksize); #endif if (yyssp >= yyss + yystacksize - 1) YYABORT; } #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Entering state %d\n", yystate); #endif goto yybackup; yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* yychar is either YYEMPTY or YYEOF or a valid token in external form. */ if (yychar == YYEMPTY) { #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Reading a token: "); #endif yychar = YYLEX; } /* Convert token to internal form (in yychar1) for indexing tables with */ if (yychar <= 0) /* This means end of input. */ { yychar1 = 0; yychar = YYEOF; /* Don't call YYLEX any more */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Now at end of input.\n"); #endif } else { yychar1 = YYTRANSLATE(yychar); #if YYDEBUG != 0 if (yydebug) { fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ #ifdef YYPRINT YYPRINT (stderr, yychar, yylval); #endif fprintf (stderr, ")\n"); } #endif } yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; yyn = yytable[yyn]; /* yyn is what to do for this token type in this state. Negative => reduce, -yyn is rule number. Positive => shift, yyn is new state. New state is final state => don't bother to shift, just return success. 0, or most negative number => error. */ if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); #endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif /* count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* Do the default action for the current state. */ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; /* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: yylen = yyr2[yyn]; if (yylen > 0) yyval = yyvsp[1-yylen]; /* implement default value of the action */ #if YYDEBUG != 0 if (yydebug) { int i; fprintf (stderr, "Reducing via rule %d (line %d), ", yyn, yyrline[yyn]); /* Print the symbols being reduced, and their result. */ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) fprintf (stderr, "%s ", yytname[yyrhs[i]]); fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); } #endif switch (yyn) { case 1: #line 158 "awkgram.y" { expression_value = yyvsp[-1].nodeval; check_funcs(); ; break;} case 2: #line 166 "awkgram.y" { if (yyvsp[0].nodeval != NULL) yyval.nodeval = yyvsp[0].nodeval; else yyval.nodeval = NULL; yyerrok; ; break;} case 3: #line 175 "awkgram.y" { if (yyvsp[0].nodeval == NULL) yyval.nodeval = yyvsp[-1].nodeval; else if (yyvsp[-1].nodeval == NULL) yyval.nodeval = yyvsp[0].nodeval; else { if (yyvsp[-1].nodeval->type != Node_rule_list) yyvsp[-1].nodeval = node(yyvsp[-1].nodeval, Node_rule_list, (NODE*) NULL); yyval.nodeval = append_right(yyvsp[-1].nodeval, node(yyvsp[0].nodeval, Node_rule_list, (NODE *) NULL)); } yyerrok; ; break;} case 4: #line 189 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 5: #line 190 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 6: #line 191 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 7: #line 195 "awkgram.y" { io_allowed = FALSE; ; break;} case 8: #line 197 "awkgram.y" { if (begin_block != NULL) { if (begin_block->type != Node_rule_list) begin_block = node(begin_block, Node_rule_list, (NODE *) NULL); (void) append_right(begin_block, node( node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval), Node_rule_list, (NODE *) NULL) ); } else begin_block = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval); yyval.nodeval = NULL; io_allowed = TRUE; yyerrok; ; break;} case 9: #line 211 "awkgram.y" { io_allowed = FALSE; parsing_end_rule = TRUE; ; break;} case 10: #line 213 "awkgram.y" { if (end_block != NULL) { if (end_block->type != Node_rule_list) end_block = node(end_block, Node_rule_list, (NODE *) NULL); (void) append_right (end_block, node( node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval), Node_rule_list, (NODE *) NULL)); } else end_block = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval); yyval.nodeval = NULL; io_allowed = TRUE; parsing_end_rule = FALSE; yyerrok; ; break;} case 11: #line 229 "awkgram.y" { warning(_("BEGIN blocks must have an action part")); errcount++; yyerrok; ; break;} case 12: #line 235 "awkgram.y" { warning(_("END blocks must have an action part")); errcount++; yyerrok; ; break;} case 13: #line 241 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_rule_node, yyvsp[0].nodeval); yyerrok; ; break;} case 14: #line 243 "awkgram.y" { yyval.nodeval = node((NODE *) NULL, Node_rule_node, yyvsp[0].nodeval); yyerrok; ; break;} case 15: #line 245 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_rule_node, node(node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL), Node_K_print, (NODE *) NULL)); yyerrok; ; break;} case 16: #line 258 "awkgram.y" { func_install(yyvsp[-1].nodeval, yyvsp[0].nodeval); yyval.nodeval = NULL; yyerrok; ; break;} case 17: #line 267 "awkgram.y" { yyval.sval = yyvsp[0].sval; ; break;} case 18: #line 269 "awkgram.y" { yyval.sval = yyvsp[0].sval; ; break;} case 19: #line 271 "awkgram.y" { yyerror(_("`%s' is a built-in function, it cannot be redefined"), tokstart); errcount++; /* yyerrok; */ ; break;} case 22: #line 286 "awkgram.y" { param_counter = 0; ; break;} case 23: #line 290 "awkgram.y" { NODE *t; t = make_param(yyvsp[-4].sval); t->flags |= FUNC; yyval.nodeval = append_right(t, yyvsp[-2].nodeval); can_return = TRUE; /* check for duplicate parameter names */ if (dup_parms(yyval.nodeval)) errcount++; ; break;} case 24: #line 305 "awkgram.y" { yyval.nodeval = yyvsp[-3].nodeval; can_return = FALSE; ; break;} case 25: #line 310 "awkgram.y" { yyval.nodeval = node((NODE *) NULL, Node_K_return, (NODE *) NULL); can_return = FALSE; ; break;} case 26: #line 319 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 27: #line 321 "awkgram.y" { yyval.nodeval = mkrangenode(node(yyvsp[-2].nodeval, Node_cond_pair, yyvsp[0].nodeval)); ; break;} case 28: #line 330 "awkgram.y" { ++want_regexp; ; break;} case 29: #line 332 "awkgram.y" { NODE *n; size_t len; getnode(n); n->type = Node_regex; len = strlen(yyvsp[-1].sval); n->re_exp = make_string(yyvsp[-1].sval, len); n->re_reg = make_regexp(yyvsp[-1].sval, len, FALSE, TRUE); n->re_text = NULL; n->re_flags = CONST; n->re_cnt = 1; yyval.nodeval = n; ; break;} case 30: #line 350 "awkgram.y" { yyval.nodeval = yyvsp[-3].nodeval; ; break;} case 31: #line 352 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 32: #line 357 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; if (do_lint && isnoeffect(yyval.nodeval->type)) lintwarn(_("statement may have no effect")); ; break;} case 33: #line 363 "awkgram.y" { if (yyvsp[-1].nodeval == NULL || yyvsp[-1].nodeval->type != Node_statement_list) yyvsp[-1].nodeval = node(yyvsp[-1].nodeval, Node_statement_list, (NODE *) NULL); yyval.nodeval = append_right(yyvsp[-1].nodeval, node(yyvsp[0].nodeval, Node_statement_list, (NODE *) NULL)); yyerrok; ; break;} case 34: #line 371 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 35: #line 373 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 38: #line 383 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 39: #line 385 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 40: #line 387 "awkgram.y" { yyval.nodeval = yyvsp[-1].nodeval; ; break;} case 41: #line 389 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 42: #line 391 "awkgram.y" { yyval.nodeval = node(yyvsp[-3].nodeval, Node_K_while, yyvsp[0].nodeval); ; break;} case 43: #line 393 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_K_do, yyvsp[-5].nodeval); ; break;} case 44: #line 395 "awkgram.y" { /* * Efficiency hack. Recognize the special case of * * for (iggy in foo) * delete foo[iggy] * * and treat it as if it were * * delete foo * * Check that the body is a `delete a[i]' statement, * and that both the loop var and array names match. */ if (yyvsp[0].nodeval != NULL && yyvsp[0].nodeval->type == Node_K_delete && yyvsp[0].nodeval->rnode != NULL && (yyvsp[0].nodeval->rnode->type == Node_var || yyvsp[0].nodeval->rnode->type == Node_param_list) && strcmp(yyvsp[-5].sval, yyvsp[0].nodeval->rnode->var_value->vname) == 0 && strcmp(yyvsp[-3].sval, yyvsp[0].nodeval->lnode->vname) == 0) { yyvsp[0].nodeval->type = Node_K_delete_loop; yyval.nodeval = yyvsp[0].nodeval; } else { yyval.nodeval = node(yyvsp[0].nodeval, Node_K_arrayfor, make_for_loop(variable(yyvsp[-5].sval, CAN_FREE, Node_var), (NODE *) NULL, variable(yyvsp[-3].sval, CAN_FREE, Node_var_array))); } ; break;} case 45: #line 423 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_K_for, (NODE *) make_for_loop(yyvsp[-9].nodeval, yyvsp[-6].nodeval, yyvsp[-3].nodeval)); ; break;} case 46: #line 427 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_K_for, (NODE *) make_for_loop(yyvsp[-8].nodeval, (NODE *) NULL, yyvsp[-3].nodeval)); ; break;} case 47: #line 433 "awkgram.y" { yyval.nodeval = node((NODE *) NULL, Node_K_break, (NODE *) NULL); ; break;} case 48: #line 436 "awkgram.y" { yyval.nodeval = node((NODE *) NULL, Node_K_continue, (NODE *) NULL); ; break;} case 49: #line 438 "awkgram.y" { yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-5].nodetypeval, yyvsp[-1].nodeval); if (yyval.nodeval->type == Node_K_printf) count_args(yyval.nodeval) ; break;} case 50: #line 444 "awkgram.y" { if (yyvsp[-3].nodetypeval == Node_K_print && yyvsp[-2].nodeval == NULL) { static int warned = FALSE; yyvsp[-2].nodeval = node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL); if (do_lint && ! io_allowed && ! warned) { warned = TRUE; lintwarn( _("plain `print' in BEGIN or END rule should probably be `print \"\"'")); } } yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-3].nodetypeval, yyvsp[-1].nodeval); if (yyval.nodeval->type == Node_K_printf) count_args(yyval.nodeval) ; break;} case 51: #line 466 "awkgram.y" { NODETYPE type; if (! io_allowed) yyerror(_("`next' used in BEGIN or END action")); type = Node_K_next; yyval.nodeval = node((NODE *) NULL, type, (NODE *) NULL); ; break;} case 52: #line 474 "awkgram.y" { if (do_lint) lintwarn(_("`nextfile' is a gawk extension")); if (do_traditional) { /* * can't use yyerror, since may have overshot * the source line */ errcount++; error(_("`nextfile' is a gawk extension")); } if (! io_allowed) { /* same thing */ errcount++; error(_("`nextfile' used in BEGIN or END action")); } yyval.nodeval = node((NODE *) NULL, Node_K_nextfile, (NODE *) NULL); ; break;} case 53: #line 493 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_exit, (NODE *) NULL); ; break;} case 54: #line 495 "awkgram.y" { if (! can_return) yyerror(_("`return' used outside function context")); ; break;} case 55: #line 500 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_return, (NODE *) NULL); ; break;} case 56: #line 502 "awkgram.y" { yyval.nodeval = node(variable(yyvsp[-4].sval, CAN_FREE, Node_var_array), Node_K_delete, yyvsp[-2].nodeval); ; break;} case 57: #line 504 "awkgram.y" { if (do_lint) lintwarn(_("`delete array' is a gawk extension")); if (do_traditional) { /* * can't use yyerror, since may have overshot * the source line */ errcount++; error(_("`delete array' is a gawk extension")); } yyval.nodeval = node(variable(yyvsp[-1].sval, CAN_FREE, Node_var_array), Node_K_delete, (NODE *) NULL); ; break;} case 58: #line 518 "awkgram.y" { yyval.nodeval = yyvsp[-1].nodeval; ; break;} case 59: #line 523 "awkgram.y" { yyval.nodetypeval = yyvsp[0].nodetypeval; ; break;} case 60: #line 525 "awkgram.y" { yyval.nodetypeval = yyvsp[0].nodetypeval; ; break;} case 61: #line 530 "awkgram.y" { yyval.nodeval = node(yyvsp[-3].nodeval, Node_K_if, node(yyvsp[0].nodeval, Node_if_branches, (NODE *) NULL)); ; break;} case 62: #line 536 "awkgram.y" { yyval.nodeval = node(yyvsp[-6].nodeval, Node_K_if, node(yyvsp[-3].nodeval, Node_if_branches, yyvsp[0].nodeval)); ; break;} case 63: #line 542 "awkgram.y" { want_assign = FALSE; ; break;} case 67: #line 553 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 68: #line 555 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_input, (NODE *) NULL); ; break;} case 69: #line 560 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 70: #line 562 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_output, (NODE *) NULL); ; break;} case 71: #line 564 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_append, (NODE *) NULL); ; break;} case 72: #line 566 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_pipe, (NODE *) NULL); ; break;} case 73: #line 568 "awkgram.y" { if (yyvsp[0].nodeval->type == Node_K_getline && yyvsp[0].nodeval->rnode->type == Node_redirect_twoway) yyerror(_("multistage two-way pipelines don't work")); yyval.nodeval = node(yyvsp[0].nodeval, Node_redirect_twoway, (NODE *) NULL); ; break;} case 74: #line 578 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 75: #line 580 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 76: #line 585 "awkgram.y" { yyval.nodeval = make_param(yyvsp[0].sval); ; break;} case 77: #line 587 "awkgram.y" { yyval.nodeval = append_right(yyvsp[-2].nodeval, make_param(yyvsp[0].sval)); yyerrok; ; break;} case 78: #line 589 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 79: #line 591 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 80: #line 593 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 81: #line 599 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 82: #line 601 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 83: #line 606 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 84: #line 608 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 85: #line 613 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL); ; break;} case 86: #line 615 "awkgram.y" { yyval.nodeval = append_right(yyvsp[-2].nodeval, node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL)); yyerrok; ; break;} case 87: #line 621 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 88: #line 623 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 89: #line 625 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 90: #line 627 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 91: #line 632 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 92: #line 634 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 93: #line 639 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL); ; break;} case 94: #line 641 "awkgram.y" { yyval.nodeval = append_right(yyvsp[-2].nodeval, node(yyvsp[0].nodeval, Node_expression_list, (NODE *) NULL)); yyerrok; ; break;} case 95: #line 647 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 96: #line 649 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 97: #line 651 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 98: #line 653 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 99: #line 658 "awkgram.y" { want_assign = FALSE; ; break;} case 100: #line 660 "awkgram.y" { if (do_lint && yyvsp[0].nodeval->type == Node_regex) lintwarn(_("regular expression on right of assignment")); yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-2].nodetypeval, yyvsp[0].nodeval); ; break;} case 101: #line 666 "awkgram.y" { yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-3].nodeval); ; break;} case 102: #line 668 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_K_getline, node(yyvsp[-3].nodeval, Node_redirect_pipein, (NODE *) NULL)); ; break;} case 103: #line 673 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_K_getline, node(yyvsp[-3].nodeval, Node_redirect_twoway, (NODE *) NULL)); ; break;} case 104: #line 678 "awkgram.y" { if (do_lint && ! io_allowed && parsing_end_rule && yyvsp[0].nodeval == NULL) lintwarn(_("non-redirected `getline' undefined inside END action")); yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_getline, yyvsp[0].nodeval); ; break;} case 105: #line 684 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_and, yyvsp[0].nodeval); ; break;} case 106: #line 686 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_or, yyvsp[0].nodeval); ; break;} case 107: #line 688 "awkgram.y" { if (yyvsp[-2].nodeval->type == Node_regex) warning(_("regular expression on left of `~' or `!~' operator")); yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, mk_rexp(yyvsp[0].nodeval)); ; break;} case 108: #line 694 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; if (do_lint && tokstart[0] == '*') { /* possible C comment */ int n = strlen(tokstart) - 1; if (tokstart[n] == '*') lintwarn(_("regexp constant `/%s/' looks like a C comment, but is not"), tokstart); } ; break;} case 109: #line 704 "awkgram.y" { yyval.nodeval = node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_nomatch, yyvsp[0].nodeval); ; break;} case 110: #line 712 "awkgram.y" { yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-2].nodeval); ; break;} case 111: #line 714 "awkgram.y" { if (do_lint && yyvsp[0].nodeval->type == Node_regex) lintwarn(_("regular expression on right of comparison")); yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, yyvsp[0].nodeval); ; break;} case 112: #line 720 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_less, yyvsp[0].nodeval); ; break;} case 113: #line 722 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_greater, yyvsp[0].nodeval); ; break;} case 114: #line 724 "awkgram.y" { yyval.nodeval = node(yyvsp[-4].nodeval, Node_cond_exp, node(yyvsp[-2].nodeval, Node_if_branches, yyvsp[0].nodeval));; break;} case 115: #line 726 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 116: #line 728 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_concat, yyvsp[0].nodeval); ; break;} case 117: #line 733 "awkgram.y" { want_assign = FALSE; ; break;} case 118: #line 735 "awkgram.y" { yyval.nodeval = node(yyvsp[-3].nodeval, yyvsp[-2].nodetypeval, yyvsp[0].nodeval); ; break;} case 119: #line 737 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_and, yyvsp[0].nodeval); ; break;} case 120: #line 739 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_or, yyvsp[0].nodeval); ; break;} case 121: #line 741 "awkgram.y" { if (do_lint && ! io_allowed && yyvsp[0].nodeval == NULL) lintwarn(_("non-redirected `getline' undefined inside BEGIN or END action")); yyval.nodeval = node(yyvsp[-1].nodeval, Node_K_getline, yyvsp[0].nodeval); ; break;} case 122: #line 747 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 123: #line 749 "awkgram.y" { yyval.nodeval = node((NODE *) NULL, Node_nomatch, yyvsp[0].nodeval); ; break;} case 124: #line 751 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, mk_rexp(yyvsp[0].nodeval)); ; break;} case 125: #line 753 "awkgram.y" { yyval.nodeval = node(variable(yyvsp[0].sval, CAN_FREE, Node_var_array), Node_in_array, yyvsp[-2].nodeval); ; break;} case 126: #line 755 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, yyvsp[-1].nodetypeval, yyvsp[0].nodeval); ; break;} case 127: #line 757 "awkgram.y" { yyval.nodeval = node(yyvsp[-4].nodeval, Node_cond_exp, node(yyvsp[-2].nodeval, Node_if_branches, yyvsp[0].nodeval));; break;} case 128: #line 759 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 129: #line 761 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_concat, yyvsp[0].nodeval); ; break;} case 131: #line 768 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_exp, yyvsp[0].nodeval); ; break;} case 132: #line 770 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_times, yyvsp[0].nodeval); ; break;} case 133: #line 772 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_quotient, yyvsp[0].nodeval); ; break;} case 134: #line 774 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_mod, yyvsp[0].nodeval); ; break;} case 135: #line 776 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_plus, yyvsp[0].nodeval); ; break;} case 136: #line 778 "awkgram.y" { yyval.nodeval = node(yyvsp[-2].nodeval, Node_minus, yyvsp[0].nodeval); ; break;} case 137: #line 780 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_postincrement, (NODE *) NULL); ; break;} case 138: #line 782 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_postdecrement, (NODE *) NULL); ; break;} case 139: #line 787 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_not, (NODE *) NULL); ; break;} case 140: #line 789 "awkgram.y" { yyval.nodeval = yyvsp[-1].nodeval; ; break;} case 141: #line 792 "awkgram.y" { yyval.nodeval = snode(yyvsp[-1].nodeval, Node_builtin, (int) yyvsp[-3].lval); ; break;} case 142: #line 794 "awkgram.y" { yyval.nodeval = snode(yyvsp[-1].nodeval, Node_builtin, (int) yyvsp[-3].lval); ; break;} case 143: #line 796 "awkgram.y" { if (do_lint) lintwarn(_("call of `length' without parentheses is not portable")); yyval.nodeval = snode((NODE *) NULL, Node_builtin, (int) yyvsp[0].lval); if (do_posix) warning(_("call of `length' without parentheses is deprecated by POSIX")); ; break;} case 144: #line 804 "awkgram.y" { yyval.nodeval = node(yyvsp[-1].nodeval, Node_func_call, make_string(yyvsp[-3].sval, strlen(yyvsp[-3].sval))); func_use(yyvsp[-3].sval, FUNC_USE); param_sanity(yyvsp[-1].nodeval); free(yyvsp[-3].sval); ; break;} case 146: #line 812 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_preincrement, (NODE *) NULL); ; break;} case 147: #line 814 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_predecrement, (NODE *) NULL); ; break;} case 148: #line 816 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 149: #line 818 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 150: #line 821 "awkgram.y" { if (yyvsp[0].nodeval->type == Node_val) { yyvsp[0].nodeval->numbr = -(force_number(yyvsp[0].nodeval)); yyval.nodeval = yyvsp[0].nodeval; } else yyval.nodeval = node(yyvsp[0].nodeval, Node_unary_minus, (NODE *) NULL); ; break;} case 151: #line 829 "awkgram.y" { /* * was: $$ = $2 * POSIX semantics: force a conversion to numeric type */ yyval.nodeval = node (make_number(0.0), Node_plus, yyvsp[0].nodeval); ; break;} case 152: #line 840 "awkgram.y" { yyval.nodeval = NULL; ; break;} case 153: #line 842 "awkgram.y" { yyval.nodeval = yyvsp[0].nodeval; ; break;} case 154: #line 847 "awkgram.y" { yyval.nodeval = variable(yyvsp[0].sval, CAN_FREE, Node_var); ; break;} case 155: #line 849 "awkgram.y" { if (yyvsp[-1].nodeval == NULL) { fatal(_("invalid subscript expression")); } else if (yyvsp[-1].nodeval->rnode == NULL) { yyval.nodeval = node(variable(yyvsp[-3].sval, CAN_FREE, Node_var_array), Node_subscript, yyvsp[-1].nodeval->lnode); freenode(yyvsp[-1].nodeval); } else yyval.nodeval = node(variable(yyvsp[-3].sval, CAN_FREE, Node_var_array), Node_subscript, yyvsp[-1].nodeval); ; break;} case 156: #line 859 "awkgram.y" { yyval.nodeval = node(yyvsp[0].nodeval, Node_field_spec, (NODE *) NULL); ; break;} case 158: #line 867 "awkgram.y" { yyerrok; ; break;} case 159: #line 871 "awkgram.y" { yyerrok; ; break;} case 162: #line 880 "awkgram.y" { yyerrok; want_assign = FALSE; ; break;} case 163: #line 883 "awkgram.y" { yyerrok; ; break;} } /* the action file gets copied in in place of this dollarsign */ #line 543 "/usr/lib/bison.simple" yyvsp -= yylen; yyssp -= yylen; #ifdef YYLSP_NEEDED yylsp -= yylen; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif *++yyvsp = yyval; #ifdef YYLSP_NEEDED yylsp++; if (yylen == 0) { yylsp->first_line = yylloc.first_line; yylsp->first_column = yylloc.first_column; yylsp->last_line = (yylsp-1)->last_line; yylsp->last_column = (yylsp-1)->last_column; yylsp->text = 0; } else { yylsp->last_line = (yylsp+yylen-1)->last_line; yylsp->last_column = (yylsp+yylen-1)->last_column; } #endif /* 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 - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; yyerrlab: /* here on detecting error */ if (! yyerrstatus) /* If not already recovering from an error, report this error. */ { ++yynerrs; #ifdef YYERROR_VERBOSE yyn = yypact[yystate]; if (yyn > YYFLAG && yyn < YYLAST) { int size = 0; char *msg; int x, count; count = 0; /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) size += strlen(yytname[x]) + 15, count++; msg = (char *) malloc(size + 15); if (msg != 0) { strcpy(msg, "parse error"); if (count < 5) { count = 0; for (x = (yyn < 0 ? -yyn : 0); x < (sizeof(yytname) / sizeof(char *)); x++) if (yycheck[x + yyn] == x) { strcat(msg, count == 0 ? ", expecting `" : " or `"); strcat(msg, yytname[x]); strcat(msg, "'"); count++; } } yyerror(msg); free(msg); } else yyerror ("parse error; also virtual memory exceeded"); } else #endif /* YYERROR_VERBOSE */ yyerror("parse error"); } goto yyerrlab1; yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { /* if just tried and failed to reuse lookahead token after an error, discard it. */ /* return failure if at end of input */ if (yychar == YYEOF) YYABORT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); #endif yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; yyerrdefault: /* current state does not do anything special for the error token. */ #if 0 /* This is wrong; only states that explicitly want error tokens should shift them. */ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ if (yyn) goto yydefault; #endif yyerrpop: /* pop the current state because it cannot handle the error token */ if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; #ifdef YYLSP_NEEDED yylsp--; #endif #if YYDEBUG != 0 if (yydebug) { short *ssp1 = yyss - 1; fprintf (stderr, "Error: state stack now"); while (ssp1 != yyssp) fprintf (stderr, " %d", *++ssp1); fprintf (stderr, "\n"); } #endif yyerrhandle: yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; yyn = -yyn; goto yyreduce; } else if (yyn == 0) goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; #if YYDEBUG != 0 if (yydebug) fprintf(stderr, "Shifting error token, "); #endif *++yyvsp = yylval; #ifdef YYLSP_NEEDED *++yylsp = yylloc; #endif yystate = yyn; goto yynewstate; yyacceptlab: /* YYACCEPT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 0; yyabortlab: /* YYABORT comes here. */ if (yyfree_stacks) { free (yyss); free (yyvs); #ifdef YYLSP_NEEDED free (yyls); #endif } return 1; } #line 886 "awkgram.y" struct token { const char *operator; /* text to match */ NODETYPE value; /* node type */ int class; /* lexical class */ unsigned flags; /* # of args. allowed and compatability */ # define ARGS 0xFF /* 0, 1, 2, 3 args allowed (any combination */ # define A(n) (1<<(n)) # define VERSION_MASK 0xFF00 /* old awk is zero */ # define NOT_OLD 0x0100 /* feature not in old awk */ # define NOT_POSIX 0x0200 /* feature not in POSIX */ # define GAWKX 0x0400 /* gawk extension */ # define RESX 0x0800 /* Bell Labs Research extension */ NODE *(*ptr)(); /* function that implements this keyword */ }; /* Tokentab is sorted ascii ascending order, so it can be binary searched. */ /* Function pointers come from declarations in awk.h. */ static struct token tokentab[] = { {"BEGIN", Node_illegal, LEX_BEGIN, 0, 0}, {"END", Node_illegal, LEX_END, 0, 0}, #ifdef ARRAYDEBUG {"adump", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_adump}, #endif {"and", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_and}, {"asort", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_asort}, {"atan2", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2), do_atan2}, {"bindtextdomain", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_bindtextdomain}, {"break", Node_K_break, LEX_BREAK, 0, 0}, {"close", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1)|A(2), do_close}, {"compl", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_compl}, {"continue", Node_K_continue, LEX_CONTINUE, 0, 0}, {"cos", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_cos}, {"dcgettext", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_dcgettext}, {"delete", Node_K_delete, LEX_DELETE, NOT_OLD, 0}, {"do", Node_K_do, LEX_DO, NOT_OLD, 0}, {"else", Node_illegal, LEX_ELSE, 0, 0}, {"exit", Node_K_exit, LEX_EXIT, 0, 0}, {"exp", Node_builtin, LEX_BUILTIN, A(1), do_exp}, {"extension", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_ext}, {"fflush", Node_builtin, LEX_BUILTIN, RESX|A(0)|A(1), do_fflush}, {"for", Node_K_for, LEX_FOR, 0, 0}, {"func", Node_K_function, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0}, {"function", Node_K_function, LEX_FUNCTION, NOT_OLD, 0}, {"gensub", Node_builtin, LEX_BUILTIN, GAWKX|A(3)|A(4), do_gensub}, {"getline", Node_K_getline, LEX_GETLINE, NOT_OLD, 0}, {"gsub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_gsub}, {"if", Node_K_if, LEX_IF, 0, 0}, {"in", Node_illegal, LEX_IN, 0, 0}, {"index", Node_builtin, LEX_BUILTIN, A(2), do_index}, {"int", Node_builtin, LEX_BUILTIN, A(1), do_int}, {"length", Node_builtin, LEX_LENGTH, A(0)|A(1), do_length}, {"log", Node_builtin, LEX_BUILTIN, A(1), do_log}, {"lshift", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_lshift}, {"match", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_match}, {"mktime", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_mktime}, {"next", Node_K_next, LEX_NEXT, 0, 0}, {"nextfile", Node_K_nextfile, LEX_NEXTFILE, GAWKX, 0}, {"or", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_or}, {"print", Node_K_print, LEX_PRINT, 0, 0}, {"printf", Node_K_printf, LEX_PRINTF, 0, 0}, {"rand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0), do_rand}, {"return", Node_K_return, LEX_RETURN, NOT_OLD, 0}, {"rshift", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_rshift}, {"sin", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_sin}, {"split", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_split}, {"sprintf", Node_builtin, LEX_BUILTIN, 0, do_sprintf}, {"sqrt", Node_builtin, LEX_BUILTIN, A(1), do_sqrt}, {"srand", Node_builtin, LEX_BUILTIN, NOT_OLD|A(0)|A(1), do_srand}, #if defined(GAWKDEBUG) || defined(ARRAYDEBUG) /* || ... */ {"stopme", Node_builtin, LEX_BUILTIN, GAWKX|A(0), stopme}, #endif {"strftime", Node_builtin, LEX_BUILTIN, GAWKX|A(0)|A(1)|A(2), do_strftime}, {"strtonum", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_strtonum}, {"sub", Node_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_sub}, {"substr", Node_builtin, LEX_BUILTIN, A(2)|A(3), do_substr}, {"system", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_system}, {"systime", Node_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime}, {"tolower", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower}, {"toupper", Node_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper}, {"while", Node_K_while, LEX_WHILE, 0, 0}, {"xor", Node_builtin, LEX_BUILTIN, GAWKX|A(2), do_xor}, }; /* getfname --- return name of a builtin function (for pretty printing) */ const char * getfname(register NODE *(*fptr)()) { register int i, j; j = sizeof(tokentab) / sizeof(tokentab[0]); /* linear search, no other way to do it */ for (i = 0; i < j; i++) if (tokentab[i].ptr == fptr) return tokentab[i].operator; fatal(_("fptr %x not in tokentab\n"), fptr); return NULL; /* to stop warnings */ } /* yyerror --- print a syntax error message, show where */ /* * Function identifier purposely indented to avoid mangling * by ansi2knr. Sigh. */ static void #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ yyerror(const char *m, ...) #else /* VARARGS0 */ yyerror(va_alist) va_dcl #endif { va_list args; const char *mesg = NULL; register char *bp, *cp; char *scan; char buf[120]; static char end_of_file_line[] = "(END OF FILE)"; errcount++; /* Find the current line in the input file */ if (lexptr && lexeme) { if (thisline == NULL) { cp = lexeme; if (*cp == '\n') { cp--; mesg = _("unexpected newline"); } for (; cp != lexptr_begin && *cp != '\n'; --cp) continue; if (*cp == '\n') cp++; thisline = cp; } /* NL isn't guaranteed */ bp = lexeme; while (bp < lexend && *bp && *bp != '\n') bp++; } else { thisline = end_of_file_line; bp = thisline + strlen(thisline); } msg("%.*s", (int) (bp - thisline), thisline); bp = buf; cp = buf + sizeof(buf) - 24; /* 24 more than longest msg. input */ if (lexptr != NULL) { scan = thisline; while (bp < cp && scan < lexeme) if (*scan++ == '\t') *bp++ = '\t'; else *bp++ = ' '; *bp++ = '^'; *bp++ = ' '; } #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ va_start(args, m); if (mesg == NULL) mesg = m; #else va_start(args); if (mesg == NULL) mesg = va_arg(args, char *); #endif strcpy(bp, mesg); err("", buf, args); va_end(args); } /* get_src_buf --- read the next buffer of source program */ static char * get_src_buf() { static int samefile = FALSE; static int nextfile = 0; static char *buf = NULL; static int fd; int n; register char *scan; static int len = 0; static int did_newline = FALSE; int newfile; struct stat sbuf; # define SLOP 128 /* enough space to hold most source lines */ again: newfile = FALSE; if (nextfile > numfiles) return NULL; if (srcfiles[nextfile].stype == CMDLINE) { if (len == 0) { len = strlen(srcfiles[nextfile].val); if (len == 0) { /* * Yet Another Special case: * gawk '' /path/name * Sigh. */ static int warned = FALSE; if (do_lint && ! warned) { warned = TRUE; lintwarn(_("empty program text on command line")); } ++nextfile; goto again; } sourceline = 1; lexptr = lexptr_begin = srcfiles[nextfile].val; lexend = lexptr + len; } else if (! did_newline && *(lexptr-1) != '\n') { /* * The following goop is to ensure that the source * ends with a newline and that the entire current * line is available for error messages. */ int offset; did_newline = TRUE; offset = lexptr - lexeme; for (scan = lexeme; scan > lexptr_begin; scan--) if (*scan == '\n') { scan++; break; } len = lexptr - scan; emalloc(buf, char *, len+1, "get_src_buf"); memcpy(buf, scan, len); thisline = buf; lexptr = buf + len; *lexptr = '\n'; lexeme = lexptr - offset; lexptr_begin = buf; lexend = lexptr + 1; } else { len = 0; lexeme = lexptr = lexptr_begin = NULL; } if (lexptr == NULL && ++nextfile <= numfiles) goto again; return lexptr; } if (! samefile) { source = srcfiles[nextfile].val; if (source == NULL) { if (buf != NULL) { free(buf); buf = NULL; } len = 0; return lexeme = lexptr = lexptr_begin = NULL; } fd = pathopen(source); if (fd <= INVALID_HANDLE) { char *in; /* suppress file name and line no. in error mesg */ in = source; source = NULL; fatal(_("can't open source file `%s' for reading (%s)"), in, strerror(errno)); } len = optimal_bufsize(fd, & sbuf); newfile = TRUE; if (buf != NULL) free(buf); emalloc(buf, char *, len + SLOP, "get_src_buf"); lexptr_begin = buf + SLOP; samefile = TRUE; sourceline = 1; } else { /* * Here, we retain the current source line (up to length SLOP) * in the beginning of the buffer that was overallocated above */ int offset; int linelen; offset = lexptr - lexeme; for (scan = lexeme; scan > lexptr_begin; scan--) if (*scan == '\n') { scan++; break; } linelen = lexptr - scan; if (linelen > SLOP) linelen = SLOP; thisline = buf + SLOP - linelen; memcpy(thisline, scan, linelen); lexeme = buf + SLOP - offset; lexptr_begin = thisline; } n = read(fd, buf + SLOP, len); if (n == -1) fatal(_("can't read sourcefile `%s' (%s)"), source, strerror(errno)); if (n == 0) { if (newfile) { static int warned = FALSE; if (do_lint && ! warned) { warned = TRUE; lintwarn(_("source file `%s' is empty"), source); } } if (fd != fileno(stdin)) /* safety */ close(fd); samefile = FALSE; nextfile++; if (lexeme) *lexeme = '\0'; len = 0; goto again; } lexptr = buf + SLOP; lexend = lexptr + n; return buf; } /* tokadd --- add a character to the token buffer */ #define tokadd(x) (*tok++ = (x), tok == tokend ? tokexpand() : tok) /* tokexpand --- grow the token buffer */ char * tokexpand() { static int toksize = 60; int tokoffset; tokoffset = tok - tokstart; toksize *= 2; if (tokstart != NULL) erealloc(tokstart, char *, toksize, "tokexpand"); else emalloc(tokstart, char *, toksize, "tokexpand"); tokend = tokstart + toksize; tok = tokstart + tokoffset; return tok; } /* nextc --- get the next input character */ #if GAWKDEBUG int nextc() { int c; if (lexptr && lexptr < lexend) c = (int) (unsigned char) *lexptr++; else if (get_src_buf()) c = (int) (unsigned char) *lexptr++; else c = EOF; return c; } #else #define nextc() ((lexptr && lexptr < lexend) ? \ ((int) (unsigned char) *lexptr++) : \ (get_src_buf() ? ((int) (unsigned char) *lexptr++) : EOF) \ ) #endif /* pushback --- push a character back on the input */ #define pushback() (lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr) /* allow_newline --- allow newline after &&, ||, ? and : */ static void allow_newline() { int c; for (;;) { c = nextc(); if (c == EOF) break; if (c == '#') { while ((c = nextc()) != '\n' && c != EOF) continue; if (c == EOF) break; } if (c == '\n') sourceline++; if (! ISSPACE(c)) { pushback(); break; } } } /* yylex --- Read the input and turn it into tokens. */ static int yylex() { register int c; int seen_e = FALSE; /* These are for numbers */ int seen_point = FALSE; int esc_seen; /* for literal strings */ int low, mid, high; static int did_newline = FALSE; char *tokkey; static int lasttok = 0, eof_warned = FALSE; int inhex = FALSE; int intlstr = FALSE; if (nextc() == EOF) { if (lasttok != NEWLINE) { lasttok = NEWLINE; if (do_lint && ! eof_warned) { lintwarn(_("source file does not end in newline")); eof_warned = TRUE; } return NEWLINE; /* fake it */ } return 0; } pushback(); #ifdef OS2 /* * added for OS/2's extproc feature of cmd.exe * (like #! in BSD sh) */ if (strncasecmp(lexptr, "extproc ", 8) == 0) { while (*lexptr && *lexptr != '\n') lexptr++; } #endif lexeme = lexptr; thisline = NULL; if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ /* * Counting brackets is non-trivial. [[] is ok, * and so is [\]], with a point being that /[/]/ as a regexp * constant has to work. * * Do not count [ or ] if either one is preceded by a \. * A `[' should be counted if * a) it is the first one so far (in_brack == 0) * b) it is the `[' in `[:' * A ']' should be counted if not preceded by a \, since * it is either closing `:]' or just a plain list. * According to POSIX, []] is how you put a ] into a set. * Try to handle that too. * * The code for \ handles \[ and \]. */ want_regexp = FALSE; tok = tokstart; for (;;) { c = nextc(); switch (c) { case '[': /* one day check for `.' and `=' too */ if (nextc() == ':' || in_brack == 0) in_brack++; pushback(); break; case ']': if (tokstart[0] == '[' && (tok == tokstart + 1 || (tok == tokstart + 2 && tokstart[1] == '^'))) /* do nothing */; else in_brack--; break; case '\\': if ((c = nextc()) == EOF) { yyerror(_("unterminated regexp ends with `\\' at end of file")); return lasttok = REGEXP; /* kludge */ } else if (c == '\n') { sourceline++; continue; } else { tokadd('\\'); tokadd(c); continue; } break; case '/': /* end of the regexp */ if (in_brack > 0) break; pushback(); tokadd('\0'); yylval.sval = tokstart; return lasttok = REGEXP; case '\n': pushback(); yyerror(_("unterminated regexp")); return lasttok = REGEXP; /* kludge */ case EOF: yyerror(_("unterminated regexp at end of file")); return lasttok = REGEXP; /* kludge */ } tokadd(c); } } retry: while ((c = nextc()) == ' ' || c == '\t') continue; lexeme = lexptr ? lexptr - 1 : lexptr; thisline = NULL; tok = tokstart; yylval.nodetypeval = Node_illegal; switch (c) { case EOF: if (lasttok != NEWLINE) { lasttok = NEWLINE; if (do_lint && ! eof_warned) { lintwarn(_("source file does not end in newline")); eof_warned = TRUE; } return NEWLINE; /* fake it */ } return 0; case '\n': sourceline++; return lasttok = NEWLINE; case '#': /* it's a comment */ while ((c = nextc()) != '\n') { if (c == EOF) { if (lasttok != NEWLINE) { lasttok = NEWLINE; if (do_lint && ! eof_warned) { lintwarn( _("source file does not end in newline")); eof_warned = TRUE; } return NEWLINE; /* fake it */ } return 0; } } sourceline++; return lasttok = NEWLINE; case '\\': #ifdef RELAXED_CONTINUATION /* * This code puports to allow comments and/or whitespace * after the `\' at the end of a line used for continuation. * Use it at your own risk. We think it's a bad idea, which * is why it's not on by default. */ if (! do_traditional) { /* strip trailing white-space and/or comment */ while ((c = nextc()) == ' ' || c == '\t') continue; if (c == '#') { if (do_lint) lintwarn( _("use of `\\ #...' line continuation is not portable")); while ((c = nextc()) != '\n') if (c == EOF) break; } pushback(); } #endif /* RELAXED_CONTINUATION */ if (nextc() == '\n') { sourceline++; goto retry; } else { yyerror(_("backslash not last character on line")); exit(1); } break; case '$': want_assign = TRUE; return lasttok = '$'; case ':': case '?': if (! do_posix) allow_newline(); return lasttok = c; case ')': case '(': case ';': case '{': case ',': want_assign = FALSE; /* fall through */ case '[': case ']': return lasttok = c; case '*': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_assign_times; return lasttok = ASSIGNOP; } else if (do_posix) { pushback(); return lasttok = '*'; } else if (c == '*') { /* make ** and **= aliases for ^ and ^= */ static int did_warn_op = FALSE, did_warn_assgn = FALSE; if (nextc() == '=') { if (! did_warn_assgn) { did_warn_assgn = TRUE; if (do_lint) lintwarn(_("POSIX does not allow operator `**='")); if (do_lint_old) warning(_("old awk does not support operator `**='")); } yylval.nodetypeval = Node_assign_exp; return ASSIGNOP; } else { pushback(); if (! did_warn_op) { did_warn_op = TRUE; if (do_lint) lintwarn(_("POSIX does not allow operator `**'")); if (do_lint_old) warning(_("old awk does not support operator `**'")); } return lasttok = '^'; } } pushback(); return lasttok = '*'; case '/': if (want_assign) { if (nextc() == '=') { yylval.nodetypeval = Node_assign_quotient; return lasttok = ASSIGNOP; } pushback(); } return lasttok = '/'; case '%': if (nextc() == '=') { yylval.nodetypeval = Node_assign_mod; return lasttok = ASSIGNOP; } pushback(); return lasttok = '%'; case '^': { static int did_warn_op = FALSE, did_warn_assgn = FALSE; if (nextc() == '=') { if (do_lint_old && ! did_warn_assgn) { did_warn_assgn = TRUE; warning(_("operator `^=' is not supported in old awk")); } yylval.nodetypeval = Node_assign_exp; return lasttok = ASSIGNOP; } pushback(); if (do_lint_old && ! did_warn_op) { did_warn_op = TRUE; warning(_("operator `^' is not supported in old awk")); } return lasttok = '^'; } case '+': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_assign_plus; return lasttok = ASSIGNOP; } if (c == '+') return lasttok = INCREMENT; pushback(); return lasttok = '+'; case '!': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_notequal; return lasttok = RELOP; } if (c == '~') { yylval.nodetypeval = Node_nomatch; want_assign = FALSE; return lasttok = MATCHOP; } pushback(); return lasttok = '!'; case '<': if (nextc() == '=') { yylval.nodetypeval = Node_leq; return lasttok = RELOP; } yylval.nodetypeval = Node_less; pushback(); return lasttok = '<'; case '=': if (nextc() == '=') { yylval.nodetypeval = Node_equal; return lasttok = RELOP; } yylval.nodetypeval = Node_assign; pushback(); return lasttok = ASSIGNOP; case '>': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_geq; return lasttok = RELOP; } else if (c == '>') { yylval.nodetypeval = Node_redirect_append; return lasttok = APPEND_OP; } yylval.nodetypeval = Node_greater; pushback(); return lasttok = '>'; case '~': yylval.nodetypeval = Node_match; want_assign = FALSE; return lasttok = MATCHOP; case '}': /* * Added did newline stuff. Easier than * hacking the grammar. */ if (did_newline) { did_newline = FALSE; return lasttok = c; } did_newline++; --lexptr; /* pick up } next time */ return lasttok = NEWLINE; case '"': string: esc_seen = FALSE; while ((c = nextc()) != '"') { if (c == '\n') { pushback(); yyerror(_("unterminated string")); exit(1); } if (c == '\\') { c = nextc(); if (c == '\n') { sourceline++; continue; } esc_seen = TRUE; tokadd('\\'); } if (c == EOF) { pushback(); yyerror(_("unterminated string")); exit(1); } tokadd(c); } yylval.nodeval = make_str_node(tokstart, tok - tokstart, esc_seen ? SCAN : 0); yylval.nodeval->flags |= PERM; if (intlstr) { yylval.nodeval->flags |= INTLSTR; intlstr = FALSE; if (do_intl) dumpintlstr(yylval.nodeval->stptr, yylval.nodeval->stlen); } return lasttok = YSTRING; case '-': if ((c = nextc()) == '=') { yylval.nodetypeval = Node_assign_minus; return lasttok = ASSIGNOP; } if (c == '-') return lasttok = DECREMENT; pushback(); return lasttok = '-'; case '.': c = nextc(); pushback(); if (! ISDIGIT(c)) return lasttok = '.'; else c = '.'; /* FALL THROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* It's a number */ for (;;) { int gotnumber = FALSE; tokadd(c); switch (c) { case 'x': case 'X': if (do_traditional) goto done; if (tok == tokstart + 2) inhex = TRUE; break; case '.': if (seen_point) { gotnumber = TRUE; break; } seen_point = TRUE; break; case 'e': case 'E': if (inhex) break; if (seen_e) { gotnumber = TRUE; break; } seen_e = TRUE; if ((c = nextc()) == '-' || c == '+') tokadd(c); else pushback(); break; case 'a': case 'A': case 'b': case 'B': case 'c': case 'C': case 'D': case 'd': case 'f': case 'F': if (do_traditional || ! inhex) goto done; /* fall through */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: done: gotnumber = TRUE; } if (gotnumber) break; c = nextc(); } if (c != EOF) pushback(); else if (do_lint && ! eof_warned) { lintwarn(_("source file does not end in newline")); eof_warned = TRUE; } tokadd('\0'); if (! do_traditional && isnondecimal(tokstart)) yylval.nodeval = make_number(nondec2awknum(tokstart, strlen(tokstart))); else yylval.nodeval = make_number(atof(tokstart)); yylval.nodeval->flags |= PERM; return lasttok = YNUMBER; case '&': if ((c = nextc()) == '&') { yylval.nodetypeval = Node_and; allow_newline(); want_assign = FALSE; return lasttok = LEX_AND; } pushback(); return lasttok = '&'; case '|': if ((c = nextc()) == '|') { yylval.nodetypeval = Node_or; allow_newline(); want_assign = FALSE; return lasttok = LEX_OR; } else if (! do_traditional && c == '&') { yylval.nodetypeval = Node_redirect_twoway; want_assign = FALSE; return lasttok = TWOWAYIO; } pushback(); return lasttok = '|'; } if (c != '_' && ! ISALPHA(c)) { yyerror(_("invalid char '%c' in expression"), c); exit(1); } if (! do_traditional && c == '_') { if ((c = nextc()) == '"') { intlstr = TRUE; goto string; } pushback(); c = '_'; } /* it's some type of name-type-thing. Find its length. */ tok = tokstart; while (is_identchar(c)) { tokadd(c); c = nextc(); } tokadd('\0'); emalloc(tokkey, char *, tok - tokstart, "yylex"); memcpy(tokkey, tokstart, tok - tokstart); if (c != EOF) pushback(); else if (do_lint && ! eof_warned) { lintwarn(_("source file does not end in newline")); eof_warned = TRUE; } /* See if it is a special token. */ low = 0; high = (sizeof(tokentab) / sizeof(tokentab[0])) - 1; while (low <= high) { int i; mid = (low + high) / 2; c = *tokstart - tokentab[mid].operator[0]; i = c ? c : strcmp(tokstart, tokentab[mid].operator); if (i < 0) /* token < mid */ high = mid - 1; else if (i > 0) /* token > mid */ low = mid + 1; else { if (do_lint) { if (tokentab[mid].flags & GAWKX) lintwarn(_("`%s' is a gawk extension"), tokentab[mid].operator); if (tokentab[mid].flags & RESX) lintwarn(_("`%s' is a Bell Labs extension"), tokentab[mid].operator); if (tokentab[mid].flags & NOT_POSIX) lintwarn(_("POSIX does not allow `%s'"), tokentab[mid].operator); } if (do_lint_old && (tokentab[mid].flags & NOT_OLD)) warning(_("`%s' is not supported in old awk"), tokentab[mid].operator); if ((do_traditional && (tokentab[mid].flags & GAWKX)) || (do_posix && (tokentab[mid].flags & NOT_POSIX))) break; if (tokentab[mid].class == LEX_BUILTIN || tokentab[mid].class == LEX_LENGTH ) yylval.lval = mid; else yylval.nodetypeval = tokentab[mid].value; free(tokkey); return lasttok = tokentab[mid].class; } } yylval.sval = tokkey; if (*lexptr == '(') return lasttok = FUNC_CALL; else { static short goto_warned = FALSE; want_assign = TRUE; #define SMART_ALECK 1 if (SMART_ALECK && do_lint && ! goto_warned && strcasecmp(tokkey, "goto") == 0) { goto_warned = TRUE; lintwarn(_("`goto' considered harmful!\n")); } return lasttok = NAME; } } /* node_common --- common code for allocating a new node */ static NODE * node_common(NODETYPE op) { register NODE *r; getnode(r); r->type = op; r->flags = MALLOC; if (r->type == Node_var) r->flags |= UNINITIALIZED; /* if lookahead is NL, lineno is 1 too high */ if (lexeme && *lexeme == '\n') r->source_line = sourceline - 1; else r->source_line = sourceline; r->source_file = source; return r; } /* node --- allocates a node with defined lnode and rnode. */ NODE * node(NODE *left, NODETYPE op, NODE *right) { register NODE *r; r = node_common(op); r->lnode = left; r->rnode = right; return r; } /* snode --- allocate a node with defined subnode and proc for builtin functions. Checks for arg. count and supplies defaults where possible. */ static NODE * snode(NODE *subn, NODETYPE op, int idx) { register NODE *r; register NODE *n; int nexp = 0; int args_allowed; r = node_common(op); /* traverse expression list to see how many args. given */ for (n = subn; n != NULL; n = n->rnode) { nexp++; if (nexp > 3) break; } /* check against how many args. are allowed for this builtin */ args_allowed = tokentab[idx].flags & ARGS; if (args_allowed && (args_allowed & A(nexp)) == 0) fatal(_("%d is invalid as number of arguments for %s"), nexp, tokentab[idx].operator); r->proc = tokentab[idx].ptr; /* special case processing for a few builtins */ if (nexp == 0 && r->proc == do_length) { subn = node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL); } else if (r->proc == do_match) { static short warned = FALSE; if (subn->rnode->lnode->type != Node_regex) subn->rnode->lnode = mk_rexp(subn->rnode->lnode); if (subn->rnode->rnode != NULL) { /* 3rd argument there */ if (do_lint && ! warned) { warned = TRUE; lintwarn(_("match: third argument is a gawk extension")); } if (do_traditional) fatal(_("match: third argument is a gawk extension")); } } else if (r->proc == do_sub || r->proc == do_gsub) { if (subn->lnode->type != Node_regex) subn->lnode = mk_rexp(subn->lnode); if (nexp == 2) append_right(subn, node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL)); else if (subn->rnode->rnode->lnode->type == Node_val) { if (do_lint) { char *f; f = (r->proc == do_sub) ? "sub" : "gsub"; lintwarn(_("%s: string literal as last arg of substitute has no effect"), f); } } else if (! isassignable(subn->rnode->rnode->lnode)) { if (r->proc == do_sub) yyerror(_("sub third parameter is not a changeable object")); else yyerror(_("gsub third parameter is not a changeable object")); } } else if (r->proc == do_gensub) { if (subn->lnode->type != Node_regex) subn->lnode = mk_rexp(subn->lnode); if (nexp == 3) append_right(subn, node(node(make_number(0.0), Node_field_spec, (NODE *) NULL), Node_expression_list, (NODE *) NULL)); } else if (r->proc == do_split) { if (nexp == 2) append_right(subn, node(FS_node, Node_expression_list, (NODE *) NULL)); n = subn->rnode->rnode->lnode; if (n->type != Node_regex) subn->rnode->rnode->lnode = mk_rexp(n); if (nexp == 2) subn->rnode->rnode->lnode->re_flags |= FS_DFLT; } else if (r->proc == do_close) { static short warned = FALSE; if ( nexp == 2) { if (do_lint && nexp == 2 && ! warned) { warned = TRUE; lintwarn(_("close: second argument is a gawk extension")); } if (do_traditional) fatal(_("close: second argument is a gawk extension")); } } else if (do_intl /* --gen-po */ && r->proc == do_dcgettext /* dcgettext(...) */ && subn->lnode->type == Node_val /* 1st arg is constant */ && (subn->lnode->flags & STR) != 0) { /* it's a string constant */ /* ala xgettext, dcgettext("some string" ...) dumps the string */ NODE *str = subn->lnode; if ((str->flags & INTLSTR) != 0) warning(_("use of dcgettext(_\"...\") is incorrect: remove leading underscore")); /* don't dump it, the lexer already did */ else dumpintlstr(str->stptr, str->stlen); } r->subnode = subn; if (r->proc == do_sprintf) { count_args(r); r->lnode->printf_count = r->printf_count; /* hack */ } return r; } /* * mkrangenode: * This allocates a Node_line_range node with defined condpair and * zeroes the trigger word to avoid the temptation of assuming that calling * 'node( foo, Node_line_range, 0)' will properly initialize 'triggered'. * Otherwise like node(). */ static NODE * mkrangenode(NODE *cpair) { register NODE *r; getnode(r); r->type = Node_line_range; r->condpair = cpair; r->triggered = FALSE; return r; } /* make_for_loop --- build a for loop */ static NODE * make_for_loop(NODE *init, NODE *cond, NODE *incr) { register FOR_LOOP_HEADER *r; NODE *n; emalloc(r, FOR_LOOP_HEADER *, sizeof(FOR_LOOP_HEADER), "make_for_loop"); getnode(n); n->type = Node_illegal; r->init = init; r->cond = cond; r->incr = incr; n->sub.nodep.r.hd = r; return n; } /* dup_parms --- return TRUE if there are duplicate parameters */ static int dup_parms(NODE *func) { register NODE *np; char *fname, **names; int count, i, j, dups; NODE *params; if (func == NULL) /* error earlier */ return TRUE; fname = func->param; count = func->param_cnt; params = func->rnode; if (count == 0) /* no args, no problem */ return FALSE; if (params == NULL) /* error earlier */ return TRUE; emalloc(names, char **, count * sizeof(char *), "dup_parms"); i = 0; for (np = params; np != NULL; np = np->rnode) { if (np->param == NULL) { /* error earlier, give up, go home */ free(names); return TRUE; } names[i++] = np->param; } dups = 0; for (i = 1; i < count; i++) { for (j = 0; j < i; j++) { if (strcmp(names[i], names[j]) == 0) { dups++; error( _("function `%s': parameter #%d, `%s', duplicates parameter #%d"), fname, i+1, names[j], j+1); } } } free(names); return (dups > 0 ? TRUE : FALSE); } /* parms_shadow --- check if parameters shadow globals */ static void parms_shadow(const char *fname, NODE *func) { int count, i; if (fname == NULL || func == NULL) /* error earlier */ return; count = func->lnode->param_cnt; if (count == 0) /* no args, no problem */ return; /* * Use warning() and not lintwarn() so that can warn * about all shadowed parameters. */ for (i = 0; i < count; i++) { if (lookup(func->parmlist[i]) != NULL) { warning( _("function `%s': parameter `%s' shadows global variable"), fname, func->parmlist[i]); } } } /* * install: * Install a name in the symbol table, even if it is already there. * Caller must check against redefinition if that is desired. */ NODE * install(char *name, NODE *value) { register NODE *hp; register size_t len; register int bucket; var_count++; len = strlen(name); bucket = hash(name, len, (unsigned long) HASHSIZE); getnode(hp); hp->type = Node_hashnode; hp->hnext = variables[bucket]; variables[bucket] = hp; hp->hlength = len; hp->hvalue = value; hp->hname = name; hp->hvalue->vname = name; return hp->hvalue; } /* lookup --- find the most recent hash node for name installed by install */ NODE * lookup(const char *name) { register NODE *bucket; register size_t len; len = strlen(name); for (bucket = variables[hash(name, len, (unsigned long) HASHSIZE)]; bucket != NULL; bucket = bucket->hnext) if (bucket->hlength == len && STREQN(bucket->hname, name, len)) return bucket->hvalue; return NULL; } /* var_comp --- compare two variable names */ static int var_comp(const void *v1, const void *v2) { NODE **npp1, **npp2; NODE *n1, *n2; int minlen; npp1 = (NODE **) v1; npp2 = (NODE **) v2; n1 = *npp1; n2 = *npp2; if (n1->hlength > n2->hlength) minlen = n1->hlength; else minlen = n2->hlength; return strncmp(n1->hname, n2->hname, minlen); } /* valinfo --- dump var info */ static void valinfo(NODE *n, FILE *fp) { if (n->flags & STRING) { fprintf(fp, "string ("); pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE); fprintf(fp, ")\n"); } else if (n->flags & NUMBER) fprintf(fp, "number (%.17g)\n", n->numbr); else if (n->flags & STR) { fprintf(fp, "string value ("); pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE); fprintf(fp, ")\n"); } else if (n->flags & NUM) fprintf(fp, "number value (%.17g)\n", n->numbr); else fprintf(fp, "?? flags %s\n", flags2str(n->flags)); } /* dump_vars --- dump the symbol table */ void dump_vars(const char *fname) { int i, j; NODE **table; NODE *p; FILE *fp; emalloc(table, NODE **, var_count * sizeof(NODE *), "dump_vars"); if (fname == NULL) fp = stderr; else if ((fp = fopen(fname, "w")) == NULL) { warning(_("could not open `%s' for writing (%s)"), fname, strerror(errno)); warning(_("sending profile to standard error")); fp = stderr; } for (i = j = 0; i < HASHSIZE; i++) for (p = variables[i]; p != NULL; p = p->hnext) table[j++] = p; assert(j == var_count); /* Shazzam! */ qsort(table, j, sizeof(NODE *), var_comp); for (i = 0; i < j; i++) { p = table[i]; if (p->hvalue->type == Node_func) continue; fprintf(fp, "%.*s: ", (int) p->hlength, p->hname); if (p->hvalue->type == Node_var_array) fprintf(fp, "array, %ld elements\n", p->hvalue->table_size); else if (p->hvalue->type == Node_var) valinfo(p->hvalue->var_value, fp); else { NODE **lhs = get_lhs(p->hvalue, NULL, FALSE); valinfo(*lhs, fp); } } if (fp != stderr && fclose(fp) != 0) warning(_("%s: close failed (%s)"), fname, strerror(errno)); free(table); } /* release_all_vars --- free all variable memory */ void release_all_vars() { int i; NODE *p, *next; for (i = 0; i < HASHSIZE; i++) for (p = variables[i]; p != NULL; p = next) { next = p->hnext; if (p->hvalue->type == Node_func) continue; else if (p->hvalue->type == Node_var_array) assoc_clear(p->hvalue); else if (p->hvalue->type == Node_var) unref(p->hvalue->var_value); else { NODE **lhs = get_lhs(p->hvalue, NULL, FALSE); unref((*lhs)->var_value); } unref(p); } } /* finfo --- for use in comparison and sorting of function names */ struct finfo { char *name; size_t nlen; NODE *func; }; /* fcompare --- comparison function for qsort */ static int fcompare(const void *p1, const void *p2) { struct finfo *f1, *f2; int minlen; f1 = (struct finfo *) p1; f2 = (struct finfo *) p2; if (f1->nlen > f2->nlen) minlen = f2->nlen; else minlen = f1->nlen; return strncmp(f1->name, f2->name, minlen); } /* dump_funcs --- print all functions */ void dump_funcs() { int i, j; NODE *p; static struct finfo *tab = NULL; if (func_count == 0) return; if (tab == NULL) emalloc(tab, struct finfo *, func_count * sizeof(struct finfo), "dump_funcs"); for (i = j = 0; i < HASHSIZE; i++) { for (p = variables[i]; p != NULL; p = p->hnext) { if (p->hvalue->type == Node_func) { tab[j].name = p->hname; tab[j].nlen = p->hlength; tab[j].func = p->hvalue; j++; } } } assert(j == func_count); /* Shazzam! */ qsort(tab, func_count, sizeof(struct finfo), fcompare); for (i = 0; i < j; i++) pp_func(tab[i].name, tab[i].nlen, tab[i].func); free(tab); } /* shadow_funcs --- check all functions for parameters that shadow globals */ void shadow_funcs() { int i, j; NODE *p; struct finfo *tab; static int calls = 0; if (func_count == 0) return; if (calls++ != 0) fatal(_("shadow_funcs() called twice!")); emalloc(tab, struct finfo *, func_count * sizeof(struct finfo), "shadow_funcs"); for (i = j = 0; i < HASHSIZE; i++) { for (p = variables[i]; p != NULL; p = p->hnext) { if (p->hvalue->type == Node_func) { tab[j].name = p->hname; tab[j].nlen = p->hlength; tab[j].func = p->hvalue; j++; } } } assert(j == func_count); /* Shazzam! */ qsort(tab, func_count, sizeof(struct finfo), fcompare); for (i = 0; i < j; i++) parms_shadow(tab[i].name, tab[i].func); free(tab); } /* * append_right: * Add new to the rightmost branch of LIST. This uses n^2 time, so we make * a simple attempt at optimizing it. */ static NODE * append_right(NODE *list, NODE *new) { register NODE *oldlist; static NODE *savefront = NULL, *savetail = NULL; if (list == NULL || new == NULL) return list; oldlist = list; if (savefront == oldlist) { savetail = savetail->rnode = new; return oldlist; } else savefront = oldlist; while (list->rnode != NULL) list = list->rnode; savetail = list->rnode = new; return oldlist; } /* * func_install: * check if name is already installed; if so, it had better have Null value, * in which case def is added as the value. Otherwise, install name with def * as value. * * Extra work, build up and save a list of the parameter names in a table * and hang it off params->parmlist. This is used to set the `vname' field * of each function parameter during a function call. See eval.c. */ static void func_install(NODE *params, NODE *def) { NODE *r, *n, *thisfunc; char **pnames, *names, *sp; size_t pcount = 0, space = 0; int i; /* check for function foo(foo) { ... }. bleah. */ for (n = params->rnode; n != NULL; n = n->rnode) { if (strcmp(n->param, params->param) == 0) fatal(_("function `%s': can't use function name as parameter name"), params->param); } thisfunc = NULL; /* turn off warnings */ /* symbol table managment */ pop_var(params, FALSE); r = lookup(params->param); if (r != NULL) { fatal(_("function name `%s' previously defined"), params->param); } else { thisfunc = node(params, Node_func, def); (void) install(params->param, thisfunc); } /* figure out amount of space to allocate */ for (n = params->rnode; n != NULL; n = n->rnode) { pcount++; space += strlen(n->param) + 1; } /* allocate it and fill it in */ if (pcount != 0) { emalloc(names, char *, space, "func_install"); emalloc(pnames, char **, pcount * sizeof(char *), "func_install"); sp = names; for (i = 0, n = params->rnode; i < pcount; i++, n = n->rnode) { pnames[i] = sp; strcpy(sp, n->param); sp += strlen(n->param) + 1; } thisfunc->parmlist = pnames; } else { thisfunc->parmlist = NULL; } /* remove params from symbol table */ pop_params(params->rnode); /* update lint table info */ func_use(params->param, FUNC_DEFINE); func_count++; /* used by profiling / pretty printer */ } /* pop_var --- remove a variable from the symbol table */ static void pop_var(NODE *np, int freeit) { register NODE *bucket, **save; register size_t len; char *name; name = np->param; len = strlen(name); save = &(variables[hash(name, len, (unsigned long) HASHSIZE)]); for (bucket = *save; bucket != NULL; bucket = bucket->hnext) { if (len == bucket->hlength && STREQN(bucket->hname, name, len)) { var_count--; *save = bucket->hnext; freenode(bucket); if (freeit) free(np->param); return; } save = &(bucket->hnext); } } /* pop_params --- remove list of function parameters from symbol table */ /* * pop parameters out of the symbol table. do this in reverse order to * avoid reading freed memory if there were duplicated parameters. */ static void pop_params(NODE *params) { if (params == NULL) return; pop_params(params->rnode); pop_var(params, TRUE); } /* make_param --- make NAME into a function parameter */ static NODE * make_param(char *name) { NODE *r; getnode(r); r->type = Node_param_list; r->rnode = NULL; r->param = name; r->param_cnt = param_counter++; return (install(name, r)); } static struct fdesc { char *name; short used; short defined; struct fdesc *next; } *ftable[HASHSIZE]; /* func_use --- track uses and definitions of functions */ static void func_use(char *name, enum defref how) { struct fdesc *fp; int len; int ind; len = strlen(name); ind = hash(name, len, HASHSIZE); for (fp = ftable[ind]; fp != NULL; fp = fp->next) { if (strcmp(fp->name, name) == 0) { if (how == FUNC_DEFINE) fp->defined++; else fp->used++; return; } } /* not in the table, fall through to allocate a new one */ emalloc(fp, struct fdesc *, sizeof(struct fdesc), "func_use"); memset(fp, '\0', sizeof(struct fdesc)); emalloc(fp->name, char *, len + 1, "func_use"); strcpy(fp->name, name); if (how == FUNC_DEFINE) fp->defined++; else fp->used++; fp->next = ftable[ind]; ftable[ind] = fp; } /* check_funcs --- verify functions that are called but not defined */ static void check_funcs() { struct fdesc *fp, *next; int i; for (i = 0; i < HASHSIZE; i++) { for (fp = ftable[i]; fp != NULL; fp = fp->next) { #ifdef REALLYMEAN /* making this the default breaks old code. sigh. */ if (fp->defined == 0) { error( _("function `%s' called but never defined"), fp->name); errcount++; } #else if (do_lint && fp->defined == 0) lintwarn( _("function `%s' called but never defined"), fp->name); #endif if (do_lint && fp->used == 0) { lintwarn(_("function `%s' defined but never called"), fp->name); } } } /* now let's free all the memory */ for (i = 0; i < HASHSIZE; i++) { for (fp = ftable[i]; fp != NULL; fp = next) { next = fp->next; free(fp->name); free(fp); } } } /* param_sanity --- look for parameters that are regexp constants */ static void param_sanity(NODE *arglist) { NODE *argp, *arg; int i; for (i = 1, argp = arglist; argp != NULL; argp = argp->rnode, i++) { arg = argp->lnode; if (arg->type == Node_regex) warning(_("regexp constant for parameter #%d yields boolean value"), i); } } /* variable --- make sure NAME is in the symbol table */ NODE * variable(char *name, int can_free, NODETYPE type) { register NODE *r; static int env_loaded = FALSE; static int procinfo_loaded = FALSE; if (! env_loaded && STREQ(name, "ENVIRON")) { load_environ(); env_loaded = TRUE; } if (! do_traditional && ! procinfo_loaded && STREQ(name, "PROCINFO")) { load_procinfo(); procinfo_loaded = TRUE; } if ((r = lookup(name)) == NULL) r = install(name, node(Nnull_string, type, (NODE *) NULL)); else if (can_free) free(name); return r; } /* mk_rexp --- make a regular expression constant */ static NODE * mk_rexp(NODE *exp) { NODE *n; if (exp->type == Node_regex) return exp; getnode(n); n->type = Node_regex; n->re_exp = exp; n->re_text = NULL; n->re_reg = NULL; n->re_flags = 0; n->re_cnt = 1; return n; } /* isnoeffect --- when used as a statement, has no side effects */ /* * To be completely general, we should recursively walk the parse * tree, to make sure that all the subexpressions also have no effect. * Instead, we just weaken the actual warning that's printed, up above * in the grammar. */ static int isnoeffect(NODETYPE type) { switch (type) { case Node_times: case Node_quotient: case Node_mod: case Node_plus: case Node_minus: case Node_subscript: case Node_concat: case Node_exp: case Node_unary_minus: case Node_field_spec: case Node_and: case Node_or: case Node_equal: case Node_notequal: case Node_less: case Node_greater: case Node_leq: case Node_geq: case Node_match: case Node_nomatch: case Node_not: case Node_val: case Node_in_array: case Node_NF: case Node_NR: case Node_FNR: case Node_FS: case Node_RS: case Node_FIELDWIDTHS: case Node_IGNORECASE: case Node_OFS: case Node_ORS: case Node_OFMT: case Node_CONVFMT: case Node_BINMODE: case Node_LINT: return TRUE; default: break; /* keeps gcc -Wall happy */ } return FALSE; } /* isassignable --- can this node be assigned to? */ static int isassignable(register NODE *n) { switch (n->type) { case Node_var: case Node_FIELDWIDTHS: case Node_RS: case Node_FS: case Node_FNR: case Node_NR: case Node_NF: case Node_IGNORECASE: case Node_OFMT: case Node_CONVFMT: case Node_ORS: case Node_OFS: case Node_LINT: case Node_BINMODE: case Node_field_spec: case Node_subscript: return TRUE; case Node_param_list: return ((n->flags & FUNC) == 0); /* ok if not func name */ default: break; /* keeps gcc -Wall happy */ } return FALSE; } /* stopme --- for debugging */ NODE * stopme(NODE *tree) { return tmp_number((AWKNUM) 0.0); } /* dumpintlstr --- write out an initial .po file entry for the string */ static void dumpintlstr(char *str, size_t len) { char *cp; /* See the GNU gettext distribution for details on the file format */ if (source != NULL) { /* ala the gettext sources, remove leading `./'s */ for (cp = source; cp[0] == '.' && cp[1] == '/'; cp += 2) continue; printf("#: %s:%d\n", cp, sourceline); } printf("msgid "); fflush(stdout); pp_string_fp(stdout, str, len, '"', TRUE); putchar('\n'); printf("msgstr \"\"\n\n"); } /* count_args --- count the number of printf arguments */ static void count_args(NODE *tree) { size_t count = 0; NODE *save_tree; assert(tree->type == Node_K_printf || (tree->type == Node_builtin && tree->proc == do_sprintf)); save_tree = tree; tree = tree->lnode; /* printf format string */ for (count = 0; tree != NULL; tree = tree->rnode) count++; save_tree->printf_count = count; }