pike.git
/
src
/
docode.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/docode.c:1:
/*\ ||| This file is part of Pike. For copyright information see COPYRIGHT. ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/ /**/ #include "global.h"
-
RCSID("$Id: docode.c,v 1.
139
2002/
01
/
16
02:
54
:
09
nilsson
Exp $");
+
RCSID("$Id: docode.c,v 1.
140
2002/
03
/
02
18
:
47
:
38
mast
Exp $");
#include "las.h" #include "program.h" #include "pike_types.h" #include "stralloc.h" #include "interpret.h" #include "constants.h" #include "array.h" #include "pike_macros.h" #include "pike_error.h" #include "pike_memory.h"
pike.git/src/docode.c:154:
} #define POP_STATEMENT_LABEL \ current_label = new_label__.prev; \ DO_IF_DEBUG( \ if (new_label__.cleanups && \ new_label__.cleanups != (void *)(ptrdiff_t) -1) \ fatal("Cleanup frames still left in statement_label.\n")); \ } while (0)
-
static
INT32 current_
switch_
case
;
-
static
INT32
current
_
switch
_default;
-
static
INT32
current_switch_
values_on_stack;
-
static
INT32 *
current
_switch_
jumptable
=0;
+
struct
switch_data
+
{
+
INT32
index
;
+
INT32
less
_
label, greater
_
label,
default
_label
;
+
INT32 values_on_stack;
+
INT32 *
jumptable;
+
struct pike
_
type *type;
+
};
+
+
static struct
switch_
data
current_switch
=
{0,
0
, 0, 0, 0, NULL, NULL}
;
static int in_catch=0;
-
static struct pike_type *current_switch_type = NULL;
+
void upd_int(int offset, INT32 tmp) { MEMCPY(Pike_compiler->new_program->program+offset, (char *)&tmp,sizeof(tmp)); } INT32 read_int(int offset) { return EXTRACT_INT(Pike_compiler->new_program->program+offset); }
pike.git/src/docode.c:388:
case F_LOOP: case F_INC_LOOP: case F_DEC_LOOP: case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_SWITCH: case '?': return 0; case F_CASE:
+
return 1;
+
case F_CASE_RANGE:
return !!CAR(n)+!!CDR(n); default: ret=0; if(car_is_node(n)) ret += count_cases(CAR(n)); if(cdr_is_node(n)) ret += count_cases(CDR(n)); return ret; } }
pike.git/src/docode.c:670:
#endif current_label->cleanups->cleanup = do_pop_to_mark; } code_expression(CAR(n), 0, "`@"); emit0(F_PUSH_ARRAY); return 0; } case '?': {
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
int adroppings , bdroppings;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
if(!CDDR(n)) { tmp1=alloc_label(); do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); DO_CODE_BLOCK(CADR(n)); low_insert_label( DO_NOT_WARN((INT32)tmp1));
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
return 0; } if(!CADR(n)) { tmp1=alloc_label(); do_jump_when_non_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); DO_CODE_BLOCK(CDDR(n)); low_insert_label( DO_NOT_WARN((INT32)tmp1));
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
return 0; } tmp1=alloc_label(); do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); adroppings=do_docode(CADR(n), flags); tmp3=emit1(F_POP_N_ELEMS,0); /* Else */
pike.git/src/docode.c:720:
if(adroppings > bdroppings) { update_arg(DO_NOT_WARN((INT32)tmp3), adroppings - bdroppings); adroppings=bdroppings; } low_insert_label( DO_NOT_WARN((INT32)tmp2));
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
return adroppings; } case F_AND_EQ: case F_OR_EQ: case F_XOR_EQ: case F_LSH_EQ: case F_RSH_EQ: case F_ADD_EQ: case F_SUB_EQ:
pike.git/src/docode.c:1115:
emit0(F_DEC_AND_POP); return 0; }else{ emit0(n->token); return 1; } } case F_FOR: {
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
BLOCK_BEGIN; PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); if(CDR(n)) { do_jump_when_zero(CAR(n),current_label->break_label); tmp2=ins_label(-1); DO_CODE_BLOCK(CADR(n)); ins_label(current_label->continue_label); DO_CODE_BLOCK(CDDR(n)); }else{ tmp2=ins_label(-1); } do_jump_when_non_zero(CAR(n), DO_NOT_WARN((INT32)tmp2)); ins_label(current_label->break_label);
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL; BLOCK_END; return 0; } case ' ': return do_docode(CAR(n),0)+do_docode(CDR(n),DO_LVALUE); case F_FOREACH: { node *arr;
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
arr=CAR(n); if(CDR(arr) && CDR(arr)->token == ':') { BLOCK_BEGIN; /* New-style */ tmp1=do_docode(CAR(arr), DO_NOT_COPY_TOPLEVEL); emit0(F_MAKE_ITERATOR); if(CADR(arr))
pike.git/src/docode.c:1179:
do_docode(CDDR(arr), DO_LVALUE); }else{ emit0(F_CONST0); emit0(F_CONST0); current_stack_depth+=2; } PUSH_CLEANUP_FRAME(do_pop, 5); PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); tmp3=do_branch(-1); tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_label->continue_label); low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(F_NEW_FOREACH, DO_NOT_WARN((INT32)tmp1)); ins_label(current_label->break_label);
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL; POP_AND_DO_CLEANUP; BLOCK_END; return 0; } BLOCK_BEGIN; if(CAR(arr) && CAR(arr)->token==F_RANGE)
pike.git/src/docode.c:1222:
goto foreach_arg_pushed; } } do_docode(CAR(n),DO_NOT_COPY); emit0(F_CONST0); current_stack_depth++; foreach_arg_pushed: PUSH_CLEANUP_FRAME(do_pop, 4); PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); tmp3=do_branch(-1); tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_label->continue_label); low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_label->break_label);
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL; POP_AND_DO_CLEANUP; BLOCK_END; return 0; } case F_INC_NEQ_LOOP: case F_DEC_NEQ_LOOP: case F_INC_LOOP: case F_DEC_LOOP: {
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
BLOCK_BEGIN; do_docode(CAR(n),0); PUSH_CLEANUP_FRAME(do_pop, 3); PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); tmp3=do_branch(-1); tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_label->continue_label); low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_label->break_label);
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL; POP_AND_DO_CLEANUP; BLOCK_END; return 0; } case F_LOOP: { /* FIXME: No support for break or continue. */ PUSH_STATEMENT_LABEL;
pike.git/src/docode.c:1291:
DO_CODE_BLOCK(CDR(n)); ins_label(tmp2); emit1(F_LOOP, tmp3); } POP_STATEMENT_LABEL; return 0; } case F_DO: {
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
BLOCK_BEGIN; PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); current_label->continue_label=alloc_label(); tmp2=ins_label(-1); DO_CODE_BLOCK(CAR(n)); ins_label(current_label->continue_label); do_jump_when_non_zero(CDR(n), DO_NOT_WARN((INT32)tmp2)); ins_label(current_label->break_label);
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
POP_STATEMENT_LABEL; BLOCK_END; return 0; } case F_POP_VALUE: { BLOCK_BEGIN; DO_CODE_BLOCK(CAR(n)); BLOCK_END;
pike.git/src/docode.c:1554:
* cases. (Ranked by the binsearch that is) The second is used if it * is equal to the first index. The third if it is greater than the * first, but lesser than the second. The fourth if it is equal to * the second.... etc. etc. */ case F_SWITCH: { INT32 e,cases,*order; INT32 *jumptable;
-
INT32
prev_
switch_
values_on_stack
= current_switch_values_on_stack;
-
INT32
prev_switch
_case
= current_switch
_case
;
-
INT32 prev_switch_default = current_switch_default;
-
INT32 *prev_switch_jumptable = current_switch_jumptable;
-
struct pike_type *prev_switch_type = current_switch_type;
+
struct
switch_
data
prev_switch = current_switch;
#ifdef PIKE_DEBUG struct svalue *save_sp=Pike_sp; #endif BLOCK_BEGIN; PUSH_STATEMENT_LABEL; if(do_docode(CAR(n),0)!=1) fatal("Internal compiler error, time to panic\n");
-
if (!(CAR(n) && (current_switch
_
type = CAR(n)->type))) {
-
current_switch
_
type = mixed_type_string;
+
if (!(CAR(n) && (current_switch
.
type = CAR(n)->type))) {
+
current_switch
.
type = mixed_type_string;
} current_label->break_label=alloc_label(); cases=count_cases(CDR(n)); tmp1=emit1(F_SWITCH,0); current_stack_depth--; emit1(F_ALIGN,sizeof(INT32));
-
current_switch
_
values_on_stack=0;
-
current_switch_
case
=1;
-
current_switch_
default
=-1;
-
current_switch_jumptable=(INT32 *)xalloc(sizeof(INT32)*(cases*2+2));
+
current_switch
.
values_on_stack=0;
+
current_switch
.index=2;
+
current
_
switch.less_label
=
-
1;
+
current_switch
.greater
_
label=-1;
+
current_switch.
default
_label
=-1;
+
current_switch
.
jumptable=(INT32 *)xalloc(sizeof(INT32)*(cases*2+2));
jumptable=(INT32 *)xalloc(sizeof(INT32)*(cases*2+2)); for(e=1; e<cases*2+2; e++) { jumptable[e] = DO_NOT_WARN((INT32)emit1(F_POINTER, 0));
-
current_switch
_
jumptable[e]=-1;
+
current_switch
.
jumptable[e]=-1;
} emit0(F_NOTREACHED);
-
current_switch_jumptable[current_switch_case++]=-1;
-
+
DO_CODE_BLOCK(CDR(n)); #ifdef PIKE_DEBUG if(Pike_sp-save_sp != cases) fatal("Count cases is wrong!\n"); #endif f_aggregate(cases); /* FIXME: get_switch_order might possibly be able to * throw errors, add a catch around this! -Hubbe */ order=get_switch_order(Pike_sp[-1].u.array); if (!Pike_compiler->num_parse_error) { /* Check for cases inside a range */
-
+
if (cases &&
+
((current_switch.less_label >= 0 &&
+
current_switch.jumptable[order[0]*2+2] !=
+
current_switch.less_label) ||
+
(current_switch.greater_label >= 0 &&
+
current_switch.jumptable[order[cases-1]*2+2] !=
+
current_switch.greater_label)))
+
yyerror("Case inside range.");
for(e=0; e<cases-1; e++) { if(order[e] < cases-1) { int o1=order[e]*2+2;
-
if(current_switch
_
jumptable[o1]==current_switch
_
jumptable[o1+1] &&
-
current_switch
_
jumptable[o1]==current_switch
_
jumptable[o1+2])
+
if(current_switch
.
jumptable[o1]==current_switch
.
jumptable[o1+1] &&
+
current_switch
.
jumptable[o1]==current_switch
.
jumptable[o1+2])
{ if(order[e]+1 != order[e+1]) yyerror("Case inside range."); e++; } } } }
-
if(current_switch_default < 0)
-
current_switch_default = ins_label(-1);
-
-
for(e=1;e<cases*2+2;e++)
-
if(current_switch_jumptable[e]==-1)
-
current_switch_jumptable[e]=current_switch_default;
-
+
order_array(Pike_sp[-1].u.array,order);
-
reorder((void *)(current_switch
_
jumptable+2),cases,sizeof(INT32)*2,order);
+
reorder((void *)(current_switch
.
jumptable+2),cases,sizeof(INT32)*2,order);
free((char *)order);
-
+
current_switch.jumptable[1] = current_switch.less_label;
+
current_switch.jumptable[current_switch.index - 1] = current_switch.greater_label;
+
+
if(current_switch.default_label < 0)
+
current_switch.default_label = ins_label(-1);
+
+
for(e=1;e<cases*2+2;e++)
+
if(current_switch.jumptable[e]==-1)
+
current_switch.jumptable[e]=current_switch.default_label;
+
for(e=1; e<cases*2+2; e++)
-
update_arg(jumptable[e], current_switch
_
jumptable[e]);
+
update_arg(jumptable[e], current_switch
.
jumptable[e]);
update_arg(DO_NOT_WARN((INT32)tmp1), store_constant(Pike_sp-1,1,0)); pop_stack(); free((char *)jumptable);
-
free((char *)current_switch
_
jumptable);
+
free((char *)current_switch
.
jumptable);
-
current_switch
_jumptable
= prev_switch
_jumptable
;
-
current_switch_default = prev_switch_default;
-
current_switch_case = prev_switch_case;
-
current_switch_values_on_stack = prev_switch_values_on_stack;
-
current_switch_type = prev_switch_type;
+
current_switch = prev_switch;
low_insert_label( current_label->break_label); POP_STATEMENT_LABEL; BLOCK_END; #ifdef PIKE_DEBUG if(Pike_interpreter.recoveries && Pike_sp-Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer) fatal("Stack error after F_SWITCH (underflow)\n"); #endif return 0; } case F_CASE:
-
+
case F_CASE_RANGE:
{
-
if(!current_switch
_
jumptable)
+
if(!current_switch
.
jumptable)
{ yyerror("Case outside switch."); }else{
-
node
*lower
=
CAR
(
n
);
-
if(!lower)
lower=CDR(n)
;
+
INT32
label
=
ins_label
(
-1
);
+
int
i
;
-
if(!is_const(
lower
))
+
for (i = 0; i < 2; i++) {
+
node *case_val = i == 0 ? CAR(n) : CDR(n);
+
+
if
(
case_val) {
+
if(
!is_const(
case_val
))
yyerror("Case label isn't constant.");
-
if
(lower
&&
lower
->type && !TEST_COMPAT(0,6)) {
-
if (!pike_types_le(
lower
->type, current_switch
_
type)) {
-
if (!match_types(
lower
->type, current_switch
_
type)) {
+
if (
case_val
->type && !TEST_COMPAT(0,6)) {
+
if (!pike_types_le(
case_val
->type, current_switch
.
type)) {
+
if (!match_types(
case_val
->type, current_switch
.
type)) {
yytype_error("Type mismatch in case.",
-
current_switch
_
type,
lower
->type, 0);
+
current_switch
.
type,
case_val
->type, 0);
} else if (lex.pragmas & ID_STRICT_TYPES) { yytype_error("Type mismatch in case.",
-
current_switch
_
type,
lower
->type, YYTE_IS_WARNING);
+
current_switch
.
type,
case_val
->type, YYTE_IS_WARNING);
} } } if (!Pike_compiler->num_parse_error) {
-
tmp1=eval_low(
lower
);
+
tmp1=eval_low(
case_val
);
if(tmp1<1) { yyerror("Error in case label."); push_int(0); tmp1=1; } pop_n_elems(tmp1-1);
-
current_switch
_
values_on_stack++;
-
for(tmp1=current_switch
_
values_on_stack; tmp1 > 1; tmp1--)
+
current_switch
.
values_on_stack++;
+
for(tmp1=current_switch
.
values_on_stack; tmp1 > 1; tmp1--)
if(is_equal(Pike_sp-tmp1, Pike_sp-1))
-
yyerror("Duplicate case.");
+
yyerror("Duplicate case
label
.");
} else { push_int(0);
-
current_switch
_
values_on_stack++;
+
current_switch
.
values_on_stack++;
}
-
current_switch_jumptable[current_switch_case++]=ins_label(-1);
+
}
+
}
-
if(
CDR(
n
))
-
{
-
current_switch
_
jumptable[current_switch
_case
]=
-
current_switch_jumptable[current_switch_case-1];
-
current_switch_case++;
-
-
if(CAR(n))
-
{
-
if(!is_const(CDR(n)))
-
yyerror("Case
label
isn't constant.")
;
-
-
current_switch
_
jumptable[current_switch
_case
]=
-
current_switch_jumptable[current_switch_case
-1
]
;
-
current_switch_case++;
-
-
if (!Pike_compiler->num_parse_error) {
-
tmp1=eval_low(CDR(n));
-
if(tmp1<1)
-
{
-
yyerror("Error in second half of case label.");
-
push_int(0);
-
tmp1=1;
+
if
(n
->token
==
F_CASE)
{
+
current_switch
.
jumptable[current_switch
.index++
]
=
label
;
+
current_switch.jumptable[current_switch
.index++
]
= -1;
}
-
pop_n_elems(tmp1-1);
-
current_switch_
values_on_stack++
;
-
for
(
tmp1=
current_switch_
values_on_stack;
tmp1
> 1
;
tmp1--)
-
if(
is_equal
(
Pike_sp-tmp1,
Pike_sp-1
))
-
yyerror("Duplicate case.")
;
-
}
else
{
-
push_int(0)
;
-
current_switch_
values_on_stack++
;
+
else
{
+
if
(!CAR(n))
current_switch
.less
_
label = label
;
+
if
(!CDR(n))
current_switch
.greater
_
label
=
label
;
+
if
(CAR(n)
&&
CDR
(
n
))
{
+
current_switch.jumptable[current_switch.index++]
=
label
;
+
current_switch.jumptable[current_switch.index++]
=
label;
+
current_switch.jumptable[current_switch.index++]
=
label
;
+
current_switch
.jumptable[current
_
switch.index++] = -1
;
}
-
current_switch
_
jumptable[current_switch_
case++
]=-1;
+
else
{
+
current_switch
.jumptable[current
_
switch.index++] = label;
+
current_switch.
jumptable[current_switch
.index++
]
=
-1;
}
-
}else{
-
current_switch_jumptable[current_switch_case++]=-1;
+
} } return 0; } case F_DEFAULT:
-
if(!current_switch
_
jumptable)
+
if(!current_switch
.
jumptable)
{ yyerror("Default outside switch.");
-
}else if(current_switch
_
default!=-1){
+
}else if(current_switch
.default
_
label
!=-1){
yyerror("Duplicate switch default."); }else{
-
current_switch
_
default = ins_label(-1);
+
current_switch
.default
_
label
= ins_label(-1);
} return 0; case F_BREAK: case F_CONTINUE: { struct statement_label *label, *p; if (CAR(n)) { struct pike_string *name = CAR(n)->u.sval.u.string; struct statement_label_name *lbl_name;
pike.git/src/docode.c:1876:
emit0(in_catch ? F_VOLATILE_RETURN : F_RETURN); return 0; case F_SSCANF: tmp1=do_docode(CAR(n),DO_NOT_COPY); tmp2=do_docode(CDR(n),DO_NOT_COPY | DO_LVALUE); emit1(F_SSCANF, DO_NOT_WARN((INT32)(tmp1+tmp2))); return 1; case F_CATCH: {
-
INT32 *prev_switch_jumptable = current_switch
_
jumptable;
+
INT32 *prev_switch_jumptable = current_switch
.
jumptable;
tmp1=do_jump(F_CATCH,-1); PUSH_CLEANUP_FRAME(do_escape_catch, 0); PUSH_STATEMENT_LABEL;
-
current_switch
_
jumptable=0;
+
current_switch
.
jumptable=0;
current_label->break_label=alloc_label(); if (TEST_COMPAT(7,0)) current_label->continue_label = current_label->break_label; in_catch++; DO_CODE_BLOCK(CAR(n)); in_catch--; ins_label(current_label->break_label); emit0(F_THROW_ZERO); POP_STATEMENT_LABEL;
-
current_switch
_
jumptable = prev_switch_jumptable;
+
current_switch
.
jumptable = prev_switch_jumptable;
ins_label(DO_NOT_WARN((INT32)tmp1)); current_stack_depth++; POP_AND_DONT_CLEANUP; return 1; } case F_LVALUE_LIST: return do_docode(CAR(n),DO_LVALUE)+do_docode(CDR(n),DO_LVALUE);