From 6f7ff819b05fe184e39d56468adfc73482bdaafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Thu, 12 Jul 2001 16:14:16 -0700 Subject: [PATCH] fixed to handle recursive stuff in programs Rev: src/encode.c:1.109 --- src/encode.c | 300 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 215 insertions(+), 85 deletions(-) diff --git a/src/encode.c b/src/encode.c index c030b6a6b8..faf3c9c2ca 100644 --- a/src/encode.c +++ b/src/encode.c @@ -25,16 +25,16 @@ #include "version.h" #include "bignum.h" -RCSID("$Id: encode.c,v 1.108 2001/07/10 11:57:26 mast Exp $"); +RCSID("$Id: encode.c,v 1.109 2001/07/12 23:14:16 hubbe Exp $"); /* #define ENCODE_DEBUG */ #ifdef ENCODE_DEBUG /* Pass a nonzero integer as the third arg to encode_value, * encode_value_canonic and decode_value to activate this debug. */ -#define EDB(X) do if (data->debug) {X;} while (0) +#define EDB(N,X) do if (data->debug>=N) {X;} while (0) #else -#define EDB(X) do {} while (0) +#define EDB(N,X) do {} while (0) #endif /* The sp macro conflicts with Solaris 2.5.1's <sys/conf.h>. */ @@ -201,7 +201,7 @@ static int (*tag_to_type)(int) = type_to_tag; static void code_entry(int tag, INT64 num, struct encode_data *data) { int t; - EDB( + EDB(5, fprintf(stderr,"%*sencode: code_entry(tag=%d (%s), num=%ld)\n", data->depth, "", tag, get_name_of_type(tag_to_type(tag)), @@ -548,7 +548,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) if((tmp=low_mapping_lookup(data->encoded, val))) { - EDB(fprintf(stderr, "%*sEncoding TAG_AGAIN to <%d>\n", + EDB(1,fprintf(stderr, "%*sEncoding TAG_AGAIN from <%d>\n", data->depth, "", tmp->u.integer)); code_entry(TAG_AGAIN, tmp->u.integer, data); #ifdef ENCODE_DEBUG @@ -556,9 +556,15 @@ static void encode_value2(struct svalue *val, struct encode_data *data) #endif return; }else if (val->type != T_TYPE) { - EDB(fprintf(stderr, "%*sEncoding to <%d>: ", + EDB(1,fprintf(stderr, "%*sEncoding to <%d>: ", data->depth, "", data->counter.u.integer); - print_svalue(stderr, val); + if(data->debug == 1) + { + fprintf(stderr,"TAG%d",val->type); + }else{ + print_svalue(stderr, val); + + } fputc('\n', stderr);); mapping_insert(data->encoded, val, &data->counter); data->counter.u.integer++; @@ -588,7 +594,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) Pike_error("Canonical encoding of the type type not supported.\n"); code_entry(TAG_TYPE, 0, data); /* Type encoding #0 */ encode_type(val->u.type, data); - EDB(fprintf(stderr, "%*sEncoded type to <%d>: ", + EDB(2,fprintf(stderr, "%*sEncoded type to <%d>: ", data->depth, "", data->counter.u.integer); print_svalue(stderr, val); fputc('\n', stderr);); @@ -611,7 +617,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) x = DO_NOT_WARN((INT64)((((INT64)1)<<(sizeof(INT64)*8 - 2))*tmp)); y -= sizeof(INT64)*8 - 2; - EDB(fprintf(stderr, + EDB(2,fprintf(stderr, "Encoding float... tmp: %10g, x: 0x%016llx, y: %d\n", tmp, x, y)); @@ -621,7 +627,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) x >>= 32; y += 32; - EDB(fprintf(stderr, + EDB(2,fprintf(stderr, "Reducing float... x: 0x%08llx, y: %d\n", x, y)); #if 0 @@ -742,18 +748,49 @@ static void encode_value2(struct svalue *val, struct encode_data *data) push_svalue(val); f_object_program(1); - code_entry(type_to_tag(val->type), 1,data); - encode_value2(Pike_sp-1, data); - pop_stack(); + /* FIXME: + * If we want to be more backwards compatible, then + * we could follow the following steps: + * 1) do a code_entry(TAG_OBJECT, 1, data); + * 2) remove ourselves from the cache + * 3) code the program + * 4) if val is present in the cache, goto 7 + * 5) call encode_object + * 6) break; + * (This is the hard part...) + * 7) change code_entry in (1) to code_entry(TAG_OBJECT,3 data) + * 8) push_svalue(val) + * 9) break; + * + * -Hubbe + */ - push_svalue(val); - apply(data->codec,"encode_object",1); + if(low_mapping_lookup(data->encoded, Pike_sp-1)) + { + code_entry(TAG_OBJECT, 1,data); + encode_value2(Pike_sp-1, data); + pop_stack(); + + push_svalue(val); + apply(data->codec,"encode_object",1); + }else{ + /* We have to remove ourself from the cache permanently */ + map_delete(data->encoded, val); + + /* Code the program */ + code_entry(TAG_OBJECT, 3,data); + encode_value2(Pike_sp-1, data); + pop_stack(); + + /* Code the object */ + push_svalue(val); + } break; } /* FALL THROUGH */ default: - code_entry(type_to_tag(val->type), 0,data); + code_entry(TAG_OBJECT, 0,data); break; } encode_value2(Pike_sp-1, data); @@ -895,7 +932,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) code_number(p->identifier_references[d].inherit_offset,data); code_number(p->identifier_references[d].identifier_offset,data); code_number(p->identifier_references[d].id_flags,data); - EDB(fprintf(stderr,"IDREF%x > %d: { %d, %d, %d }\n", + EDB(3,fprintf(stderr,"IDREF%x > %d: { %d, %d, %d }\n", p->id,d, p->identifier_references[d].inherit_offset, p->identifier_references[d].identifier_offset, @@ -917,7 +954,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) ref_push_object(p->inherits[d].parent); Pike_sp[-1].subtype=p->inherits[d].parent_identifier; Pike_sp[-1].type=T_FUNCTION; - EDB(fprintf(stderr,"INHERIT%x coded as func { %p, %d }\n", + EDB(3,fprintf(stderr,"INHERIT%x coded as func { %p, %d }\n", p->id, p->inherits[d].parent, p->inherits[d].parent_identifier);); }else if(p->inherits[d].prog){ ref_push_program(p->inherits[d].prog); @@ -930,7 +967,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) adddata3(p->inherits[d].name); - EDB(fprintf(stderr,"INHERIT%x > %d: %d id=%d\n", + EDB(3,fprintf(stderr,"INHERIT%x > %d: %d id=%d\n", p->id,d, p->inherits[d].prog->num_identifiers, p->inherits[d].prog->id);); @@ -952,14 +989,14 @@ static void encode_value2(struct svalue *val, struct encode_data *data) } } + for(d=0;d<NUM_LFUNS;d++) + code_number(p->lfuns[d], data); + for(d=0;d<p->num_constants;d++) { encode_value2(& p->constants[d].sval, data); adddata3(p->constants[d].name); } - - for(d=0;d<NUM_LFUNS;d++) - code_number(p->lfuns[d], data); }else{ code_entry(type_to_tag(val->type), 0,data); encode_value2(Pike_sp-1, data); @@ -1115,6 +1152,12 @@ struct unfinished_prog_link struct program *prog; }; +struct unfinished_obj_link +{ + struct unfinished_prog_link *next; + struct object *o; +}; + struct decode_data { unsigned char *data; @@ -1122,6 +1165,7 @@ struct decode_data ptrdiff_t ptr; struct mapping *decoded; struct unfinished_prog_link *unfinished_programs; + struct unfinished_obj_link *unfinished_objects; struct svalue counter; struct object *codec; int pickyness; @@ -1161,7 +1205,7 @@ static int my_extract_char(struct decode_data *data) #define GETC() my_extract_char(data) #define DECODE(Z) do { \ - EDB( \ + EDB(5, \ fprintf(stderr,"%*sdecode(%s) at %d: ", \ data->depth,"",(Z),__LINE__)); \ what=GETC(); \ @@ -1185,7 +1229,7 @@ static int my_extract_char(struct decode_data *data) num = ~num; \ numh = ~numh; \ } \ - EDB( \ + EDB(5, \ fprintf(stderr,"type=%d (%s), num=%ld\n", \ (what & TAG_MASK), \ get_name_of_type(tag_to_type(what & TAG_MASK)), \ @@ -1529,6 +1573,21 @@ static void decode_value2(struct decode_data *data) DECODE("decode_value2"); +#ifdef ENCODE_DEBUG + if(data->debug) + { + if((what & TAG_MASK ) == TAG_AGAIN) + fprintf(stderr, "%*sDecoding TAG_AGAIN from <%d>\n", + data->depth, "", num); + + else + if(data->debug < 2) + fprintf(stderr, "%*sDecoding to <%d>: TAG%d (%d)\n", + data->depth, "", data->counter.u.integer , + what & TAG_MASK, num); + } +#endif + check_stack(1); switch(what & TAG_MASK) @@ -1570,19 +1629,19 @@ static void decode_value2(struct decode_data *data) { double res; - EDB(fprintf(stderr, "Decoding float... numh:0x%08x, num:0x%08x\n", + EDB(2,fprintf(stderr, "Decoding float... numh:0x%08x, num:0x%08x\n", numh, num)); res = LDEXP((double)numh, 32) + (double)(unsigned INT32)num; - EDB(fprintf(stderr, "Mantissa: %10g\n", res)); + EDB(2,fprintf(stderr, "Mantissa: %10g\n", res)); tmp = data->counter; data->counter.u.integer++; DECODE("float"); - EDB(fprintf(stderr, "Exponent: %d\n", num)); + EDB(2,fprintf(stderr, "Exponent: %d\n", num)); push_float(LDEXP(res, num)); break; @@ -1614,7 +1673,7 @@ static void decode_value2(struct decode_data *data) tmp.type=T_ARRAY; tmp.u.array=a=allocate_array(num); - EDB(fprintf(stderr, "%*sDecoding array of size %d to <%d>\n", + EDB(2,fprintf(stderr, "%*sDecoding array of size %d to <%d>\n", data->depth, "", num, data->counter.u.integer)); mapping_insert(data->decoded, & data->counter, &tmp); data->counter.u.integer++; @@ -1652,7 +1711,7 @@ static void decode_value2(struct decode_data *data) m=allocate_mapping(num); tmp.type=T_MAPPING; tmp.u.mapping=m; - EDB(fprintf(stderr, "%*sDecoding mapping of size %d to <%d>\n", + EDB(2,fprintf(stderr, "%*sDecoding mapping of size %d to <%d>\n", data->depth, "", num, data->counter.u.integer)); mapping_insert(data->decoded, & data->counter, &tmp); data->counter.u.integer++; @@ -1688,7 +1747,7 @@ static void decode_value2(struct decode_data *data) m = allocate_multiset(a); tmp.type = T_MULTISET; tmp.u.multiset = m; - EDB(fprintf(stderr, "%*sDecoding multiset of size %d to <%d>\n", + EDB(2,fprintf(stderr, "%*sDecoding multiset of size %d to <%d>\n", data->depth, "", num, data->counter.u.integer)); mapping_insert(data->decoded, & data->counter, &tmp); data->counter.u.integer++; @@ -1710,10 +1769,11 @@ static void decode_value2(struct decode_data *data) return; } - case TAG_OBJECT: + { tmp=data->counter; data->counter.u.integer++; + decode_value2(data); switch(num) @@ -1730,33 +1790,50 @@ static void decode_value2(struct decode_data *data) case 1: if(IS_ZERO(Pike_sp-1)) { - EDB(fprintf(stderr, "%*sDecoded a failed object to <%d>: ", + EDB(1,fprintf(stderr, "%*sDecoded a failed object to <%d>: ", data->depth, "", tmp.u.integer); print_svalue(stderr, Pike_sp-1); fputc('\n', stderr);); - mapping_insert(data->decoded, &tmp, Pike_sp-1); decode_value2(data); pop_stack(); }else{ - f_call_function(1); - EDB(fprintf(stderr, "%*sDecoded an object to <%d>: ", + struct object *o; + /* decode_value_clone_object does not call __INIT, so + * we want to do that ourselves... + */ + o=decode_value_clone_object(Pike_sp-1); + debug_malloc_touch(o); + pop_stack(); + push_object(o); + + if(o->prog) + { + if(o->prog->flags & PROGRAM_FINISHED) + { + apply_lfun(o, LFUN___INIT, 0); + pop_stack(); + }else{ + struct unfinished_obj_link *ol=ALLOC_STRUCT(unfinished_obj_link); + ol->o=o; + ol->next=data->unfinished_objects; + data->unfinished_objects=ol; + } + } + + EDB(2,fprintf(stderr, "%*sDecoded an object to <%d>: ", data->depth, "", tmp.u.integer); print_svalue(stderr, Pike_sp-1); fputc('\n', stderr);); - mapping_insert(data->decoded, &tmp, Pike_sp-1); - push_svalue(Pike_sp-1); + + ref_push_object(o); decode_value2(data); if(!data->codec) Pike_error("Failed to decode (no codec)\n"); apply(data->codec,"decode_object",2); pop_stack(); } - if(data->pickyness && Pike_sp[-1].type != T_OBJECT) - Pike_error("Failed to decode object.\n"); -#ifdef ENCODE_DEBUG - data->depth -= 2; -#endif - return; + + break; #ifdef AUTO_BIGNUM /* It is possible that we should do this even without @@ -1776,15 +1853,24 @@ static void decode_value2(struct decode_data *data) } #endif + case 3: + pop_stack(); + decode_value2(data); + break; default: Pike_error("Object coding not compatible.\n"); break; } - if(data->pickyness && Pike_sp[-1].type != T_OBJECT) - Pike_error("Failed to decode (got type %d; expected object).\n", - Pike_sp[-1].type); + if(Pike_sp[-1].type != T_OBJECT) + if(data->pickyness) + Pike_error("Failed to decode object.\n"); + +#ifdef ENCODE_DEBUG + data->depth -= 2; +#endif break; + } case TAG_FUNCTION: tmp=data->counter; @@ -1888,7 +1974,7 @@ static void decode_value2(struct decode_data *data) debug_malloc_touch(p); tmp.type=T_PROGRAM; tmp.u.program=p; - EDB(fprintf(stderr, "%*sDecoding a program to <%d>: ", + EDB(2,fprintf(stderr, "%*sDecoding a program to <%d>: ", data->depth, "", data->counter.u.integer); print_svalue(stderr, &tmp); fputc('\n', stderr);); @@ -1904,7 +1990,8 @@ static void decode_value2(struct decode_data *data) debug_malloc_touch(p); decode_number(p->flags,data); - p->flags &= ~(PROGRAM_FINISHED | PROGRAM_OPTIMIZED); + p->flags &= ~(PROGRAM_FINISHED | PROGRAM_OPTIMIZED | + PROGRAM_FIXED | PROGRAM_PASS_1_DONE); p->flags |= PROGRAM_AVOID_CHECK; decode_number(p->storage_needed,data); decode_number(p->xstorage,data); @@ -2018,7 +2105,7 @@ static void decode_value2(struct decode_data *data) decode_number(p->identifier_references[d].identifier_offset,data); decode_number(p->identifier_references[d].id_flags,data); - EDB(fprintf(stderr,"IDREF%x < %d: { %d, %d, %d }\n", + EDB(3,fprintf(stderr,"IDREF%x < %d: { %d, %d, %d }\n", p->id,d, p->identifier_references[d].inherit_offset, p->identifier_references[d].identifier_offset, @@ -2063,7 +2150,7 @@ static void decode_value2(struct decode_data *data) if(Pike_sp[-1].subtype == FUNCTION_BUILTIN) Pike_error("Failed to decode parent.\n"); - EDB( fprintf(stderr,"INHERIT%x = func { %p, %d} \n",p->id,Pike_sp[-1].u.object, Pike_sp[-1].subtype); ); + EDB(3, fprintf(stderr,"INHERIT%x = func { %p, %d} \n",p->id,Pike_sp[-1].u.object, Pike_sp[-1].subtype); ); p->inherits[d].parent_identifier=Pike_sp[-1].subtype; p->inherits[d].prog=program_from_svalue(Pike_sp-1); @@ -2076,7 +2163,7 @@ static void decode_value2(struct decode_data *data) break; case T_PROGRAM: - EDB( fprintf(stderr,"INHERIT%x = prog\n",p->id); ); + EDB(3, fprintf(stderr,"INHERIT%x = prog\n",p->id); ); p->inherits[d].prog=Pike_sp[-1].u.program; Pike_sp--; dmalloc_touch_svalue(Pike_sp); @@ -2087,7 +2174,7 @@ static void decode_value2(struct decode_data *data) getdata3(p->inherits[d].name); - EDB( fprintf(stderr,"INHERIT%x < %d: %d id=%d\n", + EDB(3, fprintf(stderr,"INHERIT%x < %d: %d id=%d\n", p->id,d, p->inherits[d].prog->num_identifiers, p->inherits[d].prog->id); ); @@ -2123,18 +2210,6 @@ static void decode_value2(struct decode_data *data) debug_malloc_touch(dat); - debug_malloc_touch(p); - for(d=0;d<p->num_constants;d++) - { - decode_value2(data); - p->constants[d].sval=*--Pike_sp; - dmalloc_touch_svalue(Pike_sp); - getdata3(p->constants[d].name); - } - data->pickyness--; - - debug_malloc_touch(dat); - debug_malloc_touch(p); for(d=0;d<NUM_LFUNS;d++) decode_number(p->lfuns[d],data); @@ -2150,6 +2225,20 @@ static void decode_value2(struct decode_data *data) sizeof(unsigned short),(fsortfun)program_function_index_compare); Pike_compiler->new_program=new_program_save; } + + debug_malloc_touch(dat); + debug_malloc_touch(p); + p->flags |= PROGRAM_PASS_1_DONE | PROGRAM_FIXED; + for(d=0;d<p->num_constants;d++) + { + decode_value2(data); + p->constants[d].sval=*--Pike_sp; + dmalloc_touch_svalue(Pike_sp); + getdata3(p->constants[d].name); + } + data->pickyness--; + + UNSET_ONERROR(err3); ref_push_program(p); @@ -2165,40 +2254,71 @@ static void decode_value2(struct decode_data *data) if(d == p->num_inherits) { - int done=0; - struct unfinished_prog_link *l, **ptr; p->flags &=~ PROGRAM_AVOID_CHECK; p->flags |= PROGRAM_FINISHED; - -#ifdef PIKE_DEBUG - check_program(p); -#endif /* PIKE_DEBUG */ - /* It is possible that we need to restart loop - * in some cases... /Hubbe + /* Go through the linked list of unfinished programs + * to see what programs are now finished. */ - for(ptr= &data->unfinished_programs ; (l=*ptr);) { - struct program *pp=l->prog; - for(d=1;d<pp->num_inherits;d++) - if(! (pp->inherits[d].prog->flags & PROGRAM_FINISHED)) - break; + struct unfinished_prog_link *l, **ptr; - if(d == pp->num_inherits) +#ifdef PIKE_DEBUG + check_program(p); +#endif /* PIKE_DEBUG */ + + /* It is possible that we need to restart loop + * in some cases... /Hubbe + */ + for(ptr= &data->unfinished_programs ; (l=*ptr);) { - pp->flags &=~ PROGRAM_AVOID_CHECK; - pp->flags |= PROGRAM_FINISHED; + struct program *pp=l->prog; + for(d=1;d<pp->num_inherits;d++) + if(! (pp->inherits[d].prog->flags & PROGRAM_FINISHED)) + break; + if(d == pp->num_inherits) + { + pp->flags &=~ PROGRAM_AVOID_CHECK; + pp->flags |= PROGRAM_FINISHED; + #ifdef PIKE_DEBUG - check_program(pp); + check_program(pp); #endif /* PIKE_DEBUG */ + + *ptr = l->next; + free((char *)l); + }else{ + ptr=&l->next; + } + } + } + /* Go through the linked list of unfinished objects + * to see what objects are now finished. + */ + { + struct unfinished_obj_link *l, **ptr; + for(ptr= &data->unfinished_objects ; (l=*ptr);) + { + struct object *o=l->o; + if(o->prog) + { + if(o->prog->flags & PROGRAM_FINISHED) + { + apply_lfun(o, LFUN___INIT, 0); + pop_stack(); + }else{ + ptr=&l->next; + continue; + } + } *ptr = l->next; free((char *)l); - }else{ - ptr=&l->next; } } + + }else{ struct unfinished_prog_link *l; l=ALLOC_STRUCT(unfinished_prog_link); @@ -2260,7 +2380,7 @@ static void decode_value2(struct decode_data *data) Pike_error("Failed to restore string. (Illegal type)\n"); } - EDB(fprintf(stderr, "%*sDecoded to <%d>: ", data->depth, "", tmp.u.integer); + EDB(2,fprintf(stderr, "%*sDecoded to <%d>: ", data->depth, "", tmp.u.integer); print_svalue(stderr, Pike_sp-1); fputc('\n', stderr);); mapping_insert(data->decoded, & tmp, Pike_sp-1); @@ -2281,6 +2401,13 @@ static void free_decode_data(struct decode_data *data) data->unfinished_programs=tmp->next; free((char *)tmp); } + + while(data->unfinished_objects) + { + struct unfinished_obj_link *tmp=data->unfinished_objects; + data->unfinished_objects=tmp->next; + free((char *)tmp); + } if (current_decode == data) { current_decode = data->next; } else { @@ -2338,6 +2465,7 @@ static INT32 my_decode(struct pike_string *tmp, data->codec=codec; data->pickyness=0; data->unfinished_programs=0; + data->unfinished_objects=0; data->raw = tmp; data->next = current_decode; #ifdef ENCODE_DEBUG @@ -2362,7 +2490,9 @@ static INT32 my_decode(struct pike_string *tmp, #ifdef PIKE_DEBUG if(data->unfinished_programs) - fatal("We have unfinished programs left in decode()! We may need a double loop!\n"); + fatal("We have unfinished programs left in decode()!\n"); + if(data->unfinished_objects) + fatal("We have unfinished objects left in decode()!\n"); #endif CALL_AND_UNSET_ONERROR(err); return 1; -- GitLab