~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to eval.c

  • Committer: Arnold D. Robbins
  • Date: 2010-11-18 21:00:31 UTC
  • Revision ID: git-v1:6f3612539c425da2bc1d34db621696e6a273b01c
Bring latest byte code gawk into git. Hurray!

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * eval.c - gawk parse tree interpreter 
 
2
 * eval.c - gawk bytecode interpreter 
3
3
 */
4
4
 
5
5
/* 
25
25
 
26
26
#include "awk.h"
27
27
 
28
 
extern double pow P((double x, double y));
29
 
extern double modf P((double x, double *yp));
30
 
extern double fmod P((double x, double y));
31
 
 
32
 
static inline void make_scalar P((NODE *tree));
33
 
static int eval_condition P((NODE *tree));
34
 
static NODE *op_assign P((NODE *tree));
35
 
static NODE *func_call P((NODE *tree));
36
 
static NODE *match_op P((NODE *tree));
37
 
static void pop_forloop P((void));
38
 
static inline void pop_all_forloops P((void));
39
 
static void push_forloop P((const char *varname, NODE **elems, size_t nelems));
40
 
static void push_args P((int count, NODE *arglist, NODE **oldstack,
41
 
                        const char *func_name, char **varnames));
42
 
static inline void pop_fcall_stack P((void));
43
 
static void pop_fcall P((void));
44
 
static int comp_func P((const void *p1, const void *p2));
 
28
extern void after_beginfile(IOBUF **curfile);
 
29
extern double pow(double x, double y);
 
30
extern double modf(double x, double *yp);
 
31
extern double fmod(double x, double y);
 
32
extern NODE **fcall_list;
 
33
extern long fcall_count;
 
34
IOBUF *curfile = NULL;          /* current data file */
 
35
int exiting = FALSE;
 
36
 
 
37
#ifdef DEBUGGING
 
38
extern int pre_execute(INSTRUCTION **, int inloop);
 
39
extern void post_execute(INSTRUCTION *, int inloop);
 
40
#else
 
41
#define r_interpret interpret
 
42
#endif
 
43
 
 
44
/*
 
45
 * Flag which executable this is; done here because eval.c is compiled
 
46
 * differently for each of them.
 
47
 */
 
48
enum exe_mode which_gawk =
 
49
#ifdef PROFILING
 
50
                           exe_profiling        /* pgawk */
 
51
#else
 
52
# ifdef DEBUGGING
 
53
                           exe_debugging        /* dgawk */     
 
54
# else
 
55
                           exe_normal           /* normal gawk */   
 
56
# endif
 
57
#endif
 
58
                           ;    /* which_gawk */
45
59
 
46
60
#if __GNUC__ < 2
47
61
NODE *_t;               /* used as a temporary in macros */
48
62
#endif
49
 
#ifdef MSDOS
50
 
double _msc51bug;       /* to get around a bug in MSC 5.1 */
51
 
#endif
52
 
NODE *ret_node;
53
63
int OFSlen;
54
64
int ORSlen;
55
65
int OFMTidx;
62
72
#define INCREMENT(n)    /* nothing */
63
73
#endif
64
74
 
65
 
/* Macros and variables to save and restore function and loop bindings */
66
 
/*
67
 
 * the val variable allows return/continue/break-out-of-context to be
68
 
 * caught and diagnosed
69
 
 */
70
 
#define PUSH_BINDING(stack, x, val) (memcpy((char *)(stack), (const char *)(x), sizeof(jmp_buf)), val++)
71
 
#define RESTORE_BINDING(stack, x, val) (memcpy((char *)(x), (const char *)(stack), sizeof(jmp_buf)), val--)
72
 
 
73
 
static jmp_buf loop_tag;                /* always the current binding */
74
 
static int loop_tag_valid = FALSE;      /* nonzero when loop_tag valid */
75
 
static int func_tag_valid = FALSE;
76
 
static jmp_buf func_tag;
77
 
extern int exiting, exit_val;
78
 
 
79
75
/* This rather ugly macro is for VMS C */
80
76
#ifdef C
81
77
#undef C
254
250
 * This table maps node types to strings for debugging.
255
251
 * KEEP IN SYNC WITH awk.h!!!!
256
252
 */
 
253
 
257
254
static const char *const nodetypes[] = {
258
255
        "Node_illegal",
259
 
        "Node_times",
260
 
        "Node_quotient",
261
 
        "Node_mod",
262
 
        "Node_plus",
263
 
        "Node_minus",
264
 
        "Node_cond_pair",
265
 
        "Node_subscript",
266
 
        "Node_concat",
267
 
        "Node_exp",
268
 
        "Node_preincrement",
269
 
        "Node_predecrement",
270
 
        "Node_postincrement",
271
 
        "Node_postdecrement",
272
 
        "Node_unary_minus",
273
 
        "Node_field_spec",
274
 
        "Node_assign",
275
 
        "Node_assign_times",
276
 
        "Node_assign_quotient",
277
 
        "Node_assign_mod",
278
 
        "Node_assign_plus",
279
 
        "Node_assign_minus",
280
 
        "Node_assign_exp",
281
 
        "Node_assign_concat",
282
 
        "Node_and",
283
 
        "Node_or",
284
 
        "Node_equal",
285
 
        "Node_notequal",
286
 
        "Node_less",
287
 
        "Node_greater",
288
 
        "Node_leq",
289
 
        "Node_geq",
290
 
        "Node_match",
291
 
        "Node_nomatch",
292
 
        "Node_not",
293
 
        "Node_rule_list",
294
 
        "Node_rule_node",
295
 
        "Node_statement_list",
296
 
        "Node_switch_body",
297
 
        "Node_case_list",
298
 
        "Node_if_branches",
299
 
        "Node_expression_list",
300
 
        "Node_param_list",
301
 
        "Node_K_if",
302
 
        "Node_K_switch",
303
 
        "Node_K_case",
304
 
        "Node_K_default",
305
 
        "Node_K_while", 
306
 
        "Node_K_for",
307
 
        "Node_K_arrayfor",
308
 
        "Node_K_break",
309
 
        "Node_K_continue",
310
 
        "Node_K_print",
311
 
        "Node_K_print_rec",
312
 
        "Node_K_printf",
313
 
        "Node_K_next",
314
 
        "Node_K_exit",
315
 
        "Node_K_do",
316
 
        "Node_K_return",
317
 
        "Node_K_delete",
318
 
        "Node_K_delete_loop",
319
 
        "Node_K_getline",
320
 
        "Node_K_function",
321
 
        "Node_K_nextfile",
322
 
        "Node_redirect_output",
323
 
        "Node_redirect_append",
324
 
        "Node_redirect_pipe",
325
 
        "Node_redirect_pipein",
326
 
        "Node_redirect_input",
327
 
        "Node_redirect_twoway",
328
 
        "Node_var_new",
 
256
        "Node_val",
 
257
        "Node_regex",
 
258
        "Node_dynregex",
329
259
        "Node_var",
330
260
        "Node_var_array",
331
 
        "Node_val",
332
 
        "Node_builtin",
333
 
        "Node_line_range",
334
 
        "Node_in_array",
 
261
        "Node_var_new",
 
262
        "Node_param_list",
335
263
        "Node_func",
336
 
        "Node_func_call",
337
 
        "Node_indirect_func_call",
338
 
        "Node_cond_exp",
339
 
        "Node_regex",
340
 
        "Node_dynregex",
341
264
        "Node_hashnode",
342
265
        "Node_ahash",
343
266
        "Node_array_ref",
344
 
        "Node_BINMODE",
345
 
        "Node_CONVFMT",
346
 
        "Node_FIELDWIDTHS",
347
 
        "Node_FNR",
348
 
        "Node_FPAT",
349
 
        "Node_FS",
350
 
        "Node_IGNORECASE",
351
 
        "Node_LINT",
352
 
        "Node_NF",
353
 
        "Node_NR",
354
 
        "Node_OFMT",
355
 
        "Node_OFS",
356
 
        "Node_ORS",
357
 
        "Node_RS",
358
 
        "Node_SUBSEP",
359
 
        "Node_TEXTDOMAIN",
 
267
        "Node_arrayfor",
 
268
        "Node_frame",
 
269
        "Node_instruction",
360
270
        "Node_final --- this should never appear",
361
271
        NULL
362
272
};
363
273
 
 
274
 
 
275
/*
 
276
 * This table maps Op codes to strings.
 
277
 * KEEP IN SYNC WITH awk.h!!!!
 
278
 */
 
279
 
 
280
static struct optypetab {
 
281
        char *desc;
 
282
        char *operator;
 
283
} optypes[] = {
 
284
        { "Op_illegal", NULL },
 
285
        { "Op_times", " * " },
 
286
        { "Op_times_i", " * " },
 
287
        { "Op_quotient", " / " },
 
288
        { "Op_quotient_i", " / " },
 
289
        { "Op_mod", " % " },
 
290
        { "Op_mod_i", " % " },
 
291
        { "Op_plus", " + " },
 
292
        { "Op_plus_i", " + " },
 
293
        { "Op_minus", " - " },
 
294
        { "Op_minus_i", " - " },
 
295
        { "Op_exp", " ^ " },
 
296
        { "Op_exp_i", " ^ " },
 
297
        { "Op_concat", " " },
 
298
        { "Op_line_range", NULL },
 
299
        { "Op_cond_pair", ", " },
 
300
        { "Op_subscript", "[]" },
 
301
        { "Op_sub_array", "[]" },
 
302
        { "Op_preincrement", "++" },
 
303
        { "Op_predecrement", "--" },
 
304
        { "Op_postincrement", "++" },
 
305
        { "Op_postdecrement", "--" },
 
306
        { "Op_unary_minus", "-" },
 
307
        { "Op_field_spec", "$" },
 
308
        { "Op_not", "! " },
 
309
        { "Op_assign", " = " },
 
310
        { "Op_store_var", " = " },
 
311
        { "Op_store_sub", " = " },
 
312
        { "Op_store_field", " = " },
 
313
        { "Op_assign_times", " *= " },
 
314
        { "Op_assign_quotient", " /= " },
 
315
        { "Op_assign_mod", " %= " },
 
316
        { "Op_assign_plus", " += " },
 
317
        { "Op_assign_minus", " -= " },
 
318
        { "Op_assign_exp", " ^= " },
 
319
        { "Op_assign_concat", " " },
 
320
        { "Op_and", " && " },
 
321
        { "Op_and_final", NULL },
 
322
        { "Op_or", " || " },
 
323
        { "Op_or_final", NULL },
 
324
        { "Op_equal", " == " },
 
325
        { "Op_notequal", " != " },
 
326
        { "Op_less", " < " },
 
327
        { "Op_greater", " > " },
 
328
        { "Op_leq", " <= " },
 
329
        { "Op_geq", " >= " },
 
330
        { "Op_match", " ~ " },
 
331
        { "Op_match_rec", NULL },
 
332
        { "Op_nomatch", " !~ " },
 
333
        { "Op_rule", NULL }, 
 
334
        { "Op_K_case", "case" },
 
335
        { "Op_K_default", "default" },
 
336
        { "Op_K_break", "break" },
 
337
        { "Op_K_continue", "continue" },
 
338
        { "Op_K_print", "print" },
 
339
        { "Op_K_print_rec", "print" },
 
340
        { "Op_K_printf", "printf" },
 
341
        { "Op_K_next", "next" },
 
342
        { "Op_K_exit", "exit" },
 
343
        { "Op_K_return", "return" },
 
344
        { "Op_K_delete", "delete" },
 
345
        { "Op_K_delete_loop", NULL },
 
346
        { "Op_K_getline_redir", "getline" },
 
347
        { "Op_K_getline", "getline" },
 
348
        { "Op_K_nextfile", "nextfile" },
 
349
        { "Op_builtin", NULL },
 
350
        { "Op_in_array", " in " },
 
351
        { "Op_func_call", NULL },
 
352
        { "Op_indirect_func_call", NULL },
 
353
        { "Op_push", NULL },
 
354
        { "Op_push_i", NULL },
 
355
        { "Op_push_re", NULL },
 
356
        { "Op_push_array", NULL },
 
357
        { "Op_push_param", NULL },
 
358
        { "Op_push_lhs", NULL },
 
359
        { "Op_subscript_lhs", "[]" },
 
360
        { "Op_field_spec_lhs", "$" },
 
361
        { "Op_no_op", NULL },
 
362
        { "Op_pop", NULL },
 
363
        { "Op_jmp", NULL },
 
364
        { "Op_jmp_true", NULL },
 
365
        { "Op_jmp_false", NULL },
 
366
        { "Op_push_loop", NULL },
 
367
        { "Op_pop_loop", NULL },
 
368
        { "Op_get_record", NULL },
 
369
        { "Op_newfile", NULL },
 
370
        { "Op_arrayfor_init", NULL },
 
371
        { "Op_arrayfor_incr", NULL },
 
372
        { "Op_arrayfor_final", NULL },
 
373
        { "Op_var_update", NULL },
 
374
        { "Op_var_assign", NULL },
 
375
        { "Op_field_assign", NULL },
 
376
        { "Op_after_beginfile", NULL },
 
377
        { "Op_after_endfile", NULL },
 
378
        { "Op_ext_func", NULL },
 
379
        { "Op_func", NULL },
 
380
        { "Op_exec_count", NULL },
 
381
        { "Op_breakpoint", NULL },
 
382
        { "Op_lint", NULL },
 
383
        { "Op_atexit", NULL },
 
384
        { "Op_stop", NULL },
 
385
        { "Op_token", NULL },
 
386
        { "Op_symbol", NULL },
 
387
        { "Op_list", NULL },
 
388
        { "Op_case_list", NULL },
 
389
        { "Op_K_do", "do" },
 
390
        { "Op_K_for", "for" },
 
391
        { "Op_K_arrayfor", "for" },
 
392
        { "Op_K_while", "while" },
 
393
        { "Op_K_switch", "switch" },
 
394
        { "Op_K_if", "if" },
 
395
        { "Op_K_else", "else" },
 
396
        { "Op_K_function", "function" },
 
397
        { "Op_cond_exp", NULL },
 
398
        { "Op_final --- this should never appear", NULL },
 
399
        { NULL, NULL },
 
400
};
 
401
 
364
402
/* nodetype2str --- convert a node type into a printable value */
365
403
 
366
404
const char *
375
413
        return buf;
376
414
}
377
415
 
 
416
/* opcode2str --- convert a opcode type into a printable value */
 
417
 
 
418
const char *
 
419
opcode2str(OPCODE op)
 
420
{
 
421
        if (op >= Op_illegal && op < Op_final)
 
422
                return optypes[(int) op].desc;
 
423
        fatal(_("unknown opcode %d"), (int) op);
 
424
        return NULL;
 
425
}
 
426
 
 
427
const char *
 
428
op2str(OPCODE op)
 
429
{
 
430
        if (op >= Op_illegal && op < Op_final) {
 
431
                if (optypes[(int) op].operator != NULL)
 
432
                        return optypes[(int) op].operator;
 
433
                else
 
434
                        fatal(_("opcode %s not an operator or keyword"),
 
435
                                        optypes[(int) op].desc);
 
436
        } else
 
437
                fatal(_("unknown opcode %d"), (int) op);
 
438
        return NULL;
 
439
}
 
440
 
 
441
 
378
442
/* flags2str --- make a flags value readable */
379
443
 
380
444
const char *
382
446
{
383
447
        static const struct flagtab values[] = {
384
448
                { MALLOC, "MALLOC" },
385
 
                { TEMP, "TEMP" },
386
449
                { PERM, "PERM" },
387
450
                { STRING, "STRING" },
388
451
                { STRCUR, "STRCUR" },
393
456
                { FUNC, "FUNC" },
394
457
                { FIELD, "FIELD" },
395
458
                { INTLSTR, "INTLSTR" },
 
459
#ifdef WSTRCUR
396
460
                { WSTRCUR, "WSTRCUR" },
397
 
                { ASSIGNED, "ASSIGNED" },
 
461
#endif
398
462
                { 0,    NULL },
399
463
        };
400
464
 
436
500
        return buffer;
437
501
}
438
502
 
439
 
/*
440
 
 * make_scalar --- make sure that tree is a scalar.
441
 
 *
442
 
 * tree is in a scalar context.  If it is a variable, accomplish
443
 
 * what's needed; otherwise, do nothing.
444
 
 *
445
 
 * Notice that nodes of type Node_var_new have undefined value in var_value
446
 
 * (a.k.a. lnode)---even though awkgram.y:variable() initializes it,
447
 
 * push_args() doesn't.  Thus we have to initialize it.
448
 
 */
449
 
 
450
 
static inline void
451
 
make_scalar(NODE *tree)
452
 
{
453
 
        switch (tree->type) {
454
 
        case Node_var_array:
455
 
                fatal(_("attempt to use array `%s' in a scalar context"),
456
 
                        array_vname(tree));
457
 
 
458
 
        case Node_array_ref:
459
 
                switch (tree->orig_array->type) {
460
 
                case Node_var_array:
461
 
                        fatal(_("attempt to use array `%s' in a scalar context"),
462
 
                                array_vname(tree));
463
 
                case Node_var_new:
464
 
                        tree->orig_array->type = Node_var;
465
 
                        tree->orig_array->var_value = Nnull_string;
466
 
                        break;
467
 
                case Node_var:
468
 
                        break;
469
 
                default:
470
 
                        cant_happen();
471
 
                }
472
 
                /* fall through */
473
 
        case Node_var_new:
474
 
                tree->type = Node_var;
475
 
                tree->var_value = Nnull_string;
476
 
        default:
477
 
                /* shut up GCC */
478
 
                break;
479
 
        }
480
 
}
481
 
 
482
 
/*
483
 
 * interpret:
484
 
 * Tree is a bunch of rules to run. Returns zero if it hit an exit()
485
 
 * statement 
486
 
 */
487
 
int
488
 
interpret(register NODE *volatile tree)
489
 
