pike.git / src / docode.c

version» Context lines:

pike.git/src/docode.c:1:   /*\   ||| This file a part of Pike, and is copyright by Fredrik Hubinette   ||| 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.101 2001/01/25 09:14:38 hubbe Exp $"); + RCSID("$Id: docode.c,v 1.102 2001/01/31 22:02:12 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:101:    ) \    current_label->prev->cleanups = cleanup_frame__.prev; \    } \   } while (0)      #define POP_AND_DO_CLEANUP \    do_pop(current_stack_depth - cleanup_frame__.stack_depth); \    cleanup_frame__.cleanup(cleanup_frame__.cleanup_arg); \    POP_AND_DONT_CLEANUP    + /* A block in the following sense is a region of code where: +  * o Execution always enters at the beginning. +  * o All stack nesting is left intact on exit (both normally and +  * through jumps, but not through exceptions). This includes the +  * svalue and mark stacks, and the catch block nesting. +  */ + #ifdef PIKE_DEBUG + #define BLOCK_BEGIN \ +  PUSH_CLEANUP_FRAME(do_cleanup_synch_mark, 0); \ +  if (d_flag > 2) emit0(F_SYNCH_MARK); + #define BLOCK_END \ +  if (current_stack_depth != cleanup_frame__.stack_depth) { \ +  print_tree(n); \ +  fatal("Stack not in synch after block: is %d, should be %d.\n", \ +  current_stack_depth, cleanup_frame__.stack_depth); \ +  } \ +  if (d_flag > 2) emit0(F_POP_SYNCH_MARK); \ +  POP_AND_DONT_CLEANUP + #else + #define BLOCK_BEGIN + #define BLOCK_END + #endif +    #define PUSH_STATEMENT_LABEL do { \    struct statement_label new_label__; \    new_label__.prev = current_label; \    if (current_label->break_label != -2) { \    /* Only cover the current label if it's closed. */ \    new_label__.name = 0; \    new_label__.break_label = new_label__.continue_label = -1; \    new_label__.emit_break_label = 0; \    new_label__.cleanups = 0; \    new_label__.stack_depth = current_stack_depth; \
pike.git/src/docode.c:222:   #endif    switch(x)    {    case 0: return;    case 1: emit0(F_POP_VALUE); break;    default: emit1(F_POP_N_ELEMS,x); break;    }    current_stack_depth -= x;   }    - void do_cleanup_pop(int x) - { - #ifdef PIKE_DEBUG -  if(d_flag) -  emit0(F_POP_MARK); - #endif -  do_pop(x); - } -  +    void do_pop_mark()   {    emit0(F_POP_MARK);   }      void do_pop_to_mark()   {    emit0(F_POP_TO_MARK);   }    -  + void do_cleanup_synch_mark() + { +  if (d_flag > 2) +  emit0(F_CLEANUP_SYNCH_MARK); + } +    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)) + #define DO_CODE_BLOCK(X) do_pop(do_docode((X),DO_NOT_COPY | DO_POP ))      int do_docode(node *n, INT16 flags)   {    int i;    int stack_depth_save = current_stack_depth;    int save_current_line=lex.current_line;    if(!n) return 0;    lex.current_line=n->line_number;   #ifdef PIKE_DEBUG    if (current_stack_depth == -4711) fatal("do_docode() used outside docode().\n");
pike.git/src/docode.c:823:    emit0(F_DEC_AND_POP);    return 0;    }else{    emit0(n->token);    return 1;    }       case F_FOR:    {    INT32 *prev_switch_jumptable = current_switch_jumptable; +  BLOCK_BEGIN;    PUSH_STATEMENT_LABEL;       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);
pike.git/src/docode.c:844:    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;    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; -  +  BLOCK_BEGIN;       arr=CAR(n);       if(arr->token==F_RANGE)    {    node **a1=my_get_arg(&_CDR(n),0);    node **a2=my_get_arg(&_CDR(n),1);    if(a1 && a2 && a2[0]->token==F_CONSTANT &&    a2[0]->u.sval.type==T_INT &&    a2[0]->u.sval.type==0x7fffffff &&    a1[0]->type == int_type_string)    { -  tmp2=do_docode(CAR(arr),DO_NOT_COPY); +  do_docode(CAR(arr),DO_NOT_COPY);    do_docode(*a1,DO_NOT_COPY);    goto foreach_arg_pushed;    }    } -  tmp2=do_docode(CAR(n),DO_NOT_COPY); +  do_docode(CAR(n),DO_NOT_COPY);    emit0(F_CONST0);    current_stack_depth++; -  +     foreach_arg_pushed: - #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 -  * think it is worth it. -  */ -  if(d_flag) -  emit0(F_MARK); - #endif -  PUSH_CLEANUP_FRAME(do_cleanup_pop, 4); +  PUSH_CLEANUP_FRAME(do_pop, 4);       PUSH_STATEMENT_LABEL;    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;    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; -  +  BLOCK_BEGIN;    -  tmp2=do_docode(CAR(n),0); - #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 -  * think it is worth it. -  */ -  if(d_flag) -  emit0(F_MARK); - #endif -  PUSH_CLEANUP_FRAME(do_cleanup_pop, 3); +  do_docode(CAR(n),0); +  PUSH_CLEANUP_FRAME(do_pop, 3);       PUSH_STATEMENT_LABEL;    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;    POP_STATEMENT_LABEL;    POP_AND_DO_CLEANUP; -  +  BLOCK_END;    return 0;    }       case F_LOOP:    {    /* FIXME: No support for break or continue. */    PUSH_STATEMENT_LABEL;    tmp1 = do_docode(CAR(n), 0);    if (tmp1 > 0) {    do_pop(tmp1-1);
pike.git/src/docode.c:962:    ins_label(tmp2);    emit1(F_LOOP, tmp3);    }    POP_STATEMENT_LABEL;    return 0;    }       case F_DO:    {    INT32 *prev_switch_jumptable = current_switch_jumptable; +  BLOCK_BEGIN;    PUSH_STATEMENT_LABEL;       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;    POP_STATEMENT_LABEL; -  +  BLOCK_END;    return 0;    }       case F_POP_VALUE:    { -  +  BLOCK_BEGIN;    DO_CODE_BLOCK(CAR(n)); -  +  BLOCK_END;    return 0;    }       case F_CAST:    if(n->type==void_type_string)    {    DO_CODE_BLOCK(CAR(n));    return 0;    }    tmp1=store_prog_string(n->type);
pike.git/src/docode.c:1134:    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_string *prev_switch_type = current_switch_type;   #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;    }       current_label->break_label=alloc_label();
pike.git/src/docode.c:1229:       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;       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:    {    if(!current_switch_jumptable)
pike.git/src/docode.c:1395:    else    do_branch(label->continue_label);       return 0;    }       case F_NORMAL_STMT_LABEL:    case F_CUSTOM_STMT_LABEL: {    struct statement_label *label;    struct statement_label_name name; +  BLOCK_BEGIN;    PUSH_STATEMENT_LABEL;    name.str = CAR(n)->u.sval.u.string;    name.line_number = n->line_number;       for (label = current_label; label; label = label->prev) {    struct statement_label_name *lbl_name;    for (lbl_name = label->name; lbl_name; lbl_name = lbl_name->next)    if (lbl_name->str == name.str) {    INT32 save_line = lex.current_line;    lex.current_line = name.line_number;
pike.git/src/docode.c:1429:    * the statement_label "open" so the statement will use it    * instead of covering it. */    current_label->break_label = -2;    else    current_label->break_label = -1;    }    DO_CODE_BLOCK(CDR(n));    if (!name.next && current_label->emit_break_label)    low_insert_label(current_label->break_label);    POP_STATEMENT_LABEL; +  BLOCK_END;    return 0;    }       case F_RETURN:    do_docode(CAR(n),0);    emit0(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; -  +     tmp1=do_jump(F_CATCH,-1);    PUSH_CLEANUP_FRAME(do_escape_catch, 0);       PUSH_STATEMENT_LABEL;    current_switch_jumptable=0;    current_label->break_label=alloc_label();    if (TEST_COMPAT(7,0)) -  current_label->continue_label=alloc_label(); +  current_label->continue_label = current_label->break_label;       DO_CODE_BLOCK(CAR(n));    -  if (TEST_COMPAT(7,0)) -  ins_label(current_label->continue_label); +     ins_label(current_label->break_label);    emit0(F_THROW_ZERO); -  current_switch_jumptable = prev_switch_jumptable; +     POP_STATEMENT_LABEL; -  +  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);