~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to debug.c

Update README.solaris.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * debug.c - gawk debugger
 
2
 * debug.c - gawk debugger 
3
3
 */
4
4
 
5
 
/*
6
 
 * Copyright (C) 2004, 2010-2013, 2016-2023 the Free Software Foundation, Inc.
7
 
 *
 
5
/* 
 
6
 * Copyright (C) 2004, 2010-2013 the Free Software Foundation, Inc.
 
7
 * 
8
8
 * This file is part of GAWK, the GNU implementation of the
9
9
 * AWK Programming Language.
10
 
 *
 
10
 * 
11
11
 * GAWK is free software; you can redistribute it and/or modify
12
12
 * it under the terms of the GNU General Public License as published by
13
 
 * the Free Software Foundation; either version 3 of the License, or
 
13
 * the Free Software Foundation; either version 2 of the License, or
14
14
 * (at your option) any later version.
15
 
 *
 
15
 * 
16
16
 * GAWK is distributed in the hope that it will be useful,
17
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
19
 * GNU General Public License for more details.
20
 
 *
 
20
 * 
21
21
 * You should have received a copy of the GNU General Public License
22
22
 * along with this program; if not, write to the Free Software
23
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
23
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
24
24
 */
25
25
 
26
26
#include "awk.h"
30
30
#include <fcntl.h>      /* open() */
31
31
#endif
32
32
 
33
 
#ifdef __MINGW32__
34
 
#define execvp(p,a) w32_execvp(p,a)
35
 
int w32_execvp(const char *, char **);
36
 
#endif
37
 
 
38
33
extern bool exiting;
39
34
extern SRCFILE *srcfiles;
40
35
extern INSTRUCTION *rule_list;
54
49
static size_t linebuf_len;
55
50
 
56
51
FILE *out_fp;
57
 
const char *dbg_prompt;
58
 
const char *commands_prompt = "> ";     /* breakpoint or watchpoint commands list */
59
 
const char *eval_prompt = "@> ";        /* awk statement(s) */
 
52
char *dbg_prompt;
 
53
char *commands_prompt = "> ";   /* breakpoint or watchpoint commands list */
 
54
char *eval_prompt = "@> ";      /* awk statement(s) */
60
55
 
61
56
bool input_from_tty = false;
62
57
int input_fd;
64
59
static SRCFILE *cur_srcfile;
65
60
static long cur_frame = 0;
66
61
static INSTRUCTION *cur_pc;
67
 
static int cur_rule = 0;
 
62
int cur_rule = 0;
68
63
 
69
64
static bool prog_running = false;
70
65
 
82
77
        CMDARG *arg;
83
78
};
84
79
 
85
 
/* breakpoint structure */
 
80
/* breakpoint structure */              
86
81
typedef struct break_point {
87
82
        struct break_point *next;
88
83
        struct break_point *prev;
104
99
#define BP_TEMP         4
105
100
#define BP_IGNORE       8
106
101
 
107
 
} BREAKPOINT;
 
102
} BREAKPOINT; 
108
103
 
109
104
static BREAKPOINT breakpoints = { &breakpoints, &breakpoints, 0 };
110
105
 
131
126
 
132
127
        NODE *symbol;   /* variable or function param */
133
128
        NODE **subs;    /* subscripts */
134
 
        int num_subs;   /* subscript(dimension) count */
 
129
        int num_subs;   /* subscript(dimension) count */ 
135
130
        char *sname;    /* symbol or param name */
136
131
 
137
132
        long fcall_count;
138
133
 
139
 
        struct commands_item commands;
 
134
        struct commands_item commands;          
140
135
        int silent;
141
136
        struct condition cndn;
142
137
 
154
149
#define PARAM           1
155
150
#define SUBSCRIPT       2
156
151
#define FIELD_NUM       4
157
 
#define OLD_IS_ARRAY    8    /* old item is array */
158
 
#define CUR_IS_ARRAY    16   /* current item is array */
 
152
#define OLD_IS_ARRAY    8    /* old item is array */ 
 
153
#define CUR_IS_ARRAY    16   /* current item is array */ 
159
154
};
160
155
 
161
156
#define IS_PARAM(d)     (((d)->flags & PARAM) != 0)
180
175
        INSTRUCTION *pc;     /* 'until' and 'return' commands */
181
176
        int repeat_count;    /* 'step', 'next', 'stepi', 'nexti' commands */
182
177
        bool print_frame;    /* print frame info,  'finish' and 'until' */
183
 
        bool print_ret;      /* print returned value, 'finish' */
 
178
        bool print_ret;      /* print returned value, 'finish' */ 
184
179
        int break_point;     /* non-zero (breakpoint number) if stopped at break point */
185
180
        int watch_point;     /* non-zero (watchpoint number) if stopped at watch point */
186
181
 
188
183
                                                 * awk interpreter and return control
189
184
                                                 * to debugger command interpreter.
190
185
                                                 */
191
 
 
 
186
 
192
187
        enum argtype command;            /* command type */
193
188
} stop;
194
189
 
198
193
static bool need_restart = false;
199
194
enum { BREAK=1, WATCH, DISPLAY, HISTORY, OPTION };
200
195
static const char *const env_variable[] = {
201
 
        "",
202
 
        "DGAWK_BREAK",
203
 
        "DGAWK_WATCH",
204
 
        "DGAWK_DISPLAY",
205
 
        "DGAWK_HISTORY",
206
 
        "DGAWK_OPTION",
 
196
"",
 
197
"DGAWK_BREAK",
 
198
"DGAWK_WATCH",
 
199
"DGAWK_DISPLAY",
 
200
"DGAWK_HISTORY",
 
201
"DGAWK_OPTION",
207
202
};
208
 
static void serialize_list(int type);
209
 
static void unserialize_list(int type);
 
203
static void serialize(int );
 
204
static void unserialize(int );
210
205
static const char *commands_string = NULL;
211
206
static int commands_string_len = 0;
212
207
static char line_sep;
219
214
struct dbg_option {
220
215
        const char *name;
221
216
        int *num_val;
222
 
        const char **str_val;
 
217
        char **str_val;
223
218
        void (*assign)(const char *);
224
 
        const char *help_txt;
 
219
        const char *help_txt; 
225
220
};
226
221
 
227
222
#define DEFAULT_HISTFILE        "./.gawk_history"
244
239
 
245
240
/* debugger option related variables */
246
241
 
247
 
static const char *output_file = "/dev/stdout";  /* gawk output redirection */
248
 
const char *dgawk_prompt = NULL;                 /* initialized in interpret */
 
242
static char *output_file = "/dev/stdout";  /* gawk output redirection */
 
243
char *dgawk_prompt = NULL;                 /* initialized in interpret */
249
244
static int list_size = DEFAULT_LISTSIZE;   /* # of lines that 'list' prints */
250
245
static int do_trace = false;
251
246
static int do_save_history = true;
254
249
 
255
250
static const struct dbg_option option_list[] = {
256
251
{"history_size", &history_size, NULL, &set_history_size,
257
 
        gettext_noop("set or show the number of lines to keep in history file") },
 
252
        gettext_noop("set or show the number of lines to keep in history file.") },
258
253
{"listsize", &list_size, NULL, &set_listsize,
259
 
        gettext_noop("set or show the list command window size") },
 
254
        gettext_noop("set or show the list command window size.") },
260
255
{"outfile", NULL, &output_file, &set_gawk_output,
261
 
        gettext_noop("set or show gawk output file") },
 
256
        gettext_noop("set or show gawk output file.") },
262
257
{"prompt", NULL, &dgawk_prompt, &set_prompt,
263
 
        gettext_noop("set or show debugger prompt"), },
 
258
        gettext_noop("set or show debugger prompt."), },
264
259
{"save_history", &do_save_history, NULL, &set_save_history,
265
 
        gettext_noop("(un)set or show saving of command history (value=on|off)") },
 
260
        gettext_noop("(un)set or show saving of command history (value=on|off).") },
266
261
{"save_options", &do_save_options, NULL, &set_save_options,
267
 
        gettext_noop("(un)set or show saving of options (value=on|off)") },
 
262
        gettext_noop("(un)set or show saving of options (value=on|off).") },
268
263
{"trace", &do_trace, NULL, &set_trace,
269
 
        gettext_noop("(un)set or show instruction tracing (value=on|off)") },
 
264
        gettext_noop("(un)set or show instruction tracing (value=on|off).") },
270
265
{0, NULL, NULL, NULL, 0},
271
266
};
272
267
 
275
270
 
276
271
/* pager */
277
272
jmp_buf pager_quit_tag;
278
 
int pager_quit_tag_valid = 0;
 
273
bool pager_quit_tag_valid = false;
279
274
static int screen_width = INT_MAX;      /* no of columns */
280
275
static int screen_height = INT_MAX;     /* no of rows */
281
 
static int pager_lines_printed = 0;     /* no of lines printed so far */
 
276
static int pager_lines_printed = 0;     /* no of lines printed so far */ 
282
277
 
283
278
static void restart(bool run) ATTRIBUTE_NORETURN;
284
279
static void close_all(void);
315
310
static int breakpoint_triggered(BREAKPOINT *b);
316
311
static int watchpoint_triggered(struct list_item *w);
317
312
static void print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump);
318
 
static void print_ns_list(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump);
319
313
static int print_code(INSTRUCTION *pc, void *x);
320
314
static void next_command();
321
315
static void debug_post_execute(INSTRUCTION *pc);
344
338
 
345
339
static struct command_source *cmd_src = NULL;
346
340
 
347
 
#define PUSH_BINDING(stack, tag, val)   \
348
 
if (val++) \
349
 
        memcpy((char *) (stack), (const char *) tag, sizeof(jmp_buf))
350
 
#define POP_BINDING(stack, tag, val)    \
351
 
if (--val) \
352
 
        memcpy((char *) tag, (const char *) (stack), sizeof(jmp_buf))
353
 
 
354
341
 
355
342
#define CHECK_PROG_RUNNING() \
356
343
        do { \
357
344
                if (! prog_running) { \
358
 
                        d_error(_("program not running")); \
 
345
                        d_error(_("program not running.")); \
359
346
                        return false; \
360
347
                } \
361
348
        } while (false)
362
349
 
363
 
// On z/OS, one needs to use %#p to get the leading 0x in the output.
364
 
// Having that makes it consistent with Linux and makes the use of
365
 
// helper scripts easier.
366
 
#ifdef USE_EBCDIC
367
 
#define PTRFMT  "%#p"
368
 
#else
369
 
#define PTRFMT  "%p"
370
 
#endif
371
 
 
372
350
 
373
351
/* g_readline --  read a line of text; the interface is like 'readline' but
374
352
 *              without any command-line editing; used when not compiled with
467
445
        efree(buf);
468
446
 
469
447
        if (n == -1) {
470
 
                d_error(_("cannot read source file `%s': %s"),
 
448
                d_error(_("can't read source file `%s' (%s)"),
471
449
                                        s->src, strerror(errno));
472
450
                return -1;
473
451
        }
499
477
        int errno_val = 0;
500
478
 
501
479
        if (src == NULL || *src == '\0') {
502
 
                d_error(_("no current source file"));
 
480
                d_error(_("no current source file."));
503
481
                return NULL;
504
482
        }
505
483
 
524
502
                efree(path);
525
503
        }
526
504
 
527
 
        d_error(_("cannot find source file named `%s': %s"), src, strerror(errno_val));
 
505
        d_error(_("cannot find source file named `%s' (%s)"), src, strerror(errno_val));
528
506
        return NULL;
529
507
}
530
508
 
542
520
        if (s == NULL)
543
521
                return -1;
544
522
        if (s->fd <= INVALID_HANDLE && (s->fd = srcopen(s)) <= INVALID_HANDLE) {
545
 
                d_error(_("cannot open source file `%s' for reading: %s"),
 
523
                d_error(_("can't open source file `%s' for reading (%s)"),
546
524
                                src, strerror(errno));
547
525
                return -1;
548
526
        }
549
527
 
550
528
        if (fstat(s->fd, &sbuf) == 0 && s->mtime < sbuf.st_mtime) {
551
 
                fprintf(out_fp, _("warning: source file `%s' modified since program compilation.\n"),
 
529
                fprintf(out_fp, _("WARNING: source file `%s' modified since program compilation.\n"),
552
530
                                src);
553
531
                efree(s->line_offset);
554
532
                s->line_offset = NULL;
558
536
                close(s->fd);
559
537
                s->fd = INVALID_HANDLE;
560
538
                if ((s->fd = srcopen(s)) <= INVALID_HANDLE) {
561
 
                        d_error(_("cannot open source file `%s' for reading: %s"),
 
539
                        d_error(_("can't open source file `%s' for reading (%s)"),
562
540
                                        src, strerror(errno));
563
541
                        return -1;
564
542
                }
596
574
        for (i = start_line; i < start_line + nlines; i++) {
597
575
                int supposed_len, len;
598
576
                char *p;
599
 
 
 
577
                
600
578
                sprintf(linebuf, "%-8d", i);
601
579
 
602
580
                /* mark the line about to be executed with =>; nlines > 1
604
582
                 */