{
490
 
        jmp_buf volatile loop_tag_stack; /* shallow binding stack for loop_tag */
491
 
        static jmp_buf rule_tag; /* tag the rule currently being run, for NEXT
492
 
                                  * and EXIT statements.  It is static because
493
 
                                  * there are no nested rules */
494
 
        register NODE *volatile t = NULL;       /* temporary */
495
 
        NODE **volatile lhs;    /* lhs == Left Hand Side for assigns, etc */
496
 
        NODE *volatile stable_tree;
497
 
        int volatile traverse = TRUE;   /* True => loop thru tree (Node_rule_list) */
498
 
 
499
 
        /* avoid false source indications */
500
 
        source = NULL;
501
 
        sourceline = 0;
502
 
 
503
 
        if (tree == NULL)
504
 
                return 1;
505
 
        sourceline = tree->source_line;
506
 
        source = tree->source_file;
507
 
        switch (tree->type) {
508
 
        case Node_rule_node:
509
 
                traverse = FALSE;  /* False => one for-loop iteration only */
510
 
                /* FALL THROUGH */
511
 
        case Node_rule_list:
512
 
                for (t = tree; t != NULL; t = t->rnode) {
513
 
                        if (traverse)
514
 
                                tree = t->lnode;
515
 
                        sourceline = tree->source_line;
516
 
                        source = tree->source_file;
517
 
                        INCREMENT(tree->exec_count);
518
 
                        switch (setjmp(rule_tag)) {
519
 
                        case 0: /* normal non-jump */
520
 
                                /* test pattern, if any */
521
 
                                if (tree->lnode == NULL ||
522
 
                                    eval_condition(tree->lnode)) {
523
 
                                        /* using the lnode exec_count is kludgey */
524
 
                                        if (tree->lnode != NULL)
525
 
                                                INCREMENT(tree->lnode->exec_count);
526
 
                                        (void) interpret(tree->rnode);
527
 
                                }
528
 
                                break;
529
 
                        case TAG_CONTINUE:      /* NEXT statement */
530
 
                                pop_all_forloops();
531
 
                                pop_fcall_stack();
532
 
                                return 1;
533
 
                        case TAG_BREAK:         /* EXIT statement */
534
 
                                pop_all_forloops();
535
 
                                pop_fcall_stack();
536
 
                                return 0;
537
 
                        default:
538
 
                                cant_happen();
539
 
                        }
540
 
                        if (! traverse)         /* case Node_rule_node */
541
 
                                break;          /* don't loop */
542
 
                }
543
 
                break;
544
 
 
545
 
        case Node_statement_list:
546
 
                for (t = tree; t != NULL; t = t->rnode)
547
 
                        (void) interpret(t->lnode);
548
 
                break;
549
 
 
550
 
        case Node_K_if:
551
 
                INCREMENT(tree->exec_count);
552
 
                if (eval_condition(tree->lnode)) {
553
 
                        INCREMENT(tree->rnode->exec_count);
554
 
                        (void) interpret(tree->rnode->lnode);
555
 
                } else {
556
 
                        (void) interpret(tree->rnode->rnode);
557
 
                }
558
 
                break;
559
 
 
560
 
        case Node_K_switch:
561
 
                {
562
 
                NODE *switch_value;
563
 
                NODE *switch_body;
564
 
                NODE *case_list;
565
 
                NODE *default_list;
566
 
                NODE *case_stmt;
567
 
 
568
 
                int match_found = FALSE;
569
 
 
570
 
                PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
571
 
                INCREMENT(tree->exec_count);
572
 
                stable_tree = tree;
573
 
 
574
 
                switch_value = tree_eval(stable_tree->lnode);
575
 
                switch_body = stable_tree->rnode;
576
 
                case_list = switch_body->lnode;
577
 
                default_list  = switch_body->rnode;
578
 
 
579
 
                for (; case_list != NULL; case_list = case_list->rnode) {
580
 
                        case_stmt = case_list->lnode;
581
 
 
582
 
                        /*
583
 
                         * Once a match is found, all cases will be processed as they fall through,
584
 
                         * so continue to execute statements until a break is reached.
585
 
                         */
586
 
                        if (! match_found) {
587
 
                                if (case_stmt->type == Node_K_default)
588
 
                                        ;       /* do nothing */
589
 
                                else if (case_stmt->lnode->type == Node_regex) {
590
 
                                        NODE *t1;
591
 
                                        Regexp *rp;
592
 
                                        /* see comments in match_op() code about this. */
593
 
                                        int kludge_need_start = 0;
594
 
 
595
 
                                        t1 = force_string(switch_value);
596
 
                                        rp = re_update(case_stmt->lnode);
597
 
 
598
 
                                        if (avoid_dfa(tree, t1->stptr, t1->stlen))
599
 
                                                kludge_need_start = RE_NEED_START;
600
 
                                        match_found = (research(rp, t1->stptr, 0, t1->stlen, kludge_need_start) >= 0);
601
 
                                        if (t1 != switch_value)
602
 
                                                free_temp(t1);
603
 
                                } else
604
 
                                        match_found = (cmp_nodes(switch_value, case_stmt->lnode) == 0);
605
 
                        }
606
 
 
607
 
                        /* If a match was found, execute the statements associated with the case. */
608
 
                        if (match_found) {
609
 
                                INCREMENT(case_stmt->exec_count);
610
 
                                switch (setjmp(loop_tag)) {
611
 
                                case 0:                /* Normal non-jump    */
612
 
                                        (void) interpret(case_stmt->rnode);
613
 
                                        break;
614
 
                                case TAG_CONTINUE:     /* continue statement */
615
 
                                        free_temp(switch_value);
616
 
                                        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
617
 
                                        longjmp(loop_tag, TAG_CONTINUE);
618
 
                                        break;
619
 
                                case TAG_BREAK:        /* break statement    */
620
 
                                        free_temp(switch_value);
621
 
                                        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
622
 
                                        return 1;
623
 
                                default:
624
 
                                        cant_happen();
625
 
                                }
626
 
                        }
627
 
 
628
 
                }
629
 
 
630
 
                free_temp(switch_value);
631
 
 
632
 
                /*
633
 
                 * If a default section was found, execute the statements associated with it
634
 
                 * and execute any trailing case statements if the default falls through.
635
 
                 */
636
 
                if (! match_found && default_list != NULL) {
637
 
                        for (case_list = default_list;
638
 
                                        case_list != NULL; case_list = case_list->rnode) {
639
 
                                case_stmt = case_list->lnode;
640
 
 
641
 
                                INCREMENT(case_stmt->exec_count);
642
 
                                switch (setjmp(loop_tag)) {
643
 
                                case 0:                /* Normal non-jump    */
644
 
                                        (void) interpret(case_stmt->rnode);
645
 
                                        break;
646
 
                                case TAG_CONTINUE:     /* continue statement */
647
 
                                        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
648
 
                                        longjmp(loop_tag, TAG_CONTINUE);
649
 
                                        break;
650
 
                                case TAG_BREAK:        /* break statement    */
651
 
                                        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
652
 
                                        return 1;
653
 
                                default:
654
 
                                        cant_happen();
655
 
                                }
656
 
                        }
657
 
                }
658
 
 
659
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
660
 
                }
661
 
                break;
662
 
 
663
 
        case Node_K_while:
664
 
                PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
665
 
 
666
 
                stable_tree = tree;
667
 
                while (eval_condition(stable_tree->lnode)) {
668
 
                        INCREMENT(stable_tree->exec_count);
669
 
                        switch (setjmp(loop_tag)) {
670
 
                        case 0: /* normal non-jump */
671
 
                                (void) interpret(stable_tree->rnode);
672
 
                                break;
673
 
                        case TAG_CONTINUE:      /* continue statement */
674
 
                                break;
675
 
                        case TAG_BREAK: /* break statement */
676
 
                                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
677
 
                                return 1;
678
 
                        default:
679
 
                                cant_happen();
680
 
                        }
681
 
                }
682
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
683
 
                break;
684
 
 
685
 
        case Node_K_do:
686
 
                PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
687
 
                stable_tree = tree;
688
 
                do {
689
 
                        INCREMENT(stable_tree->exec_count);
690
 
                        switch (setjmp(loop_tag)) {
691
 
                        case 0: /* normal non-jump */
692
 
                                (void) interpret(stable_tree->rnode);
693
 
                                break;
694
 
                        case TAG_CONTINUE:      /* continue statement */
695
 
                                break;
696
 
                        case TAG_BREAK: /* break statement */
697
 
                                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
698
 
                                return 1;
699
 
                        default:
700
 
                                cant_happen();
701
 
                        }
702
 
                } while (eval_condition(stable_tree->lnode));
703
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
704
 
                break;
705
 
 
706
 
        case Node_K_for:
707
 
                PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
708
 
                (void) interpret(tree->forloop->init);
709
 
                stable_tree = tree;
710
 
                while (eval_condition(stable_tree->forloop->cond)) {
711
 
                        INCREMENT(stable_tree->exec_count);
712
 
                        switch (setjmp(loop_tag)) {
713
 
                        case 0: /* normal non-jump */
714
 
                                (void) interpret(stable_tree->lnode);
715
 
                                /* fall through */
716
 
                        case TAG_CONTINUE:      /* continue statement */
717
 
                                (void) interpret(stable_tree->forloop->incr);
718
 
                                break;
719
 
                        case TAG_BREAK: /* break statement */
720
 
                                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
721
 
                                return 1;
722
 
                        default:
723
 
                                cant_happen();
724
 
                        }
725
 
                }
726
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
727
 
                break;
728
 
 
729
 
        case Node_K_arrayfor:
730
 
                {
731
 
                Func_ptr after_assign = NULL;
732
 
                NODE **list = NULL;
733
 
                NODE *volatile array;
734
 
                NODE *volatile save_array;
735
 
                volatile size_t i, num_elems;
736
 
                size_t j;
737
 
                volatile int retval = 0;
738
 
                int sort_indices = whiny_users;
739
 
 
740
 
#define hakvar forloop->init
741
 
#define arrvar forloop->incr
742
 
                /* get the array */
743
 
                save_array = tree->arrvar;
744
 
                array = get_array(save_array);
745
 
 
746
 
                /* sanity: do nothing if empty */
747
 
                if (array->var_array == NULL || array->table_size == 0)
748
 
                        break;  /* from switch */
749
 
 
750
 
                /* allocate space for array */
751
 
                num_elems = array->table_size;
752
 
                emalloc(list, NODE **, num_elems * sizeof(NODE *), "for_loop");
753
 
 
754
 
                /* populate it */
755
 
                for (i = j = 0; i < array->array_size; i++) {
756
 
                        NODE *t = array->var_array[i];
757
 
 
758
 
                        if (t == NULL)
759
 
                                continue;
760
 
 
761
 
                        for (; t != NULL; t = t->ahnext) {
762
 
                                list[j++] = dupnode(t);
763
 
                                assert(list[j-1] == t);
764
 
                        }
765
 
                }
766
 
 
767
 
 
768
 
                if (sort_indices)
769
 
                        qsort(list, num_elems, sizeof(NODE *), comp_func); /* shazzam! */
770
 
 
771
 
                /* now we can run the loop */
772
 
                push_forloop(array->vname, list, num_elems);
773
 
                PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
774
 
 
775
 
                lhs = get_lhs(tree->hakvar, &after_assign, FALSE);
776
 
                stable_tree = tree;
777
 
                for (i = 0; i < num_elems; i++) {
778
 
                        INCREMENT(stable_tree->exec_count);
779
 
                        unref(*((NODE **) lhs));
780
 
                        *lhs = make_string(list[i]->ahname_str, list[i]->ahname_len);
781
 
                        if (after_assign)
782
 
                                (*after_assign)();
783
 
                        switch (setjmp(loop_tag)) {
784
 
                        case 0:
785
 
                                (void) interpret(stable_tree->lnode);
786
 
                        case TAG_CONTINUE:
787
 
                                break;
788
 
 
789
 
                        case TAG_BREAK:
790
 
                                retval = 1;
791
 
                                goto done;
792
 
 
793
 
                        default:
794
 
                                cant_happen();
795
 
                        }
796
 
                }
797
 
 
798
 
        done:
799
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
800
 
                pop_forloop();
801
 
 
802
 
                if (do_lint && num_elems != array->table_size)
803
 
                        lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
804
 
                                array_vname(save_array), (long) num_elems, (long) array->table_size);
805
 
                
806
 
                if (retval == 1)
807
 
                        return 1;
808
 
                break;
809
 
                }
810
 
#undef hakvar
811
 
#undef arrvar
812
 
 
813
 
        case Node_K_break:
814
 
                INCREMENT(tree->exec_count);
815
 
                if (! loop_tag_valid) {
816
 
                        /*
817
 
                         * Old AT&T nawk treats break outside of loops like
818
 
                         * next. New ones catch it at parse time. Allow it if
819
 
                         * do_traditional is on, and complain if lint.
820
 
                         */
821
 
                        static short warned = FALSE;
822
 
 
823
 
                        if (do_lint && ! warned) {
824
 
                                lintwarn(_("`break' outside a loop is not portable"));
825
 
                                warned = TRUE;
826
 
                        }
827
 
                        if (! do_traditional || do_posix)
828
 
                                fatal(_("`break' outside a loop is not allowed"));
829
 
                        longjmp(rule_tag, TAG_CONTINUE);
830
 
                } else
831
 
                        longjmp(loop_tag, TAG_BREAK);
832
 
                break;
833
 
 
834
 
        case Node_K_continue:
835
 
                INCREMENT(tree->exec_count);
836
 
                if (! loop_tag_valid) {
837
 
                        /*
838
 
                         * Old AT&T nawk treats continue outside of loops like
839
 
                         * next. New ones catch it at parse time. Allow it if
840
 
                         * do_traditional is on, and complain if lint.
841
 
                         */
842
 
                        static short warned = FALSE;
843
 
 
844
 
                        if (do_lint && ! warned) {
845
 
                                lintwarn(_("`continue' outside a loop is not portable"));
846
 
                                warned = TRUE;
847
 
                        }
848
 
                        if (! do_traditional || do_posix)
849
 
                                fatal(_("`continue' outside a loop is not allowed"));
850
 
                        longjmp(rule_tag, TAG_CONTINUE);
851
 
                } else
852
 
                        longjmp(loop_tag, TAG_CONTINUE);
853
 
                break;
854
 
 
855
 
        case Node_K_print:
856
 
                INCREMENT(tree->exec_count);
857
 
                do_print(tree);
858
 
                break;
859
 
 
860
 
        case Node_K_print_rec:
861
 
                INCREMENT(tree->exec_count);
862
 
                do_print_rec(tree);
863
 
                break;
864
 
 
865
 
        case Node_K_printf:
866
 
                INCREMENT(tree->exec_count);
867
 
                do_printf(tree);
868
 
                break;
869
 
 
870
 
        case Node_K_delete:
871
 
                INCREMENT(tree->exec_count);
872
 
                do_delete(tree->lnode, tree->rnode);
873
 
                break;
874
 
 
875
 
        case Node_K_delete_loop:
876
 
                INCREMENT(tree->exec_count);
877
 
                do_delete_loop(tree->lnode, tree->rnode);
878
 
                break;
879
 
 
880
 
        case Node_K_next:
881
 
                INCREMENT(tree->exec_count);
882
 
                if (in_begin_rule)
883
 
                        fatal(_("`next' cannot be called from a BEGIN rule"));
884
 
                else if (in_end_rule)
885
 
                        fatal(_("`next' cannot be called from an END rule"));
886
 
                else if (in_beginfile_rule)
887
 
                        fatal(_("`next' cannot be called from a BEGINFILE rule"));
888
 
                else if (in_endfile_rule)
889
 
                        fatal(_("`next' cannot be called from an ENDFILE rule"));
890
 
 
891
 
                /* could add a lint check here for in a loop or function */
892
 
                longjmp(rule_tag, TAG_CONTINUE);
893
 
                break;
894
 
 
895
 
        case Node_K_nextfile:
896
 
                INCREMENT(tree->exec_count);
897
 
                if (in_begin_rule && ! in_beginfile_rule)
898
 
                        fatal(_("`nextfile' cannot be called from a BEGIN rule"));
899
 
                else if (in_end_rule)
900
 
                        fatal(_("`nextfile' cannot be called from an END rule"));
901
 
                /*
902
 
                else if (in_beginfile_rule)
903
 
                        fatal(_("`nextfile' cannot be called from a BEGINFILE rule"));
904
 
                */
905
 
                else if (in_endfile_rule)
906
 
                        fatal(_("`nextfile' cannot be called from an ENDFILE rule"));
907
 
 
908
 
                /* could add a lint check here for in a loop or function */
909
 
                /*
910
 
                 * Have to do this cleanup here, since we don't longjump
911
 
                 * back to the main awk rule loop (rule_tag).
912
 
                 */
913
 
                pop_all_forloops();
914
 
                pop_fcall_stack();
915
 
 
916
 
                do_nextfile();
917
 
                break;
918
 
 
919
 
        case Node_K_exit:
920
 
                INCREMENT(tree->exec_count);
921
 
                /*
922
 
                 * In A,K,&W, p. 49, it says that an exit statement "...
923
 
                 * causes the program to behave as if the end of input had
924
 
                 * occurred; no more input is read, and the END actions, if
925
 
                 * any are executed." This implies that the rest of the rules
926
 
                 * are not done. So we immediately break out of the main loop.
927
 
                 */
928
 
                exiting = TRUE;
929
 
                if (tree->lnode != NULL) {
930
 
                        t = tree_eval(tree->lnode);
931
 
                        exit_val = (int) force_number(t);
932
 
#ifdef VMS
933
 
                        if (exit_val == 0)
934
 
                                exit_val = EXIT_SUCCESS;
935
 
                        else if (exit_val == 1)
936
 
                                exit_val = EXIT_FAILURE;
937
 
                        /* else
938
 
                                just pass anything else on through */
939
 
#endif
940
 
                        free_temp(t);
941
 
                }
942
 
                longjmp(rule_tag, TAG_BREAK);
943
 
                break;
944
 
 
945
 
        case Node_K_return:
946
 
                INCREMENT(tree->exec_count);
947
 
                t = tree_eval(tree->lnode);
948
 
                if ((t->flags & (PERM|TEMP)) != 0)
949
 
                        ret_node = t;
950
 
                else {
951
 
                        ret_node = copynode(t);  /* don't do a dupnode here */
952
 
                        ret_node->flags |= TEMP;
953
 
                }
954
 
                longjmp(func_tag, TAG_RETURN);
955
 
                break;
956
 
 
957
 
        default:
958
 
                /*
959
 
                 * Appears to be an expression statement.  Throw away the
960
 
                 * value. 
961
 
                 */
962
 
                if (do_lint && (tree->type == Node_var || tree->type == Node_var_new))
963
 
                        lintwarn(_("statement has no effect"));
964
 
                INCREMENT(tree->exec_count);
965
 
                t = tree_eval(tree);
966
 
                if (t)  /* stopme() returns NULL */
967
 
                        free_temp(t);
968
 
                break;
969
 
        }
970
 
        return 1;
971
 
}
972
 
 
973
 
/*
974
 
 * calc_exp_posint --- calculate x^n for positive integral n,
975
 
 * using exponentiation by squaring without recursion.
976
 
 */
977
 
 
978
 
static AWKNUM
979
 
calc_exp_posint(AWKNUM x, long n)
980
 
{
981
 
        AWKNUM mult = 1;
982
 
 
983
 
        while (n > 1) {
984
 
                if ((n % 2) == 1)
985
 
                        mult *= x;
986
 
                x *= x;
987
 
                n /= 2;
988
 
        }
989
 
        return mult * x;
990
 
}
991
 
 
992
 
/* calc_exp --- calculate x1^x2 */
993
 
 
994
 
AWKNUM
995
 
calc_exp(AWKNUM x1, AWKNUM x2)
996
 
{
997
 
        long lx;
998
 
 
999
 
        if ((lx = x2) == x2) {          /* integer exponent */
1000
 
                if (lx == 0)
1001
 
                        return 1;
1002
 
                return (lx > 0) ? calc_exp_posint(x1, lx)
1003
 
                                : 1.0 / calc_exp_posint(x1, -lx);
1004
 
        }
1005
 
        return (AWKNUM) pow((double) x1, (double) x2);
1006
 
}
1007
 
 
1008
 
/* r_tree_eval --- evaluate a subtree */
1009
 
 
1010
 
NODE *
1011
 
r_tree_eval(register NODE *tree, int iscond)
1012
 
