pike.git / src / encode.c

version» Context lines:

pike.git/src/encode.c:18:   #include "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.50 1999/12/11 00:31:47 grubba Exp $"); + RCSID("$Id: encode.c,v 1.51 1999/12/11 01:14:56 grubba Exp $");      /* #define ENCODE_DEBUG */      #ifdef ENCODE_DEBUG   #define EDB(X) X   #else   #define EDB(X)   #endif      #ifdef _AIX
pike.git/src/encode.c:65:    return x * pow(2.0,(double)exp);   }   #endif      #ifdef PIKE_DEBUG   #define encode_value2 encode_value2_   #define decode_value2 decode_value2_   #endif       + /* Tags used by encode value. +  * Currently they only differ from the PIKE_T variants by +  * TAG_FLOAT == PIKE_T_TYPE == 7 +  * and +  * TAG_TYPE == PIKE_T_FLOAT == 9 +  * These are NOT to be renumbered unless the file-format version is changed! +  */ + /* Current encoding: ¶ik0 */ + #define TAG_ARRAY 0 + #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_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 +  +  +    struct encode_data   {    struct object *codec;    struct svalue counter;    struct mapping *encoded;    dynamic_buffer buf;   };      static void encode_value2(struct svalue *val, struct encode_data *data);   
pike.git/src/encode.c:107:    addstr( (char *)&s, sizeof(s)); \    } \    break; \    }   #endif      #define adddata(S) do { \    if((S)->size_shift) \    { \    int q; \ -  code_entry(T_STRING,-1, data); \ +  code_entry(TAG_STRING,-1, data); \    code_entry((S)->size_shift, (S)->len, data); \    ENCODE_DATA(S); \    }else{ \ -  code_entry(T_STRING, (S)->len, data); \ +  code_entry(TAG_STRING, (S)->len, data); \    addstr((char *)((S)->str),(S)->len); \    } \   }while(0)      /* Like adddata, but allows null pointers */      #define adddata3(S) do { \    if(S) { \    adddata(S); \    } else { \ -  code_entry(T_INT, 0, data); \ +  code_entry(TAG_INT, 0, data); \    } \   }while(0)      #define adddata2(s,l) addstr((char *)(s),(l) * sizeof(s[0]));    - /* Current encoding: ¶ik0 */ - #define T_AGAIN 15 - #define T_MASK 15 - #define T_NEG 16 - #define T_SMALL 32 - #define SIZE_SHIFT 6 - #define MAX_SMALL (1<<(8-SIZE_SHIFT)) - #define COUNTER_START -MAX_SMALL + /* NOTE: Fix when type encodings change. */ + static int type_to_tag(int type) + { +  if (type == T_FLOAT) return TAG_FLOAT; +  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 type, INT32 num, struct encode_data *data) + static void code_entry(int tag, INT32 num, struct encode_data *data)   {    int t;    EDB( -  fprintf(stderr,"encode: code_entry(type=%d (%s), num=%d)\n", -  type, -  get_name_of_type(type), +  fprintf(stderr,"encode: code_entry(tag=%d (%s), num=%d)\n", +  tag, +  get_name_of_type(tag_to_type(tag)),    num) );    if(num<0)    { -  type|=T_NEG; -  num=~num; +  tag |= TAG_NEG; +  num = ~num;    }       if(num < MAX_SMALL)    { -  type|=T_SMALL | (num << SIZE_SHIFT); -  addchar(type); +  tag |= TAG_SMALL | (num << SIZE_SHIFT); +  addchar(tag);    return;    }else{ -  num-=MAX_SMALL; +  num -= MAX_SMALL;    }       for(t=0;t<3;t++)    {    if(num >= (256 << (t<<3)))    num-=(256 << (t<<3));    else    break;    }    -  type|=t << SIZE_SHIFT; -  addchar(type); +  tag |= t << SIZE_SHIFT; +  addchar(tag);       switch(t)    {    case 3: addchar((num >> 24)&0xff);    case 2: addchar((num >> 16)&0xff);    case 1: addchar((num >> 8)&0xff);    case 0: addchar(num&0xff);    }   }    -  +    static void code_number(INT32 num, struct encode_data *data)   {    code_entry(num & 15, num >> 4, data);   }      #ifdef _REENTRANT   static void do_enable_threads(void)   {    exit_threads_disable(NULL);   }
pike.git/src/encode.c:302:    static struct svalue dested = { T_INT, NUMBER_DESTRUCTED };    INT32 i;    struct svalue *tmp;       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)))    { -  code_entry(T_AGAIN, tmp->u.integer, data); +  code_entry(TAG_AGAIN, tmp->u.integer, data);    return;    }else{    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)    * then this must be fixed to encode numbers over 32 bits as    * Gmp.mpz objects    */ -  code_entry(T_INT, val->u.integer,data); +  code_entry(TAG_INT, val->u.integer,data);    break;       case T_STRING:    adddata(val->u.string);    break;       case T_TYPE: -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ +     error("Encoding of the type type not supported yet!");    break;       case T_FLOAT:    {    if(val->u.float_number==0.0)    { -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ -  code_entry(T_TYPE,0,data); -  code_entry(T_TYPE,0,data); +  code_entry(TAG_FLOAT,0,data); +  code_entry(TAG_FLOAT,0,data);    }else{    INT32 x;    int y;    double tmp;       tmp=FREXP((double)val->u.float_number, &y);    x=(INT32)((1<<30)*tmp);    y-=30;   #if 0    while(x && y && !(x&1))    {    x>>=1;    y++;    }   #endif -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ -  code_entry(T_TYPE,x,data); -  code_entry(T_TYPE,y,data); +  code_entry(TAG_FLOAT,x,data); +  code_entry(TAG_FLOAT,y,data);    }    break;    }       case T_ARRAY: -  code_entry(T_ARRAY, val->u.array->size, data); +  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);    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);    -  code_entry(T_MAPPING, sp[-2].u.array->size,data); +  code_entry(TAG_MAPPING, sp[-2].u.array->size,data);    for(i=0; i<sp[-2].u.array->size; i++)    {    encode_value2(ITEM(sp[-2].u.array)+i, data); /* indices */    encode_value2(ITEM(sp[-1].u.array)+i, data); /* values */    }    pop_n_elems(2);    break;       case T_MULTISET: -  code_entry(T_MULTISET, val->u.multiset->ind->size,data); +  code_entry(TAG_MULTISET, val->u.multiset->ind->size,data);    for(i=0; i<val->u.multiset->ind->size; i++)    encode_value2(ITEM(val->u.multiset->ind)+i, data);    break;       case T_OBJECT:    check_stack(1);      #ifdef AUTO_BIGNUM    /* This could be implemented a lot more generic,    * but that will have to wait until next time. /Hubbe    */    if(is_bignum_object(val->u.object))    { -  code_entry(T_OBJECT, 2, data); +  code_entry(TAG_OBJECT, 2, data);    /* 256 would be better, but then negative numbers    * doesn't work... /Hubbe    */    push_int(36);    apply(val->u.object,"digits",1);    if(sp[-1].type != T_STRING)    error("Gmp.mpz->digits did not return a string!\n");    encode_value2(sp-1, data);    pop_stack();    break;
pike.git/src/encode.c:428:    apply(data->codec, "nameof", 1);    switch(sp[-1].type)    {    case T_INT:    if(sp[-1].subtype == NUMBER_UNDEFINED)    {    pop_stack();    push_svalue(val);    f_object_program(1);    -  code_entry(val->type, 1,data); +  code_entry(type_to_tag(val->type), 1,data);    encode_value2(sp-1, data);    pop_stack();       push_svalue(val);    apply(data->codec,"encode_object",1);    break;    }    /* FALL THROUGH */       default: -  code_entry(val->type, 0,data); +  code_entry(type_to_tag(val->type), 0,data);    break; -  +     }    encode_value2(sp-1, data);    pop_stack();    break;       case T_FUNCTION:    check_stack(1);    push_svalue(val);    apply(data->codec,"nameof", 1);    if(sp[-1].type == T_INT && sp[-1].subtype==NUMBER_UNDEFINED)    {    if(val->subtype != FUNCTION_BUILTIN)    {    int eq; -  code_entry(val->type, 1, data); +  +  code_entry(type_to_tag(val->type), 1, data);    push_svalue(val);    sp[-1].type=T_OBJECT;    ref_push_string(ID_FROM_INT(val->u.object->prog, val->subtype)->name);    f_arrow(2);    eq=is_eq(sp-1, val);    pop_stack();    if(eq)    {    /* We have to remove ourself from the cache for now */    struct svalue tmp=data->counter;
pike.git/src/encode.c:484:    encode_value2(sp-1, data);    pop_n_elems(3);       /* Put value back in cache */    mapping_insert(data->encoded, val, &tmp);    return;    }    }    }    -  code_entry(val->type, 0,data); +  code_entry(type_to_tag(val->type), 0,data);    encode_value2(sp-1, data);    pop_stack();    break;          case T_PROGRAM:    {    int d;    check_stack(1);    push_svalue(val);    apply(data->codec,"nameof", 1);    if(sp[-1].type == val->type)    error("Error in master()->nameof(), same type returned.\n");    if(sp[-1].type == T_INT && sp[-1].subtype == NUMBER_UNDEFINED)    {    INT32 e;    struct program *p=val->u.program;    if(p->init || p->exit || p->gc_marked || p->gc_check ||    (p->flags & PROGRAM_HAS_C_METHODS))    error("Cannot encode C programs.\n"); -  code_entry(val->type, 1,data); +  code_entry(type_to_tag(val->type), 1,data);    f_version(0);    encode_value2(sp-1,data);    pop_stack();    code_number(p->flags,data);    code_number(p->storage_needed,data);    code_number(p->alignment_needed,data);    code_number(p->timestamp.tv_sec,data);    code_number(p->timestamp.tv_usec,data);      #define FOO(X,Y,Z) \
pike.git/src/encode.c:578:       for(d=0;d<p->num_constants;d++)    {    encode_value2(& p->constants[d].sval, data);    adddata3(p->constants[d].name);    }       for(d=0;d<NUM_LFUNS;d++)    code_number(p->lfuns[d], data);    }else{ -  code_entry(val->type, 0,data); +  code_entry(type_to_tag(val->type), 0,data);    encode_value2(sp-1, data);    }    pop_stack();    break;    }    }   }      static void free_encode_data(struct encode_data *data)   {
pike.git/src/encode.c:650:    return data->data [ data->ptr++ ];   }      #define GETC() my_extract_char(data)      #define DECODE(Z) do { \    EDB( \    fprintf(stderr,"decode(%s) at %d: ",(Z),__LINE__)); \    what=GETC(); \    e=what>>SIZE_SHIFT; \ -  if(what & T_SMALL) { \ +  if(what & TAG_SMALL) { \    num=e; \    } else { \    num=0; \    while(e-->=0) num=(num<<8) + (GETC()+1); \    num+=MAX_SMALL - 1; \    } \ -  if(what & T_NEG) num=~num; \ +  if(what & TAG_NEG) num=~num; \    EDB( \    fprintf(stderr,"type=%d (%s), num=%d\n", \ -  (what & T_MASK), \ -  get_name_of_type(what & T_MASK), \ +  (what & TAG_MASK), \ +  get_name_of_type(tag_to_type(what & TAG_MASK)), \    num) ); \   } while (0)            #define decode_entry(X,Y,Z) \    do { \    INT32 what, e, num; \    DECODE("decode_entry"); \ -  if((what & T_MASK) != (X)) error("Failed to decode, wrong bits (%d).\n", what & T_MASK);\ +  if((what & TAG_MASK) != (X)) error("Failed to decode, wrong bits (%d).\n", what & TAG_MASK);\    (Y)=num; \    } while(0);      #define getdata2(S,L) do { \    if(data->ptr + (long)(sizeof(S[0])*(L)) > data->len) \    error("Failed to decode string. (string range error)\n"); \    MEMCPY((S),(data->data + data->ptr), sizeof(S[0])*(L)); \    data->ptr+=sizeof(S[0])*(L); \    }while(0)   
pike.git/src/encode.c:698:    case 1: for(e=0;e<num;e++) STR1(S)[e]=ntohs(STR1(S)[e]); break; \    case 2: for(e=0;e<num;e++) STR2(S)[e]=ntohl(STR2(S)[e]); break; \    }   #endif      #define get_string_data(STR,LEN, data) do { \    if((LEN) == -1) \    { \    INT32 what, e, num; \    DECODE("get_string_data"); \ -  what&=T_MASK; \ +  what&=TAG_MASK; \    if(data->ptr + num > data->len || num <0) \    error("Failed to decode string. (string range error)\n"); \    if(what<0 || what>2) error("Failed to decode string. (Illegal size shift)\n"); \    STR=begin_wide_shared_string(num, what); \    MEMCPY(STR->str, data->data + data->ptr, num << what); \    data->ptr+=(num << what); \    BITFLIP(STR); \    STR=end_shared_string(STR); \    }else{ \    if(data->ptr + (LEN) > data->len || (LEN) <0) \    error("Failed to decode string. (string range error)\n"); \    STR=make_shared_binary_string((char *)(data->data + data->ptr), (LEN)); \    data->ptr+=(LEN); \    } \   }while(0)      #define getdata(X) do { \    long length; \ -  decode_entry(T_STRING, length,data); \ +  decode_entry(TAG_STRING, length,data); \    get_string_data(X, length, data); \    }while(0)      #define getdata3(X) do { \    INT32 what, e, num; \    DECODE("getdata3"); \ -  switch(what & T_MASK) \ +  switch(what & TAG_MASK) \    { \ -  case T_INT: \ +  case TAG_INT: \    X=0; \    break; \    \ -  case T_STRING: \ +  case TAG_STRING: \    get_string_data(X,num,data); \    break; \    \    default: \ -  error("Failed to decode string, type is wrong: %d\n",what & T_MASK); \ +  error("Failed to decode string, tag is wrong: %d\n", \ +  what & TAG_MASK); \    } \   }while(0)      #define decode_number(X,data) do { \    int what, e, num; \    DECODE("decode_number"); \ -  X=(what & T_MASK) | (num<<4); \ +  X=(what & TAG_MASK) | (num<<4); \    }while(0) \         static void restore_type_stack(unsigned char *old_stackp)   {   #if 0    fprintf(stderr, "Restoring type-stack: %p => %p\n",    type_stackp, old_stackp);   #endif /* 0 */   #ifdef PIKE_DEBUG
pike.git/src/encode.c:776: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (old_type_mark_stackp > pike_type_mark_stackp) {    fatal("type mark_stack out of sync!\n");    }   #endif /* PIKE_DEBUG */    pike_type_mark_stackp = old_type_mark_stackp;   }      static void low_decode_type(struct decode_data *data)   { +  /* FIXME: Probably ought to use the tag encodings too. */ +     int tmp;    ONERROR err1;    ONERROR err2;       SET_ONERROR(err1, restore_type_stack, type_stackp);    SET_ONERROR(err2, restore_type_mark, pike_type_mark_stackp);      one_more_type:    push_type(tmp=GETC());    switch(tmp)
pike.git/src/encode.c:902:         {    INT32 what, e, num;    struct svalue tmp, *tmp2;       DECODE("decode_value2");       check_stack(1);    -  switch(what & T_MASK) +  switch(what & TAG_MASK)    { -  case T_AGAIN: +  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{    error("Failed to decode string. (invalid T_AGAIN)\n");    }    return;    -  case T_INT: +  case TAG_INT:    tmp=data->counter;    data->counter.u.integer++;    push_int(num);    break;    -  case T_STRING: +  case TAG_STRING:    {    struct pike_string *str;    tmp=data->counter;    data->counter.u.integer++;    get_string_data(str, num, data);    push_string(str);    break;    }    -  case T_TYPE: -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ +  case TAG_FLOAT:    {    INT32 num2=num;       tmp=data->counter;    data->counter.u.integer++;       DECODE("float");    push_float(LDEXP((double)num2, num));    break;    }    -  case T_FLOAT: -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ +  case TAG_TYPE:    {    error("Failed to decode string. "    "(decode of the type type isn't supported yet).\n");    break;    }    -  case T_ARRAY: +  case TAG_ARRAY:    {    struct array *a;    if(num < 0)    error("Failed to decode string. (array size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    error("Failed to decode array. (not enough data)\n");       tmp.type=T_ARRAY;
pike.git/src/encode.c:989:    {    decode_value2(data);    ITEM(a)[e]=sp[-1];    sp--;    dmalloc_touch_svalue(sp);    }    ref_push_array(a);    return;    }    -  case T_MAPPING: +  case TAG_MAPPING:    {    struct mapping *m;    if(num<0)    error("Failed to decode string. (mapping size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    error("Failed to decode mapping. (not enough data)\n");       m=allocate_mapping(num);
pike.git/src/encode.c:1017:    {    decode_value2(data);    decode_value2(data);    mapping_insert(m, sp-2, sp-1);    pop_n_elems(2);    }    ref_push_mapping(m);    return;    }    -  case T_MULTISET: +  case TAG_MULTISET:    {    struct multiset *m;    if(num<0)    error("Failed to decode string. (multiset size is negative)\n");       /* Heruetical */    if(data->ptr + num > data->len)    error("Failed to decode multiset. (not enough data)\n");       m=mkmultiset(low_allocate_array(0, num));
pike.git/src/encode.c:1046:    {    decode_value2(data);    multiset_insert(m, sp-1);    pop_stack();    }    ref_push_multiset(m);    return;    }       -  case T_OBJECT: +  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);
pike.git/src/encode.c:1111:   #endif       default:    error("Object coding not compatible.\n");    break;    }    if(data->pickyness && sp[-1].type != T_OBJECT)    error("Failed to decode.\n");    break;    -  case T_FUNCTION: +  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);
pike.git/src/encode.c:1148:       default:    error("Function coding not compatible.\n");    break;    }    if(data->pickyness && sp[-1].type != T_FUNCTION)    error("Failed to decode function.\n");    break;       -  case T_PROGRAM: +  case TAG_PROGRAM:    switch(num)    {    case 0:    {    struct svalue *prog_code;       tmp=data->counter;    data->counter.u.integer++;    decode_value2(data);   
pike.git/src/encode.c:1495:   }      static void rec_restore_value(char **v, INT32 *l)   {    INT32 t,i;       i=extract_int(v,l);    t=extract_int(v,l);    switch(i)    { -  case T_INT: push_int(t); return; +  case TAG_INT: push_int(t); return;    -  case T_TYPE: -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ +  case TAG_FLOAT:    if(sizeof(INT32) < sizeof(float)) /* FIXME FIXME FIXME FIXME */    error("Float architecture not supported.\n");    push_int(t); /* WARNING! */    sp[-1].type = T_FLOAT;    return;    -  case T_FLOAT: -  /* NOTE: Floats are encoded with the tag T_TYPE (7) -  * for backward compatibility. -  */ +  case TAG_TYPE:    error("Format error:decoding of the type type not supported yet.\n");    return;    -  case T_STRING: +  case TAG_STRING:    if(t<0) error("Format error, length of string is negative.\n");    if(*l < t) error("Format error, string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l)-= t; (*v)+= t;    return;    -  case T_ARRAY: +  case TAG_ARRAY:    if(t<0) error("Format error, length of array is negative.\n");    check_stack(t);    for(i=0;i<t;i++) rec_restore_value(v,l);    f_aggregate(t);    return;    -  case T_MULTISET: +  case TAG_MULTISET:    if(t<0) error("Format error, length of multiset is negative.\n");    check_stack(t);    for(i=0;i<t;i++) rec_restore_value(v,l);    f_aggregate_multiset(t);    return;    -  case T_MAPPING: +  case TAG_MAPPING:    if(t<0) error("Format error, length of mapping is negative.\n");    check_stack(t*2);    for(i=0;i<t;i++)    {    rec_restore_value(v,l);    rec_restore_value(v,l);    }    f_aggregate_mapping(t*2);    return;    -  case T_OBJECT: +  case TAG_OBJECT:    if(t<0) error("Format error, length of object is negative.\n");    if(*l < t) error("Format error, string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t;    APPLY_MASTER("objectof", 1);    return;    -  case T_FUNCTION: +  case TAG_FUNCTION:    if(t<0) error("Format error, length of function is negative.\n");    if(*l < t) error("Format error, string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t;    APPLY_MASTER("functionof", 1);    return;    -  case T_PROGRAM: +  case TAG_PROGRAM:    if(t<0) error("Format error, length of program is negative.\n");    if(*l < t) error("Format error, string to short\n");    push_string(make_shared_binary_string(*v, t));    (*l) -= t; (*v) += t;    APPLY_MASTER("programof", 1);    return;       default: -  error("Format error. Unknown type\n"); +  error("Format error. Unknown type tag %d:%d\n", i, t);    }   }      void f_decode_value(INT32 args)   {    struct pike_string *s;    struct object *codec;       check_all_args("decode_value", args,    BIT_STRING, BIT_VOID | BIT_OBJECT | BIT_INT, 0);