605
583
                if (nlines > 1) {
606
584
                        BREAKPOINT *b;
607
 
                        bool has_bpt = false;
 
585
                        bool has_bpt = false;           
608
586
                        for (b = breakpoints.prev; b != &breakpoints; b = b->prev) {
609
587
                                if (src == b->src && i == b->bpi->source_line) {
610
588
                                        has_bpt = true;
617
595
                                else
618
596
                                        sprintf(linebuf, "%-4d  =>", i);
619
597
                        } else if (has_bpt)
620
 
                                sprintf(linebuf, "%-4d:b  ", i);
 
598
                                sprintf(linebuf, "%-4d:b  ", i);                        
621
599
                }
622
600
 
623
601
                p = linebuf + strlen(linebuf);
625
603
                len = read(s->fd, p, supposed_len);
626
604
                switch (len) {
627
605
                case -1:
628
 
                        d_error(_("cannot read source file `%s': %s"),
 
606
                        d_error(_("can't read source file `%s' (%s)"),
629
607
                                                src, strerror(errno));
630
608
                        return -1;
631
609
 
669
647
        long count = list_size;
670
648
        INSTRUCTION *rp;
671
649
        char *src = cur_srcfile->src;
672
 
 
 
650
        
673
651
        line_first = last_printed_line + 1;             /* default or no arg */
674
652
        if (arg == NULL)        /* list or list + */
675
653
                goto list;
701
679
                count = arg->a_int - line_first + 1;
702
680
                break;
703
681
 
704
 
        case D_string:
 
682
        case D_string:          
705
683
                src = arg->a_string;
706
684
                if (arg->next != NULL) {
707
 
                        arg = arg->next;
 
685
                        arg = arg->next;                
708
686
                        if (arg->type == D_int) /* list file:n */
709
687
                                goto line;
710
688
                        else if (arg->type == D_range)  /* list file:m-n */
735
713
        if (line_last != -1) {
736
714
                last_printed_line = line_last;
737
715
                last_print_count = line_last - line_first + 1;
738
 
        }
 
716
        } 
739
717
        return false;
740
718
}
741
719
 
775
753
 
776
754
                        gprintf(out_fp, _("Number  Disp  Enabled  Location\n\n"));
777
755
                        for (b = breakpoints.prev; b != &breakpoints; b = b->prev) {
778
 
                                const char *disp = "keep";
 
756
                                char *disp = "keep";
779
757
                                if ((b->flags & BP_ENABLE_ONCE) != 0)
780
758
                                        disp = "dis";
781
759
                                else if ((b->flags & BP_TEMP) != 0)
784
762
                                                b->number, disp, (b->flags & BP_ENABLE) != 0 ? "yes" : "no",
785
763
                                                b->src, b->bpi->source_line);
786
764
                                if (b->hit_count > 0)
787
 
                                        gprintf(out_fp, _("\tnumber of hits = %ld\n"), b->hit_count);
 
765
                                        gprintf(out_fp, _("\tno of hits = %ld\n"), b->hit_count);
788
766
                                if ((b->flags & BP_IGNORE) != 0)
789
767
                                        gprintf(out_fp, _("\tignore next %ld hit(s)\n"), b->ignore_count);
790
768
                                if (b->cndn.code != NULL)
802
780
                                                        continue;
803
781
                                                start++;
804
782
                                                *end = '\0';
805
 
                                                gprintf(out_fp, "%s", start);   /* FIXME: translate ? */
 
783
                                                gprintf(out_fp, "%s", start);   /* FIXME: translate ? */ 
806
784
                                                *end = '}';
807
785
                                        }
808
786
                                }
920
898
                                        for (i = 0; i < d->num_subs; i++) {
921
899
                                                NODE *sub;
922
900
                                                sub = d->subs[i];
923
 
                                                gprintf(out_fp, "[\"%.*s\"]", (int) sub->stlen, sub->stptr);
 
901
                                                gprintf(out_fp, "[\"%s\"]", sub->stptr);
924
902
                                        }
925
 
                                        gprintf(out_fp, "\n");
 
903
                                        gprintf(out_fp, "\n");  
926
904
                                } else if (IS_FIELD(d))
927
905
                                        gprintf(out_fp, "%d:\t$%ld\n", d->number, get_number_si(symbol));
928
906
                                else
942
920
                                                        continue;
943
921
                                                start++;
944
922
                                                *end = '\0';
945
 
                                                gprintf(out_fp, "%s", start);   /* FIXME: translate ? */
 
923
                                                gprintf(out_fp, "%s", start);   /* FIXME: translate ? */  
946
924
                                                *end = '}';
947
925
                                        }
948
926
                                }
967
945
        case Node_var_new:
968
946
                fprintf(out_fp, "untyped variable\n");
969
947
                break;
970
 
        case Node_elem_new:
971
 
                fprintf(out_fp, "untyped element\n");
972
 
                break;
973
948
        case Node_var:
974
949
                if (! isparam && r->var_update)
975
950
                        r->var_update();
976
951
                valinfo(r->var_value, fprintf, out_fp);
977
952
                break;
978
953
        case Node_var_array:
979
 
                fprintf(out_fp, "array, %ld elements\n", (long) assoc_length(r));
 
954
                fprintf(out_fp, "array, %ld elements\n", assoc_length(r));
980
955
                break;
981
956
        case Node_func:
982
957
                fprintf(out_fp, "`function'\n");
1023
998
                func = f->func_node;
1024
999
                pcount = func->param_cnt;
1025
1000
                for (i = 0; i < pcount; i++) {
1026
 
                        fparam = func->fparms[i].param;
 
1001
                        fparam = func->fparms[i].param; 
1027
1002
                        if (strcmp(name, fparam) == 0) {
1028
1003
                                r = f->stack[i];
1029
1004
                                if (r->type == Node_array_ref)
1049
1024
        if (prog_running)
1050
1025
                r = find_param(name, cur_frame, pname);
1051
1026
        if (r == NULL)
1052
 
                r = lookup(name); // for now, require fully qualified name
 
1027
                r = lookup(name);
1053
1028
        if (r == NULL)
1054
1029
                fprintf(out_fp, _("no symbol `%s' in current context\n"), name);
1055
1030
        return r;
1084
1059
        }
1085
1060
}
1086
1061
 
1087
 
/* print_array_names --- print the stack of array names */
1088
 
 
1089
 
static void
1090
 
print_array_names(const char **names, size_t num_names, FILE *out_fp)
1091
 
{
1092
 
        size_t i;
1093
 
 
1094
 
        gprintf(out_fp, "%s", names[0]);
1095
 
        for (i = 1; i < num_names; i++)
1096
 
                gprintf(out_fp, "[\"%s\"]", names[i]);
1097
 
}
1098
 
 
1099
1062
/* print_array --- print the contents of an array */
1100
1063
 
1101
1064
static int
1109
1072
        volatile int ret = 0;
1110
1073
        volatile jmp_buf pager_quit_tag_stack;
1111
1074
 
1112
 
        // manage a stack of names for printing deeply nested arrays
1113
 
        static const char **names = NULL;
1114
 
        static size_t cur_name = 0;
1115
 
        static size_t num_names = 0;
1116
 
#define INITIAL_NAME_COUNT      10
1117
 
 
1118
 
        if (names == NULL) {
1119
 
                emalloc(names, const char **, INITIAL_NAME_COUNT * sizeof(char *), "print_array");
1120
 
                memset(names, 0, INITIAL_NAME_COUNT * sizeof(char *));
1121
 
                num_names = INITIAL_NAME_COUNT;
1122
 
        }
1123
 
 
1124
1075
        if (assoc_empty((NODE *) arr)) {
1125
1076
                gprintf(out_fp, _("array `%s' is empty\n"), arr_name);
1126
1077
                return 0;
1133
1084
 
1134
1085
        PUSH_BINDING(pager_quit_tag_stack, pager_quit_tag, pager_quit_tag_valid);
1135
1086
        if (setjmp(pager_quit_tag) == 0) {
1136
 
                // push name onto stack
1137
 
                if (cur_name >= num_names) {
1138
 
                        num_names *= 2;
1139
 
                        erealloc(names, const char **, num_names * sizeof(char *), "print_array");
1140
 
                }
1141
 
                names[cur_name++] = arr_name;
1142
 
 
1143
 
                // and print the array
1144
1087
                for (i = 0; ret == 0 && i < num_elems; i++) {
1145
1088
                        subs = list[i];
1146
1089
                        r = *assoc_lookup((NODE *) arr, subs);
1147
 
                        if (r->type == Node_var_array) {
1148
 
                                // 12/2023: Use sub->stptr here, not r->vname, since
1149
 
                                // a subarray could have been created via
1150
 
                                // split() or some other mechanism where flags has NUMINT in it.
1151
 
                                // In this case, r->vname can be NULL, so pass in the
1152
 
                                // subscript itself.  This should be fixed in the code that
1153
 
                                // builds such arrays.
1154
 
                                ret = print_array(r, subs->stptr);
1155
 
                        } else {
1156
 
                                print_array_names(names, cur_name, out_fp);
1157
 
                                gprintf(out_fp, "[\"%.*s\"] = ", (int) subs->stlen, subs->stptr);
 
1090
                        if (r->type == Node_var_array)
 
1091
                                ret = print_array(r, r->vname);
 
1092
                        else {
 
1093
                                gprintf(out_fp, "%s[\"%s\"] = ", arr_name, subs->stptr);
1158
1094
                                valinfo((NODE *) r, gprintf, out_fp);
1159
1095
                        }
1160
1096
                }
1162
1098
                ret = 1;
1163
1099
 
1164
1100
        POP_BINDING(pager_quit_tag_stack, pager_quit_tag, pager_quit_tag_valid);
1165
 
        cur_name--;
1166
1101
 
1167
1102
        for (i = 0; i < num_elems; i++)
1168
1103
                unref(list[i]);
1181
1116
        subs = a->a_node;
1182
1117
        r = in_array(arr, subs);
1183
1118
        if (r == NULL)
1184
 
                fprintf(out_fp, _("subscript \"%.*s\" is not in array `%s'\n"), (int) subs->stlen, subs->stptr, arr_name);
 
1119
                fprintf(out_fp, _("[\"%s\"] not in array `%s'\n"), subs->stptr, arr_name);
1185
1120
        else if (r->type == Node_var_array) {
1186
1121
                if (count > 1)
1187
1122
                        print_subscript(r, r->vname, a->next, count - 1);
1188
1123
                else {
1189
1124
                        /* print # of elements in array */
1190
1125
                        fprintf(out_fp, "%s = ", r->vname);
1191
 
                        print_symbol(r, false);
 
1126
                        print_symbol(r, false); 
1192
1127
                }
1193
1128
        } else {
1194
 
                fprintf(out_fp, "%s[\"%.*s\"] = ", arr_name, (int) subs->stlen, subs->stptr);
 
1129
                fprintf(out_fp, "%s[\"%s\"] = ", arr_name, subs->stptr);
1195
1130
                valinfo(r, fprintf, out_fp);
1196
1131
        }
1197
1132
}
1228
1163
                        if ((r = find_array(name)) != NULL) {
1229
1164
                                int count = a->a_count;
1230
1165
                                for (; count > 0; count--) {
1231
 
                                        NODE *value, *subs;
 
1166
                                        NODE *value, *subs; 
1232
1167
                                        a = a->next;
1233
1168
                                        subs = a->a_node;
1234
1169
                                        value = in_array(r, subs);
1235
1170
                                        if (value == NULL) {
1236
 
                                                fprintf(out_fp, _("subscript \"%.*s\" is not in array `%s'\n"),
1237
 
                                                                        (int) subs->stlen, subs->stptr, name);
 
1171
                                                fprintf(out_fp, _("[\"%s\"] not in array `%s'\n"),
 
1172
                                                                        subs->stptr, name);
1238
1173
                                                break;
1239
1174
                                        } else if (value->type != Node_var_array) {
1240
 
                                                fprintf(out_fp, _("`%s[\"%.*s\"]' is not an array\n"),
1241
 
                                                                        name, (int) subs->stlen, subs->stptr);
 
1175
                                                fprintf(out_fp, _("`%s[\"%s\"]' is not an array\n"),
 
1176
                                                                        name, subs->stptr);
1242
1177
                                                break;
1243
1178
                                        } else {
1244
1179
                                                r = value;
1260
1195
                        /* notably D_node, subscript for invalid array name; skip */
1261
1196
                        break;
1262
1197
                }
1263
 
        }
 
1198
        }       
1264
1199
        return false;
1265
 
}
 
1200
}               
1266
1201
 
1267
1202
/* do_set_var --- set command */
1268
1203
 
1284
1219
 