{
1013
 
        register NODE *r, *t1, *t2;     /* return value & temporary subtrees */
1014
 
        register NODE **lhs;
1015
 
        register int di;
1016
 
        AWKNUM x, x1, x2;
1017
 
#ifdef _CRAY
1018
 
        long lx2;
1019
 
#endif
1020
 
 
1021
 
#ifndef TREE_EVAL_MACRO
1022
 
        if (tree == NULL)
1023
 
                cant_happen();
1024
 
        if (tree->type == Node_val) {
1025
 
                if (tree->stref <= 0)
1026
 
                        cant_happen();
1027
 
                return ((tree->flags & INTLSTR) != 0
1028
 
                        ? r_force_string(tree)
1029
 
                        : tree);
1030
 
        } else if (tree->type == Node_var) {
1031
 
                if (tree->var_value->stref <= 0)
1032
 
                        cant_happen();
1033
 
                if (! var_uninitialized(tree))
1034
 
                        return tree->var_value;
1035
 
        }
1036
 
#endif
1037
 
 
1038
 
        if (tree->type == Node_param_list) {
1039
 
                if ((tree->flags & FUNC) != 0)
1040
 
                        fatal(_("can't use function name `%s' as variable or array"),
1041
 
                                        tree->vname);
1042
 
 
1043
 
                tree = stack_ptr[tree->param_cnt];
1044
 
 
1045
 
                if (tree == NULL) {
1046
 
                        if (do_lint)
1047
 
                                lintwarn(_("reference to uninitialized argument `%s'"),
1048
 
                                                tree->vname);
1049
 
                        return Nnull_string;
1050
 
                }
1051
 
 
1052
 
                if (do_lint && var_uninitialized(tree))
1053
 
                        lintwarn(_("reference to uninitialized argument `%s'"),
1054
 
                              tree->vname);
1055
 
        }
1056
 
 
1057
 
        make_scalar(tree);
1058
 
 
1059
 
        switch (tree->type) {
1060
 
        case Node_var:
1061
 
                if (do_lint && var_uninitialized(tree))
1062
 
                        lintwarn(_("reference to uninitialized variable `%s'"),
1063
 
                              tree->vname);
1064
 
                return tree->var_value;
1065
 
 
1066
 
        case Node_and:
1067
 
                return tmp_number((AWKNUM) (eval_condition(tree->lnode)
1068
 
                                            && eval_condition(tree->rnode)));
1069
 
 
1070
 
        case Node_or:
1071
 
                return tmp_number((AWKNUM) (eval_condition(tree->lnode)
1072
 
                                            || eval_condition(tree->rnode)));
1073
 
 
1074
 
        case Node_not:
1075
 
                return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
1076
 
 
1077
 
                /* Builtins */
1078
 
        case Node_builtin:
1079
 
                return (*tree->builtin)(tree->subnode);
1080
 
 
1081
 
        case Node_K_getline:
1082
 
                return do_getline(tree);
1083
 
 
1084
 
        case Node_in_array:
1085
 
                return tmp_number((AWKNUM) (in_array(tree->lnode, tree->rnode) != NULL));
1086
 
 
1087
 
        case Node_indirect_func_call:
1088
 
        case Node_func_call:
1089
 
                return func_call(tree);
1090
 
 
1091
 
                /* unary operations */
1092
 
        case Node_NR:
1093
 
        case Node_FNR:
1094
 
        case Node_NF:
1095
 
        case Node_FIELDWIDTHS:
1096
 
        case Node_FPAT:
1097
 
        case Node_FS:
1098
 
        case Node_RS:
1099
 
        case Node_field_spec:
1100
 
        case Node_subscript:
1101
 
        case Node_IGNORECASE:
1102
 
        case Node_OFS:
1103
 
        case Node_ORS:
1104
 
        case Node_OFMT:
1105
 
        case Node_CONVFMT:
1106
 
        case Node_BINMODE:
1107
 
        case Node_LINT:
1108
 
        case Node_SUBSEP:
1109
 
        case Node_TEXTDOMAIN:
1110
 
                lhs = get_lhs(tree, (Func_ptr *) NULL, TRUE);
1111
 
                return *lhs;
1112
 
 
1113
 
        case Node_unary_minus:
1114
 
                t1 = tree_eval(tree->subnode);
1115
 
                x = -force_number(t1);
1116
 
                free_temp(t1);
1117
 
                return tmp_number(x);
1118
 
 
1119
 
        case Node_cond_exp:
1120
 
                if (eval_condition(tree->lnode))
1121
 
                        return tree_eval(tree->rnode->lnode);
1122
 
                return tree_eval(tree->rnode->rnode);
1123
 
 
1124
 
        case Node_match:
1125
 
        case Node_nomatch:
1126
 
        case Node_regex:
1127
 
        case Node_dynregex:
1128
 
                return match_op(tree);
1129
 
 
1130
 
        case Node_concat:
1131
 
                {
1132
 
                NODE **treelist;
1133
 
                NODE **strlist;
1134
 
                NODE *save_tree;
1135
 
                register NODE **treep;
1136
 
                register NODE **strp;
1137
 
                register size_t len;
1138
 
                register size_t supposed_len;
1139
 
                char *str;
1140
 
                register char *dest;
1141
 
                int alloc_count, str_count;
1142
 
                int i;
1143
 
 
1144
 
                /*
1145
 
                 * This is an efficiency hack for multiple adjacent string
1146
 
                 * concatenations, to avoid recursion and string copies.
1147
 
                 *
1148
 
                 * Node_concat trees grow downward to the left, so
1149
 
                 * descend to lowest (first) node, accumulating nodes
1150
 
                 * to evaluate to strings as we go.
1151
 
                 */
1152
 
 
1153
 
                /*
1154
 
                 * But first, no arbitrary limits. Count the number of
1155
 
                 * nodes and malloc the treelist and strlist arrays.
1156
 
                 * There will be alloc_count + 1 items to concatenate. We
1157
 
                 * also leave room for an extra pointer at the end to
1158
 
                 * use as a sentinel.  Thus, start alloc_count at 2.
1159
 
                 */
1160
 
                save_tree = tree;
1161
 
                for (alloc_count = 2; tree != NULL && tree->type == Node_concat;
1162
 
                                tree = tree->lnode)
1163
 
                        alloc_count++;
1164
 
                tree = save_tree;
1165
 
                emalloc(treelist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
1166
 
                emalloc(strlist, NODE **, sizeof(NODE *) * alloc_count, "tree_eval");
1167
 
 
1168
 
                /* Now, here we go. */
1169
 
                treep = treelist;
1170
 
                while (tree != NULL && tree->type == Node_concat) {
1171
 
                        *treep++ = tree->rnode;
1172
 
                        tree = tree->lnode;
1173
 
                }
1174
 
                *treep = tree;
1175
 
                /*
1176
 
                 * Now, evaluate to strings in LIFO order, accumulating
1177
 
                 * the string length, so we can do a single malloc at the
1178
 
                 * end.
1179
 
                 *
1180
 
                 * Evaluate the expressions first, then get their
1181
 
                 * lengthes, in case one of the expressions has a
1182
 
                 * side effect that changes one of the others.
1183
 
                 * See test/nasty.awk.
1184
 
                 *
1185
 
                 * dupnode the results a la do_print, to give us
1186
 
                 * more predicable behavior; compare gawk 3.0.6 to
1187
 
                 * nawk/mawk on test/nasty.awk.
1188
 
                 */
1189
 
                strp = strlist;
1190
 
                supposed_len = len = 0;
1191
 
                while (treep >= treelist) {
1192
 
                        NODE *n;
1193
 
 
1194
 
                        /* Here lies the wumpus's brother. R.I.P. */
1195
 
                        n = force_string(tree_eval(*treep--));
1196
 
                        *strp = dupnode(n);
1197
 
                        free_temp(n);
1198
 
                        supposed_len += (*strp)->stlen;
1199
 
                        strp++;
1200
 
                }
1201
 
                *strp = NULL;
1202
 
 
1203
 
                str_count = strp - strlist;
1204
 
                strp = strlist;
1205
 
                for (i = 0; i < str_count; i++) {
1206
 
                        len += (*strp)->stlen;
1207
 
                        strp++;
1208
 
                }
1209
 
                if (do_lint && supposed_len != len)
1210
 
                        lintwarn(_("concatenation: side effects in one expression have changed the length of another!"));
1211
 
                emalloc(str, char *, len+2, "tree_eval");
1212
 
                str[len] = str[len+1] = '\0';   /* for good measure */
1213
 
                dest = str;
1214
 
                strp = strlist;
1215
 
                while (*strp != NULL) {
1216
 
                        memcpy(dest, (*strp)->stptr, (*strp)->stlen);
1217
 
                        dest += (*strp)->stlen;
1218
 
                        unref(*strp);
1219
 
                        strp++;
1220
 
                }
1221
 
                r = make_str_node(str, len, ALREADY_MALLOCED);
1222
 
                r->flags |= TEMP;
1223
 
 
1224
 
                free(strlist);
1225
 
                free(treelist);
1226
 
                }
1227
 
                return r;
1228
 
 
1229
 
        /* assignments */
1230
 
        case Node_assign_concat:
1231
 
        {
1232
 
                Func_ptr after_assign = NULL;
1233
 
                NODE *l, *r, *t;
1234
 
 
1235
 
                /*
1236
 
                 * Note that something lovely like this:
1237
 
                 *
1238
 
                 * BEGIN { a = "a"; a = a (a = "b"); print a }
1239
 
                 *
1240
 
                 * is not defined.  It could print `ab' or `bb'.
1241
 
                 * Gawk 3.1.3 prints `ab', so we do that too, simply
1242
 
                 * by evaluating the LHS first.  Ugh.
1243
 
                 *
1244
 
                 * Thanks to mary1john@earthlink.net for pointing
1245
 
                 * out this issue.
1246
 
                 */
1247
 
                lhs = get_lhs(tree->lnode, &after_assign, FALSE);
1248
 
                *lhs = force_string(*lhs);
1249
 
                l = *lhs;
1250
 
 
1251
 
                /*
1252
 
                 * This is a hack. We temporarily increase the reference count
1253
 
                 * on l in case evaluating r might change the original value
1254
 
                 * of l.  We have to be careful about reducing it afterwards.
1255
 
                 * In particular, if the lhs changed during evaluation of the
1256
 
                 * rhs, we have to compensate.
1257
 
                 *
1258
 
                 * See test/nasty.awk.
1259
 
                 */
1260
 
                t = dupnode(l);
1261
 
                r = force_string(tree_eval(tree->rnode));
1262
 
 
1263
 
                if (l != *lhs) {
1264
 
                        /*
1265
 
                         * Something happened to the original
1266
 
                         * during the evaluation of the rhs.
1267
 
                         */
1268
 
                        unref(*lhs);
1269
 
                        *lhs = l;
1270
 
                }
1271
 
                else
1272
 
                        unref(t);
1273
 
 
1274
 
                /*
1275
 
                 * Don't clobber string constants!
1276
 
                 *
1277
 
                 * Also check stref; see test/strcat1.awk,
1278
 
                 * the test for l->stref == 1 can't be an
1279
 
                 * assertion.
1280
 
                 *
1281
 
                 * Thanks again to mary1john@earthlink.net for pointing
1282
 
                 * out this issue.
1283
 
                 */
1284
 
                if (l != r && (l->flags & PERM) == 0 && l->stref == 1) {
1285
 
                        size_t nlen = l->stlen + r->stlen + 2;
1286
 
 
1287
 
                        erealloc(l->stptr, char *, nlen, "interpret");
1288
 
                        memcpy(l->stptr + l->stlen, r->stptr, r->stlen);
1289
 
                        l->stlen += r->stlen;
1290
 
                        l->stptr[l->stlen] = '\0';
1291
 
                        free_wstr(l);
1292
 
                } else {
1293
 
                        char *nval;
1294
 
                        size_t nlen = l->stlen + r->stlen + 2;
1295
 
 
1296
 
                        emalloc(nval, char *, nlen, "interpret");
1297
 
                        memcpy(nval, l->stptr, l->stlen);
1298
 
                        memcpy(nval + l->stlen, r->stptr, r->stlen);
1299
 
                        unref(*lhs);
1300
 
                        *lhs = make_str_node(nval, l->stlen + r->stlen, ALREADY_MALLOCED);
1301
 
                }
1302
 
                (*lhs)->flags &= ~(NUMCUR|NUMBER);
1303
 
                (*lhs)->flags |= ASSIGNED;      /* for function pointers */
1304
 
                free_temp(r);
1305
 
 
1306
 
                if (after_assign)
1307
 
                        (*after_assign)();
1308
 
                return *lhs;
1309
 
        }
1310
 
        case Node_assign:
1311
 
                {
1312
 
                Func_ptr after_assign = NULL;
1313
 
 
1314
 
                if (do_lint && iscond)
1315
 
                        lintwarn(_("assignment used in conditional context"));
1316
 
                r = tree_eval(tree->rnode);
1317
 
                lhs = get_lhs(tree->lnode, &after_assign, FALSE);
1318
 
                assign_val(lhs, r);
1319
 
 
1320
 
                if (tree->lnode->type == Node_var)
1321
 
                        tree->lnode->var_value->flags |= ASSIGNED;      /* needed in handling of indirect function calls */
1322
 
 
1323
 
                if (after_assign)
1324
 
                        (*after_assign)();
1325
 
                return *lhs;
1326
 
                }
1327
 
 
1328
 
        /* other assignment types are easier because they are numeric */
1329
 
        case Node_preincrement:
1330
 
        case Node_predecrement:
1331
 
        case Node_postincrement:
1332
 
        case Node_postdecrement:
1333
 
        case Node_assign_exp:
1334
 
        case Node_assign_times:
1335
 
        case Node_assign_quotient:
1336
 
        case Node_assign_mod:
1337
 
        case Node_assign_plus:
1338
 
        case Node_assign_minus:
1339
 
                return op_assign(tree);
1340
 
        default:
1341
 
                break;  /* handled below */
1342
 
        }
1343
 
 
1344
 
        /*
1345
 
         * Evaluate subtrees in order to do binary operation, then keep going.
1346
 
         * Use dupnode to make sure that these values don't disappear out
1347
 
         * from under us during recursive subexpression evaluation.
1348
 
         */
1349
 
        t1 = dupnode(tree_eval(tree->lnode));
1350
 
        t2 = dupnode(tree_eval(tree->rnode));
1351
 
 
1352
 
        switch (tree->type) {
1353
 
        case Node_geq:
1354
 
        case Node_leq:
1355
 
        case Node_greater:
1356
 
        case Node_less:
1357
 
        case Node_notequal:
1358
 
        case Node_equal:
1359
 
                di = cmp_nodes(t1, t2);
1360
 
                unref(t1);
1361
 
                unref(t2);
1362
 
                switch (tree->type) {
1363
 
                case Node_equal:
1364
 
                        return tmp_number((AWKNUM) (di == 0));
1365
 
                case Node_notequal:
1366
 
                        return tmp_number((AWKNUM) (di != 0));
1367
 
                case Node_less:
1368
 
                        return tmp_number((AWKNUM) (di < 0));
1369
 
                case Node_greater:
1370
 
                        return tmp_number((AWKNUM) (di > 0));
1371
 
                case Node_leq:
1372
 
                        return tmp_number((AWKNUM) (di <= 0));
1373
 
                case Node_geq:
1374
 
                        return tmp_number((AWKNUM) (di >= 0));
1375
 
                default:
1376
 
                        cant_happen();
1377
 
                }
1378
 
                break;
1379
 
        default:
1380
 
                break;  /* handled below */
1381
 
        }
1382
 
 
1383
 
        x1 = force_number(t1);
1384
 
        x2 = force_number(t2);
1385
 
        unref(t1);
1386
 
        unref(t2);
1387
 
        switch (tree->type) {
1388
 
        case Node_exp:
1389
 
                return tmp_number(calc_exp(x1, x2));
1390
 
 
1391
 
        case Node_times:
1392
 
                return tmp_number(x1 * x2);
1393
 
 
1394
 
        case Node_quotient:
1395
 
                if (x2 == 0)
1396
 
                        fatal(_("division by zero attempted"));
1397
 
#ifdef _CRAY
1398
 
                /* special case for integer division, put in for Cray */
1399
 
                lx2 = x2;
1400
 
                if (lx2 == 0)
1401
 
                        return tmp_number(x1 / x2);
1402
 
                lx = (long) x1 / lx2;
1403
 
                if (lx * x2 == x1)
1404
 
                        return tmp_number((AWKNUM) lx);
1405
 
                else
1406
 
#endif
1407
 
                        return tmp_number(x1 / x2);
1408
 
 
1409
 
        case Node_mod:
1410
 
                if (x2 == 0)
1411
 
                        fatal(_("division by zero attempted in `%%'"));
1412
 
#ifdef HAVE_FMOD
1413
 
                return tmp_number(fmod(x1, x2));
1414
 
#else   /* ! HAVE_FMOD */
1415
 
                (void) modf(x1 / x2, &x);
1416
 
                return tmp_number(x1 - x * x2);
1417
 
#endif  /* ! HAVE_FMOD */
1418
 
 
1419
 
        case Node_plus:
1420
 
                return tmp_number(x1 + x2);
1421
 
 
1422
 
        case Node_minus:
1423
 
                return tmp_number(x1 - x2);
1424
 
 
1425
 
        default:
1426
 
                fatal(_("illegal type (%s) in tree_eval"), nodetype2str(tree->type));
1427
 
        }
1428
 
        return (NODE *) 0;
1429
 
}
1430
 
 
1431
 
/* eval_condition --- is TREE true or false? Returns 0==false, non-zero==true */
1432
 
 
1433
 
static int
1434
 
eval_condition(register NODE *tree)
1435
 
{
1436
 
        register NODE *t1;
1437
 
        register int ret;
1438
 
 
1439
 
        if (tree == NULL)       /* Null trees are the easiest kinds */
1440
 
                return TRUE;
1441
 
        if (tree->type == Node_line_range) {
1442
 
                /*
1443
 
                 * Node_line_range is kind of like Node_match, EXCEPT: the
1444
 
                 * lnode field (more properly, the condpair field) is a node
1445
 
                 * of a Node_cond_pair; whether we evaluate the lnode of that
1446
 
                 * node or the rnode depends on the triggered word.  More
1447
 
                 * precisely:  if we are not yet triggered, we tree_eval the
1448
 
                 * lnode; if that returns true, we set the triggered word. 
1449
 
                 * If we are triggered (not ELSE IF, note), we tree_eval the
1450
 
                 * rnode, clear triggered if it succeeds, and perform our
1451
 
                 * action (regardless of success or failure).  We want to be
1452
 
                 * able to begin and end on a single input record, so this
1453
 
                 * isn't an ELSE IF, as noted above.
1454
 
                 */
1455
 
                if (! tree->triggered) {
1456
 
                        if (! eval_condition(tree->condpair->lnode))
1457
 
                                return FALSE;
1458
 
                        else
1459
 
                                tree->triggered = TRUE;
1460
 
                }
1461
 
                /* Else we are triggered */
1462
 
                if (eval_condition(tree->condpair->rnode))
1463
 
                        tree->triggered = FALSE;
1464
 
                return TRUE;
1465
 
        }
1466
 
 
1467
 
        /*
1468
 
         * Could just be J.random expression. in which case, null and 0 are
1469
 
         * false, anything else is true 
1470
 
         */
1471
 
 
1472
 
        t1 = m_tree_eval(tree, TRUE);
1473
 
        if (t1->flags & MAYBE_NUM)
1474
 
                (void) force_number(t1);
1475
 
        if (t1->flags & NUMBER)
1476
 
                ret = (t1->numbr != 0.0);
1477
 
        else
1478
 
                ret = (t1->stlen != 0);
1479
 
        free_temp(t1);
1480
 
        return ret;
1481
 
}
1482
503
 
1483
504
/* cmp_nodes --- compare two nodes, returning negative, 0, positive */
1484
505
 
1485
506
int
1486
 
cmp_nodes(register NODE *t1, register NODE *t2)
 
507
cmp_nodes(NODE *t1, NODE *t2)
1487
508
{
1488
 
        register int ret;
1489
 
        register size_t len1, len2;
1490
 
        register int l;
1491
 
        int ldiff;
 
509
        int ret = 0;
 
510
        size_t len1, len2;
 
511
        int l, ldiff;
1492
512
 
1493
513
        if (t1 == t2)
1494
514
                return 0;
 
515
 
1495
516
        if (t1->flags & MAYBE_NUM)
1496
517
                (void) force_number(t1);
1497
518
        if (t2->flags & MAYBE_NUM)
1498
519
                (void) force_number(t2);
1499
520
        if ((t1->flags & NUMBER) && (t2->flags & NUMBER)) {
1500
521
                if (t1->numbr == t2->numbr)
1501
 
                        return 0;
 
522
                        ret = 0;
1502
523
                /* don't subtract, in case one or both are infinite */
1503
524
                else if (t1->numbr < t2->numbr)
1504
 
                        return -1;
 
525
                        ret = -1;
1505
526
                else
1506
 
                        return 1;
 
527
                        ret = 1;
 
528
                return ret;
1507
529
        }
 
530
 
1508
531
        (void) force_string(t1);
1509
532
        (void) force_string(t2);
1510
533
        len1 = t1->stlen;
1519
542
 
1520
543
#ifdef MBS_SUPPORT
1521
544
                if (gawk_mb_cur_max > 1) {
1522
 
                        mbstate_t mbs;
1523
 
                        memset(&mbs, 0, sizeof(mbstate_t));
1524
 
                        ret = strncasecmpmbs((const char *) cp1, mbs,
1525
 
                                             (const char *) cp2, mbs, l);
 
545
                        ret = strncasecmpmbs((const char *) cp1,
 
546
                                             (const char *) cp2, l);
1526
547
                } else
1527
548
#endif
1528
549
                /* Could use tolower() here; see discussion above. */
1533
554
        return (ret == 0 ? ldiff : ret);
1534
555
}
1535
556
 
1536
 
/* op_assign --- do +=, -=, etc. */
1537
 
 
1538
 
static NODE *
1539
 
op_assign(register NODE *tree)
1540
 
{
1541
 
        AWKNUM rval, lval;
1542
 
        NODE **lhs;
1543
 
        NODE *tmp;
1544
 
        Func_ptr after_assign = NULL;
1545
 
        int post = FALSE;
1546
 
 
1547
 
        /*
1548
 
         * For += etc, do the rhs first, since it can rearrange things,
1549
 
         * and *then* get the lhs.
1550
 
         */
1551
 
        if (tree->rnode != NULL) {
1552
 
                tmp = tree_eval(tree->rnode);
1553
 
                rval = force_number(tmp);
1554
 
                free_temp(tmp);
1555
 
        } else
1556
 
                rval = (AWKNUM) 1.0;
1557
 
 
1558
 
        lhs = get_lhs(tree->lnode, &after_assign, TRUE);
1559
 
        lval = force_number(*lhs);
1560
 
        unref(*lhs);
1561
 
 
1562
 
        switch(tree->type) {
1563
 
        case Node_postincrement:
1564
 
                post = TRUE;
1565
 
                /* fall through */
1566
 
        case Node_preincrement:
1567
 
        case Node_assign_plus:
1568
 
                *lhs = make_number(lval + rval);
1569
 
                break;
1570
 
 
1571
 
        case Node_postdecrement:
1572
 
                post = TRUE;
1573
 
                /* fall through */
1574
 
        case Node_predecrement:
1575
 
        case Node_assign_minus:
1576
 
                *lhs = make_number(lval - rval);
1577
 
                break;
1578
 
 
1579
 
        case Node_assign_exp:
1580
 
                *lhs = make_number(calc_exp(lval, rval));
1581
 
                break;
1582
 
 
1583
 
        case Node_assign_times:
1584
 
                *lhs = make_number(lval * rval);
1585
 
                break;
1586
 
 
1587
 
        case Node_assign_quotient:
1588
 
                if (rval == (AWKNUM) 0)
1589
 
                        fatal(_("division by zero attempted in `/='"));
1590
 
        {
1591
 
#ifdef _CRAY
1592
 
                long ltemp;
1593
 
 
1594
 
                /* special case for integer division, put in for Cray */
1595
 
                ltemp = rval;
1596
 
                if (ltemp == 0) {
1597
 
                        *lhs = make_number(lval / rval);
1598
 
                        break;
1599
 
                }
1600
 
                ltemp = (long) lval / ltemp;
1601
 
                if (ltemp * lval == rval)
1602
 
                        *lhs = make_number((AWKNUM) ltemp);
1603
 
                else
1604
 
#endif  /* _CRAY */
1605
 
                        *lhs = make_number(lval / rval);
1606
 
        }
1607
 
                break;
1608
 
 
1609
 
        case Node_assign_mod:
1610
 
                if (rval == (AWKNUM) 0)
1611
 
                        fatal(_("division by zero attempted in `%%='"));
1612
 
#ifdef HAVE_FMOD
1613
 
                *lhs = make_number(fmod(lval, rval));
1614
 
#else   /* ! HAVE_FMOD */
1615
 
        {
1616
 
                AWKNUM t1, t2;
1617
 
 
1618
 
                (void) modf(lval / rval, &t1);
1619
 
                t2 = lval - rval * t1;
1620
 
                *lhs = make_number(t2);
1621
 
        }
1622
 
#endif  /* ! HAVE_FMOD */
1623
 
                break;
1624
 
 
1625
 
        default:
1626
 
                cant_happen();
1627
 
        }
1628
 
 
1629
 
        (*lhs)->flags |= ASSIGNED;
1630
 
 
1631
 
        if (after_assign)
1632
 
                (*after_assign)();
1633
 
 
1634
 
        /* for postincrement or postdecrement, return the old value */
1635
 
        return (post ? tmp_number(lval) : *lhs);
1636
 
}
1637
 
 
1638
 
/*
1639
 
 * Avoiding memory leaks is difficult.  In paticular, any of `next',
1640
 
 * `nextfile', `break' or `continue' (when not in a loop), can longjmp
1641
 
 * out to the outermost level.  This leaks memory if it happens in a
1642
 
 * called function. It also leaks memory if it happens in a
1643
 
 * `for (iggy in foo)' loop, since such loops malloc an array of the
1644
 
 * current array indices to loop over, which provides stability.
1645
 
 *
1646
 
 * The following code takes care of these problems.  First comes the
1647
 
 * array-loop management code.  This can be a stack of arrays being looped
1648
 
 * on at any one time.  This stack serves for both mainline code and
1649
 
 * function body code. As each loop starts and finishes, it pushes its
1650
 
 * info onto this stack and off of it; whether the loop is in a function
1651
 
 * body or not isn't relevant.
1652
 
 *
1653
 
 * Since the list of indices is created using dupnode(), when popping
1654
 
 * this stack it should be safe to unref() things, and then memory
1655
 
 * will get finally released when the function call stack is popped.
1656
 
 * This means that the loop_stack should be popped first upon a `next'.
1657
 
 */
1658
 
 
1659
 
static struct loop_info {
1660
 
        const char *varname;    /* variable name, for debugging */
1661
 
        NODE **elems;           /* list of indices */
1662
 
        size_t nelems;          /* how many there are */
1663
 
} *loop_stack = NULL;
1664
 
size_t nloops = 0;              /* how many slots there are in the stack */
1665
 
size_t nloops_active = 0;       /* how many loops are actively stacked */
1666
 
 
1667
 
/* pop_forloop --- pop one for loop off the stack */
1668
 
 
1669
 
static void
1670
 
pop_forloop()
1671
 
{
1672
 
        int i, curloop;
1673
 
        struct loop_info *loop;
1674
 
 
1675
 
        assert(nloops_active > 0);
1676
 
 
1677
 
        curloop = --nloops_active;      /* 0-based indexing */
1678
 
        loop = & loop_stack[curloop];
1679
 
 
1680
 
        for (i = 0; i < loop->nelems; i++)
1681
 
                unref(loop->elems[i]);
1682
 
 
1683
 
        free(loop->elems);
1684
 
 
1685
 
        loop->elems = NULL;
1686
 
        loop->varname = NULL;
1687
 
        loop->nelems = 0;
1688
 
}
1689
 
 
1690
 
/* pop_forloops --- pop the for loops stack all the way */
1691
 
 
1692
 
static inline void
1693
 
pop_all_forloops()
1694
 
{
1695
 
        while (nloops_active > 0)
1696
 
                pop_forloop();  /* decrements nloops_active for us */
1697
 
}
1698
 
 
1699
 
/* push_forloop --- add a single for loop to the stack */
1700
 
 
1701
 
static void
1702
 
push_forloop(const char *varname, NODE **elems, size_t nelems)
1703
 
{
1704
 
#define NLOOPS  4       /* seems like a good guess */
1705
 
        if (loop_stack == NULL) {
1706
 
                /* allocate stack, set vars */
1707
 
                nloops = NLOOPS;
1708
 
                emalloc(loop_stack, struct loop_info *, nloops * sizeof(struct loop_info),
1709
 
                                "push_forloop");
1710
 
        } else if (nloops_active == nloops) {
1711
 
                /* grow stack, set vars */
1712
 
                nloops *= 2;
1713
 
                erealloc(loop_stack, struct loop_info *, nloops * sizeof(struct loop_info),
1714
 
                                "push_forloop");
1715
 
        }
1716
 
 
1717
 
        loop_stack[nloops_active].varname = varname;
1718
 
        loop_stack[nloops_active].elems = elems;
1719
 
        loop_stack[nloops_active].nelems = nelems;
1720
 
        nloops_active++;
1721
 
}
1722
 
 
1723
 
/*
1724
 
 * 2/2004:
1725
 
 * N.B. The code that uses fcalls[] *always* uses indexing.
1726
 
 * This avoids severe problems in case fcalls gets realloc()'ed
1727
 
 * during recursive tree_eval()'s or whatever, so that we don't
1728
 
 * have to carefully reassign pointers into the array.  The
1729
 
 * minor speed gain from using a pointer was offset too much
1730
 
 * by the hassles to get the code right and commented.
1731
 
 *
1732
 
 * Thanks and a tip of the hatlo to Brian Kernighan.
1733
 
 */
1734
 
 
1735
 
static struct fcall {
1736
 
        const char *fname;      /* function name */
1737
 
        size_t count;           /* how many args */
1738
 
        NODE *arglist;          /* list thereof */
1739
 
        NODE **prevstack;       /* function stack frame of previous function */
1740
 
        NODE **stack;           /* function stack frame of current function */
1741
 
} *fcalls = NULL;
1742
 
 
1743
 
static long fcall_list_size = 0;
1744
 
static long curfcall = -1;
1745
 
 
1746
 
/*
1747
 
 * get_curfunc_arg_count --- return number actual parameters
1748
 
 *
1749
 
 * This is for use by dynamically loaded C extension functions.
1750
 
 */
1751
 
size_t
1752
 
get_curfunc_arg_count(void)
1753
 
{
1754
 
        NODE *argp;
1755
 
        size_t argc;
1756
 
 
1757
 
        assert(curfcall >= 0);
1758
 
 
1759
 
        /* count the # of expressions in argument expression list */
1760
 
        for (argc = 0, argp = fcalls[curfcall].arglist;
1761
 
             argp != NULL; argp = argp->rnode)
1762
 
                argc++;
1763
 
 
1764
 
        return argc;
1765
 
}
1766
 
 
1767
 
/* pop_fcall --- pop off a single function call */
1768
 
 
1769
 
static void
1770
 
pop_fcall()
1771
 
{
1772
 
        NODE *n, **sp;
1773
 
        int count;
1774
 
 
1775
 
        assert(curfcall >= 0);
1776
 
        stack_ptr = fcalls[curfcall].prevstack;
1777
 
 
1778
 
        sp = fcalls[curfcall].stack;
1779
 
 
1780
 
        for (count = fcalls[curfcall].count; count > 0; count--) {
1781
 
                n = *sp++;
1782
 
                /*
1783
 
                 * If, while setting the value of an argument in push_args,
1784
 
                 * the recursively evaluating code exits, this argument
1785
 
                 * could never have been set to a value. So check for NULL,
1786
 
                 * first.
1787
 
                 */
1788
 
                if (n == NULL)
1789
 
                        continue;
1790
 
                if (n->type == Node_var)                /* local variable */
1791
 
                        unref(n->var_value);
1792
 
                else if (n->type == Node_var_array)     /* local array */
1793
 
                        assoc_clear(n);
1794
 
                freenode(n);
1795
 
        }
1796
 
        if (fcalls[curfcall].stack) {
1797
 
                free((char *) fcalls[curfcall].stack);
1798
 
                fcalls[curfcall].stack = NULL;
1799
 
        }
1800
 
        curfcall--;
1801
 
}
1802
 
 
1803
 
/* pop_fcall_stack --- pop off all function args, don't leak memory */
1804
 
 
1805
 
static inline void
1806
 
pop_fcall_stack()
1807
 
{
1808
 
        while (curfcall >= 0)
1809
 
                pop_fcall();
1810
 
}
1811
 
 
1812
 
/* push_args --- push function arguments onto the stack */
1813
 
 
1814
 
static void
1815
 
push_args(int count,
1816
 
        NODE *argp,
1817
 
        NODE **oldstack,
1818
 
        const char *func_name,
1819
 
        char **varnames)
1820
 
{
1821
 
        NODE *arg, *r, **sp;
1822
 
        int i;
1823
 
 
1824
 
        if (fcall_list_size == 0) {     /* first time */
1825
 
                emalloc(fcalls, struct fcall *, 10 * sizeof(struct fcall),
1826
 
                        "push_args");
1827
 
                fcall_list_size = 10;
1828
 
        }
1829
 
 
1830
 
        if (++curfcall >= fcall_list_size) {
1831
 
                fcall_list_size *= 2;
1832
 
                erealloc(fcalls, struct fcall *,
1833
 
                        fcall_list_size * sizeof(struct fcall), "push_args");
1834
 
        }
1835
 
 
1836
 
        if (count > 0) {
1837
 
                size_t nbytes = count * sizeof(NODE *);
1838
 
 
1839
 
                emalloc(fcalls[curfcall].stack, NODE **, nbytes, "push_args");
1840
 
                memset(fcalls[curfcall].stack, 0, nbytes);      /* Make sure these are all NULL pointers. */
1841
 
        } else
1842
 
                fcalls[curfcall].stack = NULL;
1843
 
        fcalls[curfcall].count = count;
1844
 
        fcalls[curfcall].fname = func_name;     /* not used, for debugging, just in case */
1845
 
        fcalls[curfcall].arglist = argp;
1846
 
        fcalls[curfcall].prevstack = oldstack;
1847
 
 
1848
 
        sp = fcalls[curfcall].stack;
1849
 
 
1850
 
        /* for each calling arg. add NODE * on stack */
1851
 
        for (i = 0; i < count; i++) {
1852
 
                getnode(r);
1853
 
                memset(r, 0, sizeof(*r));
1854
 
                *sp++ = r;
1855
 
                if (argp == NULL) {
1856
 
                        /* local variable */
1857
 
                        r->type = Node_var_new;
1858
 
                        r->var_value = Nnull_string;
1859
 
                        r->vname = varnames[i];
1860
 
                        r->rnode = NULL;
1861
 
                        continue;
1862
 
                }
1863
 
                arg = argp->lnode;
1864
 
                /* call by reference for arrays; see below also */
1865
 
                if (arg->type == Node_param_list)
1866
 
                        arg = fcalls[curfcall].prevstack[arg->param_cnt];
1867
 
 
1868
 
                if (arg->type == Node_var_array || arg->type == Node_var_new) {
1869
 
                        r->type = Node_array_ref;
1870
 
                        r->orig_array = arg;
1871
 
                        r->prev_array = arg;
1872
 
                } else if (arg->type == Node_array_ref) {
1873
 
                        *r = *arg;
1874
 
                        r->prev_array = arg;
1875
 
                } else {
1876
 
                        NODE *n = tree_eval(arg);
1877
 
 
1878
 
                        r->type = Node_var;
1879
 
                        r->lnode = dupnode(n);
1880
 
                        r->rnode = (NODE *) NULL;
1881
 
                        r->var_value->flags |= ASSIGNED;        /* For indirect function calls */
1882
 
                        free_temp(n);
1883
 
                }
1884
 
                r->vname = varnames[i];
1885
 
                argp = argp->rnode;
1886
 
        }
1887
 
 
1888
 
        if (argp != NULL) {
1889
 
                /* Left over calling args. */
1890
 
                warning(
1891
 
                    _("function `%s' called with more arguments than declared"),
1892
 
                    func_name);
1893
 
                /* Evaluate them, they may have side effects: */
1894
 
                do {
1895
 
                        arg = argp->lnode;
1896
 
                        if (arg->type == Node_param_list)
1897
 
                                arg = fcalls[curfcall].prevstack[arg->param_cnt];
1898
 
                        if (arg->type != Node_var_array &&
1899
 
                            arg->type != Node_array_ref &&
1900
 
                            arg->type != Node_var_new)
1901
 
                                free_temp(tree_eval(arg));
1902
 
                } while ((argp = argp->rnode) != NULL);
1903
 
        }
1904
 
 
1905
 
        stack_ptr = fcalls[curfcall].stack;
1906
 
}
1907
 
 
1908
 
/* func_call --- call a function, call by reference for arrays */
1909
 
 
1910
 
NODE **stack_ptr;
1911
 
 
1912
 
static NODE *
1913
 
func_call(NODE *tree)
1914
 
{
1915
 
        register NODE *r;
1916
 
        NODE *name, *arg_list;
1917
 
        NODE *f;
1918
 
        jmp_buf volatile func_tag_stack;
1919
 
        jmp_buf volatile loop_tag_stack;
1920
 
        int volatile save_loop_tag_valid = FALSE;
1921
 
        NODE *save_ret_node;
1922
 
        extern NODE *ret_node;
1923
 
        size_t current_nloops_active = 0;
1924
 
 
1925
 
        /* tree->rnode is a Node_val giving function name */
1926
 
        /* tree->lnode is Node_expression_list of calling args. */
1927
 
        name = tree->rnode;
1928
 
        arg_list = tree->lnode;
1929
 
 
1930
 
        /*
1931
 
         * After several attempts to both get the semantics right
1932
 
         * and to avoid duplicate code, here is the cleanest code that
1933
 
         * does the right thing.
1934
 
         *
1935
 
         * Pardon the gotos.
1936
 
         */
1937
 
 
1938
 
        /* First, decide if we can use a cached funcbody */
1939
 
        if (tree->type == Node_func_call) {     /* direct function call */
1940
 
                if (tree->funcbody != NULL) {
1941
 
                        f = tree->funcbody;
1942
 
                        goto out;
1943
 
                }
1944
 
 
1945
 
                /* Get the function body, cache it */
1946
 
                f = lookup(name->stptr);
1947
 
                if (f == NULL)
1948
 
                        fatal(_("function `%s' not defined"), name->stptr);
1949
 
                else if (f->type != Node_func)
1950
 
                        fatal(_("identifier `%s' is not a function"), name->stptr);
1951
 
 
1952
 
                tree->funcbody = f;     /* save for next call */
1953
 
                goto out;
1954
 
        }
1955
 
 
1956
 
        /* Indirect function call */
1957
 
 
1958
 
        /* Check for parameters first, since they shadow globals */
1959
 
        if (curfcall >= 0) {
1960
 
                int n = fcalls[curfcall].count;
1961
 
                NODE *parm;
1962
 
                int i;
1963
 
                int found = FALSE;
1964
 
 
1965
 
                for (i = 0; i < n; i++) {
1966
 
                        parm = fcalls[curfcall].stack[i];
1967
 
                        if (strcmp(parm->vname, name->stptr) == 0) {
1968
 
                                found = TRUE;
1969
 
                                break;
1970
 
                        }
1971
 
                }
1972
 
 
1973
 
                if (! found)
1974
 
                        goto look_for_global_symbol;
1975
 
 
1976
 
                f = NULL;
1977
 
                name = stack_ptr[i];
1978
 
                if (name->type == Node_var) {
1979
 
                        if ((name->var_value->flags & ASSIGNED) == 0 && tree->funcbody) {
1980
 
                                /* Should be safe to use cached value */
1981
 
                                f = tree->funcbody;
1982
 
                                goto out;
1983
 
                        }
1984
 
 
1985
 
                        force_string(name->var_value);
1986
 
                        f = lookup(name->var_value->stptr);
1987
 
                }
1988
 
 
1989
 
                if (f != NULL) {
1990
 
                        if (f->type == Node_func) {
1991
 
                                tree->funcbody = f;     /* save for next call */
1992
 
                                name->var_value->flags &= ~ASSIGNED;
1993
 
                                goto out;
1994
 
                        }
1995
 
                }
1996
 
 
1997
 
                fatal(_("function parameter `%s' is not a scalar and cannot be used for indirect function call"),
1998
 
                                                name->stptr);
1999
 
        }
2000
 
 
2001
 
look_for_global_symbol:
2002
 
 
2003
 
        /* not in a function call, or not a parameter, look it up globally */
2004
 
        f = lookup(name->stptr);
2005
 
        if (f != NULL) {
2006
 
                if (f->type == Node_func) {
2007
 
                        tree->funcbody = f;     /* save for next call */
2008
 
                        tree->type = Node_func_call;    /* make it a direct call */
2009
 
                        /*
2010
 
                         * This may not be so silly; it allows a unified syntax which is good
2011
 
                         * if someone is generating code. So leave it alone for now.
2012
 
                         */
2013
 
                        if (0 && do_lint)
2014
 
                                lintwarn(_("indirect call of real function `%s' is silly"), name->stptr);
2015
 
                        goto out;
2016
 
                } else if (f->type == Node_var) {
2017
 
                        char *fname;
2018
 
                        NODE *fvalue = f->var_value;
2019
 
 
2020
 
                        if ((fvalue->flags & ASSIGNED) == 0 && tree->funcbody) {
2021
 
                                f = tree->funcbody;
2022
 
                                goto out;
2023
 
                        }
2024
 
 
2025
 
                        force_string(f->var_value);
2026
 
                        fname = f->var_value->stptr;
2027
 
                        f = lookup(f->var_value->stptr);
2028
 
                        if (f != NULL && f->type == Node_func) {
2029
 
                                tree->funcbody = f;     /* save for next call */
2030
 
                                fvalue->flags &= ~ASSIGNED;
2031
 
                                goto out;
2032
 
                        }
2033
 
                        else
2034
 
                                fatal(_("function `%s' called indirectly through `%s' does not exist"),
2035
 
                                                fname, name->stptr);
2036
 
                }
2037
 
        }
2038
 
                
2039
 
        fatal(_("identifier `%s' cannot be used for indirect function call"), name->stptr);
2040
 
 
2041
 
out:
2042
 
 
2043
 
#ifdef FUNC_TRACE
2044
 
        fprintf(stderr, "function `%s' called\n", name->stptr);
2045
 
#endif
2046
 
        push_args(f->lnode->param_cnt, arg_list, stack_ptr, name->stptr,
2047
 
                        f->parmlist);
2048
 
 
2049
 
        /*
2050
 
         * Execute function body, saving context, as a return statement
2051
 
         * will longjmp back here.
2052
 
         *
2053
 
         * Have to save and restore the loop_tag stuff so that a return
2054
 
         * inside a loop in a function body doesn't scrog any loops going
2055
 
         * on in the main program.  We save the necessary info in variables
2056
 
         * local to this function so that function nesting works OK.
2057
 
         * We also only bother to save the loop stuff if we're in a loop
2058
 
         * when the function is called.
2059
 
         */
2060
 
        if (loop_tag_valid) {
2061
 
                int junk = 0;
2062
 
 
2063
 
                save_loop_tag_valid = (volatile int) loop_tag_valid;
2064
 
                PUSH_BINDING(loop_tag_stack, loop_tag, junk);
2065
 
                loop_tag_valid = FALSE;
2066
 
        }
2067
 
        PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
2068
 
        current_nloops_active = nloops_active;
2069
 
        save_ret_node = ret_node;
2070
 
        ret_node = Nnull_string;        /* default return value */
2071
 
        INCREMENT(f->exec_count);       /* count function calls */
2072
 
        if (setjmp(func_tag) == 0)
2073
 
                (void) interpret(f->rnode);
2074
 
 
2075
 
        while (nloops_active > current_nloops_active)
2076
 
                pop_forloop();
2077
 
 
2078
 
        r = ret_node;
2079
 
        ret_node = (NODE *) save_ret_node;
2080
 
        RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
2081
 
        pop_fcall();
2082
 
 
2083
 
        /* Restore the loop_tag stuff if necessary. */
2084
 
        if (save_loop_tag_valid) {
2085
 
                int junk = 0;
2086
 
 
2087
 
                loop_tag_valid = (int) save_loop_tag_valid;
2088
 
                RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
2089
 
        }
2090
 
 
2091
 
        return r;
2092
 
}
 
557
 
 
558
#if defined(PROFILING) || defined(DEBUGGING)
 
559
static void
 
560
push_frame(NODE *f)
 
561
{
 
562
        static long max_fcall;
 
563
 
 
564
        /* NB: frame numbering scheme as in GDB. frame_ptr => frame #0. */
 
565
 
 
566
        fcall_count++;
 
567
        if (fcall_list == NULL) {
 
568
                max_fcall = 10;
 
569
                emalloc(fcall_list, NODE **, (max_fcall + 1) * sizeof(NODE *), "push_frame");
 
570
        } else if (fcall_count == max_fcall) {
 
571
                max_fcall *= 2;
 
572
                erealloc(fcall_list, NODE **, (max_fcall + 1) * sizeof(NODE *), "push_frame");
 
573
        }
 
574
 
 
575
        if (fcall_count > 1)
 
576
                memmove(fcall_list + 2, fcall_list + 1, (fcall_count - 1) * sizeof(NODE *)); 
 
577
        fcall_list[1] = f;
 
578
}
 
579
 
 
580
static void
 
581
pop_frame()
 
582
{
 
583
#ifdef DEBUGGING
 
584
        extern void frame_popped();
 
585
#endif
 
586
        if (fcall_count > 1)
 
587
                memmove(fcall_list + 1, fcall_list + 2, (fcall_count - 1) * sizeof(NODE *)); 
 
588
        fcall_count--;
 
589
        assert(fcall_count >= 0);
 
590
#ifdef DEBUGGING
 
591
        frame_popped();
 
592
#endif
 
593
}
 
594
#else   /* not PROFILING or DEBUGGING */
 
595
#define push_frame(p)   /* nothing */
 
596
#define pop_frame()             /* nothing */
 
597
#endif
 
598
 
2093
599
 
2094
600
#ifdef PROFILING
 
601
 
2095
602
/* dump_fcall_stack --- print a backtrace of the awk function calls */
2096
603
 
2097
604
void
2098
605
dump_fcall_stack(FILE *fp)
2099
606
{
2100
 
        int i;
2101
 
 
2102
 
        if (curfcall < 0)
 
607
 
 
608
        NODE *f, *func;
 
609
        long i = 0;
 
610
 
 
611
        if (fcall_count == 0)
2103
612
                return;
2104
 
 
2105
613
        fprintf(fp, _("\n\t# Function Call Stack:\n\n"));
2106
 
        for (i = curfcall; i >= 0; i--)
2107
 
                fprintf(fp, "\t# %3d. %s\n", i+1, fcalls[i].fname);
2108
 
        fprintf(fp, _("\t# -- main --\n"));
 
614
 
 
615
        /* current frame */
 
616
        func = frame_ptr->func_node;
 
617
        fprintf(fp, "\t# %3ld. %s\n", i, func->lnode->param);
 
618
 
 
619
        /* outer frames except main */
 
620
        for (i = 1; i < fcall_count; i++) {
 
621
                f = fcall_list[i];
 
622
                func = f->func_node;
 
623
                fprintf(fp, "\t# %3ld. %s\n", i, func->lnode->param);
 
624
        }
 
625
 
 
626
        fprintf(fp, "\t# %3ld. -- main --\n", fcall_count);
2109
627
}
 
628
 
2110
629
#endif /* PROFILING */
2111
630
 
2112
 
/*
2113
 
 * r_get_lhs:
2114
 
 * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
2115
 
 * value of the var, or where to store the var's new value 
2116
 
 *
2117
 
 * For the special variables, don't unref their current value if it's
2118
 
 * the same as the internal copy; perhaps the current one is used in
2119
 
 * a concatenation or some other expression somewhere higher up in the
2120
 
 * call chain.  Ouch.
2121
 
 */
2122
 
 
2123
 
NODE **
2124
 
r_get_lhs(register NODE *ptr, Func_ptr *assign, int reference)
2125
 
{
2126
 
        register NODE **aptr = NULL;
2127
 
        register NODE *n;
2128
 
 
2129
 
        if (assign)
2130
 
                *assign = NULL; /* for safety */
2131
 
        if (ptr->type == Node_param_list) {
2132
 
                if ((ptr->flags & FUNC) != 0)
2133
 
                        fatal(_("can't use function name `%s' as variable or array"), ptr->vname);
2134
 
                ptr = stack_ptr[ptr->param_cnt];
2135
 
        }
2136
 
 
2137
 
        make_scalar(ptr);
2138
 
 
2139
 
        switch (ptr->type) {
2140
 
        case Node_var:
2141
 
                if (do_lint && reference && var_uninitialized(ptr))
2142
 
                        lintwarn(_("reference to uninitialized variable `%s'"),
2143
 
                                              ptr->vname);
2144
 
 
2145
 
                aptr = &(ptr->var_value);
2146
 
#ifdef GAWKDEBUG
2147
 
                if (ptr->var_value->stref <= 0)
2148
 
                        cant_happen();
2149
 
#endif
2150
 
                break;
2151
 
 
2152
 
        case Node_FIELDWIDTHS:
2153
 
                aptr = &(FIELDWIDTHS_node->var_value);
2154
 
                if (assign != NULL)
2155
 
                        *assign = set_FIELDWIDTHS;
2156
 
                break;
2157
 
 
2158
 
        case Node_RS:
2159
 
                aptr = &(RS_node->var_value);
2160
 
                if (assign != NULL)
2161
 
                        *assign = set_RS;
2162
 
                break;
2163
 
 
2164
 
        case Node_FS:
2165
 
                aptr = &(FS_node->var_value);
2166
 
                if (assign != NULL)
2167
 
                        *assign = set_FS;
2168
 
                break;
2169
 
 
2170
 
        case Node_FPAT:
2171
 
                aptr = &(FPAT_node->var_value);
2172
 
                if (assign != NULL)
2173
 
                        *assign = set_FPAT;
2174
 
                break;
2175
 
 
2176
 
        case Node_FNR:
2177
 
                if (FNR_node->var_value->numbr != FNR) {
2178
 
                        unref(FNR_node->var_value);
2179
 
                        FNR_node->var_value = make_number((AWKNUM) FNR);
2180
 
                }
2181
 
                aptr = &(FNR_node->var_value);
2182
 
                if (assign != NULL)
2183
 
                        *assign = set_FNR;
2184
 
                break;
2185
 
 
2186
 
        case Node_NR:
2187
 
                if (NR_node->var_value->numbr != NR) {
2188
 
                        unref(NR_node->var_value);
2189
 
                        NR_node->var_value = make_number((AWKNUM) NR);
2190
 
                }
2191
 
                aptr = &(NR_node->var_value);
2192
 
                if (assign != NULL)
2193
 
                        *assign = set_NR;
2194
 
                break;
2195
 
 
2196
 
        case Node_NF:
2197
 
                if (NF == -1 || NF_node->var_value->numbr != NF) {
2198
 
                        if (NF == -1)
2199
 
                                (void) get_field(UNLIMITED-1, assign); /* parse record */
2200
 
                        unref(NF_node->var_value);
2201
 
                        NF_node->var_value = make_number((AWKNUM) NF);
2202
 
                }
2203
 
                aptr = &(NF_node->var_value);
2204
 
                if (assign != NULL)
2205
 
                        *assign = set_NF;
2206
 
                break;
2207
 
 
2208
 
        case Node_IGNORECASE:
2209
 
                aptr = &(IGNORECASE_node->var_value);
2210
 
                if (assign != NULL)
2211
 
                        *assign = set_IGNORECASE;
2212
 
                break;
2213
 
 
2214
 
        case Node_BINMODE:
2215
 
                aptr = &(BINMODE_node->var_value);
2216
 
                if (assign != NULL)
2217
 
                        *assign = set_BINMODE;
2218
 
                break;
2219
 
 
2220
 
        case Node_LINT:
2221
 
                aptr = &(LINT_node->var_value);
2222
 
                if (assign != NULL)
2223
 
                        *assign = set_LINT;
2224
 
                break;
2225
 
 
2226
 
        case Node_OFMT:
2227
 
                aptr = &(OFMT_node->var_value);
2228
 
                if (assign != NULL)
2229
 
                        *assign = set_OFMT;
2230
 
                break;
2231
 
 
2232
 
        case Node_CONVFMT:
2233
 
                aptr = &(CONVFMT_node->var_value);
2234
 
                if (assign != NULL)
2235
 
                        *assign = set_CONVFMT;
2236
 
                break;
2237
 
 
2238
 
        case Node_ORS:
2239
 
                aptr = &(ORS_node->var_value);
2240
 
                if (assign != NULL)
2241
 
                        *assign = set_ORS;
2242
 
                break;
2243
 
 
2244
 
        case Node_OFS:
2245
 
                aptr = &(OFS_node->var_value);
2246
 
                if (assign != NULL)
2247
 
                        *assign = set_OFS;
2248
 
                break;
2249
 
 
2250
 
        case Node_SUBSEP:
2251
 
                aptr = &(SUBSEP_node->var_value);
2252
 
                if (assign != NULL)
2253
 
                        *assign = set_SUBSEP;
2254
 
                break;
2255
 
 
2256
 
        case Node_TEXTDOMAIN:
2257
 
                aptr = &(TEXTDOMAIN_node->var_value);
2258
 
                if (assign != NULL)
2259
 
                        *assign = set_TEXTDOMAIN;
2260
 
                break;
2261
 
 
2262
 
        case Node_field_spec:
2263
 
                {
2264
 
                int field_num;
2265
 
 
2266
 
                n = tree_eval(ptr->lnode);
2267
 
                if (do_lint) {
2268
 
                        if ((n->flags & NUMBER) == 0) {
2269
 
                                lintwarn(_("attempt to field reference from non-numeric value"));
2270
 
                                if (n->stlen == 0)
2271
 
                                        lintwarn(_("attempt to reference from null string"));
2272
 
                        }
2273
 
                }
2274
 
                field_num = (int) force_number(n);
2275
 
                free_temp(n);
2276
 
                if (field_num < 0)
2277
 
                        fatal(_("attempt to access field %d"), field_num);
2278
 
                if (field_num == 0 && field0_valid) {   /* short circuit */
2279
 
                        aptr = &fields_arr[0];
2280
 
                        if (assign != NULL)
2281
 
                                *assign = reset_record;
2282
 
                } else
2283
 
                        aptr = get_field(field_num, assign);
2284
 
                if (do_lint && reference && (*aptr == Null_field || *aptr == Nnull_string))
2285
 
                        lintwarn(_("reference to uninitialized field `$%d'"),
2286
 
                                              field_num);
2287
 
                break;
2288
 
                }
2289
 
 
2290
 
        case Node_subscript:
2291
 
                n = get_array(ptr->lnode);
2292
 
                aptr = assoc_lookup(n, concat_exp(ptr->rnode), reference);
2293
 
                break;
2294
 
 
2295
 
        case Node_builtin:
2296
 
#if 1
2297
 
                /* in gawk for a while */
2298
 
                fatal(_("assignment is not allowed to result of builtin function"));
2299
 
#else
2300
 
                /*
2301
 
                 * This is how Christos at Deshaw did it.
2302
 
                 * Does this buy us anything?
2303
 
                 */
2304
 
                if (ptr->builtin == NULL)
2305
 
                        fatal(_("assignment is not allowed to result of builtin function"));
2306
 
                ptr->callresult = (*ptr->builtin)(ptr->subnode);
2307
 
                aptr = &ptr->callresult;
2308
 
                break;
2309
 
#endif
2310
 
 
2311
 
        default:
2312
 
                fprintf(stderr, "type = %s\n", nodetype2str(ptr->type));
2313
 
                fflush(stderr);
2314
 
                cant_happen();
2315
 
        }
2316
 
        return aptr;
2317
 
}
2318
 
 
2319
 
/* match_op --- do ~ and !~ */
2320
 
 
2321
 
static NODE *
2322
 
match_op(register NODE *tree)
2323
 
{
2324
 
        register NODE *t1;
2325
 
        register Regexp *rp;
2326
 
        int i;
2327
 
        int match = TRUE;
2328
 
        int kludge_need_start = 0;      /* FIXME: --- see below */
2329
 
 
2330
 
        if (tree->type == Node_nomatch)
2331
 
                match = FALSE;
2332
 
        if (tree->type == Node_regex)
2333
 
                t1 = *get_field(0, (Func_ptr *) 0);
2334
 
        else {
2335
 
                t1 = force_string(tree_eval(tree->lnode));
2336
 
                tree = tree->rnode;
2337
 
        }
2338
 
        rp = re_update(tree);
2339
 
        /*
2340
 
         * FIXME:
2341
 
         *
2342
 
         * Any place where research() is called with a last parameter of
2343
 
         * zero, we need to use the avoid_dfa test. This appears here and
2344
 
         * in the code for Node_K_switch.
2345
 
         *
2346
 
         * A new or improved dfa that distinguishes beginning/end of
2347
 
         * string from beginning/end of line will allow us to get rid of
2348
 
         * this temporary hack.
2349
 
         *
2350
 
         * The avoid_dfa() function is in re.c; it is not very smart.
2351
 
         */
2352
 
        if (avoid_dfa(tree, t1->stptr, t1->stlen))
2353
 
                kludge_need_start = RE_NEED_START;
2354
 
        i = research(rp, t1->stptr, 0, t1->stlen, kludge_need_start);
2355
 
        i = (i == -1) ^ (match == TRUE);
2356
 
        free_temp(t1);
2357
 
        return tmp_number((AWKNUM) i);
2358
 
}
2359
 
 
2360
631
/* set_IGNORECASE --- update IGNORECASE as appropriate */
2361
632
 
2362
633
void
2485
756
/* fmt_ok --- is the conversion format a valid one? */
2486
757
 
2487
758
NODE **fmt_list = NULL;
2488
 
static int fmt_ok P((NODE *n));
2489
 
static int fmt_index P((NODE *n));
 
759
static int fmt_ok(NODE *n);
 
760
static int fmt_index(NODE *n);
2490
761
 
2491
762
static int
2492
763
fmt_ok(NODE *n)
2528
799
static int
2529
800
fmt_index(NODE *n)
2530
801
{
2531
 
        register int ix = 0;
 
802
        int ix = 0;
2532
803
        static int fmt_num = 4;
2533
804
        static int fmt_hiwater = 0;
2534
805
 
2641
912
         */
2642
913
}
2643
914
 
2644
 
/*
2645
 
 * assign_val --- do mechanics of assignment, for calling from multiple
2646
 
 *                places.
2647
 
 */
2648
 
 
2649
 
NODE *
2650
 
assign_val(NODE **lhs_p, NODE *rhs)
2651
 
{
2652
 
        if (rhs != *lhs_p) {
2653
 
                /*
2654
 
                 * Since we know that the nodes are different,
2655
 
                 * we can do the unref() before the dupnode().
2656
 
                 */
2657
 
                unref(*lhs_p);
2658
 
                *lhs_p = dupnode(rhs);
2659
 
                if ((*lhs_p)->type != Node_val)
2660
 
                        (*lhs_p)->funcbody = NULL;
2661
 
        }
2662
 
        return *lhs_p;
2663
 
}
2664
 
 
2665
915
/* update_ERRNO_saved --- update the value of ERRNO based on argument */
2666
916
 
2667
917
void
2686
936
        update_ERRNO_saved(errno);
2687
937
}
2688
938
 
 
939
/* update_NR --- update the value of NR */
 
