pike.git / src / encode.c

version» Context lines:

pike.git/src/encode.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: encode.c,v 1.175 2004/05/11 12:45:00 grubba Exp $ + || $Id: encode.c,v 1.176 2004/05/11 13:19:06 grubba Exp $   */      #include "global.h"   #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "mapping.h"
pike.git/src/encode.c:25:   #include "fsort.h"   #include "threads.h"   #include "stuff.h"   #include "version.h"   #include "bignum.h"   #include "pikecode.h"   #include "pike_types.h"   #include "opcodes.h"   #include "peep.h"    - RCSID("$Id: encode.c,v 1.175 2004/05/11 12:45:00 grubba Exp $"); + RCSID("$Id: encode.c,v 1.176 2004/05/11 13:19:06 grubba Exp $");      /* #define ENCODE_DEBUG */      /* Use the old encoding method for programs. */   #define OLD_PIKE_ENCODE_PROGRAM      #ifdef ENCODE_DEBUG   /* Pass a nonzero integer as the third arg to encode_value,    * encode_value_canonic and decode_value to activate this debug. */   #define EDB(N,X) do { debug_malloc_touch(data); if (data->debug>=N) {X;} } while (0)
pike.git/src/encode.c:2036:    debug_malloc_touch(placeholder);    }    free_object(placeholder);   }      static int init_placeholder(struct object *placeholder);         #define SETUP_DECODE_MEMOBJ(TYPE, U, VAR, ALLOCATE,SCOUR) do { \    struct svalue *tmpptr; \ +  struct svalue tmp; \    if(data->pass > 1 && \ -  (tmpptr=low_mapping_lookup(data->decoded, & data->counter))) \ +  (tmpptr=low_mapping_lookup(data->decoded, & entry_id))) \    { \    tmp=*tmpptr; \    VAR=tmp.u.U; \    SCOUR; \    }else{ \    tmp.type=TYPE; \    tmp.u.U=VAR=ALLOCATE; \ -  mapping_insert(data->decoded, & data->counter, &tmp); \ +  mapping_insert(data->decoded, & entry_id, &tmp); \    /* Since a reference to the object is stored in the mapping, we can \    * safely decrease this reference here. Thus it will be automatically \    * freed if something goes wrong. \    */ \    sub_ref(VAR); \    } \    data->counter.u.integer++; \   }while(0)      /* This really needs to disable threads.... */
pike.git/src/encode.c:2128:   static void decode_value2(struct decode_data *data)      #ifdef PIKE_DEBUG   #undef decode_value2   #define decode_value2(X) do { struct svalue *_=Pike_sp; decode_value2_(X); if(Pike_sp!=_+1) Pike_fatal("decode_value2 failed!\n"); } while(0)   #endif         {    INT32 what, e, num, numh; -  struct svalue tmp, *tmp2; +  struct svalue entry_id, *tmp2;      #ifdef ENCODE_DEBUG    data->depth += 2;   #endif       DECODE("decode_value2");      #ifdef ENCODE_DEBUG    if(data->debug)    {
pike.git/src/encode.c:2156: Inside #if defined(ENCODE_DEBUG)
   data->depth, "", data->counter.u.integer ,    what & TAG_MASK, num);    }   #endif       check_stack(1);       switch(what & TAG_MASK)    {    case TAG_AGAIN: -  tmp.type=T_INT; -  tmp.subtype=0; -  tmp.u.integer=num; -  if((tmp2=low_mapping_lookup(data->decoded, &tmp))) +  entry_id.type=T_INT; +  entry_id.subtype=0; +  entry_id.u.integer=num; +  if((tmp2=low_mapping_lookup(data->decoded, &entry_id)))    {    push_svalue(tmp2);    }else{    Pike_error("Failed to decode TAG_AGAIN entry <%d>.\n", num);    } - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto decode_done;       case TAG_INT: -  tmp.type = T_INT; -  tmp=data->counter; +  entry_id.type = T_INT; +  entry_id=data->counter;    data->counter.u.integer++;    push_int(num);    break;       case TAG_STRING:    {    struct pike_string *str; -  tmp.type = T_INT; -  tmp=data->counter; +  entry_id.type = T_INT; +  entry_id=data->counter;    data->counter.u.integer++;    get_string_data(str, num, data);    push_string(str);    break;    }       case TAG_FLOAT:    {    double res;       EDB(2,fprintf(stderr, "Decoding float... numh:0x%08x, num:0x%08x\n",    numh, num));       res = LDEXP((double)numh, 32) + (double)(unsigned INT32)num;       EDB(2,fprintf(stderr, "Mantissa: %10g\n", res));    -  tmp = data->counter; +  entry_id = data->counter;    data->counter.u.integer++;       DECODE("float");       EDB(2,fprintf(stderr, "Exponent: %d\n", num));       if(!res)    {    DECLARE_INF    DECLARE_NAN
