5267b71995-08-09Fredrik Hübinette (Hubbe) #include <math.h> #include <ctype.h> #include "global.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "stralloc.h" #include "mapping.h" #include "list.h" #include "opcodes.h" #include "object.h" #include "error.h" #include "lpc_types.h" void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { INT32 i; switch(what->type) { case T_ARRAY: simple_array_index_no_free(to,what->u.array,ind); break; case T_MAPPING: mapping_index_no_free(to,what->u.mapping,ind); break; case T_OBJECT: object_index_no_free(to, what->u.object, ind); break; case T_LIST: i=list_member(what->u.list, ind); to->type=T_INT; to->subtype=i ? NUMBER_UNDEFINED : 0; to->u.integer=i; break; case T_STRING: if(ind->type==T_INT) { i=ind->u.integer; if(i<0) i+=what->u.string->len; if(i<0 || i>=what->u.string->len) error("Index out of range.\n"); else i=EXTRACT_UCHAR(what->u.string->str + i); to->type=T_INT; to->subtype=NUMBER_NUMBER; to->u.integer=i; break; }else{ error("Index is not an integer.\n"); } default: error("Indexing a basic type.\n"); } } void f_index() { index_no_free(sp,sp-2,sp-1); free_svalue(sp-2); sp[-2]=sp[0]; pop_stack(); } void f_cast() { INT32 i; i=compile_type_to_runtime_type(sp[-1].u.string); pop_stack(); if(i != sp[-1].type) { switch(i) { case T_MIXED: break; case T_INT: switch(sp[-1].type) { case T_FLOAT: i=(int)(sp[-1].u.float_number); break; case T_STRING: i=strtol(sp[-1].u.string->str,0,0); free_string(sp[-1].u.string); break; default: error("Cannot cast to int.\n"); } sp[-1].type=T_INT; sp[-1].u.integer=i; break; case T_FLOAT: { FLOAT_TYPE f; switch(sp[-1].type) { case T_INT: f=(FLOAT_TYPE)(sp[-1].u.integer); break; case T_STRING: f=strtod(sp[-1].u.string->str,0); free_string(sp[-1].u.string); break; default: error("Cannot cast to float.\n"); f=0.0; } sp[-1].type=T_FLOAT; sp[-1].u.float_number=f; break; } case T_STRING: { char buf[200]; switch(sp[-1].type) { case T_INT:
f90e541995-08-17Fredrik Hübinette (Hubbe)  sprintf(buf,"%ld",(long)sp[-1].u.integer);
5267b71995-08-09Fredrik Hübinette (Hubbe)  break; case T_FLOAT: sprintf(buf,"%f",(double)sp[-1].u.float_number); break; default: error("Cannot cast to string.\n"); } sp[-1].type=T_STRING; sp[-1].u.string=make_shared_string(buf); break; } case T_OBJECT: switch(sp[-1].type) { case T_STRING: APPLY_MASTER("cast_to_object",1); break; case T_FUNCTION: sp[-1].type = T_OBJECT; break; } break; case T_PROGRAM: APPLY_MASTER("cast_to_program",1); break; case T_FUNCTION: { INT32 i; if(fp->current_object->prog) error("Cast to function in destructed object.\n"); i=find_shared_string_identifier(sp[-1].u.string,fp->current_object->prog); free_string(sp[-1].u.string); /* FIXME, check that it is a indeed a function */ if(i==-1) { sp[-1].type=T_FUNCTION; sp[-1].subtype=i; sp[-1].u.object=fp->current_object; fp->current_object->refs++; }else{ sp[-1].type=T_INT; sp[-1].subtype=NUMBER_UNDEFINED; sp[-1].u.integer=0; } break; } } } } /* flags: * operators: %d %s %f %c %n %[ %% */ static int read_set(char *match,int cnt,char *set,int match_len) { int init; int last=0; int e; if(cnt>=match_len) error("Error in sscanf format string.\n"); if(match[cnt]=='^') { for(e=0;e<256;e++) set[e]=1; init=0; cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); }else{ for(e=0;e<256;e++) set[e]=0; init=1; } if(match[cnt]==']') { set[last=']']=init; cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); } for(;match[cnt]!=']';cnt++) { if(match[cnt]=='-') { cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); if(match[cnt]==']') { set['-']=init; break; } for(e=last;e<EXTRACT_UCHAR(match+cnt);e++) set[e]=init; } set[last=EXTRACT_UCHAR(match+cnt)]=init; } return cnt; } static INT32 low_sscanf(INT32 num_arg) { char *input; int input_len; char *match; int match_len; struct svalue sval; int e,cnt,matches,eye,arg; int no_assign; char set[256]; struct svalue *argp; if(num_arg < 2) error("Too few arguments to sscanf.\n"); argp=sp-num_arg; if(argp[0].type != T_STRING) error("Bad argument 1 to sscanf.\n"); if(argp[1].type != T_STRING) error("Bad argument 2 to sscanf.\n"); input=argp[0].u.string->str; input_len=argp[0].u.string->len;; match=argp[1].u.string->str; match_len=argp[1].u.string->len; arg=eye=matches=0; for(cnt=0;cnt<match_len;cnt++) { for(;cnt<match_len;cnt++) { if(match[cnt]=='%') { if(match[cnt+1]=='%') { cnt++; }else{ break; } } if(eye>=input_len || input[eye]!=match[cnt]) return matches; eye++; } if(cnt>=match_len) return matches; #ifdef DEBUG if(match[cnt]!='%' || match[cnt+1]=='%') { fatal("Error in sscanf.\n"); } #endif cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); if(match[cnt]=='*') { no_assign=1; cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); }else{ no_assign=0; } switch(match[cnt]) { case 'c': if(eye>=input_len) return matches; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; sval.u.integer=EXTRACT_UCHAR(input+eye); eye++; break; case 'd': { char * t; if(eye>=input_len) return matches; sval.u.integer=STRTOL(input+eye,&t,0); if(input + eye == t) return matches; eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; break; } case 'f': { char * t; if(eye>=input_len) return matches; sval.u.float_number=STRTOD(input+eye,&t); if(input + eye == t) return matches; eye=t-input; sval.type=T_FLOAT; #ifdef __CHECKER__ sval.subtype=0; #endif break; } case 's': if(cnt+1>=match_len) { sval.type=T_STRING; #ifdef __CHECKER__ sval.subtype=0; #endif sval.u.string=make_shared_binary_string(input+eye,input_len-eye); break; }else{ char *end_str_start; char *end_str_end; char *s=0; /* make gcc happy */ char *p=0; /* make gcc happy */ int start,contains_percent_percent, new_eye; start=eye; end_str_start=match+cnt+1; s=match+cnt+1; test_again: if(*s=='%') { s++; if(*s=='*') s++; switch(*s) { case 'n': s++; goto test_again; case 's': error("Illigal to have two adjecent %%s.\n"); return 0; /* make gcc happy */ /* sscanf("foo-bar","%s%d",a,b) might not work as expected */ case 'd': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; set['-']=0; goto match_set; case 'f': for(e=0;e<256;e++) set[e]=1; for(e='0';e<='9';e++) set[e]=0; set['.']=set['-']=0; goto match_set; case '[': /* oh dear */ read_set(match,s-match+1,set,match_len); for(e=0;e<256;e++) set[e]=!set[e]; goto match_set; } } contains_percent_percent=0; for(e=cnt;e<match_len;e++) { if(match[e]=='%') { if(match[e+1]=='%') { contains_percent_percent=1; e++; }else{ break; } } } end_str_end=match+e; if(!contains_percent_percent) { s=MEMMEM(end_str_start, end_str_end-end_str_start, input+eye, input_len-eye); if(!s) return matches; eye=s-input; new_eye=eye+end_str_end-end_str_start; }else{ for(;eye<input_len;eye++) { p=input+eye; for(s=end_str_start;s<end_str_end;s++,p++) { if(*s!=*p) break; if(*s=='%') s++; } if(s==end_str_end) break; } if(eye==input_len) return matches; new_eye=p-input; } sval.type=T_STRING; #ifdef __CHECKER__ sval.subtype=0; #endif sval.u.string=make_shared_binary_string(input+start,eye-start); cnt=end_str_end-match-1; eye=new_eye; break; } case '[': cnt=read_set(match,cnt+1,set,match_len); match_set: for(e=eye;eye<input_len && set[EXTRACT_UCHAR(input+eye)];eye++); sval.type=T_STRING; #ifdef __CHECKER__ sval.subtype=0; #endif sval.u.string=make_shared_binary_string(input+e,eye-e); break; case 'n': sval.type=T_INT; sval.subtype=NUMBER_NUMBER; sval.u.integer=eye; break; default: error("Unknown sscanf token %%%c\n",match[cnt]); } matches++; if(!no_assign) { arg++; if((num_arg-2)/2<arg) { free_svalue(&sval); error("Too few arguments for format to sscanf.\n"); } assign_lvalue(argp+(2+(arg-1)*2), &sval); } free_svalue(&sval); } return matches; } void f_sscanf(INT32 args) { #ifdef DEBUG extern int t_flag; #endif INT32 i; i=low_sscanf(args); #ifdef DEBUG if(t_flag >2) { int nonblock; if((nonblock=query_nonblocking(2))) set_nonblocking(2,0);
f90e541995-08-17Fredrik Hübinette (Hubbe)  fprintf(stderr,"- Matches: %ld\n",(long)i);
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(nonblock) set_nonblocking(2,1); } #endif pop_n_elems(args); push_int(i); }