940
 
 
941
void
 
942
update_NR()
 
943
{
 
944
        if (NR_node->var_value->numbr != NR) {
 
945
                unref(NR_node->var_value);
 
946
                NR_node->var_value = make_number((AWKNUM) NR);
 
947
        }
 
948
}
 
949
 
 
950
/* update_NF --- update the value of NF */
 
951
 
 
952
void
 
953
update_NF()
 
954
{
 
955
        if (NF == -1 || NF_node->var_value->numbr != NF) {
 
956
                if (NF == -1)
 
957
                        (void) get_field(UNLIMITED - 1, NULL); /* parse record */
 
958
                unref(NF_node->var_value);
 
959
                NF_node->var_value = make_number((AWKNUM) NF);
 
960
        }
 
961
}
 
962
 
 
963
/* update_FNR --- update the value of FNR */
 
964
 
 
965
void
 
966
update_FNR()
 
967
{
 
968
        if (FNR_node->var_value->numbr != FNR) {
 
969
                unref(FNR_node->var_value);
 
970
                FNR_node->var_value = make_number((AWKNUM) FNR);
 
971
        }
 
972
}
 
973
 
2689
974
/* comp_func --- array index comparison function for qsort */
2690
975
 
2691
 
static int
 
976
int
2692
977
comp_func(const void *p1, const void *p2)
2693
978
{
2694
979
        size_t len1, len2;
2699
984
        t1 = *((const NODE *const *) p1);
2700
985
        t2 = *((const NODE *const *) p2);
2701
986
 
2702
 
/*
2703
 
        t1 = force_string(t1);
2704
 
        t2 = force_string(t2);
2705
 
*/
2706
987
        len1 = t1->ahname_len;
2707
988
        str1 = t1->ahname_str;
2708
989
 
2715
996
        return (cmp1 != 0 ? cmp1 :
2716
997
                len1 < len2 ? -1 : (len1 > len2));
2717
998
}
 