pike.git/src/encode.c:2249:    }       case TAG_TYPE:    {    struct pike_type *t;       decode_type(t, data);    check_type_string(t);    push_type_value(t);    -  tmp.type = T_INT; -  tmp = data->counter; +  entry_id.type = T_INT; +  entry_id = data->counter;    data->counter.u.integer++;    }    break;       case TAG_ARRAY:    {    struct array *a;    if(num < 0)    Pike_error("Failed to decode array. (array size is negative)\n");   
pike.git/src/encode.c:2362:    }   #else    order_multiset(m);   #endif    ref_push_multiset(m);    goto decode_done;    }       case TAG_OBJECT:    { -  tmp=data->counter; +  entry_id=data->counter;    data->counter.u.integer++;       decode_value2(data);       switch(num)    {    case 0:    if(data->codec)    {    apply(data->codec,"objectof", 1);    }else{    fallback_codec();    }    break;       case 1:    if(UNSAFE_IS_ZERO(Pike_sp-1))    {    EDB(1,fprintf(stderr, "%*sDecoded a failed object to <%d>: ", -  data->depth, "", tmp.u.integer); +  data->depth, "", entry_id.u.integer);    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr););    decode_value2(data);    pop_stack();    }else{    int fun;    struct object *o;    /* decode_value_clone_object does not call __INIT, so    * we want to do that ourselves...    */
pike.git/src/encode.c:2415:    * compatibility mode. */    }else{    struct unfinished_obj_link *ol=ALLOC_STRUCT(unfinished_obj_link);    ol->o=o;    ol->next=data->unfinished_objects;    data->unfinished_objects=ol;    }    }       EDB(2,fprintf(stderr, "%*sDecoded an object to <%d>: ", -  data->depth, "", tmp.u.integer); +  data->depth, "", entry_id.u.integer);    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr););       ref_push_object(o);    decode_value2(data);    if(!data->codec)    Pike_error("Failed to decode object (no codec)\n");       fun = find_identifier("decode_object", data->codec->prog);    if (fun < 0)
pike.git/src/encode.c:2472:    break;    }    if(Pike_sp[-1].type != T_OBJECT)    if(data->pickyness)    Pike_error("Failed to decode object.\n");       break;    }       case TAG_FUNCTION: -  tmp=data->counter; +  entry_id=data->counter;    data->counter.u.integer++;    decode_value2(data);       switch(num)    {    case 0:    if(data->codec)    {    apply(data->codec,"functionof", 1);    }else{
pike.git/src/encode.c:2529:    EDB(3,    fprintf(stderr, "%*s TAG_PROGRAM(%d)\n",    data->depth, "", num));    switch(num)    {    case 0:    {    struct svalue *prog_code;    struct program *p;    -  tmp=data->counter; +  entry_id=data->counter;    data->counter.u.integer++;    decode_value2(data);       /* Keep the value so that we can make a good error-message. */    prog_code = Pike_sp-1;    stack_dup();       if(data->codec)    {    apply(data->codec,"programof", 1);
pike.git/src/encode.c:2583:    ONERROR err1, err2, err3, err4;      #ifdef _REENTRANT    ONERROR err;    low_init_threads_disable();    SET_ONERROR(err, do_enable_threads, 0);   #endif       EDB(2,fprintf(stderr, "%*sDecoding a program to <%d>: ",    data->depth, "", data->counter.u.integer); -  print_svalue(stderr, &tmp); +  print_svalue(stderr, &entry_id);    fputc('\n', stderr););       SETUP_DECODE_MEMOBJ(T_PROGRAM, program, p, low_allocate_program(),;);       SET_ONERROR(err3, zap_unfinished_program, p);       if(data->pass == 1)    {    if(! data->supporter.prog)    data->supporter.prog = p;
pike.git/src/encode.c:3095:    }      #ifdef _REENTRANT    UNSET_ONERROR(err);    exit_threads_disable(NULL);   #endif    goto decode_done;    }       case 2: -  tmp=data->counter; +  entry_id=data->counter;    data->counter.u.integer++;    decode_value2(data);    decode_value2(data);    if(Pike_sp[-2].type==T_INT)    {    pop_stack();    }else{    f_arrow(2);    }    if(data->pickyness && Pike_sp[-1].type != T_PROGRAM)    decode_error(NULL, Pike_sp - 1, "Failed to decode program. Got: ");    break;       case 3: -  tmp=data->counter; +  entry_id=data->counter;    data->counter.u.integer++;    decode_value2(data);    if ((Pike_sp[-1].type == T_INT) &&    (Pike_sp[-1].u.integer < PROG_DYNAMIC_ID_START) &&    (Pike_sp[-1].u.integer > 0)) {    struct program *p = id_to_program(Pike_sp[-1].u.integer);    if (!p) {    Pike_error("Failed to get program from ID %"PRINTPIKEINT"d\n",    Pike_sp[-1].u.integer);    }
pike.git/src/encode.c:3136:    }    break;       case 5: { /* Forward reference for new-style encoding. */    struct program *p = low_allocate_program();       push_program (p);    EDB(2,    fprintf (stderr, "%*sInited an embryo for a delay encoded program "    "to <%d>: ", -  data->depth, "", tmp.u.integer); +  data->depth, "", entry_id.u.integer);    print_svalue (stderr, Pike_sp - 1);    fputc ('\n', stderr););      #if 0    /* Is this necessary? In that case, how do we pass an    * adequate context to __register_new_program so that it    * knows which program is being decoded? */    if (data->codec) {    ref_push_program (p);    apply (data->codec, "__register_new_program", 1);
pike.git/src/encode.c:3236:       p->flags = p_flags;       /* Kludge to get end_first_pass() to free the program. */    Pike_compiler->num_parse_error++;       SET_ONERROR(err, cleanup_new_program_decode, &orig_compilation_depth);       debug_malloc_touch(p);    -  tmp.type=T_PROGRAM; -  tmp.u.program=p; +  { +  struct svalue prog; +  prog.type=T_PROGRAM; +  prog.u.program=p;    EDB(2,fprintf(stderr, "%*sDecoding a program to <%d>: ", -  data->depth, "", data->counter.u.integer); -  print_svalue(stderr, &tmp); +  data->depth, "", entry_id.u.integer); +  print_svalue(stderr, &prog);    fputc('\n', stderr);); -  mapping_insert(data->decoded, & data->counter, &tmp); -  tmp = data->counter; -  data->counter.u.integer++; +  mapping_insert(data->decoded, &entry_id, &prog); +  }       debug_malloc_touch(p);       /* Check the version. */    decode_value2(data);    f_version(0);    if(!is_eq(Pike_sp-1,Pike_sp-2))    Pike_error("Cannot decode programs encoded with other pike version.\n");    pop_n_elems(2);   
pike.git/src/encode.c:3270:    decode_value2(data);    if (Pike_sp[-1].type == T_PROGRAM) {    p->parent = Pike_sp[-1].u.program;    } else if ((Pike_sp[-1].type == T_INT) &&    (!Pike_sp[-1].u.integer)) {    p->parent = NULL;    } else {    Pike_error("Bad type for parent program (%s)\n",    get_name_of_type(Pike_sp[-1].type));    } +  dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--;       /* Decode lengths. */   #define FOO(NUMTYPE,TYPE,NAME) \    decode_number(PIKE_CONCAT(local_num_, NAME), data);   #include "program_areas.h"       /* Byte-code method */    decode_number(bytecode_method, data);    if (bytecode_method != PIKE_BYTECODE_METHOD) {
pike.git/src/encode.c:3338:    }       /* identifier_index & variable_index are created by    * fixate_program() and optimize_program().    */       /* Decode strings */    for (e=0; e<local_num_strings; e++) {    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) { -  Pike_error("Non strings in string table.\n"); +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Nonstrings in string table: ");    }    add_to_strings(Pike_sp[-1].u.string); -  +  dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--;    }    -  /* Place holder constants. +  /* First pass constants.    *    * These will be replaced later on.    */    {    struct program_constant constant;    constant.name = NULL;    constant.sval.type = T_INT;    constant.sval.subtype = NUMBER_UNDEFINED;    constant.sval.u.integer = 0;   
pike.git/src/encode.c:3368:    }       /* Decode identifier_references, inherits and identifiers. */    decode_number(entry_type, data);    EDB(4,    fprintf(stderr, "%*sDecoding identifier references.\n",    data->depth, ""));   #ifdef ENCODE_DEBUG    data->depth+=2;   #endif +  while (entry_type == ID_ENTRY_EFUN_CONSTANT) { +  INT32 efun_no; +  struct program_constant *constant; +  decode_number(efun_no, data); +  EDB(2, +  fprintf(stderr, "%*sDecoding efun constant #%d.\n", +  data->depth, "", efun_no)); +  if ((efun_no < 0) || (efun_no >= local_num_constants)) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad efun number: %d (expected 0 - %d).\n", +  efun_no, local_num_constants-1); +  } +  constant = p->constants+efun_no; +  /* value */ +  decode_value2(data); +  if ((Pike_sp[-1].type != T_FUNCTION) || +  (Pike_sp[-1].subtype != FUNCTION_BUILTIN)) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Expected efun constant: "); +  } +  /* name */ +  decode_value2(data); +  if (Pike_sp[-1].type == T_STRING) { +  constant->name = Pike_sp[-1].u.string; +  } else if ((Pike_sp[-1].type == T_INT) && +  !Pike_sp[-1].u.integer) { +  constant->name = NULL; +  } else { +  ref_push_program (p); +  decode_error(Pike_sp - 1, Pike_sp - 2, +  "Name of constant is not a string: "); +  } +  constant->sval = Pike_sp[-2]; +  dmalloc_touch_svalue(Pike_sp-1); +  dmalloc_touch_svalue(Pike_sp-2); +  Pike_sp -= 2; +  decode_number(entry_type, data); +  }    while (entry_type != ID_ENTRY_EOT) {    decode_number(id_flags, data);    switch(entry_type) {    case ID_ENTRY_RAW:    {    int no;    int ref_no;    struct reference ref;       /* id_flags */
pike.git/src/encode.c:3410:    add_to_identifier_references(ref);    }    else {    p->identifier_references[no] = ref;    }    }    break;       case ID_ENTRY_VARIABLE:    { -  int no; +  int no, n;       /* name */    decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,    "Bad variable name (not a string): ");    }       /* type */
pike.git/src/encode.c:3442:    fprintf(stderr,    "%*sdefine_variable(\"%s\", X, 0x%04x)\n",    data->depth, "",    Pike_sp[-2].u.string->str, id_flags));       /* Alters    *    * storage, variable_index, identifiers and    * identifier_references    */ -  if (no != define_variable(Pike_sp[-2].u.string, +  n = define_variable(Pike_sp[-2].u.string,    Pike_sp[-1].u.type, -  id_flags)) { -  Pike_error("Bad variable identifier offset: %d\n", no); +  id_flags); +  if (no != n) { +  ref_push_program (p); +  decode_error(Pike_sp - 1, NULL, +  "Bad variable identifier offset: got %d, expected %d\n", +  n, no);    }       pop_n_elems(2);    }    break;    case ID_ENTRY_FUNCTION:    {    union idptr func;    unsigned INT8 func_flags;    unsigned INT16 opt_flags;
pike.git/src/encode.c:3653:    }       /* prog */    decode_value2(data);    if (Pike_sp[-1].type != T_PROGRAM) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,    "Bad inherit: Expected program, got ");    }    prog = Pike_sp[-1].u.program; +  if (prog == placeholder_program) { +  ref_push_program (p); +  decode_error (Pike_sp - 1, NULL, +  "Trying to inherit placeholder program " +  "(resolver or codec problem).\n"); +  } +  if(!(prog->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) { +  ref_push_program (p); +  decode_error (Pike_sp - 1, Pike_sp - 2, +  "Cannot inherit a program which is not " +  "fully compiled yet (resolver or codec problem):\n"); +  }       /* parent */    decode_value2(data);    if (Pike_sp[-1].type == T_OBJECT) {    parent = Pike_sp[-1].u.object;    } else if ((Pike_sp[-1].type != T_INT) ||    Pike_sp[-1].u.integer) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,    "Bad inherit: Parent isn't an object: ");
pike.git/src/encode.c:3789:       default:    Pike_error("Cannot decode program encoding type %d\n",num);    }    break;       default:    Pike_error("Failed to restore string. (Illegal type)\n");    }    - decode_done: -  EDB(2,fprintf(stderr, "%*sDecoded to <%d>: ", data->depth, "", tmp.u.integer); +  mapping_insert(data->decoded, &entry_id, Pike_sp-1); +  + decode_done:; +  EDB(2,fprintf(stderr, "%*sDecoded to <%d>: ", data->depth, "", entry_id.u.integer);    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr);); -  mapping_insert(data->decoded, & tmp, Pike_sp-1); +    #ifdef ENCODE_DEBUG    data->depth -= 2;   #endif   }      /* Placed after to prevent inlining */   static int init_placeholder(struct object *placeholder)   {    JMP_BUF rec;    /* Initialize the placeholder. */