|
|
|
|
|
|
#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" |
#include "array.h" |
#include "multiset.h" |
#include "lex.h" |
#include "dynamic_buffer.h" |
#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" |
#include "pikecode.h" |
#include "pike_types.h" |
#include "opcodes.h" |
#include "peep.h" |
#include "pike_compiler.h" |
#include "bitvector.h" |
|
|
|
|
|
|
#ifdef ENCODE_DEBUG |
|
* encode_value_canonic and decode_value to activate this debug. It |
* both enables debug messages and also lessens the pickyness to |
* sort-of be able to decode programs with the wrong codec. */ |
#define EDB(N,X) do { debug_malloc_touch(data); if (data->debug>=N) {X;} } while (0) |
#ifndef PIKE_DEBUG |
#error ENCODE_DEBUG requires PIKE_DEBUG |
#endif |
#else |
#define EDB(N,X) do { debug_malloc_touch(data); } while (0) |
#endif |
|
#ifdef _AIX |
#include <net/nh.h> |
#endif |
|
#ifdef HAVE_NETINET_IN_H |
#include <netinet/in.h> |
#endif |
|
#ifdef HAVE_SYS_SOCKET_H |
#include <sys/socket.h> |
#endif |
|
#ifdef HAVE_IEEEFP_H |
#include <ieeefp.h> |
#endif /* HAVE_IEEEFP_H */ |
|
#include <math.h> |
|
#ifdef PIKE_DEBUG |
#define encode_value2 encode_value2_ |
#define decode_value2 decode_value2_ |
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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_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 ID_ENTRY_TYPE_CONSTANT -4 |
#define ID_ENTRY_EFUN_CONSTANT -3 |
#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 |
#define ID_ENTRY_ALIAS 4 |
|
static struct object *lookup_codec (struct pike_string *codec_name) |
{ |
struct object *m = get_master(); |
if (!m) { |
|
|
return clone_object (null_program, 0); |
} |
else { |
ref_push_object (m); |
ref_push_string (codec_name); |
o_index(); |
if (UNSAFE_IS_ZERO (Pike_sp - 1)) { |
add_ref (m); |
return m; |
} |
else { |
apply_svalue (Pike_sp - 1, 0); |
if (TYPEOF(Pike_sp[-1]) != T_OBJECT) |
Pike_error ("master()->%s() did not return an object. Got: %O\n", |
codec_name->str, Pike_sp - 1); |
m = (--Pike_sp)->u.object; |
pop_stack(); |
return m; |
} |
} |
} |
|
struct encode_data |
{ |
int canonic; |
struct object *codec; |
struct svalue counter; |
struct mapping *encoded; |
|
|
|
struct array *delayed; |
dynamic_buffer buf; |
#ifdef ENCODE_DEBUG |
int debug, depth; |
#endif |
}; |
|
static struct object *encoder_codec (struct encode_data *data) |
{ |
struct pike_string *encoder_str; |
if (data->codec) return data->codec; |
MAKE_CONST_STRING (encoder_str, "Encoder"); |
return data->codec = lookup_codec (encoder_str); |
} |
|
|
#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)) |
|
|
|
#if PIKE_BYTEORDER == 4321 |
#define ENCODE_DATA(S) \ |
addstr( (S)->str, (S)->len << (S)->size_shift ); |
#else |
#define ENCODE_DATA(S) \ |
switch((S)->size_shift) \ |
{ \ |
case 1: \ |
for(q=0;q<(S)->len;q++) { \ |
INT16 s=htons( STR1(S)[q] ); \ |
addstr( (char *)&s, sizeof(s)); \ |
} \ |
break; \ |
case 2: \ |
for(q=0;q<(S)->len;q++) { \ |
INT32 s=htonl( STR2(S)[q] ); \ |
addstr( (char *)&s, sizeof(s)); \ |
} \ |
break; \ |
case 0: /* Silence clang warning */ \ |
break; \ |
} |
#endif |
|
#define adddata(S) do { \ |
if((S)->size_shift) \ |
{ \ |
int q; \ |
code_entry(TAG_STRING,-1, data); \ |
code_entry((S)->size_shift, (S)->len, data); \ |
ENCODE_DATA(S); \ |
}else{ \ |
code_entry(TAG_STRING, (S)->len, data); \ |
addstr((char *)((S)->str),(S)->len); \ |
} \ |
}while(0) |
|
#define adddata2(s,l) addstr((char *)(s),(l) * sizeof((s)[0])); |
|
#ifdef ENCODE_DEBUG |
|
static int tag_to_type(int tag) |
{ |
if (tag == TAG_FLOAT) return T_FLOAT; |
if (tag == TAG_TYPE) return T_TYPE; |
if (tag <= MAX_TYPE) return tag ^ MIN_REF_TYPE; |
return tag; |
} |
#endif |
|
|
static void code_entry(int tag, INT64 num, struct encode_data *data) |
{ |
int t; |
EDB(5, |
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) |
{ |
tag |= TAG_SMALL | (num << SIZE_SHIFT); |
addchar((char)tag); |
return; |
}else{ |
num -= MAX_SMALL; |
} |
|
|
for(t = 0; (size_t)t < 3; t++) |
{ |
if(num >= (((INT64)256) << (t<<3))) |
num -= (((INT64)256) << (t<<3)); |
else |
break; |
} |
|
tag |= t << SIZE_SHIFT; |
addchar((char)tag); |
|
switch(t) |
{ |
#if 0 |
case 7: addchar(DO_NOT_WARN((char)((num >> 56)&0xff))); |
case 6: addchar(DO_NOT_WARN((char)((num >> 48)&0xff))); |
case 5: addchar(DO_NOT_WARN((char)((num >> 40)&0xff))); |
case 4: addchar(DO_NOT_WARN((char)((num >> 32)&0xff))); |
#endif /* 0 */ |
case 3: addchar(DO_NOT_WARN((char)((num >> 24)&0xff))); |
case 2: addchar(DO_NOT_WARN((char)((num >> 16)&0xff))); |
case 1: addchar(DO_NOT_WARN((char)((num >> 8)&0xff))); |
case 0: addchar(DO_NOT_WARN((char)(num&0xff))); |
} |
} |
|
static void code_number(ptrdiff_t num, struct encode_data *data) |
{ |
EDB(5, fprintf(stderr, "%*scode_number(%d)\n", |
data->depth, "", num)); |
code_entry(DO_NOT_WARN(num & 15), |
num >> 4, data); |
} |
|
|
|
|
|
static void encode_type(struct pike_type *t, struct encode_data *data) |
{ |
one_more_type: |
if (t->type == T_MANY) { |
addchar(T_FUNCTION ^ MIN_REF_TYPE); |
addchar(T_MANY); |
} else if (t->type == T_STRING) { |
if (t->car == int_type_string) { |
addchar(T_STRING ^ MIN_REF_TYPE); |
} else { |
|
addchar(PIKE_T_NSTRING); |
encode_type(t->car, data); |
} |
return; |
} else if (t->type <= MAX_TYPE) { |
addchar(t->type ^ MIN_REF_TYPE); |
} else { |
addchar(t->type); |
} |
switch(t->type) { |
default: |
Pike_fatal("error in type tree: %d.\n", t->type); |
|
|
break; |
|
case PIKE_T_ATTRIBUTE: |
case PIKE_T_NAME: |
{ |
struct svalue sval; |
SET_SVAL(sval, PIKE_T_STRING, 0, string, (void *)t->car); |
encode_value2(&sval, data, 0); |
} |
t=t->cdr; |
goto one_more_type; |
|
case T_ASSIGN: |
{ |
ptrdiff_t marker = CAR_TO_INT(t); |
if ((marker < 0) || (marker > 9)) { |
Pike_fatal("Bad assign marker: %ld\n", |
(long)marker); |
} |
addchar('0' + marker); |
t = t->cdr; |
} |
goto one_more_type; |
|
case T_FUNCTION: |
while(t->type == T_FUNCTION) { |
encode_type(t->car, data); |
t = t->cdr; |
} |
addchar(T_MANY); |
|
case T_MANY: |
encode_type(t->car, data); |
t = t->cdr; |
goto one_more_type; |
|
case T_SCOPE: |
{ |
ptrdiff_t val = CAR_TO_INT(t); |
addchar(val & 0xff); |
} |
t = t->cdr; |
goto one_more_type; |
|
case T_MAPPING: |
case T_OR: |
case T_AND: |
encode_type(t->car, data); |
t = t->cdr; |
goto one_more_type; |
|
case T_TYPE: |
case T_PROGRAM: |
case T_ARRAY: |
case T_MULTISET: |
case T_NOT: |
t = t->car; |
goto one_more_type; |
|
case T_INT: |
{ |
ptrdiff_t val; |
|
val = CAR_TO_INT(t); |
addchar((val >> 24)&0xff); |
addchar((val >> 16)&0xff); |
addchar((val >> 8)&0xff); |
addchar(val & 0xff); |
val = CDR_TO_INT(t); |
addchar((val >> 24)&0xff); |
addchar((val >> 16)&0xff); |
addchar((val >> 8)&0xff); |
addchar(val & 0xff); |
} |
break; |
|
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
case T_FLOAT: |
case T_MIXED: |
case T_ZERO: |
case T_VOID: |
case PIKE_T_UNKNOWN: |
break; |
|
case T_OBJECT: |
{ |
addchar(CAR_TO_INT(t)); |
|
if(t->cdr) |
{ |
ptrdiff_t id = CDR_TO_INT(t); |
if( id >= PROG_DYNAMIC_ID_START ) |
{ |
struct program *p=id_to_program(id); |
if(p) |
{ |
ref_push_program(p); |
}else{ |
push_int(0); |
} |
} else |
push_int( id ); |
}else{ |
push_int(0); |
} |
|
|
|
|
|
|
|
|
|
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
break; |
} |
} |
} |
|
|
|
|
|
|
|
|
|
static void encode_value2(struct svalue *val, struct encode_data *data, int force_encode) |
|
#ifdef PIKE_DEBUG |
#undef encode_value2 |
#define encode_value2(X,Y,Z) do { \ |
struct svalue *_=Pike_sp; \ |
struct svalue *X_ = (X); \ |
encode_value2_(X_,Y,Z); \ |
if(Pike_sp != _) { \ |
fprintf(stderr, "Stack error when encoding:\n"); \ |
print_svalue(stderr, X_); \ |
fprintf(stderr, "\n"); \ |
if (TYPEOF(*X_) == T_PROGRAM) { \ |
dump_program_tables(X_->u.program, 2); \ |
} \ |
Pike_fatal("encode_value2() failed %p != %p!\n", \ |
Pike_sp, _); \ |
} \ |
} while(0) |
#endif |
|
{ |
static struct svalue dested = SVALUE_INIT (T_INT, NUMBER_DESTRUCTED, 0); |
INT32 i; |
struct svalue *tmp; |
struct svalue entry_id; |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
if((TYPEOF(*val) == T_OBJECT || |
(TYPEOF(*val) == T_FUNCTION && SUBTYPEOF(*val) != FUNCTION_BUILTIN)) && |
!val->u.object->prog) |
val = &dested; |
|
if((tmp=low_mapping_lookup(data->encoded, val))) |
{ |
entry_id = *tmp; |
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", TYPEOF(*val)); |
}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, "", 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 |
if (TYPEOF(*val) != T_TYPE) { |
entry_id = data->counter; |
EDB(1,fprintf(stderr, "%*sEncoding to <%d>: ", |
data->depth, "", entry_id.u.integer); |
if(data->debug == 1) |
{ |
fprintf(stderr,"TAG%d", TYPEOF(*val)); |
}else{ |
print_svalue(stderr, val); |
} |
fputc('\n', stderr);); |
if( TYPEOF(*val) < MIN_REF_TYPE || val->u.dummy->refs > 1 ) |
mapping_insert(data->encoded, val, &entry_id); |
data->counter.u.integer++; |
} |
} |
|
switch(TYPEOF(*val)) |
{ |
case T_INT: |
|
{ |
INT_TYPE i=val->u.integer; |
#if SIZEOF_INT_TYPE > 4 |
if (i != (INT32)i) |
{ |
MP_INT tmp; |
|
#if (SIZEOF_INT_TYPE > SIZEOF_LONG) || (SIZEOF_INT_TYPE&7) |
# error Assumption about size of int type not true. |
#endif |
char buffer[16*(SIZEOF_INT_TYPE/8)]; |
size_t l; |
|
|
|
|
mpz_init_set_si( &tmp, i ); |
mpz_get_str( buffer, 36, &tmp ); |
mpz_clear( &tmp ); |
l = strlen(buffer); |
code_entry(TAG_OBJECT, 2, data); |
code_entry(TAG_STRING, l, data); |
addstr(buffer,l); |
} |
else |
#endif |
code_entry(TAG_INT, i, data); |
} |
break; |
|
case T_STRING: |
adddata(val->u.string); |
break; |
|
case T_TYPE: |
|
|
|
if (data->canonic) |
Pike_error("Canonical encoding of the type type not supported.\n"); |
code_entry(TAG_TYPE, 0, data); |
encode_type(val->u.type, data); |
EDB(2,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: |
{ |
double d = val->u.float_number; |
|
#define Pike_FP_SNAN -4 /* Signal Not A Number */ |
#define Pike_FP_QNAN -3 /* Quiet Not A Number */ |
#define Pike_FP_NINF -2 /* Negative infinity */ |
#define Pike_FP_PINF -1 /* Positive infinity */ |
#define Pike_FP_ZERO 0 /* Backwards compatible zero */ |
#define Pike_FP_NZERO 1 /* Negative Zero */ |
#define Pike_FP_PZERO 0 /* Positive zero */ |
#define Pike_FP_UNKNOWN -4711 /* Positive zero */ |
|
|
#ifdef HAVE_FPCLASS |
switch(fpclass(d)) { |
case FP_SNAN: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_SNAN,data); |
break; |
|
case FP_QNAN: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_QNAN,data); |
break; |
|
case FP_NINF: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_NINF,data); |
break; |
|
case FP_PINF: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_PINF,data); |
break; |
|
case FP_NZERO: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_NZERO,data); |
break; |
|
case FP_PZERO: |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,Pike_FP_ZERO,data); |
break; |
|
|
default: |
goto encode_normal_float; |
} |
break; |
encode_normal_float: |
|
#else |
{ |
int pike_ftype=Pike_FP_UNKNOWN; |
#ifdef HAVE_ISINF |
if(isinf(d)) |
pike_ftype=Pike_FP_PINF; |
else |
#endif |
#ifdef HAVE_ISNAN |
if(isnan(d)) { |
pike_ftype=Pike_FP_SNAN; |
} else |
#endif |
#ifdef HAVE_ISZERO |
if(iszero(d)) |
pike_ftype=Pike_FP_PZERO; |
else |
#endif |
#ifdef HAVE_FINITE |
if(!finite(d)) |
pike_ftype=Pike_FP_PINF; |
#endif |
; |
|
if( |
#ifdef HAVE_SIGNBIT |
signbit(d) |
#else |
d<0.0 |
#endif |
) { |
switch(pike_ftype) |
{ |
case Pike_FP_PINF: |
pike_ftype=Pike_FP_NINF; |
break; |
|
case Pike_FP_PZERO: |
pike_ftype=Pike_FP_NZERO; |
break; |
} |
} |
|
if(pike_ftype != Pike_FP_UNKNOWN) |
{ |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,pike_ftype,data); |
break; |
} |
} |
#endif |
|
if(d == 0.0) |
{ |
code_entry(TAG_FLOAT,0,data); |
code_entry(TAG_FLOAT,0,data); |
}else{ |
INT64 x; |
int y; |
double tmp; |
|
tmp = frexp(d, &y); |
x = DO_NOT_WARN((INT64)((((INT64)1)<<(sizeof(INT64)*8 - 2))*tmp)); |
y -= sizeof(INT64)*8 - 2; |
|
EDB(2,fprintf(stderr, |
"Encoding float... tmp: %10g, x: 0x%016llx, y: %d\n", |
tmp, x, y)); |
|
#if 0 |
if (x && !(x & 0xffffffffUL)) { |
#endif /* 0 */ |
x >>= 32; |
y += 32; |
|
EDB(2,fprintf(stderr, |
"Reducing float... x: 0x%08llx, y: %d\n", |
x, y)); |
#if 0 |
} |
#endif /* 0 */ |
#if 0 |
while(x && y && !(x&1)) |
{ |
x>>=1; |
y++; |
} |
#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, 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); |
|
if (data->canonic) { |
INT32 *order; |
if (val->u.mapping->data->ind_types & ~(BIT_BASIC & ~BIT_TYPE)) { |
mapping_fix_type_field(val->u.mapping); |
if (val->u.mapping->data->ind_types & ~(BIT_BASIC & ~BIT_TYPE)) |
|
|
|
|
Pike_error("Canonical encoding requires basic types in indices.\n"); |
} |
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(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, 0); |
encode_value2(ITEM(Pike_sp[-1].u.array)+i, data, 0); |
} |
pop_n_elems(2); |
|
break; |
|
case T_MULTISET: { |
struct multiset *l = val->u.multiset; |
|
if (TYPEOF(*multiset_get_cmp_less(l)) != T_INT) |
Pike_error ("FIXME: Encoding of multisets with " |
"custom sort function not yet implemented.\n"); |
else { |
|
|
code_entry(TAG_MULTISET, multiset_sizeof (l), data); |
if (data->canonic) { |
INT32 *order; |
if (multiset_ind_types(l) & ~(BIT_BASIC & ~BIT_TYPE)) { |
multiset_fix_type_field(l); |
if (multiset_ind_types(l) & ~(BIT_BASIC & ~BIT_TYPE)) |
|
|
|
Pike_error("Canonical encoding requires basic types in indices.\n"); |
} |
check_stack(1); |
push_array(multiset_indices(l)); |
order = get_switch_order(Pike_sp[-1].u.array); |
order_array(Pike_sp[-1].u.array, order); |
free(order); |
for (i = 0; i < Pike_sp[-1].u.array->size; i++) |
encode_value2(ITEM(Pike_sp[-1].u.array)+i, data, 0); |
pop_stack(); |
} |
else { |
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, 0); |
} |
} |
break; |
} |
|
case T_OBJECT: |
check_stack(1); |
|
|
|
|
if(is_bignum_object(val->u.object)) |
{ |
MP_INT *i = (MP_INT*)val->u.object->storage; |
char *buffer; |
size_t l; |
|
buffer = xalloc(mpz_sizeinbase(i, 36)+2); |
mpz_get_str( buffer, 36, i ); |
l = strlen(buffer); |
code_entry(TAG_OBJECT, 2, data); |
code_entry(TAG_STRING, l, data); |
addstr(buffer,l); |
free(buffer); |
break; |
} |
|
if (data->canonic) |
Pike_error("Canonical encoding of objects not supported.\n"); |
push_svalue(val); |
apply(encoder_codec (data), "nameof", 1); |
EDB(5, fprintf(stderr, "%*s->nameof: ", data->depth, ""); |
print_svalue(stderr, Pike_sp-1); |
fputc('\n', stderr);); |
switch(TYPEOF(Pike_sp[-1])) |
{ |
case T_INT: |
if(SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED) |
{ |
int to_change = data->buf.s.len; |
struct svalue tmp = entry_id; |
|
EDB(5,fprintf(stderr, "%*s(UNDEFINED)\n", data->depth, "")); |
|
if (SUBTYPEOF(*val)) { |
|
|
|
|
code_entry(TAG_OBJECT, 4, data); |
code_number(SUBTYPEOF(*val), data); |
pop_stack(); |
ref_push_object(val->u.object); |
break; |
} |
|
|
map_delete(data->encoded, val); |
|
pop_stack(); |
push_svalue(val); |
f_object_program(1); |
|
|
code_entry(TAG_OBJECT, 3,data); |
encode_value2(Pike_sp-1, data, 1); |
pop_stack(); |
|
push_svalue(val); |
|
|
|
|
|
if(!low_mapping_lookup(data->encoded, val)) |
{ |
int fun; |
EDB(1,fprintf(stderr, "%*sZapping 3 -> 1 in TAG_OBJECT\n", |
data->depth, "")); |
|
|
|
|
|
data->buf.s.str[to_change] = 99; |
|
fun = find_identifier("encode_object", |
encoder_codec (data)->prog); |
if (fun < 0) |
Pike_error("Cannot encode objects without an " |
"\"encode_object\" function in the codec.\n"); |
apply_low(data->codec,fun,1); |
|
|
mapping_insert(data->encoded, val, &tmp); |
} |
break; |
} |
|
|
default: |
code_entry(TAG_OBJECT, 0,data); |
break; |
} |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
break; |
|
case T_FUNCTION: |
|
if (data->canonic) |
Pike_error("Canonical encoding of functions not supported.\n"); |
check_stack(1); |
push_svalue(val); |
apply(encoder_codec (data),"nameof", 1); |
if(TYPEOF(Pike_sp[-1]) == T_INT && |
SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED) |
{ |
if(SUBTYPEOF(*val) != FUNCTION_BUILTIN) |
{ |
if(really_low_find_shared_string_identifier( |
ID_FROM_INT(val->u.object->prog, SUBTYPEOF(*val))->name, |
val->u.object->prog, |
SEE_PROTECTED|SEE_PRIVATE) == SUBTYPEOF(*val)) |
{ |
|
struct svalue tmp = entry_id; |
map_delete(data->encoded, val); |
|
code_entry(TAG_FUNCTION, 1, data); |
ref_push_object(val->u.object); |
encode_value2(Pike_sp-1, data, 0); |
ref_push_string(ID_FROM_INT(val->u.object->prog, |
SUBTYPEOF(*val))->name); |
encode_value2(Pike_sp-1, data, 0); |
pop_n_elems(3); |
|
|
mapping_insert(data->encoded, val, &tmp); |
goto encode_done; |
} |
else { |
|
Pike_error("Cannot encode overloaded functions (yet).\n"); |
} |
} |
Pike_error("Cannot encode builtin functions.\n"); |
} |
|
code_entry(TAG_FUNCTION, 0, 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, 0); |
pop_stack(); |
break; |
} |
if (data->canonic) |
Pike_error("Canonical encoding of programs not supported.\n"); |
if (!(val->u.program->flags & PROGRAM_FIXED)) |
Pike_error("Encoding of unfixated programs not supported.\n"); |
check_stack(1); |
push_svalue(val); |
apply(encoder_codec (data),"nameof", 1); |
if(TYPEOF(Pike_sp[-1]) == TYPEOF(*val)) |
Pike_error("Error in master()->nameof(), same type returned.\n"); |
if(TYPEOF(Pike_sp[-1]) == T_INT && |
SUBTYPEOF(Pike_sp[-1]) == NUMBER_UNDEFINED) |
{ |
struct program *p=val->u.program; |
debug_malloc_touch(p); |
pop_stack(); |
if( (p->flags & PROGRAM_HAS_C_METHODS) || p->event_handler ) |
{ |
int has_local_c_methods = 0; |
for (d = 0; d < p->num_identifiers; d++) { |
struct identifier *id = p->identifiers + d; |
if (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) && |
!low_is_variant_dispatcher(id)) { |
has_local_c_methods = 1; |
break; |
} |
} |
if (has_local_c_methods) { |
if(p->parent) |
{ |
|
struct svalue tmp = entry_id; |
EDB(1, fprintf(stderr, |
"%*sencode: encoding C program via parent.\n", |
data->depth, "")); |
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 0 |
if(TYPEOF(Pike_sp[-1]) == PIKE_T_INT) |
Pike_error("Cannot encode C programs.\n"); |
#endif |
encode_value2(Pike_sp-1, data, 0); |
|
pop_n_elems(2); |
|
|
mapping_insert(data->encoded, val, &tmp); |
goto encode_done; |
} |
if( p->event_handler ) |
Pike_error("Cannot encode programs with event handlers.\n"); |
#if 0 |
Pike_error("Cannot encode C programs.\n"); |
#endif |
} else { |
EDB(1, fprintf(stderr, |
"%*sencode: encoding program overloading a C program.\n", |
data->depth, "")); |
} |
} |
|
|
|
if (!force_encode) { |
|
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); |
if (!tmp) |
Pike_error("Internal error in delayed encoder of programs.\n"); |
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(TAG_PROGRAM, 4, data); |
|
|
code_number(PIKE_BYTEORDER, data); |
|
|
code_number(p->flags,data); |
|
|
push_compact_version(); |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
if (p->parent) { |
ref_push_program(p->parent); |
} else { |
push_int(0); |
} |
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" |
|
|
|
#ifdef PIKE_PORTABLE_BYTECODE |
code_number(PIKE_BYTECODE_PORTABLE, data); |
#else /* !PIKE_PORTABLE_BYTECODE */ |
code_number(PIKE_BYTECODE_METHOD, data); |
#ifdef PIKE_USE_MACHINE_CODE |
|
code_number(instrs_checksum, data); |
#endif /* PIKE_USE_MACHINE_CODE */ |
|
|
#ifdef ENCODE_PROGRAM |
#ifdef PIKE_DEBUG |
{ |
ptrdiff_t bufpos = data->buf.s.len; |
#endif /* PIKE_DEBUG */ |
ENCODE_PROGRAM(p, &(data->buf)); |
#ifdef PIKE_DEBUG |
if (p->num_program * sizeof(p->program[0]) != |
data->buf.s.len - bufpos) { |
Pike_fatal("ENCODE_PROGRAM() failed:\n" |
"Encoded data len: %ld\n" |
"Expected data len: %ld\n", |
DO_NOT_WARN((long)(p->num_program * sizeof(p->program[0]))), |
DO_NOT_WARN((long)(data->buf.s.len - bufpos))); |
} |
} |
#endif /* PIKE_DEBUG */ |
#else /* !ENCODE_PROGRAM */ |
adddata2(p->program, p->num_program); |
#endif /* ENCODE_PROGRAM */ |
|
|
for(d=0; d<(int)p->num_relocations; d++) { |
code_number(p->relocations[d], data); |
} |
|
|
adddata2(p->linenumbers, p->num_linenumbers); |
|
#endif /* PIKE_PORTABLE_BYTECODE */ |
|
{ |
struct svalue str_sval; |
SET_SVAL(str_sval, T_STRING, 0, string, NULL); |
|
for(d=0;d<p->num_strings;d++) { |
str_sval.u.string = p->strings[d]; |
encode_value2(&str_sval, data, 0); |
} |
} |
|
EDB(5, dump_program_tables(p, data->depth)); |
|
#ifdef PIKE_PORTABLE_BYTECODE |
|
{ |
struct svalue str_sval; |
SET_SVAL(str_sval, T_STRING, 0, string, NULL); |
|
|
for(d=0;d<p->num_constants;d++) |
{ |
if ((TYPEOF(p->constants[d].sval) == T_FUNCTION) && |
(SUBTYPEOF(p->constants[d].sval) == FUNCTION_BUILTIN)) { |
code_number(ID_ENTRY_EFUN_CONSTANT, data); |
} else if (TYPEOF(p->constants[d].sval) == T_TYPE) { |
code_number(ID_ENTRY_TYPE_CONSTANT, data); |
} else { |
continue; |
} |
code_number(d, data); |
|
encode_value2(&p->constants[d].sval, data, 0); |
|
|
#if 0 |
if (p->constants[d].name) { |
str_sval.u.string = p->constants[d].name; |
encode_value2(&str_sval, data, 0); |
} else { |
#endif /* 0 */ |
push_int(0); |
encode_value2(Pike_sp-1, data, 0); |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp--; |
#if 0 |
} |
#endif /* 0 */ |
} |
} |
#endif /* PIKE_PORTABLE_BYTECODE */ |
|
{ |
int inherit_num = 1; |
struct svalue str_sval; |
char *id_dumped = alloca(p->num_identifiers); |
int d_min = 0; |
memset(id_dumped,0,p->num_identifiers); |
SET_SVAL(str_sval, T_STRING, 0, string, NULL); |
|
EDB(2, |
fprintf(stderr, "%*sencode: encoding references\n", |
data->depth, "")); |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
|
for (d=0; d < p->num_identifier_references;) |
{ |
int d_max = p->num_identifier_references; |
|
|
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);); |
|
|
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); |
|
|
if (ref->id_flags & ID_INHERITED) { |
if ((ref->id_flags & (ID_VARIANT|ID_HIDDEN)) == ID_VARIANT) { |
|
int i = really_low_find_shared_string_identifier(id->name, p, |
SEE_PROTECTED|SEE_PRIVATE); |
|
|
|
|
|
if ((i >= 0) && !is_variant_dispatcher(p, i) && |
!PTR_FROM_INT(p, i)->inherit_offset) { |
|
|
|
|
id_dumped[PTR_FROM_INT(p, i)->identifier_offset] = 1; |
} |
} |
continue; |
} |
|
|
|
|
if (!IDENTIFIER_IS_ALIAS(id->identifier_flags) && |
IDENTIFIER_IS_VARIABLE(id->identifier_flags) && |
(id->run_time_type == PIKE_T_GET_SET)) |
continue; |
|
EDB(3, |
fprintf(stderr, |
"%*sencoding identifier ref %d: %4x \"%s\"\n", |
data->depth, "", d, |
id->identifier_flags, |
id->name->str)); |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
|
|
if (ref->inherit_offset || ref->id_flags & ID_HIDDEN) { |
int ref_no = -1; |
|
|
EDB(3, |
fprintf(stderr, "%*sencode: encoding raw reference\n", |
data->depth, "")); |
|
code_number(ID_ENTRY_RAW, data); |
code_number(ref->id_flags, data); |
|
|
code_number(ref->inherit_offset, data); |
|
|
|
|
{ |
struct program *p2 = p->inherits[ref->inherit_offset].prog; |
int i; |
debug_malloc_touch(p); |
debug_malloc_touch(p2); |
for (i=0; i < p2->num_identifier_references; i++) { |
struct reference *ref2 = p2->identifier_references + i; |
if (!(ref2->inherit_offset) && |
!(ref2->id_flags & ID_HIDDEN) && |
(ref2->identifier_offset == ref->identifier_offset)) { |
ref_no = i; |
break; |
} |
} |
} |
if (ref_no == -1) { |
Pike_error("Failed to reverse explicit reference\n"); |
} |
code_number(ref_no, data); |
} else { |
int gs_flags = -1; |
|
if (id_dumped[ref->identifier_offset]) { |
EDB(3, |
fprintf(stderr, "%*sencode: already encoded reference\n", |
data->depth, "")); |
goto next_identifier_ref; |
} |
id_dumped[ref->identifier_offset] = 1; |
|
if (id->name && (id->name->len>3) && |
(index_shared_string(id->name, 0) == '`') && |
(index_shared_string(id->name, 1) == '-') && |
(index_shared_string(id->name, 2) == '>')) { |
|
struct pike_string *symbol = NULL; |
if (index_shared_string(id->name, id->name->len-1) != '=') { |
|
symbol = string_slice(id->name, 3, id->name->len - 3); |
} else if (id->name->len > 4) { |
|
symbol = string_slice(id->name, 3, id->name->len - 4); |
} |
if (symbol) { |
int i = really_low_find_shared_string_identifier(symbol, p, |
SEE_PROTECTED|SEE_PRIVATE); |
if (i >= 0) { |
|
gs_flags = PTR_FROM_INT(p, i)->id_flags; |
} |
free_string(symbol); |
} |
} else if (id->name && (id->name->len>1) && |
(index_shared_string(id->name, 0) == '`') && |
((((unsigned)index_shared_string(id->name, 1)) >= |
256) || |
isidchar(index_shared_string(id->name, 1)))) { |
|
struct pike_string *symbol = NULL; |
if (index_shared_string(id->name, id->name->len-1) != '=') { |
|
symbol = string_slice(id->name, 1, id->name->len - 1); |
} else if (id->name->len > 2) { |
|
symbol = string_slice(id->name, 1, id->name->len - 2); |
} |
if (symbol) { |
int i = really_low_find_shared_string_identifier(symbol, p, |
SEE_PROTECTED|SEE_PRIVATE); |
if (i >= 0) { |
|
gs_flags = PTR_FROM_INT(p, i)->id_flags; |
} |
free_string(symbol); |
} |
} else if (ref->id_flags & ID_VARIANT) { |
|
int i = really_low_find_shared_string_identifier(id->name, p, |
SEE_PROTECTED|SEE_PRIVATE); |
|
|
|
|
|
if ((i < 0) || !is_variant_dispatcher(p, i)) { |
Pike_error("Failed to find dispatcher for inherited " |
"variant function: %S\n", id->name); |
} |
if (PTR_FROM_INT(p, i)->inherit_offset) { |
Pike_error("Dispatcher for variant function %S " |
"is inherited.\n", id->name); |
} |
gs_flags = ref->id_flags & PTR_FROM_INT(p, i)->id_flags; |
if (id_dumped[PTR_FROM_INT(p, i)->identifier_offset]) { |
|
|
|
|
gs_flags |= ID_VARIANT; |
} else { |
|
id_dumped[PTR_FROM_INT(p, i)->identifier_offset] = 1; |
} |
} |
|
if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) { |
if ((!id->func.ext_ref.depth) && |
IDENTIFIER_IS_VARIABLE(id->identifier_flags)) { |
struct identifier *other = |
ID_FROM_INT(p, id->func.ext_ref.id); |
if (other->name == id->name) { |
|
EDB(3, fprintf(stderr, |
"%*sencode: encoding aliased variable\n", |
data->depth, "")); |
goto encode_entry_variable; |
} |
} |
EDB(3, fprintf(stderr, "%*sencode: encoding alias\n", |
data->depth, "")); |
|
code_number(ID_ENTRY_ALIAS, data); |
|
|
code_number(ref->id_flags, data); |
|
|
str_sval.u.string = id->name; |
encode_value2(&str_sval, data, 0); |
|
|
ref_push_type_value(id->type); |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
code_number(id->filename_strno, data); |
|
|
code_number(id->linenumber, data); |
|
|
code_number(id->func.ext_ref.depth, data); |
|
|
code_number(id->func.ext_ref.id, data); |
|
} else switch (id->identifier_flags & IDENTIFIER_TYPE_MASK) { |
case IDENTIFIER_CONSTANT: |
EDB(3, |
fprintf(stderr, "%*sencode: encoding constant\n", |
data->depth, "")); |
|
code_number(ID_ENTRY_CONSTANT, data); |
if (gs_flags >= 0) { |
code_number(gs_flags, data); |
} else { |
code_number(ref->id_flags, data); |
} |
|
|
str_sval.u.string = id->name; |
encode_value2(&str_sval, data, 0); |
|
|
ref_push_type_value(id->type); |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
code_number(id->filename_strno, data); |
|
|
code_number(id->linenumber, data); |
|
|
code_number(id->func.const_info.offset, data); |
|
|
code_number(id->run_time_type, data); |
|
|
code_number(id->opt_flags, data); |
break; |
|
case IDENTIFIER_PIKE_FUNCTION: |
EDB(3, |
fprintf(stderr, "%*sencode: encoding function\n", |
data->depth, "")); |
|
code_number(ID_ENTRY_FUNCTION, data); |
if (gs_flags >= 0) { |
code_number(gs_flags, data); |
} else { |
code_number(ref->id_flags, data); |
} |
|
|
str_sval.u.string = id->name; |
encode_value2(&str_sval, data, 0); |
|
|
ref_push_type_value(id->type); |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
code_number(id->filename_strno, data); |
|
|
code_number(id->linenumber, data); |
|
|
code_number(id->identifier_flags, data); |
|
|
#ifdef PIKE_PORTABLE_BYTECODE |
if (id->func.offset >= 0) { |
|
|
|
code_number(read_program_data(p->program + id->func.offset, |
-1), data); |
} else { |
|
code_number(-1, data); |
} |
#else /* !PIKE_PORTABLE_BYTECODE */ |
code_number(id->func.offset, data); |
#endif /* PIKE_PORTABLE_BYTECODE */ |
|
|
code_number(id->opt_flags, data); |
break; |
|
case IDENTIFIER_C_FUNCTION: |
if (is_variant_dispatcher(p, d)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
continue; |
} |
|
Pike_error("Cannot encode functions implemented in C " |
"(identifier=\"%S\").\n", |
id->name); |
break; |
|
case IDENTIFIER_VARIABLE: |
if (d < d_min) { |
EDB(3, |
fprintf(stderr, "%*sencode: Skipping overloaded variable \"%s\"\n", |
data->depth, "", |
id->name->str)); |
|
id_dumped[ref->identifier_offset] = 0; |
goto next_identifier_ref; |
} |
EDB(3, |
fprintf(stderr, "%*sencode: encoding variable\n", |
data->depth, "")); |
encode_entry_variable: |
code_number(ID_ENTRY_VARIABLE, data); |
if (gs_flags >= 0) { |
code_number(gs_flags, data); |
} else { |
code_number(ref->id_flags, data); |
} |
|
|
str_sval.u.string = id->name; |
encode_value2(&str_sval, data, 0); |
|
|
ref_push_type_value(id->type); |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
code_number(id->filename_strno, data); |
|
|
code_number(id->linenumber, data); |
|
break; |
|
#ifdef PIKE_DEBUG |
default: |
Pike_fatal ("Unknown identifier type: 0x%04x for symbol \"%s\".\n", |
id->identifier_flags & IDENTIFIER_TYPE_MASK, |
id->name->str); |
#endif |
} |
} |
|
|
code_number(d, data); |
|
next_identifier_ref: |
; |
#ifdef ENCODE_DEBUG |
data->depth -= 2; |
#endif |
} |
|
|
if (inherit_num < p->num_inherits) { |
|
|
|
INT16 inherit_flags_set = 0; |
|
|
INT16 inherit_flags_mask = ~(ID_HIDDEN|ID_INHERITED); |
struct inherit *inh = p->inherits + inherit_num; |
struct reference *ref = p->identifier_references + d; |
int i; |
|
|
d_min = inh->identifier_level + |
inh->prog->num_identifier_references; |
|
EDB(3, |
fprintf(stderr, "%*sencode: encoding inherit\n", |
data->depth, "")); |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
code_number(ID_ENTRY_INHERIT, data); |
|
|
for (i = 0; i < inh->prog->num_identifier_references; i++) { |
if (ref[i].inherit_offset) { |
INT16 id_flags = ref[i].id_flags; |
INT16 inh_id_flags = |
inh->prog->identifier_references[i].id_flags; |
|
if (!(id_flags & ID_HIDDEN)) { |
inherit_flags_set |= id_flags & ~inh_id_flags; |
if (inh_id_flags & ID_PUBLIC) { |
|
|
inherit_flags_mask &= id_flags | ID_PRIVATE; |
} else { |
inherit_flags_mask &= id_flags; |
} |
} |
} else { |
|
|
inherit_flags_mask &= ~ID_LOCAL; |
} |
} |
EDB(5, |
fprintf(stderr, "%*sraw inherit_flags_set: %04x:%04x\n", |
data->depth, "", |
inherit_flags_set, inherit_flags_mask)); |
inherit_flags_set &= inherit_flags_mask; |
code_number(inherit_flags_set, data); |
|
EDB(5, |
fprintf(stderr, "%*sinherit_flags: %04x\n", |
data->depth, "", inherit_flags_set)); |
|
|
code_number(d_max, data); |
|
|
if (!inh->name) |
Pike_error("Cannot encode programs with unnamed inherits.\n"); |
str_sval.u.string = inh->name; |
encode_value2(&str_sval, data, 0); |
|
|
ref_push_program(inh->prog); |
encode_value2(Pike_sp-1, data, 1); |
pop_stack(); |
|
|
if (inh->parent) { |
ref_push_object(inh->parent); |
} else { |
push_int(0); |
} |
encode_value2(Pike_sp-1, data, 0); |
pop_stack(); |
|
|
code_number(inh->parent_identifier, data); |
|
|
code_number(inh->parent_offset, data); |
|
|
code_number(inh->prog->num_identifier_references, data); |
|
inherit_num += inh->prog->num_inherits; |
|
#ifdef ENCODE_DEBUG |
data->depth -= 2; |
#endif |
} |
} |
|
code_number(ID_ENTRY_EOT, data); |
|
#ifdef ENCODE_DEBUG |
data->depth -= 2; |
#endif |
} |
|
|
{ |
struct svalue str_sval; |
SET_SVAL(str_sval, T_STRING, 0, string, NULL); |
|
EDB(2, |
fprintf(stderr, "%*sencode: encoding constants\n", |
data->depth, "")); |
|
|
for(d=0;d<p->num_constants;d++) |
{ |
EDB(5, |
fprintf(stderr, "%*sencode: encoding constant #%d\n", |
data->depth, "", d)); |
|
#ifdef PIKE_PORTABLE_BYTECODE |
if (((TYPEOF(p->constants[d].sval) == T_FUNCTION) && |
(SUBTYPEOF(p->constants[d].sval) == FUNCTION_BUILTIN)) || |
(TYPEOF(p->constants[d].sval) == T_TYPE)) { |
|
continue; |
} |
#endif /* PIKE_PORTABLE_BYTECODE */ |
|
encode_value2(&p->constants[d].sval, data, 0); |
|
|
#if 0 |
if (p->constants[d].name) { |
str_sval.u.string = p->constants[d].name; |
encode_value2(&str_sval, data, 0); |
} else { |
#endif /* 0 */ |
push_int(0); |
encode_value2(Pike_sp-1, data, 0); |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp--; |
#if 0 |
} |
#endif /* 0 */ |
} |
} |
}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); |
if (data->codec) free_object (data->codec); |
free_mapping(data->encoded); |
free_array(data->delayed); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 | BIT_ZERO, |
#ifdef ENCODE_DEBUG |
|
* 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); |
SET_SVAL(data->counter, T_INT, NUMBER_NUMBER, integer, COUNTER_START); |
|
#ifdef ENCODE_DEBUG |
data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0; |
data->depth = -2; |
#endif |
|
if(args > 1 && TYPEOF(Pike_sp[1-args]) == T_OBJECT) |
{ |
if (SUBTYPEOF(Pike_sp[1-args])) |
Pike_error("The codec may not be a subtyped object yet.\n"); |
|
data->codec=Pike_sp[1-args].u.object; |
add_ref (data->codec); |
}else{ |
data->codec=NULL; |
} |
|
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); |
|
if (data->codec) free_object (data->codec); |
free_mapping(data->encoded); |
free_array (data->delayed); |
|
pop_n_elems(args); |
push_string(low_free_buf(&data->buf)); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 | BIT_ZERO, |
#ifdef ENCODE_DEBUG |
|
* 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); |
SET_SVAL(data->counter, T_INT, NUMBER_NUMBER, integer, COUNTER_START); |
|
#ifdef ENCODE_DEBUG |
data->debug = args > 2 ? Pike_sp[2-args].u.integer : 0; |
data->depth = -2; |
#endif |
|
if(args > 1 && TYPEOF(Pike_sp[1-args]) == T_OBJECT) |
{ |
if (SUBTYPEOF(Pike_sp[1-args])) |
Pike_error("The codec may not be a subtyped object yet.\n"); |
|
data->codec=Pike_sp[1-args].u.object; |
add_ref (data->codec); |
}else{ |
data->codec=NULL; |
} |
|
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); |
|
if (data->codec) free_object (data->codec); |
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; |
}; |
|
struct unfinished_obj_link |
{ |
struct unfinished_obj_link *next; |
struct object *o; |
struct svalue decode_arg; |
}; |
|
struct decode_data |
{ |
struct pike_string *data_str; |
unsigned char *data; |
ptrdiff_t len; |
ptrdiff_t ptr; |
struct mapping *decoded; |
struct unfinished_prog_link *unfinished_programs; |
struct unfinished_obj_link *unfinished_objects; |
struct unfinished_obj_link *unfinished_placeholders; |
struct svalue counter; |
struct object *codec; |
int explicit_codec; |
int pickyness; |
int pass; |
int delay_counter; |
struct pike_string *raw; |
struct decode_data *next; |
#ifdef PIKE_THREADS |
struct thread_state *thread_state; |
struct object *thread_obj; |
#endif |
#ifdef ENCODE_DEBUG |
int debug, depth; |
#endif |
#if TWO_PASS_DECODE_WORKS |
|
* but it doesn't seem to really handle that. /mast */ |
struct Supporter supporter; |
#endif |
}; |
|
static struct object *decoder_codec (struct decode_data *data) |
{ |
struct pike_string *decoder_str; |
if (data->codec) return data->codec; |
MAKE_CONST_STRING (decoder_str, "Decoder"); |
return data->codec = lookup_codec (decoder_str); |
} |
|
static void decode_value2(struct decode_data *data); |
|
static int my_extract_char(struct decode_data *data) |
{ |
if(data->ptr >= data->len) |
Pike_error("Not enough data in string.\n"); |
return data->data [ data->ptr++ ]; |
} |
|
static DECLSPEC(noreturn) void decode_error ( |
struct decode_data *data, struct svalue *decoding, const char *msg, ...) |
ATTRIBUTE((noinline,noreturn)); |
|
static DECLSPEC(noreturn) void decode_error ( |
struct decode_data *data, struct svalue *decoding, const char *msg, ...) |
{ |
int n = 0; |
va_list args; |
struct string_builder sb; |
struct object *o = fast_clone_object (decode_error_program); |
struct decode_error_struct *dec = |
(struct decode_error_struct *) (o->storage + decode_error_offset); |
struct generic_error_struct *gen = get_storage (o, generic_error_program); |
|
ASSERT_THREAD_SWAPPED_IN(); |
|
copy_shared_string (dec->decode_string, data->data_str); |
|
if (decoding) { |
push_text ("Error while decoding "); n++; |
push_text ("%O"); |
push_svalue (decoding); |
f_sprintf (2); n++; |
push_text (":\n"); n++; |
} |
else { |
push_text ("Decode error: "); n++; |
} |
|
init_string_builder (&sb, 0); |
va_start (args, msg); |
string_builder_vsprintf (&sb, msg, args); |
va_end (args); |
push_string (finish_string_builder (&sb)); n++; |
|
f_add (n); |
gen->error_message = (--Pike_sp)->u.string; |
|
generic_error_va (o, NULL, NULL, 0, NULL, NULL); |
} |
|
#define GETC() my_extract_char(data) |
|
#define DECODE(Z) do { \ |
EDB(5, \ |
fprintf(stderr,"%*sdecode(%s) at %d: ", \ |
data->depth,"",(Z),__LINE__)); \ |
what=GETC(); \ |
e=what>>SIZE_SHIFT; \ |
if(what & TAG_SMALL) { \ |
num=e; \ |
} else { \ |
num = 0; \ |
while(e-->=0) num = ((unsigned INT64)num<<8) \ |
+ (GETC()+1); \ |
num += MAX_SMALL - 1; \ |
} \ |
if(what & TAG_NEG) { \ |
num = ~num; \ |
} \ |
EDB(5, \ |
fprintf(stderr,"type=%d (%s), num=%ld\n", \ |
(what & TAG_MASK), \ |
get_name_of_type(tag_to_type(what & TAG_MASK)), \ |
(long)num) ); \ |
} while (0) |
|
#define decode_entry(X,Y,Z) \ |
do { \ |
INT32 what, e; \ |
INT64 num; \ |
DECODE("decode_entry"); \ |
if((what & TAG_MASK) != (X)) \ |
decode_error(data, NULL, "Wrong bits (%d).\n", what & TAG_MASK); \ |
(Y)=num; \ |
} while(0); |
|
#if PIKE_BYTEORDER == 4321 |
#define BITFLIP(S) |
#else |
#define BITFLIP(S) \ |
switch(what) \ |
{ \ |
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; \ |
INT64 num; \ |
ptrdiff_t sz; \ |
DECODE("get_string_data"); \ |
what &= TAG_MASK; \ |
if(what<0 || what>2) \ |
decode_error (data, NULL, "Illegal size shift %d.\n", what); \ |
sz = (ptrdiff_t) num << what; \ |
if (sz < 0) \ |
decode_error (data, NULL, "Illegal negative size %td.\n", sz); \ |
if (sz > data->len - data->ptr) \ |
decode_error (data, NULL, "Too large size %td (max is %td).\n", \ |
sz, data->len - data->ptr); \ |
STR=begin_wide_shared_string(num, what); \ |
memcpy(STR->str, data->data + data->ptr, sz); \ |
data->ptr += sz; \ |
BITFLIP(STR); \ |
STR=end_shared_string(STR); \ |
}else{ \ |
ptrdiff_t sz = (LEN); \ |
if (sz < 0) \ |
decode_error (data, NULL, "Illegal negative size %td.\n", sz); \ |
if (sz > data->len - data->ptr) \ |
decode_error (data, NULL, "Too large size %td (max is %td).\n", \ |
sz, data->len - data->ptr); \ |
STR=make_shared_binary_string((char *)(data->data + data->ptr), sz); \ |
data->ptr += sz; \ |
} \ |
}while(0) |
|
#define decode_number(X,data) do { \ |
INT32 what, e; \ |
INT64 num; \ |
DECODE("decode_number"); \ |
X=(what & TAG_MASK) | ((unsigned INT64)num<<4); \ |
EDB(5, fprintf(stderr, "%*s ==>%ld\n", \ |
data->depth, "", (long) X)); \ |
}while(0) \ |
|
|
static void restore_type_stack(struct pike_type **old_stackp) |
{ |
#if 0 |
fprintf(stderr, "Restoring type-stack: %p => %p\n", |
Pike_compiler->type_stackp, old_stackp); |
#endif /* 0 */ |
#ifdef PIKE_DEBUG |
if (old_stackp > Pike_compiler->type_stackp) { |
Pike_fatal("type stack out of sync!\n"); |
} |
#endif /* PIKE_DEBUG */ |
while(Pike_compiler->type_stackp > old_stackp) { |
free_type(*(Pike_compiler->type_stackp--)); |
} |
} |
|
static void restore_type_mark(struct pike_type ***old_type_mark_stackp) |
{ |
#if 0 |
fprintf(stderr, "Restoring type-mark: %p => %p\n", |
Pike_compiler->pike_type_mark_stackp, old_type_mark_stackp); |
#endif /* 0 */ |
#ifdef PIKE_DEBUG |
if (old_type_mark_stackp > Pike_compiler->pike_type_mark_stackp) { |
Pike_fatal("type Pike_interpreter.mark_stack out of sync!\n"); |
} |
#endif /* PIKE_DEBUG */ |
Pike_compiler->pike_type_mark_stackp = old_type_mark_stackp; |
} |
|
static void low_decode_type(struct decode_data *data) |
{ |
|
|
int tmp; |
ONERROR err1; |
ONERROR err2; |
|
SET_ONERROR(err1, restore_type_stack, Pike_compiler->type_stackp); |
SET_ONERROR(err2, restore_type_mark, Pike_compiler->pike_type_mark_stackp); |
|
tmp = GETC(); |
if (tmp <= MAX_TYPE) tmp ^= MIN_REF_TYPE; |
switch(tmp) |
{ |
default: |
decode_error(data, NULL, "Error in type string (%d).\n", tmp); |
|
break; |
|
case T_ASSIGN: |
tmp = GETC(); |
if ((tmp < '0') || (tmp > '9')) { |
decode_error(data, NULL, "Bad marker in type string (%d).\n", tmp); |
} |
low_decode_type(data); |
push_assign_type(tmp); |
break; |
|
case T_SCOPE: |
tmp = GETC(); |
low_decode_type(data); |
push_scope_type(tmp); |
break; |
|
case T_FUNCTION: |
{ |
int narg = 0; |
|
while (GETC() != T_MANY) { |
data->ptr--; |
low_decode_type(data); |
narg++; |
} |
low_decode_type(data); |
low_decode_type(data); |
push_reverse_type(T_MANY); |
while(narg-- > 0) { |
push_reverse_type(T_FUNCTION); |
} |
} |
break; |
|
case T_MAPPING: |
case T_OR: |
case T_AND: |
low_decode_type(data); |
low_decode_type(data); |
push_reverse_type(tmp); |
break; |
|
case T_TYPE: |
case T_PROGRAM: |
case T_ARRAY: |
case T_MULTISET: |
case T_NOT: |
low_decode_type(data); |
push_type(tmp); |
break; |
|
case T_INT: |
{ |
INT32 min=0, max=0; |
if(data->ptr + 8 > data->len) |
decode_error(data, NULL, "Not enough data.\n"); |
min = get_unaligned_be32(data->data + data->ptr); |
data->ptr += 4; |
max = get_unaligned_be32(data->data + data->ptr); |
data->ptr += 4; |
|
if (min > max) |
decode_error(data, NULL, "Error in int type (min (%d) > max (%d)).\n", min, max); |
|
push_int_type(min, max); |
} |
break; |
|
case T_STRING: |
|
push_finished_type(int_type_string); |
push_type(T_STRING); |
break; |
|
case PIKE_T_NSTRING: |
{ |
low_decode_type(data); |
push_type(T_STRING); |
} |
break; |
|
case '0': |
case '1': |
case '2': |
case '3': |
case '4': |
case '5': |
case '6': |
case '7': |
case '8': |
case '9': |
case T_FLOAT: |
case T_MIXED: |
case T_ZERO: |
case T_VOID: |
case PIKE_T_UNKNOWN: |
push_type(tmp); |
break; |
|
case PIKE_T_ATTRIBUTE: |
decode_value2(data); |
|
if (TYPEOF(Pike_sp[-1]) != PIKE_T_STRING) { |
decode_error(data, NULL, "Type attribute is not a string: %O\n", |
Pike_sp - 1); |
} |
low_decode_type(data); |
push_type_attribute(Pike_sp[-1].u.string); |
pop_stack(); |
break; |
|
case PIKE_T_NAME: |
decode_value2(data); |
|
if (TYPEOF(Pike_sp[-1]) != PIKE_T_STRING) { |
decode_error(data, NULL, "Type name is not a string: %O\n", |
Pike_sp - 1); |
} |
low_decode_type(data); |
push_type_name(Pike_sp[-1].u.string); |
pop_stack(); |
break; |
|
case T_OBJECT: |
{ |
int flag = GETC(); |
|
decode_value2(data); |
switch(TYPEOF(Pike_sp[-1])) |
{ |
case T_INT: |
push_object_type_backwards(flag, Pike_sp[-1].u.integer ); |
break; |
|
case T_PROGRAM: |
push_object_type_backwards(flag, Pike_sp[-1].u.program->id); |
break; |
|
case T_FUNCTION: |
{ |
struct program *prog; |
if (SUBTYPEOF(Pike_sp[-1]) == FUNCTION_BUILTIN) { |
decode_error(data, NULL, "Failed to decode object type.\n"); |
} |
prog = program_from_svalue(Pike_sp-1); |
if (!prog) { |
decode_error(data, NULL, "Failed to decode object type.\n"); |
} |
debug_malloc_touch(prog); |
push_object_type_backwards(flag, prog->id); |
} |
break; |
|
default: |
decode_error(data, NULL, "Failed to decode type " |
"(object(%s), expected object(zero|program)).\n", |
get_name_of_type(TYPEOF(Pike_sp[-1]))); |
} |
pop_stack(); |
} |
} |
|
UNSET_ONERROR(err2); |
UNSET_ONERROR(err1); |
} |
|
#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, & entry_id))) \ |
{ \ |
tmp=*tmpptr; \ |
VAR=tmp.u.U; \ |
SCOUR; \ |
}else{ \ |
SET_SVAL(tmp, TYPE, 0, 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 \ |
* freed if something goes wrong. \ |
*/ \ |
sub_ref(VAR); \ |
} \ |
}while(0) |
|
|
#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 (void *UNUSED(ignored)) |
{ |
debug_malloc_touch(Pike_compiler->new_program); |
debug_malloc_touch(Pike_compiler->new_program->parent); |
|
Pike_compiler->new_program->flags &= ~PROGRAM_AVOID_CHECK; |
end_first_pass(0); |
} |
|
static void restore_current_file(void *save_current_file) |
{ |
struct compilation *c = THIS_COMPILATION; |
free_string(c->lex.current_file); |
c->lex.current_file = save_current_file; |
} |
|
|
|
|
static INT32 decode_portable_bytecode(struct decode_data *data, INT32 string_no) |
{ |
struct program *p = Pike_compiler->new_program; |
struct pike_string *bytecode; |
struct pike_string *current_file=NULL; |
INT_TYPE current_line = 0; |
int e; |
ONERROR err; |
|
debug_malloc_touch(p); |
if ((string_no < 0) || (string_no >= p->num_strings)) { |
decode_error(data, NULL, |
"Bad bytecode string number: %d (expected 0 - %d).\n", |
string_no, p->num_strings-1); |
} |
|
bytecode = p->strings[string_no]; |
|
if (bytecode->len % 3) { |
decode_error(data, NULL, "Bad bytecode string length: " |
"%td (expected multiple of 3).\n", bytecode->len); |
} |
|
init_bytecode(); |
|
SET_ONERROR(err, exit_bytecode, NULL); |
|
switch(bytecode->size_shift) { |
#define SIGNED_CHAR(X) X |
|
#if SIZEOF_INT_TYPE > 4 |
#define DO_HIGH(X) (X) |
#else |
#define DO_HIGH(X) 0 |
#endif |
|
|
|
|
|
#define EMIT_BYTECODE2(STR) \ |
if (STR(bytecode)[e] == F_FILENAME) { \ |
INT32 strno = STR(bytecode)[e+1]; \ |
if (SIGNED_CHAR(strno < 0) || \ |
(strno >= p->num_strings)) { \ |
decode_error(data, NULL, "Bad filename directive number:" \ |
" %d (expected 0 - %d).\n", \ |
strno, p->num_strings); \ |
} \ |
current_file = p->strings[strno]; \ |
} else if (STR(bytecode)[e] == F_LINE) { \ |
current_line = \ |
((unsigned INT32)STR(bytecode)[e+1]) | \ |
DO_HIGH(((INT_TYPE)STR(bytecode)[e+2])<<32); \ |
} else if (!current_file) { \ |
decode_error(data, NULL, "Missing filename directive in " \ |
"byte code.\n"); \ |
} else if (!current_line) { \ |
decode_error(data, NULL, "Missing line directive in " \ |
"byte code.\n"); \ |
} else |
|
#define EMIT_BYTECODE(STR, X) do { \ |
for (e = 0; e < bytecode->len; e += 3) { \ |
X(STR) \ |
{ \ |
insert_opcode2(STR(bytecode)[e], \ |
STR(bytecode)[e+1], \ |
STR(bytecode)[e+2], \ |
current_line, \ |
current_file); \ |
} \ |
} \ |
} while(0) |
|
case 2: |
EMIT_BYTECODE(STR2, EMIT_BYTECODE2); |
break; |
#undef SIGNED_CHAR |
#define SIGNED_CHAR(X) 0 |
case 1: |
EMIT_BYTECODE(STR1, EMIT_BYTECODE2); |
break; |
case 0: |
#undef EMIT_BYTECODE2 |
#define EMIT_BYTECODE2(X) \ |
if (!current_file) { \ |
decode_error(data, NULL, "Missing filename directive in " \ |
"byte code.\n"); \ |
} else if (!current_line) { \ |
decode_error(data, NULL, "Missing line directive in " \ |
"byte code.\n"); \ |
} else |
|
EMIT_BYTECODE(STR0, EMIT_BYTECODE2); |
break; |
#undef SIGNED_CHAR |
#undef EMIT_BYTECODE |
#undef EMIT_BYTECODE2 |
#ifdef PIKE_DEBUG |
default: |
Pike_fatal("Bad size_shift: %d\n", bytecode->size_shift); |
#endif |
} |
UNSET_ONERROR(err); |
return assemble(1); |
} |
|
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; |
INT64 num; |
struct svalue entry_id, *tmp2; |
struct svalue *delayed_enc_val; |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
check_c_stack(1024); |
|
DECODE("decode_value2"); |
|
switch(what & TAG_MASK) |
{ |
case TAG_DELAYED: |
EDB (2, fprintf(stderr, "%*sDecoding delay encoded from <%d>\n", |
data->depth, "", num);); |
SET_SVAL(entry_id, T_INT, NUMBER_NUMBER, integer, num); |
if (!(delayed_enc_val = low_mapping_lookup (data->decoded, &entry_id))) |
decode_error (data, NULL, "Failed to find previous record of " |
"delay encoded entry <%d>.\n", num); |
DECODE ("decode_value2"); |
break; |
|
case TAG_AGAIN: |
EDB (1, fprintf(stderr, "%*sDecoding TAG_AGAIN from <%d>\n", |
data->depth, "", num);); |
SET_SVAL(entry_id, T_INT, NUMBER_NUMBER, integer, num); |
if((tmp2=low_mapping_lookup(data->decoded, &entry_id))) |
{ |
push_svalue(tmp2); |
}else{ |
decode_error(data, NULL, "Failed to decode TAG_AGAIN entry <%d>.\n", |
num); |
} |
goto decode_done; |
|
default: |
entry_id = data->counter; |
data->counter.u.integer++; |
|
|
case TAG_TYPE: |
EDB (2, fprintf(stderr, "%*sDecoding to <%d>: TAG%d (%d)\n", |
data->depth, "", entry_id.u.integer , |
what & TAG_MASK, num);); |
|
|
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; |
get_string_data(str, num, data); |
push_string(str); |
break; |
} |
|
case TAG_FLOAT: |
{ |
double res; |
|
EDB(2,fprintf(stderr, "Decoding float... num:0x%016" PRINTINT64 "x\n", |
num)); |
|
res = (double)num; |
|
EDB(2,fprintf(stderr, "Mantissa: %10g\n", res)); |
|
DECODE("float"); |
|
EDB(2,fprintf(stderr, "Exponent: %d\n", num)); |
|
if(!res) |
{ |
DECLARE_INF |
DECLARE_NAN |
|
switch(num) |
{ |
case Pike_FP_SNAN: |
case Pike_FP_QNAN: |
push_float(DO_NOT_WARN((FLOAT_TYPE)MAKE_NAN())); |
break; |
|
case Pike_FP_NINF: |
push_float(DO_NOT_WARN((FLOAT_TYPE)MAKE_INF(-1))); |
break; |
|
case Pike_FP_PINF: |
push_float(DO_NOT_WARN((FLOAT_TYPE)MAKE_INF(1))); |
break; |
|
case Pike_FP_NZERO: |
push_float(-0.0); |
break; |
|
default: |
push_float(DO_NOT_WARN((FLOAT_TYPE)ldexp(res, num))); |
break; |
} |
break; |
} |
|
push_float(DO_NOT_WARN((FLOAT_TYPE)ldexp(res, num))); |
break; |
} |
|
case TAG_TYPE: |
{ |
struct pike_type *t; |
|
decode_type(t, data); |
push_type_value(t); |
|
entry_id = data->counter; |
data->counter.u.integer++; |
} |
break; |
|
case TAG_ARRAY: |
{ |
struct array *a; |
TYPE_FIELD types; |
if(num < 0) |
decode_error(data, NULL, |
"Failed to decode array (array size is negative).\n"); |
|
|
if(num > data->len - data->ptr) |
decode_error(data, NULL, "Failed to decode array (not enough data).\n"); |
|
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, 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 << TYPEOF(ITEM(a)[e]); |
} |
a->type_field = types; |
ref_push_array(a); |
goto decode_done; |
} |
|
case TAG_MAPPING: |
{ |
struct mapping *m; |
if(num<0) |
decode_error(data, NULL, "Failed to decode mapping " |
"(mapping size is negative).\n"); |
|
|
if(num > data->len - data->ptr) |
decode_error(data, NULL, "Failed to decode mapping " |
"(not enough data).\n"); |
|
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, 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); |
goto decode_done; |
} |
|
case TAG_MULTISET: |
{ |
struct multiset *m; |
struct array *a; |
TYPE_FIELD types; |
if(num<0) |
decode_error(data, NULL, "Failed to decode multiset " |
"(multiset size is negative).\n"); |
|
|
if(num > data->len - data->ptr) |
decode_error(data, NULL, "Failed to decode multiset " |
"(not enough data).\n"); |
|
|
|
EDB(2,fprintf(stderr, "%*sDecoding multiset of size %d to <%d>\n", |
data->depth, "", num, entry_id.u.integer)); |
SETUP_DECODE_MEMOBJ (T_MULTISET, multiset, m, |
allocate_multiset (0, 0, NULL), ;); |
|
a = low_allocate_array (num, 0); |
|
types = 0; |
for(e=0;e<num;e++) |
{ |
decode_value2(data); |
stack_pop_to_no_free (ITEM(a) + e); |
types |= 1 << TYPEOF(ITEM(a)[e]); |
} |
a->type_field = types; |
{ |
struct multiset *l = mkmultiset (a); |
free_array (a); |
|
merge_multisets (m, l, PIKE_MERGE_DESTR_A | PIKE_ARRAY_OP_ADD); |
free_multiset (l); |
} |
ref_push_multiset(m); |
goto decode_done; |
} |
|
case TAG_OBJECT: |
{ |
int subtype = 0; |
if (num == 4) { |
decode_number(subtype, data); |
} |
decode_value2(data); |
|
switch(num) |
{ |
case 0: |
apply(decoder_codec (data),"objectof", 1); |
break; |
|
case 1: |
{ |
int fun; |
|
|
|
struct object *o=decode_value_clone_object(Pike_sp-1); |
|
if (!o) { |
if (data->pickyness) |
decode_error (data, NULL, |
"Failed to decode program for object. Got: %O\n", |
Pike_sp - 1); |
EDB(1,fprintf(stderr, "%*sDecoded a failed object to <%d>: ", |
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(); |
push_object(o); |
|
if(o->prog) |
{ |
if(o->prog->flags & PROGRAM_FINISHED) |
{ |
int lfun = FIND_LFUN(o->prog, LFUN___INIT); |
if (lfun >= 0) { |
apply_low(o, lfun, 0); |
pop_stack(); |
} |
|
|
}else{ |
struct unfinished_obj_link *ol=ALLOC_STRUCT(unfinished_obj_link); |
EDB(2,fprintf(stderr, |
"%*sDecoded an unfinished object to <%d>: ", |
data->depth, "", entry_id.u.integer); |
print_svalue(stderr, Pike_sp-1); |
fputc('\n', stderr);); |
add_ref(ol->o = o); |
ol->next=data->unfinished_objects; |
SET_SVAL(ol->decode_arg, PIKE_T_INT, NUMBER_UNDEFINED, |
integer, 0); |
data->unfinished_objects=ol; |
decode_value2(data); |
assign_svalue(&ol->decode_arg, Pike_sp-1); |
pop_stack(); |
break; |
} |
} |
|
EDB(2,fprintf(stderr, "%*sDecoded an object to <%d>: ", |
data->depth, "", entry_id.u.integer); |
print_svalue(stderr, Pike_sp-1); |
fputc('\n', stderr);); |
|
ref_push_object(o); |
decode_value2(data); |
|
fun = find_identifier("decode_object", decoder_codec (data)->prog); |
if (fun < 0) |
decode_error(data, Pike_sp - 1, |
"Cannot decode objects without a " |
"\"decode_object\" function in the codec.\n"); |
apply_low(data->codec,fun,2); |
if ((TYPEOF(Pike_sp[-1]) == T_ARRAY) && o->prog && |
((fun = FIND_LFUN(o->prog, LFUN_CREATE)) != -1)) { |
|
INT32 args; |
Pike_sp--; |
args = Pike_sp->u.array->size; |
if (args) { |
|
push_array_items(Pike_sp->u.array); |
} else { |
free_array(Pike_sp->u.array); |
} |
apply_low(o, fun, args); |
} |
pop_stack(); |
} |
|
break; |
|
case 2: |
{ |
check_stack(2); |
|
|
|
push_int(36); |
convert_stack_top_with_base_to_bignum(); |
reduce_stack_top_bignum(); |
break; |
} |
|
case 3: |
pop_stack(); |
decode_value2(data); |
break; |
|
case 4: |
|
if ((TYPEOF(Pike_sp[-1]) != T_OBJECT) || SUBTYPEOF(Pike_sp[-1]) || |
!Pike_sp[-1].u.object->prog) { |
decode_error(data, NULL, "Expected plain object. Got: %O\n", |
Pike_sp-1); |
} |
if ((subtype < 0) || |
(subtype >= Pike_sp[-1].u.object->prog->num_inherits)) { |
decode_error(data, NULL, |
"Invalid subtype for object: %d (max: %d). " |
"Object: %O\n", |
subtype, Pike_sp[-1].u.object->prog->num_inherits, |
Pike_sp-1); |
} |
SET_SVAL_SUBTYPE(Pike_sp[-1], subtype); |
break; |
|
default: |
decode_error(data, NULL, "Object coding not compatible: %d\n", num); |
break; |
} |
|
if((TYPEOF(Pike_sp[-1]) != T_OBJECT) && data->pickyness) { |
if (num != 2) { |
decode_error(data, NULL, "Failed to decode object. Got: %O\n", |
Pike_sp - 1); |
} else if (TYPEOF(Pike_sp[-1]) != PIKE_T_INT) { |
decode_error(data, NULL, "Failed to decode bignum. Got: %O\n", |
Pike_sp - 1); |
} |
} |
|
break; |
} |
|
case TAG_FUNCTION: |
decode_value2(data); |
stack_dup(); |
|
switch(num) |
{ |
case 0: |
apply(decoder_codec (data),"functionof", 1); |
break; |
|
case 1: { |
struct program *p; |
if(TYPEOF(Pike_sp[-1]) != T_OBJECT && data->pickyness) |
decode_error(data, NULL, |
"Failed to decode function object. Got: %O\n", |
Pike_sp - 1); |
|
decode_value2(data); |
if(TYPEOF(Pike_sp[-1]) != T_STRING && data->pickyness) |
decode_error(data, NULL, |
"Failed to decode function identifier. Got: %O\n", |
Pike_sp - 1); |
|
if (TYPEOF(Pike_sp[-2]) == T_OBJECT && |
TYPEOF(Pike_sp[-1]) == T_STRING && |
(p = Pike_sp[-2].u.object->prog)) { |
int f = really_low_find_shared_string_identifier( |
Pike_sp[-1].u.string, |
p->inherits[SUBTYPEOF(Pike_sp[-2])].prog, |
SEE_PROTECTED|SEE_PRIVATE); |
debug_malloc_touch(p); |
if (f >= 0) { |
struct svalue func; |
low_object_index_no_free(&func, Pike_sp[-2].u.object, f); |
debug_malloc_touch(p); |
pop_n_elems(2); |
*Pike_sp++ = func; |
dmalloc_touch_svalue(Pike_sp-1); |
break; |
} |
else if (data->pickyness) { |
debug_malloc_touch(p); |
if (Pike_sp[-1].u.string->size_shift) |
decode_error(data, NULL, "Couldn't find identifier in %O.\n", |
Pike_sp - 2); |
else |
decode_error(data, NULL, "Couldn't find identifier %s in %O.\n", |
Pike_sp[-1].u.string->str, Pike_sp - 2); |
} |
debug_malloc_touch(p); |
} |
pop_stack(); |
break; |
} |
|
default: |
decode_error(data, NULL, "Function coding not compatible: %d\n", num); |
break; |
} |
|
if((TYPEOF(Pike_sp[-1]) != T_FUNCTION) && |
(TYPEOF(Pike_sp[-1]) != T_PROGRAM) && |
data->pickyness) |
decode_error(data, Pike_sp - 2, |
"Failed to decode function. Got: %O\n", Pike_sp - 1); |
|
stack_pop_keep_top(); |
|
break; |
|
|
case TAG_PROGRAM: |
EDB(3, |
fprintf(stderr, "%*s TAG_PROGRAM(%d)\n", |
data->depth, "", num)); |
switch(num) |
{ |
case 0: |
{ |
struct program *p; |
|
decode_value2(data); |
apply(decoder_codec (data),"programof", 1); |
|
p = program_from_svalue(Pike_sp-1); |
|
if (!p) { |
if(data->pickyness) |
decode_error(data, NULL, "Failed to decode program. Got: %O\n", |
Pike_sp - 1); |
pop_stack(); |
push_undefined(); |
break; |
} |
|
if ((p->flags & PROGRAM_NEEDS_PARENT)) { |
EDB(2, fprintf(stderr, "%*sKeeping %s to keep parent pointer.\n", |
data->depth, "", |
get_name_of_type(TYPEOF(Pike_sp[-1])))); |
break; |
} |
|
add_ref(p); |
pop_stack(); |
push_program(p); |
break; |
} |
|
case 1: |
{ |
decode_error(data, NULL, "Failed to decode program. Old-style program encoding is not supported, anymore.\n"); |
} |
|
case 2: |
decode_value2(data); |
decode_value2(data); |
if(TYPEOF(Pike_sp[-2]) == T_INT) |
{ |
pop_stack(); |
}else{ |
f_arrow(2); |
} |
if(TYPEOF(Pike_sp[-1]) != T_PROGRAM && data->pickyness) |
decode_error(data, NULL, "Failed to decode program. Got: %O\n", |
Pike_sp - 1); |
break; |
|
case 3: |
decode_value2(data); |
if ((TYPEOF(Pike_sp[-1]) == 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) { |
decode_error(data, NULL, "Failed to get program from ID %O.\n", |
Pike_sp - 1); |
} |
pop_stack(); |
ref_push_program(p); |
} else { |
decode_error(data, NULL, "Failed to decode program by ID. " |
"Expected integer, got: %O\n", Pike_sp - 1); |
} |
break; |
|
case 5: { |
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);); |
|
data->delay_counter++; |
|
#if 0 |
|
* adequate context to __register_new_program so that it |
* knows which program is being decoded? */ |
ref_push_program (p); |
apply (decoder_codec (data), "__register_new_program", 1); |
|
|
if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { |
if (Pike_sp[-1].u.object->prog != null_program) |
decode_error (data, NULL, "Placeholder object is not " |
"a null_program clone.\n"); |
} |
else if (TYPEOF(Pike_sp[-1]) != T_INT || |
Pike_sp[-1].u.integer) |
decode_error (data, NULL, "Expected placeholder object or zero " |
"from __register_new_program.\n"); |
pop_stack(); |
#endif |
|
break; |
} |
|
case 4: |
{ |
struct program *p; |
ONERROR err; |
ONERROR err2; |
int byteorder; |
int bytecode_method; |
int entry_type; |
INT16 id_flags; |
INT16 p_flags; |
ptrdiff_t old_pragmas; |
struct compilation *c; |
struct pike_string *save_current_file; |
struct object *placeholder = NULL; |
INT_TYPE save_current_line; |
#define FOO(NUMTYPE,Y,ARGTYPE,NAME) \ |
NUMTYPE PIKE_CONCAT(local_num_, NAME) = 0; |
#include "program_areas.h" |
|
#ifdef ENCODE_DEBUG |
data->depth += 2; |
#endif |
|
|
decode_number(byteorder, data); |
|
EDB(4, |
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 |
) { |
decode_error (data, NULL, "Unsupported byte-order. " |
"Native:%d Encoded:%d\n", PIKE_BYTEORDER, byteorder); |
} |
|
|
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 (TYPEOF(*delayed_enc_val) != T_PROGRAM || |
delayed_enc_val->u.program->flags != PROGRAM_VIRGIN) { |
decode_error (data, NULL, "Didn't get program embryo " |
"for delay encoded program <%O>: %O\n", |
&entry_id, delayed_enc_val); |
} |
|
|
|
p = delayed_enc_val->u.program; |
debug_malloc_touch(p); |
} |
else |
p = NULL; |
|
enter_compiler(NULL, 0); |
|
c = THIS_COMPILATION; |
|
|
|
|
old_pragmas = c->lex.pragmas; |
c->lex.pragmas = (old_pragmas & ~ID_SAVE_PARENT)|ID_DONT_SAVE_PARENT; |
|
|
low_start_new_program(p, 1, NULL, 0, NULL); |
p = Pike_compiler->new_program; |
#if TWO_PASS_DECODE_WORKS |
if(! data->supporter.prog) |
data->supporter.prog = p; |
#endif |
|
p->flags = p_flags; |
|
|
Pike_compiler->num_parse_error++; |
|
SET_ONERROR(err, cleanup_new_program_decode, NULL); |
|
{ |
int fun = find_identifier("__register_new_program", |
decoder_codec (data)->prog); |
|
if (fun >= 0) { |
ref_push_program(p); |
apply_low(data->codec, fun, 1); |
|
|
if(TYPEOF(Pike_sp[-1]) == T_OBJECT) |
{ |
add_ref(c->placeholder=Pike_sp[-1].u.object); |
if(c->placeholder->prog != null_program) { |
decode_error(data, NULL, "Placeholder object is not " |
"a __null_program clone.\n"); |
} |
} else if (TYPEOF(Pike_sp[-1]) != T_INT || |
Pike_sp[-1].u.integer) { |
decode_error (data, NULL, "Expected placeholder object or zero " |
"from __register_new_program.\n"); |
} |
pop_stack(); |
} |
} |
|
copy_shared_string(save_current_file, c->lex.current_file); |
save_current_line = c->lex.current_line; |
|
SET_ONERROR(err2, restore_current_file, save_current_file); |
|
if (!delayed_enc_val) { |
struct svalue prog; |
SET_SVAL(prog, T_PROGRAM, 0, program, p); |
EDB(2,fprintf(stderr, "%*sDecoding a program to <%d>: ", |
data->depth, "", entry_id.u.integer); |
print_svalue(stderr, &prog); |
fputc('\n', stderr);); |
mapping_insert(data->decoded, &entry_id, &prog); |
debug_malloc_touch(p); |
} else { |
data->delay_counter--; |
} |
|
debug_malloc_touch(p); |
|
|
decode_value2(data); |
push_compact_version(); |
if(!is_eq(Pike_sp-1,Pike_sp-2) |
#ifdef ENCODE_DEBUG |
&& !data->debug |
#endif |
) |
decode_error(data, NULL, "Cannot decode programs encoded with " |
"other pike version %O.\n", Pike_sp - 2); |
pop_n_elems(2); |
|
debug_malloc_touch(p); |
|
#ifdef ENCODE_DEBUG |
if (!data->debug) |
#endif |
data->pickyness++; |
|
|
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) == T_PROGRAM) { |
p->parent = Pike_sp[-1].u.program; |
debug_malloc_touch(p->parent); |
} else if ((TYPEOF(Pike_sp[-1]) == T_INT) && |
(!Pike_sp[-1].u.integer)) { |
p->parent = NULL; |
} else { |
decode_error (data, NULL, "Bad type for parent program (%s).\n", |
get_name_of_type(TYPEOF(Pike_sp[-1]))); |
} |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp--; |
|
|
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
decode_number(PIKE_CONCAT(local_num_, NAME), data); |
#include "program_areas.h" |
|
|
decode_number(bytecode_method, data); |
if (bytecode_method == PIKE_BYTECODE_PORTABLE) { |
} else if (bytecode_method != PIKE_BYTECODE_METHOD) { |
decode_error(data, NULL, "Unsupported byte-code method: %d\n", |
bytecode_method); |
} else { |
|
#ifdef PIKE_PORTABLE_BYTECODE |
fprintf(stderr, "Warning: Decoding non-portable bytecode.\n"); |
#endif /* PIKE_PORTABLE_BYTECODE */ |
|
#ifdef PIKE_USE_MACHINE_CODE |
{ |
size_t csum; |
|
decode_number(csum, data); |
if (csum != instrs_checksum) { |
decode_error(data, NULL, |
"Bad instruction checksum: %d (expected %d)\n", |
csum, instrs_checksum); |
} |
} |
#endif /* PIKE_USE_MACHINE_CODE */ |
|
|
if (SIZE_T_MUL_OVERFLOW(local_num_program, sizeof(PIKE_OPCODE_T)) || |
local_num_program * sizeof(PIKE_OPCODE_T) >= (size_t)(data->len - data->ptr)) { |
decode_error(data, NULL, |
"Failed to decode program (string too short).\n"); |
} |
low_add_many_to_program(Pike_compiler, |
(PIKE_OPCODE_T *)(data->data + data->ptr), |
local_num_program); |
data->ptr += local_num_program * sizeof(PIKE_OPCODE_T); |
|
|
for (e=0; e<(int)local_num_relocations; e++) { |
size_t reloc; |
decode_number(reloc, data); |
CHECK_RELOC(reloc, (size_t) local_num_program); |
add_to_relocations(reloc); |
} |
|
|
#ifdef DECODE_PROGRAM |
DECODE_PROGRAM(p); |
#endif /* DECODE_PROGRAM */ |
make_program_executable(p); |
|
|
if (local_num_linenumbers >= (size_t)(data->len - data->ptr)) { |
decode_error(data, NULL, "Failed to decode linenumbers " |
"(string too short).\n"); |
} |
for (e=0; e<(int)local_num_linenumbers; e++) { |
char lineno_info; |
lineno_info = *(data->data + data->ptr++); |
add_to_linenumbers(lineno_info); |
} |
|
|
|
|
EDB(2, |
fprintf(stderr, "%*sThe program is: ", data->depth, ""); |
push_program (p); |
print_svalue (stderr, --Pike_sp); |
fputc('\n', stderr)); |
} |
|
|
|
|
|
|
for (e=0; e<local_num_strings; e++) { |
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) != T_STRING) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Nonstrings in string table: %O\n", Pike_sp - 2); |
} |
add_to_strings(Pike_sp[-1].u.string); |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp--; |
} |
|
|
|
|
|
{ |
struct program_constant constant; |
SET_SVAL(constant.sval, T_INT, NUMBER_UNDEFINED, integer, 0); |
constant.offset = -1; |
|
for(e=0;e<local_num_constants;e++) { |
add_to_constants(constant); |
} |
} |
|
|
decode_number(entry_type, data); |
EDB(4, |
fprintf(stderr, "%*sDecoding identifier references.\n", |
data->depth, "")); |
#ifdef ENCODE_DEBUG |
data->depth+=2; |
#endif |
while ((entry_type == ID_ENTRY_EFUN_CONSTANT) || |
(entry_type == ID_ENTRY_TYPE_CONSTANT)) { |
INT32 efun_no; |
struct program_constant *constant; |
decode_number(efun_no, data); |
EDB(2, |
fprintf(stderr, "%*sDecoding efun/type constant #%d.\n", |
data->depth, "", efun_no)); |
if ((efun_no < 0) || (efun_no >= local_num_constants)) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad efun/type number: %d (expected 0 - %d).\n", |
efun_no, local_num_constants-1); |
} |
constant = p->constants+efun_no; |
|
decode_value2(data); |
switch(entry_type) { |
case ID_ENTRY_EFUN_CONSTANT: |
if (((TYPEOF(Pike_sp[-1]) != T_FUNCTION) || |
(SUBTYPEOF(Pike_sp[-1]) != FUNCTION_BUILTIN)) && |
data->pickyness) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Expected efun constant: %O\n", Pike_sp - 2); |
} |
break; |
case ID_ENTRY_TYPE_CONSTANT: |
if (TYPEOF(Pike_sp[-1]) != T_TYPE && data->pickyness) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Expected type constant: %O\n", Pike_sp - 2); |
} |
break; |
default: |
if (data->pickyness) |
decode_error(data, NULL, "Internal error: " |
"Unsupported early constant (%d).\n", |
entry_type); |
break; |
} |
|
decode_value2(data); |
#if 0 |
if (TYPEOF(Pike_sp[-1]) == T_STRING) { |
constant->name = Pike_sp[-1].u.string; |
} else if ((TYPEOF(Pike_sp[-1]) == T_INT) && |
!Pike_sp[-1].u.integer) { |
constant->name = NULL; |
} else { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Name of constant is not a string: %O\n", |
Pike_sp - 2); |
} |
constant->sval = Pike_sp[-2]; |
dmalloc_touch_svalue(Pike_sp-1); |
dmalloc_touch_svalue(Pike_sp-2); |
Pike_sp -= 2; |
#else /* !0 */ |
constant->offset = -1; |
pop_stack(); |
constant->sval = Pike_sp[-1]; |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp -= 1; |
#endif /* 0 */ |
decode_number(entry_type, data); |
} |
|
while (entry_type != ID_ENTRY_EOT) { |
decode_number(id_flags, data); |
if ((entry_type != ID_ENTRY_RAW) && |
(entry_type != ID_ENTRY_INHERIT)) { |
|
|
unsigned INT32 filename_strno; |
|
|
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) != T_STRING) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad identifier name (not a string): %O\n", |
Pike_sp - 2); |
} |
|
|
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) != T_TYPE) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad identifier type (not a type): %O\n", |
Pike_sp - 2); |
} |
|
|
decode_number(filename_strno, data); |
if (filename_strno >= p->num_strings) { |
ref_push_program(p); |
decode_error(data, NULL, |
"String number out of range: %ld >= %ld", |
(long)filename_strno, (long)p->num_strings); |
} |
free_string(c->lex.current_file); |
copy_shared_string(c->lex.current_file, |
p->strings[filename_strno]); |
|
|
decode_number(c->lex.current_line, data); |
|
|
|
|
} |
switch(entry_type) { |
case ID_ENTRY_RAW: |
{ |
int no; |
int ref_no; |
struct reference ref; |
|
|
ref.id_flags = id_flags; |
|
|
decode_number(ref.inherit_offset, data); |
|
|
|
decode_number(ref_no, data); |
|
if (ref.inherit_offset >= p->num_inherits) |
decode_error(data, NULL, "Inherit offset out of range %u vs %u.\n", |
ref.inherit_offset, p->num_inherits); |
if (ref_no < 0 || ref_no >= p->inherits[ref.inherit_offset].prog->num_identifier_references) |
decode_error(data, NULL, "Identifier reference out of range %u vs %u.\n", |
ref_no, p->inherits[ref.inherit_offset].prog->num_identifier_references); |
|
ref.identifier_offset = p->inherits[ref.inherit_offset].prog-> |
identifier_references[ref_no].identifier_offset; |
|
ref.run_time_type = PIKE_T_UNKNOWN; |
ref.func.offset = 0; |
|
|
decode_number(no, data); |
|
if (no < 0 || no > p->num_identifier_references) { |
EDB (3, dump_program_tables (p, data->depth)); |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad identifier reference offset: %d != %d\n", |
no, |
Pike_compiler->new_program-> |
num_identifier_references); |
} else if (no == p->num_identifier_references) { |
add_to_identifier_references(ref); |
} |
else { |
p->identifier_references[no] = ref; |
} |
} |
break; |
|
case ID_ENTRY_VARIABLE: |
{ |
int no, n; |
|
|
decode_number(no, data); |
|
EDB(5, |
fprintf(stderr, |
"%*sdefine_variable(\"%s\", X, 0x%04x)\n", |
data->depth, "", |
Pike_sp[-2].u.string->str, id_flags)); |
|
|
|
|
|
|
n = define_variable(Pike_sp[-2].u.string, |
Pike_sp[-1].u.type, |
id_flags); |
if (no != n) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad variable identifier offset " |
"(got %d, expected %d).\n", n, no); |
} |
|
pop_n_elems(2); |
} |
break; |
case ID_ENTRY_FUNCTION: |
{ |
union idptr func; |
unsigned INT8 func_flags; |
unsigned INT16 opt_flags; |
int no; |
int n; |
|
|
decode_number(func_flags, data); |
|
|
decode_number(func.offset, data); |
if (bytecode_method == PIKE_BYTECODE_PORTABLE && |
func.offset != -1) { |
#ifdef ENCODE_DEBUG |
int old_a_flag; |
#endif |
EDB(2, |
{ |
fprintf(stderr, "%*sDecoding portable bytecode.\n", |
data->depth, ""); |
old_a_flag = a_flag; |
a_flag = (a_flag > (data->debug-1))?a_flag:(data->debug-1); |
}); |
func.offset = decode_portable_bytecode(data, func.offset); |
EDB(2, a_flag = old_a_flag); |
} |
|
|
decode_number(opt_flags, data); |
|
|
|
|
|
|
decode_number(no, data); |
|
EDB(5, { |
INT_TYPE line; |
struct pike_string *file = |
get_line(func.offset + p->program, p, &line); |
fprintf(stderr, |
"%*sdefine_function(\"%s\", X, 0x%04x, 0x%04x,\n" |
"%*s 0x%04x, 0x%04x)\n" |
"%*s @ %s:%ld\n", |
data->depth, "", |
Pike_sp[-2].u.string->str, id_flags, func_flags, |
data->depth, "", |
func.offset, opt_flags, |
data->depth, "", |
file->str, (long)line); |
}); |
|
|
|
|
|
n = define_function(Pike_sp[-2].u.string, |
Pike_sp[-1].u.type, |
id_flags, func_flags, |
&func, opt_flags); |
if ((no < 0 || no >= p->num_identifier_references) || |
(no != n && |
(p->identifier_references[no].id_flags != id_flags || |
p->identifier_references[no].identifier_offset != |
p->identifier_references[n].identifier_offset || |
p->identifier_references[no].inherit_offset != 0))) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad function identifier offset: %d\n", no); |
} |
|
pop_n_elems(2); |
} |
break; |
case ID_ENTRY_CONSTANT: |
{ |
struct identifier id; |
struct reference ref; |
int no; |
int n; |
|
id.filename_strno = store_prog_string(c->lex.current_file); |
id.linenumber = c->lex.current_line; |
|
id.name = Pike_sp[-2].u.string; |
id.type = Pike_sp[-1].u.type; |
|
|
id.identifier_flags = IDENTIFIER_CONSTANT; |
|
|
decode_number(id.func.const_info.offset, data); |
|
|
|
|
|
|
decode_number(id.run_time_type, data); |
|
|
decode_number(id.opt_flags, data); |
|
ref.run_time_type = PIKE_T_UNKNOWN; |
ref.func.offset = 0; |
|
|
decode_number(no, data); |
|
n = isidentifier(id.name); |
|
#ifdef PROFILING |
id.self_time=0; |
id.num_calls=0; |
id.recur_depth=0; |
id.total_time=0; |
#endif |
|
|
ref.id_flags = id_flags; |
|
EDB(5, |
fprintf(stderr, |
"%*sdefining constant(\"%s\", X, 0x%04x)\n", |
data->depth, "", |
Pike_sp[-2].u.string->str, id_flags)); |
|
|
ref.identifier_offset = |
Pike_compiler->new_program->num_identifiers; |
add_to_identifiers(id); |
|
|
dmalloc_touch_svalue(Pike_sp-1); |
dmalloc_touch_svalue(Pike_sp-2); |
Pike_sp -= 2; |
|
|
ref.inherit_offset = 0; |
|
|
|
|
|
|
if (n < 0 || (n = override_identifier (&ref, id.name, 0)) < 0) { |
n = p->num_identifier_references; |
add_to_identifier_references(ref); |
} |
|
if (no != n) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad function identifier offset " |
"(expected %d, got %d) for %S.\n", |
no, n, id.name); |
} |
|
} |
break; |
case ID_ENTRY_ALIAS: |
{ |
int depth; |
int refno; |
int no; |
int n; |
|
|
decode_number(depth, data); |
|
|
decode_number(refno, data); |
|
|
|
|
|
|
decode_number(no, data); |
|
EDB(5, |
fprintf(stderr, |
"%*slow_define_alias(\"%s\", X, 0x%04x)\n", |
data->depth, "", |
Pike_sp[-2].u.string->str, id_flags)); |
|
|
|
|
|
|
n = low_define_alias(Pike_sp[-2].u.string, |
Pike_sp[-1].u.type, id_flags, |
depth, refno); |
|
if (no != n) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad alias identifier offset " |
"(expected %d, got %d) for %O.\n", |
no, n, Pike_sp - 3); |
} |
|
pop_n_elems(2); |
} |
break; |
case ID_ENTRY_INHERIT: |
{ |
struct program *prog; |
struct object *parent = NULL; |
int parent_identifier; |
int parent_offset; |
struct pike_string *name = NULL; |
int no; |
|
decode_number(no, data); |
if (no != |
Pike_compiler->new_program->num_identifier_references) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad inherit identifier offset: %d\n", no); |
} |
|
|
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) == T_STRING) { |
name = Pike_sp[-1].u.string; |
} else if ((TYPEOF(Pike_sp[-1]) != T_INT) || |
Pike_sp[-1].u.integer) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad inherit name (not a string): %O\n", |
Pike_sp - 2); |
} |
|
|
decode_value2(data); |
if (!(prog = program_from_svalue(Pike_sp-1))) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad inherit: Expected program, got: %O\n", |
Pike_sp - 2); |
} |
if (prog == placeholder_program) { |
ref_push_program (p); |
decode_error (data, Pike_sp - 1, |
"Trying to inherit placeholder program " |
"(resolver or codec problem).\n"); |
} |
if(!(prog->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) { |
ref_push_program (p); |
decode_error (data, Pike_sp - 1, |
"Cannot inherit a program which is not " |
"fully compiled yet (resolver or codec " |
"problem): %O\n", Pike_sp - 2); |
} |
|
|
decode_value2(data); |
if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { |
parent = Pike_sp[-1].u.object; |
} else if ((TYPEOF(Pike_sp[-1]) != T_INT) || |
Pike_sp[-1].u.integer) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Bad inherit: Parent isn't an object: %O\n", |
Pike_sp - 2); |
} |
|
|
decode_number(parent_identifier, data); |
|
|
decode_number(parent_offset, data); |
|
|
decode_number(no, data); |
|
if (prog->num_identifier_references != no) { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, "Bad number of identifiers " |
"in inherit (%d != %d).\n", |
no, prog->num_identifier_references); |
} |
|
EDB(5, |
fprintf(stderr, |
"%*slower_inherit(..., \"%s\")\n", |
data->depth, "", |
name?name->str:"NULL")); |
|
|
|
|
|
lower_inherit(prog, parent, parent_identifier, |
parent_offset + 42, id_flags, name); |
|
pop_n_elems(3); |
} |
break; |
default: |
decode_error(data, NULL, "Unsupported id entry type: %d\n", |
entry_type); |
} |
decode_number(entry_type, data); |
} |
|
|
CALL_AND_UNSET_ONERROR(err2); |
c->lex.current_line = save_current_line; |
|
#ifdef ENCODE_DEBUG |
data->depth-=2; |
#endif |
|
UNSET_ONERROR(err); |
|
|
Pike_compiler->num_parse_error--; |
|
p->flags |= PROGRAM_PASS_1_DONE; |
|
|
|
|
|
ref_push_program (p); |
if (!(p = end_first_pass(2))) { |
decode_error(data, Pike_sp - 1, "Failed to decode program.\n"); |
} |
pop_stack(); |
push_program(p); |
|
if (c->placeholder) { |
push_object(placeholder = c->placeholder); |
c->placeholder = NULL; |
} |
|
exit_compiler(); |
|
EDB(5, dump_program_tables(p, data->depth)); |
#ifdef PIKE_DEBUG |
check_program (p); |
#endif |
|
if (bytecode_method == PIKE_BYTECODE_PORTABLE) { |
|
local_num_program = p->num_program; |
local_num_relocations = p->num_relocations; |
local_num_linenumbers = p->num_linenumbers; |
} |
|
|
#define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \ |
if (PIKE_CONCAT(local_num_, NAME) != p->PIKE_CONCAT(num_,NAME)) { \ |
ref_push_program (p); \ |
decode_error(data, Pike_sp - 1, \ |
"Value mismatch for num_" TOSTR(NAME) ": " \ |
"%zd != %zd (bytecode method: %d)\n", \ |
(size_t) PIKE_CONCAT(local_num_, NAME), \ |
(size_t) p->PIKE_CONCAT(num_, NAME), \ |
bytecode_method); \ |
} |
#include "program_areas.h" |
|
|
|
|
|
for (e=0; e<local_num_constants; e++) { |
struct program_constant *constant = p->constants+e; |
if ((TYPEOF(constant->sval) != T_INT) || |
(SUBTYPEOF(constant->sval) != NUMBER_UNDEFINED)) { |
|
EDB(5, |
fprintf(stderr, "%*sskipping constant %d\n", |
data->depth, "", e)); |
continue; |
} |
|
decode_value2(data); |
|
decode_value2(data); |
#if 0 |
if (TYPEOF(Pike_sp[-1]) == T_STRING) { |
constant->name = Pike_sp[-1].u.string; |
} else if ((TYPEOF(Pike_sp[-1]) == T_INT) && |
!Pike_sp[-1].u.integer) { |
constant->name = NULL; |
} else { |
ref_push_program (p); |
decode_error(data, Pike_sp - 1, |
"Name of constant is not a string: %O\n", |
Pike_sp - 2); |
} |
constant->sval = Pike_sp[-2]; |
dmalloc_touch_svalue(Pike_sp-1); |
dmalloc_touch_svalue(Pike_sp-2); |
Pike_sp -= 2; |
#else /* !0 */ |
constant->offset = -1; |
pop_stack(); |
constant->sval = Pike_sp[-1]; |
dmalloc_touch_svalue(Pike_sp-1); |
Pike_sp -= 1; |
#endif /* 0 */ |
EDB(5, |
fprintf(stderr, "%*sDecoded constant %d to a %s\n", |
data->depth, "", |
e, get_name_of_type(TYPEOF(constant->sval)))); |
} |
|
#ifdef ENCODE_DEBUG |
if (!data->debug) |
#endif |
data->pickyness--; |
|
|
p->flags &= ~PROGRAM_AVOID_CHECK; |
|
EDB(5, fprintf(stderr, "%*sProgram flags: 0x%04x\n", |
data->depth, "", p->flags)); |
|
if (placeholder) { |
if (placeholder->prog != null_program) { |
decode_error(data, NULL, |
"Placeholder has been zapped during decoding.\n"); |
} |
debug_malloc_touch(placeholder); |
free_program(placeholder->prog); |
add_ref(placeholder->prog = p); |
placeholder->storage = p->storage_needed ? |
(char *)xcalloc(p->storage_needed, 1) : |
(char *)NULL; |
call_c_initializers(placeholder); |
if (!data->delay_counter) { |
call_pike_initializers(placeholder, 0); |
} else { |
|
|
|
struct unfinished_obj_link *up = |
ALLOC_STRUCT(unfinished_obj_link); |
up->next = data->unfinished_placeholders; |
data->unfinished_placeholders = up; |
add_ref(up->o = placeholder); |
} |
pop_stack(); |
} |
|
if (!data->delay_counter) { |
|
struct unfinished_obj_link *up; |
|
while ((up = data->unfinished_placeholders)) { |
struct object *o; |
data->unfinished_placeholders = up->next; |
push_object(o = up->o); |
free(up); |
call_pike_initializers(o, 0); |
pop_stack(); |
} |
} |
|
#ifdef ENCODE_DEBUG |
data->depth -= 2; |
#endif |
goto decode_done; |
} |
|
default: |
decode_error(data, NULL, |
"Cannot decode program encoding type %d\n",num); |
} |
break; |
|
default: |
decode_error(data, NULL, "Failed to restore string (illegal type %d).\n", |
what & TAG_MASK); |
} |
|
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);); |
#ifdef ENCODE_DEBUG |
data->depth -= 2; |
#endif |
} |
|
static struct decode_data *current_decode = NULL; |
|
static void free_decode_data (struct decode_data *data, int delay, |
int DEBUGUSED(free_after_error)) |
{ |
#ifdef PIKE_DEBUG |
int e; |
struct keypair *k; |
#endif |
|
debug_malloc_touch(data); |
|
if (current_decode == data) { |
current_decode = data->next; |
} else { |
struct decode_data *d; |
for (d = current_decode; d; d=d->next) { |
if (d->next == data) { |
d->next = d->next->next; |
break; |
} |
} |
} |
|
if(delay) |
{ |
debug_malloc_touch(data); |
|
return; |
} |
|
#ifdef PIKE_DEBUG |
if (!free_after_error) { |
NEW_MAPPING_LOOP (data->decoded->data) { |
if (TYPEOF(k->val) == T_PROGRAM && |
!(k->val.u.program->flags & PROGRAM_FINISHED)) { |
decode_error (data, NULL, |
"Got unfinished program <%O> after decode: %O\n", |
&k->ind, &k->val); |
} |
} |
if(data->unfinished_programs) |
Pike_fatal("We have unfinished programs left in decode()!\n"); |
if(data->unfinished_objects) |
Pike_fatal("We have unfinished objects left in decode()!\n"); |
if(data->unfinished_placeholders) |
Pike_fatal("We have unfinished placeholders left in decode()!\n"); |
} |
#endif |
|
free_string (data->data_str); |
if (data->codec) free_object (data->codec); |
free_mapping(data->decoded); |
|
while(data->unfinished_programs) |
{ |
struct unfinished_prog_link *tmp=data->unfinished_programs; |
data->unfinished_programs=tmp->next; |
free(tmp); |
} |
|
while(data->unfinished_objects) |
{ |
struct unfinished_obj_link *tmp=data->unfinished_objects; |
data->unfinished_objects=tmp->next; |
free_svalue(&tmp->decode_arg); |
free_object(tmp->o); |
free(tmp); |
} |
|
while(data->unfinished_placeholders) |
{ |
struct unfinished_obj_link *tmp=data->unfinished_placeholders; |
data->unfinished_placeholders=tmp->next; |
free_object(tmp->o); |
free(tmp); |
} |
|
#ifdef PIKE_THREADS |
data->thread_state = NULL; |
free_object (data->thread_obj); |
#endif |
|
free( (char *) data); |
} |
|
static void low_do_decode (struct decode_data *data) |
{ |
current_decode = data; |
|
decode_value2(data); |
|
while (data->ptr < data->len) { |
decode_value2 (data); |
pop_stack(); |
} |
} |
|
#if TWO_PASS_DECODE_WORKS |
|
int re_decode(struct decode_data *data, int ignored) |
{ |
JMP_BUF recovery; |
struct svalue orig_thrown; |
move_svalue (&orig_thrown, &throw_value); |
mark_free_svalue (&throw_value); |
|
if (SETJMP (recovery)) { |
UNSETJMP (recovery); |
call_handle_error(); |
move_svalue (&throw_value, &orig_thrown); |
free_decode_data (data, 0, 1); |
return 0; |
} |
|
else { |
data->next = current_decode; |
low_do_decode (data); |
UNSETJMP (recovery); |
move_svalue (&throw_value, &orig_thrown); |
free_decode_data (data, 0, 0); |
return 1; |
} |
} |
#endif |
|
static void error_free_decode_data (struct decode_data *data) |
{ |
int delay; |
debug_malloc_touch (data); |
#if TWO_PASS_DECODE_WORKS |
delay=unlink_current_supporter(&data->supporter); |
call_dependants(& data->supporter, 1); |
#else |
delay = 0; |
#endif |
free_decode_data (data, delay, 1); |
} |
|
static INT32 my_decode(struct pike_string *tmp, |
struct object *codec |
#ifdef ENCODE_DEBUG |
, int debug |
#endif |
) |
{ |
struct decode_data *data; |
ONERROR err; |
|
|
for (data = current_decode; data; data=data->next) { |
if (data->raw == tmp && |
(codec ? data->codec == codec : !data->explicit_codec) |
#ifdef PIKE_THREADS |
&& data->thread_state == Pike_interpreter.thread_state |
#endif |
) { |
struct svalue *res; |
struct svalue val = SVALUE_INIT_INT (COUNTER_START); |
#ifndef HAVE_UNION_INIT |
val.u.integer = COUNTER_START; |
#endif |
if ((res = low_mapping_lookup(data->decoded, &val))) { |
push_svalue(res); |
return 1; |
} |
|
|
} |
} |
|
data=ALLOC_STRUCT(decode_data); |
SET_SVAL(data->counter, T_INT, NUMBER_NUMBER, integer, COUNTER_START); |
data->data_str = tmp; |
data->data=(unsigned char *)tmp->str; |
data->len=tmp->len; |
data->ptr=0; |
data->codec=codec; |
data->explicit_codec = codec ? 1 : 0; |
data->pickyness=0; |
data->pass=1; |
data->unfinished_programs=0; |
data->unfinished_objects=0; |
data->unfinished_placeholders = NULL; |
data->delay_counter = 0; |
data->raw = tmp; |
data->next = current_decode; |
#ifdef PIKE_THREADS |
data->thread_state = Pike_interpreter.thread_state; |
data->thread_obj = Pike_interpreter.thread_state->thread_obj; |
#endif |
#ifdef ENCODE_DEBUG |
data->debug = debug; |
data->depth = -2; |
#endif |
|
if (tmp->size_shift || |
data->len < 5 || |
GETC() != 182 || |
GETC() != 'k' || |
GETC() != 'e' || |
GETC() != '0') |
{ |
free( (char *) data); |
return 0; |
} |
|
data->decoded=allocate_mapping(128); |
|
add_ref (data->data_str); |
if (data->codec) add_ref (data->codec); |
#ifdef PIKE_THREADS |
add_ref (data->thread_obj); |
#endif |
SET_ONERROR(err, error_free_decode_data, data); |
|
#if TWO_PASS_DECODE_WORKS |
init_supporter(& data->supporter, |
(supporter_callback *) re_decode, |
(void *)data); |
#endif |
|
low_do_decode (data); |
|
{ |
int delay; |
#if TWO_PASS_DECODE_WORKS |
delay=unlink_current_supporter(&data->supporter); |
call_dependants(& data->supporter, 1); |
#else |
delay = 0; |
#endif |
free_decode_data (data, delay, 0); |
} |
|
UNSET_ONERROR(err); |
|
return 1; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned char extract_char(char **v, ptrdiff_t *l) |
{ |
if(!*l) decode_error(current_decode, NULL, "Not enough place for char.\n"); |
else (*l)--; |
(*v)++; |
return ((unsigned char *)(*v))[-1]; |
} |
|
static ptrdiff_t extract_int(char **v, ptrdiff_t *l) |
{ |
INT32 j; |
ptrdiff_t i; |
|
j=extract_char(v,l); |
if(j & 0x80) return (j & 0x7f); |
|
if((j & ~8) > 4) |
decode_error(current_decode, NULL, "Invalid integer.\n"); |
i=0; |
while(j & 7) { i=(i<<8) | extract_char(v,l); j--; } |
if(j & 8) return -i; |
return i; |
} |
|
static void rec_restore_value(char **v, ptrdiff_t *l) |
{ |
ptrdiff_t t, i; |
|
i = extract_int(v,l); |
t = extract_int(v,l); |
switch(i) |
{ |
case TAG_INT: |
push_int(DO_NOT_WARN(t)); |
return; |
|
case TAG_FLOAT: |
if(sizeof(ptrdiff_t) < sizeof(FLOAT_TYPE)) |
decode_error(current_decode, NULL, "Float architecture not supported.\n"); |
push_int(DO_NOT_WARN(t)); |
SET_SVAL_TYPE(Pike_sp[-1], T_FLOAT); |
return; |
|
case TAG_TYPE: |
{ |
decode_error(current_decode, NULL, "TAG_TYPE not supported yet.\n"); |
} |
return; |
|
case TAG_STRING: |
if(t<0) decode_error(current_decode, NULL, |
"length of string is negative.\n"); |
if(*l < t) decode_error(current_decode, NULL, "string too short\n"); |
push_string(make_shared_binary_string(*v, t)); |
(*l)-= t; |
(*v)+= t; |
return; |
|
case TAG_ARRAY: |
if(t<0) decode_error(current_decode, NULL, |
"length of array is negative.\n"); |
check_stack(t); |
for(i=0;i<t;i++) rec_restore_value(v,l); |
f_aggregate(DO_NOT_WARN(t)); |
return; |
|
case TAG_MULTISET: |
if(t<0) decode_error(current_decode, NULL, |
"length of multiset is negative.\n"); |
check_stack(t); |
for(i=0;i<t;i++) rec_restore_value(v,l); |
f_aggregate_multiset(DO_NOT_WARN(t)); |
return; |
|
case TAG_MAPPING: |
if(t<0) decode_error(current_decode, NULL, |
"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(DO_NOT_WARN(t*2)); |
return; |
|
case TAG_OBJECT: |
if(t<0) decode_error(current_decode, NULL, |
"length of object is negative.\n"); |
if(*l < t) decode_error(current_decode, NULL, "string too short\n"); |
push_string(make_shared_binary_string(*v, t)); |
(*l) -= t; (*v) += t; |
APPLY_MASTER("objectof", 1); |
return; |
|
case TAG_FUNCTION: |
if(t<0) decode_error(current_decode, NULL, |
"length of function is negative.\n"); |
if(*l < t) decode_error(current_decode, NULL, "string too short\n"); |
push_string(make_shared_binary_string(*v, t)); |
(*l) -= t; (*v) += t; |
APPLY_MASTER("functionof", 1); |
return; |
|
case TAG_PROGRAM: |
if(t<0) decode_error(current_decode, NULL, |
"length of program is negative.\n"); |
if(*l < t) decode_error(current_decode, NULL, "string too short\n"); |
push_string(make_shared_binary_string(*v, t)); |
(*l) -= t; (*v) += t; |
APPLY_MASTER("programof", 1); |
return; |
|
default: |
decode_error(current_decode, NULL, "Unknown type tag %ld:%ld\n", |
PTRDIFF_T_TO_LONG(i), PTRDIFF_T_TO_LONG(t)); |
} |
} |
|
static void restore_current_decode (struct decode_data *old_data) |
{ |
current_decode = old_data; |
} |
|
|
extern struct program *MasterCodec_program; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void f_decode_value(INT32 args) |
{ |
struct pike_string *s; |
struct object *codec; |
|
#ifdef ENCODE_DEBUG |
int debug = 0; |
#endif /* ENCODE_DEBUG */ |
|
check_all_args("decode_value", args, |
BIT_STRING, |
BIT_VOID | BIT_OBJECT | BIT_ZERO, |
#ifdef ENCODE_DEBUG |
|
* 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); |
|
s = Pike_sp[-args].u.string; |
|
switch (args) { |
default: |
#ifdef ENCODE_DEBUG |
debug = Pike_sp[2-args].u.integer; |
|
case 2: |
#endif |
if (TYPEOF(Pike_sp[1-args]) == T_OBJECT) { |
if (SUBTYPEOF(Pike_sp[1-args])) { |
struct decode_data data; |
memset (&data, 0, sizeof (data)); |
data.data_str = s; |
decode_error(&data, NULL, |
"The codec may not be a subtyped object yet.\n"); |
} |
codec = Pike_sp[1-args].u.object; |
break; |
} |
|
case 1: |
if (!get_master()) { |
|
push_object (clone_object (MasterCodec_program, 0)); |
args++; |
codec = Pike_sp[-1].u.object; |
} |
else |
codec = NULL; |
} |
|
if(!my_decode(s, codec |
#ifdef ENCODE_DEBUG |
, debug |
#endif |
)) |
{ |
char *v=s->str; |
ptrdiff_t l=s->len; |
struct decode_data data; |
ONERROR uwp; |
memset (&data, 0, sizeof (data)); |
data.data_str = s; |
SET_ONERROR (uwp, restore_current_decode, current_decode); |
current_decode = &data; |
rec_restore_value(&v, &l); |
CALL_AND_UNSET_ONERROR (uwp); |
} |
assign_svalue(Pike_sp-args-1, Pike_sp-1); |
pop_n_elems(args); |
} |
|
|