pike.git / src / docode.c

version» Context lines:

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);