diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 13:09:56 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 13:09:56 +0300 |
commit | bc70de7b3302d5a81515b901cae376b8b51d2004 (patch) | |
tree | d36d6743e65697f6923b79d0ea8f9f9bf4ef7398 /awkgram.c | |
parent | b9e4a1fd4c8c8753ab8a9887bab55f03efe1e3e2 (diff) | |
download | egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.gz egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.tar.bz2 egawk-bc70de7b3302d5a81515b901cae376b8b51d2004.zip |
Move to gawk-3.1.0.
Diffstat (limited to 'awkgram.c')
-rw-r--r-- | awkgram.c | 4483 |
1 files changed, 4483 insertions, 0 deletions
diff --git a/awkgram.c b/awkgram.c new file mode 100644 index 00000000..f8b93ad9 --- /dev/null +++ b/awkgram.c @@ -0,0 +1,4483 @@ + +/* 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 <stdio.h> + +#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 <alloca.h> +#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 <malloc.h> +#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 <malloc.h> */ + #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; +} |