999
 
 
1000
 
 
1001
NODE *frame_ptr;        /* current frame */
 
1002
STACK_ITEM *stack_ptr = NULL;
 
1003
STACK_ITEM *stack_bottom;
 
1004
STACK_ITEM *stack_top;
 
1005
static unsigned long STACK_SIZE = 256;    /* initial size of stack */
 
1006
int max_args = 0;       /* maximum # of arguments to printf, print, sprintf,
 
1007
                         * or # of array subscripts, or adjacent strings     
 
1008
                         * to be concatenated.
 
1009
                         */
 
1010
NODE **args_array = NULL;
 
1011
 
 
1012
/* grow_stack --- grow the size of runtime stack */
 
1013
 
 
1014
/* N.B. stack_ptr points to the topmost occupied location
 
1015
 *      on the stack, not the first free location.
 
1016
 */
 
1017
 
 
1018
STACK_ITEM *
 
1019
grow_stack()
 
1020
{
 
1021
        if (stack_ptr == NULL) {
 
1022
                char *val;
 
1023
                if ((val = getenv("STACKSIZE")) != NULL) {
 
1024
                        if (isdigit(*val)) {
 
1025
                                unsigned long n = 0;
 
1026
                                for (; *val && isdigit(*val); val++)
 
1027
                                        n = (n * 10) + *val - '0';
 
1028
                                if (n >= 1)
 
1029
                                        STACK_SIZE = n;
 
1030
                        }
 
1031
                }
 
1032
 
 
1033
                emalloc(stack_bottom, STACK_ITEM *, STACK_SIZE * sizeof(STACK_ITEM), "grow_stack");
 
1034
                stack_ptr = stack_bottom - 1;
 
1035
                stack_top = stack_bottom + STACK_SIZE - 1;
 
1036
 
 
1037
                /* initialize frame pointer */
 
1038
                getnode(frame_ptr);
 
1039
                frame_ptr->type = Node_frame;
 
1040
                frame_ptr->stack = NULL;
 
1041
                frame_ptr->func_node = NULL;    /* in main */
 
1042
                frame_ptr->vname = NULL;
 
1043
                frame_ptr->loop_count = 0;
 
1044
                return stack_ptr;
 
1045
        }
 
1046
 
 
1047
        STACK_SIZE *= 2;
 
1048
        erealloc(stack_bottom, STACK_ITEM *, STACK_SIZE * sizeof(STACK_ITEM), "grow_stack");
 
1049
        stack_top = stack_bottom + STACK_SIZE - 1;
 
1050
        stack_ptr = stack_bottom + STACK_SIZE / 2;
 
1051
        return stack_ptr;
 
1052
}
 
1053
 
 
1054
/*
 
1055
 * r_get_lhs:
 
1056
 * This returns a POINTER to a node pointer (var's value).
 
1057
 * used to store the var's new value.
 
1058
 */
 
1059
 
 
1060
NODE **
 
1061
r_get_lhs(NODE *n, int reference)
 