1285
1220
                switch (r->type) {
1286
1221
                case Node_var_new:
1287
 
                case Node_elem_new:
1288
1222
                        r->type = Node_var;
1289
1223
                        r->var_value = dupnode(Nnull_string);
1290
1224
                        /* fall through */
1308
1242
        {
1309
1243
                NODE *subs, *value;
1310
1244
                int count = arg->a_count;
1311
 
                NODE *newval;
1312
1245
 
1313
1246
                assert(count > 0);
1314
1247
                name = arg->a_string;
1322
1255
 
1323
1256
                        if (count == 1) {
1324
1257
                                if (value != NULL && value->type == Node_var_array)
1325
 
                                        d_error(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
1326
 
                                                                name, (int) subs->stlen, subs->stptr);
 
1258
                                        d_error(_("attempt to use array `%s[\"%s\"]' in a scalar context"),
 
1259
                                                                name, subs->stptr);
1327
1260
                                else {
1328
1261
                                        arg = arg->next;
1329
1262
                                        val = arg->a_node;
1330
 
                                        newval = dupnode(val);
1331
 
                                        // subs should not be freed, so
1332
 
                                        // use dupnode in call to assoc_set.
1333
 
                                        assoc_set(r, dupnode(subs), newval);
1334
 
                                        fprintf(out_fp, "%s[\"%.*s\"] = ", name, (int) subs->stlen, subs->stptr);
1335
 
                                        valinfo(newval, fprintf, out_fp);
 
1263
                                        lhs = assoc_lookup(r, subs);
 
1264
                                        unref(*lhs);
 
1265
                                        *lhs = dupnode(val);
 
1266
                                        fprintf(out_fp, "%s[\"%s\"] = ", name, subs->stptr);
 
1267
                                        valinfo(*lhs, fprintf, out_fp);
1336
1268
                                }
1337
1269
                        } else {
1338
1270
                                if (value == NULL) {
1340
1272
                                        array = make_array();
1341
1273
                                        array->vname = estrdup(subs->stptr, subs->stlen);
1342
1274
                                        array->parent_array = r;
1343
 
                                        // subs should not be freed, so
1344
 
                                        // use dupnode in call to assoc_set.
1345
 
                                        assoc_set(r, dupnode(subs), array);
 
1275
                                        lhs = assoc_lookup(r, subs);
 
1276
                                        unref(*lhs);
 
1277
                                        *lhs = array;
1346
1278
                                        r = array;
1347
1279
                                } else if (value->type != Node_var_array) {
1348
 
                                        d_error(_("attempt to use scalar `%s[\"%.*s\"]' as array"),
1349
 
                                                        name, (int) subs->stlen, subs->stptr);
 
1280
                                        d_error(_("attempt to use scalar `%s[\"%s\"]' as array"),
 
1281
                                                        name, subs->stptr);
1350
1282
                                        break;
1351
1283
                                } else {
1352
1284
                                        r = value;
1367
1299
                arg = arg->next;
1368
1300
                val = arg->a_node;
1369
1301
                lhs = get_field(field_num, &assign);
 
1302
                unref(*lhs);
 
1303
                *lhs = dupnode(val);
1370
1304
                if (assign)
1371
 
                        /* call assign to copy fields before unref frees $0 */
1372
1305
                        assign();
1373
 
                unref(*lhs);
1374
 
                *lhs = dupnode(val);
1375
1306
                print_field(field_num);
1376
1307
        }
1377
1308
                break;
1427
1358
        free_context(d->cndn.ctxt, false);
1428
1359
        if (d->cndn.expr != NULL)
1429
1360
                efree(d->cndn.expr);
1430
 
 
 
1361
        
1431
1362
        d->next->prev = d->prev;
1432
1363
        d->prev->next = d->next;
1433
1364
        efree(d);
1440
1371
{
1441
1372
        struct list_item *d;
1442
1373
 
1443
 
        ezalloc(d, struct list_item *, sizeof(struct list_item), "add_item");
 
1374
        emalloc(d, struct list_item *, sizeof(struct list_item), "add_item");
 
1375
        memset(d, 0, sizeof(struct list_item));
1444
1376
        d->commands.next = d->commands.prev = &d->commands;
1445
1377
 
1446
1378
        d->number = ++list->number;
1564
1496
                        if ((d = find_item(list, arg->a_int)) == NULL) {
1565
1497
                                /* split into two for easier message translation */
1566
1498
                                if (list == &display_list)
1567
 
                                        d_error(_("no display item numbered %ld"),
 
1499
                                        d_error(_("No display item numbered %ld"),
1568
1500
                                                arg->a_int);
1569
1501
                                else
1570
 
                                        d_error(_("no watch item numbered %ld"),
 
1502
                                        d_error(_("No watch item numbered %ld"),
1571
1503
                                                arg->a_int);
1572
1504
                        } else
1573
1505
                                delete_item(d);
1593
1525
                        sub = d->subs[i];
1594
1526
                        r = in_array(symbol, sub);
1595
1527
                        if (r == NULL) {
1596
 
                                fprintf(out_fp, _("%d: subscript \"%.*s\" is not in array `%s'\n"),
1597
 
                                                        d->number, (int) sub->stlen, sub->stptr, d->sname);
 
1528
                                fprintf(out_fp, _("%d: [\"%s\"] not in array `%s'\n"),
 
1529
                                                        d->number, sub->stptr, d->sname);
1598
1530
                                break;
1599
1531
                        }
1600
1532
                        if (r->type == Node_var_array) {
1601
1533
                                symbol = r;
1602
1534
                                if (i == count - 1)     /* it's a sub-array */
1603
1535
                                        goto print_sym;         /* print # of elements in sub-array */
1604
 
                        } else {
 
1536
                        } else {                                                        
1605
1537
                                if (i != count - 1)
1606
1538
                                        return;         /* FIXME msg and delete item ? */
1607
 
                                fprintf(out_fp, "%d: %s[\"%.*s\"] = ", d->number,
1608
 
                                                        d->sname, (int) sub->stlen, sub->stptr);
 
1539
                                fprintf(out_fp, "%d: %s[\"%s\"] = ", d->number,
 
1540
                                                        d->sname, sub->stptr);
1609
1541
                                valinfo(r, fprintf, out_fp);
1610
1542
                        }
1611
1543
                }
1642
1574
}
1643
1575
 
1644
1576
/* do_undisplay --- undisplay command */
1645
 
 
 
1577
        
1646
1578
int
1647
1579
do_undisplay(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
1648
1580
{
1649
1581
        do_delete_item(&display_list, arg);
1650
 
        return false;
 
1582
        return false; 
1651
1583
}
1652
1584
 
1653
 
/* condition_triggered --- test if a condition expression is true */
 
1585
/* condition_triggered --- test if a condition expression is true */ 
1654
1586
 
1655
1587
static int
1656
1588
condition_triggered(struct condition *cndn)
1669
1601
                return false;   /* not triggered */
1670
1602
 
1671
1603
        force_number(r);
1672
 
        di = ! is_zero(r);
 
1604
        di = ! iszero(r);
1673
1605
        DEREF(r);
1674
1606
        return di;
1675
1607
}
1682
1614
        NODE *sub, *r;
1683
1615
        int i = 0, count = item->num_subs;
1684
1616
 
1685
 
        // without this check, in_array() will SEGV...
1686
 
        if (symbol->type == Node_var_new || symbol->type == Node_elem_new)
1687
 
                return -1;
1688
 
 
1689
1617
        r = *ptr = NULL;
1690
1618
        for (i = 0; i < count; i++) {
1691
1619
                sub = item->subs[i];
1703
1631
}
1704
1632
 
1705
1633
/* cmp_val --- compare values of watched item, returns true if different; */
1706
 
 
 
1634
 
1707
1635
static int
1708
 
cmp_val(struct list_item *w, NODE *old, NODE *new)
 
1636
cmp_val(struct list_item *w, NODE *old, NODE *new) 
1709
1637
{
1710
1638
                /*
1711
1639
                 *      case    old     new     result
1712
1640
                 *      ------------------------------
1713
 
                 *      1:      NULL    ARRAY   true
 
1641
                 *      1:      NULL    ARRAY   true    
1714
1642
                 *      2:      NULL    SCALAR  true
1715
1643
                 *      3:      NULL    NULL    false
1716
1644
                 *      4:      SCALAR  SCALAR  cmp_node
1717
1645
                 *      5:      SCALAR  ARRAY   true
1718
1646
                 *      6:      SCALAR  NULL    true
1719
1647
                 *      7:      ARRAY   SCALAR  true
1720
 
                 *      8:      ARRAY   ARRAY   compare size
 
1648
                 *      8:      ARRAY   ARRAY   compare size    
1721
1649
                 *      9:      ARRAY   NULL    true
1722
1650
                 */
1723
1651
 
1742
1670
 
1743
1671
        if (new->type == Node_var_array)        /* 5 */
1744
1672
                return true;
1745
 
        return cmp_nodes(old, new, true);       /* 4 */
 
1673
        return cmp_nodes(old, new);                     /* 4 */
1746
1674
}
1747
1675
 
1748
1676
/* watchpoint_triggered --- check if we should stop at this watchpoint;
1778
1706
                        t2 = symbol;
1779
1707
                        break;
1780
1708
                case Node_var_new:
1781
 
                case Node_elem_new:
1782
1709
                        break;
1783
1710
                default:
1784
 
                        cant_happen("unexpected symbol type %s", nodetype2str(symbol->type));
 
1711
                        cant_happen();
1785
1712
                }
1786
1713
        }
1787
1714
 
1855
1782
                r = *get_field(field_num, NULL);
1856
1783
                w->cur_value = dupnode(r);
1857
1784
        } else {
1858
 
                if (symbol->type == Node_var_new || symbol->type == Node_elem_new)
 
1785
                if (symbol->type == Node_var_new)
1859
1786
                        w->cur_value = (NODE *) 0;
1860
1787
                else if (symbol->type == Node_var) {
1861
1788
                        r = symbol->var_value;
1863
1790
                } else if (symbol->type == Node_var_array) {
1864
1791
                        w->flags |= CUR_IS_ARRAY;
1865
1792
                        w->cur_size = assoc_length(symbol);
1866
 
                } else if (symbol->type == Node_val && (symbol->flags & REGEX) != 0) {
1867
 
                        w->cur_value = dupnode(symbol);
1868
1793
                } /* else
1869
1794
                        can't happen */
1870
1795
        }
1897
1822
                fprintf(out_fp, "%s", w->sname);
1898
1823
                for (i = 0; i < w->num_subs; i++) {
1899
1824
                        sub = w->subs[i];
1900
 
                        fprintf(out_fp, "[\"%.*s\"]", (int) sub->stlen, sub->stptr);
 
1825
                        fprintf(out_fp, "[\"%s\"]", sub->stptr);
1901
1826
                }
1902
1827
                fprintf(out_fp, "\n");
1903
1828
        } else if (IS_FIELD(w))
1909
1834
}
1910
1835
 
1911
1836
/* do_unwatch --- unwatch command */
1912
 
 
 
1837
        
1913
1838
int
1914
1839
do_unwatch(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
1915
1840
{
1956
1881
{
1957
1882
        NODE *func;
1958
1883
        int i, pcount;
1959
 
        struct pf_data *data = (struct pf_data *) x;
 
1884
        struct pf_data *data = (struct pf_data *) x;  
1960
1885
        int defn = data->defn;
1961
 
        Func_print print_func = data->print_func;
 
1886
        Func_print print_func = data->print_func;       
1962
1887
        FILE *fp = data->fp;
1963
1888
 
1964
1889
        func = pc->func_body;
1967
1892
        print_func(fp, "%s(", func->vname);
1968
1893
        for (i = 0; i < pcount; i++) {
1969
1894
                print_func(fp, "%s", func->fparms[i].param);
1970
 
                if (i < pcount - 1)
 
1895
                if (i < pcount - 1)               
1971
1896
                        print_func(fp, ", ");
1972
1897
        }
1973
1898
        print_func(fp, ")");
2011
1936
        } else {
2012
1937
                fprintf(out_fp, _("#%ld\tin "), num);
2013
1938
                print_frame(f->func_node, f->vname,
2014
 
                        ((INSTRUCTION *) find_frame(num - 1)->reti)->source_line);
 
1939
                        ((INSTRUCTION *) find_frame(num - 1)->reti)->source_line); 
2015
1940
        }
2016
1941
        fprintf(out_fp, "\n");
2017
1942
}
2040
1965
                        if (cur < 0)
2041
1966
                                cur = 0;
2042
1967
                }
2043
 
        }
 
1968
        } 
2044
1969
 
2045
1970
        for (; cur <= last; cur++) {
2046
1971
                print_numbered_frame(cur);
2048
1973
        if (cur <= fcall_count)
2049
1974
                fprintf(out_fp, _("More stack frames follow ...\n"));
2050
1975
        return false;
2051
 
}
 
1976
}       
2052
1977
 
2053
1978
/* print_cur_frame_and_sourceline --- print current frame, and
2054
1979
 *                                    current source line.
2055
1980
 */
2056
 
 
 
1981
 
