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.180 2004/05/11 14:50:30 grubba Exp $ + || $Id: encode.c,v 1.181 2004/05/11 15:18:53 grubba Exp $   */      #include "global.h"   #include "stralloc.h"   #include "pike_macros.h"   #include "object.h"   #include "constants.h"   #include "interpret.h"   #include "svalue.h"   #include "mapping.h"
pike.git/src/encode.c:25:   #include "fsort.h"   #include "threads.h"   #include "stuff.h"   #include "version.h"   #include "bignum.h"   #include "pikecode.h"   #include "pike_types.h"   #include "opcodes.h"   #include "peep.h"    - RCSID("$Id: encode.c,v 1.180 2004/05/11 14:50:30 grubba Exp $"); + RCSID("$Id: encode.c,v 1.181 2004/05/11 15:18:53 grubba Exp $");      /* #define ENCODE_DEBUG */      /* Use the old encoding method for programs. */   #define OLD_PIKE_ENCODE_PROGRAM      #ifdef ENCODE_DEBUG   /* Pass a nonzero integer as the third arg to encode_value,    * encode_value_canonic and decode_value to activate this debug. */   #define EDB(N,X) do { debug_malloc_touch(data); if (data->debug>=N) {X;} } while (0)
pike.git/src/encode.c:115:   #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 +  * value less than COUNTER_START 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   };    -  + /* Convert to/from forward reference ID. */ + #define CONVERT_ENTRY_ID(ID) (-((ID) - COUNTER_START) - (-COUNTER_START + 1)) +    static void encode_value2(struct svalue *val, struct encode_data *data, int force_encode);      #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 );
pike.git/src/encode.c:469:      {    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 < COUNTER_START) +  entry_id.u.integer = CONVERT_ENTRY_ID (entry_id.u.integer); +  if (force_encode && tmp->u.integer < COUNTER_START) { +  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); - #ifdef ENCODE_DEBUG -  data->depth -= 2; +  data->depth, "", entry_id.u.integer)); +  code_entry(TAG_AGAIN, entry_id.u.integer, data); +  goto encode_done; +  } +  }else { + #ifdef PIKE_DEBUG +  if (force_encode == 2) +  Pike_fatal ("Didn't find old entry for delay encoded thing.\n");   #endif -  return; -  }else if (val->type != T_TYPE) { +  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    {
pike.git/src/encode.c:831:    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);   
pike.git/src/encode.c:902:    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, 0);    ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name);    encode_value2(Pike_sp-1, data, 0);    pop_n_elems(3);   
pike.git/src/encode.c:948:    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--; +  /* We have to remove ourselves from the cache for now */ +  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, 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, 0);    -  pop_n_elems(3); +  pop_n_elems(2);       /* 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 in old style\n",    data->depth, ""));       /* Type 1 -- Old-style encoding. */       code_entry(TAG_PROGRAM, 1, data);    f_version(0);
pike.git/src/encode.c:1069:    {    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; +  Pike_sp[-1].subtype = p->inherits[d].parent_identifier; +  Pike_sp[-1].type = T_FUNCTION;    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, 1);    pop_stack();
pike.git/src/encode.c:1117:    code_number(p->lfuns[d], data);       for(d=0;d<p->num_constants;d++)    {    encode_value2(& p->constants[d].sval, data, 0);    adddata3(p->constants[d].name);    }      #else /* !OLD_PIKE_ENCODE_PROGRAM */    -  /* Type 4 -- Portable encoding. */ +  /* Portable encoding (4 and 5). */ +  +  if (!force_encode) { +  /* 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 = CONVERT_ENTRY_ID (tmp->u.integer); +  goto encode_done; +  } +     EDB(1, fprintf(stderr, "%*sencode: encoding program in new style\n",    data->depth, "")); -  code_entry(type_to_tag(val->type), 4, data); +  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, 0);
pike.git/src/encode.c:1497:    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, 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:1550:    *! 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, +  check_all_args("encode_value", args, +  BIT_MIXED, +  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    * 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) +  + #ifdef ENCODE_DEBUG +  data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0; +  data->depth = -2; + #endif +  +  if(args > 1 && Pike_sp[1-args].type == T_OBJECT)    {    data->codec=Pike_sp[1-args].u.object;    }else{    data->codec=get_master(); -  +  if (!data->codec) { +  /* Use a dummy if there's no master around yet, to avoid checks. */ +  push_object (clone_object (null_program, 0)); +  args++; +  data->codec = Pike_sp[-1].u.object;    } - #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, 1); -  +  +  for (i = 0; i < data->delayed->size; i++) +  encode_value2 (ITEM(data->delayed) + i, data, 2); +     UNSET_ONERROR(tmp);       free_mapping(data->encoded); -  +  free_array (data->delayed);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));   }      /*! @decl string encode_value_canonic(mixed value, object|void codec)    *!    *! Code a value into a string on canonical form.    *!    *! Takes a value and converts it to a string on canonical form, much like
pike.git/src/encode.c:1611:    *! 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, +  check_all_args("encode_value_canonic", args, +  BIT_MIXED, +  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    * 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) +  + #ifdef ENCODE_DEBUG +  data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0; +  data->depth = -2; + #endif +  +  if(args > 1 && Pike_sp[1-args].type == T_OBJECT)    {    data->codec=Pike_sp[1-args].u.object;    }else{    data->codec=get_master(); -  +  if (!data->codec) { +  /* Use a dummy if there's no master around yet, to avoid checks. */ +  push_object (clone_object (null_program, 0)); +  args++; +  data->codec = Pike_sp[-1].u.object;    } - #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, 1); -  +  +  for (i = 0; i < data->delayed->size; i++) +  encode_value2 (ITEM(data->delayed) + i, data, 2); +     UNSET_ONERROR(tmp);       free_mapping(data->encoded); -  +  free_array (data->delayed);       pop_n_elems(args);    push_string(low_free_buf(&data->buf));   }         struct unfinished_prog_link   {    struct unfinished_prog_link *next;    struct program *prog;
pike.git/src/encode.c:2120:    INT32 what, e, num, numh;    struct svalue entry_id, *tmp2;    struct svalue *delayed_enc_val;      #ifdef ENCODE_DEBUG    data->depth += 2;   #endif       DECODE("decode_value2");    -  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",
pike.git/src/encode.c:2597:    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");    dmalloc_touch_svalue(Pike_sp-1); +  Pike_sp--;    }    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();    }    }