pike.git / src / encode.c

version» Context lines:

pike.git/src/encode.c:18:   #include "pike_error.h"   #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"    - RCSID("$Id: encode.c,v 1.107 2001/07/03 15:04:51 grubba Exp $"); + RCSID("$Id: encode.c,v 1.108 2001/07/10 11:57:26 mast Exp $");      /* #define ENCODE_DEBUG */      #ifdef ENCODE_DEBUG - #define EDB(X) X + /* Pass a nonzero integer as the third arg to encode_value, +  * encode_value_canonic and decode_value to activate this debug. */ + #define EDB(X) do if (data->debug) {X;} while (0)   #else - #define EDB(X) + #define EDB(X) do {} while (0)   #endif      /* The sp macro conflicts with Solaris 2.5.1's <sys/conf.h>. */   #ifdef sp   #undef sp   #define STACKPOINTER_WAS_DEFINED   #endif /* sp */      #ifdef _AIX   #include <net/nh.h>
pike.git/src/encode.c:120:   #define MAX_SMALL (1<<(8-SIZE_SHIFT))   #define COUNTER_START -MAX_SMALL      struct encode_data   {    int canonic;    struct object *codec;    struct svalue counter;    struct mapping *encoded;    dynamic_buffer buf; + #ifdef ENCODE_DEBUG +  int debug, depth; + #endif   };      static void encode_value2(struct svalue *val, struct encode_data *data);      #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
pike.git/src/encode.c:190:    if (type == T_TYPE) return TAG_TYPE;    return type;   }   static int (*tag_to_type)(int) = type_to_tag;      /* Let's cram those bits... */   static void code_entry(int tag, INT64 num, struct encode_data *data)   {    int t;    EDB( -  fprintf(stderr,"encode: code_entry(tag=%d (%s), num=%ld)\n", -  tag, +  fprintf(stderr,"%*sencode: code_entry(tag=%d (%s), num=%ld)\n", +  data->depth, "", tag,    get_name_of_type(tag_to_type(tag)),    (long)num) );    if(num<0)    {    tag |= TAG_NEG;    num = ~num;    }       if(num < MAX_SMALL)    {
pike.git/src/encode.c:525:   {    static struct svalue dested = {    T_INT, NUMBER_DESTRUCTED,   #ifdef HAVE_UNION_INIT    {0}, /* Only to avoid warnings. */   #endif    };    INT32 i;    struct svalue *tmp;    + #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)))    { -  +  EDB(fprintf(stderr, "%*sEncoding TAG_AGAIN to <%d>\n", +  data->depth, "", tmp->u.integer));    code_entry(TAG_AGAIN, tmp->u.integer, data); -  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;    }else if (val->type != T_TYPE) { -  +  EDB(fprintf(stderr, "%*sEncoding to <%d>: ", +  data->depth, "", data->counter.u.integer); +  print_svalue(stderr, val); +  fputc('\n', stderr););    mapping_insert(data->encoded, val, &data->counter);    data->counter.u.integer++;    }          switch(val->type)    {    case T_INT:    /* FIXME:    * if INT_TYPE is larger than 32 bits (not currently happening)
pike.git/src/encode.c:563:    break;       case T_TYPE:    /* NOTE: Types are added to the encoded mapping AFTER they have    * been encoded, to simplify decoding.    */    if (data->canonic)    Pike_error("Canonical encoding of the type type not supported.\n");    code_entry(TAG_TYPE, 0, data); /* Type encoding #0 */    encode_type(val->u.type, data); +  EDB(fprintf(stderr, "%*sEncoded type to <%d>: ", +  data->depth, "", data->counter.u.integer); +  print_svalue(stderr, val); +  fputc('\n', stderr););    mapping_insert(data->encoded, val, &data->counter);    data->counter.u.integer++;    break;       case T_FLOAT:    {    if(val->u.float_number==0.0)    {    code_entry(TAG_FLOAT,0,data);    code_entry(TAG_FLOAT,0,data);
pike.git/src/encode.c:759:    code_entry(type_to_tag(val->type), 1, data);    push_svalue(val);    Pike_sp[-1].type=T_OBJECT;    encode_value2(Pike_sp-1, data);    ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name);    encode_value2(Pike_sp-1, data);    pop_n_elems(3);       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp); + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;    }    }    Pike_error("Encoding of efuns is not supported yet.\n");    }       code_entry(type_to_tag(val->type), 0,data);    encode_value2(Pike_sp-1, data);    pop_stack();    break;
pike.git/src/encode.c:815:    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);       pop_n_elems(3);       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp); + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;    }    if( p->event_handler )    Pike_error("Cannot encode programs with event handlers.\n");    Pike_error("Cannot encode C programs.\n");    }    /*FIXME: save p->parent!! */    code_entry(type_to_tag(val->type), 1,data);    f_version(0);    encode_value2(Pike_sp-1,data);
pike.git/src/encode.c:864:       for(d=0;d<p->num_identifier_references;d++)    {    code_number(p->identifier_references[d].inherit_offset,data);    code_number(p->identifier_references[d].identifier_offset,data);    code_number(p->identifier_references[d].id_flags,data);    EDB(fprintf(stderr,"IDREF%x > %d: { %d, %d, %d }\n",    p->id,d,    p->identifier_references[d].inherit_offset,    p->identifier_references[d].identifier_offset, -  p->identifier_references[d].id_flags);) +  p->identifier_references[d].id_flags););    }       for(d=0;d<p->num_strings;d++) adddata(p->strings[d]);       for(d=0;d<p->num_inherits;d++)    {    code_number(p->inherits[d].inherit_level,data);    code_number(p->inherits[d].identifier_level,data);    code_number(p->inherits[d].parent_offset,data);    code_number(p->inherits[d].parent_identifier,data);    code_number(p->inherits[d].storage_offset,data);       if(p->inherits[d].parent)    {    ref_push_object(p->inherits[d].parent);    Pike_sp[-1].subtype=p->inherits[d].parent_identifier;    Pike_sp[-1].type=T_FUNCTION;    EDB(fprintf(stderr,"INHERIT%x coded as func { %p, %d }\n", -  p->id, p->inherits[d].parent, p->inherits[d].parent_identifier);) +  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);    pop_stack();       adddata3(p->inherits[d].name);       EDB(fprintf(stderr,"INHERIT%x > %d: %d id=%d\n",    p->id,d,    p->inherits[d].prog->num_identifiers, -  p->inherits[d].prog->id);) +  p->inherits[d].prog->id););    }       for(d=0;d<p->num_identifiers;d++)    {    adddata(p->identifiers[d].name);    encode_type(p->identifiers[d].type, data);    code_number(p->identifiers[d].identifier_flags,data);    code_number(p->identifiers[d].run_time_type,data);    code_number(p->identifiers[d].opt_flags,data);    if (!(p->identifiers[d].identifier_flags & IDENTIFIER_C_FUNCTION)) {
pike.git/src/encode.c:933:    for(d=0;d<NUM_LFUNS;d++)    code_number(p->lfuns[d], data);    }else{    code_entry(type_to_tag(val->type), 0,data);    encode_value2(Pike_sp-1, data);    }    pop_stack();    break;    }    } +  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif   }      static void free_encode_data(struct encode_data *data)   {    toss_buffer(& data->buf);    free_mapping(data->encoded);   }      /*! @decl string encode_value(mixed value, object|void codec)    *!
pike.git/src/encode.c:977:    *!    *! @seealso    *! @[decode_value()], @[sprintf()], @[encode_value_canonic()]    */   void f_encode_value(INT32 args)   {    ONERROR tmp;    struct encode_data d, *data;    data=&d;    + #ifdef ENCODE_DEBUG +  check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, +  BIT_VOID | BIT_INT, 0); + #else    check_all_args("encode_value", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0); -  + #endif       initialize_buf(&data->buf);    data->canonic = 0;    data->encoded=allocate_mapping(128);    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);    UNSET_ONERROR(tmp);       free_mapping(data->encoded);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));
pike.git/src/encode.c:1026:    *!    *! @seealso    *! @[encode_value()], @[decode_value()]    */   void f_encode_value_canonic(INT32 args)   {    ONERROR tmp;    struct encode_data d, *data;    data=&d;    + #ifdef ENCODE_DEBUG +  check_all_args("encode_value_canonic", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, +  BIT_VOID | BIT_INT, 0); + #else    check_all_args("encode_value_canonic", args, BIT_MIXED, BIT_VOID | BIT_OBJECT, 0); -  + #endif       initialize_buf(&data->buf);    data->canonic = 1;    data->encoded=allocate_mapping(128);    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);    UNSET_ONERROR(tmp);       free_mapping(data->encoded);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));
pike.git/src/encode.c:1070:    unsigned char *data;    ptrdiff_t len;    ptrdiff_t ptr;    struct mapping *decoded;    struct unfinished_prog_link *unfinished_programs;    struct svalue counter;    struct object *codec;    int pickyness;    struct pike_string *raw;    struct decode_data *next; + #ifdef ENCODE_DEBUG +  int debug, depth; + #endif   };      static void decode_value2(struct decode_data *data);      static void fallback_codec(void)   {    size_t x;    push_constant_text(".");    f_divide(2);    f_reverse(1);
pike.git/src/encode.c:1102:   {    if(data->ptr >= data->len)    Pike_error("Format error, not enough data in string.\n");    return data->data [ data->ptr++ ];   }      #define GETC() my_extract_char(data)      #define DECODE(Z) do { \    EDB( \ -  fprintf(stderr,"decode(%s) at %d: ",(Z),__LINE__)); \ +  fprintf(stderr,"%*sdecode(%s) at %d: ", \ +  data->depth,"",(Z),__LINE__)); \    what=GETC(); \    e=what>>SIZE_SHIFT; \    numh=0; \    if(what & TAG_SMALL) { \    num=e; \    } else { \    INT32 numl; \    num=0; \    while(e > 4) { \    numh = (numh<<8) + (GETC()+1); \
pike.git/src/encode.c:1462:   #ifdef PIKE_DEBUG   #undef decode_value2   #define decode_value2(X) do { struct svalue *_=Pike_sp; decode_value2_(X); if(Pike_sp!=_+1) fatal("decode_value2 failed!\n"); } while(0)   #endif         {    INT32 what, e, num, numh;    struct svalue tmp, *tmp2;    + #ifdef ENCODE_DEBUG +  data->depth += 2; + #endif +     DECODE("decode_value2");       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)))    {    push_svalue(tmp2);    }else{ -  Pike_error("Failed to decode string. (invalid T_AGAIN)\n"); +  Pike_error("Failed to decode TAG_AGAIN entry <%d>.\n", num);    } -  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;       case TAG_INT:    tmp.type = T_INT;    tmp=data->counter;    data->counter.u.integer++;    push_int(num);    break;       case TAG_STRING:
pike.git/src/encode.c:1546:    struct array *a;    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");       tmp.type=T_ARRAY;    tmp.u.array=a=allocate_array(num); +  EDB(fprintf(stderr, "%*sDecoding array of size %d to <%d>\n", +  data->depth, "", num, data->counter.u.integer));    mapping_insert(data->decoded, & data->counter, &tmp);    data->counter.u.integer++;       /* Since a reference to the array is stored in the mapping, we can    * safely decrease this reference here. Thus it will be automatically    * freed if something goes wrong.    */    a->refs--;       for(e=0;e<num;e++)    {    decode_value2(data);    ITEM(a)[e]=Pike_sp[-1];    Pike_sp--;    dmalloc_touch_svalue(Pike_sp);    }    ref_push_array(a); -  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;    }       case TAG_MAPPING:    {    struct mapping *m;    if(num<0)    Pike_error("Failed to decode string. (mapping size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    Pike_error("Failed to decode mapping. (not enough data)\n");       m=allocate_mapping(num);    tmp.type=T_MAPPING;    tmp.u.mapping=m; -  +  EDB(fprintf(stderr, "%*sDecoding mapping of size %d to <%d>\n", +  data->depth, "", num, data->counter.u.integer));    mapping_insert(data->decoded, & data->counter, &tmp);    data->counter.u.integer++;    m->refs--;       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;    }       case TAG_MULTISET:    {    struct multiset *m;    struct array *a;    if(num<0)    Pike_error("Failed to decode string. (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...*/    a = low_allocate_array(num, 0);    m = allocate_multiset(a);    tmp.type = T_MULTISET;    tmp.u.multiset = m; -  +  EDB(fprintf(stderr, "%*sDecoding multiset of size %d to <%d>\n", +  data->depth, "", num, data->counter.u.integer));    mapping_insert(data->decoded, & data->counter, &tmp);    data->counter.u.integer++;    debug_malloc_touch(m);       for(e=0;e<num;e++)    {    decode_value2(data);    a->item[e] = sp[-1];    sp--;    dmalloc_touch_svalue(sp);    }    array_fix_type_field(a);    order_multiset(m);    push_multiset(m); -  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;    }          case TAG_OBJECT:    tmp=data->counter;    data->counter.u.integer++;    decode_value2(data);       switch(num)
pike.git/src/encode.c:1647:    {    apply(data->codec,"objectof", 1);    }else{    fallback_codec();    }    break;       case 1:    if(IS_ZERO(Pike_sp-1))    { +  EDB(fprintf(stderr, "%*sDecoded a failed object to <%d>: ", +  data->depth, "", tmp.u.integer); +  print_svalue(stderr, Pike_sp-1); +  fputc('\n', stderr););    mapping_insert(data->decoded, &tmp, Pike_sp-1);    decode_value2(data);    pop_stack();    }else{    f_call_function(1); -  +  EDB(fprintf(stderr, "%*sDecoded an object to <%d>: ", +  data->depth, "", tmp.u.integer); +  print_svalue(stderr, Pike_sp-1); +  fputc('\n', stderr););    mapping_insert(data->decoded, &tmp, Pike_sp-1);    push_svalue(Pike_sp-1);    decode_value2(data);    if(!data->codec)    Pike_error("Failed to decode (no codec)\n");    apply(data->codec,"decode_object",2);    pop_stack();    }    if(data->pickyness && Pike_sp[-1].type != T_OBJECT)    Pike_error("Failed to decode object.\n"); -  + #ifdef ENCODE_DEBUG +  data->depth -= 2; + #endif    return;      #ifdef AUTO_BIGNUM    /* It is possible that we should do this even without    * AUTO_BIGNUM /Hubbe    * However, that requires that some of the bignum functions    * are always available...    */    case 2:    {
pike.git/src/encode.c:1794: Inside #if defined(_REENTRANT)
   low_init_threads_disable();    SET_ONERROR(err, do_enable_threads, 0);   #endif       p=low_allocate_program();    SET_ONERROR(err3, zap_unfinished_program, p);       debug_malloc_touch(p);    tmp.type=T_PROGRAM;    tmp.u.program=p; +  EDB(fprintf(stderr, "%*sDecoding a program to <%d>: ", +  data->depth, "", data->counter.u.integer); +  print_svalue(stderr, &tmp); +  fputc('\n', stderr););    mapping_insert(data->decoded, & data->counter, &tmp);    data->counter.u.integer++;    p->refs--;       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:1924:    p->identifier_references[d].inherit_offset=0;    Pike_error("Malformed program in decode.\n");    }    decode_number(p->identifier_references[d].identifier_offset,data);    decode_number(p->identifier_references[d].id_flags,data);       EDB(fprintf(stderr,"IDREF%x < %d: { %d, %d, %d }\n",    p->id,d,    p->identifier_references[d].inherit_offset,    p->identifier_references[d].identifier_offset, -  p->identifier_references[d].id_flags); ) +  p->identifier_references[d].id_flags); );    }       debug_malloc_touch(p);    for(d=0;d<p->num_strings;d++)    getdata(p->strings[d]);       debug_malloc_touch(p);    debug_malloc_touch(dat);       data->pickyness++;
pike.git/src/encode.c:1965:    Pike_error("Program decode failed!\n");    p->refs--;    }       switch(Pike_sp[-1].type)    {    case T_FUNCTION:    if(Pike_sp[-1].subtype == FUNCTION_BUILTIN)    Pike_error("Failed to decode parent.\n");    -  EDB( fprintf(stderr,"INHERIT%x = func { %x, %d} \n",p->id,Pike_sp[-1].u.object, Pike_sp[-1].subtype); ) +  EDB( fprintf(stderr,"INHERIT%x = func { %p, %d} \n",p->id,Pike_sp[-1].u.object, Pike_sp[-1].subtype); );       p->inherits[d].parent_identifier=Pike_sp[-1].subtype;    p->inherits[d].prog=program_from_svalue(Pike_sp-1);    if(!p->inherits[d].prog)    Pike_error("Failed to decode parent.\n");    add_ref(p->inherits[d].prog);    p->inherits[d].parent=Pike_sp[-1].u.object;    Pike_sp--;    dmalloc_touch_svalue(Pike_sp);    break;       case T_PROGRAM: -  EDB( fprintf(stderr,"INHERIT%x = prog\n",p->id); ) +  EDB( fprintf(stderr,"INHERIT%x = prog\n",p->id); );    p->inherits[d].prog=Pike_sp[-1].u.program;    Pike_sp--;    dmalloc_touch_svalue(Pike_sp);    break;    default:    Pike_error("Failed to decode inheritance.\n");    }       getdata3(p->inherits[d].name);       EDB( fprintf(stderr,"INHERIT%x < %d: %d id=%d\n",    p->id,d,    p->inherits[d].prog->num_identifiers, -  p->inherits[d].prog->id); ) +  p->inherits[d].prog->id); );    }       debug_malloc_touch(dat);          SET_ONERROR(err1, restore_type_stack, Pike_compiler->type_stackp);    SET_ONERROR(err2, restore_type_mark, Pike_compiler->pike_type_mark_stackp);       debug_malloc_touch(p);    for(d=0;d<p->num_identifiers;d++)
pike.git/src/encode.c:2113:    l=ALLOC_STRUCT(unfinished_prog_link);    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;    }       case 2:    tmp=data->counter;    data->counter.u.integer++;    decode_value2(data);    decode_value2(data);    if(Pike_sp[-2].type==T_INT)    {
pike.git/src/encode.c:2159:       default:    Pike_error("Cannot decode program encoding type %d\n",num);    }    break;       default:    Pike_error("Failed to restore string. (Illegal type)\n");    }    +  EDB(fprintf(stderr, "%*sDecoded to <%d>: ", data->depth, "", tmp.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   }         static struct decode_data *current_decode = NULL;      static void free_decode_data(struct decode_data *data)   {    free_mapping(data->decoded);    while(data->unfinished_programs)    {
pike.git/src/encode.c:2193: Inside #if defined(PIKE_DEBUG)
   }   #ifdef PIKE_DEBUG    if (!d) {    fatal("Decode data fell off the stack!\n");    }   #endif /* PIKE_DEBUG */    }   }      static INT32 my_decode(struct pike_string *tmp, -  struct object *codec) +  struct object *codec + #ifdef ENCODE_DEBUG +  , int debug + #endif +  )   {    ONERROR err;    struct decode_data d, *data;       /* Attempt to avoid infinite recursion on circular structures. */    for (data = current_decode; data; data=data->next) {    if (data->raw == tmp) {    struct svalue *res;    struct svalue val = {    T_INT, NUMBER_NUMBER,
pike.git/src/encode.c:2229:    data->counter.type=T_INT;    data->counter.u.integer=COUNTER_START;    data->data=(unsigned char *)tmp->str;    data->len=tmp->len;    data->ptr=0;    data->codec=codec;    data->pickyness=0;    data->unfinished_programs=0;    data->raw = tmp;    data->next = current_decode; + #ifdef ENCODE_DEBUG +  data->debug = debug; +  data->depth = -2; + #endif       if (tmp->size_shift) return 0;    if(data->len < 5) return 0;    if(GETC() != 182 ||    GETC() != 'k' ||    GETC() != 'e' ||    GETC() != '0')    return 0;       data->decoded=allocate_mapping(128);
pike.git/src/encode.c:2385:    *! If no codec is specified, the current master object will be used as codec.    *!    *! @seealso    *! @[encode_value()], @[encode_value_canonic()]    */   void f_decode_value(INT32 args)   {    struct pike_string *s;    struct object *codec;    + #ifdef ENCODE_DEBUG +  int debug;    check_all_args("decode_value", args, -  +  BIT_STRING, BIT_VOID | BIT_OBJECT | BIT_INT, BIT_VOID | BIT_INT, 0); +  debug = args > 2 ? Pike_sp[2-args].u.integer : 0; + #else +  check_all_args("decode_value", args,    BIT_STRING, BIT_VOID | BIT_OBJECT | BIT_INT, 0); -  + #endif       s = Pike_sp[-args].u.string;    if(args<2)    {    codec=get_master();    }    else if(Pike_sp[1-args].type == T_OBJECT)    {    codec=Pike_sp[1-args].u.object;    }    else    {    codec=0;    }    -  if(!my_decode(s, codec)) +  if(!my_decode(s, codec + #ifdef ENCODE_DEBUG +  , debug + #endif +  ))    {    char *v=s->str;    ptrdiff_t l=s->len;    rec_restore_value(&v, &l);    }    assign_svalue(Pike_sp-args-1, Pike_sp-1);    pop_n_elems(args);   }