2057
1982
static void
2058
1983
print_cur_frame_and_sourceline()
2059
1984
{
2167
2092
/* mk_breakpoint --- create a breakpoint instruction and the corresponding
2168
2093
 *                   breakpoint structure.
2169
2094
 */
2170
 
 
 
2095
 
2171
2096
static INSTRUCTION *
2172
2097
mk_breakpoint(char *src, int srcline)
2173
2098
{
2188
2113
        b->src = src;
2189
2114
        bp->break_pt = b;
2190
2115
        b->bpi = bp;
2191
 
 
 
2116
                        
2192
2117
        /* prepend to list */
2193
2118
        b->next = breakpoints.next;
2194
2119
        b->prev = &breakpoints;
2211
2136
         * deleteing the instruction is not that simple,
2212
2137
         * since could have reference to it somewhere else (e.g. cur_pc).
2213
2138
         */
2214
 
 
 
2139
  
2215
2140
        pc->opcode = Op_no_op;
2216
2141
        pc->source_line = 0;
2217
2142
        pc->break_pt = NULL;
2222
2147
                delete_commands_item(c->next);
2223
2148
        }
2224
2149
 
2225
 
        free_context(b->cndn.ctxt, false);
 
2150
        free_context(b->cndn.ctxt, false);      
2226
2151
        if (b->cndn.expr != NULL)
2227
2152
                efree(b->cndn.expr);
2228
2153
 
2240
2165
        BREAKPOINT *b;
2241
2166
 
2242
2167
        if (num <= 0)
2243
 
                return NULL;
 
2168
                return NULL; 
2244
2169
 
2245
2170
        for (b = breakpoints.next; b != &breakpoints; b = b->next) {
2246
2171
                if (b->number == num)
2250
2175
}
2251
2176
 
2252
2177
/* add_breakpoint --- add a breakpoint instruction between PREVP and IP */
2253
 
 
 
2178
 
2254
2179
static BREAKPOINT *
2255
2180
add_breakpoint(INSTRUCTION *prevp, INSTRUCTION *ip, char *src, bool silent)
2256
2181
{
2330
2255
                         * a monotonically increasing sequence. Check if the line # is between
2331
2256
                         * the first and last statements of the case block before continuing
2332
2257
                         * the search.
2333
 
                         */
 
2258
                         */ 
2334
2259
                        for (i2 = ip->stmt_start, i1 = i2->nexti; i2 != ip->stmt_end;
2335
2260
                                                                i2 = i1, i1 = i1->nexti) {
2336
2261
                                if (i1->source_line >= lineno)
2368
2293
        }
2369
2294
        return NULL;
2370
2295
}
2371
 
 
 
2296
                
2372
2297
/* set_breakpoint --- set a breakpoint */
2373
2298
 
2374
2299
static int
2384
2309
        if (arg == NULL) {
2385
2310
/*
2386
2311
* (From GDB Documentation):
2387
 
*
 
2312
2388
2313
* When called without any arguments, break sets a breakpoint at the next instruction
2389
2314
* to be executed in the selected stack frame (see section Examining the Stack).
2390
2315
* In any selected frame but the innermost, this makes your program stop as soon
2397
2322
* one instruction has been executed. If it did not do this,
2398
2323
* you would be unable to proceed past a breakpoint without first disabling the
2399
2324
* breakpoint. This rule applies whether or not the breakpoint already existed
2400
 
* when your program stopped.
 
2325
* when your program stopped. 
2401
2326
*/
2402
2327
                CHECK_PROG_RUNNING();
2403
2328
                if (cur_frame == 0) {
2412
2337
                rp = find_rule(src, ip->source_line);
2413
2338
                assert(rp != NULL);
2414
2339
                if ((b = set_breakpoint_next(rp, ip)) == NULL)
2415
 
                        fprintf(out_fp, _("cannot set breakpoint in file `%s'\n"), src);
 
2340
                        fprintf(out_fp, _("Can't set breakpoint in file `%s'\n"), src);
2416
2341
                else {
2417
2342
                        if (cur_frame == 0) {   /* stop next time */
2418
2343
                                b->flags |= BP_IGNORE;
2441
2366
        case D_int:             /* break lineno */
2442
2367
                lineno = (int) arg->a_int;
2443
2368
                if (lineno <= 0 || lineno > s->srclines)
2444
 
                        d_error(_("line number %d in file `%s' is out of range"), lineno, src);
 
2369
                        d_error(_("line number %d in file `%s' out of range"), lineno, src);
2445
2370
                else {
2446
2371
                        rp = find_rule(src, lineno);
2447
2372
                        if (rp == NULL)
2448
 
                                fprintf(out_fp, _("internal error: cannot find rule\n"));
 
2373
                                fprintf(out_fp, _("Can't find rule!!!\n"));
2449
2374
                        if (rp == NULL || (b = set_breakpoint_at(rp, lineno, false)) == NULL)
2450
 
                                fprintf(out_fp, _("cannot set breakpoint at `%s':%d\n"),
 
2375
                                fprintf(out_fp, _("Can't set breakpoint at `%s':%d\n"),
2451
2376
                                                src, lineno);
2452
2377
                        if (b != NULL && temporary)
2453
2378
                                b->flags |= BP_TEMP;
2459
2384
                func = arg->a_node;
2460
2385
                rp = func->code_ptr;
2461
2386
                if ((b = set_breakpoint_at(rp, rp->source_line, false)) == NULL)
2462
 
                        fprintf(out_fp, _("cannot set breakpoint in function `%s'\n"),
 
2387
                        fprintf(out_fp, _("Can't set breakpoint in function `%s'\n"),
2463
2388
                                                func->vname);
2464
 
                else {
2465
 
                        if (temporary)
2466
 
                                b->flags |= BP_TEMP;
2467
 
                        lineno = b->bpi->source_line;
2468
 
                }
 
2389
                else if (temporary)
 
2390
                        b->flags |= BP_TEMP;
 
2391
                lineno = b->bpi->source_line;
2469
2392
                break;
2470
2393
 
2471
2394
        default:
2504
2427
        if ((b->flags & BP_ENABLE_ONCE) != 0) {
2505
2428
                b->flags &= ~BP_ENABLE_ONCE;
2506
2429
                b->flags &= ~BP_ENABLE;
2507
 
        }
 
2430
        } 
2508
2431
        return b->number;
2509
2432
}
2510
2433
 
2514
2437
do_breakpoint(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
2515
2438
{
2516
2439
        return set_breakpoint(arg, false);
2517
 
}
 
2440
}       
2518
2441
 
2519
2442
/* do_tmp_breakpoint --- tbreak command */
2520
2443
 
2535
2458
        NODE *func;
2536
2459
        SRCFILE *s = cur_srcfile;
2537
2460
        char *src = cur_srcfile->src;
2538
 
        int bp_found = 0;
 
2461
        bool bp_found = false;
2539
2462
 
2540
2463
        if (arg == NULL) {      /* clear */
2541
2464
                CHECK_PROG_RUNNING();
2561
2484
                src = s->src;
2562
2485
                if (arg->type == D_func)
2563
2486
                        goto func;
2564
 
                /* fall through */
 
2487
                /* else
 
2488
                        fall through */
2565
2489
        case D_int:     /* clear lineno */
2566
2490
                lineno = (int) arg->a_int;
2567
2491
                if (lineno <= 0 || lineno > s->srclines) {
2586
2510
                                fprintf(out_fp, ", %d", b->number);
2587
2511
                        delete_breakpoint(b);
2588
2512
                }
2589
 
                if (bp_found == 0)
 
2513
                if (! bp_found)
2590
2514
                        fprintf(out_fp, _("No breakpoint(s) at entry to function `%s'\n"),
2591
2515
                                        func->vname);
2592
2516
                else
2613
2537
                }
2614
2538
        }
2615
2539
 
2616
 
        if (bp_found == 0)
 
2540
        if (! bp_found)
2617
2541
                fprintf(out_fp, _("No breakpoint at file `%s', line #%d\n"),
2618
2542
                                        src, (int) lineno);
2619
2543
        else
2687
2611
                delete_all = prompt_yes_no(
2688
2612
                                        _("Delete all breakpoints? (y or n) "),
2689
2613
                                        _("y")[0], true, out_fp);
2690
 
 
 
2614
                
2691
2615
                if (delete_all) {
2692
2616
                        while (breakpoints.next != &breakpoints)
2693
2617
                                delete_breakpoint(breakpoints.next);
2812
2736
        /* our completion function. */
2813
2737
        rl_attempted_completion_function = command_completion;
2814
2738
 
2815
 
        read_a_line = readline;
 
2739
        read_a_line = readline;  
2816
2740
}
2817
2741
#else
2818
2742
#define initialize_readline()   /* nothing */
2845
2769
        if (! read_a_line)
2846
2770
                read_a_line = g_readline;
2847
2771
 
2848
 
        push_cmd_src(input_fd, input_from_tty, read_a_line, 0, 0, EXIT_FATAL);
 
2772
        push_cmd_src(input_fd, input_from_tty, read_a_line, 0, 0, EXIT_FATAL); 
2849
2773
 
2850
 
        setbuf(out_fp, (char *) NULL);
 
2774
        setbuf(out_fp, (char *) NULL);                                                           
2851
2775
        for (cur_srcfile = srcfiles->prev; cur_srcfile != srcfiles;
2852
2776
                        cur_srcfile = cur_srcfile->prev) {
2853
2777
                if (cur_srcfile->stype == SRC_FILE
2870
2794
                /* We are restarting; restore state (breakpoints, history etc.)
2871
2795
                 * passed as environment variables and optionally execute the run command.
2872
2796
                 */
2873
 
                unserialize_list(BREAK);
2874
 
                unserialize_list(WATCH);
2875
 
                unserialize_list(DISPLAY);
2876
 
                unserialize_list(HISTORY);
2877
 
                unserialize_list(OPTION);
 
2797
                unserialize(BREAK);
 
2798
                unserialize(WATCH);
 
2799
                unserialize(DISPLAY);
 
2800
                unserialize(HISTORY);
 
2801
                unserialize(OPTION);
2878
2802
                unsetenv("DGAWK_RESTART");
2879
 
                fprintf(out_fp, _("Restarting ...\n"));
2880
 
                if (strcasecmp(run, "true") == 0)
 
2803
                fprintf(out_fp, "Restarting ...\n");    
 
2804
                if (run[0] == 'T') 
2881
2805
                        (void) do_run(NULL, 0);
2882
2806
 
2883
2807
        } else if (command_file != NULL) {
2885
2809
                int fd;
2886
2810
                fd = open_readfd(command_file);
2887
2811
                if (fd == INVALID_HANDLE) {
2888
 
                        fprintf(stderr, _("cannot open source file `%s' for reading: %s"),
 
2812
                        fprintf(stderr, _("can't open source file `%s' for reading (%s)"),
2889
2813
                                                command_file, strerror(errno));
2890
2814
                        exit(EXIT_FAILURE);
2891
2815
                }
2943
2867
 
2944
2868
        pc = *pi;
2945
2869
        if (stop.command == D_return)
2946
 
                return false;
 
2870
                return false; 
2947
2871
        if (pc->opcode == Op_breakpoint) {
2948
2872
                int bnum;
2949
2873
                *pi = pc->nexti;    /* skip past the breakpoint instruction;
2965
2889
restart(bool run)
2966
2890
{
2967
2891
        /* save state in the environment after serialization */
2968
 
        serialize_list(BREAK);
2969
 
        serialize_list(WATCH);
2970
 
        serialize_list(DISPLAY);
2971
 
        serialize_list(HISTORY);
2972
 
        serialize_list(OPTION);
 
2892
        serialize(BREAK);
 
2893
        serialize(WATCH);
 
2894
        serialize(DISPLAY);
 
2895
        serialize(HISTORY);
 
2896
        serialize(OPTION);
2973
2897
 
2974
2898
        /* tell the new process to restore state from the environment */
2975
2899
        setenv("DGAWK_RESTART", (run ? "true" : "false"), 1);
3023
2947
                restart(true);  /* does not return */
3024
2948
        }
3025
2949
 
3026
 
        fprintf(out_fp, _("Starting program:\n"));
 
2950
        fprintf(out_fp, _("Starting program: \n"));
3027
2951
 
3028
2952
        prog_running = true;
3029
 
        fatal_tag_valid = 1;
 
2953
        fatal_tag_valid = true;
3030
2954
        if (setjmp(fatal_tag) == 0)
3031
2955
                (void) interpret(code_block);
3032
2956
 
3033
 
        fatal_tag_valid = 0;
 
2957
        fatal_tag_valid = false;
3034
2958
        prog_running = false;
3035
 
        fprintf(out_fp, (! exiting && exit_val != EXIT_SUCCESS)
3036
 
                                ? _("Program exited abnormally with exit value: %d\n")
3037
 
                                : _("Program exited normally with exit value: %d\n"),
 
2959
        fprintf(out_fp, _("Program exited %s with exit value: %d\n"),
 
2960
                        (! exiting && exit_val != EXIT_SUCCESS) ? "abnormally"
 
2961
                                                                : "normally",
3038
2962
                        exit_val);
3039
2963
        need_restart = true;
3040
2964
        return false;
3088
3012
        }
3089
3013
        b = find_breakpoint(stop.break_point);
3090
3014
        if (b == NULL) {
3091
 
                d_error(_("invalid breakpoint number %d"), stop.break_point);
 
3015
                d_error(_("invalid breakpoint number %d."), stop.break_point);
3092
3016
                return false;
3093
3017
        }
3094
3018
        b->flags |= BP_IGNORE;
3108
3032
                stop.repeat_count = arg->a_int;
3109
3033
        else
3110
3034
                stop.repeat_count = 1;
3111
 
        stop.command = (enum argtype) cmd;
 
3035
        stop.command = cmd;
3112
3036
        return true;
3113
3037
}
3114
3038
 
3285
3209
        }
3286
3210
        stop.fcall_count = fcall_count - cur_frame - 1;
3287
3211
        assert(stop.fcall_count >= 0);
3288
 
        fprintf(out_fp, _("Run until return from "));
 
3212
        fprintf(out_fp, _("Run till return from "));
3289
3213
        print_numbered_frame(cur_frame);
3290
3214
        stop.check_func = check_finish;
3291
 
        stop.command = (enum argtype) cmd;
 
3215
        stop.command = cmd;
3292
3216
        stop.print_ret = true;
3293
3217
        return true;
3294
3218
}
3311
3235
 
3312
3236
                func = find_frame(cur_frame)->func_node;
3313
3237
                assert(func != NULL);
3314
 
                *pi = (func->code_ptr + 1)->lasti;
 
3238
                *pi = (func->code_ptr + 1)->lasti;              
3315
3239
                /* assert((*pi)->opcode == Op_K_return); */
3316
3240
        }
3317
3241
 
3336
3260
        assert(stop.fcall_count >= 0);
3337
3261
        stop.pc = (func->code_ptr + 1)->lasti;
3338
3262
        assert(stop.pc->opcode == Op_K_return);
3339
 
        stop.command = (enum argtype) cmd;
 
3263
        stop.command = cmd;
3340
3264
 
3341
3265
        stop.check_func = check_return;
3342
3266
 
3351
3275
 
3352
3276
/* check_until --- process until, returns true if stopping */
3353
3277
 
3354
 
static int
 
3278
int
3355
3279
check_until(INSTRUCTION **pi)
3356
3280
{
3357
3281
        if (fcall_count < stop.fcall_count) { /* current stack frame returned */
3378
3302
        int lineno;
3379
3303
        INSTRUCTION *rp, *ip;
3380
3304
        NODE *func;
3381
 
 
 
3305
        
3382
3306
        CHECK_PROG_RUNNING();
3383
3307
        stop.pc = NULL;
3384
3308
        stop.sourceline = 0;
3399
3323
                stop.sourceline = sourceline;
3400
3324
                stop.fcall_count = fcall_count - cur_frame;
3401
3325
                stop.check_func = check_until;
3402
 
                stop.command = (enum argtype) cmd;
 
3326
                stop.command = cmd;
3403
3327
                return true;
3404
3328
        }
3405
3329
 
3418
3342
                src = s->src;
3419
3343
                if (arg->type == D_func)
3420
3344
                        goto func;
3421
 
                /* fall through */
 
3345
                /* else
 
3346
                        fall through */
3422
3347
        case D_int:     /* until lineno */
3423
3348
                lineno = arg->a_int;
3424
3349
                if (lineno <= 0 || lineno > s->srclines) {
3437
3362
                                stop.pc = ip;
3438
3363
                                stop.fcall_count = fcall_count - cur_frame;
3439
3364
                                stop.check_func = check_until;
3440
 
                                stop.command = (enum argtype) cmd;
 
3365
                                stop.command = cmd;
3441
3366
                                return true;
3442
3367
                        }
3443
3368
                }
3444
 
                fprintf(out_fp, _("cannot find specified location in function `%s'\n"),
 
3369
                fprintf(out_fp, _("Can't find specified location in function `%s'\n"),
3445
3370
                                func->vname);
3446
3371
                /* fall through */
3447
3372
        default:
3458
3383
                        stop.pc = ip;
3459
3384
                        stop.fcall_count = fcall_count - cur_frame;
3460
3385
                        stop.check_func = check_until;
3461
 
                        stop.command = (enum argtype) cmd;
 
3386
                        stop.command = cmd;
3462
3387
                        return true;
3463
3388
                }
3464
3389
                if (ip == (rp + 1)->lasti)
3465
3390
                        break;
3466
3391
        }
3467
 
        fprintf(out_fp, _("cannot find specified location %d in file `%s'\n"),
 
3392
        fprintf(out_fp, _("Can't find specified location %d in file `%s'\n"),
3468
3393
                                lineno, src);
3469
3394
        return false;
3470
3395
}
3482
3407
                fprintf(out_fp, "%s", w->sname);
3483
3408
                for (i = 0; i < w->num_subs; i++) {
3484
3409
                        sub = w->subs[i];
3485
 
                        fprintf(out_fp, "[\"%.*s\"]", (int) sub->stlen, sub->stptr);
 
3410
                        fprintf(out_fp, "[\"%s\"]", sub->stptr);
3486
3411
                }
3487
 
                fprintf(out_fp, "\n");
 
3412
                fprintf(out_fp, "\n");  
3488
3413
        } else if (IS_FIELD(w))
3489
3414
                fprintf(out_fp, "$%ld\n", get_number_si(symbol));
3490
3415
        else
3549
3474
                print_watch_item(w);
3550
3475
        }
3551
3476
 
3552
 
        /* frame info */
 
3477
        /* frame info */        
3553
3478
        if (stop.print_frame) {
3554
3479
                print_frame(frame_ptr->func_node, source, sourceline);
3555
3480
                fprintf(out_fp, "\n");
3556
3481
                stop.print_frame = false;
3557
 
        }
 
3482
        } 
