aboutsummaryrefslogtreecommitdiffstats
path: root/awkgram.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-11-18 23:00:31 +0200
committerArnold D. Robbins <arnold@skeeve.com>2010-11-18 23:00:31 +0200
commit6f3612539c425da2bc1d34db621696e6a273b01c (patch)
tree9623b3ac2c54a93e5eed3be2b1dda7f4e4bf0e47 /awkgram.c
parent4e3701015635401df2fc4da58abaab7645f4ebd3 (diff)
downloadegawk-6f3612539c425da2bc1d34db621696e6a273b01c.tar.gz
egawk-6f3612539c425da2bc1d34db621696e6a273b01c.tar.bz2
egawk-6f3612539c425da2bc1d34db621696e6a273b01c.zip
Bring latest byte code gawk into git. Hurray!
Diffstat (limited to 'awkgram.c')
-rw-r--r--awkgram.c7107
1 files changed, 4651 insertions, 2456 deletions
diff --git a/awkgram.c b/awkgram.c
index b52a6bb3..607247ce 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -80,64 +80,103 @@
#define signed /**/
#endif
-#define CAN_FREE TRUE
-#define DONT_FREE FALSE
-
-#ifdef CAN_USE_STDARG_H
static void yyerror(const char *m, ...) ATTRIBUTE_PRINTF_1;
-#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 *make_for_loop P((NODE *init, NODE *cond, NODE *incr));
-static NODE *append_right P((NODE *list, NODE *new));
-static inline NODE *append_pattern P((NODE **list, NODE *patt));
-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 int parms_shadow P((const char *fname, NODE *func));
-static int isnoeffect P((NODETYPE t));
-static int isassignable P((NODE *n));
-static void dumpintlstr P((const char *str, size_t len));
-static void dumpintlstr2 P((const char *str1, size_t len1, const char *str2, size_t len2));
-static void count_args P((NODE *n));
-static int isarray P((NODE *n));
+static char *get_src_buf(void);
+static int yylex(void);
+int yyparse(void);
+static INSTRUCTION *snode(INSTRUCTION *subn, INSTRUCTION *op);
+static int func_install(INSTRUCTION *fp, INSTRUCTION *def);
+static void pop_params(NODE *params);
+static NODE *make_param(char *pname);
+static NODE *mk_rexp(INSTRUCTION *exp);
+static void append_param(char *pname);
+static int dup_parms(NODE *func);
+static void param_sanity(INSTRUCTION *arglist);
+static int parms_shadow(INSTRUCTION *pc, int *shadow);
+static int isnoeffect(OPCODE type);
+static INSTRUCTION *make_assignable(INSTRUCTION *ip);
+static void dumpintlstr(const char *str, size_t len);
+static void dumpintlstr2(const char *str1, size_t len1, const char *str2, size_t len2);
+static int isarray(NODE *n);
+static int include_source(char *src);
+static void next_sourcefile(void);
+static char *tokexpand(void);
+
+#define instruction(t) bcalloc(t, 1, 0)
+
+static INSTRUCTION *mk_program(void);
+static INSTRUCTION *append_rule(INSTRUCTION *pattern, INSTRUCTION *action);
+static INSTRUCTION *mk_condition(INSTRUCTION *cond, INSTRUCTION *ifp, INSTRUCTION *true_branch,
+ INSTRUCTION *elsep, INSTRUCTION *false_branch);
+static INSTRUCTION *mk_expression_list(INSTRUCTION *list, INSTRUCTION *s1);
+static INSTRUCTION *mk_for_loop(INSTRUCTION *forp, INSTRUCTION *init, INSTRUCTION *cond,
+ INSTRUCTION *incr, INSTRUCTION *body);
+static void fix_break_continue(INSTRUCTION *start, INSTRUCTION *end, int check_continue);
+static INSTRUCTION *mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op);
+static INSTRUCTION *mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op);
+static INSTRUCTION *mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op);
+static INSTRUCTION *mk_getline(INSTRUCTION *op, INSTRUCTION *opt_var, INSTRUCTION *redir, OPCODE redirtype);
+static NODE *make_regnode(int type, NODE *exp);
+static int count_expressions(INSTRUCTION **list, int isarg);
+static INSTRUCTION *optimize_assignment(INSTRUCTION *exp);
+static void add_lint(INSTRUCTION *list, LINTTYPE linttype);
enum defref { FUNC_DEFINE, FUNC_USE };
-static void func_use P((const char *name, enum defref how));
-static void check_funcs P((void));
+static void func_use(const char *name, enum defref how);
+static void check_funcs(void);
+static void free_bcpool(INSTRUCTION *pl);
-static ssize_t read_one_line P((int fd, void *buffer, size_t count));
-static int one_line_close P((int fd));
+static ssize_t read_one_line(int fd, void *buffer, size_t count);
+static int one_line_close(int fd);
-static NODE *constant_fold P((NODE *left, NODETYPE op, NODE *right));
-static NODE *optimize_concat P((NODE *left, NODETYPE op, NODE *right));
+static void (*install_func)(char *) = NULL;
+static int want_source = FALSE;
static int want_regexp; /* lexical scanning kludge */
static int can_return; /* parsing kludge */
-static int begin_or_end_rule = FALSE; /* parsing kludge */
-static int parsing_end_rule = FALSE; /* for warnings */
-static int beginfile_or_endfile_rule = FALSE; /* parsing kludge */
-static int parsing_endfile_rule = FALSE; /* for warnings */
+static int rule = 0;
+
+const char *const ruletab[] = {
+ "?",
+ "BEGIN",
+ "Rule",
+ "END",
+ "BEGINFILE",
+ "ENDFILE",
+};
+
static int in_print = FALSE; /* lexical scanning kludge for print */
static int in_parens = 0; /* lexical scanning kludge for print */
-static char *lexptr; /* pointer to next char during parsing */
+static int sub_counter = 0; /* array dimension counter for use in delete */
+static char *lexptr = NULL; /* 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 int lexeof; /* seen EOF for current source? */
static char *thisline = NULL;
+static int in_braces = 0; /* count braces for firstline, lastline in an 'action' */
+static int lastline = 0;
+static int firstline = 0;
+static SRCFILE *sourcefile = NULL; /* current program source */
+static int lasttok = 0;
+static int eof_warned = FALSE; /* GLOBAL: want warning for each file */
+static int break_allowed; /* kludge for break */
+static int continue_allowed; /* kludge for continue */
+
+
+#define END_FILE -1000
+#define END_SRC -2000
+
#define YYDEBUG_LEXER_TEXT (lexeme)
static int param_counter;
+static NODE *func_params; /* list of parameters for the current function */
static char *tokstart = NULL;
static char *tok = NULL;
static char *tokend;
+static int errcount = 0;
+
+static NODE *symbol_list;
+extern void destroy_symbol(char *name);
static long func_count; /* total number of functions */
@@ -147,14 +186,25 @@ static int var_count; /* total number of global variables */
extern char *source;
extern int sourceline;
-extern struct src *srcfiles;
-extern long numfiles;
-extern int errcount;
-extern NODE *begin_block;
-extern NODE *end_block;
-extern NODE *beginfile_block;
-extern NODE *endfile_block;
+extern SRCFILE *srcfiles;
+extern INSTRUCTION *rule_list;
+extern int max_args;
+
+static INSTRUCTION *rule_block[sizeof(ruletab)];
+static INSTRUCTION *ip_rec;
+static INSTRUCTION *ip_newfile;
+static INSTRUCTION *ip_atexit = NULL;
+static INSTRUCTION *ip_end;
+static INSTRUCTION *ip_endfile;
+static INSTRUCTION *ip_beginfile;
+
+static inline INSTRUCTION *list_create(INSTRUCTION *x);
+static inline INSTRUCTION *list_append(INSTRUCTION *l, INSTRUCTION *x);
+static inline INSTRUCTION *list_prepend(INSTRUCTION *l, INSTRUCTION *x);
+static inline INSTRUCTION *list_merge(INSTRUCTION *l1, INSTRUCTION *l2);
+
+extern double fmod(double x, double y);
/*
* This string cannot occur as a real awk identifier.
* Use it as a special token to make function parsing
@@ -166,9 +216,11 @@ extern NODE *endfile_block;
*/
static char builtin_func[] = "@builtin";
+#define YYSTYPE INSTRUCTION *
+
/* Line 189 of yacc.c */
-#line 172 "awkgram.c"
+#line 224 "awkgram.c"
/* Enabling traces. */
#ifndef YYDEBUG
@@ -198,7 +250,7 @@ static char builtin_func[] = "@builtin";
FUNC_CALL = 258,
NAME = 259,
REGEXP = 260,
- ERROR = 261,
+ FILENAME = 261,
YNUMBER = 262,
YSTRING = 263,
RELOP = 264,
@@ -208,46 +260,50 @@ static char builtin_func[] = "@builtin";
ASSIGN = 268,
MATCHOP = 269,
CONCAT_OP = 270,
- LEX_BEGIN = 271,
- LEX_END = 272,
- LEX_IF = 273,
- LEX_ELSE = 274,
- LEX_RETURN = 275,
- LEX_DELETE = 276,
- LEX_BEGINFILE = 277,
- LEX_ENDFILE = 278,
- LEX_SWITCH = 279,
- LEX_CASE = 280,
- LEX_DEFAULT = 281,
- LEX_WHILE = 282,
- LEX_DO = 283,
- LEX_FOR = 284,
- LEX_BREAK = 285,
- LEX_CONTINUE = 286,
- LEX_PRINT = 287,
- LEX_PRINTF = 288,
- LEX_NEXT = 289,
- LEX_EXIT = 290,
- LEX_FUNCTION = 291,
- LEX_GETLINE = 292,
- LEX_NEXTFILE = 293,
- LEX_IN = 294,
- LEX_AND = 295,
- LEX_OR = 296,
- INCREMENT = 297,
- DECREMENT = 298,
- LEX_BUILTIN = 299,
- LEX_LENGTH = 300,
- NEWLINE = 301,
- SLASH_BEFORE_EQUAL = 302,
- UNARY = 303
+ SUBSCRIPT = 271,
+ LEX_BEGIN = 272,
+ LEX_END = 273,
+ LEX_IF = 274,
+ LEX_ELSE = 275,
+ LEX_RETURN = 276,
+ LEX_DELETE = 277,
+ LEX_SWITCH = 278,
+ LEX_CASE = 279,
+ LEX_DEFAULT = 280,
+ LEX_WHILE = 281,
+ LEX_DO = 282,
+ LEX_FOR = 283,
+ LEX_BREAK = 284,
+ LEX_CONTINUE = 285,
+ LEX_PRINT = 286,
+ LEX_PRINTF = 287,
+ LEX_NEXT = 288,
+ LEX_EXIT = 289,
+ LEX_FUNCTION = 290,
+ LEX_BEGINFILE = 291,
+ LEX_ENDFILE = 292,
+ LEX_GETLINE = 293,
+ LEX_NEXTFILE = 294,
+ LEX_IN = 295,
+ LEX_AND = 296,
+ LEX_OR = 297,
+ INCREMENT = 298,
+ DECREMENT = 299,
+ LEX_BUILTIN = 300,
+ LEX_LENGTH = 301,
+ LEX_EOF = 302,
+ LEX_INCLUDE = 303,
+ LEX_EVAL = 304,
+ NEWLINE = 305,
+ SLASH_BEFORE_EQUAL = 306,
+ UNARY = 307
};
#endif
/* Tokens. */
#define FUNC_CALL 258
#define NAME 259
#define REGEXP 260
-#define ERROR 261
+#define FILENAME 261
#define YNUMBER 262
#define YSTRING 263
#define RELOP 264
@@ -257,62 +313,49 @@ static char builtin_func[] = "@builtin";
#define ASSIGN 268
#define MATCHOP 269
#define CONCAT_OP 270
-#define LEX_BEGIN 271
-#define LEX_END 272
-#define LEX_IF 273
-#define LEX_ELSE 274
-#define LEX_RETURN 275
-#define LEX_DELETE 276
-#define LEX_BEGINFILE 277
-#define LEX_ENDFILE 278
-#define LEX_SWITCH 279
-#define LEX_CASE 280
-#define LEX_DEFAULT 281
-#define LEX_WHILE 282
-#define LEX_DO 283
-#define LEX_FOR 284
-#define LEX_BREAK 285
-#define LEX_CONTINUE 286
-#define LEX_PRINT 287
-#define LEX_PRINTF 288
-#define LEX_NEXT 289
-#define LEX_EXIT 290
-#define LEX_FUNCTION 291
-#define LEX_GETLINE 292
-#define LEX_NEXTFILE 293
-#define LEX_IN 294
-#define LEX_AND 295
-#define LEX_OR 296
-#define INCREMENT 297
-#define DECREMENT 298
-#define LEX_BUILTIN 299
-#define LEX_LENGTH 300
-#define NEWLINE 301
-#define SLASH_BEFORE_EQUAL 302
-#define UNARY 303
+#define SUBSCRIPT 271
+#define LEX_BEGIN 272
+#define LEX_END 273
+#define LEX_IF 274
+#define LEX_ELSE 275
+#define LEX_RETURN 276
+#define LEX_DELETE 277
+#define LEX_SWITCH 278
+#define LEX_CASE 279
+#define LEX_DEFAULT 280
+#define LEX_WHILE 281
+#define LEX_DO 282
+#define LEX_FOR 283
+#define LEX_BREAK 284
+#define LEX_CONTINUE 285
+#define LEX_PRINT 286
+#define LEX_PRINTF 287
+#define LEX_NEXT 288
+#define LEX_EXIT 289
+#define LEX_FUNCTION 290
+#define LEX_BEGINFILE 291
+#define LEX_ENDFILE 292
+#define LEX_GETLINE 293
+#define LEX_NEXTFILE 294
+#define LEX_IN 295
+#define LEX_AND 296
+#define LEX_OR 297
+#define INCREMENT 298
+#define DECREMENT 299
+#define LEX_BUILTIN 300
+#define LEX_LENGTH 301
+#define LEX_EOF 302
+#define LEX_INCLUDE 303
+#define LEX_EVAL 304
+#define NEWLINE 305
+#define SLASH_BEFORE_EQUAL 306
+#define UNARY 307
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-
-/* Line 214 of yacc.c */
-#line 124 "awkgram.y"
-
- long lval;
- AWKNUM fval;
- NODE *nodeval;
- NODETYPE nodetypeval;
- char *sval;
- NODE *(*ptrval) P((void));
-
-
-
-/* Line 214 of yacc.c */
-#line 315 "awkgram.c"
-} YYSTYPE;
+typedef int YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -323,7 +366,7 @@ typedef union YYSTYPE
/* Line 264 of yacc.c */
-#line 327 "awkgram.c"
+#line 370 "awkgram.c"
#ifdef short
# undef short
@@ -395,8 +438,7 @@ typedef short int yytype_int16;
#ifndef lint
# define YYID(n) (n)
#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static int
YYID (int yyi)
#else
@@ -479,9 +521,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+#if (! defined yyoverflow && (! defined __cplusplus || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
@@ -536,22 +576,22 @@ union yyalloc
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 5
+#define YYFINAL 2
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 1105
+#define YYLAST 1142
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 70
+#define YYNTOKENS 74
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 58
+#define YYNNTS 66
/* YYNRULES -- Number of rules. */
-#define YYNRULES 170
+#define YYNRULES 186
/* YYNRULES -- Number of states. */
-#define YYNSTATES 314
+#define YYNSTATES 330
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 303
+#define YYMAXUTOK 307
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -562,16 +602,16 @@ static const yytype_uint8 yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 58, 2, 2, 61, 57, 2, 2,
- 62, 63, 55, 53, 50, 54, 2, 56, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 49, 69,
- 51, 2, 52, 48, 66, 2, 2, 2, 2, 2,
+ 2, 2, 2, 62, 2, 2, 65, 61, 2, 2,
+ 66, 67, 59, 57, 54, 58, 2, 60, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 53, 73,
+ 55, 2, 56, 52, 68, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 64, 2, 65, 60, 2, 2, 2, 2, 2,
+ 2, 69, 2, 70, 64, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 67, 2, 68, 2, 2, 2, 2,
+ 2, 2, 2, 71, 2, 72, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -589,7 +629,7 @@ static const yytype_uint8 yytranslate[] =
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 59
+ 45, 46, 47, 48, 49, 50, 51, 63
};
#if YYDEBUG
@@ -597,106 +637,112 @@ static const yytype_uint8 yytranslate[] =
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 7, 8, 11, 14, 17, 20, 23,
- 24, 26, 30, 32, 34, 36, 38, 44, 46, 48,
- 50, 52, 54, 55, 63, 64, 68, 70, 72, 73,
- 76, 79, 81, 84, 87, 91, 93, 103, 110, 119,
- 128, 141, 153, 156, 159, 162, 165, 169, 170, 175,
- 178, 179, 184, 190, 193, 198, 200, 201, 203, 205,
- 206, 209, 212, 218, 223, 225, 228, 231, 233, 235,
- 237, 239, 241, 247, 248, 249, 253, 260, 270, 272,
- 275, 276, 278, 279, 282, 283, 285, 287, 291, 293,
- 296, 300, 301, 303, 304, 306, 308, 312, 314, 317,
- 321, 325, 329, 333, 337, 341, 345, 349, 355, 357,
- 359, 361, 364, 366, 368, 370, 372, 374, 376, 379,
- 381, 385, 389, 393, 397, 401, 405, 409, 412, 415,
- 421, 426, 430, 434, 438, 442, 446, 450, 452, 455,
- 459, 464, 469, 471, 473, 475, 478, 481, 483, 485,
- 488, 491, 493, 496, 501, 502, 504, 506, 511, 513,
- 517, 519, 521, 522, 525, 528, 530, 531, 533, 535,
- 537
+ 0, 0, 3, 4, 7, 10, 13, 16, 19, 22,
+ 25, 30, 32, 35, 37, 38, 40, 44, 46, 48,
+ 50, 52, 58, 60, 62, 64, 67, 69, 71, 72,
+ 80, 81, 85, 87, 89, 90, 93, 96, 98, 101,
+ 104, 108, 110, 120, 127, 136, 145, 158, 170, 172,
+ 175, 178, 181, 184, 188, 189, 194, 197, 198, 203,
+ 204, 209, 214, 216, 217, 219, 221, 222, 225, 228,
+ 234, 239, 241, 244, 247, 249, 251, 253, 255, 257,
+ 261, 262, 263, 267, 274, 284, 286, 289, 290, 292,
+ 293, 296, 297, 299, 301, 305, 307, 310, 314, 315,
+ 317, 318, 320, 322, 326, 328, 331, 335, 339, 343,
+ 347, 351, 355, 359, 363, 369, 371, 373, 375, 378,
+ 380, 382, 384, 386, 388, 390, 393, 395, 399, 403,
+ 407, 411, 415, 419, 423, 426, 429, 435, 440, 444,
+ 448, 452, 456, 460, 464, 466, 469, 473, 478, 483,
+ 485, 487, 489, 492, 495, 497, 499, 502, 505, 507,
+ 510, 515, 516, 518, 519, 522, 524, 527, 529, 533,
+ 535, 538, 541, 543, 546, 548, 552, 554, 556, 557,
+ 560, 563, 565, 566, 568, 570, 572
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
+static const yytype_int16 yyrhs[] =
{
- 71, 0, -1, 100, 72, 100, -1, -1, 72, 73,
- -1, 72, 1, -1, 74, 75, -1, 74, 84, -1,
- 78, 75, -1, -1, 107, -1, 107, 50, 107, -1,
- 16, -1, 17, -1, 22, -1, 23, -1, 121, 83,
- 122, 124, 100, -1, 4, -1, 3, -1, 77, -1,
- 44, -1, 45, -1, -1, 36, 79, 76, 62, 102,
- 123, 100, -1, -1, 82, 81, 5, -1, 56, -1,
- 47, -1, -1, 83, 85, -1, 83, 1, -1, 99,
- -1, 125, 100, -1, 125, 100, -1, 121, 83, 122,
- -1, 98, -1, 24, 62, 107, 123, 100, 121, 90,
- 100, 122, -1, 27, 62, 107, 123, 100, 85, -1,
- 28, 100, 85, 27, 62, 107, 123, 100, -1, 29,
- 62, 4, 39, 4, 123, 100, 85, -1, 29, 62,
- 89, 125, 100, 107, 125, 100, 89, 123, 100, 85,
- -1, 29, 62, 89, 125, 100, 125, 100, 89, 123,
- 100, 85, -1, 30, 84, -1, 31, 84, -1, 34,
- 84, -1, 38, 84, -1, 35, 104, 84, -1, -1,
- 20, 86, 104, 84, -1, 87, 84, -1, -1, 94,
- 88, 95, 96, -1, 21, 4, 64, 106, 65, -1,
- 21, 4, -1, 21, 62, 4, 63, -1, 107, -1,
- -1, 87, -1, 91, -1, -1, 91, 92, -1, 91,
- 1, -1, 25, 93, 126, 100, 83, -1, 26, 126,
- 100, 83, -1, 7, -1, 54, 7, -1, 53, 7,
- -1, 8, -1, 80, -1, 32, -1, 33, -1, 105,
- -1, 62, 107, 127, 106, 123, -1, -1, -1, 10,
- 97, 111, -1, 18, 62, 107, 123, 100, 85, -1,
- 18, 62, 107, 123, 100, 85, 19, 100, 85, -1,
- 46, -1, 99, 46, -1, -1, 99, -1, -1, 51,
- 112, -1, -1, 103, -1, 4, -1, 103, 127, 4,
- -1, 1, -1, 103, 1, -1, 103, 127, 1, -1,
- -1, 107, -1, -1, 106, -1, 107, -1, 106, 127,
- 107, -1, 1, -1, 106, 1, -1, 106, 1, 107,
- -1, 106, 127, 1, -1, 118, 108, 107, -1, 107,
- 40, 107, -1, 107, 41, 107, -1, 107, 14, 107,
- -1, 107, 39, 4, -1, 107, 110, 107, -1, 107,
- 48, 107, 49, 107, -1, 111, -1, 13, -1, 12,
- -1, 47, 13, -1, 9, -1, 51, -1, 109, -1,
- 52, -1, 112, -1, 113, -1, 111, 112, -1, 114,
- -1, 112, 60, 112, -1, 112, 55, 112, -1, 112,
- 56, 112, -1, 112, 57, 112, -1, 112, 53, 112,
- -1, 112, 54, 112, -1, 37, 117, 101, -1, 118,
- 42, -1, 118, 43, -1, 62, 106, 123, 39, 4,
- -1, 111, 11, 37, 117, -1, 113, 60, 112, -1,
- 113, 55, 112, -1, 113, 56, 112, -1, 113, 57,
- 112, -1, 113, 53, 112, -1, 113, 54, 112, -1,
- 80, -1, 58, 112, -1, 62, 107, 123, -1, 44,
- 62, 105, 123, -1, 45, 62, 105, 123, -1, 45,
- -1, 115, -1, 118, -1, 42, 118, -1, 43, 118,
- -1, 7, -1, 8, -1, 54, 112, -1, 53, 112,
- -1, 116, -1, 66, 116, -1, 3, 62, 105, 123,
- -1, -1, 118, -1, 4, -1, 4, 64, 106, 65,
- -1, 119, -1, 61, 114, 120, -1, 42, -1, 43,
- -1, -1, 67, 100, -1, 68, 100, -1, 63, -1,
- -1, 125, -1, 69, -1, 49, -1, 50, 100, -1
+ 75, 0, -1, -1, 75, 76, -1, 75, 105, -1,
+ 75, 47, -1, 75, 1, -1, 78, 79, -1, 78,
+ 88, -1, 82, 79, -1, 68, 48, 77, 88, -1,
+ 6, -1, 6, 1, -1, 1, -1, -1, 113, -1,
+ 113, 54, 113, -1, 17, -1, 18, -1, 36, -1,
+ 37, -1, 133, 87, 134, 136, 106, -1, 4, -1,
+ 3, -1, 81, -1, 68, 49, -1, 45, -1, 46,
+ -1, -1, 35, 83, 80, 66, 108, 135, 106, -1,
+ -1, 86, 85, 5, -1, 60, -1, 51, -1, -1,
+ 87, 89, -1, 87, 1, -1, 105, -1, 137, 106,
+ -1, 137, 106, -1, 133, 87, 134, -1, 104, -1,
+ 23, 66, 113, 135, 106, 133, 96, 106, 134, -1,
+ 26, 66, 113, 135, 106, 89, -1, 27, 106, 89,
+ 26, 66, 113, 135, 106, -1, 28, 66, 4, 40,
+ 130, 135, 106, 89, -1, 28, 66, 95, 137, 106,
+ 113, 137, 106, 95, 135, 106, 89, -1, 28, 66,
+ 95, 137, 106, 137, 106, 95, 135, 106, 89, -1,
+ 90, -1, 29, 88, -1, 30, 88, -1, 33, 88,
+ -1, 39, 88, -1, 34, 110, 88, -1, -1, 21,
+ 91, 110, 88, -1, 92, 88, -1, -1, 100, 93,
+ 101, 102, -1, -1, 22, 4, 94, 124, -1, 22,
+ 66, 4, 67, -1, 113, -1, -1, 92, -1, 97,
+ -1, -1, 97, 98, -1, 97, 1, -1, 24, 99,
+ 138, 106, 87, -1, 25, 138, 106, 87, -1, 7,
+ -1, 58, 7, -1, 57, 7, -1, 8, -1, 84,
+ -1, 31, -1, 32, -1, 111, -1, 66, 112, 135,
+ -1, -1, -1, 10, 103, 117, -1, 19, 66, 113,
+ 135, 106, 89, -1, 19, 66, 113, 135, 106, 89,
+ 20, 106, 89, -1, 50, -1, 105, 50, -1, -1,
+ 105, -1, -1, 55, 118, -1, -1, 109, -1, 4,
+ -1, 109, 139, 4, -1, 1, -1, 109, 1, -1,
+ 109, 139, 1, -1, -1, 113, -1, -1, 112, -1,
+ 113, -1, 112, 139, 113, -1, 1, -1, 112, 1,
+ -1, 112, 1, 113, -1, 112, 139, 1, -1, 131,
+ 114, 113, -1, 113, 41, 113, -1, 113, 42, 113,
+ -1, 113, 14, 113, -1, 113, 40, 130, -1, 113,
+ 116, 113, -1, 113, 52, 113, 53, 113, -1, 117,
+ -1, 13, -1, 12, -1, 51, 13, -1, 9, -1,
+ 55, -1, 115, -1, 56, -1, 118, -1, 119, -1,
+ 117, 118, -1, 120, -1, 118, 64, 118, -1, 118,
+ 59, 118, -1, 118, 60, 118, -1, 118, 61, 118,
+ -1, 118, 57, 118, -1, 118, 58, 118, -1, 38,
+ 123, 107, -1, 131, 43, -1, 131, 44, -1, 66,
+ 112, 135, 40, 130, -1, 117, 11, 38, 123, -1,
+ 119, 64, 118, -1, 119, 59, 118, -1, 119, 60,
+ 118, -1, 119, 61, 118, -1, 119, 57, 118, -1,
+ 119, 58, 118, -1, 84, -1, 62, 118, -1, 66,
+ 113, 135, -1, 45, 66, 111, 135, -1, 46, 66,
+ 111, 135, -1, 46, -1, 121, -1, 131, -1, 43,
+ 131, -1, 44, 131, -1, 7, -1, 8, -1, 58,
+ 118, -1, 57, 118, -1, 122, -1, 68, 122, -1,
+ 3, 66, 111, 135, -1, -1, 131, -1, -1, 125,
+ 16, -1, 126, -1, 125, 126, -1, 127, -1, 69,
+ 112, 70, -1, 127, -1, 128, 127, -1, 128, 16,
+ -1, 4, -1, 4, 129, -1, 130, -1, 65, 120,
+ 132, -1, 43, -1, 44, -1, -1, 71, 106, -1,
+ 72, 106, -1, 67, -1, -1, 137, -1, 73, -1,
+ 53, -1, 54, 106, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 187, 187, 193, 195, 200, 212, 216, 234, 245,
- 248, 252, 262, 271, 280, 285, 293, 298, 300, 302,
- 313, 314, 319, 318, 342, 341, 367, 368, 373, 374,
- 392, 397, 398, 402, 404, 406, 408, 410, 412, 414,
- 458, 462, 467, 470, 473, 485, 523, 526, 525, 535,
- 547, 547, 578, 580, 598, 620, 626, 627, 632, 685,
- 686, 703, 708, 710, 715, 717, 722, 724, 726, 731,
- 732, 740, 741, 747, 752, 752, 764, 769, 776, 777,
- 780, 782, 787, 788, 794, 795, 800, 802, 804, 806,
- 808, 815, 816, 822, 823, 828, 830, 836, 838, 840,
- 842, 847, 853, 855, 857, 863, 869, 875, 877, 882,
- 884, 886, 891, 893, 897, 898, 903, 905, 907, 912,
- 914, 916, 918, 920, 922, 924, 926, 947, 949, 951,
- 964, 969, 971, 973, 975, 977, 979, 984, 986, 988,
- 990, 993, 995, 1009, 1010, 1011, 1013, 1015, 1017, 1020,
- 1028, 1039, 1044, 1060, 1071, 1072, 1077, 1079, 1094, 1104,
- 1119, 1120, 1121, 1125, 1129, 1133, 1136, 1138, 1142, 1146,
- 1149
+ 0, 215, 215, 217, 222, 223, 227, 239, 243, 254,
+ 262, 270, 279, 281, 287, 288, 290, 316, 326, 336,
+ 342, 351, 361, 363, 365, 376, 381, 382, 387, 386,
+ 416, 415, 446, 448, 453, 454, 467, 472, 473, 477,
+ 479, 481, 488, 509, 555, 598, 708, 715, 722, 732,
+ 741, 750, 757, 782, 797, 796, 808, 820, 820, 916,
+ 916, 944, 970, 976, 977, 982, 1035, 1036, 1048, 1053,
+ 1072, 1090, 1095, 1102, 1108, 1113, 1121, 1123, 1132, 1133,
+ 1141, 1146, 1146, 1157, 1161, 1169, 1170, 1173, 1175, 1180,
+ 1181, 1188, 1190, 1194, 1200, 1207, 1209, 1211, 1218, 1219,
+ 1225, 1226, 1231, 1233, 1238, 1240, 1242, 1244, 1250, 1256,
+ 1258, 1260, 1275, 1284, 1290, 1292, 1297, 1299, 1301, 1309,
+ 1311, 1316, 1318, 1323, 1325, 1327, 1375, 1377, 1379, 1381,
+ 1383, 1385, 1387, 1389, 1410, 1415, 1420, 1443, 1449, 1451,
+ 1453, 1455, 1457, 1459, 1464, 1468, 1508, 1510, 1516, 1522,
+ 1534, 1535, 1536, 1541, 1546, 1550, 1554, 1566, 1579, 1584,
+ 1620, 1638, 1639, 1645, 1646, 1651, 1653, 1660, 1677, 1694,
+ 1696, 1703, 1708, 1716, 1730, 1742, 1751, 1755, 1759, 1763,
+ 1767, 1771, 1774, 1776, 1780, 1784, 1788
};
#endif
@@ -705,29 +751,31 @@ static const yytype_uint16 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "FUNC_CALL", "NAME", "REGEXP", "ERROR",
- "YNUMBER", "YSTRING", "RELOP", "IO_OUT", "IO_IN", "ASSIGNOP", "ASSIGN",
- "MATCHOP", "CONCAT_OP", "LEX_BEGIN", "LEX_END", "LEX_IF", "LEX_ELSE",
- "LEX_RETURN", "LEX_DELETE", "LEX_BEGINFILE", "LEX_ENDFILE", "LEX_SWITCH",
+ "$end", "error", "$undefined", "FUNC_CALL", "NAME", "REGEXP",
+ "FILENAME", "YNUMBER", "YSTRING", "RELOP", "IO_OUT", "IO_IN", "ASSIGNOP",
+ "ASSIGN", "MATCHOP", "CONCAT_OP", "SUBSCRIPT", "LEX_BEGIN", "LEX_END",
+ "LEX_IF", "LEX_ELSE", "LEX_RETURN", "LEX_DELETE", "LEX_SWITCH",
"LEX_CASE", "LEX_DEFAULT", "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",
+ "LEX_FUNCTION", "LEX_BEGINFILE", "LEX_ENDFILE", "LEX_GETLINE",
+ "LEX_NEXTFILE", "LEX_IN", "LEX_AND", "LEX_OR", "INCREMENT", "DECREMENT",
+ "LEX_BUILTIN", "LEX_LENGTH", "LEX_EOF", "LEX_INCLUDE", "LEX_EVAL",
"NEWLINE", "SLASH_BEFORE_EQUAL", "'?'", "':'", "','", "'<'", "'>'",
"'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "UNARY", "'^'", "'$'", "'('",
- "')'", "'['", "']'", "'@'", "'{'", "'}'", "';'", "$accept", "start",
- "program", "rule", "pattern", "action", "func_name", "lex_builtin",
+ "')'", "'@'", "'['", "']'", "'{'", "'}'", "';'", "$accept", "program",
+ "rule", "source", "pattern", "action", "func_name", "lex_builtin",
"function_prologue", "$@1", "regexp", "$@2", "a_slash", "statements",
- "statement_term", "statement", "$@3", "simple_stmt", "$@4",
- "opt_simple_stmt", "switch_body", "case_statements", "case_statement",
- "case_value", "print", "print_expression_list", "output_redir", "$@5",
- "if_statement", "nls", "opt_nls", "input_redir", "opt_param_list",
- "param_list", "opt_exp", "opt_expression_list", "expression_list", "exp",
- "assign_operator", "relop_or_less", "a_relop", "common_exp", "simp_exp",
- "simp_exp_nc", "non_post_simp_exp", "function_call",
- "direct_function_call", "opt_variable", "variable", "field_spec",
- "opt_incdec", "l_brace", "r_brace", "r_paren", "opt_semi", "semi",
- "colon", "comma", 0
+ "statement_term", "statement", "non_compound_stmt", "$@3", "simple_stmt",
+ "$@4", "$@5", "opt_simple_stmt", "switch_body", "case_statements",
+ "case_statement", "case_value", "print", "print_expression_list",
+ "output_redir", "$@6", "if_statement", "nls", "opt_nls", "input_redir",
+ "opt_param_list", "param_list", "opt_exp", "opt_expression_list",
+ "expression_list", "exp", "assign_operator", "relop_or_less", "a_relop",
+ "common_exp", "simp_exp", "simp_exp_nc", "non_post_simp_exp",
+ "func_call", "direct_func_call", "opt_variable", "delete_subscript_list",
+ "delete_subscript", "delete_exp_list", "bracketed_exp_list", "subscript",
+ "subscript_list", "simple_variable", "variable", "opt_incdec", "l_brace",
+ "r_brace", "r_paren", "opt_semi", "semi", "colon", "comma", 0
};
#endif
@@ -740,56 +788,59 @@ static const yytype_uint16 yytoknum[] =
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
- 295, 296, 297, 298, 299, 300, 301, 302, 63, 58,
- 44, 60, 62, 43, 45, 42, 47, 37, 33, 303,
- 94, 36, 40, 41, 91, 93, 64, 123, 125, 59
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 63, 58, 44, 60, 62, 43, 45, 42,
+ 47, 37, 33, 307, 94, 36, 40, 41, 64, 91,
+ 93, 123, 125, 59
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 70, 71, 72, 72, 72, 73, 73, 73, 74,
- 74, 74, 74, 74, 74, 74, 75, 76, 76, 76,
- 77, 77, 79, 78, 81, 80, 82, 82, 83, 83,
- 83, 84, 84, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 86, 85, 85,
- 88, 87, 87, 87, 87, 87, 89, 89, 90, 91,
- 91, 91, 92, 92, 93, 93, 93, 93, 93, 94,
- 94, 95, 95, 96, 97, 96, 98, 98, 99, 99,
- 100, 100, 101, 101, 102, 102, 103, 103, 103, 103,
- 103, 104, 104, 105, 105, 106, 106, 106, 106, 106,
- 106, 107, 107, 107, 107, 107, 107, 107, 107, 108,
- 108, 108, 109, 109, 110, 110, 111, 111, 111, 112,
- 112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
- 113, 113, 113, 113, 113, 113, 113, 114, 114, 114,
- 114, 114, 114, 114, 114, 114, 114, 114, 114, 114,
- 114, 115, 115, 116, 117, 117, 118, 118, 118, 119,
- 120, 120, 120, 121, 122, 123, 124, 124, 125, 126,
- 127
+ 0, 74, 75, 75, 75, 75, 75, 76, 76, 76,
+ 76, 77, 77, 77, 78, 78, 78, 78, 78, 78,
+ 78, 79, 80, 80, 80, 80, 81, 81, 83, 82,
+ 85, 84, 86, 86, 87, 87, 87, 88, 88, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 90,
+ 90, 90, 90, 90, 91, 90, 90, 93, 92, 94,
+ 92, 92, 92, 95, 95, 96, 97, 97, 97, 98,
+ 98, 99, 99, 99, 99, 99, 100, 100, 101, 101,
+ 102, 103, 102, 104, 104, 105, 105, 106, 106, 107,
+ 107, 108, 108, 109, 109, 109, 109, 109, 110, 110,
+ 111, 111, 112, 112, 112, 112, 112, 112, 113, 113,
+ 113, 113, 113, 113, 113, 113, 114, 114, 114, 115,
+ 115, 116, 116, 117, 117, 117, 118, 118, 118, 118,
+ 118, 118, 118, 118, 118, 118, 118, 119, 119, 119,
+ 119, 119, 119, 119, 120, 120, 120, 120, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120, 121, 121,
+ 122, 123, 123, 124, 124, 125, 125, 126, 127, 128,
+ 128, 129, 130, 130, 131, 131, 132, 132, 132, 133,
+ 134, 135, 136, 136, 137, 138, 139
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 3, 0, 2, 2, 2, 2, 2, 0,
- 1, 3, 1, 1, 1, 1, 5, 1, 1, 1,
- 1, 1, 0, 7, 0, 3, 1, 1, 0, 2,
- 2, 1, 2, 2, 3, 1, 9, 6, 8, 8,
- 12, 11, 2, 2, 2, 2, 3, 0, 4, 2,
- 0, 4, 5, 2, 4, 1, 0, 1, 1, 0,
- 2, 2, 5, 4, 1, 2, 2, 1, 1, 1,
- 1, 1, 5, 0, 0, 3, 6, 9, 1, 2,
- 0, 1, 0, 2, 0, 1, 1, 3, 1, 2,
- 3, 0, 1, 0, 1, 1, 3, 1, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 5, 1, 1,
- 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,
- 3, 3, 3, 3, 3, 3, 3, 2, 2, 5,
- 4, 3, 3, 3, 3, 3, 3, 1, 2, 3,
- 4, 4, 1, 1, 1, 2, 2, 1, 1, 2,
- 2, 1, 2, 4, 0, 1, 1, 4, 1, 3,
- 1, 1, 0, 2, 2, 1, 0, 1, 1, 1,
- 2
+ 0, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 4, 1, 2, 1, 0, 1, 3, 1, 1, 1,
+ 1, 5, 1, 1, 1, 2, 1, 1, 0, 7,
+ 0, 3, 1, 1, 0, 2, 2, 1, 2, 2,
+ 3, 1, 9, 6, 8, 8, 12, 11, 1, 2,
+ 2, 2, 2, 3, 0, 4, 2, 0, 4, 0,
+ 4, 4, 1, 0, 1, 1, 0, 2, 2, 5,
+ 4, 1, 2, 2, 1, 1, 1, 1, 1, 3,
+ 0, 0, 3, 6, 9, 1, 2, 0, 1, 0,
+ 2, 0, 1, 1, 3, 1, 2, 3, 0, 1,
+ 0, 1, 1, 3, 1, 2, 3, 3, 3, 3,
+ 3, 3, 3, 3, 5, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 2, 1, 3, 3, 3,
+ 3, 3, 3, 3, 2, 2, 5, 4, 3, 3,
+ 3, 3, 3, 3, 1, 2, 3, 4, 4, 1,
+ 1, 1, 2, 2, 1, 1, 2, 2, 1, 2,
+ 4, 0, 1, 0, 2, 1, 2, 1, 3, 1,
+ 2, 2, 1, 2, 1, 3, 1, 1, 0, 2,
+ 2, 1, 0, 1, 1, 1, 2
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -797,372 +848,385 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 80, 78, 0, 81, 3, 1, 79, 0, 5, 0,
- 156, 147, 148, 12, 13, 14, 15, 22, 154, 0,
- 0, 0, 142, 27, 0, 0, 26, 0, 0, 0,
- 0, 4, 0, 0, 137, 24, 2, 10, 108, 116,
- 117, 119, 143, 151, 144, 158, 0, 0, 0, 82,
- 155, 145, 146, 0, 0, 150, 144, 149, 138, 0,
- 162, 144, 97, 0, 95, 152, 80, 168, 6, 7,
- 31, 28, 80, 8, 0, 112, 0, 0, 0, 0,
- 0, 0, 113, 115, 114, 0, 0, 118, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 110, 109, 127, 128, 0, 0, 0, 0, 95, 0,
- 18, 17, 20, 21, 0, 19, 0, 126, 0, 0,
- 0, 160, 161, 159, 98, 80, 165, 0, 0, 139,
- 163, 0, 32, 25, 104, 105, 102, 103, 0, 11,
- 106, 154, 124, 125, 121, 122, 123, 120, 135, 136,
- 132, 133, 134, 131, 111, 101, 153, 157, 0, 83,
- 140, 141, 99, 170, 0, 100, 96, 30, 0, 47,
- 0, 0, 0, 80, 0, 0, 0, 69, 70, 0,
- 91, 0, 80, 29, 0, 50, 35, 55, 28, 166,
- 80, 0, 130, 88, 86, 0, 0, 129, 0, 91,
- 53, 0, 0, 0, 0, 56, 42, 43, 44, 0,
- 92, 45, 164, 49, 0, 0, 80, 167, 33, 107,
- 80, 89, 0, 0, 0, 0, 0, 0, 0, 0,
- 156, 57, 0, 46, 0, 73, 71, 34, 16, 23,
- 90, 87, 80, 48, 0, 54, 80, 80, 0, 0,
- 80, 95, 74, 51, 0, 52, 0, 0, 0, 0,
- 0, 0, 0, 76, 59, 37, 0, 80, 0, 80,
- 0, 75, 80, 80, 0, 80, 0, 80, 56, 72,
- 0, 0, 61, 0, 0, 60, 38, 39, 56, 0,
- 77, 36, 64, 67, 0, 0, 68, 0, 169, 80,
- 0, 80, 66, 65, 80, 28, 80, 0, 28, 0,
- 0, 41, 0, 40
+ 2, 0, 1, 6, 0, 172, 154, 155, 17, 18,
+ 28, 19, 20, 161, 0, 0, 0, 149, 5, 85,
+ 33, 0, 0, 32, 0, 0, 0, 0, 3, 0,
+ 0, 144, 30, 4, 15, 115, 123, 124, 126, 150,
+ 158, 174, 151, 0, 0, 169, 0, 173, 0, 89,
+ 162, 152, 153, 0, 0, 0, 157, 151, 156, 145,
+ 0, 178, 151, 104, 0, 102, 0, 159, 87, 184,
+ 7, 8, 37, 34, 87, 9, 0, 86, 119, 0,
+ 0, 0, 0, 0, 0, 120, 122, 121, 0, 0,
+ 125, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 117, 116, 134, 135, 0, 0, 0,
+ 0, 102, 0, 171, 170, 23, 22, 26, 27, 0,
+ 0, 24, 0, 133, 0, 0, 0, 176, 177, 175,
+ 105, 87, 181, 0, 0, 146, 13, 0, 0, 88,
+ 179, 0, 38, 31, 111, 112, 109, 110, 0, 16,
+ 113, 161, 131, 132, 128, 129, 130, 127, 142, 143,
+ 139, 140, 141, 138, 118, 108, 160, 168, 25, 0,
+ 90, 147, 148, 106, 186, 0, 107, 103, 12, 10,
+ 36, 0, 54, 0, 0, 0, 87, 0, 0, 0,
+ 76, 77, 0, 98, 0, 87, 35, 48, 0, 57,
+ 41, 62, 34, 182, 87, 0, 137, 95, 93, 0,
+ 0, 136, 0, 98, 59, 0, 0, 0, 0, 63,
+ 49, 50, 51, 0, 99, 52, 180, 56, 0, 0,
+ 87, 183, 39, 114, 87, 96, 0, 0, 0, 163,
+ 0, 0, 0, 0, 172, 64, 0, 53, 0, 80,
+ 78, 40, 21, 29, 97, 94, 87, 55, 60, 0,
+ 165, 167, 61, 87, 87, 0, 0, 87, 0, 81,
+ 58, 0, 164, 166, 0, 0, 0, 0, 0, 79,
+ 0, 83, 66, 43, 0, 87, 0, 87, 82, 87,
+ 87, 0, 87, 0, 87, 63, 0, 0, 68, 0,
+ 0, 67, 44, 45, 63, 0, 84, 42, 71, 74,
+ 0, 0, 75, 0, 185, 87, 0, 87, 73, 72,
+ 87, 34, 87, 0, 34, 0, 0, 47, 0, 46
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 2, 7, 31, 32, 68, 114, 115, 33, 48,
- 34, 74, 35, 131, 69, 183, 199, 184, 214, 232,
- 273, 274, 285, 297, 185, 235, 253, 262, 186, 3,
- 4, 117, 195, 196, 209, 106, 107, 187, 105, 84,
- 85, 38, 39, 40, 41, 42, 43, 49, 44, 45,
- 123, 188, 189, 129, 216, 190, 299, 128
+ -1, 1, 28, 138, 29, 70, 120, 121, 30, 48,
+ 31, 76, 32, 141, 71, 196, 197, 213, 198, 228,
+ 239, 246, 290, 291, 301, 313, 199, 249, 270, 280,
+ 200, 139, 140, 123, 209, 210, 223, 109, 110, 201,
+ 108, 87, 88, 35, 36, 37, 38, 39, 40, 49,
+ 258, 259, 260, 45, 46, 47, 41, 42, 129, 202,
+ 203, 135, 230, 204, 315, 134
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -263
+#define YYPACT_NINF -267
static const yytype_int16 yypact[] =
{
- -27, -263, 29, -23, -263, -263, -263, 365, -263, -21,
- -18, -263, -263, -263, -263, -263, -263, -263, 9, 9,
- 9, -15, -10, -263, 1014, 1014, -263, 1014, 1039, 792,
- 48, -263, -31, -14, -263, -263, -263, 712, 958, 195,
- 274, -263, -263, -263, 176, -263, 764, 792, 126, 3,
- -263, -263, -263, 764, 764, 2, -11, 2, 2, 1014,
- -8, -263, -263, 44, 389, -263, -27, -263, -263, -263,
- -23, -263, -27, -263, 58, -263, 1014, 65, 1014, 1014,
- 1014, 1014, -263, -263, -263, 1014, 31, 195, 1014, 1014,
- 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014,
- -263, -263, -263, -263, 83, 1014, 42, 10, 907, 21,
- -263, -263, -263, -263, 50, -263, 1014, -263, 42, 42,
- 389, -263, -263, -263, 1014, -27, -263, 75, 848, -263,
- -263, 547, -263, -263, 117, -263, 194, 97, 824, 907,
- 52, 9, 181, 181, 2, 2, 2, 2, 181, 181,
- 2, 2, 2, 2, -263, 907, -263, -263, 17, 195,
- -263, -263, 907, -263, 111, -263, 907, -263, 54, -263,
- 4, 55, 59, -27, 61, -29, -29, -263, -263, -29,
- 1014, -29, -27, -263, -29, -263, -263, 907, -263, 56,
- -27, 1014, -263, -263, -263, 42, 47, -263, 1014, 1014,
- 63, 124, 1014, 1014, 680, 875, -263, -263, -263, -29,
- 907, -263, -263, -263, 616, 547, -27, -263, -263, 907,
- -27, -263, 23, 389, -29, 792, 69, 389, 389, 106,
- -25, -263, 56, -263, 792, 125, -263, -263, -263, -263,
- -263, -263, -27, -263, 43, -263, -27, -27, 72, 135,
- -27, 588, -263, -263, 680, -263, -14, 680, 1014, 42,
- 736, 792, 1014, 123, -263, -263, 389, -27, 306, -27,
- 44, 958, -27, -27, 32, -27, 680, -27, 931, -263,
- 680, 82, -263, 91, 102, -263, -263, -263, 931, 42,
- -263, -263, -263, -263, 139, 158, -263, 102, -263, -27,
- 42, -27, -263, -263, -27, -263, -27, 680, -263, 435,
- 680, -263, 491, -263
+ -267, 330, -267, -267, -36, -37, -267, -267, -267, -267,
+ -267, -267, -267, 20, 20, 20, -30, -20, -267, -267,
+ -267, 973, 973, -267, 973, 1018, 799, 6, -267, -15,
+ -21, -267, -267, 10, 1057, 947, 300, 325, -267, -267,
+ -267, -267, 299, 731, 799, -267, 53, -267, 112, 66,
+ -267, -267, -267, 731, 731, 122, 70, -3, 70, 70,
+ 973, 88, -267, -267, 50, 1051, 25, -267, 97, -267,
+ -267, -267, 10, -267, 97, -267, 143, -267, -267, 973,
+ 146, 973, 973, 973, 973, -267, -267, -267, 973, 113,
+ 300, 973, 973, 973, 973, 973, 973, 973, 973, 973,
+ 973, 973, 973, -267, -267, -267, -267, 139, 973, 87,
+ 118, 1086, 7, -267, -267, -267, -267, -267, -267, 121,
+ 96, -267, 973, -267, 87, 87, 1051, -267, -267, -267,
+ 973, 97, -267, 137, 825, -267, -267, 36, -16, 10,
+ -267, 547, -267, -267, 19, -267, 260, 251, 1080, 1086,
+ 105, 20, 115, 115, 70, 70, 70, 70, 115, 115,
+ 70, 70, 70, 70, -267, 1086, -267, -267, -267, 63,
+ 300, -267, -267, 1086, -267, 146, -267, 1086, -267, -267,
+ -267, 116, -267, 45, 120, 124, 97, 129, -16, -16,
+ -267, -267, -16, 973, -16, 97, -267, -267, -16, -267,
+ -267, 1086, -267, 123, 97, 973, -267, -267, -267, 87,
+ 117, -267, 973, 973, -267, 193, 973, 973, 660, 870,
+ -267, -267, -267, -16, 1086, -267, -267, -267, 593, 547,
+ 97, -267, -267, 1086, 97, -267, 72, 1051, -16, -37,
+ 133, 1051, 1051, 175, -22, -267, 123, -267, 799, 192,
+ -267, -267, -267, -267, -267, -267, 97, -267, -267, 90,
+ -267, -267, -267, 97, 97, 141, 146, 97, 50, -267,
+ -267, 660, -267, -267, -21, 660, 973, 87, 705, 137,
+ 973, 183, -267, -267, 1051, 97, 262, 97, 947, 97,
+ 97, 38, 97, 660, 97, 902, 660, 136, -267, 198,
+ 156, -267, -267, -267, 902, 87, -267, -267, -267, -267,
+ 203, 210, -267, 156, -267, 97, 87, 97, -267, -267,
+ 97, -267, 97, 660, -267, 401, 660, -267, 474, -267
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -263, -263, -263, -263, -263, 145, -263, -263, -263, -263,
- -111, -263, -263, -186, 114, -167, -263, -193, -263, -262,
- -263, -263, -263, -263, -263, -263, -263, -263, -263, -2,
- -7, -263, -263, -263, -13, -47, -19, -4, -263, -263,
- -263, -81, 187, -263, 157, -263, 160, 51, 64, -263,
- -263, -28, -214, 78, -263, 132, -106, -187
+ -267, -267, -267, -267, -267, 188, -267, -267, -267, -267,
+ -77, -267, -267, -197, 56, -170, -267, -267, -192, -267,
+ -267, -266, -267, -267, -267, -267, -267, -267, -267, -267,
+ -267, 43, 34, -267, -267, -267, 11, -39, -23, -1,
+ -267, -267, -267, -52, 44, -267, 201, -267, -10, 82,
+ -267, -267, -19, -40, -267, -267, -73, -2, -267, -28,
+ -213, -54, -267, -25, -79, 26
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -95
+#define YYTABLE_NINF -102
static const yytype_int16 yytable[] =
{
- 36, 237, 215, 37, 71, 71, 118, 119, 200, 222,
- 63, 124, 231, 10, 249, 1, 289, 1, 193, 1,
- -94, 194, 124, 6, 240, 64, 300, 241, 109, 5,
- 70, 102, 103, 282, 121, 122, 66, 229, 67, 47,
- 67, 46, 108, 108, 124, 124, 47, 53, 221, 108,
- 108, 9, 54, 66, 116, 120, -94, 283, 284, 130,
- 125, -95, 93, 133, 261, 132, 201, 291, 141, 135,
- 28, 125, 134, -94, 136, 137, 138, 139, -58, -94,
- -84, 140, 50, 51, 52, 231, 157, 263, 56, 56,
- 265, 56, 61, 125, 125, 231, 154, 125, 292, 293,
- -58, 155, 56, -95, -95, 126, 75, 126, 255, 287,
- -85, 76, 158, 290, 164, 197, 198, 202, 163, 309,
- 162, 203, 312, 205, 166, 67, 75, 225, 226, 110,
- 111, -95, 245, 248, 258, 252, 77, 78, 23, 259,
- 311, 127, 272, 313, 294, 295, 302, 26, 82, 83,
- 182, 298, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 72, 303, 204, 236, 82, 83,
- 112, 113, 296, 70, 70, 212, 210, 70, 73, 70,
- 56, 271, 70, 218, 156, 60, 224, 219, 100, 101,
- 65, 304, 192, 0, 223, 210, 160, 161, 227, 228,
- 0, 0, 0, 75, 0, 50, 244, 70, 76, 238,
- 108, 55, 57, 239, 58, 63, 0, 0, 102, 103,
- 0, 108, 70, 104, 0, 87, 0, 0, 264, 0,
- 251, 0, 0, 77, 0, 254, 90, 91, 92, 256,
- 257, 93, 270, 260, 0, 82, 83, 0, 88, 89,
- 90, 91, 92, 0, 266, 93, 268, 108, 0, 0,
- 276, 0, 278, 0, 0, 280, 281, 0, 286, 0,
- 288, 0, 0, 220, 0, 142, 143, 144, 145, 146,
- 147, 148, 149, 150, 151, 152, 153, 0, 0, 206,
- 207, 0, 305, 208, 307, 211, 0, 308, 213, 310,
- 0, 242, 0, 159, 0, 246, 247, 72, 72, 0,
- 0, 72, 0, 72, 0, 75, 72, 0, 0, 0,
- 76, 217, 0, 233, 0, 0, 56, 94, 95, 96,
- 97, 98, 0, 0, 99, 56, 0, 267, 243, 0,
- 0, 72, 0, 0, 275, 77, 78, 79, 279, 0,
- 0, 0, 0, 0, 80, 0, 72, 82, 83, 0,
- 0, 0, 0, 0, 250, -80, 8, 301, 9, 10,
- 0, 0, 11, 12, 0, 67, 0, 0, 306, 0,
- 0, 13, 14, 0, 0, 0, 0, 15, 16, 0,
- 0, 0, 269, 0, 0, 0, 0, 0, 75, 0,
- 277, 17, 18, 76, 0, 0, 0, 19, 20, 21,
- 22, 1, 23, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 0, 27, 0, 0, 28, 29, 77, 78,
- 79, 30, -9, 0, -9, 0, 167, 80, 9, 10,
- 82, 83, 11, 12, 0, 0, 0, 0, 0, 0,
- 0, 0, 126, 168, 0, 169, 170, 0, 87, 171,
- -63, -63, 172, 173, 174, 175, 176, 177, 178, 179,
- 180, 0, 18, 181, 0, 0, 0, 19, 20, 21,
- 22, -63, 23, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 167, 27, 9, 10, 28, 29, 11, 12,
- 0, 30, 66, -63, 67, 0, 0, 0, 0, 168,
- 0, 169, 170, 0, 0, 171, -62, -62, 172, 173,
- 174, 175, 176, 177, 178, 179, 180, 0, 18, 181,
- 0, 0, 0, 19, 20, 21, 22, -62, 23, 0,
- 0, 0, 0, 0, 24, 25, 0, 26, 167, 27,
- 9, 10, 28, 29, 11, 12, 0, 30, 66, -62,
- 67, 0, 0, 0, 0, 168, 0, 169, 170, 0,
- 0, 171, 0, 0, 172, 173, 174, 175, 176, 177,
- 178, 179, 180, 0, 18, 181, 0, 0, 0, 19,
- 20, 21, 22, 0, 23, 0, 0, 75, 0, 0,
- 24, 25, 76, 26, 0, 27, 0, 0, 28, 29,
- 0, 0, 0, 30, 66, 182, 67, 62, 0, 9,
- 10, 0, 0, 11, 12, 0, -93, 77, 78, 79,
- 0, 0, 0, 0, 0, 0, 80, 0, 125, 82,
- 83, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 126, 0, 18, 0, 0, 0, 0, 19, 20,
- 21, 22, -93, 23, 0, 0, 0, 0, 0, 24,
- 25, 0, 26, 0, 27, 0, 0, 28, 234, -93,
- 0, 0, 30, 9, 10, -93, 0, 11, 12, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 168, 0,
- 169, 170, 0, 0, 171, 0, 0, 172, 173, 174,
- 175, 176, 177, 178, 179, 180, 0, 18, 181, 0,
- 0, 75, 19, 20, 21, 22, 76, 23, 0, 0,
- 0, 0, 0, 24, 25, 0, 26, 0, 27, 9,
- 10, 28, 29, 11, 12, 0, 30, 66, 0, 67,
- 0, 77, 78, 79, 0, 0, 0, 0, 0, 0,
- 80, 0, 81, 82, 83, 62, 0, 9, 10, 0,
- 0, 11, 12, 18, 0, 0, 0, 0, 19, 20,
- 21, 22, 0, 23, 0, 0, 0, 0, 0, 24,
- 25, 0, 26, 62, 27, 9, 10, 28, 29, 11,
- 12, 18, 30, 0, 0, 67, 19, 20, 21, 22,
- 0, 23, 0, 0, 0, 0, 0, 24, 25, 0,
- 26, 0, 27, 0, 0, 28, 29, -93, 0, 18,
- 30, 0, 0, 75, 19, 20, 21, 22, 76, 23,
- 0, 0, 0, 0, 0, 24, 25, 0, 26, 165,
- 27, 9, 10, 28, 29, 11, 12, 0, 30, 0,
- 0, 0, 0, 77, 78, 79, 0, 0, 0, 0,
- 0, 0, 80, 191, 0, 82, 83, 0, 9, 230,
- 0, 0, 11, 12, 0, 18, 0, 0, 0, 0,
- 19, 20, 21, 22, 0, 23, 170, 0, 0, 0,
- 0, 24, 25, 0, 26, 0, 27, 177, 178, 28,
- 29, 0, 18, 0, 30, 0, 75, 19, 20, 21,
- 22, 76, 23, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 0, 27, 9, 10, 28, 29, 11, 12,
- 0, 30, 0, 0, 0, 0, 77, 78, 79, 0,
- 0, 0, 170, 0, 0, 80, 0, 0, 82, 83,
- 0, 9, 10, 177, 178, 11, 12, 0, 18, 86,
- 0, 0, 0, 19, 20, 21, 22, 0, 23, 0,
- 0, 0, 0, 0, 24, 25, 0, 26, 0, 27,
- 0, 0, 28, 29, 0, 18, 0, 30, 0, 0,
- 19, 20, 21, 22, 0, 23, 0, 0, 0, 0,
- 0, 24, 25, 0, 26, 0, 27, 9, 10, 28,
- 29, 11, 12, 0, 30, 0, 0, 0, 0, 0,
+ 34, 73, 73, 64, 74, 229, 114, 145, 130, 4,
+ 133, 50, 51, 52, 124, 125, 251, 67, 266, 57,
+ 57, 112, 57, 62, 5, 65, 136, 245, 78, 305,
+ 43, 137, 44, 57, 19, 19, 53, 178, 316, 298,
+ 105, 106, 111, 111, 33, 67, 54, 44, 243, 214,
+ 68, 130, 111, 111, 66, 166, 68, 69, 69, 126,
+ 77, 131, 299, 300, 207, 56, 58, 208, 59, 113,
+ 171, 172, 72, 254, 85, 86, 255, 167, 144, 90,
+ 146, 147, 148, 149, 307, 25, -11, 150, -65, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 281, 211, 245, 131, 283, 272, 165, 142, -11,
+ -65, 215, 245, 74, -102, 115, 116, 132, 235, 130,
+ 57, 122, 44, 303, 325, 4, 306, 328, -101, 173,
+ -91, 127, 128, 177, 96, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 19, 143, 50,
+ 5, 151, 164, 327, 132, 234, 329, 117, 118, 44,
+ -102, -102, 169, 74, 74, 174, 170, 74, -101, 74,
+ 168, 131, 131, 74, 93, 94, 95, 175, 231, 96,
+ 119, 72, 212, 256, -92, -101, 216, 263, 264, 250,
+ 217, -101, 224, 277, 179, 219, 69, 240, 74, 261,
+ 262, 265, 269, 289, 233, 308, 309, 276, 195, 314,
+ 318, 237, 224, 74, 279, 241, 242, 319, 75, 261,
+ 218, 267, 312, 285, 238, 268, 61, 111, 288, 226,
+ 292, 72, 72, 206, 320, 72, 236, 72, 232, 0,
+ 273, 72, 0, 0, 220, 221, 282, 65, 222, 20,
+ 225, 317, 0, 287, 227, 310, 311, 0, 23, 0,
+ 78, 294, 322, 0, 252, 79, 72, 0, 253, 78,
+ 0, 78, 0, 0, 79, 284, 79, 286, 57, 247,
+ 0, 72, 0, 0, 0, 0, 57, 0, 0, 0,
+ 271, 80, 81, 0, 257, 0, 0, 274, 275, 0,
+ 80, 278, 80, 81, 82, 0, 85, 86, 0, 0,
+ 0, 103, 104, 0, 83, 85, 86, 85, 86, 293,
+ 0, 295, 0, 296, 297, 0, 302, 0, 304, 0,
+ 2, 3, 90, 4, 5, 69, 0, 6, 7, 0,
+ 0, 0, 105, 106, 0, 0, 0, 8, 9, 321,
+ 107, 323, 0, 0, 324, 0, 326, 91, 92, 93,
+ 94, 95, 0, 0, 96, 10, 11, 12, 13, 0,
+ 0, 0, 0, 14, 15, 16, 17, 18, 0, 0,
+ 19, 20, 97, 98, 99, 100, 101, 21, 22, 102,
+ 23, 0, 24, 0, 0, 25, 26, 0, 27, 0,
+ 0, -14, 180, -14, 4, 5, 0, 0, 6, 7,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 181, 0, 182, 183, 184, -70, -70, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 0, 0, 0, 13,
+ 194, 0, 0, 0, 14, 15, 16, 17, 0, 0,
+ 0, -70, 20, 0, 0, 0, 0, 0, 21, 22,
+ 0, 23, 0, 24, 0, 0, 25, 26, 0, 55,
+ 0, 0, 68, -70, 69, 180, 0, 4, 5, 0,
+ 0, 6, 7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 181, 0, 182, 183, 184, -69, -69,
+ 185, 186, 187, 188, 189, 190, 191, 192, 193, 0,
+ 0, 0, 13, 194, 0, 0, 0, 14, 15, 16,
+ 17, 0, 0, 0, -69, 20, 0, 0, 0, 0,
+ 0, 21, 22, 0, 23, 0, 24, 0, 0, 25,
+ 26, 0, 55, 0, 0, 68, -69, 69, 180, 0,
+ 4, 5, 0, 0, 6, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 181, 0, 182, 183,
+ 184, 0, 0, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 0, 0, 0, 13, 194, 0, 0, 0,
+ 14, 15, 16, 17, 63, 0, 4, 5, 20, 0,
+ 6, 7, 0, -100, 21, 22, 0, 23, 0, 24,
+ 0, 0, 25, 26, 0, 55, 0, 0, 68, 195,
+ 69, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 13, 0, 0, 0, 0, 14, 15, 16, 17,
+ 0, 0, 0, -100, 20, 0, 0, 0, 0, 0,
+ 21, 22, 0, 23, 0, 24, 0, 0, 25, 248,
+ -100, 55, 0, 4, 5, 0, -100, 6, 7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 181,
+ 0, 182, 183, 184, 0, 0, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 0, 0, 0, 13, 194,
+ 0, 0, 0, 14, 15, 16, 17, 0, 4, 5,
+ 0, 20, 6, 7, 0, 0, 0, 21, 22, 0,
+ 23, 0, 24, 0, 0, 25, 26, 0, 55, 0,
+ 0, 68, 63, 69, 4, 5, 0, 0, 6, 7,
+ 0, 0, 0, 13, 0, 0, 0, 0, 14, 15,
+ 16, 17, 0, 0, 0, 0, 20, 0, 0, 0,
+ 0, 0, 21, 22, 0, 23, 0, 24, 0, 13,
+ 25, 26, 0, 55, 14, 15, 16, 17, 69, 0,
+ 0, 0, 20, 0, 0, 0, 0, 0, 21, 22,
+ 0, 23, 0, 24, 0, 0, 25, 26, -100, 55,
+ 63, 0, 4, 5, 0, 0, 6, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 176, 0, 4, 5,
+ 0, 0, 6, 7, 0, 0, 0, 13, 0, 0,
+ 0, 0, 14, 15, 16, 17, 0, 0, 0, 0,
+ 20, 0, 0, 0, 0, 0, 21, 22, 0, 23,
+ 0, 24, 0, 13, 25, 26, 0, 55, 14, 15,
+ 16, 17, 0, 4, 244, 0, 20, 6, 7, 0,
+ 0, 0, 21, 22, 0, 23, 0, 24, 0, 0,
+ 25, 26, 183, 55, 0, 0, 0, 0, 0, 0,
+ 0, 190, 191, 0, 0, 4, 5, 0, 13, 6,
+ 7, 0, 0, 14, 15, 16, 17, 0, 0, 0,
+ 0, 20, 0, 0, 183, 0, 0, 21, 22, 0,
+ 23, 0, 24, 190, 191, 25, 26, 0, 55, 0,
+ 13, 0, 0, 0, 0, 14, 15, 16, 17, 0,
+ 4, 5, 0, 20, 6, 7, 0, 0, 89, 21,
+ 22, 0, 23, 0, 24, 0, 0, 25, 26, 0,
+ 55, 0, 0, 0, 0, 0, 4, 5, 0, 0,
+ 6, 7, 0, 0, 0, 13, 0, 0, 0, 0,
+ 14, 15, 16, 17, 0, 0, 0, 0, 20, 0,
+ 0, 0, 0, 0, 21, 22, 0, 23, 0, 24,
+ 0, 13, 25, 26, 0, 55, 14, 15, 16, 17,
+ 0, 4, 5, 0, 20, 6, 7, 0, 0, 0,
+ 21, 22, 0, 23, 0, 24, 0, 0, 25, 26,
+ 0, 55, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 10, 0, 0, 11, 12, 0, 0,
- 0, 18, 0, 0, 0, 0, 19, 20, 21, 22,
- 0, 23, 0, 0, 0, 0, 0, 24, 25, 0,
- 26, 0, 27, 0, 0, 28, 29, 0, 0, 0,
- 30, 19, 20, 21, 22, 0, 23, 0, 0, 0,
- 0, 0, 24, 25, 0, 26, 0, 27, 0, 0,
- 28, 59, 0, 0, 0, 30
+ 78, 14, 15, 16, 17, 79, 78, 0, 0, 20,
+ 0, 79, 0, 0, 0, 21, 22, 0, 23, 0,
+ 24, 0, 0, 25, 60, 0, 55, 0, 0, 78,
+ 0, 80, 81, 82, 79, 78, 0, 80, 81, 82,
+ 79, 0, 0, 83, 0, 0, 85, 86, 0, 83,
+ 0, 84, 85, 86, 0, 0, 0, 0, 132, 0,
+ 80, 81, 82, 0, 0, 0, 80, 81, 82, 0,
+ 0, 0, 83, 205, 0, 85, 86, 0, 83, 0,
+ 0, 85, 86
};
static const yytype_int16 yycheck[] =
{
- 7, 215, 188, 7, 32, 33, 53, 54, 4, 196,
- 29, 1, 205, 4, 39, 46, 278, 46, 1, 46,
- 10, 4, 1, 46, 1, 29, 288, 4, 47, 0,
- 32, 42, 43, 1, 42, 43, 67, 204, 69, 64,
- 69, 62, 46, 47, 1, 1, 64, 62, 1, 53,
- 54, 3, 62, 67, 51, 59, 46, 25, 26, 66,
- 50, 9, 60, 5, 251, 72, 62, 281, 37, 4,
- 61, 50, 76, 63, 78, 79, 80, 81, 46, 69,
- 63, 85, 18, 19, 20, 278, 65, 254, 24, 25,
- 257, 27, 28, 50, 50, 288, 13, 50, 7, 8,
- 68, 105, 38, 51, 52, 63, 9, 63, 65, 276,
- 63, 14, 62, 280, 39, 4, 62, 62, 125, 305,
- 124, 62, 308, 62, 128, 69, 9, 64, 4, 3,
- 4, 14, 63, 27, 62, 10, 39, 40, 47, 4,
- 307, 63, 19, 310, 53, 54, 7, 56, 51, 52,
- 68, 49, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 32, 7, 173, 214, 51, 52,
- 44, 45, 283, 175, 176, 182, 180, 179, 33, 181,
- 116, 262, 184, 190, 106, 28, 199, 191, 12, 13,
- 30, 297, 141, -1, 198, 199, 118, 119, 202, 203,
- -1, -1, -1, 9, -1, 141, 225, 209, 14, 216,
- 214, 24, 25, 220, 27, 234, -1, -1, 42, 43,
- -1, 225, 224, 47, -1, 38, -1, -1, 256, -1,
- 234, -1, -1, 39, -1, 242, 55, 56, 57, 246,
- 247, 60, 261, 250, -1, 51, 52, -1, 53, 54,
- 55, 56, 57, -1, 258, 60, 260, 261, -1, -1,
- 267, -1, 269, -1, -1, 272, 273, -1, 275, -1,
- 277, -1, -1, 195, -1, 88, 89, 90, 91, 92,
- 93, 94, 95, 96, 97, 98, 99, -1, -1, 175,
- 176, -1, 299, 179, 301, 181, -1, 304, 184, 306,
- -1, 223, -1, 116, -1, 227, 228, 175, 176, -1,
- -1, 179, -1, 181, -1, 9, 184, -1, -1, -1,
- 14, 189, -1, 209, -1, -1, 262, 53, 54, 55,
- 56, 57, -1, -1, 60, 271, -1, 259, 224, -1,
- -1, 209, -1, -1, 266, 39, 40, 41, 270, -1,
- -1, -1, -1, -1, 48, -1, 224, 51, 52, -1,
- -1, -1, -1, -1, 232, 0, 1, 289, 3, 4,
- -1, -1, 7, 8, -1, 69, -1, -1, 300, -1,
- -1, 16, 17, -1, -1, -1, -1, 22, 23, -1,
- -1, -1, 260, -1, -1, -1, -1, -1, 9, -1,
- 268, 36, 37, 14, -1, -1, -1, 42, 43, 44,
- 45, 46, 47, -1, -1, -1, -1, -1, 53, 54,
- -1, 56, -1, 58, -1, -1, 61, 62, 39, 40,
- 41, 66, 67, -1, 69, -1, 1, 48, 3, 4,
- 51, 52, 7, 8, -1, -1, -1, -1, -1, -1,
- -1, -1, 63, 18, -1, 20, 21, -1, 271, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, -1, 37, 38, -1, -1, -1, 42, 43, 44,
- 45, 46, 47, -1, -1, -1, -1, -1, 53, 54,
- -1, 56, 1, 58, 3, 4, 61, 62, 7, 8,
- -1, 66, 67, 68, 69, -1, -1, -1, -1, 18,
- -1, 20, 21, -1, -1, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, -1, 37, 38,
- -1, -1, -1, 42, 43, 44, 45, 46, 47, -1,
- -1, -1, -1, -1, 53, 54, -1, 56, 1, 58,
- 3, 4, 61, 62, 7, 8, -1, 66, 67, 68,
- 69, -1, -1, -1, -1, 18, -1, 20, 21, -1,
- -1, 24, -1, -1, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, -1, 37, 38, -1, -1, -1, 42,
- 43, 44, 45, -1, 47, -1, -1, 9, -1, -1,
- 53, 54, 14, 56, -1, 58, -1, -1, 61, 62,
- -1, -1, -1, 66, 67, 68, 69, 1, -1, 3,
- 4, -1, -1, 7, 8, -1, 10, 39, 40, 41,
- -1, -1, -1, -1, -1, -1, 48, -1, 50, 51,
- 52, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 63, -1, 37, -1, -1, -1, -1, 42, 43,
- 44, 45, 46, 47, -1, -1, -1, -1, -1, 53,
- 54, -1, 56, -1, 58, -1, -1, 61, 62, 63,
- -1, -1, 66, 3, 4, 69, -1, 7, 8, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 18, -1,
- 20, 21, -1, -1, 24, -1, -1, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, -1, 37, 38, -1,
- -1, 9, 42, 43, 44, 45, 14, 47, -1, -1,
- -1, -1, -1, 53, 54, -1, 56, -1, 58, 3,
- 4, 61, 62, 7, 8, -1, 66, 67, -1, 69,
- -1, 39, 40, 41, -1, -1, -1, -1, -1, -1,
- 48, -1, 50, 51, 52, 1, -1, 3, 4, -1,
- -1, 7, 8, 37, -1, -1, -1, -1, 42, 43,
- 44, 45, -1, 47, -1, -1, -1, -1, -1, 53,
- 54, -1, 56, 1, 58, 3, 4, 61, 62, 7,
- 8, 37, 66, -1, -1, 69, 42, 43, 44, 45,
- -1, 47, -1, -1, -1, -1, -1, 53, 54, -1,
- 56, -1, 58, -1, -1, 61, 62, 63, -1, 37,
- 66, -1, -1, 9, 42, 43, 44, 45, 14, 47,
- -1, -1, -1, -1, -1, 53, 54, -1, 56, 1,
- 58, 3, 4, 61, 62, 7, 8, -1, 66, -1,
- -1, -1, -1, 39, 40, 41, -1, -1, -1, -1,
- -1, -1, 48, 49, -1, 51, 52, -1, 3, 4,
- -1, -1, 7, 8, -1, 37, -1, -1, -1, -1,
- 42, 43, 44, 45, -1, 47, 21, -1, -1, -1,
- -1, 53, 54, -1, 56, -1, 58, 32, 33, 61,
- 62, -1, 37, -1, 66, -1, 9, 42, 43, 44,
- 45, 14, 47, -1, -1, -1, -1, -1, 53, 54,
- -1, 56, -1, 58, 3, 4, 61, 62, 7, 8,
- -1, 66, -1, -1, -1, -1, 39, 40, 41, -1,
- -1, -1, 21, -1, -1, 48, -1, -1, 51, 52,
- -1, 3, 4, 32, 33, 7, 8, -1, 37, 11,
- -1, -1, -1, 42, 43, 44, 45, -1, 47, -1,
- -1, -1, -1, -1, 53, 54, -1, 56, -1, 58,
- -1, -1, 61, 62, -1, 37, -1, 66, -1, -1,
- 42, 43, 44, 45, -1, 47, -1, -1, -1, -1,
- -1, 53, 54, -1, 56, -1, 58, 3, 4, 61,
- 62, 7, 8, -1, 66, -1, -1, -1, -1, -1,
+ 1, 29, 30, 26, 29, 202, 46, 80, 1, 3,
+ 64, 13, 14, 15, 53, 54, 229, 27, 40, 21,
+ 22, 44, 24, 25, 4, 26, 1, 219, 9, 295,
+ 66, 6, 69, 35, 50, 50, 66, 1, 304, 1,
+ 43, 44, 43, 44, 1, 55, 66, 69, 218, 4,
+ 71, 1, 53, 54, 48, 109, 71, 73, 73, 60,
+ 50, 54, 24, 25, 1, 21, 22, 4, 24, 16,
+ 124, 125, 29, 1, 55, 56, 4, 70, 79, 35,
+ 81, 82, 83, 84, 297, 65, 50, 88, 50, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 271, 175, 295, 54, 275, 16, 108, 74, 73,
+ 72, 66, 304, 138, 9, 3, 4, 67, 1, 1,
+ 122, 55, 69, 293, 321, 3, 296, 324, 10, 130,
+ 67, 43, 44, 134, 64, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 50, 5, 151,
+ 4, 38, 13, 323, 67, 209, 326, 45, 46, 69,
+ 55, 56, 66, 188, 189, 131, 122, 192, 50, 194,
+ 49, 54, 54, 198, 59, 60, 61, 40, 203, 64,
+ 68, 138, 66, 237, 67, 67, 66, 241, 242, 228,
+ 66, 73, 193, 266, 138, 66, 73, 4, 223, 239,
+ 67, 26, 10, 20, 205, 7, 8, 66, 72, 53,
+ 7, 212, 213, 238, 268, 216, 217, 7, 30, 259,
+ 186, 246, 299, 277, 213, 248, 25, 228, 280, 195,
+ 284, 188, 189, 151, 313, 192, 210, 194, 204, -1,
+ 259, 198, -1, -1, 188, 189, 274, 248, 192, 51,
+ 194, 305, -1, 278, 198, 57, 58, -1, 60, -1,
+ 9, 286, 316, -1, 230, 14, 223, -1, 234, 9,
+ -1, 9, -1, -1, 14, 276, 14, 278, 280, 223,
+ -1, 238, -1, -1, -1, -1, 288, -1, -1, -1,
+ 256, 40, 41, -1, 238, -1, -1, 263, 264, -1,
+ 40, 267, 40, 41, 42, -1, 55, 56, -1, -1,
+ -1, 12, 13, -1, 52, 55, 56, 55, 56, 285,
+ -1, 287, -1, 289, 290, -1, 292, -1, 294, -1,
+ 0, 1, 288, 3, 4, 73, -1, 7, 8, -1,
+ -1, -1, 43, 44, -1, -1, -1, 17, 18, 315,
+ 51, 317, -1, -1, 320, -1, 322, 57, 58, 59,
+ 60, 61, -1, -1, 64, 35, 36, 37, 38, -1,
+ -1, -1, -1, 43, 44, 45, 46, 47, -1, -1,
+ 50, 51, 57, 58, 59, 60, 61, 57, 58, 64,
+ 60, -1, 62, -1, -1, 65, 66, -1, 68, -1,
+ -1, 71, 1, 73, 3, 4, -1, -1, 7, 8,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 19, -1, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, -1, -1, -1, 38,
+ 39, -1, -1, -1, 43, 44, 45, 46, -1, -1,
+ -1, 50, 51, -1, -1, -1, -1, -1, 57, 58,
+ -1, 60, -1, 62, -1, -1, 65, 66, -1, 68,
+ -1, -1, 71, 72, 73, 1, -1, 3, 4, -1,
+ -1, 7, 8, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 19, -1, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, -1,
+ -1, -1, 38, 39, -1, -1, -1, 43, 44, 45,
+ 46, -1, -1, -1, 50, 51, -1, -1, -1, -1,
+ -1, 57, 58, -1, 60, -1, 62, -1, -1, 65,
+ 66, -1, 68, -1, -1, 71, 72, 73, 1, -1,
+ 3, 4, -1, -1, 7, 8, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 19, -1, 21, 22,
+ 23, -1, -1, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, -1, -1, -1, 38, 39, -1, -1, -1,
+ 43, 44, 45, 46, 1, -1, 3, 4, 51, -1,
+ 7, 8, -1, 10, 57, 58, -1, 60, -1, 62,
+ -1, -1, 65, 66, -1, 68, -1, -1, 71, 72,
+ 73, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 38, -1, -1, -1, -1, 43, 44, 45, 46,
+ -1, -1, -1, 50, 51, -1, -1, -1, -1, -1,
+ 57, 58, -1, 60, -1, 62, -1, -1, 65, 66,
+ 67, 68, -1, 3, 4, -1, 73, 7, 8, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 19,
+ -1, 21, 22, 23, -1, -1, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, -1, -1, -1, 38, 39,
+ -1, -1, -1, 43, 44, 45, 46, -1, 3, 4,
+ -1, 51, 7, 8, -1, -1, -1, 57, 58, -1,
+ 60, -1, 62, -1, -1, 65, 66, -1, 68, -1,
+ -1, 71, 1, 73, 3, 4, -1, -1, 7, 8,
+ -1, -1, -1, 38, -1, -1, -1, -1, 43, 44,
+ 45, 46, -1, -1, -1, -1, 51, -1, -1, -1,
+ -1, -1, 57, 58, -1, 60, -1, 62, -1, 38,
+ 65, 66, -1, 68, 43, 44, 45, 46, 73, -1,
+ -1, -1, 51, -1, -1, -1, -1, -1, 57, 58,
+ -1, 60, -1, 62, -1, -1, 65, 66, 67, 68,
+ 1, -1, 3, 4, -1, -1, 7, 8, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1, -1, 3, 4,
+ -1, -1, 7, 8, -1, -1, -1, 38, -1, -1,
+ -1, -1, 43, 44, 45, 46, -1, -1, -1, -1,
+ 51, -1, -1, -1, -1, -1, 57, 58, -1, 60,
+ -1, 62, -1, 38, 65, 66, -1, 68, 43, 44,
+ 45, 46, -1, 3, 4, -1, 51, 7, 8, -1,
+ -1, -1, 57, 58, -1, 60, -1, 62, -1, -1,
+ 65, 66, 22, 68, -1, -1, -1, -1, -1, -1,
+ -1, 31, 32, -1, -1, 3, 4, -1, 38, 7,
+ 8, -1, -1, 43, 44, 45, 46, -1, -1, -1,
+ -1, 51, -1, -1, 22, -1, -1, 57, 58, -1,
+ 60, -1, 62, 31, 32, 65, 66, -1, 68, -1,
+ 38, -1, -1, -1, -1, 43, 44, 45, 46, -1,
+ 3, 4, -1, 51, 7, 8, -1, -1, 11, 57,
+ 58, -1, 60, -1, 62, -1, -1, 65, 66, -1,
+ 68, -1, -1, -1, -1, -1, 3, 4, -1, -1,
+ 7, 8, -1, -1, -1, 38, -1, -1, -1, -1,
+ 43, 44, 45, 46, -1, -1, -1, -1, 51, -1,
+ -1, -1, -1, -1, 57, 58, -1, 60, -1, 62,
+ -1, 38, 65, 66, -1, 68, 43, 44, 45, 46,
+ -1, 3, 4, -1, 51, 7, 8, -1, -1, -1,
+ 57, 58, -1, 60, -1, 62, -1, -1, 65, 66,
+ -1, 68, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3, 4, -1, -1, 7, 8, -1, -1,
- -1, 37, -1, -1, -1, -1, 42, 43, 44, 45,
- -1, 47, -1, -1, -1, -1, -1, 53, 54, -1,
- 56, -1, 58, -1, -1, 61, 62, -1, -1, -1,
- 66, 42, 43, 44, 45, -1, 47, -1, -1, -1,
- -1, -1, 53, 54, -1, 56, -1, 58, -1, -1,
- 61, 62, -1, -1, -1, 66
+ 9, 43, 44, 45, 46, 14, 9, -1, -1, 51,
+ -1, 14, -1, -1, -1, 57, 58, -1, 60, -1,
+ 62, -1, -1, 65, 66, -1, 68, -1, -1, 9,
+ -1, 40, 41, 42, 14, 9, -1, 40, 41, 42,
+ 14, -1, -1, 52, -1, -1, 55, 56, -1, 52,
+ -1, 54, 55, 56, -1, -1, -1, -1, 67, -1,
+ 40, 41, 42, -1, -1, -1, 40, 41, 42, -1,
+ -1, -1, 52, 53, -1, 55, 56, -1, 52, -1,
+ -1, 55, 56
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 46, 71, 99, 100, 0, 46, 72, 1, 3,
- 4, 7, 8, 16, 17, 22, 23, 36, 37, 42,
- 43, 44, 45, 47, 53, 54, 56, 58, 61, 62,
- 66, 73, 74, 78, 80, 82, 100, 107, 111, 112,
- 113, 114, 115, 116, 118, 119, 62, 64, 79, 117,
- 118, 118, 118, 62, 62, 112, 118, 112, 112, 62,
- 114, 118, 1, 106, 107, 116, 67, 69, 75, 84,
- 99, 121, 125, 75, 81, 9, 14, 39, 40, 41,
- 48, 50, 51, 52, 109, 110, 11, 112, 53, 54,
- 55, 56, 57, 60, 53, 54, 55, 56, 57, 60,
- 12, 13, 42, 43, 47, 108, 105, 106, 107, 106,
- 3, 4, 44, 45, 76, 77, 51, 101, 105, 105,
- 107, 42, 43, 120, 1, 50, 63, 123, 127, 123,
- 100, 83, 100, 5, 107, 4, 107, 107, 107, 107,
- 107, 37, 112, 112, 112, 112, 112, 112, 112, 112,
- 112, 112, 112, 112, 13, 107, 123, 65, 62, 112,
- 123, 123, 107, 100, 39, 1, 107, 1, 18, 20,
- 21, 24, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 38, 68, 85, 87, 94, 98, 107, 121, 122,
- 125, 49, 117, 1, 4, 102, 103, 4, 62, 86,
- 4, 62, 62, 62, 100, 62, 84, 84, 84, 104,
- 107, 84, 100, 84, 88, 83, 124, 125, 100, 107,
- 123, 1, 127, 107, 104, 64, 4, 107, 107, 85,
- 4, 87, 89, 84, 62, 95, 105, 122, 100, 100,
- 1, 4, 123, 84, 106, 63, 123, 123, 27, 39,
- 125, 107, 10, 96, 100, 65, 100, 100, 62, 4,
- 100, 127, 97, 85, 121, 85, 107, 123, 107, 125,
- 106, 111, 19, 90, 91, 123, 100, 125, 100, 123,
- 100, 100, 1, 25, 26, 92, 100, 85, 100, 89,
- 85, 122, 7, 8, 53, 54, 80, 93, 49, 126,
- 89, 123, 7, 7, 126, 100, 123, 100, 100, 83,
- 100, 85, 83, 85
+ 0, 75, 0, 1, 3, 4, 7, 8, 17, 18,
+ 35, 36, 37, 38, 43, 44, 45, 46, 47, 50,
+ 51, 57, 58, 60, 62, 65, 66, 68, 76, 78,
+ 82, 84, 86, 105, 113, 117, 118, 119, 120, 121,
+ 122, 130, 131, 66, 69, 127, 128, 129, 83, 123,
+ 131, 131, 131, 66, 66, 68, 118, 131, 118, 118,
+ 66, 120, 131, 1, 112, 113, 48, 122, 71, 73,
+ 79, 88, 105, 133, 137, 79, 85, 50, 9, 14,
+ 40, 41, 42, 52, 54, 55, 56, 115, 116, 11,
+ 118, 57, 58, 59, 60, 61, 64, 57, 58, 59,
+ 60, 61, 64, 12, 13, 43, 44, 51, 114, 111,
+ 112, 113, 112, 16, 127, 3, 4, 45, 46, 68,
+ 80, 81, 55, 107, 111, 111, 113, 43, 44, 132,
+ 1, 54, 67, 135, 139, 135, 1, 6, 77, 105,
+ 106, 87, 106, 5, 113, 130, 113, 113, 113, 113,
+ 113, 38, 118, 118, 118, 118, 118, 118, 118, 118,
+ 118, 118, 118, 118, 13, 113, 135, 70, 49, 66,
+ 118, 135, 135, 113, 106, 40, 1, 113, 1, 88,
+ 1, 19, 21, 22, 23, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 39, 72, 89, 90, 92, 100,
+ 104, 113, 133, 134, 137, 53, 123, 1, 4, 108,
+ 109, 130, 66, 91, 4, 66, 66, 66, 106, 66,
+ 88, 88, 88, 110, 113, 88, 106, 88, 93, 87,
+ 136, 137, 106, 113, 135, 1, 139, 113, 110, 94,
+ 4, 113, 113, 89, 4, 92, 95, 88, 66, 101,
+ 111, 134, 106, 106, 1, 4, 135, 88, 124, 125,
+ 126, 127, 67, 135, 135, 26, 40, 137, 112, 10,
+ 102, 106, 16, 126, 106, 106, 66, 130, 106, 135,
+ 103, 89, 133, 89, 113, 135, 113, 137, 117, 20,
+ 96, 97, 135, 106, 137, 106, 106, 106, 1, 24,
+ 25, 98, 106, 89, 106, 95, 89, 134, 7, 8,
+ 57, 58, 84, 99, 53, 138, 95, 135, 7, 7,
+ 138, 106, 135, 106, 106, 87, 106, 89, 87, 89
};
#define yyerrok (yyerrstatus = 0)
@@ -1286,8 +1350,7 @@ do { \
`--------------------------------*/
/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
@@ -1318,8 +1381,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
@@ -1344,8 +1406,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
| TOP (included). |
`------------------------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
#else
@@ -1375,8 +1436,7 @@ do { \
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static void
yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
#else
@@ -1444,8 +1504,7 @@ int yydebug;
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
#else
@@ -1468,8 +1527,7 @@ yystrlen (yystr)
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
#else
@@ -1653,8 +1711,7 @@ yysyntax_error (char *yyresult, int yystate, int yychar)
`-----------------------------------------------*/
/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
#else
@@ -1711,8 +1768,7 @@ int yynerrs;
`-------------------------*/
#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
int
yyparse (void *YYPARSE_PARAM)
#else
@@ -1721,8 +1777,7 @@ yyparse (YYPARSE_PARAM)
void *YYPARSE_PARAM;
#endif
#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+#if (defined __STDC__ || defined __C99__FUNC__ || defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
#else
@@ -1973,343 +2028,538 @@ yyreduce:
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
- case 2:
+ case 3:
/* Line 1455 of yacc.c */
-#line 188 "awkgram.y"
+#line 218 "awkgram.y"
{
- check_funcs();
- }
+ rule = 0;
+ yyerrok;
+ }
break;
- case 4:
+ case 5:
/* Line 1455 of yacc.c */
-#line 196 "awkgram.y"
+#line 224 "awkgram.y"
{
- beginfile_or_endfile_rule = begin_or_end_rule = parsing_end_rule = FALSE;
- yyerrok;
+ next_sourcefile();
}
break;
- case 5:
+ case 6:
/* Line 1455 of yacc.c */
-#line 201 "awkgram.y"
+#line 228 "awkgram.y"
{
- beginfile_or_endfile_rule = begin_or_end_rule = parsing_end_rule = FALSE;
+ rule = 0;
/*
* If errors, give up, don't produce an infinite
* stream of syntax error messages.
*/
/* yyerrok; */
- }
+ }
break;
- case 6:
+ case 7:
/* Line 1455 of yacc.c */
-#line 213 "awkgram.y"
+#line 240 "awkgram.y"
{
- (yyvsp[(1) - (2)].nodeval)->rnode = (yyvsp[(2) - (2)].nodeval);
+ (void) append_rule((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
}
break;
- case 7:
+ case 8:
/* Line 1455 of yacc.c */
-#line 217 "awkgram.y"
+#line 244 "awkgram.y"
{
- if ((yyvsp[(1) - (2)].nodeval)->lnode != NULL) {
- /* pattern rule with non-empty pattern */
- (yyvsp[(1) - (2)].nodeval)->rnode = node(NULL, Node_K_print_rec, NULL);
- } else {
- /* an error */
- if (begin_or_end_rule)
- msg(_("%s blocks must have an action part"),
- (parsing_end_rule ? "END" : "BEGIN"));
- else if (beginfile_or_endfile_rule)
- msg(_("%s blocks must have an action part"),
- (parsing_endfile_rule ? "ENDFILE" : "BEGINFILE"));
- else
- msg(_("each rule must have a pattern or an action part"));
+ if (rule != Rule) {
+ msg(_("%s blocks must have an action part"), ruletab[rule]);
errcount++;
- }
+ } else if ((yyvsp[(1) - (2)]) == NULL) {
+ msg(_("each rule must have a pattern or an action part"));
+ errcount++;
+ } else /* pattern rule with non-empty pattern */
+ (void) append_rule((yyvsp[(1) - (2)]), NULL);
}
break;
- case 8:
+ case 9:
/* Line 1455 of yacc.c */
-#line 235 "awkgram.y"
+#line 255 "awkgram.y"
{
can_return = FALSE;
- if ((yyvsp[(1) - (2)].nodeval))
- func_install((yyvsp[(1) - (2)].nodeval), (yyvsp[(2) - (2)].nodeval));
+ if ((yyvsp[(1) - (2)]) && func_install((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])) < 0)
+ YYABORT;
+ func_params = NULL;
yyerrok;
}
break;
- case 9:
+ case 10:
/* Line 1455 of yacc.c */
-#line 245 "awkgram.y"
+#line 263 "awkgram.y"
{
- (yyval.nodeval) = append_pattern(&expression_value, (NODE *) NULL);
+ want_source = FALSE;
+ yyerrok;
}
break;
- case 10:
+ case 11:
/* Line 1455 of yacc.c */
-#line 249 "awkgram.y"
+#line 271 "awkgram.y"
{
- (yyval.nodeval) = append_pattern(&expression_value, (yyvsp[(1) - (1)].nodeval));
+ char *src = (yyvsp[(1) - (1)])->lextok;
+ if (include_source(src) < 0)
+ YYABORT;
+ efree(src);
+ bcfree((yyvsp[(1) - (1)]));
+ (yyval) = NULL;
}
break;
- case 11:
+ case 12:
/* Line 1455 of yacc.c */
-#line 253 "awkgram.y"
- {
- NODE *r;
+#line 280 "awkgram.y"
+ { (yyval) = NULL; }
+ break;
+
+ case 13:
+
+/* Line 1455 of yacc.c */
+#line 282 "awkgram.y"
+ { (yyval) = NULL; }
+ break;
+
+ case 14:
+
+/* Line 1455 of yacc.c */
+#line 287 "awkgram.y"
+ { (yyval) = NULL; rule = Rule; }
+ break;
+
+ case 15:
+
+/* Line 1455 of yacc.c */
+#line 289 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); rule = Rule; }
+ break;
- getnode(r);
- r->type = Node_line_range;
- r->condpair = node((yyvsp[(1) - (3)].nodeval), Node_cond_pair, (yyvsp[(3) - (3)].nodeval));
- r->triggered = FALSE;
- (yyval.nodeval) = append_pattern(&expression_value, r);
+ case 16:
+
+/* Line 1455 of yacc.c */
+#line 291 "awkgram.y"
+ {
+ INSTRUCTION *tp;
+
+ add_lint((yyvsp[(1) - (3)]), LINT_assign_in_cond);
+ add_lint((yyvsp[(3) - (3)]), LINT_assign_in_cond);
+
+ tp = instruction(Op_no_op);
+ list_prepend((yyvsp[(1) - (3)]), bcalloc(Op_line_range, !!do_profiling + 1, 0));
+ (yyvsp[(1) - (3)])->nexti->triggered = FALSE;
+ (yyvsp[(1) - (3)])->nexti->target_jmp = (yyvsp[(3) - (3)])->nexti;
+
+ list_append((yyvsp[(1) - (3)]), instruction(Op_cond_pair));
+ (yyvsp[(1) - (3)])->lasti->line_range = (yyvsp[(1) - (3)])->nexti;
+ (yyvsp[(1) - (3)])->lasti->target_jmp = tp;
+
+ list_append((yyvsp[(3) - (3)]), instruction(Op_cond_pair));
+ (yyvsp[(3) - (3)])->lasti->line_range = (yyvsp[(1) - (3)])->nexti;
+ (yyvsp[(3) - (3)])->lasti->target_jmp = tp;
+ if (do_profiling) {
+ ((yyvsp[(1) - (3)])->nexti + 1)->condpair_left = (yyvsp[(1) - (3)])->lasti;
+ ((yyvsp[(1) - (3)])->nexti + 1)->condpair_right = (yyvsp[(3) - (3)])->lasti;
+ }
+ (yyval) = list_append(list_merge((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])), tp);
+ rule = Rule;
}
break;
- case 12:
+ case 17:
/* Line 1455 of yacc.c */
-#line 263 "awkgram.y"
+#line 317 "awkgram.y"
{
static int begin_seen = 0;
if (do_lint_old && ++begin_seen == 2)
warning(_("old awk does not support multiple `BEGIN' or `END' rules"));
- begin_or_end_rule = TRUE;
- (yyval.nodeval) = append_pattern(&begin_block, (NODE *) NULL);
+ (yyvsp[(1) - (1)])->in_rule = rule = BEGIN;
+ (yyvsp[(1) - (1)])->source_file = source;
+ (yyval) = (yyvsp[(1) - (1)]);
}
break;
- case 13:
+ case 18:
/* Line 1455 of yacc.c */
-#line 272 "awkgram.y"
+#line 327 "awkgram.y"
{
static int end_seen = 0;
if (do_lint_old && ++end_seen == 2)
warning(_("old awk does not support multiple `BEGIN' or `END' rules"));
- begin_or_end_rule = parsing_end_rule = TRUE;
- (yyval.nodeval) = append_pattern(&end_block, (NODE *) NULL);
+ (yyvsp[(1) - (1)])->in_rule = rule = END;
+ (yyvsp[(1) - (1)])->source_file = source;
+ (yyval) = (yyvsp[(1) - (1)]);
}
break;
- case 14:
+ case 19:
/* Line 1455 of yacc.c */
-#line 281 "awkgram.y"
+#line 337 "awkgram.y"
{
- beginfile_or_endfile_rule = TRUE;
- (yyval.nodeval) = append_pattern(&beginfile_block, (NODE *) NULL);
+ (yyvsp[(1) - (1)])->in_rule = rule = BEGINFILE;
+ (yyvsp[(1) - (1)])->source_file = source;
+ (yyval) = (yyvsp[(1) - (1)]);
}
break;
- case 15:
+ case 20:
/* Line 1455 of yacc.c */
-#line 286 "awkgram.y"
+#line 343 "awkgram.y"
{
- beginfile_or_endfile_rule = parsing_endfile_rule = TRUE;
- (yyval.nodeval) = append_pattern(&endfile_block, (NODE *) NULL);
+ (yyvsp[(1) - (1)])->in_rule = rule = ENDFILE;
+ (yyvsp[(1) - (1)])->source_file = source;
+ (yyval) = (yyvsp[(1) - (1)]);
}
break;
- case 16:
+ case 21:
/* Line 1455 of yacc.c */
-#line 294 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(2) - (5)].nodeval); }
+#line 352 "awkgram.y"
+ {
+ if ((yyvsp[(2) - (5)]) == NULL)
+ (yyval) = list_create(instruction(Op_no_op));
+ else
+ (yyval) = (yyvsp[(2) - (5)]);
+ }
break;
- case 17:
+ case 22:
/* Line 1455 of yacc.c */
-#line 299 "awkgram.y"
- { (yyval.sval) = (yyvsp[(1) - (1)].sval); }
+#line 362 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
- case 18:
+ case 23:
/* Line 1455 of yacc.c */
-#line 301 "awkgram.y"
- { (yyval.sval) = (yyvsp[(1) - (1)].sval); }
+#line 364 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
- case 19:
+ case 24:
/* Line 1455 of yacc.c */
-#line 303 "awkgram.y"
+#line 366 "awkgram.y"
{
yyerror(_("`%s' is a built-in function, it cannot be redefined"),
tokstart);
- errcount++;
- (yyval.sval) = builtin_func;
+ (yyvsp[(1) - (1)])->opcode = Op_symbol; /* Op_symbol instead of Op_token so that
+ * free_bc_internal does not try to free it
+ */
+ (yyvsp[(1) - (1)])->lextok = builtin_func;
+ (yyval) = (yyvsp[(1) - (1)]);
/* yyerrok; */
}
break;
- case 22:
+ case 25:
/* Line 1455 of yacc.c */
-#line 319 "awkgram.y"
+#line 377 "awkgram.y"
+ { (yyval) = (yyvsp[(2) - (2)]); }
+ break;
+
+ case 28:
+
+/* Line 1455 of yacc.c */
+#line 387 "awkgram.y"
{
- param_counter = 0;
- }
+ param_counter = 0;
+ func_params = NULL;
+ }
break;
- case 23:
+ case 29:
/* Line 1455 of yacc.c */
-#line 323 "awkgram.y"
+#line 392 "awkgram.y"
{
NODE *t;
- t = make_param((yyvsp[(3) - (7)].sval));
+ (yyvsp[(1) - (7)])->source_file = source;
+ t = make_param((yyvsp[(3) - (7)])->lextok);
+ (yyvsp[(3) - (7)])->lextok = NULL;
+ bcfree((yyvsp[(3) - (7)]));
t->flags |= FUNC;
- (yyval.nodeval) = append_right(t, (yyvsp[(5) - (7)].nodeval));
+ t->rnode = func_params;
+ func_params = t;
+ (yyval) = (yyvsp[(1) - (7)]);
can_return = TRUE;
/* check for duplicate parameter names */
- if (dup_parms((yyval.nodeval)))
+ if (dup_parms(t))
errcount++;
}
break;
- case 24:
+ case 30:
/* Line 1455 of yacc.c */
-#line 342 "awkgram.y"
+#line 416 "awkgram.y"
{ ++want_regexp; }
break;
- case 25:
+ case 31:
/* Line 1455 of yacc.c */
-#line 344 "awkgram.y"
+#line 418 "awkgram.y"
{
- NODE *n;
- size_t len = strlen((yyvsp[(3) - (3)].sval));
+ NODE *n, *exp;
+ char *re;
+ size_t len;
+ re = (yyvsp[(3) - (3)])->lextok;
+ len = strlen(re);
if (do_lint) {
if (len == 0)
lintwarn(_("regexp constant `//' looks like a C++ comment, but is not"));
- else if (((yyvsp[(3) - (3)].sval))[0] == '*' && ((yyvsp[(3) - (3)].sval))[len-1] == '*')
+ else if ((re)[0] == '*' && (re)[len-1] == '*')
/* possible C comment */
lintwarn(_("regexp constant `/%s/' looks like a C comment, but is not"), tokstart);
}
- getnode(n);
- n->type = Node_regex;
- n->re_exp = make_string((yyvsp[(3) - (3)].sval), len);
- n->re_reg = make_regexp((yyvsp[(3) - (3)].sval), len, FALSE, TRUE);
- n->re_text = NULL;
- n->re_flags = CONSTANT;
- n->re_cnt = 1;
- (yyval.nodeval) = n;
+
+ exp = make_str_node(re, len, ALREADY_MALLOCED);
+ n = make_regnode(Node_regex, exp);
+ if (n == NULL) {
+ unref(exp);
+ YYABORT;
+ }
+ (yyval) = (yyvsp[(3) - (3)]);
+ (yyval)->opcode = Op_match_rec;
+ (yyval)->memory = n;
}
break;
- case 28:
+ case 32:
/* Line 1455 of yacc.c */
-#line 373 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 447 "awkgram.y"
+ { bcfree((yyvsp[(1) - (1)])); }
break;
- case 29:
+ case 34:
/* Line 1455 of yacc.c */
-#line 375 "awkgram.y"
+#line 453 "awkgram.y"
+ { (yyval) = NULL; }
+ break;
+
+ case 35:
+
+/* Line 1455 of yacc.c */
+#line 455 "awkgram.y"
{
- if ((yyvsp[(2) - (2)].nodeval) == NULL)
- (yyval.nodeval) = (yyvsp[(1) - (2)].nodeval);
+ if ((yyvsp[(2) - (2)]) == NULL)
+ (yyval) = (yyvsp[(1) - (2)]);
else {
- if (do_lint && isnoeffect((yyvsp[(2) - (2)].nodeval)->type))
- lintwarn(_("statement may have no effect"));
- if ((yyvsp[(1) - (2)].nodeval) == NULL)
- (yyval.nodeval) = (yyvsp[(2) - (2)].nodeval);
+ add_lint((yyvsp[(2) - (2)]), LINT_no_effect);
+ if ((yyvsp[(1) - (2)]) == NULL)
+ (yyval) = (yyvsp[(2) - (2)]);
else
- (yyval.nodeval) = append_right(
- ((yyvsp[(1) - (2)].nodeval)->type == Node_statement_list ? (yyvsp[(1) - (2)].nodeval)
- : node((yyvsp[(1) - (2)].nodeval), Node_statement_list, (NODE *) NULL)),
- ((yyvsp[(2) - (2)].nodeval)->type == Node_statement_list ? (yyvsp[(2) - (2)].nodeval)
- : node((yyvsp[(2) - (2)].nodeval), Node_statement_list, (NODE *) NULL)));
+ (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
}
- yyerrok;
+ yyerrok;
}
break;
- case 30:
+ case 36:
/* Line 1455 of yacc.c */
-#line 393 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 468 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 33:
+ case 39:
/* Line 1455 of yacc.c */
-#line 403 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 478 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 34:
+ case 40:
/* Line 1455 of yacc.c */
-#line 405 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(2) - (3)].nodeval); }
+#line 480 "awkgram.y"
+ { (yyval) = (yyvsp[(2) - (3)]); }
break;
- case 35:
+ case 41:
/* Line 1455 of yacc.c */
-#line 407 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 482 "awkgram.y"
+ {
+ if (do_profiling)
+ (yyval) = list_prepend((yyvsp[(1) - (1)]), instruction(Op_exec_count));
+ else
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
break;
- case 36:
+ case 42:
/* Line 1455 of yacc.c */
-#line 409 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(3) - (9)].nodeval), Node_K_switch, (yyvsp[(7) - (9)].nodeval)); }
+#line 489 "awkgram.y"
+ {
+ INSTRUCTION *ip;
+
+ (yyvsp[(1) - (9)])->opcode = Op_push_loop;
+ (yyvsp[(1) - (9)])->target_continue = NULL;
+ ip = list_prepend((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]));
+ if ((yyvsp[(7) - (9)])->nexti->switch_dflt == NULL)
+ (yyvsp[(7) - (9)])->nexti->switch_dflt = (yyvsp[(1) - (9)]); /* implicit break */
+ if (do_profiling) {
+ (void) list_prepend(ip, instruction(Op_exec_count));
+ ((yyvsp[(1) - (9)]) + 1)->opcode = Op_K_switch;
+ ((yyvsp[(1) - (9)]) + 1)->switch_body = (yyvsp[(7) - (9)])->nexti;
+ }
+ (void) list_merge(ip, (yyvsp[(7) - (9)]));
+ (yyval) = list_append(ip, instruction(Op_pop_loop));
+ (yyvsp[(1) - (9)])->target_break = (yyval)->lasti;
+
+ break_allowed--;
+ fix_break_continue((yyvsp[(1) - (9)]), (yyval)->lasti, FALSE);
+ }
break;
- case 37:
+ case 43:
/* Line 1455 of yacc.c */
-#line 411 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(3) - (6)].nodeval), Node_K_while, (yyvsp[(6) - (6)].nodeval)); }
+#line 510 "awkgram.y"
+ {
+ /*
+ * [Op_push_loop| z| y]
+ * -----------------
+ * z:
+ * cond
+ * -----------------
+ * [Op_jmp_false y ]
+ * -----------------
+ * body
+ * -----------------
+ * [Op_jmp z ]
+ * y: [Op_pop_loop ]
+ */
+
+ INSTRUCTION *ip, *tp;
+
+ tp = instruction(Op_pop_loop);
+
+ add_lint((yyvsp[(3) - (6)]), LINT_assign_in_cond);
+ (yyvsp[(1) - (6)])->opcode = Op_push_loop;
+ (yyvsp[(1) - (6)])->target_continue = (yyvsp[(3) - (6)])->nexti;
+ (yyvsp[(1) - (6)])->target_break = tp;
+ ip = list_create((yyvsp[(1) - (6)]));
+
+ (void) list_merge(ip, (yyvsp[(3) - (6)]));
+ (void) list_append(ip, instruction(Op_jmp_false));
+ ip->lasti->target_jmp = tp;
+
+ if (do_profiling) {
+ (void) list_append(ip, instruction(Op_exec_count));
+ ((yyvsp[(1) - (6)]) + 1)->opcode = Op_K_while;
+ ((yyvsp[(1) - (6)]) + 1)->while_body = ip->lasti;
+ }
+
+ if ((yyvsp[(6) - (6)]) != NULL)
+ (void) list_merge(ip, (yyvsp[(6) - (6)]));
+ (void) list_append(ip, instruction(Op_jmp));
+ ip->lasti->target_jmp = (yyvsp[(1) - (6)])->target_continue;
+ (yyval) = list_append(ip, tp);
+
+ break_allowed--;
+ continue_allowed--;
+ fix_break_continue((yyvsp[(1) - (6)]), tp, TRUE);
+ }
break;
- case 38:
+ case 44:
/* Line 1455 of yacc.c */
-#line 413 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(6) - (8)].nodeval), Node_K_do, (yyvsp[(3) - (8)].nodeval)); }
+#line 556 "awkgram.y"
+ {
+ /*
+ * [Op_push_loop | x | y]
+ * -----------------
+ * z:
+ * body
+ * -----------------
+ * x:
+ * cond
+ * -----------------
+ * [Op_jmp_true | z ]
+ * y: [Op_pop_loop ]
+ */
+
+ INSTRUCTION *ip;
+
+ (yyvsp[(4) - (8)])->opcode = Op_pop_loop;
+ (yyvsp[(1) - (8)])->opcode = Op_push_loop;
+ (yyvsp[(1) - (8)])->target_continue = (yyvsp[(6) - (8)])->nexti;
+ (yyvsp[(1) - (8)])->target_break = (yyvsp[(4) - (8)]);
+
+ add_lint((yyvsp[(6) - (8)]), LINT_assign_in_cond);
+ if ((yyvsp[(3) - (8)]) != NULL)
+ ip = list_merge((yyvsp[(3) - (8)]), (yyvsp[(6) - (8)]));
+ else
+ ip = list_prepend((yyvsp[(6) - (8)]), instruction(Op_no_op));
+
+ if (do_profiling) {
+ (void) list_prepend(ip, instruction(Op_exec_count));
+ ((yyvsp[(1) - (8)]) + 1)->opcode = Op_K_do;
+ ((yyvsp[(1) - (8)]) + 1)->doloop_cond = (yyvsp[(1) - (8)])->target_continue;
+ }
+
+ (void) list_append(ip, instruction(Op_jmp_true));
+ ip->lasti->target_jmp = ip->nexti;
+ (yyval) = list_prepend(ip, (yyvsp[(1) - (8)]));
+ (void) list_append(ip, (yyvsp[(4) - (8)]));
+
+ break_allowed--;
+ continue_allowed--;
+ fix_break_continue((yyvsp[(1) - (8)]), (yyvsp[(4) - (8)]), TRUE);
+ }
break;
- case 39:
+ case 45:
/* Line 1455 of yacc.c */
-#line 415 "awkgram.y"
+#line 599 "awkgram.y"
{
- /*
- * Efficiency hack. Recognize the special case of
+
+ char *var_name = (yyvsp[(3) - (8)])->lextok;
+
+ if ((yyvsp[(8) - (8)]) != NULL
+ && (yyvsp[(8) - (8)])->lasti->opcode == Op_K_delete
+ && (yyvsp[(8) - (8)])->lasti->expr_count == 1
+ && (yyvsp[(8) - (8)])->nexti->opcode == Op_push
+ && ((yyvsp[(8) - (8)])->nexti->memory->type != Node_var || !((yyvsp[(8) - (8)])->nexti->memory->var_update))
+ && strcmp((yyvsp[(8) - (8)])->nexti->memory->vname, var_name) == 0
+ ) {
+
+ /* Efficiency hack. Recognize the special case of
*
* for (iggy in foo)
* delete foo[iggy]
@@ -2320,1170 +2570,1652 @@ yyreduce:
*
* Check that the body is a `delete a[i]' statement,
* and that both the loop var and array names match.
- */
- if ((yyvsp[(8) - (8)].nodeval) != NULL && (yyvsp[(8) - (8)].nodeval)->type == Node_K_delete && (yyvsp[(8) - (8)].nodeval)->rnode != NULL) {
- NODE *arr, *sub;
-
- assert((yyvsp[(8) - (8)].nodeval)->rnode->type == Node_expression_list);
- arr = (yyvsp[(8) - (8)].nodeval)->lnode; /* array var */
- sub = (yyvsp[(8) - (8)].nodeval)->rnode->lnode; /* index var */
-
- if ( (arr->type == Node_var_new
- || arr->type == Node_var_array
- || arr->type == Node_param_list)
- && (sub->type == Node_var_new
- || sub->type == Node_var
- || sub->type == Node_param_list)
- && strcmp((yyvsp[(3) - (8)].sval), sub->vname) == 0
- && strcmp((yyvsp[(5) - (8)].sval), arr->vname) == 0) {
- (yyvsp[(8) - (8)].nodeval)->type = Node_K_delete_loop;
- (yyval.nodeval) = (yyvsp[(8) - (8)].nodeval);
- free((yyvsp[(3) - (8)].sval)); /* thanks to valgrind for pointing these out */
- free((yyvsp[(5) - (8)].sval));
+ */
+ NODE *arr = NULL;
+ INSTRUCTION *ip = (yyvsp[(8) - (8)])->nexti->nexti;
+
+ if ((yyvsp[(5) - (8)])->nexti->opcode == Op_push && (yyvsp[(5) - (8)])->lasti == (yyvsp[(5) - (8)])->nexti)
+ arr = (yyvsp[(5) - (8)])->nexti->memory;
+ if (arr != NULL
+ && ip->opcode == Op_no_op
+ && ip->nexti->opcode == Op_push_array
+ && strcmp(ip->nexti->memory->vname, arr->vname) == 0
+ && ip->nexti->nexti == (yyvsp[(8) - (8)])->lasti
+ ) {
+ (void) make_assignable((yyvsp[(8) - (8)])->nexti);
+ (yyvsp[(8) - (8)])->lasti->opcode = Op_K_delete_loop;
+ (yyvsp[(8) - (8)])->lasti->expr_count = 0;
+ bcfree((yyvsp[(1) - (8)]));
+ efree(var_name);
+ bcfree((yyvsp[(3) - (8)]));
+ bcfree((yyvsp[(4) - (8)]));
+ bcfree((yyvsp[(5) - (8)]));
+ (yyval) = (yyvsp[(8) - (8)]);
}
- else
- goto regular_loop;
} else {
- regular_loop:
- (yyval.nodeval) = node((yyvsp[(8) - (8)].nodeval), Node_K_arrayfor,
- make_for_loop(variable((yyvsp[(3) - (8)].sval), CAN_FREE, Node_var),
- (NODE *) NULL, variable((yyvsp[(5) - (8)].sval), CAN_FREE, Node_var_array)));
- }
+
+ /* [ Op_push_array a ]
+ * [ Op_arrayfor_init| w ]
+ * [ Op_push_loop | z | y ]
+ * z: [ Op_arrayfor_incr | y ]
+ * [ Op_var_assign if any ]
+ *
+ * body
+ *
+ * [Op_jmp | z ]
+ * y: [Op_pop_loop ]
+ * w: [Op_arrayfor_final ]
+ */
+ INSTRUCTION *ip;
+
+ ip = (yyvsp[(5) - (8)]);
+ ip->nexti->opcode = Op_push_array;
+ (yyvsp[(3) - (8)])->opcode = Op_arrayfor_init;
+ (void) list_append(ip, (yyvsp[(3) - (8)]));
+
+ (yyvsp[(4) - (8)])->opcode = Op_arrayfor_incr;
+ (yyvsp[(4) - (8)])->array_var = variable(var_name, Node_var);
+ (yyvsp[(1) - (8)])->opcode = Op_push_loop;
+ (yyvsp[(1) - (8)])->target_continue = (yyvsp[(4) - (8)]);
+
+ (void) list_append(ip, (yyvsp[(1) - (8)]));
+
+ /* add update_FOO instruction if necessary */
+ if ((yyvsp[(4) - (8)])->array_var->type == Node_var && (yyvsp[(4) - (8)])->array_var->var_update) {
+ (void) list_append(ip, instruction(Op_var_update));
+ ip->lasti->memory = (yyvsp[(4) - (8)])->array_var;
+ }
+ (void) list_append(ip, (yyvsp[(4) - (8)]));
+
+ /* add set_FOO instruction if necessary */
+ if ((yyvsp[(4) - (8)])->array_var->type == Node_var && (yyvsp[(4) - (8)])->array_var->var_assign) {
+ (void) list_append(ip, instruction(Op_var_assign));
+ ip->lasti->memory = (yyvsp[(4) - (8)])->array_var;
+ }
+
+ if (do_profiling) {
+ (void) list_append(ip, instruction(Op_exec_count));
+ ((yyvsp[(1) - (8)]) + 1)->opcode = Op_K_arrayfor;
+ ((yyvsp[(1) - (8)]) + 1)->forloop_cond = (yyvsp[(4) - (8)]);
+ ((yyvsp[(1) - (8)]) + 1)->forloop_body = ip->lasti;
+ }
+
+ if ((yyvsp[(8) - (8)]) != NULL)
+ (void) list_merge(ip, (yyvsp[(8) - (8)]));
+
+ (void) list_append(ip, instruction(Op_jmp));
+ ip->lasti->target_jmp = (yyvsp[(4) - (8)]);
+ (void) list_append(ip, instruction(Op_pop_loop));
+ (yyvsp[(4) - (8)])->target_jmp = (yyvsp[(1) - (8)])->target_break = ip->lasti;
+ (yyval) = list_append(ip, instruction(Op_arrayfor_final));
+ (yyvsp[(3) - (8)])->target_jmp = (yyval)->lasti;
+
+ fix_break_continue((yyvsp[(1) - (8)]), (yyvsp[(4) - (8)])->target_jmp, TRUE);
+ }
+
+ break_allowed--;
+ continue_allowed--;
}
break;
- case 40:
+ case 46:
/* Line 1455 of yacc.c */
-#line 459 "awkgram.y"
+#line 709 "awkgram.y"
{
- (yyval.nodeval) = node((yyvsp[(12) - (12)].nodeval), Node_K_for, (NODE *) make_for_loop((yyvsp[(3) - (12)].nodeval), (yyvsp[(6) - (12)].nodeval), (yyvsp[(9) - (12)].nodeval)));
+ (yyval) = mk_for_loop((yyvsp[(1) - (12)]), (yyvsp[(3) - (12)]), (yyvsp[(6) - (12)]), (yyvsp[(9) - (12)]), (yyvsp[(12) - (12)]));
+
+ break_allowed--;
+ continue_allowed--;
}
break;
- case 41:
+ case 47:
/* Line 1455 of yacc.c */
-#line 463 "awkgram.y"
+#line 716 "awkgram.y"
{
- (yyval.nodeval) = node((yyvsp[(11) - (11)].nodeval), Node_K_for,
- (NODE *) make_for_loop((yyvsp[(3) - (11)].nodeval), (NODE *) NULL, (yyvsp[(8) - (11)].nodeval)));
+ (yyval) = mk_for_loop((yyvsp[(1) - (11)]), (yyvsp[(3) - (11)]), (INSTRUCTION *) NULL, (yyvsp[(8) - (11)]), (yyvsp[(11) - (11)]));
+
+ break_allowed--;
+ continue_allowed--;
}
break;
- case 42:
+ case 48:
/* Line 1455 of yacc.c */
-#line 469 "awkgram.y"
- { (yyval.nodeval) = node((NODE *) NULL, Node_K_break, (NODE *) NULL); }
+#line 723 "awkgram.y"
+ {
+ if (do_profiling)
+ (yyval) = list_prepend((yyvsp[(1) - (1)]), instruction(Op_exec_count));
+ else
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
break;
- case 43:
+ case 49:
/* Line 1455 of yacc.c */
-#line 472 "awkgram.y"
- { (yyval.nodeval) = node((NODE *) NULL, Node_K_continue, (NODE *) NULL); }
+#line 733 "awkgram.y"
+ {
+ if (! break_allowed)
+ yyerror(_("`break' is not allowed outside a loop or switch"));
+
+ (yyvsp[(1) - (2)])->target_jmp = NULL;
+ (yyval) = list_create((yyvsp[(1) - (2)]));
+
+ }
break;
- case 44:
+ case 50:
/* Line 1455 of yacc.c */
-#line 474 "awkgram.y"
- { NODETYPE type;
+#line 742 "awkgram.y"
+ {
+ if (! continue_allowed)
+ yyerror(_("`continue' is not allowed outside a loop"));
- if (begin_or_end_rule)
- yyerror(_("`%s' used in %s action"), "next",
- (parsing_end_rule ? "END" : "BEGIN"));
- else if (beginfile_or_endfile_rule)
- yyerror(_("`%s' used in %s action"), "next",
- (parsing_endfile_rule ? "ENDFILE" : "BEGINFILE"));
- type = Node_K_next;
- (yyval.nodeval) = node((NODE *) NULL, type, (NODE *) NULL);
- }
+ (yyvsp[(1) - (2)])->target_jmp = NULL;
+ (yyval) = list_create((yyvsp[(1) - (2)]));
+
+ }
break;
- case 45:
+ case 51:
/* Line 1455 of yacc.c */
-#line 486 "awkgram.y"
+#line 751 "awkgram.y"
{
- static short warned = FALSE;
+ if (rule != Rule)
+ yyerror(_("`next' used in %s action"), ruletab[rule]);
+ (yyvsp[(1) - (2)])->target_jmp = ip_rec;
+ (yyval) = list_create((yyvsp[(1) - (2)]));
+ }
+ break;
- if (do_traditional) {
- /*
- * can't use yyerror, since may have overshot
- * the source line
- */
+ case 52:
+
+/* Line 1455 of yacc.c */
+#line 758 "awkgram.y"
+ {
+ static short warned = FALSE;
+
+ if (do_traditional) {
+ /*
+ * can't use yyerror, since may have overshot
+ * the source line
+ */
errcount++;
error(_("`nextfile' is a gawk extension"));
- }
- if (do_lint && ! warned) {
- warned = TRUE;
+ }
+ if (do_lint && ! warned) {
+ warned = TRUE;
lintwarn(_("`nextfile' is a gawk extension"));
- }
- if (begin_or_end_rule) {
- /* same thing */
- errcount++;
- error(_("`%s' used in %s action"), "nextfile",
- (parsing_end_rule ? "END" : "BEGIN"));
- }
-#if 0
- else if (beginfile_or_endfile_rule) {
- /* same thing */
- errcount++;
- error(_("`%s' used in %s action"), "nextfile",
- (parsing_endfile_rule ? "END" : "BEGIN"));
- }
-#endif
- else if (parsing_endfile_rule) {
- /* same thing */
+ }
+ if (rule == BEGIN || rule == END || rule == ENDFILE) {
errcount++;
- error(_("`%s' used in %s action"), "nextfile",
- (parsing_endfile_rule ? "ENDFILE" : "BEGINFILE"));
- }
- (yyval.nodeval) = node((NODE *) NULL, Node_K_nextfile, (NODE *) NULL);
+ error(_("`nextfile' used in %s action"), ruletab[rule]);
}
+
+ (yyvsp[(1) - (2)])->target_jmp = ip_newfile;
+ (yyvsp[(1) - (2)])->target_endfile = ip_endfile;
+ (yyval) = list_create((yyvsp[(1) - (2)]));
+ }
break;
- case 46:
+ case 53:
/* Line 1455 of yacc.c */
-#line 524 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (3)].nodeval), Node_K_exit, (NODE *) NULL); }
+#line 783 "awkgram.y"
+ {
+ if (rule == END)
+ (yyvsp[(1) - (3)])->target_jmp = ip_atexit;
+ else
+ (yyvsp[(1) - (3)])->target_jmp = ip_end; /* first instruction (no-op) in end block */
+
+ if ((yyvsp[(2) - (3)]) == NULL) {
+ (yyval) = list_create((yyvsp[(1) - (3)]));
+ (void) list_prepend((yyval), instruction(Op_push_i));
+ (yyval)->nexti->memory = Nnull_string;
+ } else
+ (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
+ }
break;
- case 47:
+ case 54:
/* Line 1455 of yacc.c */
-#line 526 "awkgram.y"
+#line 797 "awkgram.y"
{
- if (! can_return)
+ if (! can_return)
yyerror(_("`return' used outside function context"));
- }
+ }
break;
- case 48:
+ case 55:
/* Line 1455 of yacc.c */
-#line 531 "awkgram.y"
+#line 800 "awkgram.y"
{
- (yyval.nodeval) = node((yyvsp[(3) - (4)].nodeval) == NULL ? Nnull_string : (yyvsp[(3) - (4)].nodeval),
- Node_K_return, (NODE *) NULL);
- }
+ if ((yyvsp[(3) - (4)]) == NULL) {
+ (yyval) = list_create((yyvsp[(1) - (4)]));
+ (void) list_prepend((yyval), instruction(Op_push_i));
+ (yyval)->nexti->memory = Nnull_string;
+ } else
+ (yyval) = list_append((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
+ }
break;
- case 50:
+ case 57:
/* Line 1455 of yacc.c */
-#line 547 "awkgram.y"
+#line 820 "awkgram.y"
{ in_print = TRUE; in_parens = 0; }
break;
- case 51:
+ case 58:
/* Line 1455 of yacc.c */
-#line 548 "awkgram.y"
+#line 821 "awkgram.y"
{
/*
* Optimization: plain `print' has no expression list, so $3 is null.
- * If $3 is an expression list with one element (rnode == null)
- * and lnode is a field spec for field 0, we have `print $0'.
- * For both, use Node_K_print_rec, which is faster for these two cases.
+ * If $3 is NULL or is a bytecode list for $0 use Op_K_print_rec,
+ * which is faster for these two cases.
*/
- if ((yyvsp[(1) - (4)].nodetypeval) == Node_K_print &&
- ((yyvsp[(3) - (4)].nodeval) == NULL
- || ((yyvsp[(3) - (4)].nodeval)->type == Node_expression_list
- && (yyvsp[(3) - (4)].nodeval)->rnode == NULL
- && (yyvsp[(3) - (4)].nodeval)->lnode->type == Node_field_spec
- && (yyvsp[(3) - (4)].nodeval)->lnode->lnode->type == Node_val
- && (yyvsp[(3) - (4)].nodeval)->lnode->lnode->numbr == 0.0))
+
+ if ((yyvsp[(1) - (4)])->opcode == Op_K_print &&
+ ((yyvsp[(3) - (4)]) == NULL
+ || ((yyvsp[(3) - (4)])->lasti->opcode == Op_field_spec
+ && (yyvsp[(3) - (4)])->nexti->nexti->nexti == (yyvsp[(3) - (4)])->lasti
+ && (yyvsp[(3) - (4)])->nexti->nexti->opcode == Op_push_i
+ && (yyvsp[(3) - (4)])->nexti->nexti->memory->type == Node_val
+ && (yyvsp[(3) - (4)])->nexti->nexti->memory->numbr == 0.0)
+ )
) {
static short warned = FALSE;
+ /* -----------------
+ * output_redir
+ * [ redirect exp ]
+ * -----------------
+ * expression_list
+ * ------------------
+ * [Op_K_print_rec | NULL | redir_type | expr_count]
+ */
- (yyval.nodeval) = node(NULL, Node_K_print_rec, (yyvsp[(4) - (4)].nodeval));
+ if ((yyvsp[(3) - (4)]) != NULL) {
+ bcfree((yyvsp[(3) - (4)])->lasti); /* Op_field_spec */
+ (yyvsp[(3) - (4)])->nexti->nexti->memory->flags &= ~PERM;
+ (yyvsp[(3) - (4)])->nexti->nexti->memory->flags |= MALLOC;
+ unref((yyvsp[(3) - (4)])->nexti->nexti->memory); /* Node_val */
+ bcfree((yyvsp[(3) - (4)])->nexti->nexti); /* Op_push_i */
+ bcfree((yyvsp[(3) - (4)])->nexti); /* Op_list */
+ bcfree((yyvsp[(3) - (4)])); /* Op_list */
+ } else {
+ if (do_lint && (rule == BEGIN || rule == END) && ! warned) {
+ warned = TRUE;
+ lintwarn(
+ _("plain `print' in BEGIN or END rule should probably be `print \"\"'"));
+ }
+ }
- if (do_lint && (yyvsp[(3) - (4)].nodeval) == NULL && begin_or_end_rule && ! warned) {
- warned = TRUE;
- lintwarn(
- _("plain `print' in BEGIN or END rule should probably be `print \"\"'"));
+ (yyvsp[(1) - (4)])->expr_count = 0;
+ (yyvsp[(1) - (4)])->opcode = Op_K_print_rec;
+ if ((yyvsp[(4) - (4)]) == NULL) { /* no redircetion */
+ (yyvsp[(1) - (4)])->redir_type = 0;
+ (yyval) = list_create((yyvsp[(1) - (4)]));
+ } else {
+ INSTRUCTION *ip;
+ ip = (yyvsp[(4) - (4)])->nexti;
+ (yyvsp[(1) - (4)])->redir_type = ip->redir_type;
+ (yyvsp[(4) - (4)])->nexti = ip->nexti;
+ bcfree(ip);
+ (yyval) = list_append((yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]));
}
} else {
- (yyval.nodeval) = node((yyvsp[(3) - (4)].nodeval), (yyvsp[(1) - (4)].nodetypeval), (yyvsp[(4) - (4)].nodeval));
- if ((yyval.nodeval)->type == Node_K_printf)
- count_args((yyval.nodeval));
+ /* -----------------
+ * [ output_redir ]
+ * [ redirect exp ]
+ * -----------------
+ * [ expression_list ]
+ * ------------------
+ * [$1 | NULL | redir_type | expr_count]
+ *
+ */
+
+ if ((yyvsp[(4) - (4)]) == NULL) { /* no redirection */
+ if ((yyvsp[(3) - (4)]) == NULL) { /* printf without arg */
+ (yyvsp[(1) - (4)])->expr_count = 0;
+ (yyvsp[(1) - (4)])->redir_type = 0;
+ (yyval) = list_create((yyvsp[(1) - (4)]));
+ } else {
+ INSTRUCTION *t = (yyvsp[(3) - (4)]);
+ (yyvsp[(1) - (4)])->expr_count = count_expressions(&t, FALSE);
+ (yyvsp[(1) - (4)])->redir_type = 0;
+ (yyval) = list_append(t, (yyvsp[(1) - (4)]));
+ }
+ } else {
+ INSTRUCTION *ip;
+ ip = (yyvsp[(4) - (4)])->nexti;
+ (yyvsp[(1) - (4)])->redir_type = ip->redir_type;
+ (yyvsp[(4) - (4)])->nexti = ip->nexti;
+ bcfree(ip);
+ if ((yyvsp[(3) - (4)]) == NULL) {
+ (yyvsp[(1) - (4)])->expr_count = 0;
+ (yyval) = list_append((yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]));
+ } else {
+ INSTRUCTION *t = (yyvsp[(3) - (4)]);
+ (yyvsp[(1) - (4)])->expr_count = count_expressions(&t, FALSE);
+ (yyval) = list_append(list_merge((yyvsp[(4) - (4)]), t), (yyvsp[(1) - (4)]));
+ }
+ }
}
}
break;
- case 52:
+ case 59:
/* Line 1455 of yacc.c */
-#line 579 "awkgram.y"
- { (yyval.nodeval) = node(variable((yyvsp[(2) - (5)].sval), CAN_FREE, Node_var_array), Node_K_delete, (yyvsp[(4) - (5)].nodeval)); }
+#line 916 "awkgram.y"
+ { sub_counter = 0; }
break;
- case 53:
+ case 60:
/* Line 1455 of yacc.c */
-#line 581 "awkgram.y"
+#line 917 "awkgram.y"
{
- static short warned = FALSE;
+ char *arr = (yyvsp[(2) - (4)])->lextok;
- if (do_lint && ! warned) {
- warned = TRUE;
- 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[(2) - (2)].sval), CAN_FREE, Node_var_array), Node_K_delete, (NODE *) NULL);
+ (yyvsp[(2) - (4)])->opcode = Op_push_array;
+ (yyvsp[(2) - (4)])->memory = variable(arr, Node_var_array);
+
+ if ((yyvsp[(4) - (4)]) == NULL) {
+ static short warned = FALSE;
+ if (do_lint && ! warned) {
+ warned = TRUE;
+ 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"));
+ }
+ (yyvsp[(1) - (4)])->expr_count = 0;
+ (yyval) = list_append(list_create((yyvsp[(2) - (4)])), (yyvsp[(1) - (4)]));
+ } else {
+ (yyvsp[(1) - (4)])->expr_count = sub_counter;
+ (yyval) = list_append(list_append((yyvsp[(4) - (4)]), (yyvsp[(2) - (4)])), (yyvsp[(1) - (4)]));
}
+ }
break;
- case 54:
+ case 61:
/* Line 1455 of yacc.c */
-#line 599 "awkgram.y"
+#line 949 "awkgram.y"
{
- /*
- * this is for tawk compatibility. maybe the warnings
- * should always be done.
- */
- static short warned = FALSE;
+ static short warned = FALSE;
+ char *arr = (yyvsp[(3) - (4)])->lextok;
- if (do_lint && ! warned) {
+ if (do_lint && ! warned) {
warned = TRUE;
lintwarn(_("`delete(array)' is a non-portable tawk extension"));
- }
- if (do_traditional) {
+ }
+ if (do_traditional) {
/*
* can't use yyerror, since may have overshot
- * the source line
+ * the source line.
*/
errcount++;
error(_("`delete(array)' is a non-portable tawk extension"));
- }
- (yyval.nodeval) = node(variable((yyvsp[(3) - (4)].sval), CAN_FREE, Node_var_array), Node_K_delete, (NODE *) NULL);
}
+ (yyvsp[(3) - (4)])->memory = variable(arr, Node_var_array);
+ (yyvsp[(3) - (4)])->opcode = Op_push_array;
+ (yyvsp[(1) - (4)])->expr_count = 0;
+ (yyval) = list_append(list_create((yyvsp[(3) - (4)])), (yyvsp[(1) - (4)]));
+ }
break;
- case 55:
+ case 62:
/* Line 1455 of yacc.c */
-#line 621 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 971 "awkgram.y"
+ { (yyval) = optimize_assignment((yyvsp[(1) - (1)])); }
break;
- case 56:
+ case 63:
/* Line 1455 of yacc.c */
-#line 626 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 976 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 57:
+ case 64:
/* Line 1455 of yacc.c */
-#line 628 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 978 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
- case 58:
+ case 65:
/* Line 1455 of yacc.c */
-#line 633 "awkgram.y"
+#line 983 "awkgram.y"
{
- if ((yyvsp[(1) - (1)].nodeval) == NULL) {
- (yyval.nodeval) = NULL;
- } else {
- NODE *dflt = NULL;
- NODE *head = (yyvsp[(1) - (1)].nodeval);
- NODE *curr;
-
- const char **case_values = NULL;
-
- int maxcount = 128;
- int case_count = 0;
- int i;
-
- emalloc(case_values, const char **, sizeof(char*) * maxcount, "switch_body");
- for (curr = (yyvsp[(1) - (1)].nodeval); curr != NULL; curr = curr->rnode) {
- /* Assure that case statement values are unique. */
- if (curr->lnode->type == Node_K_case) {
- char *caseval;
-
- if (curr->lnode->lnode->type == Node_regex)
- caseval = curr->lnode->lnode->re_exp->stptr;
- else
- caseval = force_string(tree_eval(curr->lnode->lnode))->stptr;
-
- for (i = 0; i < case_count; i++)
- if (strcmp(caseval, case_values[i]) == 0)
- yyerror(_("duplicate case values in switch body: %s"), caseval);
-
- if (case_count >= maxcount) {
- maxcount += 128;
- erealloc(case_values, const char **, sizeof(char*) * maxcount, "switch_body");
+ INSTRUCTION *dflt = NULL;
+
+ if ((yyvsp[(1) - (1)]) != NULL) {
+ INSTRUCTION *curr;
+ const char **case_values = NULL;
+ int maxcount = 128;
+ int case_count = 0;
+ int i;
+
+ emalloc(case_values, const char **, sizeof(char *) * maxcount, "statement");
+
+ for (curr = (yyvsp[(1) - (1)])->case_val->nexti; curr != NULL; curr = curr->nexti) {
+ if (curr->opcode == Op_K_case) {
+ char *caseval;
+ if (curr->memory->type == Node_regex)
+ caseval = curr->memory->re_exp->stptr;
+ else
+ caseval = force_string(curr->memory)->stptr;
+ for (i = 0; i < case_count; i++)
+ if (strcmp(caseval, case_values[i]) == 0)
+ yyerror(_("duplicate case values in switch body: %s"), caseval);
+
+ if (case_count >= maxcount) {
+ maxcount += 128;
+ erealloc(case_values, const char **, sizeof(char*) * maxcount, "statement");
+ }
+ case_values[case_count++] = caseval;
+ } else {
+ /* Otherwise save a pointer to the default node. */
+ if (dflt != NULL)
+ yyerror(_("duplicate `default' detected in switch body"));
+ dflt = curr;
}
- case_values[case_count++] = caseval;
- } else {
- /* Otherwise save a pointer to the default node. */
- if (dflt != NULL)
- yyerror(_("Duplicate `default' detected in switch body"));
- dflt = curr;
}
+
+ efree(case_values);
+ (yyval) = list_prepend((yyvsp[(1) - (1)])->case_stmt, instruction(Op_K_switch));
+ (yyval)->nexti->case_val = (yyvsp[(1) - (1)])->case_val->nexti;
+ (yyval)->nexti->switch_dflt = dflt;
+ bcfree((yyvsp[(1) - (1)])->case_val); /* Op_list */
+ bcfree((yyvsp[(1) - (1)])); /* Op_case_list */
+ } else {
+ (yyval) = list_create(instruction(Op_K_switch));
+ (yyval)->nexti->case_val = NULL;
+ (yyval)->nexti->switch_dflt = NULL;
}
-
- free(case_values);
-
- /* Create the switch body. */
- (yyval.nodeval) = node(head, Node_switch_body, dflt);
}
- }
break;
- case 59:
+ case 66:
/* Line 1455 of yacc.c */
-#line 685 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1035 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 60:
+ case 67:
/* Line 1455 of yacc.c */
-#line 687 "awkgram.y"
+#line 1037 "awkgram.y"
{
- if ((yyvsp[(2) - (2)].nodeval) == NULL)
- (yyval.nodeval) = (yyvsp[(1) - (2)].nodeval);
- else {
- if (do_lint && isnoeffect((yyvsp[(2) - (2)].nodeval)->type))
- lintwarn(_("statement may have no effect"));
- if ((yyvsp[(1) - (2)].nodeval) == NULL)
- (yyval.nodeval) = node((yyvsp[(2) - (2)].nodeval), Node_case_list, (NODE *) NULL);
- else
- (yyval.nodeval) = append_right(
- ((yyvsp[(1) - (2)].nodeval)->type == Node_case_list ? (yyvsp[(1) - (2)].nodeval) : node((yyvsp[(1) - (2)].nodeval), Node_case_list, (NODE *) NULL)),
- ((yyvsp[(2) - (2)].nodeval)->type == Node_case_list ? (yyvsp[(2) - (2)].nodeval) : node((yyvsp[(2) - (2)].nodeval), Node_case_list, (NODE *) NULL))
- );
+ if ((yyvsp[(1) - (2)]) == NULL) {
+ (yyvsp[(2) - (2)])->case_val = list_create((yyvsp[(2) - (2)])->case_val);
+ (yyval) = (yyvsp[(2) - (2)]);
+ } else {
+ (void) list_append((yyvsp[(1) - (2)])->case_val, (yyvsp[(2) - (2)])->case_val);
+ (void) list_merge((yyvsp[(1) - (2)])->case_stmt, (yyvsp[(2) - (2)])->case_stmt);
+ bcfree((yyvsp[(2) - (2)])); /* Op_case_list */
+ (yyval) = (yyvsp[(1) - (2)]);
}
- yyerrok;
}
break;
- case 61:
-
-/* Line 1455 of yacc.c */
-#line 704 "awkgram.y"
- { (yyval.nodeval) = NULL; }
- break;
-
- case 62:
-
-/* Line 1455 of yacc.c */
-#line 709 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (5)].nodeval), Node_K_case, (yyvsp[(5) - (5)].nodeval)); }
- break;
-
- case 63:
-
-/* Line 1455 of yacc.c */
-#line 711 "awkgram.y"
- { (yyval.nodeval) = node((NODE *) NULL, Node_K_default, (yyvsp[(4) - (4)].nodeval)); }
- break;
-
- case 64:
+ case 68:
/* Line 1455 of yacc.c */
-#line 716 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1049 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 65:
+ case 69:
/* Line 1455 of yacc.c */
-#line 718 "awkgram.y"
+#line 1054 "awkgram.y"
{
- (yyvsp[(2) - (2)].nodeval)->numbr = -(force_number((yyvsp[(2) - (2)].nodeval)));
- (yyval.nodeval) = (yyvsp[(2) - (2)].nodeval);
+ INSTRUCTION *casestmt = (yyvsp[(5) - (5)]);
+
+ (yyvsp[(1) - (5)])->memory = (yyvsp[(2) - (5)])->memory;
+ bcfree((yyvsp[(2) - (5)]));
+ if ((yyvsp[(5) - (5)]) == NULL)
+ casestmt = list_create(instruction(Op_no_op));
+ if (do_profiling)
+ (void) list_prepend(casestmt, instruction(Op_exec_count));
+
+ (yyvsp[(1) - (5)])->target_stmt = casestmt->nexti;
+
+ /* recycle $3 as Op_case_list */
+ (yyvsp[(3) - (5)])->opcode = Op_case_list;
+ (yyvsp[(3) - (5)])->case_val = (yyvsp[(1) - (5)]); /* Op_K_case */
+ (yyvsp[(3) - (5)])->case_stmt = casestmt; /* Op_list */
+ (yyval) = (yyvsp[(3) - (5)]);
}
break;
- case 66:
-
-/* Line 1455 of yacc.c */
-#line 723 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(2) - (2)].nodeval); }
- break;
-
- case 67:
+ case 70:
/* Line 1455 of yacc.c */
-#line 725 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1073 "awkgram.y"
+ {
+ INSTRUCTION *casestmt = (yyvsp[(4) - (4)]);
+
+ if ((yyvsp[(4) - (4)]) == NULL)
+ casestmt = list_create(instruction(Op_no_op));
+ if (do_profiling)
+ (void) list_prepend(casestmt, instruction(Op_exec_count));
+
+ (yyvsp[(1) - (4)])->target_stmt = casestmt->nexti;
+ (yyvsp[(2) - (4)])->opcode = Op_case_list;
+ (yyvsp[(2) - (4)])->case_val = (yyvsp[(1) - (4)]); /* Op_K_default */
+ (yyvsp[(2) - (4)])->case_stmt = casestmt; /* Op_list */
+ (yyval) = (yyvsp[(2) - (4)]);
+ }
break;
- case 68:
+ case 71:
/* Line 1455 of yacc.c */
-#line 727 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1091 "awkgram.y"
+ {
+ (yyvsp[(1) - (1)])->opcode = Op_K_case;
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
break;
case 72:
/* Line 1455 of yacc.c */
-#line 742 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (5)].nodeval), Node_expression_list, (yyvsp[(4) - (5)].nodeval)); }
+#line 1096 "awkgram.y"
+ {
+ (yyvsp[(2) - (2)])->memory->numbr = -(force_number((yyvsp[(2) - (2)])->memory));
+ bcfree((yyvsp[(1) - (2)]));
+ (yyvsp[(2) - (2)])->opcode = Op_K_case;
+ (yyval) = (yyvsp[(2) - (2)]);
+ }
break;
case 73:
/* Line 1455 of yacc.c */
-#line 747 "awkgram.y"
+#line 1103 "awkgram.y"
{
- in_print = FALSE;
- in_parens = 0;
- (yyval.nodeval) = NULL;
+ bcfree((yyvsp[(1) - (2)]));
+ (yyvsp[(2) - (2)])->opcode = Op_K_case;
+ (yyval) = (yyvsp[(2) - (2)]);
}
break;
case 74:
/* Line 1455 of yacc.c */
-#line 752 "awkgram.y"
- { in_print = FALSE; in_parens = 0; }
+#line 1109 "awkgram.y"
+ {
+ (yyvsp[(1) - (1)])->opcode = Op_K_case;
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
break;
case 75:
/* Line 1455 of yacc.c */
-#line 753 "awkgram.y"
+#line 1114 "awkgram.y"
{
- (yyval.nodeval) = node((yyvsp[(3) - (3)].nodeval), (yyvsp[(1) - (3)].nodetypeval), (NODE *) NULL);
- if ((yyvsp[(1) - (3)].nodetypeval) == Node_redirect_twoway
- && (yyvsp[(3) - (3)].nodeval)->type == Node_K_getline
- && (yyvsp[(3) - (3)].nodeval)->rnode != NULL
- && (yyvsp[(3) - (3)].nodeval)->rnode->type == Node_redirect_twoway)
- yyerror(_("multistage two-way pipelines don't work"));
+ (yyvsp[(1) - (1)])->opcode = Op_K_case;
+ (yyval) = (yyvsp[(1) - (1)]);
}
break;
case 76:
/* Line 1455 of yacc.c */
-#line 765 "awkgram.y"
- {
- (yyval.nodeval) = node((yyvsp[(3) - (6)].nodeval), Node_K_if,
- node((yyvsp[(6) - (6)].nodeval), Node_if_branches, (NODE *) NULL));
- }
+#line 1122 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 77:
/* Line 1455 of yacc.c */
-#line 771 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(3) - (9)].nodeval), Node_K_if,
- node((yyvsp[(6) - (9)].nodeval), Node_if_branches, (yyvsp[(9) - (9)].nodeval))); }
+#line 1124 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
- case 82:
+ case 79:
/* Line 1455 of yacc.c */
-#line 787 "awkgram.y"
- { (yyval.nodeval) = NULL; }
- break;
-
- case 83:
-
-/* Line 1455 of yacc.c */
-#line 789 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (2)].nodeval), Node_redirect_input, (NODE *) NULL); }
+#line 1134 "awkgram.y"
+ {
+ (yyval) = (yyvsp[(2) - (3)]);
+ }
break;
- case 84:
+ case 80:
/* Line 1455 of yacc.c */
-#line 794 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1141 "awkgram.y"
+ {
+ in_print = FALSE;
+ in_parens = 0;
+ (yyval) = NULL;
+ }
break;
- case 85:
+ case 81:
/* Line 1455 of yacc.c */
-#line 796 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1146 "awkgram.y"
+ { in_print = FALSE; in_parens = 0; }
break;
- case 86:
+ case 82:
/* Line 1455 of yacc.c */
-#line 801 "awkgram.y"
- { (yyval.nodeval) = make_param((yyvsp[(1) - (1)].sval)); }
+#line 1147 "awkgram.y"
+ {
+ if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway
+ && (yyvsp[(3) - (3)])->lasti->opcode == Op_K_getline_redir
+ && (yyvsp[(3) - (3)])->lasti->redir_type == redirect_twoway)
+ yyerror(_("multistage two-way pipelines don't work"));
+ (yyval) = list_prepend((yyvsp[(3) - (3)]), (yyvsp[(1) - (3)]));
+ }
break;
- case 87:
+ case 83:
/* Line 1455 of yacc.c */
-#line 803 "awkgram.y"
- { (yyval.nodeval) = append_right((yyvsp[(1) - (3)].nodeval), make_param((yyvsp[(3) - (3)].sval))); yyerrok; }
+#line 1158 "awkgram.y"
+ {
+ (yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), (yyvsp[(6) - (6)]), NULL, NULL);
+ }
break;
- case 88:
+ case 84:
/* Line 1455 of yacc.c */
-#line 805 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1163 "awkgram.y"
+ {
+ (yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), (yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)]));
+ }
break;
case 89:
/* Line 1455 of yacc.c */
-#line 807 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1180 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 90:
/* Line 1455 of yacc.c */
-#line 809 "awkgram.y"
- { (yyval.nodeval) = NULL; }
- break;
-
- case 91:
-
-/* Line 1455 of yacc.c */
-#line 815 "awkgram.y"
- { (yyval.nodeval) = NULL; }
- break;
-
- case 92:
-
-/* Line 1455 of yacc.c */
-#line 817 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1182 "awkgram.y"
+ {
+ bcfree((yyvsp[(1) - (2)]));
+ (yyval) = (yyvsp[(2) - (2)]);
+ }
break;
case 93:
/* Line 1455 of yacc.c */
-#line 822 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1195 "awkgram.y"
+ {
+ append_param((yyvsp[(1) - (1)])->lextok);
+ (yyvsp[(1) - (1)])->lextok = NULL;
+ bcfree((yyvsp[(1) - (1)]));
+ }
break;
case 94:
/* Line 1455 of yacc.c */
-#line 824 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1201 "awkgram.y"
+ {
+ append_param((yyvsp[(3) - (3)])->lextok);
+ (yyvsp[(3) - (3)])->lextok = NULL;
+ bcfree((yyvsp[(3) - (3)]));
+ yyerrok;
+ }
break;
case 95:
/* Line 1455 of yacc.c */
-#line 829 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (1)].nodeval), Node_expression_list, (NODE *) NULL); }
+#line 1208 "awkgram.y"
+ { /* func_params = NULL; */ }
break;
case 96:
/* Line 1455 of yacc.c */
-#line 831 "awkgram.y"
- {
- (yyval.nodeval) = append_right((yyvsp[(1) - (3)].nodeval),
- node((yyvsp[(3) - (3)].nodeval), Node_expression_list, (NODE *) NULL));
- yyerrok;
- }
+#line 1210 "awkgram.y"
+ { /* func_params = NULL; */ }
break;
case 97:
/* Line 1455 of yacc.c */
-#line 837 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1212 "awkgram.y"
+ { /* func_params = NULL; */ }
break;
case 98:
/* Line 1455 of yacc.c */
-#line 839 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1218 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 99:
/* Line 1455 of yacc.c */
-#line 841 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1220 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 100:
/* Line 1455 of yacc.c */
-#line 843 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1225 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 101:
/* Line 1455 of yacc.c */
-#line 848 "awkgram.y"
- {
- if (do_lint && (yyvsp[(3) - (3)].nodeval)->type == Node_regex)
- lintwarn(_("regular expression on right of assignment"));
- (yyval.nodeval) = optimize_concat((yyvsp[(1) - (3)].nodeval), (yyvsp[(2) - (3)].nodetypeval), (yyvsp[(3) - (3)].nodeval));
- }
+#line 1227 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 102:
/* Line 1455 of yacc.c */
-#line 854 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_and, (yyvsp[(3) - (3)].nodeval)); }
+#line 1232 "awkgram.y"
+ { (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); }
break;
case 103:
/* Line 1455 of yacc.c */
-#line 856 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_or, (yyvsp[(3) - (3)].nodeval)); }
+#line 1234 "awkgram.y"
+ {
+ (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
+ yyerrok;
+ }
break;
case 104:
/* Line 1455 of yacc.c */
-#line 858 "awkgram.y"
- {
- if ((yyvsp[(1) - (3)].nodeval)->type == Node_regex)
- warning(_("regular expression on left of `~' or `!~' operator"));
- (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), (yyvsp[(2) - (3)].nodetypeval), mk_rexp((yyvsp[(3) - (3)].nodeval)));
- }
+#line 1239 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 105:
/* Line 1455 of yacc.c */
-#line 864 "awkgram.y"
- {
- if (do_lint_old)
- warning(_("old awk does not support the keyword `in' except after `for'"));
- (yyval.nodeval) = node(variable((yyvsp[(3) - (3)].sval), CAN_FREE, Node_var_array), Node_in_array, (yyvsp[(1) - (3)].nodeval));
- }
+#line 1241 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 106:
/* Line 1455 of yacc.c */
-#line 870 "awkgram.y"
- {
- if (do_lint && (yyvsp[(3) - (3)].nodeval)->type == Node_regex)
- lintwarn(_("regular expression on right of comparison"));
- (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), (yyvsp[(2) - (3)].nodetypeval), (yyvsp[(3) - (3)].nodeval));
- }
+#line 1243 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 107:
/* Line 1455 of yacc.c */
-#line 876 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (5)].nodeval), Node_cond_exp, node((yyvsp[(3) - (5)].nodeval), Node_if_branches, (yyvsp[(5) - (5)].nodeval)));}
+#line 1245 "awkgram.y"
+ { (yyval) = NULL; }
break;
case 108:
/* Line 1455 of yacc.c */
-#line 878 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1251 "awkgram.y"
+ {
+ if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
+ lintwarn(_("regular expression on right of assignment"));
+ (yyval) = mk_assignment((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)]));
+ }
break;
case 109:
/* Line 1455 of yacc.c */
-#line 883 "awkgram.y"
- { (yyval.nodetypeval) = (yyvsp[(1) - (1)].nodetypeval); }
+#line 1257 "awkgram.y"
+ { (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 110:
/* Line 1455 of yacc.c */
-#line 885 "awkgram.y"
- { (yyval.nodetypeval) = (yyvsp[(1) - (1)].nodetypeval); }
+#line 1259 "awkgram.y"
+ { (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 111:
/* Line 1455 of yacc.c */
-#line 887 "awkgram.y"
- { (yyval.nodetypeval) = Node_assign_quotient; }
+#line 1261 "awkgram.y"
+ {
+ if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec)
+ warning(_("regular expression on left of `~' or `!~' operator"));
+
+ if ((yyvsp[(3) - (3)])->lasti == (yyvsp[(3) - (3)])->nexti && (yyvsp[(3) - (3)])->nexti->opcode == Op_match_rec) {
+ (yyvsp[(2) - (3)])->memory = (yyvsp[(3) - (3)])->nexti->memory;
+ bcfree((yyvsp[(3) - (3)])->nexti); /* Op_match_rec */
+ bcfree((yyvsp[(3) - (3)])); /* Op_list */
+ (yyval) = list_append((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]));
+ } else {
+ (yyvsp[(2) - (3)])->memory = make_regnode(Node_dynregex, NULL);
+ (yyval) = list_append(list_merge((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])), (yyvsp[(2) - (3)]));
+ }
+ }
break;
case 112:
/* Line 1455 of yacc.c */
-#line 892 "awkgram.y"
- { (yyval.nodetypeval) = (yyvsp[(1) - (1)].nodetypeval); }
+#line 1276 "awkgram.y"
+ {
+ if (do_lint_old)
+ warning(_("old awk does not support the keyword `in' except after `for'"));
+ (yyvsp[(3) - (3)])->nexti->opcode = Op_push_array;
+ (yyvsp[(2) - (3)])->opcode = Op_in_array;
+ (yyvsp[(2) - (3)])->expr_count = 1;
+ (yyval) = list_append(list_merge((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])), (yyvsp[(2) - (3)]));
+ }
break;
case 113:
/* Line 1455 of yacc.c */
-#line 894 "awkgram.y"
- { (yyval.nodetypeval) = Node_less; }
+#line 1285 "awkgram.y"
+ {
+ if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec)
+ lintwarn(_("regular expression on right of comparison"));
+ (yyval) = list_append(list_merge((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])), (yyvsp[(2) - (3)]));
+ }
+ break;
+
+ case 114:
+
+/* Line 1455 of yacc.c */
+#line 1291 "awkgram.y"
+ { (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), (yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); }
break;
case 115:
/* Line 1455 of yacc.c */
-#line 899 "awkgram.y"
- { (yyval.nodetypeval) = Node_greater; }
+#line 1293 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 116:
/* Line 1455 of yacc.c */
-#line 904 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1298 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 117:
/* Line 1455 of yacc.c */
-#line 906 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1300 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 118:
/* Line 1455 of yacc.c */
-#line 908 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (2)].nodeval), Node_concat, (yyvsp[(2) - (2)].nodeval)); }
+#line 1302 "awkgram.y"
+ {
+ (yyvsp[(2) - (2)])->opcode = Op_assign_quotient;
+ (yyval) = (yyvsp[(2) - (2)]);
+ }
+ break;
+
+ case 119:
+
+/* Line 1455 of yacc.c */
+#line 1310 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 120:
/* Line 1455 of yacc.c */
-#line 915 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_exp, (yyvsp[(3) - (3)].nodeval)); }
+#line 1312 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 121:
/* Line 1455 of yacc.c */
-#line 917 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_times, (yyvsp[(3) - (3)].nodeval)); }
+#line 1317 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 122:
/* Line 1455 of yacc.c */
-#line 919 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_quotient, (yyvsp[(3) - (3)].nodeval)); }
+#line 1319 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 123:
/* Line 1455 of yacc.c */
-#line 921 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_mod, (yyvsp[(3) - (3)].nodeval)); }
+#line 1324 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 124:
/* Line 1455 of yacc.c */
-#line 923 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_plus, (yyvsp[(3) - (3)].nodeval)); }
+#line 1326 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
case 125:
/* Line 1455 of yacc.c */
-#line 925 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(1) - (3)].nodeval), Node_minus, (yyvsp[(3) - (3)].nodeval)); }
- break;
-
- case 126:
-
-/* Line 1455 of yacc.c */
-#line 927 "awkgram.y"
+#line 1328 "awkgram.y"
{
- /*
- * In BEGINFILE/ENDFILE, allow `getline var < file'
- */
- if (beginfile_or_endfile_rule) {
- if ((yyvsp[(2) - (3)].nodeval) != NULL && (yyvsp[(3) - (3)].nodeval) != NULL)
- ; /* all ok */
- else {
- if ((yyvsp[(2) - (3)].nodeval) != NULL)
- fatal(_("`getline var' invalid inside %s rule"),
- parsing_endfile_rule ? "ENDFILE" : "BEGINFILE");
- else
- fatal(_("`getline' invalid inside %s rule"),
- parsing_endfile_rule ? "ENDFILE" : "BEGINFILE");
- }
- }
- if (do_lint && parsing_end_rule && (yyvsp[(3) - (3)].nodeval) == NULL)
- lintwarn(_("non-redirected `getline' undefined inside END action"));
- (yyval.nodeval) = node((yyvsp[(2) - (3)].nodeval), Node_K_getline, (yyvsp[(3) - (3)].nodeval));
+ int count = 2;
+ int is_simple_var = FALSE;
+ INSTRUCTION *ip1, *ip2;
+
+ if ((yyvsp[(1) - (2)])->lasti->opcode == Op_concat) {
+ /* multiple (> 2) adjacent strings optimization */
+ is_simple_var = ((yyvsp[(1) - (2)])->lasti->concat_flag & CSVAR);
+ count = (yyvsp[(1) - (2)])->lasti->expr_count + 1;
+ (yyvsp[(1) - (2)])->lasti->opcode = Op_no_op;
+ } else {
+ is_simple_var = ((yyvsp[(1) - (2)])->nexti->opcode == Op_push
+ && (yyvsp[(1) - (2)])->lasti == (yyvsp[(1) - (2)])->nexti); /* first exp. is a simple
+ * variable?; kludge for use
+ * in Op_assign_concat.
+ */
+ }
+ ip1 = (yyvsp[(1) - (2)])->nexti;
+ ip2 = (yyvsp[(2) - (2)])->nexti;
+ if (ip1->memory != NULL && ip1->memory->type == Node_val && ip1 == (yyvsp[(1) - (2)])->lasti
+ && ip2->memory != NULL && ip2->memory->type == Node_val && ip2 == (yyvsp[(2) - (2)])->lasti && do_optimize > 1){
+ size_t nlen;
+
+ ip1->memory = force_string(ip1->memory);
+ ip2->memory = force_string(ip2->memory);
+ nlen = ip1->memory->stlen + ip2->memory->stlen;
+ erealloc(ip1->memory->stptr, char *, nlen + 2, "constant fold");
+ memcpy(ip1->memory->stptr + ip1->memory->stlen, ip2->memory->stptr, ip2->memory->stlen);
+ ip1->memory->stlen = nlen;
+ ip1->memory->stptr[nlen] = '\0';
+ ip1->memory->flags &= ~(NUMCUR|NUMBER);
+ ip1->memory->flags |= (STRING|STRCUR);
+ bcfree((yyvsp[(2) - (2)]));
+ bcfree(ip2);
+ (yyvsp[(1) - (2)])->opcode = Op_push_i;
+ (yyval) = (yyvsp[(1) - (2)]);
+ } else {
+ (yyval) = list_append(list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])), instruction(Op_concat));
+ (yyval)->lasti->concat_flag = (is_simple_var ? CSVAR : 0);
+ (yyval)->lasti->expr_count = count;
+ if (count > max_args)
+ max_args = count;
}
+ }
break;
case 127:
/* Line 1455 of yacc.c */
-#line 948 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (2)].nodeval), Node_postincrement, (NODE *) NULL); }
+#line 1378 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 128:
/* Line 1455 of yacc.c */
-#line 950 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (2)].nodeval), Node_postdecrement, (NODE *) NULL); }
+#line 1380 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 129:
/* Line 1455 of yacc.c */
-#line 952 "awkgram.y"
- {
- if (do_lint_old) {
- warning(_("old awk does not support the keyword `in' except after `for'"));
- warning(_("old awk does not support multidimensional arrays"));
- }
- (yyval.nodeval) = node(variable((yyvsp[(5) - (5)].sval), CAN_FREE, Node_var_array), Node_in_array, (yyvsp[(2) - (5)].nodeval));
- }
+#line 1382 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 130:
/* Line 1455 of yacc.c */
-#line 965 "awkgram.y"
- {
- (yyval.nodeval) = node((yyvsp[(4) - (4)].nodeval), Node_K_getline,
- node((yyvsp[(1) - (4)].nodeval), (yyvsp[(2) - (4)].nodetypeval), (NODE *) NULL));
- }
+#line 1384 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 131:
/* Line 1455 of yacc.c */
-#line 970 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_exp, (yyvsp[(3) - (3)].nodeval)); }
+#line 1386 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 132:
/* Line 1455 of yacc.c */
-#line 972 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_times, (yyvsp[(3) - (3)].nodeval)); }
+#line 1388 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 133:
/* Line 1455 of yacc.c */
-#line 974 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_quotient, (yyvsp[(3) - (3)].nodeval)); }
+#line 1390 "awkgram.y"
+ {
+ /*
+ * In BEGINFILE/ENDFILE, allow `getline var < file'
+ */
+ if (rule == BEGINFILE || rule == ENDFILE) {
+ if ((yyvsp[(2) - (3)]) != NULL && (yyvsp[(3) - (3)]) != NULL)
+ ; /* all ok */
+ else {
+ if ((yyvsp[(2) - (3)]) != NULL)
+ yyerror(_("`getline var' invalid inside `%s' rule"), ruletab[rule]);
+ else
+ yyerror(_("`getline' invalid inside `%s' rule"), ruletab[rule]);
+ YYABORT;
+ }
+ }
+
+ if (do_lint && rule == END && (yyvsp[(3) - (3)]) == NULL)
+ lintwarn(_("non-redirected `getline' undefined inside END action"));
+ (yyval) = mk_getline((yyvsp[(1) - (3)]), (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)]), redirect_input);
+ }
break;
case 134:
/* Line 1455 of yacc.c */
-#line 976 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_mod, (yyvsp[(3) - (3)].nodeval)); }
+#line 1411 "awkgram.y"
+ {
+ (yyvsp[(2) - (2)])->opcode = Op_postincrement;
+ (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - (2)]));
+ }
break;
case 135:
/* Line 1455 of yacc.c */
-#line 978 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_plus, (yyvsp[(3) - (3)].nodeval)); }
+#line 1416 "awkgram.y"
+ {
+ (yyvsp[(2) - (2)])->opcode = Op_postdecrement;
+ (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - (2)]));
+ }
break;
case 136:
/* Line 1455 of yacc.c */
-#line 980 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(1) - (3)].nodeval), Node_minus, (yyvsp[(3) - (3)].nodeval)); }
+#line 1421 "awkgram.y"
+ {
+ if (do_lint_old) {
+ warning(_("old awk does not support the keyword `in' except after `for'"));
+ warning(_("old awk does not support multidimensional arrays"));
+ }
+ (yyvsp[(5) - (5)])->nexti->opcode = Op_push_array;
+ (yyvsp[(4) - (5)])->opcode = Op_in_array;
+ if ((yyvsp[(2) - (5)]) == NULL) { /* error */
+ errcount++;
+ (yyvsp[(4) - (5)])->expr_count = 0;
+ (yyval) = list_merge((yyvsp[(5) - (5)]), (yyvsp[(4) - (5)]));
+ } else {
+ INSTRUCTION *t = (yyvsp[(2) - (5)]);
+ (yyvsp[(4) - (5)])->expr_count = count_expressions(&t, FALSE);
+ (yyval) = list_append(list_merge(t, (yyvsp[(5) - (5)])), (yyvsp[(4) - (5)]));
+ }
+ }
break;
case 137:
/* Line 1455 of yacc.c */
-#line 985 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1444 "awkgram.y"
+ {
+ (yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type);
+ bcfree((yyvsp[(2) - (4)]));
+ }
break;
case 138:
/* Line 1455 of yacc.c */
-#line 987 "awkgram.y"
- { (yyval.nodeval) = constant_fold((yyvsp[(2) - (2)].nodeval), Node_not, (NODE *) NULL); }
+#line 1450 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 139:
/* Line 1455 of yacc.c */
-#line 989 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(2) - (3)].nodeval); }
+#line 1452 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 140:
/* Line 1455 of yacc.c */
-#line 992 "awkgram.y"
- { (yyval.nodeval) = snode((yyvsp[(3) - (4)].nodeval), Node_builtin, (int) (yyvsp[(1) - (4)].lval)); }
+#line 1454 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 141:
/* Line 1455 of yacc.c */
-#line 994 "awkgram.y"
- { (yyval.nodeval) = snode((yyvsp[(3) - (4)].nodeval), Node_builtin, (int) (yyvsp[(1) - (4)].lval)); }
+#line 1456 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
break;
case 142:
/* Line 1455 of yacc.c */
-#line 996 "awkgram.y"
- {
- static short warned1 = FALSE, warned2 = FALSE;
+#line 1458 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
+ break;
- if (do_lint && ! warned1) {
- warned1 = TRUE;
- lintwarn(_("call of `length' without parentheses is not portable"));
- }
- (yyval.nodeval) = snode((NODE *) NULL, Node_builtin, (int) (yyvsp[(1) - (1)].lval));
- if (do_posix && ! warned2) {
- warned2 = TRUE;
- warning(_("call of `length' without parentheses is deprecated by POSIX"));
- }
+ case 143:
+
+/* Line 1455 of yacc.c */
+#line 1460 "awkgram.y"
+ { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); }
+ break;
+
+ case 144:
+
+/* Line 1455 of yacc.c */
+#line 1465 "awkgram.y"
+ {
+ (yyval) = list_create((yyvsp[(1) - (1)]));
}
break;
case 145:
/* Line 1455 of yacc.c */
-#line 1012 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (2)].nodeval), Node_preincrement, (NODE *) NULL); }
+#line 1469 "awkgram.y"
+ {
+ if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) {
+ (yyvsp[(2) - (2)])->opcode = Op_nomatch;
+ (yyvsp[(1) - (2)])->opcode = Op_push_i;
+ (yyvsp[(1) - (2)])->memory = mk_number(0.0, (PERM|NUMCUR|NUMBER));
+ (yyval) = list_append(list_append(list_create((yyvsp[(1) - (2)])),
+ instruction(Op_field_spec)), (yyvsp[(2) - (2)]));
+ } else {
+ INSTRUCTION *ip;
+ ip = (yyvsp[(2) - (2)])->nexti;
+ if (ip->memory->type == Node_val && (yyvsp[(2) - (2)])->lasti == ip && do_optimize > 1) {
+ NODE *ret;
+ if ((ip->memory->flags & (STRCUR|STRING)) != 0) {
+ if (ip->memory->stlen == 0) {
+ ret = make_number((AWKNUM) 1.0);
+ } else {
+ ret = make_number((AWKNUM) 0.0);
+ }
+ } else {
+ if (ip->memory->numbr == 0) {
+ ret = make_number((AWKNUM) 1.0);
+ } else {
+ ret = make_number((AWKNUM) 0.0);
+ }
+ }
+ ret->flags &= ~MALLOC;
+ ret->flags |= PERM;
+ (yyvsp[(1) - (2)])->memory = ret;
+ (yyvsp[(1) - (2)])->opcode = Op_push_i;
+ bcfree(ip);
+ bcfree((yyvsp[(2) - (2)]));
+ (yyval) = list_create((yyvsp[(1) - (2)]));
+ } else {
+ (yyvsp[(1) - (2)])->opcode = Op_not;
+ add_lint((yyvsp[(2) - (2)]), LINT_assign_in_cond);
+ (yyval) = list_append((yyvsp[(2) - (2)]), (yyvsp[(1) - (2)]));
+ }
+ }
+ }
break;
case 146:
/* Line 1455 of yacc.c */
-#line 1014 "awkgram.y"
- { (yyval.nodeval) = node((yyvsp[(2) - (2)].nodeval), Node_predecrement, (NODE *) NULL); }
+#line 1509 "awkgram.y"
+ { (yyval) = (yyvsp[(2) - (3)]); }
break;
case 147:
/* Line 1455 of yacc.c */
-#line 1016 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1511 "awkgram.y"
+ {
+ (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
+ if ((yyval) == NULL)
+ YYABORT;
+ }
break;
case 148:
/* Line 1455 of yacc.c */
-#line 1018 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1517 "awkgram.y"
+ {
+ (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
+ if ((yyval) == NULL)
+ YYABORT;
+ }
break;
case 149:
/* Line 1455 of yacc.c */
-#line 1021 "awkgram.y"
+#line 1523 "awkgram.y"
{
- if ((yyvsp[(2) - (2)].nodeval)->type == Node_val && ((yyvsp[(2) - (2)].nodeval)->flags & (STRCUR|STRING)) == 0) {
- (yyvsp[(2) - (2)].nodeval)->numbr = -(force_number((yyvsp[(2) - (2)].nodeval)));
- (yyval.nodeval) = (yyvsp[(2) - (2)].nodeval);
- } else
- (yyval.nodeval) = node((yyvsp[(2) - (2)].nodeval), Node_unary_minus, (NODE *) NULL);
+ static short warned1 = FALSE;
+
+ if (do_lint && ! warned1) {
+ warned1 = TRUE;
+ lintwarn(_("call of `length' without parentheses is not portable"));
}
+ (yyval) = snode(NULL, (yyvsp[(1) - (1)]));
+ if ((yyval) == NULL)
+ YYABORT;
+ }
break;
- case 150:
+ case 152:
+
+/* Line 1455 of yacc.c */
+#line 1537 "awkgram.y"
+ {
+ (yyvsp[(1) - (2)])->opcode = Op_preincrement;
+ (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - (2)]));
+ }
+ break;
+
+ case 153:
+
+/* Line 1455 of yacc.c */
+#line 1542 "awkgram.y"
+ {
+ (yyvsp[(1) - (2)])->opcode = Op_predecrement;
+ (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - (2)]));
+ }
+ break;
+
+ case 154:
/* Line 1455 of yacc.c */
-#line 1029 "awkgram.y"
+#line 1547 "awkgram.y"
{
- /*
- * was: $$ = $2
- * POSIX semantics: force a conversion to numeric type
- */
- (yyval.nodeval) = node (make_number(0.0), Node_plus, (yyvsp[(2) - (2)].nodeval));
+ (yyval) = list_create((yyvsp[(1) - (1)]));
+ }
+ break;
+
+ case 155:
+
+/* Line 1455 of yacc.c */
+#line 1551 "awkgram.y"
+ {
+ (yyval) = list_create((yyvsp[(1) - (1)]));
+ }
+ break;
+
+ case 156:
+
+/* Line 1455 of yacc.c */
+#line 1555 "awkgram.y"
+ {
+ if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i
+ && ((yyvsp[(2) - (2)])->lasti->memory->flags & (STRCUR|STRING)) == 0) {
+ (yyvsp[(2) - (2)])->lasti->memory->numbr = -(force_number((yyvsp[(2) - (2)])->lasti->memory));
+ (yyval) = (yyvsp[(2) - (2)]);
+ bcfree((yyvsp[(1) - (2)]));
+ } else {
+ (yyvsp[(1) - (2)])->opcode = Op_unary_minus;
+ (yyval) = list_append((yyvsp[(2) - (2)]), (yyvsp[(1) - (2)]));
}
+ }
break;
- case 151:
+ case 157:
/* Line 1455 of yacc.c */
-#line 1040 "awkgram.y"
+#line 1567 "awkgram.y"
{
- func_use((yyvsp[(1) - (1)].nodeval)->rnode->stptr, FUNC_USE);
- (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval);
+ /*
+ * was: $$ = $2
+ * POSIX semantics: force a conversion to numeric type
+ */
+ (yyvsp[(1) - (2)])->opcode = Op_plus_i;
+ (yyvsp[(1) - (2)])->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
+ (yyval) = list_append((yyvsp[(2) - (2)]), (yyvsp[(1) - (2)]));
}
break;
- case 152:
+ case 158:
+
+/* Line 1455 of yacc.c */
+#line 1580 "awkgram.y"
+ {
+ func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE);
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
+ break;
+
+ case 159:
/* Line 1455 of yacc.c */
-#line 1045 "awkgram.y"
+#line 1585 "awkgram.y"
{
/* indirect function call */
+ INSTRUCTION *f, *t;
+ char *name;
+ NODE *indirect_var;
static short warned = FALSE;
+ const char *msg = _("indirect function calls are a gawk extension");
- if (do_lint && ! warned) {
+ if (do_traditional || do_posix)
+ yyerror("%s", msg);
+ else if (do_lint && ! warned) {
warned = TRUE;
- lintwarn(_("indirect function calls are a gawk extension"));
+ lintwarn("%s", msg);
}
+
+ f = (yyvsp[(2) - (2)])->lasti;
+ f->opcode = Op_indirect_func_call;
+ name = estrdup(f->func_name, strlen(f->func_name));
+ indirect_var = variable(name, Node_var_new);
+ if (is_std_var(name))
+ yyerror(_("can not use special variable `%s' for indirect function call"), name);
+ t = instruction(Op_push);
+ t->memory = indirect_var;
+
+ /* prepend indirect var instead of appending to arguments (opt_expression_list),
+ * and pop it off in setup_frame (eval.c) (left to right evaluation order); Test case:
+ * f = "fun"
+ * @f(f="real_fun")
+ */
- (yyval.nodeval) = (yyvsp[(2) - (2)].nodeval);
- (yyval.nodeval)->type = Node_indirect_func_call;
+ (yyval) = list_prepend((yyvsp[(2) - (2)]), t);
}
break;
- case 153:
+ case 160:
/* Line 1455 of yacc.c */
-#line 1061 "awkgram.y"
+#line 1621 "awkgram.y"
{
- (yyval.nodeval) = node((yyvsp[(3) - (4)].nodeval), Node_func_call, make_string((yyvsp[(1) - (4)].sval), strlen((yyvsp[(1) - (4)].sval))));
- (yyval.nodeval)->funcbody = NULL;
- param_sanity((yyvsp[(3) - (4)].nodeval));
- free((yyvsp[(1) - (4)].sval));
+ param_sanity((yyvsp[(3) - (4)]));
+ (yyvsp[(1) - (4)])->opcode = Op_func_call;
+ (yyvsp[(1) - (4)])->func_body = NULL;
+ if ((yyvsp[(3) - (4)]) == NULL) { /* no argument or error */
+ ((yyvsp[(1) - (4)]) + 1)->expr_count = 0;
+ (yyval) = list_create((yyvsp[(1) - (4)]));
+ } else {
+ INSTRUCTION *t = (yyvsp[(3) - (4)]);
+ ((yyvsp[(1) - (4)]) + 1)->expr_count = count_expressions(&t, TRUE);
+ (yyval) = list_append(t, (yyvsp[(1) - (4)]));
+ }
}
break;
- case 154:
+ case 161:
/* Line 1455 of yacc.c */
-#line 1071 "awkgram.y"
- { (yyval.nodeval) = NULL; }
+#line 1638 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 155:
+ case 162:
/* Line 1455 of yacc.c */
-#line 1073 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1640 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
break;
- case 156:
+ case 163:
/* Line 1455 of yacc.c */
-#line 1078 "awkgram.y"
- { (yyval.nodeval) = variable((yyvsp[(1) - (1)].sval), CAN_FREE, Node_var_new); }
+#line 1645 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 157:
+ case 164:
/* Line 1455 of yacc.c */
-#line 1080 "awkgram.y"
+#line 1647 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (2)]); }
+ break;
+
+ case 165:
+
+/* Line 1455 of yacc.c */
+#line 1652 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
+ break;
+
+ case 166:
+
+/* Line 1455 of yacc.c */
+#line 1654 "awkgram.y"
+ {
+ (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
+ }
+ break;
+
+ case 167:
+
+/* Line 1455 of yacc.c */
+#line 1661 "awkgram.y"
+ {
+ INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti;
+ int count = ip->sub_count; /* # of SUBSEP-seperated expressions */
+ if (count > 1) {
+ /* change Op_subscript or Op_sub_array to Op_concat */
+ ip->opcode = Op_concat;
+ ip->concat_flag = CSUBSEP;
+ ip->expr_count = count;
+ } else
+ ip->opcode = Op_no_op;
+ sub_counter++; /* count # of dimensions */
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
+ break;
+
+ case 168:
+
+/* Line 1455 of yacc.c */
+#line 1678 "awkgram.y"
+ {
+ INSTRUCTION *t = (yyvsp[(2) - (3)]);
+ if ((yyvsp[(2) - (3)]) == NULL) {
+ errcount++;
+ error(_("invalid subscript expression"));
+ /* install Null string as subscript. */
+ t = list_create(instruction(Op_push_i));
+ t->nexti->memory = Nnull_string;
+ (yyvsp[(3) - (3)])->sub_count = 1;
+ } else
+ (yyvsp[(3) - (3)])->sub_count = count_expressions(&t, FALSE);
+ (yyval) = list_append(t, (yyvsp[(3) - (3)]));
+ }
+ break;
+
+ case 169:
+
+/* Line 1455 of yacc.c */
+#line 1695 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); }
+ break;
+
+ case 170:
+
+/* Line 1455 of yacc.c */
+#line 1697 "awkgram.y"
+ {
+ (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
+ }
+ break;
+
+ case 171:
+
+/* Line 1455 of yacc.c */
+#line 1704 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (2)]); }
+ break;
+
+ case 172:
+
+/* Line 1455 of yacc.c */
+#line 1709 "awkgram.y"
+ {
+ char *var_name = (yyvsp[(1) - (1)])->lextok;
+
+ (yyvsp[(1) - (1)])->opcode = Op_push;
+ (yyvsp[(1) - (1)])->memory = variable(var_name, Node_var_new);
+ (yyval) = list_create((yyvsp[(1) - (1)]));
+ }
+ break;
+
+ case 173:
+
+/* Line 1455 of yacc.c */
+#line 1717 "awkgram.y"
{
NODE *n;
- if ((n = lookup((yyvsp[(1) - (4)].sval))) != NULL && ! isarray(n)) {
+ char *arr = (yyvsp[(1) - (2)])->lextok;
+ if ((n = lookup(arr)) != NULL && ! isarray(n))
yyerror(_("use of non-array as array"));
- (yyval.nodeval) = node(variable((yyvsp[(1) - (4)].sval), CAN_FREE, Node_var_array), Node_subscript, (yyvsp[(3) - (4)].nodeval));
- } else if ((yyvsp[(3) - (4)].nodeval) == NULL) {
- fatal(_("invalid subscript expression"));
- } else if ((yyvsp[(3) - (4)].nodeval)->rnode == NULL) {
- (yyval.nodeval) = node(variable((yyvsp[(1) - (4)].sval), CAN_FREE, Node_var_array), Node_subscript, (yyvsp[(3) - (4)].nodeval)->lnode);
- freenode((yyvsp[(3) - (4)].nodeval));
- } else
- (yyval.nodeval) = node(variable((yyvsp[(1) - (4)].sval), CAN_FREE, Node_var_array), Node_subscript, (yyvsp[(3) - (4)].nodeval));
+ (yyvsp[(1) - (2)])->memory = variable(arr, Node_var_array);
+ (yyvsp[(1) - (2)])->opcode = Op_push_array;
+ (yyval) = list_prepend((yyvsp[(2) - (2)]), (yyvsp[(1) - (2)]));
}
break;
- case 158:
+ case 174:
/* Line 1455 of yacc.c */
-#line 1094 "awkgram.y"
- { (yyval.nodeval) = (yyvsp[(1) - (1)].nodeval); }
+#line 1731 "awkgram.y"
+ {
+ INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti;
+ if (ip->opcode == Op_push
+ && ip->memory->type == Node_var
+ && ip->memory->var_update
+ ) {
+ (yyval) = list_prepend((yyvsp[(1) - (1)]), instruction(Op_var_update));
+ (yyval)->nexti->memory = ip->memory;
+ } else
+ (yyval) = (yyvsp[(1) - (1)]);
+ }
break;
- case 159:
+ case 175:
/* Line 1455 of yacc.c */
-#line 1105 "awkgram.y"
+#line 1743 "awkgram.y"
{
- NODE *n = node((yyvsp[(2) - (3)].nodeval), Node_field_spec, (NODE *) NULL);
- if ((yyvsp[(3) - (3)].sval) != NULL) {
- if ((yyvsp[(3) - (3)].sval)[0] == '+')
- (yyval.nodeval) = node(n, Node_postincrement, (NODE *) NULL);
- else
- (yyval.nodeval) = node(n, Node_postdecrement, (NODE *) NULL);
- } else {
- (yyval.nodeval) = n;
- }
+ (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
+ if ((yyvsp[(3) - (3)]) != NULL)
+ mk_assignment((yyvsp[(2) - (3)]), NULL, (yyvsp[(3) - (3)]));
}
break;
- case 160:
+ case 176:
/* Line 1455 of yacc.c */
-#line 1119 "awkgram.y"
- { (yyval.sval) = "+"; }
+#line 1752 "awkgram.y"
+ {
+ (yyvsp[(1) - (1)])->opcode = Op_postincrement;
+ }
break;
- case 161:
+ case 177:
/* Line 1455 of yacc.c */
-#line 1120 "awkgram.y"
- { (yyval.sval) = "-"; }
+#line 1756 "awkgram.y"
+ {
+ (yyvsp[(1) - (1)])->opcode = Op_postdecrement;
+ }
break;
- case 162:
+ case 178:
/* Line 1455 of yacc.c */
-#line 1121 "awkgram.y"
- { (yyval.sval) = NULL; }
+#line 1759 "awkgram.y"
+ { (yyval) = NULL; }
break;
- case 164:
+ case 180:
/* Line 1455 of yacc.c */
-#line 1129 "awkgram.y"
+#line 1767 "awkgram.y"
{ yyerrok; }
break;
- case 165:
+ case 181:
/* Line 1455 of yacc.c */
-#line 1133 "awkgram.y"
+#line 1771 "awkgram.y"
{ yyerrok; }
break;
- case 168:
+ case 184:
/* Line 1455 of yacc.c */
-#line 1142 "awkgram.y"
+#line 1780 "awkgram.y"
{ yyerrok; }
break;
- case 169:
+ case 185:
/* Line 1455 of yacc.c */
-#line 1146 "awkgram.y"
- { yyerrok; }
+#line 1784 "awkgram.y"
+ { (yyval) = (yyvsp[(1) - (1)]); yyerrok; }
break;
- case 170:
+ case 186:
/* Line 1455 of yacc.c */
-#line 1149 "awkgram.y"
+#line 1788 "awkgram.y"
{ yyerrok; }
break;
/* Line 1455 of yacc.c */
-#line 3487 "awkgram.c"
+#line 4231 "awkgram.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3695,14 +4427,14 @@ yyreturn:
/* Line 1675 of yacc.c */
-#line 1152 "awkgram.y"
+#line 1790 "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 */
+ const char *operator; /* text to match */
+ OPCODE value; /* 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 */
@@ -3710,7 +4442,9 @@ struct token {
# define NOT_POSIX 0x0200 /* feature not in POSIX */
# define GAWKX 0x0400 /* gawk extension */
# define RESX 0x0800 /* Bell Labs Research extension */
- NODE *(*ptr) P((NODE *)); /* function that implements this keyword */
+# define BREAK 0x1000 /* break allowed inside */
+# define CONTINUE 0x2000 /* continue allowed inside */
+ NODE *(*ptr)(int); /* function that implements this keyword */
};
#if 'a' == 0x81 /* it's EBCDIC */
@@ -3735,77 +4469,79 @@ tokcompare(void *l, void *r)
*/
static const struct token tokentab[] = {
-{"BEGIN", Node_illegal, LEX_BEGIN, 0, 0},
-{"BEGINFILE", Node_illegal, LEX_BEGINFILE, GAWKX, 0},
-{"END", Node_illegal, LEX_END, 0, 0},
-{"ENDFILE", Node_illegal, LEX_ENDFILE, GAWKX, 0},
+{"BEGIN", Op_rule, LEX_BEGIN, 0, 0},
+{"BEGINFILE", Op_rule, LEX_BEGINFILE, GAWKX, 0},
+{"END", Op_rule, LEX_END, 0, 0},
+{"ENDFILE", Op_rule, LEX_ENDFILE, GAWKX, 0},
#ifdef ARRAYDEBUG
-{"adump", Node_builtin, LEX_BUILTIN, GAWKX|A(1), do_adump},
+{"adump", Op_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},
-{"asorti", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_asorti},
-{"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},
-{"case", Node_K_case, LEX_CASE, GAWKX, 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},
-{"dcngettext", Node_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3)|A(4)|A(5), do_dcngettext},
-{"default", Node_K_default, LEX_DEFAULT, GAWKX, 0},
-{"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},
-{"patsplit", Node_builtin, LEX_BUILTIN, GAWKX|A(2)|A(3)|A(4), do_patsplit},
-{"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)|A(4), 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},
+{"and", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_and},
+{"asort", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_asort},
+{"asorti", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_asorti},
+{"atan2", Op_builtin, LEX_BUILTIN, NOT_OLD|A(2), do_atan2},
+{"bindtextdomain", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2), do_bindtextdomain},
+{"break", Op_K_break, LEX_BREAK, 0, 0},
+{"case", Op_K_case, LEX_CASE, GAWKX, 0},
+{"close", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1)|A(2), do_close},
+{"compl", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_compl},
+{"continue", Op_K_continue, LEX_CONTINUE, 0, 0},
+{"cos", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_cos},
+{"dcgettext", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_dcgettext},
+{"dcngettext", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3)|A(4)|A(5), do_dcngettext},
+{"default", Op_K_default, LEX_DEFAULT, GAWKX, 0},
+{"delete", Op_K_delete, LEX_DELETE, NOT_OLD, 0},
+{"do", Op_symbol, LEX_DO, NOT_OLD|BREAK|CONTINUE, 0},
+{"else", Op_K_else, LEX_ELSE, 0, 0},
+{"eval", Op_symbol, LEX_EVAL, 0, 0},
+{"exit", Op_K_exit, LEX_EXIT, 0, 0},
+{"exp", Op_builtin, LEX_BUILTIN, A(1), do_exp},
+{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_ext},
+{"fflush", Op_builtin, LEX_BUILTIN, RESX|A(0)|A(1), do_fflush},
+{"for", Op_symbol, LEX_FOR, BREAK|CONTINUE, 0},
+{"func", Op_func, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0},
+{"function",Op_func, LEX_FUNCTION, NOT_OLD, 0},
+{"gensub", Op_builtin, LEX_BUILTIN, GAWKX|A(3)|A(4), do_gensub},
+{"getline", Op_K_getline_redir, LEX_GETLINE, NOT_OLD, 0},
+{"gsub", Op_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_gsub},
+{"if", Op_K_if, LEX_IF, 0, 0},
+{"in", Op_symbol, LEX_IN, 0, 0},
+{"include", Op_symbol, LEX_INCLUDE, GAWKX, 0},
+{"index", Op_builtin, LEX_BUILTIN, A(2), do_index},
+{"int", Op_builtin, LEX_BUILTIN, A(1), do_int},
+{"length", Op_builtin, LEX_LENGTH, A(0)|A(1), do_length},
+{"log", Op_builtin, LEX_BUILTIN, A(1), do_log},
+{"lshift", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_lshift},
+{"match", Op_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_match},
+{"mktime", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_mktime},
+{"next", Op_K_next, LEX_NEXT, 0, 0},
+{"nextfile", Op_K_nextfile, LEX_NEXTFILE, GAWKX, 0},
+{"or", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_or},
+{"patsplit", Op_builtin, LEX_BUILTIN, GAWKX|A(2)|A(3)|A(4), do_patsplit},
+{"print", Op_K_print, LEX_PRINT, 0, 0},
+{"printf", Op_K_printf, LEX_PRINTF, 0, 0},
+{"rand", Op_builtin, LEX_BUILTIN, NOT_OLD|A(0), do_rand},
+{"return", Op_K_return, LEX_RETURN, NOT_OLD, 0},
+{"rshift", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_rshift},
+{"sin", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_sin},
+{"split", Op_builtin, LEX_BUILTIN, A(2)|A(3)|A(4), do_split},
+{"sprintf", Op_builtin, LEX_BUILTIN, 0, do_sprintf},
+{"sqrt", Op_builtin, LEX_BUILTIN, A(1), do_sqrt},
+{"srand", Op_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},
+{"stopme", Op_builtin, LEX_BUILTIN, GAWKX|A(0), stopme},
#endif
-{"strftime", Node_builtin, LEX_BUILTIN, GAWKX|A(0)|A(1)|A(2)|A(3), 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},
-{"switch", Node_K_switch, LEX_SWITCH, GAWKX, 0},
-{"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},
+{"strftime", Op_builtin, LEX_BUILTIN, GAWKX|A(0)|A(1)|A(2)|A(3), do_strftime},
+{"strtonum", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_strtonum},
+{"sub", Op_builtin, LEX_BUILTIN, NOT_OLD|A(2)|A(3), do_sub},
+{"substr", Op_builtin, LEX_BUILTIN, A(2)|A(3), do_substr},
+{"switch", Op_symbol, LEX_SWITCH, GAWKX|BREAK, 0},
+{"system", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_system},
+{"systime", Op_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime},
+{"tolower", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower},
+{"toupper", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper},
+{"while", Op_symbol, LEX_WHILE, BREAK|CONTINUE, 0},
+{"xor", Op_builtin, LEX_BUILTIN, GAWKX|A(2), do_xor},
};
#ifdef MBS_SUPPORT
@@ -3828,9 +4564,9 @@ static int cur_ring_idx;
/* getfname --- return name of a builtin function (for pretty printing) */
const char *
-getfname(register NODE *(*fptr)(NODE *))
+getfname(NODE *(*fptr)(int))
{
- register int i, j;
+ int i, j;
j = sizeof(tokentab) / sizeof(tokentab[0]);
/* linear search, no other way to do it */
@@ -3849,22 +4585,44 @@ getfname(register NODE *(*fptr)(NODE *))
*/
static void
-#ifdef CAN_USE_STDARG_H
- yyerror(const char *m, ...)
-#else
-/* VARARGS0 */
- yyerror(va_alist)
- va_dcl
-#endif
+yyerror(const char *m, ...)
{
va_list args;
const char *mesg = NULL;
- register char *bp, *cp;
+ char *bp, *cp;
char *scan;
char *buf;
int count;
static char end_of_file_line[] = "(END OF FILE)";
char save;
+ int saveline;
+ SRCFILE *s;
+
+ /* suppress current file name, line # from `.. included from ..' msgs */
+ saveline = sourceline;
+ sourceline = 0;
+
+ for (s = sourcefile; s->stype == SRC_INC; ) {
+ int line;
+ s = s->next;
+ if (s->fd <= INVALID_HANDLE)
+ continue;
+
+ line = s->srclines;
+ /* if last token is NEWLINE, line number is off by 1. */
+ if (s->lasttok == NEWLINE)
+ line--;
+
+ msg("%s %s:%d%c",
+ s->prev == sourcefile ? "In file included from"
+ : " from",
+ (s->stype == SRC_INC ||
+ s->stype == SRC_FILE) ? s->src : "cmd. line",
+ line,
+ s->stype == SRC_INC ? ',' : ':'
+ );
+ }
+ sourceline = saveline;
errcount++;
/* Find the current line in the input file */
@@ -3904,15 +4662,9 @@ static void
*bp = save;
-#ifdef CAN_USE_STDARG_H
va_start(args, m);
if (mesg == NULL)
mesg = m;
-#else
- va_start(args);
- if (mesg == NULL)
- mesg = va_arg(args, char *);
-#endif
count = (bp - thisline) + strlen(mesg) + 2 + 1;
emalloc(buf, char *, count, "yyerror");
@@ -3931,7 +4683,333 @@ static void
strcpy(bp, mesg);
err("", buf, args);
va_end(args);
- free(buf);
+ efree(buf);
+}
+
+/* mk_program --- create a single list of instructions */
+
+static INSTRUCTION *
+mk_program()
+{
+ INSTRUCTION *cp, *tmp;
+
+#define begin_block rule_block[BEGIN]
+#define end_block rule_block[END]
+#define prog_block rule_block[Rule]
+#define beginfile_block rule_block[BEGINFILE]
+#define endfile_block rule_block[ENDFILE]
+
+ if (end_block == NULL)
+ end_block = list_create(ip_end);
+ else
+ (void) list_prepend(end_block, ip_end);
+
+ if (get_context()->level > 0) {
+ if (begin_block != NULL && prog_block != NULL)
+ cp = list_merge(begin_block, prog_block);
+ else
+ cp = (begin_block != NULL) ? begin_block : prog_block;
+
+ if (cp != NULL)
+ (void) list_merge(cp, end_block);
+ else
+ cp = end_block;
+
+ (void) list_append(cp, instruction(Op_stop));
+ goto out;
+ }
+
+ if (endfile_block == NULL)
+ endfile_block = list_create(ip_endfile);
+ else {
+ extern int has_endfile; /* kludge for use in inrec (io.c) */
+ has_endfile = TRUE;
+ (void) list_prepend(endfile_block, ip_endfile);
+ }
+
+ if (beginfile_block == NULL)
+ beginfile_block = list_create(ip_beginfile);
+ else
+ (void) list_prepend(beginfile_block, ip_beginfile);
+
+ if (prog_block == NULL) {
+ if (end_block->nexti == end_block->lasti
+ && beginfile_block->nexti == beginfile_block->lasti
+ && endfile_block->nexti == endfile_block->lasti
+ ) {
+ /* no pattern-action and (real) end, beginfile or endfile blocks */
+ bcfree(ip_rec);
+ bcfree(ip_newfile);
+ ip_rec = ip_newfile = NULL;
+
+ list_append(beginfile_block, instruction(Op_after_beginfile));
+ (void) list_append(endfile_block, instruction(Op_after_endfile));
+
+ if (begin_block == NULL) /* no program at all */
+ cp = end_block;
+ else
+ cp = list_merge(begin_block, end_block);
+ (void) list_append(cp, ip_atexit);
+ (void) list_append(cp, instruction(Op_stop));
+
+ /* append beginfile_block and endfile_block for sole use
+ * in getline without redirection (Op_K_getline).
+ */
+
+ (void) list_merge(cp, beginfile_block);
+ (void) list_merge(cp, endfile_block);
+
+ goto out;
+
+ } else {
+ /* install a do-nothing prog block */
+ prog_block = list_create(instruction(Op_no_op));
+ }
+ }
+
+ (void) list_append(endfile_block, instruction(Op_after_endfile));
+ (void) list_prepend(prog_block, ip_rec);
+ (void) list_append(prog_block, instruction(Op_jmp));
+ prog_block->lasti->target_jmp = ip_rec;
+
+ list_append(beginfile_block, instruction(Op_after_beginfile));
+
+ cp = list_merge(beginfile_block, prog_block);
+ (void) list_prepend(cp, ip_newfile);
+ (void) list_merge(cp, endfile_block);
+ (void) list_merge(cp, end_block);
+ if (begin_block != NULL)
+ cp = list_merge(begin_block, cp);
+
+ (void) list_append(cp, ip_atexit);
+ (void) list_append(cp, instruction(Op_stop));
+
+out:
+ /* delete the Op_list, not needed */
+ tmp = cp->nexti;
+ bcfree(cp);
+ return tmp;
+
+#undef begin_block
+#undef end_block
+#undef prog_block
+#undef beginfile_block
+#undef endfile_block
+}
+
+/* parse_program --- read in the program and convert into a list of instructions */
+
+int
+parse_program(INSTRUCTION **pcode)
+{
+ int ret;
+
+ /* pre-create non-local jump targets
+ * ip_end (Op_no_op) -- used as jump target for `exit'
+ * outside an END block.
+ */
+ ip_end = instruction(Op_no_op);
+
+ if (get_context()->level > 0)
+ ip_newfile = ip_rec = ip_atexit = ip_beginfile = ip_endfile = NULL;
+ else {
+ ip_endfile = instruction(Op_no_op);
+ ip_beginfile = instruction(Op_no_op);
+ ip_newfile = instruction(Op_newfile); /* target for `nextfile' */
+ ip_newfile->target_jmp = ip_end;
+ ip_newfile->target_endfile = ip_endfile;
+ ip_rec = instruction(Op_get_record); /* target for `next' */
+ ip_atexit = instruction(Op_atexit); /* target for `exit' in END block */
+ }
+
+ sourcefile = srcfiles->next;
+ lexeof = FALSE;
+ lexptr = NULL;
+ lasttok = 0;
+ memset(rule_block, 0, sizeof(ruletab) * sizeof(INSTRUCTION *));
+ errcount = 0;
+ tok = tokstart != NULL ? tokstart : tokexpand();
+
+ ret = yyparse();
+ *pcode = mk_program();
+
+ /* avoid false source indications */
+ source = NULL;
+ sourceline = 0;
+
+ check_funcs();
+ return (ret || errcount);
+}
+
+/* do_add_srcfile --- add one item to srcfiles */
+
+static SRCFILE *
+do_add_srcfile(int stype, char *src, char *path, SRCFILE *thisfile)
+{
+ SRCFILE *s;
+
+ emalloc(s, SRCFILE *, sizeof(SRCFILE), "do_add_srcfile");
+ memset(s, 0, sizeof(SRCFILE));
+ s->src = estrdup(src, strlen(src));
+ s->fullpath = path;
+ s->stype = stype;
+ s->fd = INVALID_HANDLE;
+ s->next = thisfile;
+ s->prev = thisfile->prev;
+ thisfile->prev->next = s;
+ thisfile->prev = s;
+ return s;
+}
+
+/* add_srcfile --- add one item to srcfiles after checking if
+ * a source file exists and not already in list.
+ */
+
+SRCFILE *
+add_srcfile(int stype, char *src, SRCFILE *thisfile, int *already_included, int *errcode)
+{
+ SRCFILE *s;
+ struct stat sbuf;
+ char *path;
+ int errno_val = 0;
+
+ if (already_included)
+ *already_included = FALSE;
+ if (errcode)
+ *errcode = 0;
+ if (stype == SRC_CMDLINE || stype == SRC_STDIN)
+ return do_add_srcfile(stype, src, NULL, thisfile);
+
+ path = find_source(src, &sbuf, &errno_val);
+ if (path == NULL) {
+ if (errcode) {
+ *errcode = errno_val;
+ return NULL;
+ }
+ fatal(_("can't open source file `%s' for reading (%s)"),
+ src, errno_val ? strerror(errno_val) : _("reason unknown"));
+ }
+
+ for (s = srcfiles->next; s != srcfiles; s = s->next) {
+ if ((s->stype == SRC_FILE || s->stype == SRC_INC)
+ && files_are_same(& sbuf, & s->sbuf)
+ ) {
+ if (do_lint)
+ lintwarn(_("already included source file `%s'"), src);
+ efree(path);
+ if (already_included)
+ *already_included = TRUE;
+ return NULL;
+ }
+ }
+
+ s = do_add_srcfile(stype, src, path, thisfile);
+ s->sbuf = sbuf;
+ s->mtime = sbuf.st_mtime;
+ return s;
+}
+
+/* include_source --- read program from source included using `@include' */
+
+static int
+include_source(char *src)
+{
+ SRCFILE *s;
+ int errcode;
+ int already_included;
+
+ if (do_traditional || do_posix) {
+ error(_("@include is a gawk extension"));
+ errcount++;
+ return -1;
+ }
+
+ if (strlen(src) == 0) {
+ if (do_lint)
+ lintwarn(_("empty filename after @include"));
+ return 0;
+ }
+
+ s = add_srcfile(SRC_INC, src, sourcefile, &already_included, &errcode);
+ if (s == NULL) {
+ if (already_included)
+ return 0;
+ error(_("can't open source file `%s' for reading (%s)"),
+ src, errcode ? strerror(errcode) : _("reason unknown"));
+ errcount++;
+ return -1;
+ }
+
+ /* save scanner state for the current sourcefile */
+ sourcefile->srclines = sourceline;
+ sourcefile->lexptr = lexptr;
+ sourcefile->lexend = lexend;
+ sourcefile->lexptr_begin = lexptr_begin;
+ sourcefile->lexeme = lexeme;
+ sourcefile->lasttok = lasttok;
+
+ /* included file becomes the current source */
+ sourcefile = s;
+ lexptr = NULL;
+ sourceline = 0;
+ source = NULL;
+ lasttok = 0;
+ lexeof = FALSE;
+ eof_warned = FALSE;
+ return 0;
+}
+
+/* next_sourcefile --- read program from the next source in srcfiles */
+
+static void
+next_sourcefile()
+{
+ static int (*closefunc)(int fd) = NULL;
+
+ if (closefunc == NULL) {
+ char *cp = getenv("AWKREADFUNC");
+
+ /* If necessary, one day, test value for different functions. */
+ if (cp == NULL)
+ closefunc = close;
+ else
+ closefunc = one_line_close;
+ }
+
+ assert(lexeof == TRUE);
+ lexeof = FALSE;
+ eof_warned = FALSE;
+ sourcefile->srclines = sourceline; /* total no of lines in current file */
+ if (sourcefile->fd > INVALID_HANDLE) {
+ if (sourcefile->fd != fileno(stdin)) /* safety */
+ (*closefunc)(sourcefile->fd);
+ sourcefile->fd = INVALID_HANDLE;
+ }
+ if (sourcefile->buf != NULL) {
+ efree(sourcefile->buf);
+ sourcefile->buf = NULL;
+ sourcefile->lexptr_begin = NULL;
+ }
+
+ sourcefile = sourcefile->next;
+ if (sourcefile == srcfiles)
+ return;
+
+ if (sourcefile->lexptr_begin != NULL) {
+ /* resume reading from already opened file (postponed to process '@include') */
+ lexptr = sourcefile->lexptr;
+ lexend = sourcefile->lexend;
+ lasttok = sourcefile->lasttok;
+ lexptr_begin = sourcefile->lexptr_begin;
+ lexeme = sourcefile->lexeme;
+ sourceline = sourcefile->srclines;
+ source = sourcefile->src;
+ } else {
+ lexptr = NULL;
+ sourceline = 0;
+ source = NULL;
+ lasttok = 0;
+ }
}
/* get_src_buf --- read the next buffer of source program */
@@ -3939,11 +5017,11 @@ static void
static char *
get_src_buf()
{
- static int samefile = FALSE;
- static int nextfile = 0;
- static char *buf = NULL;
- static size_t buflen = 0;
- static int fd;
+ int n;
+ char *scan;
+ int newfile;
+ int savelen;
+ struct stat sbuf;
/*
* No argument prototype on readfunc on purpose,
@@ -3951,105 +5029,94 @@ get_src_buf()
* the types of arguments to read() aren't up to date.
*/
static ssize_t (*readfunc)() = 0;
- static int (*closefunc)P((int fd)) = NULL;
-
- int n;
- register char *scan;
- int newfile;
- struct stat sbuf;
- int readcount = 0;
- int l;
- char *readloc;
if (readfunc == NULL) {
char *cp = getenv("AWKREADFUNC");
/* If necessary, one day, test value for different functions. */
- if (cp == NULL) {
+ if (cp == NULL)
readfunc = read;
- closefunc = close;
- } else {
+ else
readfunc = read_one_line;
- closefunc = one_line_close;
- }
}
-again:
newfile = FALSE;
- if (nextfile > numfiles)
+ if (sourcefile == srcfiles)
return NULL;
- if (srcfiles[nextfile].stype == CMDLINE) {
- if ((l = strlen(srcfiles[nextfile].val)) == 0) {
+ if (sourcefile->stype == SRC_CMDLINE) {
+ if (sourcefile->bufsize == 0) {
+ sourcefile->bufsize = strlen(sourcefile->src);
+ lexptr = lexptr_begin = lexeme = sourcefile->src;
+ lexend = lexptr + sourcefile->bufsize;
+ sourceline = 1;
+ if (sourcefile->bufsize == 0) {
+ /*
+ * Yet Another Special case:
+ * gawk '' /path/name
+ * Sigh.
+ */
+ static short warned = FALSE;
+
+ if (do_lint && ! warned) {
+ warned = TRUE;
+ lintwarn(_("empty program text on command line"));
+ }
+ lexeof = TRUE;
+ }
+ } else if (sourcefile->buf == NULL && *(lexptr-1) != '\n') {
/*
- * Yet Another Special case:
- * gawk '' /path/name
- * Sigh.
+ * The following goop is to ensure that the source
+ * ends with a newline and that the entire current
+ * line is available for error messages.
*/
- static short warned = FALSE;
+ int offset;
+ char *buf;
- if (do_lint && ! warned) {
- warned = TRUE;
- lintwarn(_("empty program text on command line"));
- }
- ++nextfile;
- goto again;
- }
- if (srcfiles[nextfile].val[l-1] == '\n') {
- /* has terminating newline, can use it directly */
- sourceline = 1;
- source = NULL;
- lexptr = lexptr_begin = srcfiles[nextfile].val;
- /* fall through to pointer adjustment and return, below */
- } else {
- /* copy it into static buffer */
-
- /* make sure buffer exists and has room */
- if (buflen == 0) {
- emalloc(buf, char *, l+2, "get_src_buf");
- buflen = l + 2;
- } else if (l+2 > buflen) {
- erealloc(buf, char *, l+2, "get_src_buf");
- buflen = l + 2;
- } /* else
- buffer has room, just use it */
-
- /* copy in data */
- memcpy(buf, srcfiles[nextfile].val, l);
- buf[l] = '\n';
- buf[++l] = '\0';
-
- /* set vars and return */
- sourceline = 0;
- source = NULL;
- lexptr = lexptr_begin = buf;
- }
- lexend = lexptr + l;
- nextfile++; /* for next entry to this routine */
+ offset = lexptr - lexeme;
+ for (scan = lexeme; scan > lexptr_begin; scan--)
+ if (*scan == '\n') {
+ scan++;
+ break;
+ }
+ savelen = lexptr - scan;
+ emalloc(buf, char *, savelen + 1, "get_src_buf");
+ memcpy(buf, scan, savelen);
+ thisline = buf;
+ lexptr = buf + savelen;
+ *lexptr = '\n';
+ lexeme = lexptr - offset;
+ lexptr_begin = buf;
+ lexend = lexptr + 1;
+ sourcefile->buf = buf;
+ } else
+ lexeof = TRUE;
return lexptr;
}
- if (! samefile) {
- source = srcfiles[nextfile].val;
- if (source == NULL) { /* read all the source files, all done */
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- buflen = 0;
- return lexeme = lexptr = lexptr_begin = NULL;
- }
- fd = pathopen(source);
+ if (sourcefile->fd <= INVALID_HANDLE) {
+ int fd;
+ int l;
+
+ source = sourcefile->src;
+ if (source == NULL)
+ return NULL;
+ fd = srcopen(sourcefile);
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)"),
+ error(_("can't open source file `%s' for reading (%s)"),
in, strerror(errno));
+ errcount++;
+ lexeof = TRUE;
+ return sourcefile->src;
}
- l = optimal_bufsize(fd, & sbuf);
+
+ sourcefile->fd = fd;
+ l = optimal_bufsize(fd, &sbuf);
/*
* Make sure that something silly like
* AWKBUFSIZE=8 make check
@@ -4059,110 +5126,71 @@ again:
if (l < A_DECENT_BUFFER_SIZE)
l = A_DECENT_BUFFER_SIZE;
#undef A_DECENT_BUFFER_SIZE
-
+ sourcefile->bufsize = l;
newfile = TRUE;
-
- /* make sure buffer exists and has room */
- if (buflen == 0) {
- emalloc(buf, char *, l+2, "get_src_buf");
- buflen = l + 2;
- } else if (l+2 > buflen) {
- erealloc(buf, char *, l+2, "get_src_buf");
- buflen = l + 2;
- } /* else
- buffer has room, just use it */
-
- readcount = l;
- readloc = lexeme = lexptr = lexptr_begin = buf;
- samefile = TRUE;
+ emalloc(sourcefile->buf, char *, sourcefile->bufsize, "get_src_buf");
+ lexptr = lexptr_begin = lexeme = sourcefile->buf;
+ savelen = 0;
sourceline = 1;
+ thisline = NULL;
} else {
/*
- * In same file, ran off edge of buffer.
- * Shift current line down to front, adjust
- * pointers and fill in the rest of the buffer.
+ * Here, we retain the current source line in the beginning of the buffer.
*/
-
- int lexeme_offset = lexeme - lexptr_begin;
- int lexptr_offset = lexptr - lexptr_begin;
- int lexend_offset = lexend - lexptr_begin;
-
- /* find beginning of current line */
- for (scan = lexeme; scan >= lexptr_begin; scan--) {
+ int offset;
+ for (scan = lexeme; scan > lexptr_begin; scan--)
if (*scan == '\n') {
scan++;
break;
}
- }
- /*
- * This condition can be read as follows: IF
- * 1. The beginning of the line is at the beginning of the
- * buffer (no newline was found: scan <= buf)
- * AND:
- * 2. The start of valid lexical data is into the buffer
- * (lexptr_begin > buf)
- * OR:
- * 3. We have scanned past the end of the last data read
- * (lexptr == lexend)
- * AND:
- * 4. There's no room left in the buffer
- * (lexptr_offset >= buflen - 2)
- *
- * If all that's true, grow the buffer to add more to
- * the current line.
- */
+ savelen = lexptr - scan;
+ offset = lexptr - lexeme;
- if (scan <= buf
- && (lexptr_begin > buf
- || (lexptr == lexend
- && lexptr_offset >= buflen - 2))) {
- /* have to grow the buffer */
- buflen *= 2;
- erealloc(buf, char *, buflen, "get_src_buf");
- } else if (scan > buf) {
- /* Line starts in middle of the buffer, shift things down. */
- memmove(buf, scan, lexend - scan);
+ if (savelen > 0) {
/*
- * make offsets relative to start of line,
- * not start of buffer.
+ * Need to make sure we have room left for reading new text;
+ * grow the buffer (by doubling, an arbitrary choice), if the retained line
+ * takes up more than a certain percentage (50%, again an arbitrary figure)
+ * of the available space.
*/
- lexend_offset = lexend - scan;
- lexeme_offset = lexeme - scan;
- lexptr_offset = lexptr - scan;
- }
- /* adjust pointers */
- lexeme = buf + lexeme_offset;
- lexptr = buf + lexptr_offset;
- lexend = buf + lexend_offset;
- lexptr_begin = buf;
- readcount = buflen - (lexend - buf);
- readloc = lexend;
+ if (savelen > sourcefile->bufsize / 2) { /* long line or token */
+ sourcefile->bufsize *= 2;
+ erealloc(sourcefile->buf, char *, sourcefile->bufsize, "get_src_buf");
+ scan = sourcefile->buf + (scan - lexptr_begin);
+ lexptr_begin = sourcefile->buf;
+ }
+
+ thisline = lexptr_begin;
+ memmove(thisline, scan, savelen);
+ lexptr = thisline + savelen;
+ lexeme = lexptr - offset;
+ } else {
+ savelen = 0;
+ lexptr = lexeme = lexptr_begin;
+ thisline = NULL;
+ }
}
- /* add more data to buffer */
- n = (*readfunc)(fd, readloc, readcount);
- if (n == -1)
- fatal(_("can't read sourcefile `%s' (%s)"),
- source, strerror(errno));
- if (n == 0) {
- if (newfile) {
+ n = (*readfunc)(sourcefile->fd, lexptr, sourcefile->bufsize - savelen);
+ if (n == -1) {
+ error(_("can't read sourcefile `%s' (%s)"),
+ source, strerror(errno));
+ errcount++;
+ lexeof = TRUE;
+ } else {
+ lexend = lexptr + n;
+ if (n == 0) {
static short warned = FALSE;
-
- if (do_lint && ! warned) {
+ if (do_lint && newfile && ! warned){
warned = TRUE;
lintwarn(_("source file `%s' is empty"), source);
}
+ lexeof = TRUE;
}
- if (fd != fileno(stdin)) /* safety */
- (*closefunc)(fd);
- samefile = FALSE;
- nextfile++;
- goto again;
}
- lexend = lexptr + n;
- return lexptr;
+ return sourcefile->buf;
}
/* tokadd --- add a character to the token buffer */
@@ -4171,20 +5199,23 @@ again:
/* tokexpand --- grow the token buffer */
-char *
+static char *
tokexpand()
{
- static int toksize = 60;
+ static int toksize;
int tokoffset;
-
- tokoffset = tok - tokstart;
- toksize *= 2;
- if (tokstart != NULL)
+
+ if (tokstart != NULL) {
+ tokoffset = tok - tokstart;
+ toksize *= 2;
erealloc(tokstart, char *, toksize, "tokexpand");
- else
+ tok = tokstart + tokoffset;
+ } else {
+ toksize = 60;
emalloc(tokstart, char *, toksize, "tokexpand");
+ tok = tokstart;
+ }
tokend = tokstart + toksize;
- tok = tokstart + tokoffset;
return tok;
}
@@ -4196,9 +5227,13 @@ static int
nextc(void)
{
if (gawk_mb_cur_max > 1) {
- if (!lexptr || lexptr >= lexend) {
- if (! get_src_buf())
- return EOF;
+again:
+ if (lexeof)
+ return END_FILE;
+ if (lexptr == NULL || lexptr >= lexend) {
+ if (get_src_buf())
+ goto again;
+ return END_SRC;
}
/* Update the buffer index. */
@@ -4211,7 +5246,7 @@ nextc(void)
int idx, work_ring_idx = cur_ring_idx;
mbstate_t tmp_state;
size_t mbclen;
-
+
for (idx = 0 ; lexptr + idx < lexend ; idx++) {
tmp_state = cur_mbstate;
mbclen = mbrlen(lexptr, idx + 1, &tmp_state);
@@ -4242,44 +5277,30 @@ nextc(void)
}
return (int) (unsigned char) *lexptr++;
- }
- else {
- 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 {
+ do {
+ if (lexeof)
+ return END_FILE;
+ if (lexptr && lexptr < lexend)
+ return ((int) (unsigned char) *lexptr++);
+ } while (get_src_buf());
+ return END_SRC;
}
}
#else /* MBS_SUPPORT */
-#if GAWKDEBUG
int
-nextc(void)
+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;
+ do {
+ if (lexeof)
+ return END_FILE;
+ if (lexptr && lexptr < lexend)
+ return ((int) (unsigned char) *lexptr++);
+ } while (get_src_buf());
+ return END_SRC;
}
-#else
-#define nextc() ((lexptr && lexptr < lexend) ? \
- ((int) (unsigned char) *lexptr++) : \
- (get_src_buf() ? ((int) (unsigned char) *lexptr++) : EOF) \
- )
-#endif
#endif /* MBS_SUPPORT */
@@ -4293,7 +5314,7 @@ pushback(void)
cur_ring_idx = (cur_ring_idx == 0)? RING_BUFFER_SIZE - 1 :
cur_ring_idx - 1;
#endif
- (lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr);
+ (! lexeof && lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr);
}
@@ -4306,13 +5327,17 @@ allow_newline(void)
for (;;) {
c = nextc();
- if (c == EOF)
+ if (c == END_FILE) {
+ pushback();
break;
+ }
if (c == '#') {
- while ((c = nextc()) != '\n' && c != EOF)
+ while ((c = nextc()) != '\n' && c != END_FILE)
continue;
- if (c == EOF)
+ if (c == END_FILE) {
+ pushback();
break;
+ }
}
if (c == '\n')
sourceline++;
@@ -4328,30 +5353,44 @@ allow_newline(void)
static int
yylex(void)
{
- register int c;
+ int c;
int seen_e = FALSE; /* These are for numbers */
int seen_point = FALSE;
int esc_seen; /* for literal strings */
int mid;
static int did_newline = FALSE;
char *tokkey;
- static int lasttok = 0;
- static short 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;
+#define GET_INSTRUCTION(op) bcalloc(op, 1, sourceline)
+
+ /* NB: a newline at end does not start a source line. */
+
+#define NEWLINE_EOF \
+ (lasttok != NEWLINE ? \
+ (pushback(), do_lint && ! eof_warned && \
+ (lintwarn(_("source file does not end in newline")), \
+ eof_warned = TRUE), sourceline++, NEWLINE) : \
+ (sourceline--, eof_warned = FALSE, LEX_EOF))
+
+
+ yylval = (INSTRUCTION *) NULL;
+ if (lasttok == SUBSCRIPT) {
+ lasttok = 0;
+ return SUBSCRIPT;
}
+
+ if (lasttok == LEX_EOF) /* error earlier in current source, must give up !! */
+ return 0;
+
+ c = nextc();
+ if (c == END_SRC)
+ return 0;
+ if (c == END_FILE)
+ return lasttok = NEWLINE_EOF;
pushback();
+
#if defined OS2 || defined __EMX__
/*
* added for OS/2's extproc feature of cmd.exe
@@ -4362,6 +5401,7 @@ yylex(void)
lexptr++;
}
#endif
+
lexeme = lexptr;
thisline = NULL;
if (want_regexp) {
@@ -4405,7 +5445,8 @@ yylex(void)
in_brack--;
break;
case '\\':
- if ((c = nextc()) == EOF) {
+ if ((c = nextc()) == END_FILE) {
+ pushback();
yyerror(_("unterminated regexp ends with `\\' at end of file"));
goto end_regexp; /* kludge */
} else if (c == '\n') {
@@ -4421,8 +5462,8 @@ yylex(void)
if (in_brack > 0)
break;
end_regexp:
- tokadd('\0');
- yylval.sval = tokstart;
+ yylval = GET_INSTRUCTION(Op_token);
+ yylval->lextok = estrdup(tokstart, tok - tokstart);
if (do_lint) {
int peek = nextc();
@@ -4443,7 +5484,8 @@ end_regexp:
pushback();
yyerror(_("unterminated regexp"));
goto end_regexp; /* kludge */
- case EOF:
+ case END_FILE:
+ pushback();
yyerror(_("unterminated regexp at end of file"));
goto end_regexp; /* kludge */
}
@@ -4459,42 +5501,32 @@ retry:
lexeme = lexptr ? lexptr - 1 : lexptr;
thisline = NULL;
tok = tokstart;
- yylval.nodetypeval = Node_illegal;
-
- if (gawk_mb_cur_max == 1 || nextc_is_1stbyte) 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 */
- }
+
+#ifdef MBS_SUPPORT
+ if (gawk_mb_cur_max == 1 || nextc_is_1stbyte)
+#endif
+ switch (c) {
+ case END_SRC:
return 0;
+ case END_FILE:
+ return lasttok = NEWLINE_EOF;
+
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;
- }
+ if (c == END_FILE)
+ return lasttok = NEWLINE_EOF;
}
sourceline++;
return lasttok = NEWLINE;
+ case '@':
+ return lasttok = '@';
+
case '\\':
#ifdef RELAXED_CONTINUATION
/*
@@ -4516,23 +5548,27 @@ retry:
_("use of `\\ #...' line continuation is not portable"));
}
while ((c = nextc()) != '\n')
- if (c == EOF)
+ if (c == END_FILE)
break;
}
pushback();
}
#endif /* RELAXED_CONTINUATION */
- if (nextc() == '\n') {
+ c = nextc();
+ if (c == '\r') /* allow MS-DOS files. bleah */
+ c = nextc();
+ if (c == '\n') {
sourceline++;
goto retry;
} else {
yyerror(_("backslash not last character on line"));
- exit(EXIT_FAILURE);
+ return lasttok = LEX_EOF;
}
break;
case ':':
case '?':
+ yylval = GET_INSTRUCTION(Op_cond_exp);
if (! do_posix)
allow_newline();
return lasttok = c;
@@ -4547,21 +5583,36 @@ retry:
case '(':
in_parens++;
- /* FALL THROUGH */
+ return lasttok = c;
case '$':
- case ';':
+ yylval = GET_INSTRUCTION(Op_field_spec);
+ return lasttok = c;
case '{':
+ if (++in_braces == 1)
+ firstline = sourceline;
+ case ';':
case ',':
case '[':
+ return lasttok = c;
case ']':
- return lasttok = c;
+ c = nextc();
+ pushback();
+ if (c == '[') {
+ yylval = GET_INSTRUCTION(Op_sub_array);
+ lasttok = ']';
+ } else {
+ yylval = GET_INSTRUCTION(Op_subscript);
+ lasttok = SUBSCRIPT; /* end of subscripts */
+ }
+ return ']';
case '*':
if ((c = nextc()) == '=') {
- yylval.nodetypeval = Node_assign_times;
+ yylval = GET_INSTRUCTION(Op_assign_times);
return lasttok = ASSIGNOP;
} else if (do_posix) {
pushback();
+ yylval = GET_INSTRUCTION(Op_times);
return lasttok = '*';
} else if (c == '*') {
/* make ** and **= aliases for ^ and ^= */
@@ -4575,7 +5626,7 @@ retry:
if (do_lint_old)
warning(_("old awk does not support operator `**='"));
}
- yylval.nodetypeval = Node_assign_exp;
+ yylval = GET_INSTRUCTION(Op_assign_exp);
return ASSIGNOP;
} else {
pushback();
@@ -4586,10 +5637,12 @@ retry:
if (do_lint_old)
warning(_("old awk does not support operator `**'"));
}
+ yylval = GET_INSTRUCTION(Op_exp);
return lasttok = '^';
}
}
pushback();
+ yylval = GET_INSTRUCTION(Op_times);
return lasttok = '*';
case '/':
@@ -4598,14 +5651,16 @@ retry:
return lasttok = SLASH_BEFORE_EQUAL;
}
pushback();
+ yylval = GET_INSTRUCTION(Op_quotient);
return lasttok = '/';
case '%':
if (nextc() == '=') {
- yylval.nodetypeval = Node_assign_mod;
+ yylval = GET_INSTRUCTION(Op_assign_mod);
return lasttok = ASSIGNOP;
}
pushback();
+ yylval = GET_INSTRUCTION(Op_mod);
return lasttok = '%';
case '^':
@@ -4617,7 +5672,7 @@ retry:
did_warn_assgn = TRUE;
warning(_("operator `^=' is not supported in old awk"));
}
- yylval.nodetypeval = Node_assign_exp;
+ yylval = GET_INSTRUCTION(Op_assign_exp);
return lasttok = ASSIGNOP;
}
pushback();
@@ -4625,67 +5680,74 @@ retry:
did_warn_op = TRUE;
warning(_("operator `^' is not supported in old awk"));
}
+ yylval = GET_INSTRUCTION(Op_exp);
return lasttok = '^';
}
case '+':
if ((c = nextc()) == '=') {
- yylval.nodetypeval = Node_assign_plus;
+ yylval = GET_INSTRUCTION(Op_assign_plus);
return lasttok = ASSIGNOP;
}
- if (c == '+')
+ if (c == '+') {
+ yylval = GET_INSTRUCTION(Op_symbol);
return lasttok = INCREMENT;
+ }
pushback();
+ yylval = GET_INSTRUCTION(Op_plus);
return lasttok = '+';
case '!':
if ((c = nextc()) == '=') {
- yylval.nodetypeval = Node_notequal;
+ yylval = GET_INSTRUCTION(Op_notequal);
return lasttok = RELOP;
}
if (c == '~') {
- yylval.nodetypeval = Node_nomatch;
+ yylval = GET_INSTRUCTION(Op_nomatch);
return lasttok = MATCHOP;
}
pushback();
+ yylval = GET_INSTRUCTION(Op_symbol);
return lasttok = '!';
case '<':
if (nextc() == '=') {
- yylval.nodetypeval = Node_leq;
+ yylval = GET_INSTRUCTION(Op_leq);
return lasttok = RELOP;
}
- yylval.nodetypeval = Node_less;
+ yylval = GET_INSTRUCTION(Op_less);
pushback();
return lasttok = '<';
case '=':
if (nextc() == '=') {
- yylval.nodetypeval = Node_equal;
+ yylval = GET_INSTRUCTION(Op_equal);
return lasttok = RELOP;
}
- yylval.nodetypeval = Node_assign;
+ yylval = GET_INSTRUCTION(Op_assign);
pushback();
return lasttok = ASSIGN;
case '>':
if ((c = nextc()) == '=') {
- yylval.nodetypeval = Node_geq;
+ yylval = GET_INSTRUCTION(Op_geq);
return lasttok = RELOP;
} else if (c == '>') {
- yylval.nodetypeval = Node_redirect_append;
+ yylval = GET_INSTRUCTION(Op_symbol);
+ yylval->redir_type = redirect_append;
return lasttok = IO_OUT;
}
pushback();
if (in_print && in_parens == 0) {
- yylval.nodetypeval = Node_redirect_output;
+ yylval = GET_INSTRUCTION(Op_symbol);
+ yylval->redir_type = redirect_output;
return lasttok = IO_OUT;
}
- yylval.nodetypeval = Node_greater;
+ yylval = GET_INSTRUCTION(Op_greater);
return lasttok = '>';
case '~':
- yylval.nodetypeval = Node_match;
+ yylval = GET_INSTRUCTION(Op_match);
return lasttok = MATCHOP;
case '}':
@@ -4695,6 +5757,8 @@ retry:
*/
if (did_newline) {
did_newline = FALSE;
+ if (--in_braces == 0)
+ lastline = sourceline;
return lasttok = c;
}
did_newline++;
@@ -4708,7 +5772,7 @@ retry:
if (c == '\n') {
pushback();
yyerror(_("unterminated string"));
- exit(EXIT_FAILURE);
+ return lasttok = LEX_EOF;
}
if ((gawk_mb_cur_max == 1 || nextc_is_1stbyte) &&
c == '\\') {
@@ -4718,35 +5782,46 @@ retry:
continue;
}
esc_seen = TRUE;
- tokadd('\\');
+ if (! want_source || c != '"')
+ tokadd('\\');
}
- if (c == EOF) {
+ if (c == END_FILE) {
pushback();
yyerror(_("unterminated string"));
- exit(EXIT_FAILURE);
+ return lasttok = LEX_EOF;
}
tokadd(c);
}
- yylval.nodeval = make_str_node(tokstart,
- tok - tokstart, esc_seen ? SCAN : 0);
- yylval.nodeval->flags |= PERM;
+ yylval = GET_INSTRUCTION(Op_token);
+ if (want_source) {
+ yylval->lextok = estrdup(tokstart, tok - tokstart);
+ return lasttok = FILENAME;
+ }
+
+ yylval->opcode = Op_push_i;
+ yylval->memory = make_str_node(tokstart,
+ tok - tokstart, esc_seen ? SCAN : 0);
+ yylval->memory->flags &= ~MALLOC;
+ yylval->memory->flags |= PERM;
if (intlstr) {
- yylval.nodeval->flags |= INTLSTR;
+ yylval->memory->flags |= INTLSTR;
intlstr = FALSE;
if (do_intl)
- dumpintlstr(yylval.nodeval->stptr,
- yylval.nodeval->stlen);
- }
+ dumpintlstr(yylval->memory->stptr, yylval->memory->stlen);
+ }
return lasttok = YSTRING;
case '-':
if ((c = nextc()) == '=') {
- yylval.nodetypeval = Node_assign_minus;
+ yylval = GET_INSTRUCTION(Op_assign_minus);
return lasttok = ASSIGNOP;
}
- if (c == '-')
+ if (c == '-') {
+ yylval = GET_INSTRUCTION(Op_symbol);
return lasttok = DECREMENT;
+ }
pushback();
+ yylval = GET_INSTRUCTION(Op_minus);
return lasttok = '-';
case '.':
@@ -4856,13 +5931,10 @@ retry:
break;
c = nextc();
}
- if (c != EOF)
- pushback();
- else if (do_lint && ! eof_warned) {
- lintwarn(_("source file does not end in newline"));
- eof_warned = TRUE;
- }
+ pushback();
+
tokadd('\0');
+ yylval = GET_INSTRUCTION(Op_push_i);
if (! do_traditional && isnondecimal(tokstart, FALSE)) {
if (do_lint) {
if (isdigit(tokstart[1])) /* not an 'x' or 'X' */
@@ -4872,48 +5944,47 @@ retry:
lintwarn("numeric constant `%.*s' treated as hexadecimal",
(int) strlen(tokstart)-1, tokstart);
}
- yylval.nodeval = make_number(nondec2awknum(tokstart, strlen(tokstart)));
+ yylval->memory = mk_number(nondec2awknum(tokstart, strlen(tokstart)),
+ PERM|NUMCUR|NUMBER);
} else
- yylval.nodeval = make_number(atof(tokstart));
- yylval.nodeval->flags |= PERM;
+ yylval->memory = mk_number(atof(tokstart), PERM|NUMCUR|NUMBER);
return lasttok = YNUMBER;
case '&':
if ((c = nextc()) == '&') {
- yylval.nodetypeval = Node_and;
+ yylval = GET_INSTRUCTION(Op_and);
allow_newline();
return lasttok = LEX_AND;
}
pushback();
+ yylval = GET_INSTRUCTION(Op_symbol);
return lasttok = '&';
case '|':
if ((c = nextc()) == '|') {
- yylval.nodetypeval = Node_or;
+ yylval = GET_INSTRUCTION(Op_or);
allow_newline();
return lasttok = LEX_OR;
} else if (! do_traditional && c == '&') {
- yylval.nodetypeval = Node_redirect_twoway;
+ yylval = GET_INSTRUCTION(Op_symbol);
+ yylval->redir_type = redirect_twoway;
return lasttok = (in_print && in_parens == 0 ? IO_OUT : IO_IN);
}
pushback();
if (in_print && in_parens == 0) {
- yylval.nodetypeval = Node_redirect_pipe;
+ yylval = GET_INSTRUCTION(Op_symbol);
+ yylval->redir_type = redirect_pipe;
return lasttok = IO_OUT;
} else {
- yylval.nodetypeval = Node_redirect_pipein;
+ yylval = GET_INSTRUCTION(Op_symbol);
+ yylval->redir_type = redirect_pipein;
return lasttok = IO_IN;
}
-
- case '@': /* indirect function call */
- if (do_posix || do_traditional)
- break;
- return lasttok = c;
}
if (c != '_' && ! isalpha(c)) {
yyerror(_("invalid char '%c' in expression"), c);
- exit(EXIT_FAILURE);
+ return lasttok = LEX_EOF;
}
/*
@@ -4941,23 +6012,21 @@ retry:
/* it's some type of name-type-thing. Find its length. */
tok = tokstart;
- while (is_identchar(c)) {
+ while (c != END_FILE && 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;
- }
+ pushback();
/* See if it is a special token. */
-
if ((mid = check_special(tokstart)) >= 0) {
+ int class = tokentab[mid].class;
+
+ if ((class == LEX_INCLUDE || class == LEX_EVAL)
+ && lasttok != '@')
+ goto out;
+
if (do_lint) {
if (tokentab[mid].flags & GAWKX)
lintwarn(_("`%s' is a gawk extension"),
@@ -4972,26 +6041,64 @@ retry:
if (do_lint_old && (tokentab[mid].flags & NOT_OLD))
warning(_("`%s' is not supported in old awk"),
tokentab[mid].operator);
+ if (tokentab[mid].flags & BREAK)
+ break_allowed++;
+ if (tokentab[mid].flags & CONTINUE)
+ continue_allowed++;
if ((do_traditional && (tokentab[mid].flags & GAWKX))
|| (do_posix && (tokentab[mid].flags & NOT_POSIX)))
- ;
- else {
- 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;
+ goto out;
+
+ switch (class) {
+ case LEX_INCLUDE:
+ want_source = TRUE;
+ break;
+ case LEX_EVAL:
+ if (get_context()->level == 0)
+ goto out;
+ emalloc(tokkey, char *, tok - tokstart + 1, "yylex");
+ tokkey[0] = '@';
+ memcpy(tokkey + 1, tokstart, tok - tokstart);
+ yylval = GET_INSTRUCTION(Op_token);
+ yylval->lextok = tokkey;
+ break;
+
+ case LEX_FUNCTION:
+ case LEX_BEGIN:
+ case LEX_END:
+ case LEX_BEGINFILE:
+ case LEX_ENDFILE:
+ yylval = bcalloc(tokentab[mid].value, 3, sourceline);
+ break;
+
+ case LEX_WHILE:
+ case LEX_DO:
+ case LEX_FOR:
+ case LEX_SWITCH:
+ yylval = bcalloc(tokentab[mid].value,
+ !!do_profiling + 1, sourceline);
+ break;
+
+ default:
+ yylval = GET_INSTRUCTION(tokentab[mid].value);
+ if (class == LEX_BUILTIN || class == LEX_LENGTH)
+ yylval->builtin_idx = mid;
+ break;
}
+ return lasttok = class;
}
-
- yylval.sval = tokkey;
- if (*lexptr == '(')
+out:
+ tokkey = estrdup(tokstart, tok - tokstart);
+ if (*lexptr == '(') {
+ yylval = bcalloc(Op_token, 2, sourceline);
+ yylval->lextok = tokkey;
return lasttok = FUNC_CALL;
- else {
+ } else {
static short goto_warned = FALSE;
+ yylval = GET_INSTRUCTION(Op_token);
+ yylval->lextok = tokkey;
+
#define SMART_ALECK 1
if (SMART_ALECK && do_lint
&& ! goto_warned && strcasecmp(tokkey, "goto") == 0) {
@@ -5000,147 +6107,215 @@ retry:
}
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 lookahead is a NL, lineno is 1 too high */
- if (lexeme && lexeme >= lexptr_begin && *lexeme == '\n')
- r->source_line = sourceline - 1;
- else
- r->source_line = sourceline;
- r->source_file = source;
- return r;
+#undef GET_INSTRUCTION
+#undef NEWLINE_EOF
}
-/* node --- allocates a node with defined lnode and rnode. */
+/* mk_symbol --- allocates a symbol for the symbol table. */
NODE *
-node(NODE *left, NODETYPE op, NODE *right)
+mk_symbol(NODETYPE type, NODE *value)
{
- register NODE *r;
+ NODE *r;
- r = node_common(op);
- r->lnode = left;
- r->rnode = right;
+ getnode(r);
+ r->type = type;
+ r->flags = MALLOC;
+ r->lnode = value;
+ r->rnode = NULL;
+ r->var_assign = (Func_ptr) 0;
return r;
}
-/* snode --- allocate a node with defined subnode and builtin for builtin
- functions. Checks for arg. count and supplies defaults where
- possible. */
+/* snode --- instructions for builtin functions. Checks for arg. count
+ and supplies defaults where possible. */
-static NODE *
-snode(NODE *subn, NODETYPE op, int idx)
+static INSTRUCTION *
+snode(INSTRUCTION *subn, INSTRUCTION *r)
{
- register NODE *r;
- register NODE *n;
+ INSTRUCTION *arg;
+ INSTRUCTION *ip;
+ NODE *n;
int nexp = 0;
int args_allowed;
+ int idx = r->builtin_idx;
+
+ if (subn != NULL) {
+ INSTRUCTION *tp;
+ for (tp = subn->nexti; tp; tp = tp->nexti) {
+ /* assert(tp->opcode == Op_list); */
+ tp = tp->lasti;
+ nexp++;
+ }
+ assert(nexp > 0);
+ }
- r = node_common(op);
-
- /* traverse expression list to see how many args. given */
- for (n = subn; n != NULL; n = n->rnode) {
- nexp++;
- if (nexp > 5)
- break;
- }
+ r->builtin = tokentab[idx].ptr;
/* 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"),
+ if (args_allowed && (args_allowed & A(nexp)) == 0) {
+ yyerror(_("%d is invalid as number of arguments for %s"),
nexp, tokentab[idx].operator);
-
- r->builtin = tokentab[idx].ptr;
+ return NULL;
+ }
/* special case processing for a few builtins */
- if (nexp == 0 && r->builtin == do_length) {
- subn = node(node(make_number(0.0), Node_field_spec, (NODE *) NULL),
- Node_expression_list,
- (NODE *) NULL);
+ if (r->builtin == do_length) {
+ if (nexp == 0) {
+ INSTRUCTION *list; /* no args. Use $0 */
+
+ r->expr_count = 1;
+ list = list_create(r);
+ (void) list_prepend(list, instruction(Op_field_spec));
+ (void) list_prepend(list, instruction(Op_push_i));
+ list->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
+ return list;
+ }
} else if (r->builtin == do_match) {
static short warned = FALSE;
- if (subn->rnode->lnode->type != Node_regex)
- subn->rnode->lnode = mk_rexp(subn->rnode->lnode);
+ arg = subn->nexti->lasti->nexti; /* 2nd arg list */
+ (void) mk_rexp(arg);
- if (subn->rnode->rnode != NULL) { /* 3rd argument there */
+ if (nexp == 3) { /* 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"));
+ if (do_traditional) {
+ yyerror(_("match: third argument is a gawk extension"));
+ return NULL;
+ }
+
+ arg = arg->lasti->nexti; /* third arg list */
+ ip = arg->lasti;
+ if (/*ip == arg->nexti && */ ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
}
} else if (r->builtin == do_sub || r->builtin == 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) {
+ int literal = FALSE;
+
+ arg = subn->nexti; /* first arg list */
+ (void) mk_rexp(arg);
+
+ arg = arg->lasti->nexti; /* 2nd arg list */
+ if (nexp == 2) {
+ INSTRUCTION *expr;
+ expr = list_create(instruction(Op_push_i));
+ expr->nexti->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
+ (void) mk_expression_list(subn,
+ list_append(expr, instruction(Op_field_spec)));
+ }
+
+ arg = arg->lasti->nexti; /* third arg list */
+ ip = arg->lasti;
+ if (ip->opcode == Op_push_i) {
if (do_lint)
lintwarn(_("%s: string literal as last arg of substitute has no effect"),
(r->builtin == do_sub) ? "sub" : "gsub");
- } else if (! isassignable(subn->rnode->rnode->lnode)) {
- yyerror(_("%s third parameter is not a changeable object"),
- (r->builtin == do_sub) ? "sub" : "gsub");
+ literal = TRUE;
+ } else {
+ if (make_assignable(ip) == NULL)
+ yyerror(_("%s third parameter is not a changeable object"),
+ (r->builtin == do_sub) ? "sub" : "gsub");
+ else
+ ip->do_reference = TRUE;
}
+
+ /* kludge: This is one of the few cases
+ * when we need to know the type of item on stack.
+ * In case of string literal as the last argument,
+ * pass 4 as # of args (See sub_common code in builtin.c).
+ * Other cases like length(array or scalar) seem
+ * to work out ok.
+ */
+
+ r->expr_count = count_expressions(&subn, FALSE) + !!literal;
+ ip = subn->lasti;
+
+ (void) list_append(subn, r);
+
+ /* add after_assign bytecode(s) */
+ if (ip->opcode == Op_push_lhs && ip->memory->type == Node_var && ip->memory->var_assign) {
+ (void) list_append(subn, instruction(Op_var_assign));
+ subn->lasti->memory = ip->memory;
+ } else if (ip->opcode == Op_field_spec_lhs) {
+ (void) list_append(subn, instruction(Op_field_assign));
+ subn->lasti->field_assign = (Func_ptr) 0;
+ ip->target_assign = subn->lasti;
+ }
+ return subn;
} else if (r->builtin == 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));
+ if (nexp == 3) {
+ arg = subn->nexti->lasti->nexti->lasti->nexti; /* 3rd arg list */
+ ip = instruction(Op_push_i);
+ ip->memory = mk_number((AWKNUM) 0.0, (PERM|NUMCUR|NUMBER));
+ (void) mk_expression_list(subn,
+ list_append(list_create(ip),
+ instruction(Op_field_spec)));
+ }
+ arg = subn->nexti; /* first arg list */
+ (void) mk_rexp(arg);
} else if (r->builtin == do_split) {
+ arg = subn->nexti->lasti->nexti; /* 2nd arg list */
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ if (nexp == 2) {
+ INSTRUCTION *expr;
+ expr = list_create(instruction(Op_push));
+ expr->nexti->memory = FS_node;
+ (void) mk_expression_list(subn, expr);
+ }
+ arg = arg->lasti->nexti;
+ n = mk_rexp(arg);
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;
+ n->re_flags |= FS_DFLT;
+ if (nexp == 4) {
+ arg = arg->lasti->nexti;
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
} else if (r->builtin == do_patsplit) {
- if (nexp == 2)
- append_right(subn,
- node(FPAT_node, Node_expression_list, (NODE *) NULL));
- n = subn->rnode->rnode->lnode;
- if (n->type != Node_regex)
- subn->rnode->rnode->lnode = mk_rexp(n);
+ arg = subn->nexti->lasti->nexti; /* 2nd arg list */
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ if (nexp == 2) {
+ INSTRUCTION *expr;
+ expr = list_create(instruction(Op_push));
+ expr->nexti->memory = FPAT_node;
+ (void) mk_expression_list(subn, expr);
+ }
+ arg = arg->lasti->nexti;
+ n = mk_rexp(arg);
+ if (nexp == 4) {
+ arg = arg->lasti->nexti;
+ ip = arg->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
} else if (r->builtin == do_close) {
static short warned = FALSE;
-
- if ( nexp == 2) {
- if (do_lint && nexp == 2 && ! warned) {
+ if (nexp == 2) {
+ if (do_lint && ! warned) {
warned = TRUE;
lintwarn(_("close: second argument is a gawk extension"));
}
- if (do_traditional)
- fatal(_("close: second argument is a gawk extension"));
+ if (do_traditional) {
+ yyerror(_("close: second argument is a gawk extension"));
+ return NULL;
+ }
}
} else if (do_intl /* --gen-po */
&& r->builtin == do_dcgettext /* dcgettext(...) */
- && subn->lnode->type == Node_val /* 1st arg is constant */
- && (subn->lnode->flags & STRCUR) != 0) { /* it's a string constant */
+ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */
+ && (subn->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */
/* ala xgettext, dcgettext("some string" ...) dumps the string */
- NODE *str = subn->lnode;
+ NODE *str = subn->nexti->lasti->memory;
if ((str->flags & INTLSTR) != 0)
warning(_("use of dcgettext(_\"...\") is incorrect: remove leading underscore"));
@@ -5149,45 +6324,65 @@ snode(NODE *subn, NODETYPE op, int idx)
dumpintlstr(str->stptr, str->stlen);
} else if (do_intl /* --gen-po */
&& r->builtin == do_dcngettext /* dcngettext(...) */
- && subn->lnode->type == Node_val /* 1st arg is constant */
- && (subn->lnode->flags & STRCUR) != 0 /* it's a string constant */
- && subn->rnode->lnode->type == Node_val /* 2nd arg is constant too */
- && (subn->rnode->lnode->flags & STRCUR) != 0) { /* it's a string constant */
+ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */
+ && (subn->nexti->lasti->memory->flags & STRCUR) != 0 /* it's a string constant */
+ && subn->nexti->lasti->nexti->lasti->opcode == Op_push_i /* 2nd arg is constant too */
+ && (subn->nexti->lasti->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */
/* ala xgettext, dcngettext("some string", "some plural" ...) dumps the string */
- NODE *str1 = subn->lnode;
- NODE *str2 = subn->rnode->lnode;
+ NODE *str1 = subn->nexti->lasti->memory;
+ NODE *str2 = subn->nexti->lasti->nexti->lasti->memory;
if (((str1->flags | str2->flags) & INTLSTR) != 0)
warning(_("use of dcngettext(_\"...\") is incorrect: remove leading underscore"));
else
dumpintlstr2(str1->stptr, str1->stlen, str2->stptr, str2->stlen);
+ } else if (r->builtin == do_asort || r->builtin == do_asorti) {
+ arg = subn->nexti; /* 1st arg list */
+ ip = arg->lasti;
+ if (/* ip == arg->nexti && */ ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ if (nexp == 2) {
+ arg = ip->nexti;
+ ip = arg->lasti;
+ if (/* ip == arg->nexti && */ ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
}
+#ifdef ARRAYDEBUG
+ else if (r->builtin == do_adump) {
+ ip = subn->nexti->lasti;
+ if (ip->opcode == Op_push)
+ ip->opcode = Op_push_array;
+ }
+#endif
- r->subnode = subn;
- if (r->builtin == do_sprintf) {
- count_args(r);
- if (r->lnode != NULL) /* r->lnode set from subn. guard against syntax errors & check it's valid */
- r->lnode->printf_count = r->printf_count; /* hack */
+ if (subn != NULL) {
+ r->expr_count = count_expressions(&subn, FALSE);
+ return list_append(subn, r);
}
- return r;
+
+ r->expr_count = 0;
+ return list_create(r);
}
-/* make_for_loop --- build a for loop */
+/* append_param --- append PNAME to the list of parameters
+ * for the current function.
+ */
-static NODE *
-make_for_loop(NODE *init, NODE *cond, NODE *incr)
+static void
+append_param(char *pname)
{
- register FOR_LOOP_HEADER *r;
- NODE *n;
+ static NODE *savetail = NULL;
+ NODE *p;
- 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;
+ p = make_param(pname);
+ if (func_params == NULL) {
+ func_params = p;
+ savetail = p;
+ } else if (savetail != NULL) {
+ savetail->rnode = p;
+ savetail = p;
+ }
}
/* dup_parms --- return TRUE if there are duplicate parameters */
@@ -5195,7 +6390,7 @@ make_for_loop(NODE *init, NODE *cond, NODE *incr)
static int
dup_parms(NODE *func)
{
- register NODE *np;
+ NODE *np;
const char *fname, **names;
int count, i, j, dups;
NODE *params;
@@ -5218,7 +6413,7 @@ dup_parms(NODE *func)
i = 0;
for (np = params; np != NULL; np = np->rnode) {
if (np->param == NULL) { /* error earlier, give up, go home */
- free(names);
+ efree(names);
return TRUE;
}
names[i++] = np->param;
@@ -5231,36 +6426,45 @@ dup_parms(NODE *func)
dups++;
error(
_("function `%s': parameter #%d, `%s', duplicates parameter #%d"),
- fname, i+1, names[j], j+1);
+ fname, i + 1, names[j], j+1);
}
}
}
- free(names);
+ efree(names);
return (dups > 0 ? TRUE : FALSE);
}
/* parms_shadow --- check if parameters shadow globals */
static int
-parms_shadow(const char *fname, NODE *func)
+parms_shadow(INSTRUCTION *pc, int *shadow)
{
- int count, i;
+ int pcount, i;
int ret = FALSE;
+ NODE *func;
+ char *fname;
+ func = pc->func_body;
+ fname = func->lnode->param;
+
+#if 0 /* can't happen, already exited if error ? */
if (fname == NULL || func == NULL) /* error earlier */
return FALSE;
+#endif
- count = func->lnode->param_cnt;
+ pcount = func->lnode->param_cnt;
- if (count == 0) /* no args, no problem */
- return FALSE;
+ if (pcount == 0) /* no args, no problem */
+ return 0;
+ source = pc->source_file;
+ sourceline = pc->source_line;
/*
* Use warning() and not lintwarn() so that can warn
* about all shadowed parameters.
*/
- for (i = 0; i < count; i++) {
+ for (i = 0; i < pcount; i++) {
if (lookup(func->parmlist[i]) != NULL) {
warning(
_("function `%s': parameter `%s' shadows global variable"),
@@ -5269,21 +6473,27 @@ parms_shadow(const char *fname, NODE *func)
}
}
- return ret;
+ *shadow |= ret;
+ return 0;
}
+
/*
- * install:
+ * install_symbol:
* 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)
+install_symbol(char *name, NODE *value)
{
- register NODE *hp;
- register size_t len;
- register int bucket;
+ NODE *hp;
+ size_t len;
+ int bucket;
+
+ if (install_func)
+ (*install_func)(name);
var_count++;
len = strlen(name);
@@ -5299,27 +6509,26 @@ install(char *name, NODE *value)
return hp->hvalue;
}
-/* lookup --- find the most recent hash node for name installed by install */
+/* lookup --- find the most recent hash node for name installed by install_symbol */
NODE *
lookup(const char *name)
{
- register NODE *bucket;
- register size_t len;
+ NODE *bucket;
+ size_t len;
len = strlen(name);
for (bucket = variables[hash(name, len, (unsigned long) HASHSIZE, NULL)];
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 */
+/* sym_comp --- compare two symbol (variable or function) names */
static int
-var_comp(const void *v1, const void *v2)
+sym_comp(const void *v1, const void *v2)
{
const NODE *const *npp1, *const *npp2;
const NODE *n1, *n2;
@@ -5340,77 +6549,90 @@ var_comp(const void *v1, const void *v2)
/* valinfo --- dump var info */
-static void
-valinfo(NODE *n, FILE *fp)
+void
+valinfo(NODE *n, int (*print_func)(FILE *, const char *, ...), FILE *fp)
{
- if (n->flags & STRING) {
- fprintf(fp, "string (");
- pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE);
- fprintf(fp, ")\n");
+ if (n == Nnull_string)
+ print_func(fp, "uninitialized scalar\n");
+ else if (n->flags & STRING) {
+ pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', FALSE);
+ print_func(fp, "\n");
} else if (n->flags & NUMBER)
- fprintf(fp, "number (%.17g)\n", n->numbr);
+ print_func(fp, "%.17g\n", n->numbr);
else if (n->flags & STRCUR) {
- fprintf(fp, "string value (");
- pp_string_fp(fp, n->stptr, n->stlen, '"', FALSE);
- fprintf(fp, ")\n");
+ pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', FALSE);
+ print_func(fp, "\n");
} else if (n->flags & NUMCUR)
- fprintf(fp, "number value (%.17g)\n", n->numbr);
+ print_func(fp, "%.17g\n", n->numbr);
else
- fprintf(fp, "?? flags %s\n", flags2str(n->flags));
+ print_func(fp, "?? flags %s\n", flags2str(n->flags));
}
+/* get_varlist --- list of global variables */
-/* dump_vars --- dump the symbol table */
-
-void
-dump_vars(const char *fname)
+NODE **
+get_varlist()
{
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;
- }
+ emalloc(table, NODE **, (var_count + 1) * sizeof(NODE *), "get_varlist");
+ update_global_values();
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);
+ qsort(table, j, sizeof(NODE *), sym_comp);
+
+ table[j] = NULL;
+ return table;
+}
- for (i = 0; i < j; i++) {
- p = table[i];
+/* print_vars --- print names and values of global variables */
+
+void
+print_vars(int (*print_func)(FILE *, const char *, ...), FILE *fp)
+{
+ int i;
+ NODE **table;
+ NODE *p;
+
+ table = get_varlist();
+ for (i = 0; (p = table[i]) != NULL; i++) {
if (p->hvalue->type == Node_func)
continue;
- fprintf(fp, "%.*s: ", (int) p->hlength, p->hname);
+ print_func(fp, "%.*s: ", (int) p->hlength, p->hname);
if (p->hvalue->type == Node_var_array)
- fprintf(fp, "array, %ld elements\n", p->hvalue->table_size);
+ print_func(fp, "array, %ld elements\n", p->hvalue->table_size);
else if (p->hvalue->type == Node_var_new)
- fprintf(fp, "unused variable\n");
+ print_func(fp, "untyped variable\n");
else if (p->hvalue->type == Node_var)
- valinfo(p->hvalue->var_value, fp);
- else {
- NODE **lhs = get_lhs(p->hvalue, NULL, FALSE);
+ valinfo(p->hvalue->var_value, print_func, fp);
+ }
+ efree(table);
+}
- valinfo(*lhs, fp);
- }
+/* dump_vars --- dump the symbol table */
+
+void
+dump_vars(const char *fname)
+{
+ FILE *fp;
+
+ 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;
}
+ print_vars(fprintf, fp);
if (fp != stderr && fclose(fp) != 0)
warning(_("%s: close failed (%s)"), fname, strerror(errno));
-
- free(table);
}
/* release_all_vars --- free all variable memory */
@@ -5420,8 +6642,8 @@ release_all_vars()
{
int i;
NODE *p, *next;
-
- for (i = 0; i < HASHSIZE; i++)
+
+ for (i = 0; i < HASHSIZE; i++) {
for (p = variables[i]; p != NULL; p = next) {
next = p->hnext;
@@ -5429,40 +6651,14 @@ release_all_vars()
continue;
else if (p->hvalue->type == Node_var_array)
assoc_clear(p->hvalue);
- else if (p->hvalue->type != Node_var_new) {
- NODE **lhs = get_lhs(p->hvalue, NULL, FALSE);
-
- unref(*lhs);
- }
- unref(p);
- }
-}
-
-/* finfo --- for use in comparison and sorting of function names */
-
-struct finfo {
- const char *name;
- size_t nlen;
- NODE *func;
-};
-
-/* fcompare --- comparison function for qsort */
-
-static int
-fcompare(const void *p1, const void *p2)
-{
- const struct finfo *f1, *f2;
- int minlen;
-
- f1 = (const struct finfo *) p1;
- f2 = (const struct finfo *) p2;
+ else if (p->hvalue->type != Node_var_new)
+ unref(p->hvalue->var_value);
- if (f1->nlen > f2->nlen)
- minlen = f2->nlen;
- else
- minlen = f1->nlen;
-
- return strncmp(f1->name, f2->name, minlen);
+ efree(p->hname);
+ freenode(p->hvalue);
+ freenode(p);
+ }
+ }
}
/* dump_funcs --- print all functions */
@@ -5470,48 +6666,10 @@ fcompare(const void *p1, const void *p2)
void
dump_funcs()
{
- int i, j;
- NODE *p;
- struct finfo *tab = NULL;
-
- /*
- * Walk through symbol table countng functions.
- * Could be more than func_count if there are
- * extension functions.
- */
- for (i = j = 0; i < HASHSIZE; i++) {
- for (p = variables[i]; p != NULL; p = p->hnext) {
- if (p->hvalue->type == Node_func) {
- j++;
- }
- }
- }
-
- if (j == 0)
+ if (func_count <= 0)
return;
- emalloc(tab, struct finfo *, j * sizeof(struct finfo), "dump_funcs");
-
- /* now walk again, copying info */
- 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++;
- }
- }
- }
-
-
- /* Shazzam! */
- qsort(tab, j, sizeof(struct finfo), fcompare);
-
- for (i = 0; i < j; i++)
- pp_func(tab[i].name, tab[i].nlen, tab[i].func);
-
- free(tab);
+ (void) foreach_func((int (*)(INSTRUCTION *, void *)) pp_func, TRUE, (void *) 0);
}
/* shadow_funcs --- check all functions for parameters that shadow globals */
@@ -5519,40 +6677,16 @@ dump_funcs()
void
shadow_funcs()
{
- int i, j;
- NODE *p;
- struct finfo *tab;
static int calls = 0;
int shadow = FALSE;
- if (func_count == 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++)
- shadow |= parms_shadow(tab[i].name, tab[i].func);
-
- free(tab);
+ (void) foreach_func((int (*)(INSTRUCTION *, void *)) parms_shadow, TRUE, &shadow);
/* End with fatal if the user requested it. */
if (shadow && lintfunc != warning)
@@ -5560,54 +6694,6 @@ shadow_funcs()
}
/*
- * 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)
- list = savetail; /* Be careful: maybe list->rnode != NULL */
- else
- savefront = oldlist;
-
- while (list->rnode != NULL)
- list = list->rnode;
- savetail = list->rnode = new;
- return oldlist;
-}
-
-/*
- * append_pattern:
- * A wrapper around append_right, used for rule lists.
- */
-static inline NODE *
-append_pattern(NODE **list, NODE *patt)
-{
- NODE *n = node(patt, Node_rule_node, (NODE *) NULL);
-
- if (*list == NULL)
- *list = n;
- else {
- NODE *n1 = node(n, Node_rule_list, (NODE *) NULL);
- if ((*list)->type != Node_rule_list)
- *list = node(*list, Node_rule_list, n1);
- else
- (void) append_right(*list, n1);
- }
- return n;
-}
-
-/*
* 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
@@ -5618,92 +6704,117 @@ append_pattern(NODE **list, NODE *patt)
* of each function parameter during a function call. See eval.c.
*/
-static void
-func_install(NODE *params, NODE *def)
+static int
+func_install(INSTRUCTION *func, INSTRUCTION *def)
{
- NODE *r, *n, *thisfunc;
- char **pnames, *names, *sp;
- size_t pcount = 0, space = 0;
+ NODE *params;
+ NODE *r, *n, *thisfunc, *hp;
+ char **pnames = NULL;
+ char *fname;
+ int pcount = 0;
int i;
+ params = func_params;
+
/* 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);
- else if (is_std_var(n->param))
- fatal(_("function `%s': can't use special variable `%s' as a function parameter"),
+ if (strcmp(n->param, params->param) == 0) {
+ error(_("function `%s': can't use function name as parameter name"),
+ params->param);
+ errcount++;
+ return -1;
+ } else if (is_std_var(n->param)) {
+ error(_("function `%s': can't use special variable `%s' as a function parameter"),
params->param, n->param);
+ errcount++;
+ return -1;
+ }
}
- thisfunc = NULL; /* turn off warnings */
+ thisfunc = NULL; /* turn off warnings */
- /* symbol table managment */
- pop_var(params, FALSE);
- r = lookup(params->param);
+ fname = params->param;
+ /* symbol table management */
+ hp = remove_symbol(params->param); /* remove function name out of symbol table */
+ if (hp != NULL)
+ freenode(hp);
+ r = lookup(fname);
if (r != NULL) {
- fatal(_("function name `%s' previously defined"), params->param);
- } else if (params->param == builtin_func) /* not a valid function name */
+ error(_("function name `%s' previously defined"), fname);
+ errcount++;
+ return -1;
+ } else if (fname == builtin_func) /* not a valid function name */
goto remove_params;
+ /* add an implicit return at end;
+ * also used by 'return' command in debugger
+ */
+
+ (void) list_append(def, instruction(Op_push_i));
+ def->lasti->memory = Nnull_string;
+ (void) list_append(def, instruction(Op_K_return));
+
+ if (do_profiling)
+ (void) list_prepend(def, instruction(Op_exec_count));
+
+ /* func->opcode is Op_func */
+ (func + 1)->firsti = def->nexti;
+ (func + 1)->lasti = def->lasti;
+ (func + 2)->first_line = func->source_line;
+ (func + 2)->last_line = lastline;
+
+ func->nexti = def->nexti;
+ bcfree(def);
+
+ (void) list_append(rule_list, func + 1); /* debugging */
+
/* install the function */
- thisfunc = node(params, Node_func, def);
- (void) install(params->param, thisfunc);
+ thisfunc = mk_symbol(Node_func, params);
+ (void) install_symbol(fname, thisfunc);
+ thisfunc->code_ptr = func;
+ func->func_body = thisfunc;
- /* figure out amount of space to allocate for variable names */
- for (n = params->rnode; n != NULL; n = n->rnode) {
+ 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;
+ emalloc(pnames, char **, (pcount + 1) * sizeof(char *), "func_install");
+ for (i = 0, n = params->rnode; i < pcount; i++, n = n->rnode)
+ pnames[i] = n->param;
+ pnames[pcount] = NULL;
}
+ thisfunc->parmlist = pnames;
/* update lint table info */
- func_use(params->param, FUNC_DEFINE);
+ func_use(fname, FUNC_DEFINE);
- func_count++; /* used by profiling / pretty printer */
+ func_count++; /* used in profiler / pretty printer */
remove_params:
/* remove params from symbol table */
pop_params(params->rnode);
+ return 0;
}
-/* pop_var --- remove a variable from the symbol table */
+/* remove_symbol --- remove a variable from the symbol table */
-static void
-pop_var(NODE *np, int freeit)
+NODE *
+remove_symbol(char *name)
{
- register NODE *bucket, **save;
- register size_t len;
- char *name;
+ NODE *bucket, **save;
+ size_t len;
- name = np->param;
len = strlen(name);
save = &(variables[hash(name, len, (unsigned long) HASHSIZE, NULL)]);
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;
+ return bucket;
}
save = &(bucket->hnext);
}
+ return NULL;
}
/* pop_params --- remove list of function parameters from symbol table */
@@ -5715,10 +6826,13 @@ pop_var(NODE *np, int freeit)
static void
pop_params(NODE *params)
{
+ NODE *hp;
if (params == NULL)
return;
pop_params(params->rnode);
- pop_var(params, TRUE);
+ hp = remove_symbol(params->param);
+ if (hp != NULL)
+ freenode(hp);
}
/* make_param --- make NAME into a function parameter */
@@ -5731,9 +6845,8 @@ make_param(char *name)
getnode(r);
r->type = Node_param_list;
r->rnode = NULL;
- r->param = name;
r->param_cnt = param_counter++;
- return (install(name, r));
+ return (install_symbol(name, r));
}
static struct fdesc {
@@ -5787,6 +6900,9 @@ check_funcs()
struct fdesc *fp, *next;
int i;
+ if (get_context()->level > 0)
+ goto free_mem;
+
for (i = 0; i < HASHSIZE; i++) {
for (fp = ftable[i]; fp != NULL; fp = fp->next) {
#ifdef REALLYMEAN
@@ -5808,29 +6924,98 @@ check_funcs()
}
}
+free_mem:
/* 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);
+ efree(fp->name);
+ efree(fp);
}
+ ftable[i] = NULL;
}
}
/* param_sanity --- look for parameters that are regexp constants */
static void
-param_sanity(NODE *arglist)
+param_sanity(INSTRUCTION *arglist)
{
- NODE *argp, *arg;
- int i;
+ INSTRUCTION *argl, *arg;
+ int i = 1;
- for (i = 1, argp = arglist; argp != NULL; argp = argp->rnode, i++) {
- arg = argp->lnode;
- if (arg->type == Node_regex)
+ if (arglist == NULL)
+ return;
+ for (argl = arglist->nexti; argl; ) {
+ arg = argl->lasti;
+ if (arg->opcode == Op_match_rec)
warning(_("regexp constant for parameter #%d yields boolean value"), i);
+ argl = arg->nexti;
+ i++;
+ }
+}
+
+/* foreach_func --- execute given function for each awk function in symbol table. */
+
+int
+foreach_func(int (*pfunc)(INSTRUCTION *, void *), int sort, void *data)
+{
+ int i, j;
+ NODE *p;
+ int ret = 0;
+
+ if (sort) {
+ NODE **tab;
+
+ /*
+ * Walk through symbol table counting functions.
+ * Could be more than func_count if there are
+ * extension functions.
+ */
+ for (i = j = 0; i < HASHSIZE; i++) {
+ for (p = variables[i]; p != NULL; p = p->hnext) {
+ if (p->hvalue->type == Node_func) {
+ j++;
+ }
+ }
+ }
+
+ if (j == 0)
+ return 0;
+
+ emalloc(tab, NODE **, j * sizeof(NODE *), "foreach_func");
+
+ /* now walk again, copying info */
+ for (i = j = 0; i < HASHSIZE; i++) {
+ for (p = variables[i]; p != NULL; p = p->hnext) {
+ if (p->hvalue->type == Node_func) {
+ tab[j] = p;
+ j++;
+ }
+ }
+ }
+
+ /* Shazzam! */
+ qsort(tab, j, sizeof(NODE *), sym_comp);
+
+ for (i = 0; i < j; i++) {
+ if ((ret = pfunc(tab[i]->hvalue->code_ptr, data)) != 0)
+ break;
+ }
+
+ efree(tab);
+ return ret;
}
+
+ /* unsorted */
+ for (i = 0; i < HASHSIZE; i++) {
+ for (p = variables[i]; p != NULL; p = p->hnext) {
+ if (p->hvalue->type == Node_func
+ && (ret = pfunc(p->hvalue->code_ptr, data)) != 0)
+ return ret;
+ }
+ }
+ return 0;
}
/* deferred variables --- those that are only defined if needed. */
@@ -5867,33 +7052,31 @@ register_deferred_variable(const char *name, NODE *(*load_func)(void))
/* variable --- make sure NAME is in the symbol table */
NODE *
-variable(char *name, int can_free, NODETYPE type)
+variable(char *name, NODETYPE type)
{
- register NODE *r;
+ NODE *r;
if ((r = lookup(name)) != NULL) {
- if (r->type == Node_func)
- fatal(_("function `%s' called with space between name and `(',\nor used as a variable or an array"),
+ if (r->type == Node_func) {
+ error(_("function `%s' called with space between name and `(',\nor used as a variable or an array"),
r->vname);
-
+ errcount++;
+ r->type = Node_var_new; /* continue parsing instead of exiting */
+ }
} else {
/* not found */
struct deferred_variable *dv;
for (dv = deferred_variables; TRUE; dv = dv->next) {
if (dv == NULL) {
- /*
- * This is the only case in which we may not
- * free the string.
- */
- NODE *n;
-
- if (type == Node_var_array)
- n = node(NULL, type, NULL);
+ /*
+ * This is the only case in which we may not free the string.
+ */
+ if (type == Node_var)
+ r = mk_symbol(type, Nnull_string);
else
- n = node(Nnull_string, type, NULL);
-
- return install(name, n);
+ r = mk_symbol(type, (NODE *) NULL);
+ return install_symbol(name, r);
}
if (STREQ(name, dv->name)) {
r = (*dv->load_func)();
@@ -5901,31 +7084,55 @@ variable(char *name, int can_free, NODETYPE type)
}
}
}
- if (can_free)
- free(name);
+ efree(name);
return r;
}
-/* mk_rexp --- make a regular expression constant */
+/* make_regnode --- make a regular expression node */
static NODE *
-mk_rexp(NODE *exp)
+make_regnode(int type, NODE *exp)
{
NODE *n;
- if (exp->type == Node_regex)
- return exp;
-
getnode(n);
- n->type = Node_dynregex;
- n->re_exp = exp;
- n->re_text = NULL;
- n->re_reg = NULL;
- n->re_flags = 0;
+ memset(n, 0, sizeof(NODE));
+ n->type = type;
n->re_cnt = 1;
+
+ if (type == Node_regex) {
+ n->re_reg = make_regexp(exp->stptr, exp->stlen, FALSE, TRUE, FALSE);
+ if (n->re_reg == NULL) {
+ freenode(n);
+ return NULL;
+ }
+ n->re_exp = exp;
+ n->re_flags = CONSTANT;
+ }
return n;
}
+
+/* mk_rexp --- make a regular expression constant */
+
+static NODE *
+mk_rexp(INSTRUCTION *list)
+{
+ INSTRUCTION *ip;
+
+ ip = list->nexti;
+ if (ip == list->lasti && ip->opcode == Op_match_rec)
+ ip->opcode = Op_push_re;
+ else {
+ ip = instruction(Op_push_re);
+ ip->memory = make_regnode(Node_dynregex, NULL);
+ ip->nexti = list->lasti->nexti;
+ list->lasti->nexti = ip;
+ list->lasti = ip;
+ }
+ return ip->memory;
+}
+
/* isnoeffect --- when used as a statement, has no side effects */
/*
@@ -5936,48 +7143,38 @@ mk_rexp(NODE *exp)
*/
static int
-isnoeffect(NODETYPE type)
+isnoeffect(OPCODE 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_FPAT:
- 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:
- case Node_SUBSEP:
- case Node_TEXTDOMAIN:
+ case Op_times:
+ case Op_times_i:
+ case Op_quotient:
+ case Op_quotient_i:
+ case Op_mod:
+ case Op_mod_i:
+ case Op_plus:
+ case Op_plus_i:
+ case Op_minus:
+ case Op_minus_i:
+ case Op_subscript:
+ case Op_concat:
+ case Op_exp:
+ case Op_exp_i:
+ case Op_unary_minus:
+ case Op_field_spec:
+ case Op_and_final:
+ case Op_or_final:
+ case Op_equal:
+ case Op_notequal:
+ case Op_less:
+ case Op_greater:
+ case Op_leq:
+ case Op_geq:
+ case Op_match:
+ case Op_nomatch:
+ case Op_match_rec:
+ case Op_not:
+ case Op_in_array:
return TRUE;
default:
break; /* keeps gcc -Wall happy */
@@ -5986,45 +7183,34 @@ isnoeffect(NODETYPE type)
return FALSE;
}
-/* isassignable --- can this node be assigned to? */
+/* make_assignable --- make this operand an assignable one if posiible */
-static int
-isassignable(register NODE *n)
+static INSTRUCTION *
+make_assignable(INSTRUCTION *ip)
{
- switch (n->type) {
- case Node_var_new:
- case Node_var:
- case Node_FIELDWIDTHS:
- case Node_RS:
- case Node_FS:
- case Node_FNR:
- case Node_FPAT:
- 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_SUBSEP:
- case Node_TEXTDOMAIN:
- case Node_field_spec:
- case Node_subscript:
- return TRUE;
- case Node_param_list:
- return ((n->flags & FUNC) == 0); /* ok if not func name */
+ switch (ip->opcode) {
+ case Op_push:
+ if (ip->memory->type == Node_param_list
+ && (ip->memory->flags & FUNC) != 0)
+ return NULL;
+ ip->opcode = Op_push_lhs;
+ return ip;
+ case Op_field_spec:
+ ip->opcode = Op_field_spec_lhs;
+ return ip;
+ case Op_subscript:
+ ip->opcode = Op_subscript_lhs;
+ return ip;
default:
break; /* keeps gcc -Wall happy */
}
- return FALSE;
+ return NULL;
}
/* stopme --- for debugging */
NODE *
-stopme(NODE *tree ATTRIBUTE_UNUSED)
+stopme(int nargs ATTRIBUTE_UNUSED)
{
return (NODE *) 0;
}
@@ -6046,7 +7232,7 @@ dumpintlstr(const char *str, size_t len)
}
printf("msgid ");
- pp_string_fp(stdout, str, len, '"', TRUE);
+ pp_string_fp(fprintf, stdout, str, len, '"', TRUE);
putchar('\n');
printf("msgstr \"\"\n\n");
fflush(stdout);
@@ -6069,35 +7255,15 @@ dumpintlstr2(const char *str1, size_t len1, const char *str2, size_t len2)
}
printf("msgid ");
- pp_string_fp(stdout, str1, len1, '"', TRUE);
+ pp_string_fp(fprintf, stdout, str1, len1, '"', TRUE);
putchar('\n');
printf("msgid_plural ");
- pp_string_fp(stdout, str2, len2, '"', TRUE);
+ pp_string_fp(fprintf, stdout, str2, len2, '"', TRUE);
putchar('\n');
printf("msgstr[0] \"\"\nmsgstr[1] \"\"\n\n");
fflush(stdout);
}
-/* 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->builtin == 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;
-}
-
/* isarray --- can this type be subscripted? */
static int
@@ -6119,6 +7285,1194 @@ isarray(NODE *n)
return FALSE;
}
+
+static INSTRUCTION *
+mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op)
+{
+ INSTRUCTION *ip,*ip1;
+ AWKNUM res;
+
+ ip = s2->nexti;
+ if (s2->lasti == ip && ip->opcode == Op_push_i) {
+ /* do any numeric constant folding */
+ ip1 = s1->nexti;
+ if (ip1->memory != NULL && ip1->memory->type == Node_val
+ && (ip1->memory->flags & (STRCUR|STRING)) == 0
+ && ip->memory != NULL && ip->memory->type == Node_val
+ && (ip->memory->flags & (STRCUR|STRING)) == 0
+ && ip1 == s1->lasti && do_optimize > 1) {
+ ip1->memory->numbr = force_number(ip1->memory);
+ ip->memory->numbr = force_number(ip->memory);
+ res = ip1->memory->numbr;
+ switch (op->opcode) {
+ case Op_times:
+ res *= ip->memory->numbr;
+ break;
+ case Op_quotient:
+ if (ip->memory->numbr == 0) {
+ /* don't fatalize, allow parsing rest of the input */
+ yyerror(_("division by zero attempted"));
+ goto regular;
+ }
+
+ res /= ip->memory->numbr;
+ break;
+ case Op_mod:
+ if (ip->memory->numbr == 0) {
+ /* don't fatalize, allow parsing rest of the input */
+ yyerror(_("division by zero attempted in `%%'"));
+ goto regular;
+ }
+#ifdef HAVE_FMOD
+ res = fmod(res, ip->memory->numbr);
+#else /* ! HAVE_FMOD */
+ (void) modf(res / ip->memory->numbr, &res);
+ res = ip1->memory->numbr - res * ip->memory->numbr;
+#endif /* ! HAVE_FMOD */
+ break;
+ case Op_plus:
+ res += ip->memory->numbr;
+ break;
+ case Op_minus:
+ res -= ip->memory->numbr;
+ break;
+ case Op_exp:
+ res = calc_exp(res, ip->memory->numbr);
+ break;
+ default:
+ goto regular;
+ }
+
+ op->opcode = Op_push_i;
+ op->memory = mk_number(res, (PERM|NUMCUR|NUMBER));
+ bcfree(ip1);
+ bcfree(ip);
+ bcfree(s1);
+ bcfree(s2);
+ return list_create(op);
+ } else {
+ /* do basic arithmetic optimisation */
+ /* convert (Op_push_i Node_val) + (Op_plus) to (Op_plus_i Node_val) */
+ switch (op->opcode) {
+ case Op_times:
+ op->opcode = Op_times_i;
+ break;
+ case Op_quotient:
+ op->opcode = Op_quotient_i;
+ break;
+ case Op_mod:
+ op->opcode = Op_mod_i;
+ break;
+ case Op_plus:
+ op->opcode = Op_plus_i;
+ break;
+ case Op_minus:
+ op->opcode = Op_minus_i;
+ break;
+ case Op_exp:
+ op->opcode = Op_exp_i;
+ break;
+ default:
+ goto regular;
+ }
+
+ op->memory = ip->memory;
+ bcfree(ip);
+ bcfree(s2); /* Op_list */
+ return list_append(s1, op);
+ }
+ }
+
+regular:
+ /* append lists s1, s2 and add `op' bytecode */
+ (void) list_merge(s1, s2);
+ return list_append(s1, op);
+}
+
+/* mk_boolean --- instructions for boolean and, or */
+
+static INSTRUCTION *
+mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op)
+{
+ INSTRUCTION *tp;
+ OPCODE opc, final_opc;
+
+ opc = op->opcode; /* Op_and or Op_or */
+ final_opc = (opc == Op_or) ? Op_or_final : Op_and_final;
+
+ add_lint(right, LINT_assign_in_cond);
+
+ tp = left->lasti;
+
+ if (tp->opcode != final_opc) { /* x || y */
+ list_append(right, instruction(final_opc));
+ add_lint(left, LINT_assign_in_cond);
+ (void) list_append(left, op);
+ left->lasti->target_jmp = right->lasti;
+
+ /* NB: target_stmt points to previous Op_and(Op_or) in a chain;
+ * target_stmt only used in the parser (see below).
+ */
+
+ left->lasti->target_stmt = left->lasti;
+ right->lasti->target_stmt = left->lasti;
+ } else { /* optimization for x || y || z || ... */
+ INSTRUCTION *ip;
+
+ op->opcode = final_opc;
+ (void) list_append(right, op);
+ op->target_stmt = tp;
+ tp->opcode = opc;
+ tp->target_jmp = op;
+
+ /* update jump targets */
+ for (ip = tp->target_stmt; ; ip = ip->target_stmt) {
+ assert(ip->opcode == opc);
+ assert(ip->target_jmp == tp);
+ /* if (ip->opcode == opc && ip->target_jmp == tp) */
+ ip->target_jmp = op;
+ if (ip->target_stmt == ip)
+ break;
+ }
+ }
+
+ return list_merge(left, right);
+}
+
+/* mk_condition --- if-else and conditional */
+
+static INSTRUCTION *
+mk_condition(INSTRUCTION *cond, INSTRUCTION *ifp, INSTRUCTION *true_branch,
+ INSTRUCTION *elsep, INSTRUCTION *false_branch)
+{
+ /*
+ * ----------------
+ * cond
+ * ----------------
+ * t: [Op_jmp_false f ]
+ * ----------------
+ * true_branch
+ *
+ * ----------------
+ * [Op_jmp y]
+ * ----------------
+ * f:
+ * false_branch
+ * ----------------
+ * y: [Op_no_op]
+ * ----------------
+ */
+
+ INSTRUCTION *ip;
+
+ /* FIXME else { } -- add elsep */
+
+ if (false_branch == NULL) {
+ if (elsep != NULL) /* else { } */
+ false_branch = list_append(list_create(elsep), instruction(Op_no_op));
+ else
+ false_branch = list_create(instruction(Op_no_op));
+ } else {
+ /* assert(elsep != NULL); */
+
+ /* avoid a series of no_op's: if .. else if .. else if .. */
+ if (false_branch->lasti->opcode != Op_no_op)
+ (void) list_append(false_branch, instruction(Op_no_op));
+ (void) list_prepend(false_branch, elsep);
+ false_branch->nexti->branch_end = false_branch->lasti;
+ if (do_profiling)
+ (void) list_prepend(false_branch, instruction(Op_exec_count));
+ }
+
+ (void) list_prepend(false_branch, instruction(Op_jmp));
+ false_branch->nexti->target_jmp = false_branch->lasti;
+
+ add_lint(cond, LINT_assign_in_cond);
+ ip = list_append(cond, instruction(Op_jmp_false));
+ ip->lasti->target_jmp = false_branch->nexti->nexti;
+
+ (void) list_prepend(ip, ifp);
+ if (do_profiling) {
+ (void) list_append(ip, instruction(Op_exec_count));
+ ip->nexti->branch_if = ip->lasti;
+ ip->nexti->branch_else = false_branch->nexti;
+ }
+
+ if (true_branch != NULL)
+ list_merge(ip, true_branch);
+ return list_merge(ip, false_branch);
+}
+
+enum defline { FIRST_LINE, LAST_LINE };
+
+/* find_line -- find the first(last) line in a list of (pattern) instructions */
+
+static int
+find_line(INSTRUCTION *pattern, enum defline what)
+{
+ INSTRUCTION *ip;
+ int lineno = 0;
+
+ for (ip = pattern->nexti; ip; ip = ip->nexti) {
+ if (what == LAST_LINE) {
+ if (ip->source_line > lineno)
+ lineno = ip->source_line;
+ } else { /* FIRST_LINE */
+ if (ip->source_line > 0
+ && (lineno == 0 || ip->source_line < lineno))
+ lineno = ip->source_line;
+ }
+ if (ip == pattern->lasti)
+ break;
+ }
+ assert(lineno > 0);
+ return lineno;
+}
+
+/* append_rule --- pattern-action instructions */
+
+static INSTRUCTION *
+append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
+{
+ /*
+ * ----------------
+ * pattern
+ * ----------------
+ * [Op_jmp_false f ]
+ * ----------------
+ * action
+ * ----------------
+ * f: [Op_no_op ]
+ * ----------------
+ */
+
+ INSTRUCTION *rp;
+ INSTRUCTION *tp;
+ INSTRUCTION *ip;
+
+ if (rule != Rule) {
+ rp = pattern;
+ if (do_profiling)
+ (void) list_append(action, instruction(Op_no_op));
+ (rp + 1)->firsti = action->nexti;
+ (rp + 1)->lasti = action->lasti;
+ (rp + 2)->first_line = pattern->source_line;
+ (rp + 2)->last_line = lastline;
+ ip = list_prepend(action, rp);
+
+ } else {
+ rp = bcalloc(Op_rule, 3, 0);
+ rp->in_rule = Rule;
+ rp->source_file = source;
+ tp = instruction(Op_no_op);
+
+ if (pattern == NULL) {
+ /* assert(action != NULL); */
+ if (do_profiling)
+ (void) list_prepend(action, instruction(Op_exec_count));
+ (rp + 1)->firsti = action->nexti;
+ (rp + 1)->lasti = tp;
+ (rp + 2)->first_line = firstline;
+ (rp + 2)->last_line = lastline;
+ rp->source_line = firstline;
+ ip = list_prepend(list_append(action, tp), rp);
+ } else {
+ (void) list_append(pattern, instruction(Op_jmp_false));
+ pattern->lasti->target_jmp = tp;
+ (rp + 2)->first_line = find_line(pattern, FIRST_LINE);
+ rp->source_line = (rp + 2)->first_line;
+ if (action == NULL) {
+ (rp + 2)->last_line = find_line(pattern, LAST_LINE);
+ action = list_create(instruction(Op_K_print_rec));
+ if (do_profiling)
+ (void) list_prepend(action, instruction(Op_exec_count));
+ } else
+ (rp + 2)->last_line = lastline;
+
+ if (do_profiling) {
+ (void) list_prepend(pattern, instruction(Op_exec_count));
+ (void) list_prepend(action, instruction(Op_exec_count));
+ }
+ (rp + 1)->firsti = action->nexti;
+ (rp + 1)->lasti = tp;
+ ip = list_append(
+ list_merge(list_prepend(pattern, rp),
+ action),
+ tp);
+ }
+
+ }
+
+ list_append(rule_list, rp + 1);
+
+ if (rule_block[rule] == NULL)
+ rule_block[rule] = ip;
+ else
+ (void) list_merge(rule_block[rule], ip);
+
+ return rule_block[rule];
+}
+
+/* mk_assignment --- assignment bytecodes */
+
+static INSTRUCTION *
+mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
+{
+ INSTRUCTION *tp;
+ INSTRUCTION *ip;
+
+ tp = lhs->lasti;
+ switch (tp->opcode) {
+ case Op_field_spec:
+ tp->opcode = Op_field_spec_lhs;
+ break;
+ case Op_subscript:
+ tp->opcode = Op_subscript_lhs;
+ break;
+ case Op_push:
+ case Op_push_array:
+ tp->opcode = Op_push_lhs;
+ break;
+ default:
+ cant_happen();
+ }
+
+ tp->do_reference = (op->opcode != Op_assign); /* check for uninitialized reference */
+
+ if (rhs != NULL)
+ ip = list_merge(rhs, lhs);
+ else
+ ip = lhs;
+
+ (void) list_append(ip, op);
+
+ if (tp->opcode == Op_push_lhs
+ && tp->memory->type == Node_var
+ && tp->memory->var_assign
+ ) {
+ tp->do_reference = FALSE; /* no uninitialized reference checking
+ * for a special variable.
+ */
+ (void) list_append(ip, instruction(Op_var_assign));
+ ip->lasti->memory = tp->memory;
+ } else if (tp->opcode == Op_field_spec_lhs) {
+ (void) list_append(ip, instruction(Op_field_assign));
+ ip->lasti->field_assign = (Func_ptr) 0;
+ tp->target_assign = ip->lasti;
+ }
+
+ return ip;
+}
+
+/* optimize_assignment --- peephole optimization for assignment */
+
+static INSTRUCTION *
+optimize_assignment(INSTRUCTION *exp)
+{
+ INSTRUCTION *i1;
+ INSTRUCTION *i2;
+ INSTRUCTION *i3;
+
+ /*
+ * Optimize assignment statements array[subs] = x; var = x; $n = x;
+ * string concatenation of the form s = s t.
+ *
+ * 1) Array element assignment array[subs] = x:
+ * Replaces Op_push_array + Op_subscript_lhs + Op_assign + Op_pop
+ * with single instruction Op_store_sub.
+ * Limitation (FIXME): 1 dimension and sub is simple var/value.
+ *
+ * 2) Simple variable assignment var = x:
+ * Replaces Op_push_lhs + Op_assign + Op_pop with Op_store_var.
+ *
+ * 3) Field assignment $n = x:
+ * Replaces Op_field_spec_lhs + Op_assign + Op_field_assign + Op_pop
+ * with Op_store_field.
+ *
+ * 4) Optimization for string concatenation:
+ * For cases like x = x y, uses realloc to include y in x;
+ * also eliminates instructions Op_push_lhs and Op_pop.
+ */
+
+ /*
+ * N.B.: do not append Op_pop instruction to the returned
+ * instruction list if optimized. None of these
+ * optimized instructions push the r-value of assignment
+ * onto the runtime stack.
+ */
+
+ i2 = NULL;
+ i1 = exp->lasti;
+
+ if ( ! do_optimize
+ || ( i1->opcode != Op_assign
+ && i1->opcode != Op_field_assign)
+ )
+ return list_append(exp, instruction(Op_pop));
+
+ for (i2 = exp->nexti; i2 != i1; i2 = i2->nexti) {
+ switch (i2->opcode) {
+ case Op_concat:
+ if (i2->nexti->opcode == Op_push_lhs /* l.h.s is a simple variable */
+ && (i2->concat_flag & CSVAR) /* 1st exp in r.h.s is a simple variable;
+ * see Op_concat in the grammer above.
+ */
+ && i2->nexti->memory == exp->nexti->memory /* and the same as in l.h.s */
+ && i2->nexti->nexti == i1
+ && i1->opcode == Op_assign
+ ) {
+ /* s = s ... optimization */
+
+ /* avoid stuff like x = x (x = y) or x = x gsub(/./, "b", x);
+ * check for l-value reference to this variable in the r.h.s.
+ * Also avoid function calls in general, to guard against
+ * global variable assignment.
+ */
+
+ for (i3 = exp->nexti->nexti; i3 != i2; i3 = i3->nexti) {
+ if ((i3->opcode == Op_push_lhs && i3->memory == i2->nexti->memory)
+ || i3->opcode == Op_func_call)
+ return list_append(exp, instruction(Op_pop)); /* no optimization */
+ }
+
+ /* remove the variable from r.h.s */
+ i3 = exp->nexti;
+ exp->nexti = i3->nexti;
+ bcfree(i3);
+
+ if (--i2->expr_count == 1) /* one less expression in Op_concat */
+ i2->opcode = Op_no_op;
+
+ i3 = i2->nexti;
+ assert(i3->opcode == Op_push_lhs);
+ i3->opcode = Op_assign_concat; /* change Op_push_lhs to Op_assign_concat */
+ i3->nexti = NULL;
+ bcfree(i1); /* Op_assign */
+ exp->lasti = i3; /* update Op_list */
+ return exp;
+ }
+ break;
+
+ case Op_field_spec_lhs:
+ if (i2->nexti->opcode == Op_assign
+ && i2->nexti->nexti == i1
+ && i1->opcode == Op_field_assign
+ ) {
+ /* $n = .. */
+ i2->opcode = Op_store_field;
+ bcfree(i2->nexti); /* Op_assign */
+ i2->nexti = NULL;
+ bcfree(i1); /* Op_field_assign */
+ exp->lasti = i2; /* update Op_list */
+ return exp;
+ }
+ break;
+
+ case Op_push_array:
+ if (i2->nexti->nexti->opcode == Op_subscript_lhs) {
+ i3 = i2->nexti->nexti;
+ if (i3->sub_count == 1
+ && i3->nexti == i1
+ && i1->opcode == Op_assign
+ ) {
+ /* array[sub] = .. */
+ i3->opcode = Op_store_sub;
+ i3->memory = i2->memory;
+ i3->expr_count = 1; /* sub_count shadows memory,
+ * so use expr_count instead.
+ */
+ i3->nexti = NULL;
+ i2->opcode = Op_no_op;
+ bcfree(i1); /* Op_assign */
+ exp->lasti = i3; /* update Op_list */
+ return exp;
+ }
+ }
+ break;
+
+ case Op_push_lhs:
+ if (i2->nexti == i1
+ && i1->opcode == Op_assign
+ ) {
+ /* var = .. */
+ i2->opcode = Op_store_var;
+ i2->nexti = NULL;
+ bcfree(i1); /* Op_assign */
+ exp->lasti = i2; /* update Op_list */
+ return exp;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* no optimization */
+ return list_append(exp, instruction(Op_pop));
+}
+
+
+/* mk_getline --- make instructions for getline */
+
+static INSTRUCTION *
+mk_getline(INSTRUCTION *op, INSTRUCTION *var, INSTRUCTION *redir, OPCODE redirtype)
+{
+ INSTRUCTION *ip;
+ INSTRUCTION *tp;
+ INSTRUCTION *asgn = NULL;
+
+ /*
+ * getline [var] < [file]
+ *
+ * [ file (simp_exp)]
+ * [ [ var ] ]
+ * [ Op_K_getline_redir|NULL|redir_type|into_var]
+ * [ [var_assign] ]
+ *
+ */
+
+ if (redir == NULL) {
+ int sline = op->source_line;
+ bcfree(op);
+ op = bcalloc(Op_K_getline, 2, sline);
+ (op + 1)->target_endfile = ip_endfile;
+ (op + 1)->target_beginfile = ip_beginfile;
+ }
+
+ if (var != NULL) {
+ tp = make_assignable(var->lasti);
+ assert(tp != NULL);
+
+ /* check if we need after_assign bytecode */
+ if (tp->opcode == Op_push_lhs
+ && tp->memory->type == Node_var
+ && tp->memory->var_assign
+ ) {
+ asgn = instruction(Op_var_assign);
+ asgn->memory = tp->memory;
+ } else if (tp->opcode == Op_field_spec_lhs) {
+ asgn = instruction(Op_field_assign);
+ asgn->field_assign = (Func_ptr) 0; /* determined at run time */
+ tp->target_assign = asgn;
+ }
+ if (redir != NULL) {
+ ip = list_merge(redir, var);
+ (void) list_append(ip, op);
+ } else
+ ip = list_append(var, op);
+ } else if (redir != NULL)
+ ip = list_append(redir, op);
+ else
+ ip = list_create(op);
+ op->into_var = (var != NULL);
+ op->redir_type = (redir != NULL) ? redirtype : 0;
+
+ return (asgn == NULL ? ip : list_append(ip, asgn));
+}
+
+
+/* mk_for_loop --- for loop bytecodes */
+
+static INSTRUCTION *
+mk_for_loop(INSTRUCTION *forp, INSTRUCTION *init, INSTRUCTION *cond,
+ INSTRUCTION *incr, INSTRUCTION *body)
+{
+ /*
+ * [ Op_push_loop | z| y] <-- continue | break
+ * ------------------------
+ * init (may be NULL)
+ * ------------------------
+ * x:
+ * cond (Op_no_op if NULL)
+ * ------------------------
+ * [ Op_jmp_false y ]
+ * ------------------------
+ * body (may be NULL)
+ * ------------------------
+ * z:
+ * incr (may be NULL)
+ * [ Op_jmp x ]
+ * ------------------------
+ * y:[ Op_pop_loop ]
+ */
+
+ INSTRUCTION *ip;
+ INSTRUCTION *cp;
+ INSTRUCTION *jmp;
+ INSTRUCTION *pp_cond;
+ INSTRUCTION *ret;
+
+ cp = instruction(Op_pop_loop);
+
+ forp->opcode = Op_push_loop;
+ forp->target_break = cp;
+ ip = list_create(forp);
+
+ if (init != NULL)
+ (void) list_merge(ip, init);
+
+ if (cond != NULL) {
+ add_lint(cond, LINT_assign_in_cond);
+ pp_cond = cond->nexti;
+ (void) list_merge(ip, cond);
+ (void) list_append(ip, instruction(Op_jmp_false));
+ ip->lasti->target_jmp = cp;
+ } else {
+ pp_cond = instruction(Op_no_op);
+ (void) list_append(ip, pp_cond);
+ }
+
+ if (do_profiling) {
+ (void) list_append(ip, instruction(Op_exec_count));
+ (forp + 1)->opcode = Op_K_for;
+ (forp + 1)->forloop_cond = pp_cond;
+ (forp + 1)->forloop_body = ip->lasti;
+ }
+
+ if (body != NULL)
+ (void) list_merge(ip, body);
+
+ if (incr != NULL) {
+ forp->target_continue = incr->nexti;
+ (void) list_merge(ip, incr);
+ }
+ jmp = instruction(Op_jmp);
+ jmp->target_jmp = pp_cond;
+ if (incr == NULL)
+ forp->target_continue = jmp;
+ (void) list_append(ip, jmp);
+
+ ret = list_append(ip, cp);
+
+ fix_break_continue(forp, cp, TRUE);
+
+ return ret;
+}
+
+/* add_lint --- add lint warning bytecode if needed */
+
+static void
+add_lint(INSTRUCTION *list, LINTTYPE linttype)
+{
+#ifndef NO_LINT
+ INSTRUCTION *ip;
+
+ switch (linttype) {
+ case LINT_assign_in_cond:
+ ip = list->lasti;
+ if (ip->opcode == Op_var_assign || ip->opcode == Op_field_assign) {
+ assert(ip != list->nexti);
+ for (ip = list->nexti; ip->nexti != list->lasti; ip = ip->nexti)
+ ;
+ }
+
+ if (ip->opcode == Op_assign || ip->opcode == Op_assign_concat) {
+ list_append(list, instruction(Op_lint));
+ list->lasti->lint_type = linttype;
+ }
+ break;
+
+ case LINT_no_effect:
+ if (list->lasti->opcode == Op_pop && list->nexti != list->lasti) {
+ for (ip = list->nexti; ip->nexti != list->lasti; ip = ip->nexti)
+ ;
+
+ if (do_lint) { /* compile-time warning */
+ if (isnoeffect(ip->opcode))
+ lintwarn(_("statement may have no effect"));
+ }
+
+ if (ip->opcode == Op_push) { /* run-time warning */
+ list_append(list, instruction(Op_lint));
+ list->lasti->lint_type = linttype;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+/* mk_expression_list --- list of bytecode lists */
+
+static INSTRUCTION *
+mk_expression_list(INSTRUCTION *list, INSTRUCTION *s1)
+{
+ INSTRUCTION *r;
+
+ /* we can't just combine all bytecodes, since we need to
+ * process individual expressions for a few builtins in snode() (-:
+ */
+
+ /* -- list of lists */
+ /* [Op_list| ... ]------
+ * |
+ * [Op_list| ... ] -- |
+ * ... | |
+ * ... <------- |
+ * [Op_list| ... ] -- |
+ * ... | |
+ * ... | |
+ * ... <------- --
+ */
+
+ assert(s1 != NULL && s1->opcode == Op_list);
+ if (list == NULL) {
+ list = instruction(Op_list);
+ list->nexti = s1;
+ list->lasti = s1->lasti;
+ return list;
+ }
+
+ /* append expression to the end of the list */
+
+ r = list->lasti;
+ r->nexti = s1;
+ list->lasti = s1->lasti;
+ return list;
+}
+
+/* count_expressions --- fixup expression_list from mk_expression_list.
+ * returns no of expressions in list. isarg is true
+ * for function arguments.
+ */
+
+static int
+count_expressions(INSTRUCTION **list, int isarg)
+{
+ INSTRUCTION *expr;
+ INSTRUCTION *r = NULL;
+ int count = 0;
+
+ if (*list == NULL) /* error earlier */
+ return 0;
+
+ for (expr = (*list)->nexti; expr; ) {
+ INSTRUCTION *t1, *t2;
+ t1 = expr->nexti;
+ t2 = expr->lasti;
+ if (isarg && t1 == t2 && t1->opcode == Op_push)
+ t1->opcode = Op_push_param;
+ if (++count == 1)
+ r = expr;
+ else
+ (void) list_merge(r, expr);
+ expr = t2->nexti;
+ }
+
+ assert(count > 0);
+ if (! isarg && count > max_args)
+ max_args = count;
+ bcfree(*list);
+ *list = r;
+ return count;
+}
+
+/* fix_break_continue --- fix up break & continue nodes in loop bodies */
+
+static void
+fix_break_continue(INSTRUCTION *start, INSTRUCTION *end, int check_continue)
+{
+ INSTRUCTION *ip, *b_target, *c_target;
+
+ assert(start->opcode == Op_push_loop);
+ assert(end->opcode == Op_pop_loop);
+
+ b_target = start->target_break;
+ c_target = start->target_continue;
+
+ for (ip = start; ip != end; ip = ip->nexti) {
+ switch (ip->opcode) {
+ case Op_K_break:
+ if (ip->target_jmp == NULL)
+ ip->target_jmp = b_target;
+ break;
+
+ case Op_K_continue:
+ if (check_continue && ip->target_jmp == NULL)
+ ip->target_jmp = c_target;
+ break;
+
+ default:
+ /* this is to keep the compiler happy. sheesh. */
+ break;
+ }
+ }
+}
+
+
+/* append_symbol --- append symbol to the list of symbols
+ * installed in the symbol table.
+ */
+
+void
+append_symbol(char *name)
+{
+ NODE *hp;
+
+ /* N.B.: func_install removes func name and reinstalls it;
+ * and we get two entries for it here!. destroy_symbol()
+ * will find and destroy the Node_func which is what we want.
+ */
+
+ getnode(hp);
+ hp->hname = name; /* shallow copy */
+ hp->hnext = symbol_list->hnext;
+ symbol_list->hnext = hp;
+}
+
+void
+release_symbols(NODE *symlist, int keep_globals)
+{
+ NODE *hp, *n;
+
+ for (hp = symlist->hnext; hp != NULL; hp = n) {
+ if (! keep_globals) {
+ /* destroys globals, function, and params
+ * if still in symbol table and not removed by func_install
+ * due to syntax error.
+ */
+ destroy_symbol(hp->hname);
+ }
+ n = hp->hnext;
+ freenode(hp);
+ }
+ symlist->hnext = NULL;
+}
+
+/* destroy_symbol --- remove a symbol from symbol table
+* and free all associated memory.
+*/
+
+
+void
+destroy_symbol(char *name)
+{
+ NODE *symbol, *hp;
+
+ symbol = lookup(name);
+ if (symbol == NULL)
+ return;
+
+ if (symbol->type == Node_func) {
+ char **varnames;
+ NODE *func, *n;
+
+ func = symbol;
+ varnames = func->parmlist;
+ if (varnames != NULL)
+ efree(varnames);
+
+ /* function parameters of type Node_param_list */
+ for (n = func->lnode->rnode; n != NULL; ) {
+ NODE *np;
+ np = n->rnode;
+ efree(n->param);
+ freenode(n);
+ n = np;
+ }
+ freenode(func->lnode);
+ func_count--;
+
+ } else if (symbol->type == Node_var_array)
+ assoc_clear(symbol);
+ else if (symbol->type == Node_var)
+ unref(symbol->var_value);
+
+ /* remove from symbol table */
+ hp = remove_symbol(name);
+ efree(hp->hname);
+ freenode(hp->hvalue);
+ freenode(hp);
+}
+
+#define pool_size d.dl
+#define freei x.xi
+static INSTRUCTION *pool_list;
+static CONTEXT *curr_ctxt = NULL;
+
+
+CONTEXT *
+new_context()
+{
+ CONTEXT *ctxt;
+
+ emalloc(ctxt, CONTEXT *, sizeof(CONTEXT), "new_context");
+ memset(ctxt, 0, sizeof(CONTEXT));
+ ctxt->srcfiles.next = ctxt->srcfiles.prev = &ctxt->srcfiles;
+ ctxt->rule_list.opcode = Op_list;
+ ctxt->rule_list.lasti = &ctxt->rule_list;
+ if (curr_ctxt == NULL) {
+ ctxt->level = 0;
+ pool_list = &ctxt->pools;
+ symbol_list = &ctxt->symbols;
+ srcfiles = &ctxt->srcfiles;
+ rule_list = &ctxt->rule_list;
+ install_func = ctxt->install_func;
+ curr_ctxt = ctxt;
+ } else
+ ctxt->level = curr_ctxt->level + 1; /* this assumes contexts don't overlap each other ? */
+
+ return ctxt;
+}
+
+
+/* N.B.: new context (level > 0) inherits all command line options;
+ * probably should restore defaults for lint etc.
+ */
+
+CONTEXT *
+set_context(CONTEXT *ctxt)
+{
+ assert(curr_ctxt != NULL);
+ if (curr_ctxt == ctxt)
+ goto update;
+
+ /* save current source and sourceline */
+ curr_ctxt->sourceline = sourceline;
+ curr_ctxt->source = source;
+
+ if (ctxt == NULL) {
+ assert(curr_ctxt->prev != NULL);
+ ctxt = curr_ctxt->prev;
+ } else
+ ctxt->prev = curr_ctxt;
+
+ /* restore source and sourceline */
+ sourceline = ctxt->sourceline;
+ source = ctxt->source;
+
+update:
+ pool_list = &ctxt->pools;
+ symbol_list = &ctxt->symbols;
+ srcfiles = &ctxt->srcfiles;
+ rule_list = &ctxt->rule_list;
+ install_func = ctxt->install_func;
+ curr_ctxt = ctxt;
+ return curr_ctxt;
+}
+
+CONTEXT *
+get_context()
+{
+ assert(curr_ctxt != NULL);
+ return curr_ctxt;
+}
+
+void
+free_context(CONTEXT *ctxt, int keep_globals)
+{
+ SRCFILE *s, *sn;
+
+ if (ctxt == NULL)
+ return;
+
+ assert(curr_ctxt != ctxt);
+
+ /* free all code including function codes */
+ free_bcpool(&ctxt->pools);
+ /* free symbols */
+ release_symbols(&ctxt->symbols, keep_globals);
+ /* free srcfiles */
+ for (s = &ctxt->srcfiles; s != &ctxt->srcfiles; s = sn) {
+ sn = s->next;
+ if (s->stype != SRC_CMDLINE && s->stype != SRC_STDIN)
+ efree(s->fullpath);
+ efree(s->src);
+ efree(s);
+ }
+ efree(ctxt);
+}
+
+static void
+free_bc_internal(INSTRUCTION *cp)
+{
+ INSTRUCTION *curr;
+ NODE *m;
+
+ switch(cp->opcode) {
+ case Op_func_call:
+ if (cp->func_name != NULL
+ && cp->func_name != builtin_func
+ )
+ efree(cp->func_name);
+ break;
+ case Op_K_switch:
+ for (curr = cp->case_val; curr != NULL; curr = curr->nexti) {
+ if (curr->opcode == Op_K_case &&
+ curr->memory->type != Node_val
+ ) {
+ m = curr->memory;
+ if (m->re_text != NULL)
+ unref(m->re_text);
+ if (m->re_reg != NULL)
+ refree(m->re_reg);
+ if (m->re_exp != NULL)
+ unref(m->re_exp);
+ freenode(m);
+ }
+ }
+ break;
+ case Op_push_re:
+ case Op_match_rec:
+ case Op_match:
+ case Op_nomatch:
+ m = cp->memory;
+ if (m->re_reg != NULL)
+ refree(m->re_reg);
+ if (m->re_exp != NULL)
+ unref(m->re_exp);
+ if (m->re_text != NULL)
+ unref(m->re_text);
+ freenode(m);
+ break;
+ case Op_token: /* token lost during error recovery in yyparse */
+ if (cp->lextok != NULL)
+ efree(cp->lextok);
+ break;
+ case Op_illegal:
+ cant_happen();
+ default:
+ break;
+ }
+}
+
+
+/* INSTR_CHUNK must be > largest code size (3) */
+#define INSTR_CHUNK 127
+
+/* bcfree --- deallocate instruction */
+
+void
+bcfree(INSTRUCTION *cp)
+{
+ cp->opcode = 0;
+ cp->nexti = pool_list->freei;
+ pool_list->freei = cp;
+}
+
+
+/* bcalloc --- allocate a new instruction */
+
+INSTRUCTION *
+bcalloc(OPCODE op, int size, int srcline)
+{
+ INSTRUCTION *cp;
+
+ if (size > 1) {
+ /* wide instructions Op_rule, Op_func_call .. */
+ emalloc(cp, INSTRUCTION *, (size + 1) * sizeof(INSTRUCTION), "bcalloc");
+ cp->pool_size = size;
+ cp->nexti = pool_list->nexti;
+ pool_list->nexti = cp++;
+ } else {
+ INSTRUCTION *pool;
+
+ pool = pool_list->freei;
+ if (pool == NULL) {
+ INSTRUCTION *last;
+ emalloc(cp, INSTRUCTION *, (INSTR_CHUNK + 1) * sizeof(INSTRUCTION), "bcalloc");
+
+ cp->pool_size = INSTR_CHUNK;
+ cp->nexti = pool_list->nexti;
+ pool_list->nexti = cp;
+ pool = ++cp;
+ last = &pool[INSTR_CHUNK - 1];
+ for (; cp <= last; cp++) {
+ cp->opcode = 0;
+ cp->nexti = cp + 1;
+ }
+ --cp;
+ cp->nexti = NULL;
+ }
+ cp = pool;
+ pool_list->freei = cp->nexti;
+ }
+
+ memset(cp, 0, size * sizeof(INSTRUCTION));
+ cp->opcode = op;
+ cp->source_line = srcline;
+ return cp;
+}
+
+
+static void
+free_bcpool(INSTRUCTION *pl)
+{
+ INSTRUCTION *pool, *tmp;
+
+ for (pool = pl->nexti; pool != NULL; pool = tmp) {
+ INSTRUCTION *cp, *last;
+ long psiz;
+ psiz = pool->pool_size;
+ if (psiz == INSTR_CHUNK)
+ last = pool + psiz;
+ else
+ last = pool + 1;
+ for (cp = pool + 1; cp <= last ; cp++) {
+ if (cp->opcode != 0)
+ free_bc_internal(cp);
+ }
+ tmp = pool->nexti;
+ efree(pool);
+ }
+ memset(pl, 0, sizeof(INSTRUCTION));
+}
+
+
+static inline INSTRUCTION *
+list_create(INSTRUCTION *x)
+{
+ INSTRUCTION *l;
+
+ l = instruction(Op_list);
+ l->nexti = x;
+ l->lasti = x;
+ return l;
+}
+
+static inline INSTRUCTION *
+list_append(INSTRUCTION *l, INSTRUCTION *x)
+{
+#ifdef GAWKDEBUG
+ if (l->opcode != Op_list)
+ cant_happen();
+#endif
+ l->lasti->nexti = x;
+ l->lasti = x;
+ return l;
+}
+
+static inline INSTRUCTION *
+list_prepend(INSTRUCTION *l, INSTRUCTION *x)
+{
+#ifdef GAWKDEBUG
+ if (l->opcode != Op_list)
+ cant_happen();
+#endif
+ x->nexti = l->nexti;
+ l->nexti = x;
+ return l;
+}
+
+static inline INSTRUCTION *
+list_merge(INSTRUCTION *l1, INSTRUCTION *l2)
+{
+#ifdef GAWKDEBUG
+ if (l1->opcode != Op_list)
+ cant_happen();
+ if (l2->opcode != Op_list)
+ cant_happen();
+#endif
+ l1->lasti->nexti = l2->nexti;
+ l1->lasti = l2->lasti;
+ bcfree(l2);
+ return l1;
+}
+
/* See if name is a special token. */
int
@@ -6136,7 +8490,6 @@ check_special(const char *name)
}
#endif
-
low = 0;
high = (sizeof(tokentab) / sizeof(tokentab[0])) - 1;
while (low <= high) {
@@ -6175,7 +8528,7 @@ read_one_line(int fd, void *buffer, size_t count)
fp = fdopen(fd, "r");
if (fp == NULL) {
fprintf(stderr, "ugh. fdopen: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
+ gawk_exit(EXIT_FAILURE);
}
}
@@ -6201,162 +8554,4 @@ one_line_close(int fd)
return ret;
}
-/* constant_fold --- try to fold constant operations */
-
-static NODE *
-constant_fold(NODE *left, NODETYPE op, NODE *right)
-{
- AWKNUM result;
- extern double fmod P((double x, double y));
-
- if (! do_optimize)
- return node(left, op, right);
-
- /* Unary not */
- if (right == NULL) {
- if (op == Node_not && left->type == Node_val) {
- if ((left->flags & (STRCUR|STRING)) != 0) {
- NODE *ret;
- if (left->stlen == 0) {
- ret = make_number((AWKNUM) 1.0);
- } else {
- ret = make_number((AWKNUM) 0.0);
- }
- unref(left);
-
- return ret;
- } else {
- if (left->numbr == 0) {
- left->numbr = 1.0;
- } else {
- left->numbr = 0.0;
- }
-
- return left;
- }
- }
-
- return node(left, op, right);
- }
-
- /* String concatentation of two string constants */
- if (op == Node_concat
- && left->type == Node_val
- && (left->flags & (STRCUR|STRING)) != 0
- && right->type == Node_val
- && (right->flags & (STRCUR|STRING)) != 0) {
- size_t newlen = left->stlen + right->stlen + 2;
-
- erealloc(left->stptr, char *, newlen, "constant_fold");
- memcpy(left->stptr + left->stlen, right->stptr, right->stlen);
- left->stptr[left->stlen + right->stlen] = '\0';
- left->stlen += right->stlen;
-
- unref(right);
- return left;
- }
-
- /*
- * From here down, numeric operations.
- * Check for string and bail out if have them.
- */
- if (left->type != Node_val
- || (left->flags & (STRCUR|STRING)) != 0
- || right->type != Node_val
- || (right->flags & (STRCUR|STRING)) != 0) {
- return node(left, op, right);
- }
-
- /* Numeric operations: */
- switch (op) {
- case Node_not:
- case Node_exp:
- case Node_times:
- case Node_quotient:
- case Node_mod:
- case Node_plus:
- case Node_minus:
- break;
- default:
- return node(left, op, right);
- }
-
- left->numbr = force_number(left);
- right->numbr = force_number(right);
-
- result = left->numbr;
- switch (op) {
- case Node_exp:
- result = calc_exp(left->numbr, right->numbr);
- break;
- case Node_times:
- result *= right->numbr;
- break;
- case Node_quotient:
- if (right->numbr == 0)
- fatal(_("division by zero attempted in `/'"));
- result /= right->numbr;
- break;
- case Node_mod:
- if (right->numbr == 0)
- fatal(_("division by zero attempted in `%%'"));
-#ifdef HAVE_FMOD
- result = fmod(result, right->numbr);
-#else /* ! HAVE_FMOD */
- (void) modf(left->numbr / right->numbr, &result);
- result = left->numbr - result * right->numbr;
-#endif /* ! HAVE_FMOD */
- break;
- case Node_plus:
- result += right->numbr;
- break;
- case Node_minus:
- result -= right->numbr;
- break;
- default:
- /* Shut up compiler warnings */
- fatal("can't happen");
- break;
- }
-
- unref(right);
- left->numbr = result;
-
- return left;
-}
-
-/* optimize_concat --- optimize the general "x = x y z a" case */
-
-static NODE *
-optimize_concat(NODE *left, NODETYPE op, NODE *right)
-{
- NODE *top, *leftmost;
-
- if (op != Node_assign)
- return node(left, op, right);
-
- /*
- * optimization of `x = x y'. can save lots of time
- * if done a lot.
- */
- if (( left->type == Node_var
- || left->type == Node_var_new
- || left->type == Node_param_list)
- && right->type == Node_concat) {
- /* find bottom of tree, save it */
- for (top = right; top->lnode != NULL && top->type == Node_concat; top = top->lnode) {
- leftmost = top->lnode;
- if (leftmost->type == Node_concat)
- continue;
-
- /* at this point, we've run out of concatentation */
- if (leftmost != left)
- return node(left, op, right);
-
- top->lnode = Nnull_string;
- return node(left, Node_assign_concat, right);
- }
- }
- return node(left, op, right);
-}