1062
{
 
1063
        int isparam = FALSE;
 
1064
 
 
1065
        if (n->type == Node_param_list) {
 
1066
                if ((n->flags & FUNC) != 0)
 
1067
                        fatal(_("can't use function name `%s' as variable or array"),
 
1068
                                        n->vname);
 
1069
                isparam = TRUE;
 
1070
                n = GET_PARAM(n->param_cnt);
 
1071
        }
 
1072
 
 
1073
        switch (n->type) {
 
1074
        case Node_var_array:
 
1075
                fatal(_("attempt to use array `%s' in a scalar context"),
 
1076
                                array_vname(n));
 
1077
        case Node_array_ref:
 
1078
                if (n->orig_array->type == Node_var_array)
 
1079
                        fatal(_("attempt to use array `%s' in a scalar context"),
 
1080
                                        array_vname(n));
 
1081
                n->orig_array->type = Node_var;
 
1082
                n->orig_array->var_value = Nnull_string;
 
1083
                /* fall through */
 
1084
        case Node_var_new:
 
1085
                n->type = Node_var;
 
1086
                n->var_value = Nnull_string;
 
1087
                break;
 
1088
 
 
1089
        case Node_var:
 
1090
                break;
 
1091
 
 
1092
#if 0
 
1093
        case Node_builtin:
 
1094
                /* in gawk for a while */
 
1095
                fatal(_("assignment is not allowed to result of builtin function"));
 
1096
#endif
 
1097
 
 
1098
        default:
 
1099
                cant_happen();
 
1100
        }
 
1101
 
 
1102
        if (do_lint && reference && var_uninitialized(n))
 
1103
                lintwarn((isparam ?
 
1104
                        _("reference to uninitialized argument `%s'") :
 
1105
                        _("reference to uninitialized variable `%s'")),
 
1106
                                n->vname);
 
1107
        return &n->var_value;
 
1108
}
 
1109
 
 
1110
 
 
1111
/* r_get_field --- get the address of a field node */
 
1112
 
 
1113
static inline NODE **
 
1114
r_get_field(NODE *n, Func_ptr *assign, int reference)
 
1115
{
 
1116
        long field_num;
 
1117
        NODE **lhs;
 
1118
 
 
1119
        if (assign)
 
1120
                *assign = NULL;
 
1121
        if (do_lint) {
 
1122
                if ((n->flags & NUMBER) == 0) {
 
1123
                        lintwarn(_("attempt to field reference from non-numeric value"));
 
1124
                        if (n->stlen == 0)
 
1125
                                lintwarn(_("attempt to field reference from null string"));
 
1126
                }
 
1127
        }
 
1128
 
 
1129
        field_num = (long) force_number(n);
 
1130
        if (field_num < 0)
 
1131
                fatal(_("attempt to access field %ld"), field_num);
 
1132
 
 
1133
        if (field_num == 0 && field0_valid) {           /* short circuit */
 
1134
                lhs = &fields_arr[0];
 
1135
                if (assign)
 
1136
                        *assign = reset_record;
 
1137
        } else
 
1138
                lhs = get_field(field_num, assign);
 
1139
        if (do_lint && reference && (*lhs == Null_field || *lhs == Nnull_string))
 
1140
                lintwarn(_("reference to uninitialized field `$%ld'"),
 
1141
                              field_num);
 
1142
        return lhs;
 
1143
}
 
1144
 
 
1145
 
 
1146
/*
 
1147
 * calc_exp_posint --- calculate x^n for positive integral n,
 
1148
 * using exponentiation by squaring without recursion.
 
1149
 */
 
1150
 
 
1151
static AWKNUM
 
1152
calc_exp_posint(AWKNUM x, long n)
 
1153
{
 
1154
        AWKNUM mult = 1;
 
1155
 
 
1156
        while (n > 1) {
 
1157
                if ((n % 2) == 1)
 
1158
                        mult *= x;
 
1159
                x *= x;
 
1160
                n /= 2;
 
1161
        }
 
1162
        return mult * x;
 
1163
}
 
1164
 
 
1165
/* calc_exp --- calculate x1^x2 */
 
1166
 
 
1167
AWKNUM
 
1168
calc_exp(AWKNUM x1, AWKNUM x2)
 
1169
{
 
1170
        long lx;
 
1171
 
 
1172
        if ((lx = x2) == x2) {          /* integer exponent */
 
1173
                if (lx == 0)
 
1174
                        return 1;
 
1175
                return (lx > 0) ? calc_exp_posint(x1, lx)
 
1176
                                : 1.0 / calc_exp_posint(x1, -lx);
 
1177
        }
 
1178
        return (AWKNUM) pow((double) x1, (double) x2);
 
1179
}
 
1180
 
 
1181
 
 
1182
/* setup_frame --- setup new frame for function call */ 
 
1183
 
 
1184
static void
 
1185
setup_frame(INSTRUCTION *pc)
 
1186
{
 
1187
        NODE *r = NULL;
 
1188
        NODE *m;
 
1189
        NODE *f;
 
1190
        NODE **sp = NULL;
 
1191
        char **varnames;
 
1192
        int pcount, arg_count, i;
 
1193
 
 
1194
        f = pc->func_body;
 
1195
        pcount = f->lnode->param_cnt;
 
1196
        varnames = f->parmlist;
 
1197
        arg_count = (pc + 1)->expr_count;
 
1198
 
 
1199
        /* check for extra args */ 
 
1200
        if (arg_count > pcount) {
 
1201
                warning(
 
1202
                        _("function `%s' called with more arguments than declared"),
 
1203
                        f->vname);
 
1204
                do {
 
1205
                        r = POP();
 
1206
                        if (r->type == Node_val)
 
1207
                                DEREF(r);
 
1208
                } while (--arg_count > pcount);
 
1209
        }
 
1210
 
 
1211
        if (pcount > 0) {
 
1212
                emalloc(sp, NODE **, pcount * sizeof(NODE *), "setup_frame");
 
1213
                memset(sp, 0, pcount * sizeof(NODE *));
 
1214
        }
 
1215
 
 
1216
        for (i = 0; i < pcount; i++) {
 
1217
                getnode(r);
 
1218
                memset(r, 0, sizeof(NODE));
 
1219
                sp[i] = r;
 
1220
                if (i >= arg_count) {
 
1221
                        /* local variable */
 
1222
                        r->type = Node_var_new;
 
1223
                        r->vname = varnames[i];
 
1224
                        continue;
 
1225
                }
 
1226
 
 
1227
                m = PEEK(arg_count - i - 1); /* arguments in reverse order on runtime stack */
 
1228
 
 
1229
                if (m->type == Node_param_list)
 
1230
                        m = GET_PARAM(m->param_cnt);
 
1231
                        
 
1232
                switch (m->type) {
 
1233
                case Node_var_new:
 
1234
                case Node_var_array:
 
1235
                        r->type = Node_array_ref;
 
1236
                        r->orig_array = r->prev_array = m;
 
1237
                        break;
 
1238
 
 
1239
                case Node_array_ref:
 
1240
                        r->type = Node_array_ref;
 
1241
                        r->orig_array = m->orig_array;
 
1242
                        r->prev_array = m;
 
1243
                        break;
 
1244
 
 
1245
                case Node_val:
 
1246
                        r->type = Node_var;
 
1247
                        r->var_value = m;
 
1248
                        break;
 
1249
 
 
1250
                default:
 
1251
                        cant_happen();
 
1252
                }
 
1253
                r->vname = varnames[i];
 
1254
        }
 
1255
        stack_adj(-arg_count);  /* adjust stack pointer */
 
1256
 
 
1257
        if (pc->opcode == Op_indirect_func_call) {
 
1258
                r = POP();      /* indirect var */
 
1259
                DEREF(r);
 
1260
        }
 
1261
 
 
1262
        push_frame(frame_ptr);
 
1263
 
 
1264
        /* save current frame in stack */
 
1265
        PUSH(frame_ptr);
 
1266
        /* setup new frame */
 
1267
        getnode(frame_ptr);
 
1268
        frame_ptr->type = Node_frame;   
 
1269
        frame_ptr->stack = sp;
 
1270
        frame_ptr->func_node = f;
 
1271
        frame_ptr->loop_count = 0;
 
1272
        frame_ptr->vname = NULL;
 
1273
 
 
1274
        frame_ptr->reti = (unsigned long) pc; /* on return execute pc->nexti */
 
1275
}
 
1276
 
 
1277
 
 
1278
/* restore_frame --- clean up the stack and update frame */
 
1279
 
 
1280
static INSTRUCTION *
 
1281
restore_frame(NODE *fp)
 
1282
{
 
1283
        NODE *r;
 
1284
        NODE **sp;
 
1285
        int n;
 
1286
        NODE *func;
 
1287
        INSTRUCTION *ri;
 
1288
 
 
1289
        func = frame_ptr->func_node;
 
1290
        n = func->lnode->param_cnt;
 
1291
        sp = frame_ptr->stack;
 
1292
 
 
1293
        for (; n > 0; n--) {
 
1294
                r = *sp++;
 
1295
                if (r->type == Node_var)     /* local variable */
 
1296
                        DEREF(r->var_value);
 
1297
                else if (r->type == Node_var_array)     /* local array */
 
1298
                        assoc_clear(r);
 
1299
                freenode(r);
 
1300
        }
 
1301
        if (frame_ptr->stack != NULL)
 
1302
                efree(frame_ptr->stack);
 
1303
        ri = (INSTRUCTION *) frame_ptr->reti; /* execution in calling frame
 
1304
                                               * resumes from ri->nexti.
 
1305
                                               */
 
1306
        freenode(frame_ptr);
 
1307
        pop_frame();
 
1308
 
 
1309
        frame_ptr = fp;
 
1310
        return ri->nexti;
 
1311
}
 
1312
 
 
1313
 
 
1314
/* free_arrayfor --- free 'for (var in array)' related data */
 
1315
 
 
1316
static inline void
 
1317
free_arrayfor(NODE *r)
 
1318
{
 
1319
        if (r->var_array != NULL) {
 
1320
                size_t num_elems = r->table_size;
 
1321
                NODE **list = r->var_array;
 
1322
                while (num_elems > 0)
 
1323
                        ahash_unref(list[--num_elems]);
 
1324
                efree(list);
 
1325
        }
 
1326
        freenode(r);
 
1327
}
 
1328
 
 
1329
/* unwind_stack --- pop the runtime stack */
 
1330
 
 
1331
void
 
1332
unwind_stack(STACK_ITEM *sp_bottom)
 
1333
{
 
1334
        NODE *r;
 
1335
 
 
1336
        while (stack_ptr >= sp_bottom) {
 
1337
                r = POP();
 
1338
                switch (r->type) {
 
1339
                case Node_instruction:
 
1340
                        freenode(r);
 
1341
                        break;
 
1342
 
 
1343
                case Node_frame:
 
1344
                        (void) restore_frame(r);
 
1345
                        source = frame_ptr->vname;
 
1346
                        break;
 
1347
 
 
1348
                case Node_arrayfor:
 
1349
                        free_arrayfor(r);
 
1350
                        break;
 
1351
 
 
1352
                case Node_val:
 
1353
                        DEREF(r);
 
1354
                        break;
 
1355
 
 
1356
                default:
 
1357
                        if (get_context()->level == 0)
 
1358
                                fatal(_("unwind_stack: unexpected type `%s'"),
 
1359
                                                nodetype2str(r->type));
 
1360
                        /* else 
 
1361
                                * Node_var_array,
 
1362
                                * Node_param_list,
 
1363
                                * Node_var (e.g: trying to use scalar for array)
 
1364
                                * Node_regex/Node_dynregex
 
1365
                                * ?
 
1366
                         */
 
1367
                        break;
 
1368
                }
 
1369
        }
 
1370
}
 
1371
 
 
1372
 
 
1373
/*
 
1374
 * This generated compiler warnings from GCC 4.4. Who knows why.
 
1375
 *
 
1376
#define eval_condition(t)       (((t)->flags & MAYBE_NUM) && force_number(t), \
 
1377
                ((t)->flags & NUMBER) ? ((t)->numbr != 0.0) : ((t)->stlen != 0))
 
1378
*/
 
1379
 
 
1380
 
 
1381
static inline int
 
1382
eval_condition(NODE *t)
 
1383
{
 
1384
        if ((t->flags & MAYBE_NUM) != 0)
 
1385
                force_number(t);
 
1386
 
 
1387
        if ((t->flags & NUMBER) != 0)
 
1388
                return (t->numbr != 0.0);
 
1389
 
 
1390
        return (t->stlen != 0);
 
1391
}
 
1392
 
 
1393
/* PUSH_CODE --- push a code onto the runtime stack */
 
1394
 
 
1395
void
 
1396
PUSH_CODE(INSTRUCTION *cp)
 
1397
{
 
1398
        NODE *r;
 
1399
        getnode(r);
 
1400
        r->type = Node_instruction;
 
1401
        r->code_ptr = cp;
 
1402
        PUSH(r);
 
1403
}
 
1404
 
 
1405
/* POP_CODE --- pop a code off the runtime stack */
 
1406
 
 
1407
INSTRUCTION *
 
1408
POP_CODE()
 
1409
{
 
1410
        NODE *r;
 
1411
        INSTRUCTION *cp;
 
1412
        r = POP();
 
1413
        cp = r->code_ptr;
 
1414
        freenode(r);
 
1415
        return cp;
 
1416
}
 
1417
 
 
1418
 
 
1419
/*
 
1420
 * r_interpret:
 
1421
 *   code is a list of instructions to run. returns the exit value
 
1422
 *       from the awk code.
 
1423
 */
 
1424
 
 
1425
 /* N.B.:
 
1426
 *   1) reference counting done for both number and string values.
 
1427
 *   2) TEMP flag no longer needed (consequence of the above; valref = 0
 
1428
 *      is the replacement).
 
1429
 *   3) Stack operations:
 
1430
 *       Use REPLACE[_XX] if last stack operation was TOP[_XX],
 
1431
 *       PUSH[_XX] if last operation was POP[_XX] instead. 
 
1432
 *   4) UPREF and DREF -- see awk.h 
 
1433
 */
 
1434
 
 
1435
 
 
1436
int
 
1437
r_interpret(INSTRUCTION *code)
 