3558
3483
 
3559
3484
        (void) print_lines(source, sourceline, 1);
3560
3485
 
3566
3491
        /* update last_printed_line, so that  output of 'list' is
3567
3492
         * centered around current sourceline
3568
3493
         */
3569
 
 
 
3494
 
3570
3495
        last_printed_line = sourceline - list_size / 2;
3571
3496
        if (last_printed_line < 0)
3572
3497
                last_printed_line = 0;
3573
3498
 
3574
 
        /* update current source file */
 
3499
        /* update current source file */        
3575
3500
        s = source_find(source);
3576
3501
        if (cur_srcfile != s) {
3577
3502
                if (cur_srcfile->fd != INVALID_HANDLE) {
3597
3522
        read_command();         /* zzparse */
3598
3523
}
3599
3524
 
3600
 
/* debug_post_execute --- post_hook in the interpreter */
 
3525
/* debug_post_execute --- post_hook in the interpreter */ 
3601
3526
 
3602
3527
static void
3603
3528
debug_post_execute(INSTRUCTION *pc)
3616
3541
                        stop.command = D_illegal;
3617
3542
                        stop.check_func = NULL;
3618
3543
                        fprintf(out_fp, _("'finish' not meaningful with non-local jump '%s'\n"),
3619
 
                                                        op2str(pc->opcode));
 
3544
                                                        op2str(pc->opcode)); 
3620
3545
                } else if (stop.command == D_until) {
3621
3546
                        /* cancel until command */
3622
3547
                        stop.print_frame = false;
3623
3548
                        stop.command = D_illegal;
3624
3549
                        stop.check_func = NULL;
3625
3550
                        fprintf(out_fp, _("'until' not meaningful with non-local jump '%s'\n"),
3626
 
                                                        op2str(pc->opcode));
 
3551
                                                        op2str(pc->opcode)); 
3627
3552
                }
3628
3553
                break;
3629
3554
 
3650
3575
        }
3651
3576
}
3652
3577
 
3653
 
/* debug_pre_execute --- pre_hook, called by the interpreter before execution;
 
3578
/* debug_pre_execute --- pre_hook, called by the interpreter before execution; 
3654
3579
 *                 checks if execution needs to be suspended and control
3655
3580
 *                 transferred to the debugger.
3656
3581
 */
3680
3605
 * yield surprising results. Ditto for Op_push_lhs for special variables
3681
3606
 * (upto Op_var_assign, the set_FOO routine).
3682
3607
 */
3683
 
 
 
3608
 
3684
3609
        switch (cur_pc->opcode) {
3685
3610
        case Op_field_spec_lhs:
3686
3611
                cant_stop = true;
3688
3613
 
3689
3614
        case Op_field_assign:
3690
3615
                cant_stop = false;
3691
 
                return true; /* may stop at next instruction */
 
3616
                return true; /* may stop at next instruction */ 
3692
3617
 
3693
3618
        case Op_push_lhs:
3694
3619
                m = cur_pc->memory;
3718
3643
                break;  /* processed later in check_breakpoint() */
3719
3644
 
3720
3645
        default:
3721
 
                if (cur_pc->source_line <= 0)
 
3646
                if (cur_pc->source_line <= 0) 
3722
3647
                        return true;
3723
3648
                break;
3724
3649
        }
3728
3653
 
3729
3654
        assert(sourceline > 0);
3730
3655
 
3731
 
        /*
3732
 
         * 11/2015: This used to check breakpoints first, but that could
3733
 
         * produce strange behavior, where a watchpoint doesn't print until
3734
 
         * some time after the data changed.  This reworks things so that
3735
 
         * watchpoints are checked first. It's a bit of a hack, but
3736
 
         * the behavior for the user is more logical.
3737
 
         */
