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 2003/06/02 21:16:51 mast Exp $ + || $Id: encode.c,v 1.176 2003/06/03 18:15:31 mast 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:20:   #include "operators.h"   #include "builtin_functions.h"   #include "module_support.h"   #include "fsort.h"   #include "threads.h"   #include "stuff.h"   #include "version.h"   #include "bignum.h"   #include "pikecode.h"    - RCSID("$Id: encode.c,v 1.175 2003/06/02 21:16:51 mast Exp $"); + RCSID("$Id: encode.c,v 1.176 2003/06/03 18:15:31 mast Exp $");    - /* #define ENCODE_DEBUG */ + #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)   #else   #define EDB(N,X) do { debug_malloc_touch(data); } while (0)
pike.git/src/encode.c:83:   #define TAG_MAPPING 1   #define TAG_MULTISET 2   #define TAG_OBJECT 3   #define TAG_FUNCTION 4   #define TAG_PROGRAM 5   #define TAG_STRING 6   #define TAG_FLOAT 7   #define TAG_INT 8   #define TAG_TYPE 9 /* Not supported yet */    + #define TAG_DELAYED 14 /* Note: Coincides with T_ZERO. */   #define TAG_AGAIN 15   #define TAG_MASK 15   #define TAG_NEG 16   #define TAG_SMALL 32   #define SIZE_SHIFT 6   #define MAX_SMALL (1<<(8-SIZE_SHIFT)) - #define COUNTER_START -MAX_SMALL + #define COUNTER_START 1      /* Entries used to encode the identifier_references table. */   #define ID_ENTRY_RAW -2   #define ID_ENTRY_EOT -1   #define ID_ENTRY_VARIABLE 0   #define ID_ENTRY_FUNCTION 1   #define ID_ENTRY_CONSTANT 2   #define ID_ENTRY_INHERIT 3      struct encode_data   {    int canonic;    struct object *codec;    struct svalue counter;    struct mapping *encoded; -  +  /* The encoded mapping maps encoded things to their entry IDs. A +  * negative value means that it's a forward reference to a thing not +  * yet encoded. */ +  struct array *delayed;    dynamic_buffer buf;   #ifdef ENCODE_DEBUG    int debug, depth;   #endif   };    - static void encode_value2(struct svalue *val, struct encode_data *data); + static void encode_value2(struct svalue *val, struct encode_data *data, int force_dump);      #define addstr(s, l) low_my_binary_strcat((s), (l), &(data->buf))   #define addchar(t) low_my_putchar((char)(t), &(data->buf))      /* Code a pike string */      #if BYTEORDER == 4321   #define ENCODE_DATA(S) \    addstr( (S)->str, (S)->len << (S)->size_shift );   #else
pike.git/src/encode.c:271:       break;       case PIKE_T_NAME:    {    struct svalue sval;    sval.type = PIKE_T_STRING;    sval.subtype = 0;    sval.u.string = (void *)t->car;    -  encode_value2(&sval, data); +  encode_value2(&sval, data, 0);    }    t=t->cdr;    goto one_more_type;       case T_ASSIGN:    {    ptrdiff_t marker = ((char *)t->car)-(char *)0;    if ((marker < 0) || (marker > 9)) {    Pike_fatal("Bad assign marker: %ld\n",    (long)marker);
pike.git/src/encode.c:371:    {    ref_push_program(p);    }else{    push_int(0);    }    } else    push_int( id );    }else{    push_int(0);    } -  encode_value2(Pike_sp-1, data); +  /* If it's a program that should be encoded recursively then we +  * must delay it. Consider: +  * +  * class A {B b;} +  * class B {inherit A;} +  * +  * We can't dump B when the type is encountered inside A, since +  * upon decode B won't have a complete A to inherit then. +  */ +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    break;    }    }   }      static void zap_unfinished_program(struct program *p)   {    int e;    debug_malloc_touch(p);
pike.git/src/encode.c:412:    {    if(p->inherits[e].prog)    {    free_program(p->inherits[e].prog);    p->inherits[e].prog=0;    }    }    }   }    - static void encode_value2(struct svalue *val, struct encode_data *data) + /* force_dump == 0: Maybe dump the thing later, and only a forward +  * reference here (applies to programs only). +  * +  * force_dump == 1: Dump the thing now. +  * +  * force_dump == 2: A forward reference has been encoded to this +  * thing. Now it's time to dump it. */    -  + static void encode_value2(struct svalue *val, struct encode_data *data, int force_dump) +    #ifdef PIKE_DEBUG   #undef encode_value2 - #define encode_value2(X,Y) do { struct svalue *_=Pike_sp; encode_value2_(X,Y); if(Pike_sp!=_) Pike_fatal("encode_value2 failed!\n"); } while(0) + #define encode_value2(X,Y,Z) do { \ +  struct svalue *_=Pike_sp; \ +  encode_value2_(X,Y,Z); \ +  if(Pike_sp!=_) Pike_fatal("encode_value2 failed!\n"); \ +  } while(0)   #endif      {    static struct svalue dested = {    T_INT, NUMBER_DESTRUCTED,   #ifdef HAVE_UNION_INIT    {0}, /* Only to avoid warnings. */   #endif    };    INT32 i;    struct svalue *tmp; -  +  struct svalue entry_id;      #ifdef ENCODE_DEBUG    data->depth += 2;   #endif       if((val->type == T_OBJECT ||    (val->type==T_FUNCTION && val->subtype!=FUNCTION_BUILTIN)) &&    !val->u.object->prog)    val = &dested;       if((tmp=low_mapping_lookup(data->encoded, val)))    { -  +  entry_id = *tmp; /* It's always a small integer. */ +  if (entry_id.u.integer < 0) entry_id.u.integer = -entry_id.u.integer; +  if (force_dump && tmp->u.integer < 0) { +  EDB(1, +  fprintf(stderr, "%*sEncoding delayed thing to <%d>: ", +  data->depth, "", entry_id.u.integer); +  if(data->debug == 1) +  { +  fprintf(stderr,"TAG%d",val->type); +  }else{ +  print_svalue(stderr, val); +  +  } +  fputc('\n', stderr);); +  code_entry (TAG_DELAYED, entry_id.u.integer, data); +  tmp->u.integer = entry_id.u.integer; +  } +  else {    EDB(1,fprintf(stderr, "%*sEncoding TAG_AGAIN from <%d>\n", -  data->depth, "", tmp->u.integer)); -  code_entry(TAG_AGAIN, tmp->u.integer, data); +  data->depth, "", entry_id.u.integer)); +  code_entry(TAG_AGAIN, entry_id.u.integer, data);    goto encode_done; -  }else if (val->type != T_TYPE) { +  } +  }else { + #ifdef PIKE_DEBUG +  if (force_dump == 2) +  Pike_fatal ("Didn't find old entry for delay encoded thing.\n"); + #endif +  if (val->type != T_TYPE) { +  entry_id = data->counter; /* It's always a small integer. */    EDB(1,fprintf(stderr, "%*sEncoding to <%d>: ", -  data->depth, "", data->counter.u.integer); +  data->depth, "", entry_id.u.integer);    if(data->debug == 1)    {    fprintf(stderr,"TAG%d",val->type);    }else{    print_svalue(stderr, val);       }    fputc('\n', stderr);); -  mapping_insert(data->encoded, val, &data->counter); +  mapping_insert(data->encoded, val, &entry_id);    data->counter.u.integer++;    } -  +  }    -  +     switch(val->type)    {    case T_INT:    /* NOTE: Doesn't encode NUMBER_UNDEFINED et al. */    /* But that's a feature; NUMBER_UNDEFINED is an inherently    * transient value. It would lose its usefulness otherwise.    * /mast */      #if SIZEOF_INT_TYPE > 4    {    INT_TYPE i=val->u.integer;    if (i != (INT32)i)    {   #ifdef AUTO_BIGNUM    push_int(i);    convert_stack_top_to_bignum(); -  encode_value2(Pike_sp-1,data); +  encode_value2(Pike_sp-1,data, 0);    pop_stack();   #else    Pike_error ("Cannot encode integers with more than 32 bits "    "without bignum support.\n");   #endif    goto encode_done;    }    else    code_entry(TAG_INT, i,data);    }
pike.git/src/encode.c:662:   #endif    code_entry(TAG_FLOAT,x,data);    code_entry(TAG_FLOAT,y,data);    }    break;    }       case T_ARRAY:    code_entry(TAG_ARRAY, val->u.array->size, data);    for(i=0; i<val->u.array->size; i++) -  encode_value2(ITEM(val->u.array)+i, data); +  encode_value2(ITEM(val->u.array)+i, data, 0);    break;       case T_MAPPING:    check_stack(2);    ref_push_mapping(val->u.mapping);    f_indices(1);       ref_push_mapping(val->u.mapping);    f_values(1);   
pike.git/src/encode.c:693:    }    order = get_switch_order(Pike_sp[-2].u.array);    order_array(Pike_sp[-2].u.array, order);    order_array(Pike_sp[-1].u.array, order);    free((char *) order);    }       code_entry(TAG_MAPPING, Pike_sp[-2].u.array->size,data);    for(i=0; i<Pike_sp[-2].u.array->size; i++)    { -  encode_value2(ITEM(Pike_sp[-2].u.array)+i, data); /* indices */ -  encode_value2(ITEM(Pike_sp[-1].u.array)+i, data); /* values */ +  encode_value2(ITEM(Pike_sp[-2].u.array)+i, data, 0); /* indices */ +  encode_value2(ITEM(Pike_sp[-1].u.array)+i, data, 0); /* values */    }    pop_n_elems(2);    break;       case T_MULTISET: {    struct multiset *l = val->u.multiset;      #ifdef PIKE_NEW_MULTISETS    if (multiset_indval (l) || multiset_get_cmp_less (l)->type != T_INT)    Pike_error ("FIXME: Encoding of multisets with values and/or "
pike.git/src/encode.c:731: Inside #if defined(PIKE_NEW_MULTISETS)
   check_stack(1);   #ifdef PIKE_NEW_MULTISETS    push_array(multiset_indices(l));   #else    push_array(copy_array(l->ind));   #endif    order = get_switch_order(Pike_sp[-1].u.array);    order_array(Pike_sp[-1].u.array, order);    free((char *) order);    for (i = 0; i < Pike_sp[-1].u.array->size; i++) -  encode_value2(ITEM(Pike_sp[-1].u.array)+i, data); +  encode_value2(ITEM(Pike_sp[-1].u.array)+i, data, 0);    pop_stack();    }    else {   #ifdef PIKE_NEW_MULTISETS    struct svalue ind;    union msnode *node = low_multiset_first (l->msd);    for (; node; node = low_multiset_next (node)) -  encode_value2 (low_use_multiset_index (node, ind), data); +  encode_value2 (low_use_multiset_index (node, ind), data, 0);   #else    for(i=0; i<l->ind->size; i++) -  encode_value2(ITEM(l->ind)+i, data); +  encode_value2(ITEM(l->ind)+i, data, 0);   #endif    }   #ifdef PIKE_NEW_MULTISETS    }   #endif    break;    }       case T_OBJECT:    check_stack(1);
pike.git/src/encode.c:768: Inside #if defined(AUTO_BIGNUM)
   if(is_bignum_object(val->u.object))    {    code_entry(TAG_OBJECT, 2, data);    /* 256 would be better, but then negative numbers    * won't work... /Hubbe    */    push_int(36);    apply(val->u.object,"digits",1);    if(Pike_sp[-1].type != T_STRING)    Pike_error("Gmp.mpz->digits did not return a string!\n"); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    break;    }   #endif       if (data->canonic)    Pike_error("Canonical encoding of objects not supported.\n");    push_svalue(val);    apply(data->codec, "nameof", 1);    EDB(5, fprintf(stderr, "%*s->nameof: ", data->depth, "");    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr););    switch(Pike_sp[-1].type)    {    case T_INT:    if(Pike_sp[-1].subtype == NUMBER_UNDEFINED)    {    int to_change = data->buf.s.len; -  struct svalue tmp=data->counter; -  tmp.u.integer--; +  struct svalue tmp = entry_id;       EDB(5,fprintf(stderr, "%*s(UNDEFINED)\n", data->depth, ""));       /* We have to remove ourself from the cache */    map_delete(data->encoded, val);       pop_stack();    push_svalue(val);    f_object_program(1);       /* Code the program */    code_entry(TAG_OBJECT, 3,data); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       push_svalue(val);       /* If we do not exist in cache, use backwards-    * compatible method, otherwise use newfangled    * style=3. -Hubbe    */    if(!low_mapping_lookup(data->encoded, val))    {
pike.git/src/encode.c:839:    mapping_insert(data->encoded, val, &tmp);    }    break;    }    /* FALL THROUGH */       default:    code_entry(TAG_OBJECT, 0,data);    break;    } -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    break;       case T_FUNCTION:    /* FIXME: Ought to have special treatment of trampolines. */    if (data->canonic)    Pike_error("Canonical encoding of functions not supported.\n");    check_stack(1);    push_svalue(val);    apply(data->codec,"nameof", 1);    if(Pike_sp[-1].type == T_INT && Pike_sp[-1].subtype==NUMBER_UNDEFINED)    {    if(val->subtype != FUNCTION_BUILTIN)    {    if(find_shared_string_identifier(ID_FROM_INT(val->u.object->prog, val->subtype)->name,    val->u.object->prog)==val->subtype)    {    /* We have to remove ourself from the cache for now */ -  struct svalue tmp=data->counter; -  tmp.u.integer--; +  struct svalue tmp = entry_id;    map_delete(data->encoded, val);       code_entry(TAG_FUNCTION, 1, data);    push_svalue(val);    Pike_sp[-1].type=T_OBJECT; -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_n_elems(3);       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp);    goto encode_done;    }    }    Pike_error("Cannot encode builtin functions.\n");    }       code_entry(TAG_FUNCTION, 0, data); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    break;          case T_PROGRAM:    {    int d;    if (val->u.program->id < PROG_DYNAMIC_ID_START) {    code_entry(TAG_PROGRAM, 3, data);    push_int(val->u.program->id); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    break;    }    if (data->canonic)    Pike_error("Canonical encoding of programs not supported.\n");    check_stack(1);    push_svalue(val);    apply(data->codec,"nameof", 1);    if(Pike_sp[-1].type == val->type)    Pike_error("Error in master()->nameof(), same type returned.\n");    if(Pike_sp[-1].type == T_INT && Pike_sp[-1].subtype == NUMBER_UNDEFINED)    {    struct program *p=val->u.program; -  +  pop_stack();    if( (p->flags & PROGRAM_HAS_C_METHODS) || p->event_handler )    {    if(p->parent)    {    /* We have to remove ourself from the cache for now */ -  struct svalue tmp=data->counter; -  tmp.u.integer--; +  struct svalue tmp = entry_id;    map_delete(data->encoded, val);       code_entry(TAG_PROGRAM, 2, data);    ref_push_program(p->parent); -  encode_value2(Pike_sp-1,data); +  encode_value2(Pike_sp-1,data, 0);       ref_push_program(p);    f_function_name(1);    if(Pike_sp[-1].type == PIKE_T_INT)    Pike_error("Cannot encode C programs.\n"); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);       pop_n_elems(3);       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp);    goto encode_done;    }    if( p->event_handler )    Pike_error("Cannot encode programs with event handlers.\n");    Pike_error("Cannot encode C programs.\n");    }    -  + #ifdef OLD_PIKE_ENCODE_PROGRAM       EDB(1, -  fprintf(stderr, "%*sencode: encoding program\n", +  fprintf(stderr, "%*sencode: encoding program in old style\n",    data->depth, ""));    - #ifdef OLD_PIKE_ENCODE_PROGRAM -  +     /* Type 1 -- Old-style encoding. */       code_entry(TAG_PROGRAM, 1, data);    f_version(0); -  encode_value2(Pike_sp-1,data); +  encode_value2(Pike_sp-1,data, 0);    pop_stack();    code_number(p->flags,data);    code_number(p->storage_needed,data);    code_number(p->xstorage,data); /**/    code_number(p->parent_info_storage,data); /**/       code_number(p->alignment_needed,data);    code_number(p->timestamp.tv_sec,data);    code_number(p->timestamp.tv_usec,data);       if(p->parent)    ref_push_program(p->parent);    else    push_int(0); -  encode_value2(Pike_sp-1,data); /**/ +  encode_value2(Pike_sp-1,data, 0); /**/    pop_stack();      #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    code_number( p->PIKE_CONCAT(num_,NAME), data);   #include "program_areas.h"       code_number(PIKE_BYTECODE_METHOD, data);      #ifdef ENCODE_PROGRAM   #ifdef PIKE_DEBUG
pike.git/src/encode.c:1034:    ref_push_function(p->inherits[d].parent,    p->inherits[d].parent_identifier);    EDB(3,fprintf(stderr,"INHERIT%x coded as func { %p, %d }\n",    p->id, p->inherits[d].parent, p->inherits[d].parent_identifier););    }else if(p->inherits[d].prog){    ref_push_program(p->inherits[d].prog);    }else{    Pike_error("Failed to encode inherit #%d\n", d);    push_int(0);    } -  encode_value2(Pike_sp-1,data); +  encode_value2(Pike_sp-1,data, 1);    pop_stack();       adddata3(p->inherits[d].name);       EDB(3,fprintf(stderr,"INHERIT%x > %d: %d id=%d\n",    p->id,d,    p->inherits[d].prog->num_identifiers,    p->inherits[d].prog->id););    }   
pike.git/src/encode.c:1066:    "(identifier='%s').\n",    p->identifiers[d].name->str);    }    }       for(d=0;d<NUM_LFUNS;d++)    code_number(p->lfuns[d], data);       for(d=0;d<p->num_constants;d++)    { -  encode_value2(& p->constants[d].sval, data); +  encode_value2(& p->constants[d].sval, data, 0);    adddata3(p->constants[d].name);    }      #else /* !OLD_PIKE_ENCODE_PROGRAM */    -  /* Type 4 -- Portable encoding. */ -  code_entry(type_to_tag(val->type), 4, data); +  /* Portable encoding (4 and 5). */    -  +  if (!force_dump) { +  /* Encode later (5). */ +  EDB(1, fprintf(stderr, "%*sencode: delayed encoding of program\n", +  data->depth, "")); +  code_entry (TAG_PROGRAM, 5, data); +  data->delayed = append_array (data->delayed, val); +  tmp = low_mapping_lookup (data->encoded, val); +  tmp->u.integer = -tmp->u.integer; +  goto encode_done; +  } +  +  EDB(1, fprintf(stderr, "%*sencode: encoding program in new style\n", +  data->depth, "")); +  code_entry(TAG_PROGRAM, 4, data); +     /* Byte-order. */    code_number(PIKE_BYTEORDER, data);       /* flags */    code_number(p->flags,data);       /* version */    f_version(0); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* parent */    if (p->parent) {    ref_push_program(p->parent);    } else {    push_int(0);    } -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* num_* */   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    code_number( p->PIKE_CONCAT(num_,NAME), data);   #include "program_areas.h"       /* Byte-code method    */    code_number(PIKE_BYTECODE_METHOD, data);
pike.git/src/encode.c:1141:    /* linenumbers */    adddata2(p->linenumbers, p->num_linenumbers);       {    struct svalue str_sval;    str_sval.type = T_STRING;    str_sval.subtype = 0;    /* strings */    for(d=0;d<p->num_strings;d++) {    str_sval.u.string = p->strings[d]; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);    }    }       EDB(5, dump_program_tables(p, data->depth));       /* Dump the identifiers in a portable manner... */    {    int inherit_num = 1;    struct svalue str_sval;    char *id_dumped = (char *) alloca(p->num_identifiers);
pike.git/src/encode.c:1174:    /* NOTE: d is incremented by hand inside the loop. */    for (d=0; d < p->num_identifier_references;)    {    int d_max = p->num_identifier_references;       /* Find insertion point of next inherit. */    if (inherit_num < p->num_inherits) {    d_max = p->inherits[inherit_num].identifier_ref_offset;    }    +  EDB (4, fprintf (stderr, "%*sencode: inherit_num: %d, d_max: %d\n", +  data->depth, "", inherit_num, d_max);); +     /* Fix locally defined identifiers. */    for (; d < d_max; d++) {    struct reference *ref = p->identifier_references + d;    struct inherit *inh = INHERIT_FROM_PTR(p, ref);    struct identifier *id = ID_FROM_PTR(p, ref);       /* Skip identifiers that haven't been overloaded. */    if (ref->id_flags & ID_INHERITED) continue;       EDB(3,
pike.git/src/encode.c:1251:       EDB(3,    fprintf(stderr, "%*sencode: encoding constant\n",    data->depth, ""));       code_number(ID_ENTRY_CONSTANT, data);    code_number(ref->id_flags, data);       /* name */    str_sval.u.string = id->name; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);       /* offset */    code_number(id->func.offset, data);       /* type */    ref_push_type_value(id->type); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* run-time type */    code_number(id->run_time_type, data);    } else if (IDENTIFIER_IS_PIKE_FUNCTION(id->identifier_flags)) {    /* Pike function */       EDB(3,    fprintf(stderr, "%*sencode: encoding function\n",    data->depth, ""));       code_number(ID_ENTRY_FUNCTION, data);    code_number(ref->id_flags, data);       /* name */    str_sval.u.string = id->name; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);       /* type */    ref_push_type_value(id->type); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* func_flags (aka identifier_flags) */    code_number(id->identifier_flags, data);       /* func */    code_number(id->func.offset, data);       /* opt_flags */    code_number(id->opt_flags, data);
pike.git/src/encode.c:1307:    /* Variable */    EDB(3,    fprintf(stderr, "%*sencode: encoding variable\n",    data->depth, ""));       code_number(ID_ENTRY_VARIABLE, data);    code_number(ref->id_flags, data);       /* name */    str_sval.u.string = id->name; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);       /* type */    ref_push_type_value(id->type); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();    }    }       /* Identifier reference number */    code_number(d, data);       next_identifier_ref:    ; /* C requires a statement after lables. */   #ifdef ENCODE_DEBUG
pike.git/src/encode.c:1367:       EDB(5,    fprintf(stderr, "%*sinherit_flags: %04x\n",    data->depth, "", inherit_flags_change));       /* Identifier reference level at insertion. */    code_number(d_max, data);       /* name */    str_sval.u.string = inh->name; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);       /* prog */    ref_push_program(inh->prog); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 1);    pop_stack();       /* parent */    if (inh->parent) {    ref_push_object(inh->parent);    } else {    push_int(0);    } -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    pop_stack();       /* parent_identifier */    code_number(inh->parent_identifier, data);       /* parent_offset */    code_number(inh->parent_offset, data);       /* Number of identifier references. */    code_number(inh->prog->num_identifier_references, data);
pike.git/src/encode.c:1417:    /* Encode the constant values table. */    {    struct svalue str_sval;    str_sval.type = T_STRING;    str_sval.subtype = 0;       /* constants */    for(d=0;d<p->num_constants;d++)    {    /* value */ -  encode_value2(&p->constants[d].sval, data); +  encode_value2(&p->constants[d].sval, data, 0);       /* name */    if (p->constants[d].name) {    str_sval.u.string = p->constants[d].name; -  encode_value2(&str_sval, data); +  encode_value2(&str_sval, data, 0);    } else {    push_int(0); -  encode_value2(Pike_sp-1, data); +  encode_value2(Pike_sp-1, data, 0);    dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--;    }    }    }   #endif /* OLD_PIKE_ENCODE_PROGRAM */    }else{    code_entry(TAG_PROGRAM, 0, data); -  encode_value2(Pike_sp-1, data); -  } +  encode_value2(Pike_sp-1, data, 0);    pop_stack(); -  +  }    break;    }    }      encode_done:;      #ifdef ENCODE_DEBUG    data->depth -= 2;   #endif   }      static void free_encode_data(struct encode_data *data)   {    toss_buffer(& data->buf);    free_mapping(data->encoded); -  +  free_array(data->delayed);   }      /*! @decl string encode_value(mixed value, object|void codec)    *!    *! Code a value into a string.    *!    *! This function takes a value, and converts it to a string. This string    *! can then be saved, sent to another Pike process, packed or used in    *! any way you like. When you want your value back you simply send this    *! string to @[decode_value()] and it will return the value you encoded.
pike.git/src/encode.c:1488:    *! when Pike programs are actually dumped in full, then the string    *! can probably only be read by the same pike version.    *!    *! @seealso    *! @[decode_value()], @[sprintf()], @[encode_value_canonic()]    */   void f_encode_value(INT32 args)   {    ONERROR tmp;    struct encode_data d, *data; +  int i;    data=&d;       check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT,   #ifdef ENCODE_DEBUG    /* This argument is only an internal debug helper.    * It's intentionally not part of the function    * prototype, to keep the argument position free for    * other uses in the future. */    BIT_VOID | BIT_INT,   #endif    0);       initialize_buf(&data->buf);    data->canonic = 0;    data->encoded=allocate_mapping(128); -  +  data->delayed = allocate_array (0);    data->counter.type=T_INT;    data->counter.u.integer=COUNTER_START;    if(args > 1)    {    data->codec=Pike_sp[1-args].u.object;    }else{    data->codec=get_master();    }   #ifdef ENCODE_DEBUG    data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0;    data->depth = -2;   #endif       SET_ONERROR(tmp, free_encode_data, data);    addstr("\266ke0", 4); -  encode_value2(Pike_sp-args, data); +  +  encode_value2(Pike_sp-args, data, 1); +  +  for (i = 0; i < data->delayed->size; i++) +  encode_value2 (ITEM(data->delayed) + i, data, 2); +     UNSET_ONERROR(tmp);       free_mapping(data->encoded);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));   }      /*! @decl string encode_value_canonic(mixed value, object|void codec)    *!
pike.git/src/encode.c:1549:    *! respect to the types of values it can encode. It will throw an error    *! if it can't encode to a canonical form.    *!    *! @seealso    *! @[encode_value()], @[decode_value()]    */   void f_encode_value_canonic(INT32 args)   {    ONERROR tmp;    struct encode_data d, *data; +  int i;    data=&d;       check_all_args("encode_value_canonic", args, BIT_MIXED, BIT_VOID | BIT_OBJECT,   #ifdef ENCODE_DEBUG    /* This argument is only an internal debug helper.    * It's intentionally not part of the function    * prototype, to keep the argument position free for    * other uses in the future. */    BIT_VOID | BIT_INT,   #endif    0);       initialize_buf(&data->buf);    data->canonic = 1;    data->encoded=allocate_mapping(128); -  +  data->delayed = allocate_array (0);    data->counter.type=T_INT;    data->counter.u.integer=COUNTER_START;    if(args > 1)    {    data->codec=Pike_sp[1-args].u.object;    }else{    data->codec=get_master();    }   #ifdef ENCODE_DEBUG    data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0;    data->depth = -2;   #endif       SET_ONERROR(tmp, free_encode_data, data);    addstr("\266ke0", 4); -  encode_value2(Pike_sp-args, data); +  +  encode_value2(Pike_sp-args, data, 1); +  +  for (i = 0; i < data->delayed->size; i++) +  encode_value2 (ITEM(data->delayed) + i, data, 2); +     UNSET_ONERROR(tmp);       free_mapping(data->encoded);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));   }         struct unfinished_prog_link
pike.git/src/encode.c:1975:    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.... */   #define decode_type(X,data) do { \    type_stack_mark(); \    low_decode_type(data); \    (X)=pop_unfinished_type(); \   } while(0)      static void cleanup_new_program_decode (int *orig_compilation_depth)
pike.git/src/encode.c:2062:   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; +  struct svalue *delayed_enc_val;      #ifdef ENCODE_DEBUG    data->depth += 2;   #endif       DECODE("decode_value2");    - #ifdef ENCODE_DEBUG -  if(data->debug) -  { -  if((what & TAG_MASK ) == TAG_AGAIN) -  fprintf(stderr, "%*sDecoding TAG_AGAIN from <%d>\n", -  data->depth, "", num); -  -  else -  if(data->debug > 1) -  fprintf(stderr, "%*sDecoding to <%d>: TAG%d (%d)\n", -  data->depth, "", data->counter.u.integer , -  what & TAG_MASK, num); -  } - #endif -  -  check_stack(1); -  +     switch(what & TAG_MASK)    { -  +  case TAG_DELAYED: +  EDB (2, fprintf(stderr, "%*sDecoding delay encoded from <%d>\n", +  data->depth, "", num);); +  entry_id.type = T_INT; +  entry_id.subtype = 0; +  entry_id.u.integer = num; +  if (!(delayed_enc_val = low_mapping_lookup (data->decoded, &entry_id))) +  Pike_error ("Failed to find previous record of delay encoded entry <%d>.\n", +  num); +  DECODE ("decode_value2"); +  break; +     case TAG_AGAIN: -  tmp.type=T_INT; -  tmp.subtype=0; -  tmp.u.integer=num; -  if((tmp2=low_mapping_lookup(data->decoded, &tmp))) +  EDB (1, fprintf(stderr, "%*sDecoding TAG_AGAIN from <%d>\n", +  data->depth, "", num);); +  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; +  default: +  entry_id = data->counter;    data->counter.u.integer++; -  +  /* Fall through. */ +  +  case TAG_TYPE: +  EDB (2, fprintf(stderr, "%*sDecoding to <%d>: TAG%d (%d)\n", +  data->depth, "", entry_id.u.integer , +  what & TAG_MASK, num);); +  /* Types are added to the encoded mapping AFTER they have been +  * encoded. */ +  delayed_enc_val = NULL; +  break; +  } +  +  check_stack(1); +  +  switch(what & TAG_MASK) +  { +  case TAG_INT:    push_int(num);    break;       case TAG_STRING:    {    struct pike_string *str; -  tmp.type = T_INT; -  tmp=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; -  data->counter.u.integer++; -  +     DECODE("float");       EDB(2,fprintf(stderr, "Exponent: %d\n", num));       if(!res)    {    DECLARE_INF    DECLARE_NAN       switch(num)
pike.git/src/encode.c:2183:    }       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 = data->counter;    data->counter.u.integer++;    }    break;       case TAG_ARRAY:    {    struct array *a;    TYPE_FIELD types;    if(num < 0)    Pike_error("Failed to decode array. (array size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    Pike_error("Failed to decode array. (not enough data)\n");       EDB(2,fprintf(stderr, "%*sDecoding array of size %d to <%d>\n", -  data->depth, "", num, data->counter.u.integer)); +  data->depth, "", num, entry_id.u.integer));       SETUP_DECODE_MEMOBJ(T_ARRAY, array, a, allocate_array(num),    free_svalues(ITEM(a), a->size, a->type_field));       types = 0;    for(e=0;e<num;e++)    {    decode_value2(data);    stack_pop_to_no_free (ITEM(a) + e);    types |= 1 << ITEM(a)[e].type;    }    a->type_field = types;    ref_push_array(a); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto decode_done;    }       case TAG_MAPPING:    {    struct mapping *m;    if(num<0)    Pike_error("Failed to decode mapping. (mapping size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    Pike_error("Failed to decode mapping. (not enough data)\n");       EDB(2,fprintf(stderr, "%*sDecoding mapping of size %d to <%d>\n", -  data->depth, "", num, data->counter.u.integer)); +  data->depth, "", num, entry_id.u.integer));       SETUP_DECODE_MEMOBJ(T_MAPPING, mapping, m, allocate_mapping(num), ; );       for(e=0;e<num;e++)    {    decode_value2(data);    decode_value2(data);    mapping_insert(m, Pike_sp-2, Pike_sp-1);    pop_n_elems(2);    }    ref_push_mapping(m); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto decode_done;    }       case TAG_MULTISET:    {    struct multiset *m;    struct array *a;    TYPE_FIELD types;    if(num<0)    Pike_error("Failed to decode multiset. (multiset size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    Pike_error("Failed to decode multiset. (not enough data)\n");       /* NOTE: This code knows stuff about the implementation of multisets...*/       EDB(2,fprintf(stderr, "%*sDecoding multiset of size %d to <%d>\n", -  data->depth, "", num, data->counter.u.integer)); +  data->depth, "", num, entry_id.u.integer));   #ifdef PIKE_NEW_MULTISETS    SETUP_DECODE_MEMOBJ (T_MULTISET, multiset, m,    allocate_multiset (0, 0, NULL), ;);    /* FIXME: This array could be avoided by building the multiset directly. */    a = low_allocate_array (num, 0);   #else    SETUP_DECODE_MEMOBJ(T_MULTISET, multiset, m,    allocate_multiset(low_allocate_array(num, 0)), ;);    a=m->ind;   #endif
pike.git/src/encode.c:2297: Inside #if defined(PIKE_NEW_MULTISETS)
   struct multiset *l = mkmultiset (a);    free_array (a);    /* This special case is handled efficiently by merge_multisets. */    merge_multisets (m, l, PIKE_MERGE_DESTR_A | PIKE_ARRAY_OP_ADD);    free_multiset (l);    }   #else    order_multiset(m);   #endif    ref_push_multiset(m); - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto decode_done;    }       case TAG_OBJECT:    { -  tmp=data->counter; -  data->counter.u.integer++; -  +     decode_value2(data);       switch(num)    {    case 0:    if(data->codec)    {    apply(data->codec,"objectof", 1);    }else{    fallback_codec();
pike.git/src/encode.c:2334:    /* decode_value_clone_object does not call __INIT, so    * we want to do that ourselves...    */    struct object *o=decode_value_clone_object(Pike_sp-1);       if (!o) {    if (data->pickyness)    decode_error (NULL, Pike_sp - 1,    "Failed to decode program for object. Got: ");    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_n_elems(2);    push_undefined();    break;    }       debug_malloc_touch(o);    pop_stack();
pike.git/src/encode.c:2364:    * 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)    decode_error(Pike_sp - 1, NULL,    "Cannot decode object without codec.\n");       fun = find_identifier("decode_object", data->codec->prog);
pike.git/src/encode.c:2420:    break;    }       if(Pike_sp[-1].type != T_OBJECT && data->pickyness)    decode_error(NULL, Pike_sp - 1, "Failed to decode object. Got: ");       break;    }       case TAG_FUNCTION: -  tmp=data->counter; -  data->counter.u.integer++; +     decode_value2(data);       switch(num)    {    case 0:    if(data->codec)    {    apply(data->codec,"functionof", 1);    }else{    fallback_codec();
pike.git/src/encode.c:2494:    case TAG_PROGRAM:    EDB(3,    fprintf(stderr, "%*s TAG_PROGRAM(%d)\n",    data->depth, "", num));    switch(num)    {    case 0:    {    struct program *p;    -  tmp=data->counter; -  data->counter.u.integer++; +     decode_value2(data);       if(data->codec)    {    apply(data->codec,"programof", 1);    }else{    fallback_codec();    }       p = program_from_svalue(Pike_sp-1);
pike.git/src/encode.c:2537:    struct program *p;    struct object *placeholder=0;    ONERROR err1, err2, err3, err4;      #ifdef _REENTRANT    ONERROR err;    low_init_threads_disable();    SET_ONERROR(err, do_enable_threads, 0);   #endif    +  fprintf (stderr, "Warning: Using old-style encoding\n"); +     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, &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:2562:    if(data->codec)    {    ref_push_program(p);    apply(data->codec, "__register_new_program", 1);       /* return a placeholder */    if(Pike_sp[-1].type == T_OBJECT)    {    placeholder=Pike_sp[-1].u.object;    if(placeholder->prog != null_program) -  Pike_error("Placeholder object is not a null_program clone!\n"); +  Pike_error("Placeholder object is not a null_program clone.\n");    dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--; -  }else{ +  } +  else if (Pike_sp[-1].type != T_INT || +  Pike_sp[-1].u.integer) +  Pike_error ("Expected placeholder object or zero " +  "from __register_new_program.\n"); +  else {    pop_stack();    }    }    }       if(placeholder)    SET_ONERROR(err4, zap_placeholder, placeholder);       decode_value2(data);    f_version(0);
pike.git/src/encode.c:3053:    l->prog=p;    l->next=data->unfinished_programs;    data->unfinished_programs=l;    }    }      #ifdef _REENTRANT    UNSET_ONERROR(err);    exit_threads_disable(NULL);   #endif - #ifdef ENCODE_DEBUG -  data->depth -= 2; - #endif -  return; +  goto decode_done;    }       case 2: -  tmp=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(Pike_sp[-1].type != T_PROGRAM && data->pickyness)    decode_error(NULL, Pike_sp - 1, "Failed to decode program. Got: ");    break;       case 3: -  tmp=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);    }    pop_stack();    ref_push_program(p);    } else {    decode_error(NULL, Pike_sp - 1,    "Failed to decode program by ID. Expected integer, got: ");    }    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, "", 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); +  +  /* Returns a placeholder. */ +  if (Pike_sp[-1].type == T_OBJECT) { +  if (Pike_sp[-1].u.object->prog != null_program) +  Pike_error ("Placeholder object is not a null_program clone.\n"); +  } +  else if (Pike_sp[-1].type != T_INT || +  Pike_sp[-1].u.integer) +  Pike_error ("Expected placeholder object or zero " +  "from __register_new_program.\n"); +  pop_stack(); +  } + #endif +  +  break; +  } +     case 4: /* New-style encoding. */    {    struct program *p;    ONERROR err;    int orig_compilation_depth;    int byteorder;    int bytecode_method;    int entry_type;    INT16 id_flags;    INT16 p_flags;
pike.git/src/encode.c:3116:   #include "program_areas.h"      #ifdef ENCODE_DEBUG    data->depth += 2;   #endif       /* Decode byte-order. */    decode_number(byteorder, data);       EDB(4, -  fprintf(stderr, "%*sByte order:%d\n", +  fprintf(stderr, "%*sbyte order:%d\n",    data->depth, "", byteorder));       if ((byteorder != PIKE_BYTEORDER)   #if (PIKE_BYTEORDER == 1234)    && (byteorder != 4321)   #else   #if (PIKE_BYTEORDER == 4321)    && (byteorder != 1234)   #endif   #endif
pike.git/src/encode.c:3138:    Pike_error("Unsupported byte-order. Native:%d Encoded:%d\n",    PIKE_BYTEORDER, byteorder);    }       /* Decode flags. */    decode_number(p_flags,data);    p_flags &= ~(PROGRAM_FINISHED | PROGRAM_OPTIMIZED |    PROGRAM_FIXED | PROGRAM_PASS_1_DONE);    p_flags |= PROGRAM_AVOID_CHECK;    +  if (delayed_enc_val) { +  EDB(2,fprintf(stderr, "%*sdecoding a delay encoded program: ", +  data->depth, ""); +  print_svalue(stderr, delayed_enc_val); +  fputc('\n', stderr);); +  if (delayed_enc_val->type != T_PROGRAM || +  delayed_enc_val->u.program->flags != PROGRAM_VIRGIN) { +  decode_error (NULL, delayed_enc_val, +  "Didn't get program embryo " +  "for delay encoded program <%d>: ", entry_id.u.integer); +  } +  add_ref (p = delayed_enc_val->u.program); +  } +  else +  p = NULL; +     /* Start the new program. */    orig_compilation_depth = compilation_depth;    compilation_depth = -1; -  low_start_new_program(NULL, NULL, 0, NULL); +  low_start_new_program(p, 1, NULL, 0, NULL);    p = Pike_compiler->new_program;       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; +  if (!delayed_enc_val) { +  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:3239:    }    for (e=0; e<(int)local_num_linenumbers; e++) {    char lineno_info;    lineno_info = *(data->data + data->ptr++);    add_to_linenumbers(lineno_info);    }       /* Now with the linenumber info in place it gets useful to    * include the program in error messages. */    +  EDB(2, +  fprintf(stderr, "%*sThe program is: ", data->depth, ""); +  push_program (p); +  print_svalue (stderr, --Pike_sp); +  fputc('\n', stderr)); +     /* 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) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
pike.git/src/encode.c:3521:       if (n < 0 || (n = override_identifier (&ref, id.name)) < 0) {    n = p->num_identifier_references;    add_to_identifier_references(ref);    }       if (no != n) {    ref_push_program (p);    ref_push_string (id.name);    decode_error(Pike_sp - 2, Pike_sp - 1, -  "Bad function identifier offset %d for ", no); +  "Bad function identifier offset " +  "(expected %d, got %d) for ", no, n);    }       add_to_identifiers(id);    dmalloc_touch_svalue(Pike_sp-1);    dmalloc_touch_svalue(Pike_sp-2);    Pike_sp -= 2;    }    break;    case ID_ENTRY_INHERIT:    {
pike.git/src/encode.c:3639:    data->depth-=2;   #endif       UNSET_ONERROR(err);       /* De-kludge to get end_first_pass() to free the program. */    Pike_compiler->num_parse_error--;       p->flags |= PROGRAM_PASS_1_DONE;    -  EDB(5, dump_program_tables(p, data->depth)); -  +     /* Fixate & optimize    *    * lfuns and identifier_index    */    ref_push_program (p);    if (!(p = end_first_pass(2))) {    decode_error(Pike_sp - 1, NULL, "Failed to decode program.\n");    }    pop_stack();    compilation_depth = orig_compilation_depth;    push_program(p);    -  +  EDB(5, dump_program_tables(p, data->depth)); + #ifdef PIKE_DEBUG +  check_program (p); + #endif +     /* Verify... */   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (PIKE_CONCAT(local_num_, NAME) != p->PIKE_CONCAT(num_,NAME)) { \    ref_push_program (p); \    decode_error(Pike_sp - 1, NULL, \    "Value mismatch for num_" TOSTR(NAME) ": %d != %d\n", \    PIKE_CONCAT(local_num_, NAME), \    p->PIKE_CONCAT(num_, NAME)); \    }   #include "program_areas.h"
pike.git/src/encode.c:3701:       /* The program should be consistent now. */    p->flags &= ~PROGRAM_AVOID_CHECK;       EDB(5, fprintf(stderr, "%*sProgram flags: 0x%04x\n",    data->depth, "", p->flags));      #ifdef ENCODE_DEBUG    data->depth -= 2;   #endif +  goto decode_done;    } -  break; +        default:    Pike_error("Cannot decode program encoding type %d\n",num);    }    break;       default:    Pike_error("Failed to restore string. (Illegal type)\n");    }    -  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. */
pike.git/src/encode.c:3833:      static INT32 my_decode(struct pike_string *tmp,    struct object *codec   #ifdef ENCODE_DEBUG    , int debug   #endif    )   {    ONERROR err;    struct decode_data *data; +  int e; +  struct keypair *k;       /* Attempt to avoid infinite recursion on circular structures. */    for (data = current_decode; data; data=data->next) {    if (data->raw == tmp && data->codec == codec   #ifdef PIKE_THREADS    && data->thread_state == Pike_interpreter.thread_state   #endif    ) {    struct svalue *res;    struct svalue val = {
pike.git/src/encode.c:3901:       current_decode = data;       SET_ONERROR(err, free_decode_data, data);       init_supporter(& data->supporter,    (supporter_callback *) re_decode,    (void *)data);       decode_value2(data); +  while (data->ptr < data->len) { +  decode_value2 (data); +  pop_stack(); +  }    -  + #ifdef PIKE_DEBUG +  NEW_MAPPING_LOOP (data->decoded->data) { +  if (k->val.type == T_PROGRAM && +  !(k->val.u.program->flags & PROGRAM_FINISHED)) { +  decode_error (NULL, &k->val, +  "Got unfinished program <%"PRINTPIKEINT"d> after decode: ", +  k->ind.u.integer); +  } +  } + #endif +     CALL_AND_UNSET_ONERROR(err);    return 1;   }      /* Compatibilidy decoder */      static unsigned char extract_char(char **v, ptrdiff_t *l)   {    if(!*l) Pike_error("Format error, not enough place for char.\n");    else (*l)--;