2001-01-10
2001-01-10 23:31:55 by Martin Stjernholm <mast@lysator.liu.se>
-
f181dec74a26c934255332cf30f8da73f8985f65
(99 lines)
(+55/-44)
[
Show
| Annotate
]
Branch: 7.9
More generic statement cleanup system for labeled statements. Fixed
cleanup for F_FOREACH and F_*_LOOP.
Rev: src/docode.c:1.91
5:
\*/
/**/
#include "global.h"
- RCSID("$Id: docode.c,v 1.90 2001/01/10 20:00:23 mast Exp $");
+ RCSID("$Id: docode.c,v 1.91 2001/01/10 23:31:55 mast Exp $");
#include "las.h"
#include "program.h"
#include "pike_types.h"
42:
struct statement_label_name *name;
INT16 emit_break_label;
INT32 break_label, continue_label;
- unsigned catch_depth;
+ void (*cleanup)(void *);
+ void *cleanup_arg;
};
static struct statement_label *current_label = 0;
- static unsigned catch_depth = 0;
-
+
#define PUSH_STATEMENT_LABEL do { \
struct statement_label new_label__; \
new_label__.prev = current_label; \
-
+ new_label__.cleanup = 0; \
if (!current_label || current_label->break_label != -2) { \
/* Only cover the current label if it's in use by a statement. */ \
new_label__.name = 0; \
new_label__.break_label = new_label__.continue_label = -1; \
- new_label__.catch_depth = catch_depth; \
+
current_label = &new_label__; \
} \
-
+ DO_IF_DEBUG( \
+ else if (current_label && current_label->cleanup) \
+ fatal("Cleanup callback taken in unused statement label.\n"); \
+ ) \
do
#define POP_STATEMENT_LABEL \
while (0); \
current_label = new_label__.prev; \
-
+ if (new_label__.cleanup) \
+ new_label__.cleanup(new_label__.cleanup_arg); \
} while (0)
static INT32 current_switch_case;
100:
static int lbl_cache[LBLCACHESIZE];
- int do_branch(INT32 lbl, int catch_escapes)
+ int do_branch(INT32 lbl)
{
if(lbl==-1)
{
127:
}
}
- while (catch_escapes--)
- emit0(F_ESCAPE_CATCH);
+
emit1(F_BRANCH, lbl);
return lbl;
}
156:
}
}
+ void do_escape_catch()
+ {
+ emit0(F_ESCAPE_CATCH);
+ }
+
#define DO_CODE_BLOCK(X) do_pop(do_docode((X),DO_NOT_COPY | DO_POP | DO_DEFER_POP))
int do_docode(node *n, INT16 flags)
201:
f=!!node_is_false(n);
if(t || f)
{
- if(t == iftrue) do_branch( label, 0);
+ if(t == iftrue) do_branch( label);
return;
}
}
468:
tmp3=emit1(F_POP_N_ELEMS,0);
/* Else */
- tmp2=do_branch(-1, 0);
+ tmp2=do_branch(-1);
low_insert_label( DO_NOT_WARN((INT32)tmp1));
bdroppings=do_docode(CDDR(n), flags);
760:
emit0(F_CONST0);
foreach_arg_pushed:
+ current_label->cleanup = (void (*)(void *)) do_pop;
+ current_label->cleanup_arg = (void *) 4;
#ifdef PIKE_DEBUG
/* This is really ugly because there is always a chance that the bug
* will disappear when new instructions are added to the code, but
768: Inside #if defined(PIKE_DEBUG)
if(d_flag)
emit0(F_MARK);
#endif
- tmp3=do_branch(-1, 0);
+ tmp3=do_branch(-1);
tmp1=ins_label(-1);
DO_CODE_BLOCK(CDR(n));
ins_label(current_label->continue_label);
783:
current_switch_jumptable = prev_switch_jumptable;
} POP_STATEMENT_LABEL;
- do_pop(4);
+
return 0;
}
800:
current_label->continue_label=alloc_label();
tmp2=do_docode(CAR(n),0);
+ current_label->cleanup = (void (*)(void *)) do_pop;
+ current_label->cleanup_arg = (void *) 3;
#ifdef PIKE_DEBUG
/* This is really ugly because there is always a chance that the bug
* will disappear when new instructions are added to the code, but
808: Inside #if defined(PIKE_DEBUG)
if(d_flag)
emit0(F_MARK);
#endif
- tmp3=do_branch(-1, 0);
+ tmp3=do_branch(-1);
tmp1=ins_label(-1);
DO_CODE_BLOCK(CDR(n));
823:
current_switch_jumptable = prev_switch_jumptable;
} POP_STATEMENT_LABEL;
- do_pop(3);
+
return 0;
}
1193:
return 0;
case F_BREAK:
- case F_CONTINUE:
+ case F_CONTINUE: {
+ struct statement_label *label, *p;
+
if (CAR(n)) {
struct pike_string *name = CAR(n)->u.sval.u.string;
- struct statement_label *label;
+
struct statement_label_name *lbl_name;
for (label = current_label; label; label = label->prev)
for (lbl_name = label->name; lbl_name; lbl_name = lbl_name->next)
1206:
return 0;
label_found:
- if (n->token == F_BREAK) {
- if (label->break_label < 0) label->emit_break_label = 1;
- label->break_label =
- do_branch(label->break_label, catch_depth - label->catch_depth);
- }
- else {
- if (label->continue_label < 0)
+ if (n->token == F_CONTINUE && label->continue_label < 0) {
my_yyerror("Cannot continue the non-loop statement on line %d.",
lbl_name->line_number);
- else
- do_branch(label->continue_label, catch_depth - label->catch_depth);
+ return 0;
}
}
else
if (n->token == F_BREAK) {
- if(!current_label || current_label->break_label < 0)
+ label = current_label;
+ if(!label || label->break_label < 0)
{
yyerror("Break outside loop or switch.");
- }else{
- do_branch( current_label->break_label,
- catch_depth - current_label->catch_depth);
+ return 0;
}
}
else {
- struct statement_label *label;
+
for (label = current_label; label; label = label->prev)
- if (label->continue_label >= 0) {
- do_branch( label->continue_label,
- catch_depth - label->catch_depth);
+ if (label->continue_label >= 0)
+ goto continue_label_found;
+ yyerror("Continue outside loop.");
return 0;
-
+ continue_label_found:
}
- yyerror("Continue outside loop.");
+
+ for (p = current_label; p != label; p = p->prev)
+ if (p->cleanup)
+ p->cleanup(p->cleanup_arg);
+
+ if (n->token == F_BREAK) {
+ if (label->break_label < 0) label->emit_break_label = 1;
+ label->break_label = do_branch(label->break_label);
}
-
+ else
+ do_branch(label->continue_label);
+
return 0;
-
+ }
case F_NORMAL_STMT_LABEL:
case F_CUSTOM_STMT_LABEL:
- {
+
PUSH_STATEMENT_LABEL {
struct statement_label *label;
struct statement_label_name name;
1282:
low_insert_label(current_label->break_label);
} POP_STATEMENT_LABEL;
return 0;
- }
+
case F_RETURN:
do_docode(CAR(n),0);
1296:
return 1;
case F_CATCH:
- {
+
PUSH_STATEMENT_LABEL {
INT32 *prev_switch_jumptable = current_switch_jumptable;
1304:
current_label->break_label=alloc_label();
if (TEST_COMPAT(7,0))
current_label->continue_label=alloc_label();
+ current_label->cleanup = (void (*)(void *)) do_escape_catch;
- catch_depth++;
+
tmp1=do_jump(F_CATCH,-1);
DO_CODE_BLOCK(CAR(n));
- catch_depth--;
+
if (TEST_COMPAT(7,0))
ins_label(current_label->continue_label);
1317:
ins_label(DO_NOT_WARN((INT32)tmp1));
current_switch_jumptable = prev_switch_jumptable;
+ current_label->cleanup = 0;
} POP_STATEMENT_LABEL;
return 1;
- }
+
case F_LVALUE_LIST:
return do_docode(CAR(n),DO_LVALUE)+do_docode(CDR(n),DO_LVALUE);
1516:
do_docode(CDR(n), (INT16)(flags | DO_LVALUE));
default:
- fatal("Infernal compiler error (unknown parse-tree-token).\n");
+ fatal("Infernal compiler error (unknown parse-tree-token %d).\n", n->token);
return 0; /* make gcc happy */
}
}