3738
 
        if (check_watchpoint()) {
3739
 
                next_command(); /* return to debugger interface */
3740
 
                if (stop.command == D_return)
3741
 
                        *pi = stop.pc;  /* jump to this instruction */
3742
 
                else if (cur_pc->opcode == Op_breakpoint)
3743
 
                        cur_pc = cur_pc->nexti;    /* skip past the breakpoint instruction */
3744
 
        } else if (check_breakpoint(pi)
 
3656
        if (check_breakpoint(pi)
 
3657
                        || check_watchpoint()
3745
3658
                        || (stop.check_func && stop.check_func(pi))) {
3746
3659
                next_command(); /* return to debugger interface */
3747
3660
                if (stop.command == D_return)
3756
3669
 
3757
3670
/* print_memory --- print a scalar value */
3758
3671
 
3759
 
static void
 
3672
static void 
3760
3673
print_memory(NODE *m, NODE *func, Func_print print_func, FILE *fp)
3761
3674
{
3762
3675
        switch (m->type) {
3774
3687
                                print_func(fp, "%g", m->numbr);
3775
3688
                } else if ((m->flags & STRING) != 0)
3776
3689
                        pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', false);
3777
 
                else if ((m->flags & REGEX) != 0) {
3778
 
                        print_func(fp, "@");
3779
 
                        pp_string_fp(print_func, fp, m->stptr, m->stlen, '/', false);
3780
 
                } else
 
3690
                else if ((m->flags & NUMCUR) != 0) {
 
3691
#ifdef HAVE_MPFR
 
3692
                        if ((m->flags & MPFN) != 0)
 
3693
                                print_func(fp, "%s", mpg_fmt("%R*g", ROUND_MODE, m->mpg_numbr));
 
3694
                        else if ((m->flags & MPZN) != 0)
 
3695
                                print_func(fp, "%s", mpg_fmt("%Zd", m->mpg_i));
 
3696
                        else
 
3697
#endif
 
3698
                                print_func(fp, "%g", m->numbr);
 
3699
                } else if ((m->flags & STRCUR) != 0)
 
3700
                        pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', false);
 
3701
                else
3781
3702
                        print_func(fp, "-?-");
3782
3703
                print_func(fp, " [%s]", flags2str(m->flags));
3783
3704
                break;
3788
3709
 
3789
3710
        case Node_dynregex:
3790
3711
                break;
3791
 
 
 
3712
                
3792
3713
        case Node_param_list:
3793
3714
                assert(func != NULL);
3794
3715
                print_func(fp, "%s", func->fparms[m->param_cnt].param);
3800
3721
                print_func(fp, "%s", m->vname);
3801
3722
                break;
3802
3723
 
3803
 
        case Node_elem_new:
3804
 
                print_func(fp, "element - %p", m);
3805
 
                break;
3806
 
 
3807
3724
        default:
3808
3725
                print_func(fp, "?");  /* can't happen */
3809
3726
        }
3821
3738
        if (noffset == 0) {
3822
3739
                static char buf[50];
3823
3740
                /* offset for 2nd to last lines in a multi-line output */
3824
 
                noffset = sprintf(buf, "[      :" PTRFMT "] %-20.20s: ", (void *) pc,
 
3741
                noffset = sprintf(buf, "[      :%p] %-20.20s: ", (void *) pc,
3825
3742
                                opcode2str(pc->opcode));
3826
3743
        }
3827
3744
 
3847
3764
                print_func(fp, "\n");
3848
3765
 
3849
3766
        if (pc->source_line <= 0)
3850
 
                print_func(fp, "[      :" PTRFMT "] %-20.20s: ", pc, opcode2str(pc->opcode));
 
3767
                print_func(fp, "[      :%p] %-20.20s: ", pc, opcode2str(pc->opcode));
3851
3768
        else
3852
 
                print_func(fp, "[%6d:" PTRFMT "] %-20.20s: ",
 
3769
                print_func(fp, "[%6d:%p] %-20.20s: ",
3853
3770
                                pc->source_line, pc, opcode2str(pc->opcode));
3854
3771
 
3855
3772
        if (prog_running && ! in_dump) {
3857
3774
                func = find_frame(0)->func_node;
3858
3775
        }
3859
3776
 
3860
 
 
 
3777
                        
3861
3778
        switch (pc->opcode) {
3862
 
        case Op_K_if:
3863
 
                print_func(fp, "[branch_if = " PTRFMT "] [branch_else = " PTRFMT "] [branch_else->lasti = " PTRFMT "]\n",
3864
 
                                pc->branch_if, pc->branch_else, pc->branch_else->lasti);
3865
 
                break;
3866
 
 
3867
 
        case Op_K_else:
3868
 
                print_func(fp, "[branch_end = " PTRFMT "]\n", pc->branch_end);
3869
 
                break;
3870
 
 
3871
 
        case Op_K_while:
3872
 
                print_func(fp, "[while_body = " PTRFMT "] [target_break = " PTRFMT "]\n", (pc+1)->while_body, pc->target_break);
3873
 
                break;
3874
 
 
3875
 
        case Op_K_do:
3876
 
                print_func(fp, "[doloop_cond = " PTRFMT "] [target_break = " PTRFMT "]", (pc+1)->doloop_cond, pc->target_break);
3877
 
                if (pc->comment)
3878
 
                        print_func(fp, " [comment = " PTRFMT "]", pc->comment);
3879
 
                print_func(fp, "\n");
3880
 
                if (pc->comment)
3881
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
3882
 
                break;
3883
 
 
3884
 
        case Op_K_for:
3885
 
                print_func(fp, "[forloop_cond = " PTRFMT "] ", (pc+1)->forloop_cond);
3886
 
                /* fall through */
3887
 
        case Op_K_arrayfor:
3888
 
                print_func(fp, "[forloop_body = " PTRFMT "] ", (pc+1)->forloop_body);
3889
 
                print_func(fp, "[target_break = " PTRFMT "] [target_continue = " PTRFMT "]", pc->target_break, pc->target_continue);
3890
 
                if (pc->comment != NULL) {
3891
 
                        print_func(fp, " [comment = " PTRFMT "]\n", (pc)->comment);
3892
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
3893
 
                } else
3894
 
                        print_func(fp, "\n");
3895
 
                break;
3896
 
 
3897
 
        case Op_K_switch:
3898
 
        {
3899
 
                bool need_newline = false;
3900
 
                print_func(fp, "[switch_start = " PTRFMT "] [switch_end = " PTRFMT "]\n", (pc+1)->switch_start, (pc+1)->switch_end);
3901
 
                if (pc->comment || (pc+1)->switch_end->comment)
3902
 
                        print_func(fp, "%*s", noffset, "");
3903
 
                if (pc->comment) {
3904
 
                        print_func(fp, "[start_comment = " PTRFMT "]", pc->comment);
3905
 
                        need_newline = true;
3906
 
                }
3907
 
                if ((pc+1)->switch_end->comment) {
3908
 
                        print_func(fp, "[end_comment = " PTRFMT "]", (pc + 1)->switch_end->comment);
3909
 
                        need_newline = true;
3910
 
                }
3911
 
                if (need_newline)
3912
 
                        print_func(fp, "\n");
3913
 
                if (pc->comment)
3914
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
3915
 
                if ((pc+1)->switch_end->comment)
3916
 
                        print_instruction((pc+1)->switch_end->comment, print_func, fp, in_dump);
3917
 
        }
3918
 
                break;
3919
 
 
3920
 
        case Op_K_default:
3921
 
                print_func(fp, "[stmt_start = " PTRFMT "] [stmt_end = " PTRFMT "]", pc->stmt_start, pc->stmt_end);
3922
 
                if (pc->comment) {
3923
 
                        print_func(fp, " [comment = " PTRFMT "]\n", pc->comment);
3924
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
3925
 
                } else
3926
 
                        print_func(fp, "\n");
3927
 
                break;
3928
 
 
3929
3779
        case Op_var_update:
3930
3780
                print_func(fp, "[update_%s()]\n", get_spec_varname(pc->update_var));
3931
3781
                break;
3933
3783
        case Op_var_assign:
3934
3784
                print_func(fp, "[set_%s()]", get_spec_varname(pc->assign_var));
3935
3785
                if (pc->assign_ctxt != 0)
3936
 
                        print_func(fp, " [assign_ctxt = %s]", opcode2str((OPCODE) pc->assign_ctxt));
 
3786
                        print_func(fp, " [assign_ctxt = %s]", opcode2str(pc->assign_ctxt));
3937
3787
                print_func(fp, "\n");
3938
3788
                break;
3939
3789
 
3943
3793
                break;
3944
3794
 
3945
3795
        case Op_field_spec_lhs:
3946
 
                print_func(fp, "[target_assign = " PTRFMT "] [do_reference = %s]\n",
 
3796
                print_func(fp, "[target_assign = %p] [do_reference = %s]\n",
3947
3797
                                pc->target_assign, pc->do_reference ? "true" : "false");
3948
3798
                break;
3949
3799
 
3950
3800
        case Op_func:
3951
 
                print_func(fp, "[param_cnt = %d] [source_file = %s]", pcount,
 
3801
                print_func(fp, "[param_cnt = %d] [source_file = %s]\n", pcount,
3952
3802
                                pc->source_file ? pc->source_file : "cmd. line");
3953
 
                if (pc[3].nexti != NULL) {
3954
 
                        print_func(fp, "[ns_list = " PTRFMT "]\n", pc[3].nexti);
3955
 
                        print_ns_list(pc[3].nexti, print_func, fp, in_dump);
3956
 
                } else
3957
 
                        print_func(fp, "\n");
3958
3803
                break;
3959
3804
 
3960
3805
        case Op_K_getline_redir:
3965
3810
 
3966
3811
        case Op_K_getline:
3967
3812
                print_func(fp, "[into_var = %s]\n", pc->into_var ? "true" : "false");
3968
 
                print_func(fp, "%*s[target_beginfile = " PTRFMT "] [target_endfile = " PTRFMT "]\n",
 
3813
                print_func(fp, "%*s[target_beginfile = %p] [target_endfile = %p]\n",
3969
3814
                                noffset, "",
3970
3815
                                (pc + 1)->target_beginfile, (pc + 1)->target_endfile);
3971
3816
                break;
3987
3832
                break;
3988
3833
 
3989
3834
        case Op_K_nextfile:
3990
 
                print_func(fp, "[target_newfile = " PTRFMT "] [target_endfile = " PTRFMT "]\n",
 
3835
                print_func(fp, "[target_newfile = %p] [target_endfile = %p]\n",
3991
3836
                                pc->target_newfile, pc->target_endfile);
3992
3837
                break;
3993
3838
 
3994
3839
        case Op_newfile:
3995
 
                print_func(fp, "[target_jmp = " PTRFMT "] [target_endfile = " PTRFMT "]\n",
 
3840
                print_func(fp, "[target_jmp = %p] [target_endfile = %p]\n",
3996
3841
                                pc->target_jmp, pc->target_endfile);
3997
 
                print_func(fp, "%*s[target_get_record = " PTRFMT "]\n",
 
3842
                print_func(fp, "%*s[target_get_record = %p]\n",
3998
3843
                                noffset, "", (pc + 1)->target_get_record);
3999
3844
                break;
4000
3845
 
4001
3846
        case Op_get_record:
4002
 
                print_func(fp, "[target_newfile = " PTRFMT "]\n", pc->target_newfile);
 
3847
                print_func(fp, "[target_newfile = %p]\n", pc->target_newfile);
4003
3848
                break;
4004
3849
 
4005
3850
        case Op_jmp:
4011
3856
        case Op_arrayfor_init:
4012
3857
        case Op_K_break:
4013
3858
        case Op_K_continue:
4014
 
                print_func(fp, "[target_jmp = " PTRFMT "]\n", pc->target_jmp);
 
3859
                print_func(fp, "[target_jmp = %p]\n", pc->target_jmp);
4015
3860
                break;
4016
 
 
4017
3861
        case Op_K_exit:
4018
 
                print_func(fp, "[target_end = " PTRFMT "] [target_atexit = " PTRFMT "]\n",
 
3862
                print_func(fp, "[target_end = %p] [target_atexit = %p]\n",
4019
3863
                                                pc->target_end, pc->target_atexit);
4020
3864
                break;
4021
3865
 
4022
3866
        case Op_K_case:
4023
 
                print_func(fp, "[target_jmp = " PTRFMT "] [match_exp = %s]",
 
3867
                print_func(fp, "[target_jmp = %p] [match_exp = %s]\n",
4024
3868
                                                pc->target_jmp, (pc + 1)->match_exp ? "true" : "false");
4025
 
                if (pc->comment) {
4026
 
                        print_func(fp, " [comment = " PTRFMT "]\n", pc->comment);
4027
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
4028
 
                } else
4029
 
                        print_func(fp, "\n");
4030
 
                break;
4031
 
 
4032
 
        case Op_K_namespace:
4033
 
                print_func(fp, "[namespace = %s]", pc->ns_name);
4034
 
                if (pc->nexti)
4035
 
                        print_func(fp, "[nexti = " PTRFMT "]", pc->nexti);
4036
 
                if (pc->comment)
4037
 
                        print_func(fp, "[comment = " PTRFMT "]", pc->comment);
4038
 
                print_func(fp, "\n");
4039
3869
                break;
4040
3870
 
4041
3871
        case Op_arrayfor_incr:
4042
 
                print_func(fp, "[array_var = %s] [target_jmp = " PTRFMT "]\n",
 
3872
                print_func(fp, "[array_var = %s] [target_jmp = %p]\n",
4043
3873
                                pc->array_var->type == Node_param_list ?
4044
3874
                                   func->fparms[pc->array_var->param_cnt].param : pc->array_var->vname,
4045
3875
                                pc->target_jmp);
4046
3876
                break;
4047
3877
 
4048
3878
        case Op_line_range:
4049
 
                print_func(fp, "[triggered = %ld] [target_jmp = " PTRFMT "]\n",
 
3879
                print_func(fp, "[triggered = %ld] [target_jmp = %p]\n",
4050
3880
                                pc->triggered, pc->target_jmp);
4051
3881
                break;
4052
3882
 
4053
3883
        case Op_cond_pair:
4054
 
                print_func(fp, "[line_range = " PTRFMT "] [target_jmp = " PTRFMT "]\n",
 
3884
                print_func(fp, "[line_range = %p] [target_jmp = %p]\n",
4055
3885
                                pc->line_range, pc->target_jmp);
4056
3886
                break;
4057
3887
 
4074
3904
                                genflags2str(pc->sub_flags, values));
4075
3905
        }
4076
3906
                break;
4077
 
 
 
3907
        
4078
3908
        case Op_builtin:
4079
 
                print_func(fp, "%s [arg_count = %ld]\n", getfname(pc->builtin, false),
 
3909
                print_func(fp, "%s [arg_count = %ld]\n", getfname(pc->builtin),
4080
3910
                                                pc->expr_count);
4081
3911
                break;
4082
3912
 
4107
3937
                break;
4108
3938
 
4109
3939
        case Op_concat:
4110
 
                /* NB: concat_flag CSVAR only used in grammar, don't display it */
 
3940
                /* NB: concat_flag CSVAR only used in grammar, don't display it */ 
4111
3941
                print_func(fp, "[expr_count = %ld] [concat_flag = %s]\n",
4112
3942
                                                pc->expr_count,
4113
3943
                                                (pc->concat_flag & CSUBSEP) != 0 ? "CSUBSEP" : "0");
4114
3944
                break;
4115
3945
 
4116
3946
        case Op_rule:
4117
 
                print_func(fp, "[in_rule = %s] [source_file = %s]",
 
3947
                print_func(fp, "[in_rule = %s] [source_file = %s]\n",
4118
3948
                                ruletab[pc->in_rule],
4119
3949
                                pc->source_file ? pc->source_file : "cmd. line");
4120
 
                if (pc[3].nexti != NULL) {
4121
 
                        print_func(fp, "[ns_list = " PTRFMT "]\n", pc[3].nexti);
4122
 
                        print_ns_list(pc[3].nexti, print_func, fp, in_dump);
4123
 
                } else
4124
 
                        print_func(fp, "\n");
4125
3950
                break;
4126
3951
 
4127
3952
        case Op_lint:
4136
3961
                break;
4137
3962
 
4138
3963
        case Op_exec_count:
4139
 
                print_func(fp, "[exec_count = " EXEC_COUNT_FMT "]\n", pc->exec_count);
 
3964
                print_func(fp, "[exec_count = %ld]\n", pc->exec_count);
4140
3965
                break;
4141
3966
 
4142
3967
        case Op_store_var:
4153
3978
                print_func(fp, " [do_reference = %s]\n",
4154
3979
                                pc->do_reference ? "true" : "false");
4155
3980
                break;
4156
 
 
4157
 
        case Op_comment:
4158
 
                print_memory(pc->memory, func, print_func, fp);
4159
 
                print_func(fp, " [comment_type = %s]",
4160
 
                        pc->memory->comment_type == EOL_COMMENT ?
4161
 
                                                "EOL" : "BLOCK");
4162
 
                if (pc->comment) {
4163
 
                        print_func(fp, " [comment = " PTRFMT "]\n", pc->comment);
4164
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
4165
 
                } else
4166
 
                        print_func(fp, "\n");
4167
 
                break;
4168
 
 
 
3981
                                
4169
3982
        case Op_push_i:
4170
3983
        case Op_push:
4171
3984
        case Op_push_arg:
4172
 
        case Op_push_arg_untyped:
4173
3985
        case Op_push_param:
4174
3986
        case Op_push_array:
4175
3987
        case Op_push_re:
4202
4014
        else
4203
4015
                do_trace = false;
4204
4016
        return false;
4205
 
}
 
4017
4206
4018
 
4207
4019
/* print_code --- print a list of instructions */
4208
4020
 
4215
4027
        return 0;
4216
4028
}
4217
4029
 
4218
 
/* print_ns_list --- print the list of namespaces */
4219
 
 
4220
 
static void
4221
 
print_ns_list(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
4222
 
{
4223
 
        for (; pc != NULL; pc = pc->nexti) {
4224
 
                print_instruction(pc, print_func, fp, in_dump);
4225
 
                if (pc->comment != NULL)
4226
 
                        print_instruction(pc->comment, print_func, fp, in_dump);
4227
 
        }
4228
 
}
4229
 
 
4230
4030
/* do_dump_instructions --- dump command */
4231
4031
 
4232
4032
int
4238
4038
        if (arg != NULL && arg->type == D_string) {
4239
4039
                /* dump to a file */
4240
4040
                if ((fp = fopen(arg->a_string, "w")) == NULL) {
4241
 
                        d_error(_("could not open `%s' for writing: %s"),
 
4041
                        d_error(_("could not open `%s' for writing (%s)"),
4242
4042
                                        arg->a_string, strerror(errno));
4243
4043
                        return false;
4244
4044
                }
4281
4081
        int i;
4282
4082
 
4283
4083
        if ((fp = fopen(arg->a_string, "w")) == NULL) {
4284
 
                d_error(_("could not open `%s' for writing: %s"),
 
4084
                d_error(_("could not open `%s' for writing (%s)"),
4285
4085
                                arg->a_string, strerror(errno));
4286
4086
                return false;
4287
4087
        }
4298
4098
                         */
4299
4099
 
4300
4100
                        if (strlen(line) > 1
4301
 
                            && strncmp(line, "sa", 2) == 0)
 
4101
                            && strncmp(line, "sa", 2) == 0)     
4302
4102
                                continue;
4303
4103
 
4304
4104
                        fprintf(fp, "%s\n", line);
4314
4114
int
4315
4115
do_option(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
4316
4116
{
4317
 
        const struct dbg_option *opt;
 
4117
        const struct dbg_option *opt;   
4318
4118
        char *name, *value;
4319
 
 
 
4119
        
4320
4120
        if (arg == NULL) {      /* display all available options and corresponding values */
4321
4121
                for (opt = option_list; opt->name; opt++) {
4322
4122
                        if (opt->str_val != NULL)
4351
4151
 
4352
4152
#ifdef HAVE_LIBREADLINE
4353
4153
 
4354
 
/* initialize_pager --- initialize our idea of the terminal size */
 
4154
/* initialize_pager --- initialize our idea of the terminal size */ 
4355
4155
 
4356
4156
void
4357
4157
initialize_pager(FILE *fp)
4382
4182
 
4383
4183
        if (os_isatty(fileno(fp)) && input_fd == 0)
4384
4184
                quit_pager = prompt_yes_no(
4385
 
                        // TRANSLATORS: don't translate the 'q' inside the brackets.
4386
 
                        _("\t------[Enter] to continue or [q] + [Enter] to quit------"),
4387
 
                        'q', false, fp);
 
4185
                        _("\t------[Enter] to continue or q [Enter] to quit------"),
 
4186
                        _("q")[0], false, fp);
4388
4187
        if (quit_pager)
4389
4188
                longjmp(pager_quit_tag, 1);
4390
4189
        pager_lines_printed = 0;
4391
 
}
 
4190
}    
4392
4191
 
4393
 
/* gprintf --- like fprintf but allows paging */
 
4192
/* gprintf --- like fprintf but allows paging */ 
4394
4193
 
4395
4194
int
4396
4195
gprintf(FILE *fp, const char *format, ...)
4405
4204
#define GPRINTF_BUFSIZ 512
4406
4205
        if (buf == NULL) {
4407
4206
                buflen = GPRINTF_BUFSIZ;
4408
 
                emalloc(buf, char *, buflen * sizeof(char), "gprintf");
 
4207
                emalloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf");
4409
4208
        } else if (buflen - bl < GPRINTF_BUFSIZ/2) {
4410
4209
                buflen += GPRINTF_BUFSIZ;
4411
 
                erealloc(buf, char *, buflen * sizeof(char), "gprintf");
4412
 
        }
 
4210
                erealloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf");
 
4211
        }        
4413
4212
#undef GPRINTF_BUFSIZ
4414
 
 
 
4213
        
4415
4214
        while (true) {
4416
4215
                va_start(args, format);
4417
4216
                nchar = vsnprintf(buf + bl, buflen - bl, format, args);
4425
4224
                        break;
4426
4225
                }
4427
4226
 
4428
 
                /* enlarge buffer, and try again */
 
4227
                /* enlarge buffer, and try again */ 
4429
4228
                buflen *= 2;
4430
 
                erealloc(buf, char *, buflen * sizeof(char), "gprintf");
 
4229
                erealloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf");
4431
4230
        }
4432
4231
 
4433
4232
        bl = 0;
4434
4233
        for (p = buf; (q = strchr(p, '\n')) != NULL; p = q + 1) {
4435
 
                int sz = (int) (q - p);
 
4234
                int sz = (int) (q - p); 
4436
4235
 
4437
4236
                while (sz > 0) {
4438
4237
                        int cnt;
4452
4251
                                sz -= screen_width;
4453
4252
                                assert(sz > 0);
4454
4253
                                p += cnt;
4455
 
                        }
 
4254
                        }                       
4456
4255
                }
4457
4256
 
4458
4257
                fprintf(fp, "\n");
4467
4266
static int
4468
4267
serialize_subscript(char *buf, int buflen, struct list_item *item)
4469
4268
{
4470
 
        int bl, nchar, i;
 
4269
        int bl = 0, nchar, i;
4471
4270
        NODE *sub;
4472
4271
 
4473
4272
        nchar = snprintf(buf, buflen, "%d%c%d%c%s%c%d%c",
4477
4276
                return 0;
4478
4277
        else if (nchar >= buflen)       /* need larger buffer */
4479
4278
                return nchar;
4480
 
        bl = nchar;
 
4279
        bl += nchar;
4481
4280
        for (i = 0; i < item->num_subs; i++) {
4482
4281
                sub = item->subs[i];
4483
 
                nchar = snprintf(buf + bl, buflen - bl, "%lu%c%.*s%c",
4484
 
                                        (unsigned long) sub->stlen, FSEP,
4485
 
                                        (int) sub->stlen, sub->stptr, FSEP);
 
4282
                nchar = snprintf(buf + bl, buflen - bl, "%lu%c%s%c",
 
4283
                                        (unsigned long) sub->stlen, FSEP, sub->stptr, FSEP);
4486
4284
                if (nchar <= 0)
4487
4285
                        return 0;
4488
4286
                bl += nchar;
4493
4291
}
4494
4292
 
4495
4293
 
4496
 
/*
4497
 
 * serialize_list--- convert a list structure to a byte stream and
 
4294
 
 
4295
/* serialize --- convert a list structure to a byte stream and
4498
4296
 *               save in environment.
4499
4297
 */
4500
4298
 
4501
4299
static void
4502
 
serialize_list(int type)
 
4300
serialize(int type)
4503
4301
{
4504
4302
        static char *buf = NULL;
4505
4303
        static int buflen = 0;
4513
4311
        int cnum = 0;
4514
4312
        struct condition *cndn = NULL;
4515
4313
        void *ptr, *end_ptr;
4516
 
#if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
 
4314
#ifdef HAVE_LIBREADLINE
4517
4315
        HIST_ENTRY *h = NULL;
4518
4316
#endif
4519
4317
 
4557
4355
 
4558
4356
        if (buf == NULL) {      /* first time */
4559
4357
                buflen = SERIALIZE_BUFSIZ;
4560
 
                emalloc(buf, char *, buflen + 1, "serialize");
 
4358
                emalloc(buf, char *, buflen + 2, "serialize");
4561
4359
        }
4562
4360
        bl = 0;
4563
4361
 
4566
4364
                if (buflen - bl < SERIALIZE_BUFSIZ/2) {
4567
4365
enlarge_buffer:
4568
4366
                        buflen *= 2;
4569
 
                        erealloc(buf, char *, buflen + 1, "serialize");
 
4367
                        erealloc(buf, char *, buflen + 2, "serialize");
4570
4368
                }
4571
4369
 
4572
4370
#undef SERIALIZE_BUFSIZ
4609
4407
                        else
4610
4408
                                nchar = snprintf(buf + bl, buflen - bl, "%d%c%d%c%s%c",
4611
4409
                                            wd->number, FSEP, D_variable, FSEP, wd->sname, FSEP);
4612
 
                        cnum = wd->number;
 
4410
                        cnum = wd->number;      
4613
4411
                        commands = &wd->commands;
4614
4412
                        cndn = &wd->cndn;
4615
4413
                        break;
4649
4447
                case WATCH:
4650
4448
                        /* recreate the `commands' command strings including the `commands'
4651
4449
                         * and `end' commands; command seperator is '\034'.
4652
 
                         * re-parsed in unserialize_list to recover the commands list.
 
4450
                         * re-parsed in unserialize to recover the commands list.
4653
4451
                         * Alternatively, one could encode(serialize) each command and it's arguments.
4654
4452
                         */
4655
4453
 
4667
4465
                        }
4668
4466
 
4669
4467
                        if (nchar > 0) {        /* non-empty commands list */
4670
 
                                nchar += (strlen("commands ") + 20 /*cnum*/ + 1 /*CSEP*/ + strlen("end") + 1 /*FSEP*/);
4671
 
                                if (nchar >= buflen - bl) {
4672
 
                                        buflen = bl + nchar + 1 /*RSEP*/;
4673
 
                                        erealloc(buf, char *, buflen + 1, "serialize_list");
 
4468
                                nchar += (strlen("commands ") + 20 + strlen("end") + 2); /* 20 for cnum (an int) */
 
4469
                                if (nchar > buflen - bl) {
 
4470
                                        buflen = bl + nchar;
 
4471
                                        erealloc(buf, char *, buflen + 3, "serialize");
4674
4472
                                }
4675
4473
                                nchar = sprintf(buf + bl, "commands %d", cnum);
4676
4474
                                bl += nchar;
4696
4494
                                nchar = strlen("end");  /* end of 'commands' */
4697
4495
                                memcpy(buf + bl, "end", nchar);
4698
4496
                                bl += nchar;
4699
 
                                buf[bl++] = FSEP;               /* field */
4700
4497
                        }
 
4498
                        buf[bl++] = FSEP;               /* field */
4701
4499
                        buf[bl++] = RSEP;               /* record */
4702
4500
                        buf[bl] = '\0';
4703
 
 
4704
 
                        /* condition expression */
 
4501
        
 
4502
                        /* condition expression */      
4705
4503
                        if (cndn->expr) {
4706
4504
                                bl--;   /* undo RSEP from above */
4707
4505
                                nchar = strlen(cndn->expr);
4708
 
                                if (nchar + 1 /*FSEP*/ >= buflen - bl) {
4709
 
                                        buflen = bl + nchar + 1 /*FSEP*/ + 1 /*RSEP*/;
4710
 
                                        erealloc(buf, char *, buflen + 1, "serialize_list");
 
4506
                                if (nchar > buflen - bl) {
 
4507
                                        buflen = bl + nchar;
 
4508
                                        erealloc(buf, char *, buflen + 3, "serialize");
4711
4509
                                }
4712
4510
                                memcpy(buf + bl, cndn->expr, nchar);
4713
4511
                                bl += nchar;
4729
4527
                        break;
4730
4528
                default:
4731
4529
                        break;
4732
 
                }
 
4530
                }  
4733
4531
        }
4734
4532
 
4735
4533
        if (bl > 0)     /* non-empty list */
4752
4550
 
4753
4551
 
4754
4552
/* unserialize_list_item --- create a list_item structure from unserialized data */
4755
 
 
 
4553
 
4756
4554
static struct list_item *
4757
4555
unserialize_list_item(struct list_item *list, char **pstr, int *pstr_len, int field_cnt)
4758
4556
{
4802
4600
                l->subs = subs;
4803
4601
        }
4804
4602
        l->number = num;        /* keep same item number across executions */
4805
 
 
 
4603
        
4806
4604
        if (list == &watch_list) {
4807
4605
                initialize_watch_item(l);
4808
4606
                /* unserialize watchpoint `commands' */
4819
4617
        } else
4820
4618
                list->number = num;
4821
4619
 
4822
 
        return l;
 
4620
        return l;       
4823
4621
}
4824
4622
 
4825
4623
/* unserialize_breakpoint --- create a breakpoint structure from unserialized data */
4826
 
 
 
4624
 
4827
4625
static BREAKPOINT *
4828
4626
unserialize_breakpoint(char **pstr, int *pstr_len, int field_cnt)
4829
4627
{
4858
4656
        if (field_cnt > 6)      /* unserialize breakpoint `commands' */
4859
4657
                unserialize_commands(pstr[6], pstr_len[6]);
4860
4658
 
4861
 
        if (field_cnt > 7) {    /* condition expression */
 
4659
        if (field_cnt > 7) {    /* condition expression */ 
4862
4660
                char *expr;
4863
4661
                expr = estrdup(pstr[7], pstr_len[7]);
4864
4662
                if (parse_condition(D_break, b->number, expr) != 0)
4890
4688
        return NULL;
4891
4689
}
4892
4690
 
4893
 
/* unserialize_list -- reconstruct list from serialized data stored in
 
4691
/* unserialize -- reconstruct list from serialized data stored in
4894
4692
 *                environment variable.
4895
4693
 */
4896
4694
 
4897
4695
static void
4898
 
unserialize_list(int type)
 
4696
unserialize(int type)
4899
4697
{
4900
4698
        char *val;
4901
4699
        char *p, *q, *r, *s;
4924
4722
                        field_cnt++;
4925
4723
                        if (field_cnt == MAX_FIELD)
4926
4724
#ifdef GAWKDEBUG
4927
 
                                fatal("Increase MAX_FIELD and recompile");
 
4725
                                fatal("Increase MAX_FIELD and recompile.\n");
4928
4726
#else
4929
 
                                return;
 
4727
                                return; 
4930
4728
#endif
4931
4729
                }
4932
4730
 
5016
4814
 
5017
4815
        /* N.B: breakpoints and watchpoints get numbers from a single
5018
4816
         * counter/sequencer watch_list.number.
5019
 
         */
 
4817
         */ 
5020
4818
 
5021
4819
        for (b = breakpoints.next; b != &breakpoints; b = b->next) {
5022
4820
                if (b->number == *pnum)
5051
4849
        static struct list_item *w;
5052
4850
        static struct commands_item *commands;
5053
4851
        struct commands_item *c;
5054
 
 
 
4852
        
5055
4853
        if (cmd == D_commands) {
5056
 
                int num = -1, type;
 
4854
                int num, type;
5057
4855
                if (arg == NULL)
5058
4856
                        type = has_break_or_watch_point(&num, true);
5059
4857
                else {
5099
4897
        c->next = NULL;
5100
4898
        c->cmd = cmd;
5101
4899
 
5102
 
        /* N.B.: first arg is the command string, see command.y */
 
4900
        /* N.B.: first arg is the command string, see command.y */ 
5103
4901
        c->cmd_string = arg->a_string;
5104
4902
        c->arg = arg->next; /* actual arguments to the command */
5105
4903
        efree(arg);
5160
4958
                        r = find_symbol(name, NULL);
5161
4959
                        if (r == NULL)
5162
4960
                                goto done;
5163
 
                        if (r->type == Node_var_new || r->type == Node_elem_new)
 
4961
                        if (r->type == Node_var_new)
5164
4962
                                tmp[i] = Nnull_string;
5165
4963
                        else if (r->type != Node_var) {
5166
4964
                                d_error(_("`%s' is not a scalar variable"), name);
5193
4991
                                        if (value == NULL)
5194
4992
                                                tmp[i] = Nnull_string;          /* FIXME: goto done ? */
5195
4993
                                        else if (value->type == Node_var_array) {
5196
 
                                                d_error(_("attempt to use array `%s[\"%.*s\"]' in a scalar context"),
5197
 
                                                                        name, (int) subs->stlen, subs->stptr);
 
4994
                                                d_error(_("attempt to use array `%s[\"%s\"]' in a scalar context"),
 
4995
                                                                        name, subs->stptr);
5198
4996
                                                goto done;
5199
 
                                        } else
 
4997
                                        } else 
5200
4998
                                                tmp[i] = value;
5201
4999
                                } else {
5202
5000
                                        if (value == NULL) {
5203
 
                                                d_error(_("[\"%.*s\"] not in array `%s'"),
5204
 
                                                                        (int) subs->stlen, subs->stptr, name);
 
5001
                                                d_error(_("[\"%s\"] not in array `%s'"),
 
5002
                                                                        subs->stptr, name);
5205
5003
                                                goto done;
5206
5004
                                        } else if (value->type != Node_var_array) {
5207
 
                                                d_error(_("attempt to use scalar `%s[\"%.*s\"]' as array"),
5208
 
                                                                        name, (int) subs->stlen, subs->stptr);
 
5005
                                                d_error(_("attempt to use scalar `%s[\"%s\"]' as array"),
 
5006
                                                                        name, subs->stptr);
5209
5007
                                                goto done;
5210
5008
                                        } else {
5211
5009
                                                r = value;
5214
5012
                                }
5215
5013
                        }
5216
5014
                }
5217
 
                        break;
 
5015
                        break;                   
5218
5016
                case D_node:
5219
5017
                        tmp[i] = a->a_node;
5220
5018
                        break;
5227
5025
 
5228
5026
        PUSH_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
5229
5027
        if (setjmp(fatal_tag) == 0)
5230
 
                r = format_args(tmp[0]->stptr, tmp[0]->stlen, tmp, i);
 
5028
                r = format_tree(tmp[0]->stptr, tmp[0]->stlen, tmp, i);
5231
5029
        else {
5232
5030
                /* fatal error, restore exit_val of program */
5233
5031
                exit_val = EXIT_SUCCESS;
5254
5052
 
5255
5053
        fd = open_readfd(file);
5256
5054
        if (fd <= INVALID_HANDLE) {
5257
 
                d_error(_("cannot open source file `%s' for reading: %s"),
 
5055
                d_error(_("can't open source file `%s' for reading (%s)"),
5258
5056
                                        file, strerror(errno));
5259
5057
                return false;
5260
5058
        }
5270
5068
open_readfd(const char *file)
5271
5069
{
5272
5070
        int fd;
5273
 
 
 
5071
        
5274
5072
        fd = open(file, O_RDONLY);
5275
5073
        if (fd <= INVALID_HANDLE)
5276
5074
                return INVALID_HANDLE;
5302
5100
void
5303
5101
option_help()
5304
5102
{
5305
 
        const struct dbg_option *opt;
 
5103
        const struct dbg_option *opt;   
5306
5104
 
5307
5105
        for (opt = option_list; opt->name; opt++)
5308
5106
                fprintf(out_fp, "\t%-15.15s - %s\n", opt->name, _(opt->help_txt));
5309
5107
}
5310
5108
 
5311
5109
#ifdef HAVE_LIBREADLINE
5312
 
 
 
5110
        
5313
5111
/* option_generator --- generator function for option name completion */
5314
5112
 
5315
5113
char *
5344
5142
        if (output_fp != stdout) {
5345
5143
                if (output_fp != stderr) {
5346
5144
                        fclose(output_fp);
5347
 
                        efree((void*) output_file);
 
5145
                        efree(output_file);
5348
5146
                }
5349
5147
                output_fp = stdout;
5350
5148
                output_is_tty = os_isatty(fileno(stdout));
5371
5169
                        output_is_tty = os_isatty(fileno(stderr));
5372
5170
                        return;
5373
5171
                }
5374
 
 
 
5172
                
5375
5173
                if (strncmp(cp, "fd/", 3) == 0) {
5376
5174
                        cp += 3;
5377
5175
                        fd = (int) strtoul(cp, NULL, 10);
5389
5187
                if (fd > INVALID_HANDLE && fp == NULL) {
5390
5188
                        fp = fdopen(fd, "w");
5391
5189
                        if (fp == NULL)
5392
 
                                close(fd);
 
5190
                                close(fd); 
5393
5191
                }
5394
5192
 
5395
5193
        } else {
5403
5201
                setbuf(fp, (char *) NULL);
5404
5202
                output_is_tty = os_isatty(fileno(fp));
5405
5203
        } else {
5406
 
                d_error(_("could not open `%s' for writing: %s"),
 
5204
                d_error(_("could not open `%s' for writing (%s)"),
5407
5205
                                        file,
5408
5206
                                        errno != 0 ? strerror(errno) : _("reason unknown"));
5409
5207
                fprintf(out_fp, _("sending output to stdout\n"));
5415
5213
static void
5416
5214
set_prompt(const char *value)
5417
5215
{
5418
 
        efree((void *) dgawk_prompt);
 
5216
        efree(dgawk_prompt);
5419
5217
        dgawk_prompt = estrdup(value, strlen(value));
5420
5218
        dbg_prompt = dgawk_prompt;
5421
5219
}
5422
5220
 
5423
 
/* set_option_flag --- convert option string to flag value */
 
5221
/* set_option_flag --- convert option string to flag value */ 
5424
5222
 
5425
5223
static int
5426
5224
set_option_flag(const char *value)
5504
5302
                return NULL;
5505
5303
 
5506
5304
        p = (char *) commands_string;
5507
 
        end = (char *) commands_string + commands_string_len;
 
5305
        end = (char *) commands_string + commands_string_len; 
5508
5306
        for (; p < end; p++) {
5509
5307
                if (*p == line_sep) {
5510
5308
                        line = estrdup(commands_string, p - commands_string);
5526
5324
save_options(const char *file)
5527
5325
{
5528
5326
        FILE *fp;
5529
 
        const struct dbg_option *opt;
 
5327
        const struct dbg_option *opt;   
5530
5328
 
5531
5329
        fp = fopen(file, "w");
5532
5330
        if (fp == NULL)
5547
5345
static void
5548
5346
close_all()
5549
5347
{
5550
 
        bool stdio_problem, got_EPIPE;
 
5348
        bool stdio_problem;
5551
5349
        struct command_source *cs;
5552
5350
 
5553
5351
        (void) nextfile(& curfile, true);       /* close input data file */
5554
 
        (void) close_io(& stdio_problem, & got_EPIPE);
 
5352
        (void) close_io(& stdio_problem);
5555
5353
        if (cur_srcfile->fd != INVALID_HANDLE) {
5556
5354
                close(cur_srcfile->fd);
5557
5355
                cur_srcfile->fd = INVALID_HANDLE;
5565
5363
 
5566
5364
        close_extensions();
5567
5365
 
5568
 
        set_gawk_output(NULL);  /* closes output_fp if not stdout */
 
5366
        set_gawk_output(NULL);  /* closes output_fp if not stdout */ 
5569
5367
}
5570
5368
 
5571
5369
/* pre_execute_code --- pre_hook for execute_code, called by pre_execute */
5585
5383
                                op2str(ei->opcode));
5586
5384
                *pi = ei->nexti;
5587
5385
                break;
5588
 
        case Op_K_return_from_eval:
 
5386
        case Op_K_return:
5589
5387
                if (ei->nexti != NULL) {        /* not an implicit return */
5590
5388
                        NODE *r;
5591
5389
                        d_error(_("`return' not allowed in current context;"
5609
5407
{
5610
5408
        volatile NODE *r = NULL;
5611
5409
        volatile jmp_buf fatal_tag_stack;
5612
 
        // long save_stack_size;        // see comment below
 
5410
        long save_stack_size;
5613
5411
        int save_flags = do_flags;
5614
5412
 
5615
5413
        /* We use one global stack for all contexts.
5616
5414
         * Save # of items in stack; in case of
5617
5415
         * a fatal error, pop stack until it has that many items.
5618
 
         */
 
5416
         */ 
5619
5417
 
5620
 
        // save_stack_size = (stack_ptr  - stack_bottom) + 1;   // see comment below
 
5418
        save_stack_size = (stack_ptr  - stack_bottom) + 1;
5621
5419
        do_flags = false;
5622
5420
 
5623
5421
        PUSH_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
5624
5422
        if (setjmp(fatal_tag) == 0) {
5625
5423
                (void) interpret((INSTRUCTION *) code);
5626
5424
                r = POP_SCALAR();
5627
 
        } else {        /* fatal error */
5628
 
                /*
5629
 
                 * 9/2022:
5630
 
                 * Initially, the code did this:
5631
 
                 *
5632
 
                 * (void) unwind_stack(save_stack_size);
5633
 
                 *
5634
 
                 * to attempt to recover and keep going. But a fatal error
5635
 
                 * can corrupt memory. Instead of trying to recover, just
5636
 
                 * start over.
5637
 
                 */
5638
 
                // Let the user know, but DON'T use the fatal() function!
5639
 
                fprintf(stderr, _("fatal error during eval, need to restart.\n"));
5640
 
                // Go back to debugger
5641
 
                restart(false);         // does not return
5642
 
        }
 
5425
        } else  /* fatal error */
 
5426
                (void) unwind_stack(save_stack_size);
5643
5427
 
5644
5428
        POP_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
5645
5429
        do_flags = save_flags;
5664
5448
        int ecount = 0, pcount = 0;
5665
5449
        int ret;
5666
5450
        int save_flags = do_flags;
5667
 
        SRCFILE *the_source;
5668
 
 
 
5451
        
5669
5452
        if (prog_running) {
5670
5453
                this_frame = find_frame(0);
5671
5454
                this_func = this_frame->func_node;
5672
5455
        }
5673
5456
 
5674
 
        install_params(this_func);      /* expose current function parameters to eval */
 
5457
        install_params(this_func);      /* expose current function parameters to eval */ 
5675
5458
        ctxt = new_context();
5676
5459
        ctxt->install_func = append_symbol;     /* keep track of newly installed globals */
5677
5460
        push_context(ctxt);
5678
 
        the_source = add_srcfile(SRC_CMDLINE, arg->a_string, srcfiles, NULL, NULL);
5679
 
        do_flags &= DO_MPFR;    // preserve this flag only
5680
 
        ret = parse_program(&code, true);
 
5461
        (void) add_srcfile(SRC_CMDLINE, arg->a_string, srcfiles, NULL, NULL);
 
5462
        do_flags = false;
 
5463
        ret = parse_program(&code);
5681
5464
        do_flags = save_flags;
5682
5465
        remove_params(this_func);
5683
5466
        if (ret != 0) {
5684
5467
                pop_context();  /* switch to prev context */
5685
5468
                free_context(ctxt, false /* keep_globals */);
5686
 
 
5687
 
                /* Remove @eval from FUNCTAB. */
5688
 
                NODE *s = make_string("@eval", 5);
5689
 
                (void) assoc_remove(func_table, s);
5690
 
                unref(s);
5691
 
 
5692
5469
                return false;
5693
5470
        }
5694
5471
 
5702
5479
                eval->func_name = NULL; /* not needed, func_body already assigned */
5703
5480
                (eval + 1)->expr_count = 0;
5704
5481
                eval->nexti = bcalloc(Op_stop, 1, 0);
5705
 
 
 
5482
                
5706
5483
        } else {
5707
 
                /* execute as a part of the current function */
 
5484
                /* execute as a part of the current function */ 
5708
5485
                int i;
5709
5486
                INSTRUCTION *t;
5710
5487
 
5717
5494
                /* add or append eval locals to the current frame stack */
5718
5495
                ecount = f->param_cnt;  /* eval local count */
5719
5496
                pcount = this_func->param_cnt;
5720
 
 
 
5497
                
5721
5498
                if (ecount > 0) {
5722
5499
                        if (pcount == 0)
5723
5500
                                emalloc(this_frame->stack, NODE **, ecount * sizeof(NODE *), "do_eval");
5757
5534
        /* else
5758
5535
                fatal error */
5759
5536
 
5760
 
        if (this_func != NULL && ecount > 0) {
 
5537
        if (this_func != NULL && ecount > 0) { 
5761
5538
                int i;
5762
5539
 
5763
5540
                /* undo frame manipulation from above */
5782
5559
                this_func->param_cnt -= ecount;
5783
5560
        }
5784
5561
 
5785
 
        /*
5786
 
         * Always destroy symbol "@eval", however destroy all newly installed
 
5562
        /* always destroy symbol "@eval", however destroy all newly installed
5787
5563
         * globals only if fatal error (execute_code() returing NULL).
5788
5564
         */
5789
5565
 
5790
5566
        pop_context();  /* switch to prev context */
5791
5567
        free_context(ctxt, (ret_val != NULL));   /* free all instructions and optionally symbols */
5792
 
 
5793
 
        if (ret_val != NULL) {
5794
 
                /*
5795
 
                 * Remove @eval from FUNCTAB, so that above code
5796
 
                 * will work the next time around.
5797
 
                 */
5798
 
                NODE *s = make_string("@eval", 5);
5799
 
 
5800
 
                (void) assoc_remove(func_table, s);
5801
 
                unref(s);
5802
 
        }
5803
 
 
5804
 
        free(f->vname);
5805
 
        freenode(f);
5806
 
 
5807
 
        free_srcfile(the_source);
5808
 
 
 
5568
        if (ret_val != NULL)
 
5569
                destroy_symbol(f);      /* destroy "@eval" */
5809
5570
        return false;
5810
5571
}
5811
5572
 
5815
5576
immediately for syntactic correctness, and to determine whether symbols
5816
5577
in it have referents in the context of your breakpoint. If expression
5817
5578
uses symbols not referenced in the context of the breakpoint, GDB prints
5818
 
an error message:
 
5579
an error message:       
5819
5580
 
5820
5581
    No symbol "foo" in current context.
5821
5582
*/
5826
5587
check_symbol(NODE *r)
5827
5588
{
5828
5589
        invalid_symbol++;
5829
 
        d_error(_("no symbol `%s' in current context"), r->vname);
 
5590
        d_error(_("No symbol `%s' in current context"), r->vname);
5830
5591
        /* install anyway, but keep track of it */
5831
5592
        append_symbol(r);
5832
5593
}
5851
5612
                cndn = &b->cndn;
5852
5613
                rp = find_rule(b->src, b->bpi->source_line);
5853
5614
                if (rp != NULL && rp->opcode == Op_func)
5854
 
                        this_func = rp->func_body;
 
5615
                        this_func = rp->func_body; 
5855
5616
        } else if (type == D_watch && (w = find_item(&watch_list, num)) != NULL) {
5856
5617
                cndn = &w->cndn;
5857
5618
                this_func = find_frame(cur_frame)->func_node;
5869
5630
        push_context(ctxt);
5870
5631
        (void) add_srcfile(SRC_CMDLINE, expr, srcfiles, NULL, NULL);
5871
5632
        do_flags = false;
5872
 
        ret = parse_program(&code, true);
 
5633
        ret = parse_program(&code);
5873
5634
        do_flags = save_flags;
5874
 
        remove_params(this_func);
 
5635
        remove_params(this_func); 
5875
5636
        pop_context();
5876
5637
 
5877
5638
        if (ret != 0 || invalid_symbol) {
5880
5641
        }
5881
5642
 
5882
5643
        /* condition expression is parsed as awk pattern without
5883
 
         * any action. The code is then modified to end up with
 
5644
         * any action. The code is then modified to end up with 
5884
5645
         * a `1.0' on stack when the expression is true, `0.0' otherwise.
5885
5646
         */
5886
5647
 
5895
5656
        it->nexti = bcalloc(Op_jmp, 1, 0);
5896
5657
        it->nexti->target_jmp = stop;
5897
5658
        it->nexti->nexti = rule->lasti;
5898
 
 
 
5659
 
5899
5660
        it = rule->lasti;               /* Op_no_op, target for Op_jmp_false */
5900
5661
        assert(it->opcode == Op_no_op);
5901
5662
        it->opcode = Op_push_i;
5973
5734
 
5974
5735
        /* eof_status = EXIT_FATAL     - exit with status EXIT_FATAL on EOF or error.
5975
5736
         *            = EXIT_FAILURE   - exit status EXIT_FAILURE on error.
5976
 
         *            = EXIT_SUCCESS   - don't exit on EOF or error.
 
5737
         *            = EXIT_SUCCESS   - don't exit on EOF or error. 
5977
5738
         */
5978
5739
        cs->eof_status = eofstatus;
5979
5740
        cs->str = NULL;
5980
5741
        cs->next = cmd_src;
5981
5742
        cmd_src = cs;
5982
 
 
 
5743
        
5983
5744
        input_fd = fd;
5984
5745
        input_from_tty = istty;
5985
5746
        read_a_line = readfunc;