aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--awk.h12
-rw-r--r--awkgram.c2
-rw-r--r--awkgram.y2
-rw-r--r--cmd.h1
-rw-r--r--command.c2
-rw-r--r--command.y2
-rw-r--r--debug.c55
-rw-r--r--eval.c211
9 files changed, 179 insertions, 127 deletions
diff --git a/ChangeLog b/ChangeLog
index 5fdb73c7..a99d139c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+Sun Nov 21 14:23:58 2010 John Haque <j.eh@mchsi.com>
+
+ Debugger: Fix memory leak when quitting pager.
+ * awk.h (PUSH_BINDING, POP_BINDING): Generalize macro definitions.
+ * debug.c (print_array): save and restore bindings for pager.
+ free list in case of an early exit in the pager.
+ (do_dump_instructions): Don't sort functions to avoid potential
+ memory leak.
+ (execute_code): Adjust PUSH_BINDING and POP_BINDING macro invocations.
+
+ * awkgram.y (func_call): Avoid reading freed memory for indirect var
+ name; do the special variable check before the call to 'variable'.
+
+ * eval.c (r_interpret): Fixes and cleanups. Change TOP to TOP_SCALAR
+ in the case Op_store_field.
+ (assign_common, assign, compare): Nuked macros.
+ (cmp_scalar, op_assign): New functions as replacements for the macros.
+
+
Fri Nov 19 11:57:28 2010 Arnold D. Robbins <arnold@skeeve.com>
* bootstrap.sh, Makefile.am: Remove treatment of CVS.
diff --git a/awk.h b/awk.h
index 74cba872..3e187807 100644
--- a/awk.h
+++ b/awk.h
@@ -1081,12 +1081,12 @@ extern STACK_ITEM *stack_top;
extern jmp_buf fatal_tag;
extern int fatal_tag_valid;
-#define PUSH_BINDING(stack) \
-if (fatal_tag_valid++) \
- memcpy((char *) (stack), (const char *) fatal_tag, sizeof(jmp_buf))
-#define POP_BINDING(stack) \
-if (--fatal_tag_valid) \
- memcpy((char *) fatal_tag, (const char *) (stack), sizeof(jmp_buf))
+#define PUSH_BINDING(stack, tag, val) \
+if (val++) \
+ memcpy((char *) (stack), (const char *) tag, sizeof(jmp_buf))
+#define POP_BINDING(stack, tag, val) \
+if (--val) \
+ memcpy((char *) tag, (const char *) (stack), sizeof(jmp_buf))
/* ------------- Function prototypes or defs (as appropriate) ------------- */
typedef int (*Func_print)(FILE *, const char *, ...);
diff --git a/awkgram.c b/awkgram.c
index 607247ce..df43a94f 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -3955,9 +3955,9 @@ yyreduce:
f = (yyvsp[(2) - (2)])->lasti;
f->opcode = Op_indirect_func_call;
name = estrdup(f->func_name, strlen(f->func_name));
- indirect_var = variable(name, Node_var_new);
if (is_std_var(name))
yyerror(_("can not use special variable `%s' for indirect function call"), name);
+ indirect_var = variable(name, Node_var_new);
t = instruction(Op_push);
t->memory = indirect_var;
diff --git a/awkgram.y b/awkgram.y
index 1247cfd9..322088b7 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -1600,9 +1600,9 @@ func_call
f = $2->lasti;
f->opcode = Op_indirect_func_call;
name = estrdup(f->func_name, strlen(f->func_name));
- indirect_var = variable(name, Node_var_new);
if (is_std_var(name))
yyerror(_("can not use special variable `%s' for indirect function call"), name);
+ indirect_var = variable(name, Node_var_new);
t = instruction(Op_push);
t->memory = indirect_var;
diff --git a/cmd.h b/cmd.h
index d40d3e32..f086b975 100644
--- a/cmd.h
+++ b/cmd.h
@@ -37,6 +37,7 @@ extern char **get_parmlist(void);
extern int gprintf(FILE *fp, const char *format, ...);
extern jmp_buf pager_quit_tag;
+extern int pager_quit_tag_valid;
extern int output_is_tty;
extern int input_fd;
diff --git a/command.c b/command.c
index 2f4608e2..070b9809 100644
--- a/command.c
+++ b/command.c
@@ -2322,7 +2322,7 @@ yyreduce:
for (a = (yyvsp[(2) - (3)]); a != NULL; a = a->next)
count++;
- subs =concat_args((yyvsp[(2) - (3)]), count);
+ subs = concat_args((yyvsp[(2) - (3)]), count);
free_cmdarg((yyvsp[(2) - (3)])->next);
(yyvsp[(2) - (3)])->next = NULL;
(yyvsp[(2) - (3)])->type = D_node;
diff --git a/command.y b/command.y
index 6d203b9a..b5bbf031 100644
--- a/command.y
+++ b/command.y
@@ -632,7 +632,7 @@ subscript
for (a = $2; a != NULL; a = a->next)
count++;
- subs =concat_args($2, count);
+ subs = concat_args($2, count);
free_cmdarg($2->next);
$2->next = NULL;
$2->type = D_node;
diff --git a/debug.c b/debug.c
index 4b70f2e2..fad42b80 100644
--- a/debug.c
+++ b/debug.c
@@ -262,6 +262,7 @@ static void save_options(const char *file);
/* pager */
jmp_buf pager_quit_tag;
+int pager_quit_tag_valid;
static int screen_width = INT_MAX; /* no of columns */
static int screen_height = INT_MAX; /* no of rows */
static int pager_lines_printed = 0; /* no of lines printed so far */
@@ -1055,7 +1056,7 @@ extern int comp_func(const void *p1, const void *p2);
/* print_array --- print the contents of an array */
-static void
+static int
print_array(NODE *arr, char *arr_name, Func_print print_func)
{
NODE *bucket;
@@ -1065,7 +1066,7 @@ print_array(NODE *arr, char *arr_name, Func_print print_func)
if (arr->var_array == NULL || arr->table_size == 0) {
print_func(out_fp, _("array `%s' is empty\n"), arr_name);
- return;
+ return 0;
}
/* sort indices */
@@ -1088,13 +1089,27 @@ print_array(NODE *arr, char *arr_name, Func_print print_func)
bucket = list[i];
if (bucket->ahvalue->type == Node_var_array) {
arr = bucket->ahvalue;
- print_array(arr, arr->vname, print_func);
+ if (pager_quit_tag_valid) { /* we are using pager */
+ volatile jmp_buf pager_quit_tag_stack;
+ volatile int ret = 1;
+
+ PUSH_BINDING(pager_quit_tag_stack, pager_quit_tag, pager_quit_tag_valid);
+ if (setjmp(pager_quit_tag) == 0)
+ ret = print_array(arr, arr->vname, print_func);
+ POP_BINDING(pager_quit_tag_stack, pager_quit_tag, pager_quit_tag_valid);
+ if (ret == 1) {
+ efree(list);
+ return 1;
+ }
+ } else
+ (void) print_array(arr, arr->vname, print_func);
} else {
print_func(out_fp, "%s[\"%s\"] = ", arr_name, bucket->ahname_str);
valinfo(bucket->ahvalue, print_func, out_fp);
}
}
efree(list);
+ return 0;
}
/* print_subscript --- print an array element */
@@ -1173,8 +1188,10 @@ do_print_var(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
}
if (count == 0) {
initialize_pager(out_fp);
+ pager_quit_tag_valid = TRUE;
if (setjmp(pager_quit_tag) == 0)
print_array(r, name, gprintf);
+ pager_quit_tag_valid = FALSE;
}
}
break;
@@ -1624,17 +1641,17 @@ static int
cmp_val(struct list_item *w, NODE *old, NODE *new)
{
/*
- * case old new result
+ * case old new result
* ------------------------------
- * 1: NULL ARRAY TRUE
- * 2: NULL SCALAR TRUE
- * 3: NULL NULL FALSE
- * 4: SCALAR SCALAR cmp_node
- * 5: SCALAR ARRAY TRUE
- * 6: SCALAR NULL TRUE
- * 7: ARRAY SCALAR TRUE
- * 8: ARRAY ARRAY compare size
- * 9: ARRAY NULL TRUE
+ * 1: NULL ARRAY TRUE
+ * 2: NULL SCALAR TRUE
+ * 3: NULL NULL FALSE
+ * 4: SCALAR SCALAR cmp_node
+ * 5: SCALAR ARRAY TRUE
+ * 6: SCALAR NULL TRUE
+ * 7: ARRAY SCALAR TRUE
+ * 8: ARRAY ARRAY compare size
+ * 9: ARRAY NULL TRUE
*/
if (WATCHING_ARRAY(w)) {
@@ -3522,8 +3539,6 @@ post_execute(INSTRUCTION *pc, int inloop)
&& stop.print_ret
) {
NODE *r;
-
- assert(stack_empty() == FALSE);
/* print the returned value before it disappears. */
r = TOP();
fprintf(out_fp, "Returned value = ");
@@ -3986,7 +4001,7 @@ do_dump_instructions(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
pf_data.defn = TRUE; /* in_dump = TRUE */
(void) print_code(code_block, &pf_data);
(void) foreach_func((int (*)(INSTRUCTION *, void *)) print_code,
- TRUE, /* sort */
+ FALSE, /* sort */
&pf_data /* data */
);
fclose(fp);
@@ -4000,7 +4015,7 @@ do_dump_instructions(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
pf_data.defn = TRUE; /* in_dump = TRUE */
(void) print_code(code_block, &pf_data);
(void) foreach_func((int (*)(INSTRUCTION *, void *)) print_code,
- TRUE, /* sort */
+ FALSE, /* sort */
&pf_data /* data */
);
}
@@ -4497,7 +4512,7 @@ unserialize_list_item(struct list_item *list, char **pstr, int *pstr_len, int fi
int num, type, i;
struct list_item *l;
NODE *symbol = NULL;
- int sub_cnt, cnt;
+ int sub_cnt = 0, cnt;
NODE **subs = NULL;
/* subscript -- number type sname num_subs subs [commands [condition]]
@@ -5376,7 +5391,7 @@ execute_code(volatile INSTRUCTION *code)
*/
ctxt_stack_bottom = stack_ptr + 1;
- PUSH_BINDING(fatal_tag_stack);
+ PUSH_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
if (setjmp(fatal_tag) == 0) {
(void) r_interpret((INSTRUCTION *) code);
assert(stack_ptr == ctxt_stack_bottom);
@@ -5384,7 +5399,7 @@ execute_code(volatile INSTRUCTION *code)
} else /* fatal error */
unwind_stack(ctxt_stack_bottom);
- POP_BINDING(fatal_tag_stack);
+ POP_BINDING(fatal_tag_stack, fatal_tag, fatal_tag_valid);
if (exit_val != EXIT_SUCCESS) { /* must be EXIT_FATAL? */
exit_val = EXIT_SUCCESS;
diff --git a/eval.c b/eval.c
index 5279f245..6c5aaeda 100644
--- a/eval.c
+++ b/eval.c
@@ -1390,6 +1390,96 @@ eval_condition(NODE *t)
return (t->stlen != 0);
}
+/* cmp_scalar -- compare two nodes on the stack */
+
+static inline int
+cmp_scalar()
+{
+ NODE *t1, *t2;
+ int di;
+
+ t2 = POP_SCALAR();
+ t1 = TOP();
+ if (t1->type == Node_var_array) {
+ DEREF(t2);
+ fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t1));
+ }
+ di = cmp_nodes(t1, t2);
+ DEREF(t1);
+ DEREF(t2);
+ return di;
+}
+
+/* op_assign --- assignment operators excluding = */
+
+static void
+op_assign(OPCODE op)
+{
+ NODE **lhs;
+ NODE *r;
+ AWKNUM x, x1, x2;
+#ifdef _CRAY
+ long lx;
+#endif
+
+ lhs = POP_ADDRESS();
+ x1 = force_number(*lhs);
+ TOP_NUMBER(x2);
+ unref(*lhs);
+ switch (op) {
+ case Op_assign_plus:
+ r = *lhs = make_number(x1 + x2);
+ break;
+ case Op_assign_minus:
+ r = *lhs = make_number(x1 - x2);
+ break;
+ case Op_assign_times:
+ r = *lhs = make_number(x1 * x2);
+ break;
+ case Op_assign_quotient:
+ if (x2 == (AWKNUM) 0) {
+ decr_sp();
+ fatal(_("division by zero attempted in `/='"));
+ }
+#ifdef _CRAY
+ /* special case for integer division, put in for Cray */
+ lx = x2;
+ if (lx == 0) {
+ r = *lhs = make_number(x1 / x2);
+ break;
+ }
+ lx = (long) x1 / lx;
+ if (lx * x1 == x2)
+ r = *lhs = make_number((AWKNUM) lx);
+ else
+#endif /* _CRAY */
+ r = *lhs = make_number(x1 / x2);
+ break;
+ case Op_assign_mod:
+ if (x2 == (AWKNUM) 0) {
+ decr_sp();
+ fatal(_("division by zero attempted in `%%='"));
+ }
+#ifdef HAVE_FMOD
+ r = *lhs = make_number(fmod(x1, x2));
+#else /* ! HAVE_FMOD */
+ (void) modf(x1 / x2, &x);
+ x = x1 - x2 * x;
+ r = *lhs = make_number(x);
+#endif /* ! HAVE_FMOD */
+ break;
+ case Op_assign_exp:
+ r = *lhs = make_number((AWKNUM) calc_exp((double) x1, (double) x2));
+ break;
+ default:
+ break;
+ }
+
+ UPREF(r);
+ REPLACE(r);
+}
+
+
/* PUSH_CODE --- push a code onto the runtime stack */
void
@@ -1748,40 +1838,34 @@ top:
break;
case Op_equal:
-
-/* compare two nodes on the stack */
-#define compare(X, Y) \
-t2 = POP_SCALAR(); \
-t1 = TOP_SCALAR(); \
-X = cmp_nodes(t1, t2); \
-DEREF(t1); \
-DEREF(t2); \
-r = make_number((AWKNUM) (Y)); \
-REPLACE(r);
-
- compare(di, di == 0);
+ r = make_number((AWKNUM) (cmp_scalar() == 0));
+ REPLACE(r);
break;
case Op_notequal:
- compare(di, di != 0);
+ r = make_number((AWKNUM) (cmp_scalar() != 0));
+ REPLACE(r);
break;
case Op_less:
- compare(di, di < 0);
+ r = make_number((AWKNUM) (cmp_scalar() < 0));
+ REPLACE(r);
break;
case Op_greater:
- compare(di, di > 0);
+ r = make_number((AWKNUM) (cmp_scalar() > 0));
+ REPLACE(r);
break;
case Op_leq:
- compare(di, di <= 0);
+ r = make_number((AWKNUM) (cmp_scalar() <= 0));
+ REPLACE(r);
break;
case Op_geq:
- compare(di, di >= 0);
+ r = make_number((AWKNUM) (cmp_scalar() >= 0));
+ REPLACE(r);
break;
-#undef compare
case Op_plus_i:
x2 = force_number(pc->memory);
@@ -1839,11 +1923,10 @@ exponent:
case Op_quotient:
POP_NUMBER(x2);
quotient:
- TOP_NUMBER(x1);
- if (x2 == 0) {
- decr_sp();
+ if (x2 == 0)
fatal(_("division by zero attempted"));
- }
+
+ TOP_NUMBER(x1);
#ifdef _CRAY
/* special case for integer division, put in for Cray */
lx2 = x2;
@@ -1870,12 +1953,10 @@ quotient:
case Op_mod:
POP_NUMBER(x2);
mod:
- TOP_NUMBER(x1);
-
- if (x2 == 0) {
- decr_sp();
+ if (x2 == 0)
fatal(_("division by zero attempted in `%%'"));
- }
+
+ TOP_NUMBER(x1);
#ifdef HAVE_FMOD
x = fmod(x1, x2);
#else /* ! HAVE_FMOD */
@@ -1949,7 +2030,7 @@ post:
*/
Func_ptr assign;
- t1 = TOP();
+ t1 = TOP_SCALAR();
lhs = r_get_field(t1, &assign, FALSE);
decr_sp();
DEREF(t1);
@@ -1970,7 +2051,7 @@ post:
if (t1 != t2 && t1->valref == 1 && (t1->flags & PERM) == 0) {
size_t nlen = t1->stlen + t2->stlen;
- erealloc(t1->stptr, char *, nlen + 2, "interpret");
+ erealloc(t1->stptr, char *, nlen + 2, "r_interpret");
memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen);
t1->stlen = nlen;
t1->stptr[nlen] = '\0';
@@ -1978,7 +2059,7 @@ post:
size_t nlen = t1->stlen + t2->stlen;
char *p;
- emalloc(p, char *, nlen + 2, "interpret");
+ emalloc(p, char *, nlen + 2, "r_interpret");
memcpy(p, t1->stptr, t1->stlen);
memcpy(p + t1->stlen, t2->stptr, t2->stlen);
unref(*lhs);
@@ -1997,79 +2078,16 @@ post:
REPLACE(r);
break;
+ /* numeric assignments */
case Op_assign_plus:
-#define assign_common(X, Y) \
-lhs = POP_ADDRESS(); \
-X = force_number(*lhs); \
-TOP_NUMBER(Y); \
-unref(*lhs)
-
-#define assign(X, Y, Z) \
-assign_common(X, Y); \
-r = *lhs = make_number(Z); \
-UPREF(r); \
-REPLACE(r)
-
- assign(x1, x2, x1 + x2);
- break;
-
case Op_assign_minus:
- assign(x1, x2, x1 - x2);
- break;
-
case Op_assign_times:
- assign(x1, x2, x1 * x2);
- break;
-
case Op_assign_quotient:
- assign_common(x1, x2);
- if (x2 == (AWKNUM) 0) {
- decr_sp();
- fatal(_("division by zero attempted in `/='"));
- }
-#ifdef _CRAY
- /* special case for integer division, put in for Cray */
- lx = x2;
- if (lx == 0) {
- r = *lhs = make_number(x1 / x2);
- UPREF(r);
- REPLACE(r);
- break;
- }
- lx = (long) x1 / lx;
- if (lx * x1 == x2)
- r = *lhs = make_number((AWKNUM) lx);
- else
-#endif /* _CRAY */
- r = *lhs = make_number(x1 / x2);
- UPREF(r);
- REPLACE(r);
- break;
-
case Op_assign_mod:
- assign_common(x1, x2);
- if (x2 == (AWKNUM) 0) {
- decr_sp();
- fatal(_("division by zero attempted in `%%='"));
- }
-#ifdef HAVE_FMOD
- r = *lhs = make_number(fmod(x1, x2));
-#else /* ! HAVE_FMOD */
- (void) modf(x1 / x2, &x);
- x = x1 - x2 * x;
- r = *lhs = make_number(x);
-#endif /* ! HAVE_FMOD */
- UPREF(r);
- REPLACE(r);
- break;
-
case Op_assign_exp:
- assign(x1, x2, (AWKNUM) calc_exp((double) x1, (double) x2));
+ op_assign(pc->opcode);
break;
-#undef assign
-#undef assign_common
-
case Op_var_update: /* update value of NR, FNR or NF */
pc->memory->var_update();
break;
@@ -2091,7 +2109,6 @@ REPLACE(r)
{
INSTRUCTION *curr;
int match_found = FALSE;
-
t1 = TOP_SCALAR(); /* switch expression */
for (curr = pc->case_val; curr != NULL; curr = curr->nexti) {
if (curr->opcode == Op_K_case) {
@@ -2471,7 +2488,7 @@ func_call:
ni = POP_CODE(); /* Op_newfile */
ni = ni->target_jmp; /* end_block or Op_atexit */
} else if (inrec(curfile) == 0)
- break; /* prog block */
+ break; /* prog(rule) block */
else
ni = POP_CODE(); /* Op_newfile */
JUMPTO(ni);