#include "global.h" #include <math.h> #include <ctype.h> #include "array.h" #include "interpret.h" #include "exec.h" #include "object.h" #include "main.h" #include "stralloc.h" #include "save_objectII.h" #include "efun_protos.h" #include "simulate.h" #include "regexp.h" extern int d_flag; int save_style=0; struct processing { struct processing *next; struct vector *v; }; static void low_save_svalue(struct svalue *s,struct processing *p); static void my_error(char *t) { char *s; if((s=simple_free_buf())) free(s); error(t); } static void save_svalue_list(struct vector *v,struct processing *prev) { int e; struct processing p; p.next=prev; p.v=v; for(e=0;prev;e++,prev=prev->next) { if(prev->v==v) { char buf[20]; sprintf(buf,"#%d",e); my_strcat(buf); return; } } for(e=0;e<v->size;e++) { if(e) my_putchar(','); low_save_svalue(&(v->item[e]),&p); } } void debug_save_svalue_list(struct vector *v) { save_svalue_list(v,0); } static void save_mapping(struct vector *v,struct processing *p) { int e; struct processing prev; prev.next=p; prev.v=v; for(e=0;p;e++,p=p->next) { if(p->v==v) { char buf[20]; sprintf(buf,"#%d",e); my_strcat(buf); return; } } for(e=0;e<v->item[0].u.vec->size;e++) { if(e) my_putchar(','); low_save_svalue(&(v->item[0].u.vec->item[e]),&prev); my_putchar(':'); low_save_svalue(&(v->item[1].u.vec->item[e]),&prev); } } static void save_string(char *s,int len) { char buf[20]; int e; switch(save_style) { default: case SAVE_DEFAULT: sprintf(buf,"%dH",len); my_strcat(buf); my_binary_strcat(s,len); break; case SAVE_AS_ONE_LINE: my_putchar('"'); for(e=0;e<len;e++) { switch(s[e]) { case '\n': my_putchar('\\'); my_putchar('n'); break; case '\t': my_putchar('\\'); my_putchar('t'); break; case '\b': my_putchar('\\'); my_putchar('b'); break; case '"': case '\\': my_putchar('\\'); default: my_putchar(s[e]); } } my_putchar('"'); break; case SAVE_OLD_STYLE: my_putchar('"'); for(e=0;e<len;e++) { switch(s[e]) { case '"': case '\n': case '\\': my_putchar('\\'); default: my_putchar(s[e]); } } my_putchar('"'); break; } } void save_object_desc(struct object *ob) { char b[20]; extern struct object fake_object; if(ob==&fake_object) error("*"); if(ob->obj_index) { my_strcat("H("); save_string(ob->obj_index,strlen(ob->obj_index)); my_strcat(")"); }else{ sprintf(b,"O(%d)",ob->clone_number); my_strcat(b); } } static void low_save_svalue(struct svalue *s,struct processing *p) { char b[30]; switch(s->type) { case T_LVALUE: my_strcat("Lvalue"); break; case T_REGEXP: my_strcat("R("); save_string(s->u.regexp->str,strlen(s->u.regexp->str)); my_strcat(")"); break; case T_STRING: save_string(strptr(s),my_strlen(s)); break; case T_NUMBER: sprintf(b,"%d",s->u.number); my_strcat(b); break; case T_FLOAT: sprintf(b,"F%0.8f",s->u.fnum); my_strcat(b); break; case T_POINTER: sprintf(b,"(%d{",s->u.vec->size); my_strcat(b); save_svalue_list(s->u.vec,p); my_strcat("})"); break; case T_ALIST_PART: sprintf(b,"(%d*",s->u.vec->size); my_strcat(b); save_svalue_list(s->u.vec,p); my_strcat("*)"); break; case T_LIST: sprintf(b,"(%d<",s->u.vec->item[0].u.vec->size); my_strcat(b); save_svalue_list(s->u.vec->item[0].u.vec,p); my_strcat(">)"); break; case T_MAPPING: sprintf(b,"(%d[",s->u.vec->item[0].u.vec->size); my_strcat(b); save_mapping(s->u.vec,p); my_strcat("])"); break; case T_OBJECT: save_object_desc(s->u.ob); break; case T_FUNCTION: save_object_desc(s->u.ob); my_strcat("->"); my_strcat(FUNC(s->u.ob->prog,s->subtype)->name); break; default: fatal("Unknown type %d in save_object.\n",s->type); } } void save_svalue(struct svalue *s) { low_save_svalue(s,0); } static char *restore_string(char **t) { init_buf(); (*t)++; while(**t!='"') { switch(**t) { case 0: my_error("Unexpected end of string in restore.\n"); case '\\': { (*t)++; switch(**t) { case 0: my_error("Unexpected end of string in restore.\n"); case 'n': my_putchar('\n'); break; case 't': my_putchar('\t'); break; case 'b': my_putchar('\b'); break; case '0': case '1': case '2': { char c; c=(**t-'0')*8*8; (*t)++; if(**t<'0' || **t>'8') my_error("Error in restore string.\n"); c+=(**t-'0')*8; (*t)++; if(**t<'0' || **t>'8') my_error("Error in restore string.\n"); c+=(**t-'0'); my_putchar(c); } default: my_putchar(**t); break; } (*t)++; break; } default: my_putchar(*((*t)++)); } } (*t)++; return free_buf(); } struct processing2 { struct processing2 *next; struct svalue *s; }; static char *low_restore_svalue(char *t,struct svalue *s,struct processing2 *p) { extern struct svalue *sp; free_svalue(s); switch(*t) { case '#': { int e; e=(int)STRTOL(t,&t,10); while(e-- && p) p=p->next; if(!p || !p->s) my_error("Error in restore object"); assign_svalue(s,p->s); return t; } case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': s->u.number=(int)STRTOL(t,&t,10); if(*t=='H') { int tmp; tmp=s->u.number; t++; SET_STR(s,make_shared_binary_string(t,tmp)); t+=tmp; }else{ s->type=T_NUMBER; s->subtype=NUMBER_NUMBER; } return t; case 'R': if(strncmp("R(",t,2)) my_error("Error in restore object"); t+=2; sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,s,p); if(*t!=')') my_error("Error in restore object"); t++; f_cast_to_regexp(); assign_svalue(s,sp); pop_stack(); break; case 'O': s->type=T_NUMBER; s->subtype=NUMBER_DESTRUCTED_OBJECT; s->u.number=0; if(strncmp("O(",t,2)) my_error("Error in restore object"); t+=2; while(*t>='0' && *t<='9') t++; if(*t!=')') my_error("Error in restore object"); t++; return t; case 'F': s->type=T_FLOAT; t++; s->u.fnum=STRTOD(t,&t); return t; case 'H': if(strncmp("H(",t,2)) my_error("Error in restore object"); t+=2; sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,sp,p); if(*t!=')') my_error("Error in restore object"); t++; f_cast_to_object(); if(*t=='-') { char *tmp; if(strncmp("->",t,2)) my_error("Error in restore object.\n"); t+=2; if(*t=='"') t++; tmp=t; while(isalnum(*t) || *t=='_') t++; if(*t=='"') t++; push_shared_string(make_shared_binary_string(tmp,t-tmp)); f_get_function(2,sp-1); } assign_svalue(s,sp); pop_stack(); return t; case '"': SET_STR(s,restore_string(&t)); return t; case '(': { struct processing2 curr; curr.next=p; curr.s=s; switch(*++t) { int e,size; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': size=(int)STRTOL(t,&t,10); switch(*(t++)) { case '{': s->u.vec=allocate_array(size); if(!s) my_error("Out of memory in restore_object.\n"); s->type=T_POINTER; for(e=0;e<size;e++) { t=low_restore_svalue(t,s->u.vec->item+e,&curr); if(*t==',') t++; } if(t[0]!='}' || t[1]!=')') my_error("Error while restoring array.\n"); t+=2; return t; case '<': s->u.vec=allocate_array(1); if(!s) my_error("Out of memory in restore_object.\n"); s->type=T_POINTER; s->u.vec->item[0].u.vec=allocate_array(size); if(!s->u.vec->item[0].u.vec) my_error("Out of memory in restore_object.\n"); s->u.vec->item[0].type=T_ALIST_PART; s->type=T_LIST; for(e=0;e<size;e++) { t=low_restore_svalue(t,s->u.vec->item[0].u.vec->item+e,&curr); if(*t==',') t++; } if(t[0]!='>' || t[1]!=')') my_error("Error while restoring list.\n"); t+=2; order_alist(s->u.vec); return t; case '[': s->u.vec=allocate_array(3); if(!s) my_error("Out of memory in restore_object.\n"); s->type=T_POINTER; s->u.vec->item[0].u.vec=allocate_array(size); if(!s->u.vec->item[0].u.vec) my_error("Out of memory in restore_object.\n"); s->u.vec->item[0].type=T_ALIST_PART; s->u.vec->item[1].u.vec=allocate_array(size); if(!s->u.vec->item[0].u.vec) my_error("Out of memory in restore_object.\n"); s->u.vec->item[1].type=T_ALIST_PART; s->type=T_MAPPING; for(e=0;e<size;e++) { t=low_restore_svalue(t,s->u.vec->item[0].u.vec->item+e,&curr); if(*t!=':') my_error("Error when restoring mapping.\n"); t++; t=low_restore_svalue(t,s->u.vec->item[1].u.vec->item+e,&curr); if(*t==',') t++; } if(t[0]!=']' || t[1]!=')') my_error("Error while restoring list.\n"); t+=2; order_alist(s->u.vec); return t; } case '{': t++; e=0; while(*t!='}' && *t) { sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,sp,&curr); if(*t==',') t++; e++; } if(!*t) my_error("Unexpected end of string in restore object.\n"); if(*++t==')') t++; f_aggregate(e,sp-e+1); assign_svalue(s,sp); pop_stack(); return t; case '<': t++; e=0; while(*t!='>' && *t) { sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,sp,&curr); if(*t==',') t++; e++; } if(!*t) my_error("Unexpected end of string in restore object.\n"); if(*++t==')') t++; f_l_aggregate(e,sp-e+1); assign_svalue(s,sp); pop_stack(); return t; case '[': t++; e=0; while(*t!=']' && *t) { sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,sp,&curr); if(*t!=':') my_error("Error while restoring mapping.\n"); t++; e++; sp++; SET_TO_ZERO(*sp); t=low_restore_svalue(t,sp,&curr); if(*t==',') t++; e++; } if(!*t) my_error("Unexpected end of string in restore object.\n"); if(*++t==')') t++; f_m_aggregate(e,sp-e+1); assign_svalue(s,sp); pop_stack(); return t; } } } return t; } char *restore_svalue(char *t,struct svalue *s) { return low_restore_svalue(t,s,0); } char *save_object() { int i; if (current_object->flags & O_DESTRUCTED) error("Save_object on destructed object.\n"); init_buf(); for (i=0;i < current_object->prog->num_variables; i++) { struct svalue tmp; if(current_object->prog->variable_names[i].rttype==T_NOTHING) continue; if(current_object->prog->variable_names[i].rttype==T_ANY) { tmp=*(struct svalue *)(current_object->variables+i); }else{ tmp.type=current_object->prog->variable_names[i].rttype; tmp.u=current_object->variables[i]; if(!tmp.u.number && tmp.type<=MAX_REF_TYPE) tmp.type=T_NUMBER; } if (current_object->prog->variable_names[i].type & TYPE_MOD_STATIC) continue; my_strcat(current_object->prog->variable_names[i].name); my_putchar(' '); save_svalue(&tmp); my_putchar('\n'); } return free_buf(); } int restore_object(char *t) { char *var,q[150]; struct variable *p; if (current_object->flags & O_DESTRUCTED) error("Restore object on destructed object.\n"); while(*t) { int i; struct svalue *v,tmp; SET_TO_ZERO(tmp); if(*t=='\n') { t++; continue; } t=STRCHR(var=t, ' '); if (t == 0 || t-var>=sizeof(q)-1) error("Illegal format when restore.\n"); strncpy(q,var,t-var); q[t-var]=0; p = find_status(q, 0); t++; t=restore_svalue(t,&tmp); if (p == 0 || (p->type & TYPE_MOD_STATIC)) { free_svalue(&tmp); }else if(p->rttype==T_ANY){ i=p - current_object->prog->variable_names; v = (struct svalue *)¤t_object->variables[i]; assign_svalue(v,&tmp); free_svalue(&tmp); }else if(p->rttype==tmp.type){ i=p - current_object->prog->variable_names; assign_short_svalue(current_object->variables+i,&tmp,tmp.type); free_svalue(&tmp); } if(*t=='\n') t++; } if (d_flag > 1) debug_message("Object %s restored.\n", current_object->prog->name); return 1; }