Branch: Tag:

2003-06-12

2003-06-12 18:42:56 by Martin Stjernholm <mast@lysator.liu.se>

Sorry, checked in the wrong working copy again..

Rev: src/encode.c:1.189

2:   || 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.188 2003/06/12 14:13:49 grubba Exp $ + || $Id: encode.c,v 1.189 2003/06/12 18:42:56 mast Exp $   */      #include "global.h"
27:   #include "bignum.h"   #include "pikecode.h"    - RCSID("$Id: encode.c,v 1.188 2003/06/12 14:13:49 grubba Exp $"); + RCSID("$Id: encode.c,v 1.189 2003/06/12 18:42:56 mast Exp $");      /* #define ENCODE_DEBUG */   
1506:    for(d=0;d<p->num_constants;d++)    {    /* value */ -  /* Must force encoding of constants. They typically are -  * inner classes which must be finished before this -  * program is, since an object might be created for it -  * immediately afterwards which instantiate the inner -  * classes. */ -  encode_value2(&p->constants[d].sval, data, 1); +  encode_value2(&p->constants[d].sval, data, 0);       /* name */    if (p->constants[d].name) {
1742:    struct unfinished_obj_link *unfinished_objects;    struct svalue counter;    struct object *codec; -  struct program *target_prog; -  struct object *placeholder; -  struct array *delayed; +     int pickyness;    int pass;    struct pike_string *raw;
1758:    struct Supporter supporter;   };    - static void decode_value2(struct decode_data *data, int force_decode); + static void decode_value2(struct decode_data *data);      static int my_extract_char(struct decode_data *data)   {
2018:    break;       case PIKE_T_NAME: -  decode_value2(data, 0); +  decode_value2(data);       if (Pike_sp[-1].type != PIKE_T_STRING) {    Pike_error("decode_value(): Type name is not a string (%s)\n",
2033:    {    int flag = GETC();    -  decode_value2(data, 0); +  decode_value2(data);    switch(Pike_sp[-1].type)    {    case T_INT:
2072:   }       + static void zap_placeholder(struct object *placeholder) + { +  /* fprintf(stderr, "Destructing placeholder.\n"); */ +  if (placeholder->storage) { +  debug_malloc_touch(placeholder); +  destruct(placeholder); +  } else { +  free_program(placeholder->prog); +  placeholder->prog = NULL; +  debug_malloc_touch(placeholder); +  } +  free_object(placeholder); + } +    static int init_placeholder(struct object *placeholder);      
2083:    { \    tmp=*tmpptr; \    VAR=tmp.u.U; \ -  {SCOUR;} \ +  SCOUR; \    }else{ \    tmp.type=TYPE; \ -  {ALLOCATE;} \ -  tmp.u.U=VAR; \ +  tmp.u.U=VAR=ALLOCATE; \    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 \
2106:      static void cleanup_new_program_decode (int *orig_compilation_depth)   { - #if 0 -  ref_push_program (Pike_compiler->new_program); -  /* FIXME: Shouldn't the compilation handler be used here? */ -  SAFE_APPLY_MASTER("unregister",1); -  pop_stack(); - #endif -  +     end_first_pass(0);    compilation_depth = *orig_compilation_depth;   }
2162:    pike_throw();   }    - /* force_decode == 0: A placeholder (object or program) suffices. -  * force_decode == 1: Must have the real object. */ - static void decode_value2(struct decode_data *data, int force_decode) + static void decode_value2(struct decode_data *data)      #ifdef PIKE_DEBUG   #undef decode_value2 - #define decode_value2(X, Y) do { \ -  struct svalue *_=Pike_sp; \ -  decode_value2_(X, Y); \ -  if(Pike_sp!=_+1) \ -  Pike_fatal("decode_value2 failed!\n"); \ -  } while(0) + #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 entry_id, *tmp2;
2323:    EDB(2,fprintf(stderr, "%*sDecoding array of size %d to <%d>\n",    data->depth, "", num, entry_id.u.integer));    -  SETUP_DECODE_MEMOBJ(T_ARRAY, array, a, a = allocate_array(num), +  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, 0); +  decode_value2(data);    stack_pop_to_no_free (ITEM(a) + e);    types |= 1 << ITEM(a)[e].type;    }
2351:    EDB(2,fprintf(stderr, "%*sDecoding mapping of size %d to <%d>\n",    data->depth, "", num, entry_id.u.integer));    -  SETUP_DECODE_MEMOBJ(T_MAPPING, mapping, m, m = allocate_mapping(num), ; ); +  SETUP_DECODE_MEMOBJ(T_MAPPING, mapping, m, allocate_mapping(num), ; );       for(e=0;e<num;e++)    { -  decode_value2(data, 0); -  decode_value2(data, 0); +  decode_value2(data); +  decode_value2(data);    mapping_insert(m, Pike_sp-2, Pike_sp-1);    pop_n_elems(2);    }
2382: Inside #if defined(PIKE_NEW_MULTISETS)
   data->depth, "", num, entry_id.u.integer));   #ifdef PIKE_NEW_MULTISETS    SETUP_DECODE_MEMOBJ (T_MULTISET, multiset, m, -  m = allocate_multiset (0, 0, NULL), ;); +  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, -  m = allocate_multiset(low_allocate_array(num, 0)), ;); +  allocate_multiset(low_allocate_array(num, 0)), ;);    a=m->ind;   #endif       types = 0;    for(e=0;e<num;e++)    { -  decode_value2(data, 0); +  decode_value2(data);    stack_pop_to_no_free (ITEM(a) + e);    types |= 1 << ITEM(a)[e].type;    }
2416:       case TAG_OBJECT:    { +  decode_value2(data); +     switch(num)    {    case 0: -  decode_value2(data, 0); -  push_int (!force_decode); -  apply(data->codec,"objectof", 2); +  apply(data->codec,"objectof", 1);    break;       case 1:    {    int fun; -  struct object *o; +     /* decode_value_clone_object does not call __INIT, so    * we want to do that ourselves...    */ -  decode_value2(data, 1); -  o = decode_value_clone_object(Pike_sp-1); +  struct object *o=decode_value_clone_object(Pike_sp-1);       if (!o) {    if (data->pickyness)
2442:    data->depth, "", entry_id.u.integer);    print_svalue(stderr, Pike_sp-1);    fputc('\n', stderr);); -  decode_value2(data, 0); +  decode_value2(data);    pop_n_elems(2);    push_undefined();    break;
2474:    fputc('\n', stderr););       ref_push_object(o); -  decode_value2(data, 0); +  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);    if (fun < 0)
2495: Inside #if defined(AUTO_BIGNUM)
   */    case 2:    { -  decode_value2(data, 0); +     check_stack(2);    /* 256 would be better, but then negative numbers    * doesn't work... /Hubbe
2507:      #endif    case 3: -  decode_value2(data, 0); +     pop_stack(); -  decode_value2(data, 0); +  decode_value2(data);    break;       default:
2524:    }       case TAG_FUNCTION: +  decode_value2(data); +     switch(num)    {    case 0: -  decode_value2(data, 0); -  push_int (0); -  apply(data->codec,"functionof", 2); +  apply(data->codec,"functionof", 1);    break;       case 1: {    struct program *p; -  decode_value2(data, 1); +     if(Pike_sp[-1].type != T_OBJECT && data->pickyness)    decode_error(NULL, Pike_sp - 1,    "Failed to decode function object. Got: ");    -  decode_value2(data, 0); +  decode_value2(data);    if(Pike_sp[-1].type != T_STRING && data->pickyness)    decode_error(NULL, Pike_sp - 1,    "Failed to decode function identifier. Got: ");
2592:    {    struct program *p;    -  decode_value2(data, 0); -  push_int (!force_decode); -  apply(data->codec,"programof", 2); +  decode_value2(data); +  apply(data->codec,"programof", 1);    -  if (Pike_sp[-1].type == T_PROGRAM || Pike_sp[-1].type == T_FUNCTION) +     p = program_from_svalue(Pike_sp-1); -  else -  p = 0; +        if (!p) {    if(data->pickyness)
2613:    add_ref(p);    pop_stack();    push_program(p); -  -  if (p->flags == PROGRAM_VIRGIN) { -  EDB (2, -  fprintf (stderr, "%*sdecode: got program embryo to finish later: ", -  data->depth, ""); -  print_svalue (stderr, Pike_sp - 1); -  fputc ('\n', stderr);); -  data->delayed = append_array (data->delayed, Pike_sp - 1); -  } -  +     break;    }   
2633:    char *dat=0;    struct program *p;    struct object *placeholder=0; -  ONERROR err1, err2, err3; +  ONERROR err1, err2, err3, err4;      #ifdef _REENTRANT    ONERROR err;
2648:    print_svalue(stderr, &entry_id);    fputc('\n', stderr););    -  SETUP_DECODE_MEMOBJ(T_PROGRAM, program, p, -  { -  if (data->target_prog) { -  add_ref (p = data->target_prog); -  data->target_prog = NULL; -  } -  else -  p = low_allocate_program(); -  }, -  ;); +  SETUP_DECODE_MEMOBJ(T_PROGRAM, program, p, low_allocate_program(),;);       SET_ONERROR(err3, zap_unfinished_program, p);    - #if 0 +     if(data->pass == 1)    {    if(! data->supporter.prog)
2688: Inside #if 0
   pop_stack();    }    } - #endif +     -  placeholder = data->placeholder; -  data->placeholder = NULL; +  if(placeholder) +  SET_ONERROR(err4, zap_placeholder, placeholder);    -  decode_value2(data, 0); +  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");
2724:    }       debug_malloc_touch(p); -  decode_value2(data, 0); +  decode_value2(data);    switch(Pike_sp[-1].type)    {    case T_INT:
2884:    decode_error(Pike_sp - 1, NULL,    "Placeholder is no longer a __null_program clone.\n");    }else{ -  Pike_fatal ("foo\n"); +     free_program(placeholder->prog);    add_ref(placeholder->prog = p);    debug_malloc_touch(placeholder);
2902:    decode_number(p->inherits[d].parent_identifier,data);    decode_number(p->inherits[d].storage_offset,data);    -  decode_value2(data, 0); +  decode_value2(data);    if(d==0)    {    if(Pike_sp[-1].type != T_PROGRAM ||
3023:    p->flags |= PROGRAM_PASS_1_DONE | PROGRAM_FIXED;    for(d=0;d<p->num_constants;d++)    { -  decode_value2(data, 0); +  decode_value2(data);    if(data->pass > 1)    {    assign_svalue(& p->constants[d].sval , Pike_sp -1 );
3061:       data->pickyness--;    +  if(placeholder) +  { +  free_object(placeholder); +  UNSET_ONERROR(err4); +  }    UNSET_ONERROR(err3);       ref_push_program(p);
3172:    }       case 2: -  decode_value2(data, 1); -  decode_value2(data, 0); +  decode_value2(data); +  decode_value2(data);    if(Pike_sp[-2].type==T_INT)    {    pop_stack();
3185:    break;       case 3: -  decode_value2(data, 0); +  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)) {
3202:    }    break;    -  case 5: /* Forward reference for new-style encoding. */ -  push_program (low_allocate_program()); +  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; -  struct object *placeholder = NULL; +     ONERROR err;    int orig_compilation_depth;    int byteorder;
3269:    "for delay encoded program <%d>: ", entry_id.u.integer);    }    /* No new ref here; low_start_new_program will add one for -  * Pike_compiler->new_program and we want to ride on that -  * one just like when it's created there. */ +  * Pike_compiler->new_program and we want ride on that one +  * just like when it's created there. */    p = delayed_enc_val->u.program;    } -  else if (data->target_prog) { -  p = data->target_prog; -  debug_malloc_touch (p); -  data->target_prog = NULL; -  } +     else    p = NULL;   
3309:       debug_malloc_touch(p);    - #if 0 -  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"); -  placeholder = Pike_sp[-1].u.object; -  dmalloc_touch_svalue (Pike_sp - 1); -  Pike_sp--; -  SET_ONERROR (placeholder_uwp, zap_placeholder, placeholder); -  } -  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 -  -  placeholder = data->placeholder; -  data->placeholder = NULL; -  +     /* Check the version. */ -  decode_value2(data, 0); +  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");
3346:    data->pickyness++;       /* parent */ -  decode_value2(data, 0); +  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) &&
3420:       /* Decode strings */    for (e=0; e<local_num_strings; e++) { -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3500:    int no, n;       /* name */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3508:    }       /* type */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3551:    int n;       /* name */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3559:    }       /* type */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3627:    int n;       /* name */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_STRING) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3646:    */       /* type */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type != T_TYPE) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3726:    }       /* name */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type == T_STRING) {    name = Pike_sp[-1].u.string;    } else if ((Pike_sp[-1].type != T_INT) ||
3737:    }       /* prog */ -  decode_value2(data, 1); +  decode_value2(data);    if (Pike_sp[-1].type != T_PROGRAM) {    ref_push_program (p);    decode_error(Pike_sp - 1, Pike_sp - 2,
3758:    }       /* parent */ -  decode_value2(data, 0); +  decode_value2(data);    if (Pike_sp[-1].type == T_OBJECT) {    parent = Pike_sp[-1].u.object;    } else if ((Pike_sp[-1].type != T_INT) ||
3810:    data->depth-=2;   #endif    -  push_program(p); /* "Take" the ref from Pike_compiler->new_program. */ +     UNSET_ONERROR(err);       /* De-kludge to get end_first_pass() to free the program. */
3822:    *    * 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"); +  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
3851:    for (e=0; e<local_num_constants; e++) {    struct program_constant *constant = p->constants+e;    /* value */ -  decode_value2(data, 0); +  decode_value2(data);    /* name */ -  decode_value2(data, 0); +  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) &&
3875:    /* The program should be consistent now. */    p->flags &= ~PROGRAM_AVOID_CHECK;    -  /* Make a real object of the placeholder. */ -  if (placeholder) { -  if(placeholder->prog != null_program) -  { -  debug_malloc_touch(placeholder); -  ref_push_program (p); -  decode_error(Pike_sp - 1, NULL, -  "Placeholder is no longer a __null_program clone.\n"); -  } -  -  free_program(placeholder->prog); -  add_ref(placeholder->prog = p); -  debug_malloc_touch(placeholder); -  -  if(placeholder->storage) { -  ref_push_object (placeholder); -  decode_error(Pike_sp - 2, Pike_sp - 1, -  "Placeholder already has storage: "); -  } -  -  placeholder->storage=p->storage_needed ? -  (char *)xalloc(p->storage_needed) : -  (char *)0; -  call_c_initializers(placeholder); -  init_placeholder (placeholder); -  } -  +     EDB(5, fprintf(stderr, "%*sProgram flags: 0x%04x\n",    data->depth, "", p->flags));   
3920:    Pike_error("Failed to restore string. (Illegal type)\n");    }    -  if (data->target_prog || data->placeholder) -  Pike_error ("Failed to decode a program to use for the target or placeholder.\n"); -  +     mapping_insert(data->decoded, &entry_id, Pike_sp-1);      decode_done:;
3943:    {    dmalloc_touch_svalue(&throw_value);    call_handle_error(); +  zap_placeholder(placeholder);    UNSETJMP(rec);    return 1;    }else{
3991:    }       free_mapping(data->decoded); -  free_array (data->delayed); +       #ifdef PIKE_DEBUG    if(data->unfinished_programs)
4028:    SET_ONERROR(err, free_decode_data, data);    current_decode = data;    -  decode_value2(data, 0); +  decode_value2(data);       while (data->ptr < data->len) { -  decode_value2 (data, 0); +  decode_value2 (data);    pop_stack();    }   
4046:    }   #endif    -  for (e = 0; e < data->delayed->size; e++) { -  struct program *p; - #ifdef PIKE_DEBUG -  if (ITEM (data->delayed)[e].type != T_PROGRAM) -  Pike_fatal ("Invalid value in data->delayed.\n"); - #endif -  p = ITEM (data->delayed)[e].u.program; -  if (p->flags == PROGRAM_VIRGIN) { -  ref_push_program (p); -  apply (data->codec, "finish_program", 1); -  if (p->flags == PROGRAM_VIRGIN) { -  ref_push_program (p); -  decode_error (NULL, Pike_sp - 1, "finish_program() failed to finish "); -  } -  pop_stack(); -  } -  } -  +     UNSET_ONERROR(err);    free_decode_data(data);   }
4077:   }      static INT32 my_decode(struct pike_string *tmp, -  struct object *codec, -  struct program *target_prog, -  struct object *placeholder +  struct object *codec   #ifdef ENCODE_DEBUG    , int debug   #endif
4118:    data->len=tmp->len;    data->ptr=0;    data->codec=codec; -  data->target_prog = target_prog; -  data->placeholder = placeholder; +     data->pickyness=0;    data->pass=1;    data->unfinished_programs=0;
4146:    }       data->decoded=allocate_mapping(128); -  data->delayed = allocate_array (0); +        init_supporter(& data->supporter,    (supporter_callback *) re_decode,
4228:    *! @[objectof()], @[functionof()], @[objectof()]    */    - /*! @decl object objectof(string data, int delay) -  *! @decl function functionof(string data, int delay) -  *! @decl program programof(string data, int delay) + /*! @decl object objectof(string data)    *! -  *! Get the object, function and program, respectively, represented -  *! by @[data]. +  *! Decode object encoded in @[data].    *!    *! This function is called by @[decode_value()] when it encounters -  *! values from @[nameof()] in the encoded data. +  *! encoded objects.    *!    *! @param data -  *! Encoding of some object, function or program as specified by -  *! @[nameof()]. +  *! Encoding of some object as specified by @[nameof()].    *! -  *! @param delay -  *! This parameter is used to handle circular references between the -  *! values decoded by several different @[decode_value] sessions. In -  *! the simple case when the decoding environment is complete, it's -  *! safe to ignore it. +  *! @param minor +  *! Minor version.    *! -  *! If compilation or decoding is needed to retrieve the object or -  *! program, then try to delay it and return a placeholder object -  *! (@[__null_program] clone) or empty program (@[__empty_program] -  *! return value) instead. If an empty program is returned then the -  *! codec will get a call to @[finish] later on with the returned -  *! value and it should then be filled out to the real program. -  *! (Placeholder objects get no calls since they are converted -  *! automatically when the corresponding program is finished.) +  *! @returns +  *! Returns the decoded object.    *! -  *! This delay process isn't applicable for functions since they -  *! always involve an indexing, but the parameter is passed anyway -  *! for consistency. +  *! @seealso +  *! @[functionof()], @[programof()] +  */ +  + /*! @decl function functionof(string data)    *! -  +  *! Decode function encoded in @[data]. +  *! +  *! This function is called by @[decode_value()] when it encounters +  *! encoded functions. +  *! +  *! @param data +  *! Encoding of some function as specified by @[nameof()]. +  *! +  *! @param minor +  *! Minor version. +  *!    *! @returns -  *! Returns the decoded object. +  *! Returns the decoded function. +  *! +  *! @seealso +  *! @[objectof()], @[programof()]    */    - /*! @decl void finish (program target) + /*! @decl program programof(string data)    *! -  *! FIXME +  *! Decode program encoded in @[data]. +  *! +  *! This function is called by @[decode_value()] when it encounters +  *! encoded programs. +  *! +  *! @param data +  *! Encoding of some program as specified by @[nameof()]. +  *! +  *! @param minor +  *! Minor version. +  *! +  *! @returns +  *! Returns the decoded program. +  *! +  *! @seealso +  *! @[functionof()], @[objectof()]    */    -  + /*! @decl object __register_new_program(program p) +  *! +  *! Called by @[decode_value()] to register the program that is +  *! being decoded. Might get called repeatedly with several other +  *! programs that are being decoded recursively. The only safe +  *! assumption is that when the top level thing being decoded is a +  *! program, then the first call will be with the unfinished embryo +  *! that will later become that program. +  *! +  *! @returns +  *! Returns either zero or a placeholder object. A placeholder +  *! object must be a clone of @[__null_program]. When the program is +  *! finished, the placeholder object will be converted to a clone of +  *! it. This is used for pike module objects. +  */ +    /*! @endclass    */   
4336:    if(*l < t) Pike_error("Format error: string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t; -  push_int (0); -  APPLY_MASTER("objectof", 2); +  APPLY_MASTER("objectof", 1);    return;       case TAG_FUNCTION:
4345:    if(*l < t) Pike_error("Format error: string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t; -  push_int (0); -  APPLY_MASTER("functionof", 2); +  APPLY_MASTER("functionof", 1);    return;       case TAG_PROGRAM:
4354:    if(*l < t) Pike_error("Format error: string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t; -  push_int (0); -  APPLY_MASTER("programof", 2); +  APPLY_MASTER("programof", 1);    return;       default:
4364:    }   }    - /*! @decl mixed decode_value(string coded_value, void|Codec codec, @ -  *! void|program target, void|object placeholder) + /*! @decl mixed decode_value(string coded_value, void|Codec codec)    *!    *! Decode a value from the string @[coded_value].    *!
4376:    *! If @[codec] is specified, it's used as the codec for the decode.    *! If no codec is specified, the current master object will be used.    *! -  *! @[target] and @[placeholder] are used to deal with cyclic -  *! references between programs and modules that are being decoded; -  *! users normally don't need to bother with them. If @[target] is -  *! given, it's extended with the decoded program, so that @[target] -  *! will become it afterwards. @[target] must be a newly created value -  *! from @[__empty_program]. If @[placeholder] is given, it must be a -  *! new created instance of @[__null_program] and it will become an -  *! instance of the program decoded to @[target]. -  *! +     *! @seealso    *! @[encode_value()], @[encode_value_canonic()]    */   void f_decode_value(INT32 args)   {    struct pike_string *s; -  struct object *codec, *placeholder = NULL; -  struct program *target_prog = NULL; +  struct object *codec;      #ifdef ENCODE_DEBUG    int debug = 0;
4401:    check_all_args("decode_value", args,    BIT_STRING,    BIT_VOID | BIT_OBJECT | BIT_ZERO, -  BIT_VOID | BIT_PROGRAM | BIT_ZERO, -  BIT_VOID | BIT_OBJECT | BIT_ZERO, +    #ifdef ENCODE_DEBUG    /* This argument is only an internal debug helper.    * It's intentionally not part of the function
4418: Inside #if defined(ENCODE_DEBUG)
   default:   #ifdef ENCODE_DEBUG    debug = Pike_sp[4-args].u.integer; -  case 4: - #endif -  if (Pike_sp[3-args].type == T_OBJECT) { -  placeholder = Pike_sp[3-args].u.object; -  if(placeholder->prog != null_program) -  SIMPLE_ARG_ERROR ("decode_value", 4, "Not a __null_program clone.\n"); -  debug_malloc_touch (placeholder); -  } +     /* Fall through. */ -  case 3: -  if (Pike_sp[2-args].type == T_PROGRAM) { -  target_prog = Pike_sp[2-args].u.program; -  if (target_prog->flags != PROGRAM_VIRGIN) -  SIMPLE_ARG_ERROR ("decode_value", 3, "Not an empty program.\n"); -  } -  /* Fall through. */ +     case 2: -  + #endif    if (Pike_sp[1-args].type == T_OBJECT) {    codec = Pike_sp[1-args].u.object;    break;
4450:    }    }    -  if(!my_decode(s, codec, target_prog, placeholder +  if(!my_decode(s, codec   #ifdef ENCODE_DEBUG    , debug   #endif