1438
{
 
1439
        INSTRUCTION *pc;   /* current instruction */
 
1440
        NODE *r = NULL;
 
1441
        NODE *m;
 
1442
        INSTRUCTION *ni;
 
1443
        NODE *t1, *t2;
 
1444
        NODE *f;        /* function definition */
 
1445
        NODE **lhs;
 
1446
        AWKNUM x, x1, x2;
 
1447
        int di, pre = FALSE;
 
1448
#ifdef _CRAY
 
1449
        long lx;
 
1450
        long lx2;
 
1451
#endif
 
1452
        Regexp *rp;
 
1453
        int currule = 0;
 
1454
#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
 
1455
        int last_was_stopme = FALSE;    /* builtin stopme() called ? */
 
1456
#endif
 
1457
        long in_loop = 0;
 
1458
        int stdio_problem = FALSE;
 
1459
 
 
1460
        if (args_array == NULL)
 
1461
                emalloc(args_array, NODE **, (max_args + 2)*sizeof(NODE *), "r_interpret");
 
1462
        else
 
1463
                erealloc(args_array, NODE **, (max_args + 2)*sizeof(NODE *), "r_interpret");
 
1464
 
 
1465
/* array subscript */
 
1466
#define mk_sub(n)       (n == 1 ? POP_STRING() : concat_exp(n, TRUE))
 
1467
 
 
1468
#ifdef DEBUGGING
 
1469
#define JUMPTO(x)       do { post_execute(pc, in_loop); pc = (x); goto top; } while(FALSE)
 
1470
#else
 
1471
#define JUMPTO(x)       do { pc = (x); goto top; } while(FALSE)
 
1472
#endif
 
1473
 
 
1474
        pc = code;
 
1475
 
 
1476
        /* N.B.: always use JUMPTO for next instruction, otherwise bad things
 
1477
         * may happen. DO NOT add a real loop (for/while) below to
 
1478
         * replace ' forever {'; this catches failure to use JUMPTO to execute
 
1479
         * next instruction (e.g. continue statement).
 
1480
         */
 
1481
 
 
1482
        /* loop until hit Op_stop instruction */
 
1483
 
 
1484
        /* forever {  */
 
1485
top:
 
1486
                if (pc->source_line > 0)
 
1487
                        sourceline = pc->source_line;
 
1488
 
 
1489
#ifdef DEBUGGING
 
1490
                if (! pre_execute(&pc, in_loop))
 
1491
                        goto top;
 
1492
#endif
 
1493
 
 
1494
                switch (pc->opcode) {
 
1495
                case Op_rule:
 
1496
                        currule = pc->in_rule;   /* for sole use in Op_K_next, Op_K_nextfile */
 
1497
                        /* fall through */
 
1498
                case Op_func:
 
1499
                case Op_ext_func:
 
1500
                        source = pc->source_file;
 
1501
                        break;
 
1502
 
 
1503
                case Op_atexit:
 
1504
                        /* avoid false source indications */
 
1505
                        source = NULL;
 
1506
                        sourceline = 0;
 
1507
                        (void) nextfile(&curfile, TRUE);        /* close input data file */ 
 
1508
                        /*
 
1509
                         * This used to be:
 
1510
                         *
 
1511
                         * if (close_io() != 0 && ! exiting && exit_val == 0)
 
1512
                         *      exit_val = 1;
 
1513
                         *
 
1514
                         * Other awks don't care about problems closing open files
 
1515
                         * and pipes, in that it doesn't affect their exit status.
 
1516
                         * So we no longer do either.
 
1517
                         */
 
1518
                        (void) close_io(& stdio_problem);
 
1519
                        /*
 
1520
                         * However, we do want to exit non-zero if there was a problem
 
1521
                         * with stdout/stderr, so we reinstate a slightly different
 
1522
                         * version of the above:
 
1523
                         */
 
1524
                        if (stdio_problem && ! exiting && exit_val == 0)
 
1525
                                exit_val = 1;
 
1526
                        break;
 
1527
 
 
1528
                case Op_stop:
 
1529
                        return 0;
 
1530
 
 
1531
                case Op_push_i:
 
1532
                        m = pc->memory;
 
1533
                        PUSH((m->flags & INTLSTR) != 0 ? format_val(CONVFMT, CONVFMTidx, m): m);
 
1534
                        break;
 
1535
 
 
1536
                case Op_push:
 
1537
                {
 
1538
                        NODE *save_symbol;
 
1539
                        int isparam = FALSE;
 
1540
 
 
1541
                        save_symbol = m = pc->memory;
 
1542
                        if (m->type == Node_param_list) {
 
1543
                                if ((m->flags & FUNC) != 0)
 
1544
                                        fatal(_("can't use function name `%s' as variable or array"),
 
1545
                                                        m->vname);
 
1546
                                isparam = TRUE;
 
1547
                                save_symbol = m = GET_PARAM(m->param_cnt);
 
1548
                                if (m->type == Node_array_ref)
 
1549
                                        m = m->orig_array;
 
1550
                        }
 
1551
                                
 
1552
                        switch (m->type) {
 
1553
                        case Node_var:
 
1554
                                if (do_lint && var_uninitialized(m))
 
1555
                                        lintwarn(isparam ?
 
1556
                                                _("reference to uninitialized argument `%s'") :
 
1557
                                                _("reference to uninitialized variable `%s'"),
 
1558
                                                                save_symbol->vname);
 
1559
                                m = m->var_value;
 
1560
                                UPREF(m);
 
1561
                                PUSH(m);
 
1562
                                break;
 
1563
 
 
1564
                        case Node_var_new:
 
1565
                                m->type = Node_var;
 
1566
                                m->var_value = Nnull_string;
 
1567
                                if (do_lint)
 
1568
                                        lintwarn(isparam ?
 
1569
                                                _("reference to uninitialized argument `%s'") :
 
1570
                                                _("reference to uninitialized variable `%s'"),
 
1571
                                                                save_symbol->vname);
 
1572
                                PUSH(Nnull_string);
 
1573
                                break;
 
1574
 
 
1575
                        case Node_var_array:
 
1576
                                if (! do_posix
 
1577
                                                && pc->nexti->opcode == Op_builtin
 
1578
                                                && pc->nexti->builtin == do_length)  /* length(array) */
 
1579
                                        PUSH(m);
 
1580
                                else
 
1581
                                        fatal(_("attempt to use array `%s' in a scalar context"),
 
1582
                                                        array_vname(save_symbol));
 
1583
                                break;
 
1584
 
 
1585
                        default:
 
1586
                                cant_happen();
 
1587
                        }
 
1588
                }
 
1589
                        break;  
 
1590
 
 
1591
                case Op_push_param:             /* function argument */
 
1592
                        m = pc->memory;
 
1593
                        if (m->type == Node_param_list)
 
1594
                                m = GET_PARAM(m->param_cnt);
 
1595
                        if (m->type == Node_var) {
 
1596
                                m = m->var_value;
 
1597
                                UPREF(m);
 
1598
                                PUSH(m);
 
1599
                                break;
 
1600
                        }
 
1601
                        /* else
 
1602
                                fall through */
 
1603
                case Op_push_array:
 
1604
                        PUSH(pc->memory);
 
1605
                        break;
 
1606
 
 
1607
                case Op_push_lhs:
 
1608
                        lhs = get_lhs(pc->memory, pc->do_reference);
 
1609
                        PUSH_ADDRESS(lhs);
 
1610
                        break;
 
1611
 
 
1612
                case Op_subscript:
 
1613
                        t2 = mk_sub(pc->sub_count);
 
1614
                        t1 = POP_ARRAY();
 
1615
                        r = *assoc_lookup(t1, t2, TRUE);
 
1616
                        DEREF(t2);
 
1617
                        if (r->type == Node_val)
 
1618
                                UPREF(r);
 
1619
                        PUSH(r);
 
1620
                        break;
 
1621
 
 
1622
                case Op_sub_array:
 
1623
                        t2 = mk_sub(pc->sub_count);
 
1624
                        t1 = POP_ARRAY();
 
1625
                        r = in_array(t1, t2);
 
1626
                        if (r == NULL) {
 
1627
                                const char *arr_name = make_aname(t1, t2);
 
1628
                                getnode(r);
 
1629
                                r->type = Node_var_array;
 
1630
                                r->var_array = NULL;
 
1631
                                r->vname = estrdup(arr_name, strlen(arr_name));
 
1632
                                *assoc_lookup(t1, t2, FALSE) = r;
 
1633
                        } else if (r->type != Node_var_array) {
 
1634
                                const char *arr_name = make_aname(t1, t2);
 
1635
                                DEREF(t2);
 
1636
                                fatal(_("attempt to use scalar `%s' as an array"), arr_name);
 
1637
                        }
 
1638
                        DEREF(t2);
 
1639
                        PUSH(r);
 
1640
                        break;
 
1641
 
 
1642
                case Op_subscript_lhs:
 
1643
                        t2 = mk_sub(pc->sub_count);
 
1644
                        t1 = POP_ARRAY();
 
1645
                        lhs = assoc_lookup(t1, t2, pc->do_reference);
 
1646
                        if ((*lhs)->type == Node_var_array) {
 
1647
                                const char *arr_name = make_aname(t1, t2);
 
1648
                                DEREF(t2);
 
1649
                                fatal(_("attempt to use array `%s' in a scalar context"), arr_name);
 
1650
                        }
 
1651
                        DEREF(t2);
 
1652
                        PUSH_ADDRESS(lhs);
 
1653
                        break;
 
1654
 
 
1655
                case Op_field_spec:
 
1656
                        t1 = TOP_SCALAR();
 
1657
                        lhs = r_get_field(t1, (Func_ptr *) 0, TRUE);
 
1658
                        decr_sp();
 
1659
                        DEREF(t1);
 
1660
                        /* This used to look like this:
 
1661
                            PUSH(dupnode(*lhs));
 
1662
                           but was changed to bypass an apparent bug in the z/OS C compiler.
 
1663
                           Please do not remerge.  */
 
1664
                        r = dupnode(*lhs);     /* can't use UPREF here */
 
1665
                        PUSH(r);
 
1666
                        break;
 
1667
 
 
1668
                case Op_field_spec_lhs:
 
1669
                        t1 = TOP_SCALAR();
 
1670
                        lhs = r_get_field(t1, &pc->target_assign->field_assign, pc->do_reference);
 
1671
                        decr_sp();
 
1672
                        DEREF(t1);
 
1673
                        PUSH_ADDRESS(lhs);
 
1674
                        break;
 
1675
 
 
1676
                case Op_lint:
 
1677
                        if (do_lint) {
 
1678
                                switch (pc->lint_type) {
 
1679
                                case LINT_assign_in_cond:
 
1680
                                        lintwarn(_("assignment used in conditional context"));
 
1681
                                        break;
 
1682
 
 
1683
                                case LINT_no_effect:
 
1684
                                        lintwarn(_("statement has no effect"));
 
1685
                                        break;
 
1686
 
 
1687
                                default:
 
1688
                                        cant_happen();
 
1689
                                }
 
1690
                        }
 
1691
                        break;
 
1692
 
 
1693
                case Op_push_loop:      /* for break/continue in loop, switch */
 
1694
                        PUSH_CODE(pc);
 
1695
                        in_loop++;
 
1696
                        break;
 
1697
 
 
1698
                case Op_pop_loop:
 
1699
                        (void) POP_CODE();
 
1700
                        in_loop--;
 
1701
                        break;
 
1702
 
 
1703
                case Op_jmp:
 
1704
                        JUMPTO(pc->target_jmp);
 
1705
 
 
1706
                case Op_jmp_false:
 
1707
                        r = POP_SCALAR();
 
1708
                        di = eval_condition(r);
 
1709
                        DEREF(r);
 
1710
                        if (! di)
 
1711
                                JUMPTO(pc->target_jmp);
 
1712
                        break;
 
1713
 
 
1714
                case Op_jmp_true:
 
1715
                        r = POP_SCALAR();
 
1716
                        di = eval_condition(r);
 
1717
                        DEREF(r);                       
 
1718
                        if (di)
 
1719
                                JUMPTO(pc->target_jmp);
 
1720
                        break;
 
1721
 
 
1722
                case Op_and:
 
1723
                case Op_or:
 
1724
                        t1 = POP_SCALAR();
 
1725
                        di = eval_condition(t1);
 
1726
                        DEREF(t1);
 
1727
                        if ((pc->opcode == Op_and && di)
 
1728
                                        || (pc->opcode == Op_or && ! di))
 
1729
                                break;
 
1730
                        r = make_number((AWKNUM) di);
 
1731
                        PUSH(r);
 
1732
                        ni = pc->target_jmp;
 
1733
                        JUMPTO(ni->nexti);
 
1734
 
 
1735
                case Op_and_final:
 
1736
                case Op_or_final:
 
1737
                        t1 = TOP_SCALAR();
 
1738
                        r = make_number((AWKNUM) eval_condition(t1));
 
1739
                        DEREF(t1);
 
1740
                        REPLACE(r);
 
1741
                        break;
 
1742
 
 
1743
                case Op_not:
 
1744
                        t1 = TOP_SCALAR(); 
 
1745
                        r = make_number((AWKNUM) ! eval_condition(t1));
 
1746
                        DEREF(t1);
 
1747
                        REPLACE(r);
 
1748
                        break;
 
1749
 
 
1750
                case Op_equal:
 
1751
 
 
1752
/* compare two nodes on the stack */
 
1753
#define compare(X, Y)  \
 
1754
t2 = POP_SCALAR(); \
 
1755
t1 = TOP_SCALAR(); \
 
1756
X = cmp_nodes(t1, t2); \
 
1757
DEREF(t1); \
 
1758
DEREF(t2); \
 
1759
r = make_number((AWKNUM) (Y)); \
 
1760
REPLACE(r);
 
1761
 
 
1762
                        compare(di, di == 0);
 
1763
                        break;
 
1764
 
 
1765
                case Op_notequal:
 
1766
                        compare(di, di != 0);
 
1767
                        break;
 
1768
 
 
1769
                case Op_less:
 
1770
                        compare(di, di < 0);
 
1771
                        break;
 
1772
 
 
1773
                case Op_greater:
 
1774
                        compare(di, di > 0);
 
1775
                        break;
 
1776
 
 
1777
                case Op_leq:
 
1778
                        compare(di, di <= 0);
 
1779
                        break;
 
1780
 
 
1781
                case Op_geq:
 
1782
                        compare(di, di >= 0);
 
1783
                        break;
 
1784
#undef compare
 
1785
 
 
1786
                case Op_plus_i:
 
1787
                        x2 = force_number(pc->memory);
 
1788
                        goto plus;
 
1789
 
 
1790
                case Op_plus:
 
1791
                        POP_NUMBER(x2);
 
1792
plus:
 
1793
                        TOP_NUMBER(x1);
 
1794
                        r = make_number(x1 + x2);
 
1795
                        REPLACE(r);
 
1796
                        break;
 
1797
 
 
1798
                case Op_minus_i:
 
1799
                        x2 = force_number(pc->memory);
 
1800
                        goto minus;
 
1801
 
 
1802
                case Op_minus:
 
1803
                        POP_NUMBER(x2);
 
1804
minus:
 
1805
                        TOP_NUMBER(x1);
 
1806
                        r = make_number(x1 - x2);
 
1807
                        REPLACE(r);
 
1808
                        break;
 
1809
 
 
1810
                case Op_times_i:
 
1811
                        x2 = force_number(pc->memory);
 
1812
                        goto times;
 
1813
 
 
1814
                case Op_times:
 
1815
                        POP_NUMBER(x2);
 
1816
times:
 
1817
                        TOP_NUMBER(x1);
 
1818
                        r = make_number(x1 * x2);
 
1819
                        REPLACE(r);
 
1820
                        break;
 
1821
 
 
1822
                case Op_exp_i:
 
1823
                        x2 = force_number(pc->memory);
 
1824
                        goto exponent;
 
1825
 
 
1826
                case Op_exp:
 
1827
                        POP_NUMBER(x2);
 
1828
exponent:
 
1829
                        TOP_NUMBER(x1);
 
1830
                        x = calc_exp(x1, x2);
 
1831
                        r = make_number(x);
 
1832
                        REPLACE(r);
 
1833
                        break;
 
1834
 
 
1835
                case Op_quotient_i:
 
1836
                        x2 = force_number(pc->memory);
 
1837
                        goto quotient;
 
1838
 
 
1839
                case Op_quotient:
 
1840
                        POP_NUMBER(x2);
 
1841
quotient:
 
1842
                        TOP_NUMBER(x1);
 
1843
                        if (x2 == 0) {
 
1844
                                decr_sp();
 
1845
                                fatal(_("division by zero attempted"));
 
1846
                        }
 
1847
#ifdef _CRAY
 
1848
                        /* special case for integer division, put in for Cray */
 
1849
                        lx2 = x2;
 
1850
                        if (lx2 == 0)
 
1851
                                x = x1 / x2;
 
1852
                        else {
 
1853
                                lx = (long) x1 / lx2;
 
1854
                                if (lx * x2 == x1)
 
1855
                                        x = lx;
 
1856
                                else
 
1857
                                        x = x1 / x2;
 
1858
                        }
 
1859
#else
 
1860
                        x = x1 / x2;
 
1861
#endif
 
1862
                        r = make_number(x);
 
1863
                        REPLACE(r);
 
1864
                        break;          
 
1865
 
 
1866
                case Op_mod_i:
 
1867
                        x2 = force_number(pc->memory);
 
1868
                        goto mod;
 
1869
 
 
1870
                case Op_mod:
 
1871
                        POP_NUMBER(x2);
 
1872
mod:
 
1873
                        TOP_NUMBER(x1);
 
1874
 
 
1875
                        if (x2 == 0) {
 
1876
                                decr_sp();
 
1877
                                fatal(_("division by zero attempted in `%%'"));
 
1878
                        }
 
1879
#ifdef HAVE_FMOD
 
1880
                        x = fmod(x1, x2);
 
1881
#else   /* ! HAVE_FMOD */
 
1882
                        (void) modf(x1 / x2, &x);
 
1883
                        x = x1 - x * x2;
 
1884
#endif  /* ! HAVE_FMOD */
 
1885
                        r = make_number(x);
 
1886
                        REPLACE(r);
 
1887
                        break;          
 
1888
 
 
1889
                case Op_preincrement:
 
1890
                        pre = TRUE;
 
1891
                case Op_postincrement:
 
1892
                        x2 = 1.0;
 
1893
post:
 
1894
                        lhs = TOP_ADDRESS();
 
1895
                        x1 = force_number(*lhs);
 
1896
                        unref(*lhs);
 
1897
                        r = *lhs = make_number(x1 + x2);
 
1898
                        if (pre)
 
1899
                                UPREF(r);
 
1900
                        else
 
1901
                                r = make_number(x1);
 
1902
                        REPLACE(r);
 
1903
                        pre = FALSE;
 
1904
                        break;                  
 
1905
 
 
1906
                case Op_predecrement:
 
1907
                        pre = TRUE;
 
1908
                case Op_postdecrement:
 
1909
                        x2 = -1.0;
 
1910
                        goto post;                                      
 
1911
 
 
1912
                case Op_unary_minus:
 
1913
                        TOP_NUMBER(x1);
 
1914
                        r = make_number(-x1);
 
1915
                        REPLACE(r);
 
1916
                        break;
 
1917
 
 
1918
                case Op_store_sub:
 
1919
                        /* array[sub] assignment optimization,
 
1920
                         * see awkgram.y (optimize_assignment)
 
1921
                         */
 
1922
                        t1 = get_array(pc->memory, TRUE);       /* array */
 
1923
                        t2 = mk_sub(pc->expr_count);    /* subscript */
 
1924
                        lhs = assoc_lookup(t1, t2, FALSE);
 
1925
                        if ((*lhs)->type == Node_var_array) {
 
1926
                                const char *arr_name = make_aname(t1, t2);
 
1927
                                DEREF(t2);
 
1928
                                fatal(_("attempt to use array `%s' in a scalar context"), arr_name);
 
1929
                        }
 
1930
                        DEREF(t2);
 
1931
                        unref(*lhs);
 
1932
                        *lhs = POP_SCALAR();
 
1933
                        break;
 
1934
 
 
1935
                case Op_store_var:
 
1936
                        /* simple variable assignment optimization,
 
1937
                         * see awkgram.y (optimize_assignment)
 
1938
                         */
 
1939
        
 
1940
                        lhs = get_lhs(pc->memory, FALSE);
 
1941
                        unref(*lhs);
 
1942
                        *lhs = POP_SCALAR();
 
1943
                        break;
 
1944
 
 
1945
                case Op_store_field:
 
1946
                {
 
1947
                        /* field assignment optimization,
 
1948
                         * see awkgram.y (optimize_assignment)
 
1949
                         */
 
1950
 
 
1951
                        Func_ptr assign;
 
1952
                        t1 = TOP();
 
1953
                        lhs = r_get_field(t1, &assign, FALSE);
 
1954
                        decr_sp();
 
1955
                        DEREF(t1);
 
1956
                        unref(*lhs);
 
1957
                        *lhs = POP_SCALAR();
 
1958
                        assert(assign != NULL);
 
1959
                        assign();
 
1960
                }
 
1961
                        break;
 
1962
 
 
1963
                case Op_assign_concat:
 
1964
                        /* x = x ... string concatenation optimization */
 
1965
                        lhs = get_lhs(pc->memory, FALSE);
 
1966
                        t1 = force_string(*lhs);
 
1967
                        t2 = POP_STRING();
 
1968
 
 
1969
                        free_wstr(*lhs);
 
1970
 
 
1971
                        if (t1 != t2 && t1->valref == 1 && (t1->flags & PERM) == 0) {
 
1972
                                size_t nlen = t1->stlen + t2->stlen;
 
1973
                                erealloc(t1->stptr, char *, nlen + 2, "interpret");
 
1974
                                memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen);
 
1975
                                t1->stlen = nlen;
 
1976
                                t1->stptr[nlen] = '\0';
 
1977
                        } else {
 
1978
                                size_t nlen = t1->stlen + t2->stlen;  
 
1979
                                char *p;
 
1980
 
 
1981
                                emalloc(p, char *, nlen + 2, "interpret");
 
1982
                                memcpy(p, t1->stptr, t1->stlen);
 
1983
                                memcpy(p + t1->stlen, t2->stptr, t2->stlen);
 
1984
                                unref(*lhs);
 
1985
                                t1 = *lhs = make_str_node(p, nlen,  ALREADY_MALLOCED); 
 
1986
                        }
 
1987
                        t1->flags &= ~(NUMCUR|NUMBER);
 
1988
                        DEREF(t2);
 
1989
                        break;
 
1990
 
 
1991
                case Op_assign:
 
1992
                        lhs = POP_ADDRESS();
 
1993
                        r = TOP_SCALAR();
 
1994
                        unref(*lhs);
 
1995
                        *lhs = r;
 
1996
                        UPREF(r);
 
1997
                        REPLACE(r);
 
1998
                        break;
 
1999
 
 
2000
                case Op_assign_plus:
 
2001
#define assign_common(X, Y) \
 
2002
lhs = POP_ADDRESS(); \
 
2003
X = force_number(*lhs); \
 
2004
TOP_NUMBER(Y); \
 
2005
unref(*lhs)
 
2006
 
 
2007
#define assign(X, Y, Z) \
 
2008
assign_common(X, Y); \
 
2009
r = *lhs = make_number(Z); \
 
2010
UPREF(r); \
 
2011
REPLACE(r)
 
2012
                
 
2013
                        assign(x1, x2, x1 + x2);
 
2014
                        break;
 
2015
 
 
2016
                case Op_assign_minus:
 
2017
                        assign(x1, x2, x1 - x2);
 
2018
                        break;
 
2019
 
 
2020
                case Op_assign_times:
 
2021
                        assign(x1, x2, x1 * x2);
 
2022
                        break;
 
2023
 
 
2024
                case Op_assign_quotient:
 
2025
                        assign_common(x1, x2);
 
2026
                        if (x2 == (AWKNUM) 0) {
 
2027
                                decr_sp();
 
2028
                                fatal(_("division by zero attempted in `/='"));
 
2029
                        }
 
2030
#ifdef _CRAY
 
2031
                        /* special case for integer division, put in for Cray */
 
2032
                        lx = x2;
 
2033
                        if (lx == 0) {
 
2034
                                r = *lhs = make_number(x1 / x2);
 
2035
                                UPREF(r);
 
2036
                                REPLACE(r);
 
2037
                                break;
 
2038
                        }
 
2039
                        lx = (long) x1 / lx;
 
2040
                        if (lx * x1 == x2)
 
2041
                                r = *lhs = make_number((AWKNUM) lx);
 
2042
                        else
 
2043
#endif  /* _CRAY */
 
2044
                                r = *lhs = make_number(x1 / x2);
 
2045
                        UPREF(r);
 
2046
                        REPLACE(r);
 
2047
                        break;
 
2048
 
 
2049
                case Op_assign_mod:
 
2050
                        assign_common(x1, x2);
 
2051
                        if (x2 == (AWKNUM) 0) {
 
2052
                                decr_sp();
 
2053
                                fatal(_("division by zero attempted in `%%='"));
 
2054
                        }
 
2055
#ifdef HAVE_FMOD
 
2056
                        r = *lhs = make_number(fmod(x1, x2));
 
2057
#else   /* ! HAVE_FMOD */
 
2058
                        (void) modf(x1 / x2, &x);
 
2059
                        x = x1 - x2 * x;
 
2060
                        r = *lhs = make_number(x);
 
2061
#endif  /* ! HAVE_FMOD */
 
2062
                        UPREF(r);
 
2063
                        REPLACE(r);
 
2064
                        break;
 
2065
 
 
2066
                case Op_assign_exp:
 
2067
                        assign(x1, x2, (AWKNUM) calc_exp((double) x1, (double) x2));
 
2068
                        break;
 
2069
 
 
2070
#undef assign
 
2071
#undef assign_common
 
2072
 
 
2073
                case Op_var_update:        /* update value of NR, FNR or NF */
 
2074
                        pc->memory->var_update();
 
2075
                        break;
 
2076
 
 
2077
                case Op_var_assign:
 
2078
                        pc->memory->var_assign();
 
2079
                        break;
 
2080
 
 
2081
                case Op_field_assign:
 
2082
                        pc->field_assign();
 
2083
                        break;
 
2084
 
 
2085
                case Op_concat:
 
2086
                        r = concat_exp(pc->expr_count, pc->concat_flag & CSUBSEP);
 
2087
                        PUSH(r);
 
2088
                        break;
 
2089
 
 
2090
                case Op_K_switch:
 
2091
                {
 
2092
                        INSTRUCTION *curr;
 
2093
                        int match_found = FALSE;
 
2094
 
 
2095
                        t1 = TOP_SCALAR();      /* switch expression */
 
2096
                        for (curr = pc->case_val; curr != NULL; curr = curr->nexti) {
 
2097
                                if (curr->opcode == Op_K_case) {
 
2098
                                        m = curr->memory;
 
2099
                                        if (m->type == Node_regex) {
 
2100
                                                (void) force_string(t1);
 
2101
                                                rp = re_update(m);
 
2102
                                                match_found = (research(rp, t1->stptr, 0, t1->stlen,
 
2103
                                                                                avoid_dfa(m, t1->stptr, t1->stlen)) >= 0);
 
2104
                                        } else
 
2105
                                                match_found = (cmp_nodes(t1, m) == 0);
 
2106
                                        if (match_found)
 
2107
                                                break;
 
2108
                                }
 
2109
                        }
 
2110
 
 
2111
                        if (! match_found)
 
2112
                                curr = pc->switch_dflt;
 
2113
                        decr_sp();
 
2114
                        DEREF(t1);
 
2115
                        JUMPTO(curr->target_stmt);
 
2116
                }
 
2117
 
 
2118
                case Op_K_continue:
 
2119
                        assert(in_loop >= 0);
 
2120
                        while (in_loop) {
 
2121
                                r = TOP();
 
2122
                                ni = r->code_ptr;
 
2123
                                /* assert(ip->opcode == Op_push_loop); */
 
2124
                                if (ni->target_continue != NULL)
 
2125
                                        break;
 
2126
 
 
2127
                                /*
 
2128
                                 * This one is for continue in case statement;
 
2129
                                 * keep searching for one that corresponds
 
2130
                                 * to a loop.
 
2131
                                 */
 
2132
                                (void) POP_CODE();
 
2133
                                in_loop--;
 
2134
                        }
 
2135
 
 
2136
                        if (in_loop)
 
2137
                                JUMPTO(pc->target_jmp);
 
2138
                        else
 
2139
                                fatal(_("`continue' outside a loop is not allowed"));
 
2140
                        break;
 
2141
                
 
2142
                case Op_K_break:
 
2143
                        assert(in_loop >= 0);
 
2144
                        if (! in_loop)
 
2145
                                fatal(_("`break' outside a loop is not allowed"));
 
2146
                        else {
 
2147
                                JUMPTO(pc->target_jmp);
 
2148
                        }
 
2149
                        break;
 
2150
 
 
2151
                case Op_K_delete:
 
2152
                        t1 = POP_ARRAY();
 
2153
                        do_delete(t1, pc->expr_count);
 
2154
                        stack_adj(-pc->expr_count);
 
2155
                        break;
 
2156
 
 
2157
                case Op_K_delete_loop:
 
2158
                        t1 = POP_ARRAY();
 
2159
                        lhs = POP_ADDRESS();    /* item */
 
2160
                        do_delete_loop(t1, lhs);
 
2161
                        break;
 
2162
 
 
2163
                case Op_in_array:
 
2164
                        t1 = POP_ARRAY();
 
2165
                        t2 = mk_sub(pc->expr_count);
 
2166
                        di = (in_array(t1, t2) != NULL);
 
2167
                        DEREF(t2);
 
2168
                        PUSH(make_number((AWKNUM) di));
 
2169
                        break;
 
2170
 
 
2171
                case Op_arrayfor_init:
 
2172
                {
 
2173
                        NODE **list = NULL;
 
2174
                        NODE *array;
 
2175
                        size_t num_elems = 0;
 
2176
                        size_t i, j;
 
2177
                        int sort_indices = whiny_users;
 
2178
 
 
2179
                        /* get the array */
 
2180
                        array = POP_ARRAY();
 
2181
 
 
2182
                        /* sanity: check if empty */
 
2183
                        if (array->var_array == NULL || array->table_size == 0)
 
2184
                                goto arrayfor;
 
2185
 
 
2186
                        /* allocate space for array */
 
2187
                        num_elems = array->table_size;
 
2188
                        emalloc(list, NODE **, (num_elems + 1) * sizeof(NODE *), "interpret");
 
2189
 
 
2190
                        /* populate it */
 
2191
                        for (i = j = 0; i < array->array_size; i++) {
 
2192
                                r = array->var_array[i];
 
2193
                                if (r == NULL)
 
2194
                                        continue;
 
2195
                                for (; r != NULL; r = r->ahnext) {
 
2196
                                        list[j++] = ahash_dupnode(r);
 
2197
                                        assert(list[j-1] == r);
 
2198
                                }
 
2199
                        }
 
2200
 
 
2201
                        if (sort_indices)
 
2202
                                qsort(list, num_elems, sizeof(NODE *), comp_func); /* shazzam! */
 
2203
                        list[num_elems] = array;      /* actual array for use in
 
2204
                                                       * lint warning in Op_arrayfor_incr
 
2205
                                                       */
 
2206
 
 
2207
arrayfor:
 
2208
                        getnode(r);
 
2209
                        r->type = Node_arrayfor;
 
2210
                        r->var_array = list;
 
2211
                        r->table_size = num_elems;     /* # of elements in list */
 
2212
                        r->array_size = -1;            /* current index */
 
2213
                        PUSH(r);
 
2214
 
 
2215
                        if (num_elems == 0)
 
2216
                                JUMPTO(pc->target_jmp);   /* Op_arrayfor_final */
 
2217
                }
 
2218
                        break;          /* next instruction is Op_push_loop */
 
2219
 
 
2220
                case Op_arrayfor_incr:
 
2221
                        r = PEEK(1);         /* (break/continue) bytecode from Op_push_loop has
 
2222
                                              * an offset of 0.
 
2223
                                              */
 
2224
                        /* assert(r->type == Node_arrayfor); */
 
2225
                        if (++r->array_size == r->table_size) {
 
2226
                                NODE *array;
 
2227
                                array = r->var_array[r->table_size];    /* actual array */
 
2228
                                if (do_lint && array->table_size != r->table_size)
 
2229
                                        lintwarn(_("for loop: array `%s' changed size from %ld to %ld during loop execution"),
 
2230
                                                array_vname(array), (long) r->table_size, (long) array->table_size);
 
2231
                                JUMPTO(pc->target_jmp); /* Op_pop_loop */
 
2232
                        }
 
2233
 
 
2234
                        t1 = r->var_array[r->array_size];
 
2235
                        lhs = get_lhs(pc->array_var, FALSE);
 
2236
                        unref(*lhs);
 
2237
                        *lhs = make_string(t1->ahname_str, t1->ahname_len);
 
2238
                        break;                   
 
2239
 
 
2240
                case Op_arrayfor_final:
 
2241
                        r = POP();
 
2242
                        assert(r->type == Node_arrayfor);
 
2243
                        free_arrayfor(r);
 
2244
                        break;
 
2245
 
 
2246
                case Op_builtin:
 
2247
                        r = pc->builtin(pc->expr_count);
 
2248
#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
 
2249
                        if (! r)
 
2250
                                last_was_stopme = TRUE;
 
2251
                        else
 
2252
#endif
 
2253
                                PUSH(r);
 
2254
                        break;
 
2255
                        
 
2256
                case Op_K_print:
 
2257
                        do_print(pc->expr_count, pc->redir_type);
 
2258
                        break;
 
2259
 
 
2260
                case Op_K_printf:
 
2261
                        do_printf(pc->expr_count, pc->redir_type);
 
2262
                        break;
 
2263
 
 
2264
                case Op_K_print_rec:
 
2265
                        do_print_rec(pc->expr_count, pc->redir_type);
 
2266
                        break;
 
2267
 
 
2268
                case Op_push_re:
 
2269
                        m = pc->memory;
 
2270
                        if (m->type == Node_dynregex) {
 
2271
                                r = POP_STRING();
 
2272
                                unref(m->re_exp);
 
2273
                                m->re_exp = r;
 
2274
                        }
 
2275
                        PUSH(m);
 
2276
                        break;
 
2277
                        
 
2278
                case Op_match_rec:
 
2279
                        m = pc->memory;
 
2280
                        t1 = *get_field(0, (Func_ptr *) 0);
 
2281
match_re:
 
2282
                        rp = re_update(m);
 
2283
                        /*
 
2284
                         * FIXME:
 
2285
                         *
 
2286
                         * Any place where research() is called with a last parameter of
 
2287
                         * zero, we need to use the avoid_dfa test. This appears here and
 
2288
                         * in the code for Op_K_switch.
 
2289
                         *
 
2290
                         * A new or improved dfa that distinguishes beginning/end of
 
2291
                         * string from beginning/end of line will allow us to get rid of
 
2292
                         * this temporary hack.
 
2293
                         *
 
2294
                         * The avoid_dfa() function is in re.c; it is not very smart.
 
2295
                         */
 
2296
 
 
2297
                        di = research(rp, t1->stptr, 0, t1->stlen,
 
2298
                                                                avoid_dfa(m, t1->stptr, t1->stlen));
 
2299
                        di = (di == -1) ^ (pc->opcode != Op_nomatch);
 
2300
                        if(pc->opcode != Op_match_rec) {
 
2301
                                decr_sp();
 
2302
                                DEREF(t1);
 
2303
                        }
 
2304
                        r = make_number((AWKNUM) di);
 
2305
                        PUSH(r);
 
2306
                        break;
 
2307
 
 
2308
                case Op_nomatch:
 
2309
                        /* fall through */
 
2310
                case Op_match:
 
2311
                        m = pc->memory;
 
2312
                        t1 = TOP_STRING();
 
2313
                        if (m->type == Node_dynregex) {
 
2314
                                unref(m->re_exp);
 
2315
                                m->re_exp = t1;
 
2316
                                decr_sp();
 
2317
                                t1 = TOP_STRING();
 
2318
                        }
 
2319
                        goto match_re;
 
2320
                        break;
 
2321
 
 
2322
                case Op_indirect_func_call:
 
2323
                {
 
2324
                        int arg_count;
 
2325
 
 
2326
                        f = NULL;
 
2327
                        arg_count = (pc + 1)->expr_count;
 
2328
                        t1 = PEEK(arg_count);   /* indirect var */
 
2329
                        assert(t1->type == Node_val);   /* @a[1](p) not allowed in grammar */
 
2330
                        (void) force_string(t1);
 
2331
                        if (t1->stlen > 0) {
 
2332
                                /* retrieve function definition node */
 
2333
                                f = pc->func_body;
 
2334
                                if (f != NULL
 
2335
                                                && STREQ(f->vname, t1->stptr)   /* indirect var hasn't been reassigned */
 
2336
                                )
 
2337
                                        goto func_call;
 
2338
                                f = lookup(t1->stptr);
 
2339
                        }
 
2340
 
 
2341
                        if (f == NULL || f->type != Node_func)
 
2342
                                fatal(_("function called indirectly through `%s' does not exist"), pc->func_name);      
 
2343
                        pc->func_body = f;     /* save for next call */
 
2344
 
 
2345
                        goto func_call;
 
2346
                }
 
2347
 
 
2348
                case Op_func_call:
 
2349
                        /* retrieve function definition node */
 
2350
                        f = pc->func_body;
 
2351
                        if (f == NULL) {
 
2352
                                f = lookup(pc->func_name);
 
2353
                                if (f == NULL || f->type != Node_func)
 
2354
                                        fatal(_("function `%s' not defined"), pc->func_name);
 
2355
                                pc->func_body = f;     /* save for next call */
 
2356
                        }
 
2357
 
 
2358
                        /* save current frame along with source and loop count.
 
2359
                         * NB: 'function fun() { break; } BEGIN { while (1) fun(); }'
 
2360
                         *     should be fatal.
 
2361
                         */
 
2362
 
 
2363
func_call:
 
2364
                        frame_ptr->vname = source;          /* save current source */
 
2365
                        frame_ptr->loop_count = in_loop;    /* save loop count */
 
2366
                        setup_frame(pc);
 
2367
                        in_loop = 0;
 
2368
 
 
2369
                        ni = f->code_ptr;       /* function code */                                                     
 
2370
                        if (ni->opcode == Op_ext_func) {
 
2371
                                /* dynamically set source and line numbers for an extension builtin. */
 
2372
                                ni->source_file = source;
 
2373
                                ni->source_line = sourceline;
 
2374
                                ni->nexti->source_line = sourceline;    /* Op_builtin */
 
2375
                                ni->nexti->nexti->source_line = sourceline;     /* Op_K_return */
 
2376
                        }
 
2377
 
 
2378
                        /* run the function instructions */
 
2379
                        JUMPTO(ni);             /* Op_func or Op_ext_func */
 
2380
 
 
2381
                case Op_K_return:
 
2382
                        m = POP_SCALAR();       /* return value */
 
2383
 
 
2384
                        r = POP();
 
2385
                        while (r->type != Node_frame) {
 
2386
                                switch (r->type) {
 
2387
                                case Node_arrayfor:
 
2388
                                        free_arrayfor(r);
 
2389
                                        break;
 
2390
                                case Node_val:
 
2391
                                        DEREF(r);
 
2392
                                        break;
 
2393
                                case Node_instruction:
 
2394
                                        freenode(r);
 
2395
                                        break;
 
2396
                                default:
 
2397
                                        break;
 
2398
                                }
 
2399
                                r = POP();
 
2400
                        } 
 
2401
 
 
2402
                        ni = restore_frame(r);
 
2403
                        source = frame_ptr->vname;
 
2404
                        in_loop = frame_ptr->loop_count;
 
2405
                        
 
2406
                        /* put the return value back on stack */
 
2407
                        PUSH(m);
 
2408
                        JUMPTO(ni);
 
2409
 
 
2410
                case Op_K_getline_redir:
 
2411
                        r = do_getline_redir(pc->into_var, pc->redir_type);
 
2412
                        PUSH(r);
 
2413
                        break;
 
2414
 
 
2415
                case Op_K_getline:      /* no redirection */
 
2416
                        do {
 
2417
                                int ret;
 
2418
                                ret = nextfile(&curfile, FALSE);
 
2419
                                if (ret <= 0)
 
2420
                                        r = do_getline(pc->into_var, curfile);
 
2421
                                else {
 
2422
                                        PUSH_CODE(pc);
 
2423
                                        if (curfile == NULL)
 
2424
                                                JUMPTO((pc + 1)->target_endfile);
 
2425
                                        else {
 
2426
                                                TOP()->loop_count = in_loop; 
 
2427
                                                in_loop = 0;
 
2428
                                                JUMPTO((pc + 1)->target_beginfile);
 
2429
                                        }
 
2430
                                }
 
2431
                        } while (r == NULL);    /* EOF */
 
2432
                        PUSH(r);
 
2433
                        break;
 
2434
 
 
2435
                case Op_after_endfile:
 
2436
                        ni = POP_CODE();
 
2437
                        assert(ni->opcode == Op_newfile || ni->opcode == Op_K_getline);
 
2438
                        JUMPTO(ni);
 
2439
 
 
2440
                case Op_after_beginfile:
 
2441
                        after_beginfile(&curfile);
 
2442
                        in_loop = TOP()->loop_count;
 
2443
                        ni = POP_CODE();
 
2444
                        if (ni->opcode == Op_K_getline
 
2445
                                        || curfile == NULL      /* skipping directory argument */
 
2446
                        )
 
2447
                                JUMPTO(ni);
 
2448
                        PUSH_CODE(ni);      /* for use in Op_K_nextfile and Op_get_record */
 
2449
                        break;              /* Op_get_record */
 
2450
 
 
2451
                case Op_newfile:
 
2452
                {
 
2453
                        int ret;
 
2454
                        ret = nextfile(&curfile, FALSE);
 
2455
                        if (ret < 0)
 
2456
                                JUMPTO(pc->target_jmp);     /* end block or Op_atexit */
 
2457
                        else if (ret > 0) {
 
2458
                                PUSH_CODE(pc);
 
2459
                                if (curfile == NULL)
 
2460
                                        JUMPTO(pc->target_endfile);
 
2461
                                TOP()->loop_count = in_loop;
 
2462
                                in_loop = 0;
 
2463
                                break;  /* beginfile block */
 
2464
                        } else
 
2465
                                PUSH_CODE(pc);
 
2466
                                /* fall through */
 
2467
                }
 
2468
                        
 
2469
                case Op_get_record:
 
2470
                        if (curfile == NULL) {          /* from getline without redirection */
 
2471
                                ni = POP_CODE();            /* Op_newfile */
 
2472
                                ni = ni->target_jmp;        /* end_block or Op_atexit */
 
2473
                        } else if (inrec(curfile) == 0)
 
2474
                                break;                      /* prog block */
 
2475
                        else
 
2476
                                ni = POP_CODE();            /* Op_newfile */
 
2477
                        JUMPTO(ni);
 
2478
 
 
2479
                case Op_K_nextfile:
 
2480
                        if (currule != Rule && currule != BEGINFILE)
 
2481
                                fatal(_("`nextfile' cannot be called from a `%s' rule"),
 
2482
                                                ruletab[currule]);
 
2483
                        (void) nextfile(&curfile, TRUE);
 
2484
                        if (currule == BEGINFILE) {
 
2485
                                while (TRUE) {
 
2486
                                        r = POP();
 
2487
                                        switch (r->type) {
 
2488
                                        case Node_instruction:
 
2489
                                                ni = r->code_ptr;
 
2490
                                                if (ni->opcode == Op_newfile
 
2491
                                                                        || ni->opcode == Op_K_getline
 
2492
                                                ) {
 
2493
                                                        in_loop = r->loop_count;
 
2494
                                                        freenode(r);
 
2495
                                                        JUMPTO(ni);
 
2496
                                                }
 
2497
                                                freenode(r);
 
2498
                                                break;
 
2499
                                        case Node_frame:
 
2500
                                                (void) restore_frame(r);
 
2501
                                                source = frame_ptr->vname;
 
2502
                                                break;
 
2503
                                        case Node_arrayfor:
 
2504
                                                free_arrayfor(r);
 
2505
                                                break;
 
2506
                                        case Node_val:
 
2507
                                                DEREF(r);
 
2508
                                                break;
 
2509
                                        default:
 
2510
                                                break;
 
2511
                                        }
 
2512
                                }
 
2513
                        }
 
2514
 
 
2515
                        unwind_stack(stack_bottom + 1); /* don't pop Op_newfile */ 
 
2516
                        in_loop = 0;
 
2517
                        JUMPTO(pc->target_endfile);             /* endfile block */
 
2518
 
 
2519
                case Op_K_exit:
 
2520
                        exiting = TRUE;
 
2521
                        POP_NUMBER(x1);
 
2522
                        exit_val = (int) x1;
 
2523
#ifdef VMS
 
2524
                        if (exit_val == 0)
 
2525
                                exit_val = EXIT_SUCCESS;
 
2526
                        else if (exit_val == 1)
 
2527
                                exit_val = EXIT_FAILURE;
 
2528
                        /* else
 
2529
                                just pass anything else on through */
 
2530
#endif
 
2531
                        /* jump to either the first end_block instruction
 
2532
                         * or to Op_atexit
 
2533
                         */
 
2534
                        unwind_stack(stack_bottom);
 
2535
                        in_loop = 0;
 
2536
                        JUMPTO(pc->target_jmp);
 
2537
 
 
2538
                case Op_K_next:
 
2539
                        if (currule != Rule)
 
2540
                                fatal(_("`next' cannot be called from a `%s' rule"), ruletab[currule]);
 
2541
 
 
2542
                        /* jump to Op_get_record */
 
2543
                        unwind_stack(stack_bottom + 1); /* don't pop Op_newfile */
 
2544
                        in_loop = 0;
 
2545
                        JUMPTO(pc->target_jmp);
 
2546
 
 
2547
                case Op_pop:
 
2548
#if defined(GAWKDEBUG) || defined(ARRAYDEBUG)
 
2549
                        if (last_was_stopme)
 
2550
                                last_was_stopme = FALSE;
 
2551
                        else
 
2552
#endif
 
2553
                        {
 
2554
                                r = POP_SCALAR();
 
2555
                                DEREF(r);
 
2556
                        }
 
2557
                        break;
 
2558
 
 
2559
                case Op_line_range:
 
2560
                        if (pc->triggered)              /* evaluate right expression */
 
2561
                                JUMPTO(pc->target_jmp);
 
2562
                        /* else
 
2563
                                evaluate left expression */
 
2564
                        break;
 
2565
 
 
2566
                case Op_cond_pair:
 
2567
                {
 
2568
                        int result;
 
2569
                        INSTRUCTION *ip;
 
2570
 
 
2571
                        t1 = TOP_SCALAR();   /* from right hand side expression */
 
2572
                        di = (eval_condition(t1) != 0);
 
2573
                        DEREF(t1);
 
2574
 
 
2575
                        ip = pc->line_range;            /* Op_line_range */
 
2576
 
 
2577
                        if (! ip->triggered && di) {
 
2578
                                /* not already triggered and left expression is TRUE */
 
2579
                                decr_sp();
 
2580
                                ip->triggered = TRUE;
 
2581
                                JUMPTO(ip->target_jmp); /* evaluate right expression */ 
 
2582
                        }
 
2583
 
 
2584
                        result = ip->triggered || di;
 
2585
                        ip->triggered ^= di;            /* update triggered flag */
 
2586
                        r = make_number((AWKNUM) result);      /* final value of condition pair */
 
2587
                        REPLACE(r);
 
2588
                        JUMPTO(pc->target_jmp);
 
2589
                }
 
2590
 
 
2591
                case Op_exec_count:
 
2592
                        INCREMENT(pc->exec_count);
 
2593
                        break;
 
2594
 
 
2595
                case Op_no_op:
 
2596
                case Op_K_if:
 
2597
                case Op_K_else:
 
2598
                case Op_cond_exp:
 
2599
                        break;
 
2600
 
 
2601
                default:
 
2602
                        fatal(_("Sorry, don't know how to interpret `%s'"), opcode2str(pc->opcode));
 
2603
                }
 
2604
 
 
2605
                JUMPTO(pc->nexti);
 
2606
 
 
2607
/*      } forever */
 
2608
 
 
2609
        /* not reached */
 
2610
        return 0;
 
2611
 
 
2612
#undef mk_sub
 
2613
#undef JUMPTO
 
2614
}