diff --git a/src/builtin_functions.c b/src/builtin_functions.c index e9423a0f31830febd3f46a85ba6401164544c4ae..a8149cd316403e40d55802fef01d7a46d0af0064 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.97 1998/04/15 19:10:27 hedda Exp $"); +RCSID("$Id: builtin_functions.c,v 1.98 1998/04/16 01:14:16 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -2748,6 +2748,7 @@ void init_builtin_efuns(void) add_efun("upper_case",f_upper_case,"function(string:string)",0); add_efun("values",f_values,"function(string|multiset:int*)|function(array(0=mixed)|mapping(mixed:0=mixed)|object:array(0))",0); add_efun("zero_type",f_zero_type,"function(mixed:int)",0); + add_efun("array_sscanf",f_sscanf,"function(string,string:array)",0); #ifdef HAVE_LOCALTIME add_efun("localtime",f_localtime,"function(int:mapping(string:int))",OPT_EXTERNAL_DEPEND); diff --git a/src/opcodes.c b/src/opcodes.c index 0cdc1deae3bf8f51b0bc9735ef3974017df3f671..a1de7350a00f6cfa0ca1a318c65d5c9745e72965 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -20,8 +20,9 @@ #include "fd_control.h" #include "cyclic.h" #include "builtin_functions.h" +#include "module_support.h" -RCSID("$Id: opcodes.c,v 1.18 1998/04/14 20:10:49 hubbe Exp $"); +RCSID("$Id: opcodes.c,v 1.19 1998/04/16 01:14:16 hubbe Exp $"); void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { @@ -359,7 +360,7 @@ void f_cast(void) %% */ -static int read_set(char *match,int cnt,char *set,int match_len) +static int read_set(unsigned char *match,int cnt,char *set,int match_len) { int init; int last=0; @@ -379,9 +380,9 @@ static int read_set(char *match,int cnt,char *set,int match_len) for(e=0;e<256;e++) set[e]=0; init=1; } - if(match[cnt]==']') + if(match[cnt]==']' || match[cnt]=='-') { - set[last=']']=init; + set[last=match[cnt]]=init; cnt++; if(cnt>=match_len) error("Error in sscanf format string.\n"); @@ -406,29 +407,21 @@ static int read_set(char *match,int cnt,char *set,int match_len) return cnt; } -static INT32 low_sscanf(INT32 num_arg) + +static INT32 really_low_sscanf(char *input, + long input_len, + char *match, + long match_len, + long *chars_matched, + int *success) { - char *input; - int input_len; - char *match; - int match_len; struct svalue sval; int e,cnt,matches,eye,arg; int no_assign,field_length; 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; + success[0]=0; arg=eye=matches=0; @@ -446,10 +439,17 @@ static INT32 low_sscanf(INT32 num_arg) } } if(eye>=input_len || input[eye]!=match[cnt]) + { + chars_matched[0]=eye; return matches; + } eye++; } - if(cnt>=match_len) return matches; + if(cnt>=match_len) + { + chars_matched[0]=eye; + return matches; + } #ifdef DEBUG if(match[cnt]!='%' || match[cnt+1]=='%') @@ -485,9 +485,64 @@ static INT32 low_sscanf(INT32 num_arg) continue; } + case '{': + { + ONERROR err; + long tmp; + for(e=cnt+1,tmp=1;tmp;e++) + { + if(!match[e]) + { + error("Missing %%} in format string.\n"); + break; /* UNREACHED */ + } + if(match[e]=='%') + { + switch(match[e+1]) + { + case '%': e++; break; + case '}': tmp--; break; + case '{': tmp++; break; + } + } + } + sval.type=T_ARRAY; + sval.u.array=allocate_array(0); + SET_ONERROR(err, do_free_array, sval.u.array); + + while(1) + { + int yes; + struct svalue *save_sp=sp; + really_low_sscanf(input+eye, + input_len-eye, + match+cnt+1, + e-cnt-2, + &tmp, + &yes); + if(yes) + { + f_aggregate(sp-save_sp); + sval.u.array=append_array(sval.u.array,sp-1); + pop_stack(); + eye+=tmp; + }else{ + pop_n_elems(sp-save_sp); + break; + } + } + cnt=e; + UNSET_ONERROR(err); + break; + } + case 'c': if(field_length == -1) field_length = 1; - if(eye+field_length > input_len) return matches; + if(eye+field_length > input_len) + { + chars_matched[0]=eye; + return matches; + } sval.type=T_INT; sval.subtype=NUMBER_NUMBER; sval.u.integer=0; @@ -503,16 +558,25 @@ static INT32 low_sscanf(INT32 num_arg) { char * t; - if(eye>=input_len) return matches; + if(eye>=input_len) + { + chars_matched[0]=eye; + return matches; + } if(field_length != -1 && eye+field_length < input_len) { - char save=input[eye+field_length+1]; + char save=input[eye+field_length]; + input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,10); - input[eye+field_length+1]=save; + input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,10); - if(input + eye == t) return matches; + if(input + eye == t) + { + chars_matched[0]=eye; + return matches; + } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; @@ -523,15 +587,24 @@ static INT32 low_sscanf(INT32 num_arg) { char * t; - if(eye>=input_len) return matches; + if(eye>=input_len) + { + chars_matched[0]=eye; + return matches; + } if(field_length != -1 && eye+field_length < input_len) { - char save=input[eye+field_length+1]; + char save=input[eye+field_length]; + input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,16); - input[eye+field_length+1]=save; + input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,16); - if(input + eye == t) return matches; + if(input + eye == t) + { + chars_matched[0]=eye; + return matches; + } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; @@ -542,15 +615,24 @@ static INT32 low_sscanf(INT32 num_arg) { char * t; - if(eye>=input_len) return matches; + if(eye>=input_len) + { + chars_matched[0]=eye; + return matches; + } if(field_length != -1 && eye+field_length < input_len) { - char save=input[eye+field_length+1]; + char save=input[eye+field_length]; + input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,8); - input[eye+field_length+1]=save; + input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,8); - if(input + eye == t) return matches; + if(input + eye == t) + { + chars_matched[0]=eye; + return matches; + } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; @@ -562,15 +644,24 @@ static INT32 low_sscanf(INT32 num_arg) { char * t; - if(eye>=input_len) return matches; + if(eye>=input_len) + { + chars_matched[0]=eye; + return matches; + } if(field_length != -1 && eye+field_length < input_len) { - char save=input[eye+field_length+1]; + char save=input[eye+field_length]; + input[eye+field_length]=0; /* DANGEROUS */ sval.u.integer=STRTOL(input+eye,&t,0); - input[eye+field_length+1]=save; + input[eye+field_length]=save; }else sval.u.integer=STRTOL(input+eye,&t,0); - if(input + eye == t) return matches; + if(input + eye == t) + { + chars_matched[0]=eye; + return matches; + } eye=t-input; sval.type=T_INT; sval.subtype=NUMBER_NUMBER; @@ -581,9 +672,17 @@ static INT32 low_sscanf(INT32 num_arg) { char * t; - if(eye>=input_len) return matches; + if(eye>=input_len) + { + chars_matched[0]=eye; + return matches; + } sval.u.float_number=STRTOD(input+eye,&t); - if(input + eye == t) return matches; + if(input + eye == t) + { + chars_matched[0]=eye; + return matches; + } eye=t-input; sval.type=T_FLOAT; #ifdef __CHECKER__ @@ -596,7 +695,10 @@ static INT32 low_sscanf(INT32 num_arg) if(field_length != -1) { if(input_len - eye < field_length) + { + chars_matched[0]=eye; return matches; + } sval.type=T_STRING; #ifdef __CHECKER__ @@ -674,7 +776,7 @@ static INT32 low_sscanf(INT32 num_arg) goto match_set; case '[': /* oh dear */ - read_set(match,s-match+1,set,match_len); + read_set((unsigned char *)match,s-match+1,set,match_len); for(e=0;e<256;e++) set[e]=!set[e]; goto match_set; } @@ -704,7 +806,11 @@ static INT32 low_sscanf(INT32 num_arg) end_str_end-end_str_start, input+eye, input_len-eye); - if(!s) return matches; + if(!s) + { + chars_matched[0]=eye; + return matches; + } eye=s-input; new_eye=eye+end_str_end-end_str_start; }else{ @@ -720,7 +826,10 @@ static INT32 low_sscanf(INT32 num_arg) break; } if(eye==input_len) + { + chars_matched[0]=eye; return matches; + } new_eye=p-input; } @@ -736,7 +845,7 @@ static INT32 low_sscanf(INT32 num_arg) } case '[': - cnt=read_set(match,cnt+1,set,match_len); + cnt=read_set((unsigned char *)match,cnt+1,set,match_len); match_set: for(e=eye;eye<input_len && set[EXTRACT_UCHAR(input+eye)];eye++); @@ -760,28 +869,52 @@ static INT32 low_sscanf(INT32 num_arg) } matches++; - if(!no_assign) + 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); + }else{ + check_stack(1); + *sp++=sval; +#ifdef DEBUG + sval.type=99; +#endif } - free_svalue(&sval); } + chars_matched[0]=eye; + success[0]=1; return matches; } -void f_sscanf(INT32 args) +void o_sscanf(INT32 args) { #ifdef DEBUG extern int t_flag; #endif - INT32 i; - i=low_sscanf(args); + INT32 e,i; + int x; + long matched_chars; + struct svalue *save_sp=sp; + + if(sp[-args].type != T_STRING) + error("Bad argument 1 to sscanf().\n"); + + if(sp[1-args].type != T_STRING) + error("Bad argument 1 to sscanf().\n"); + + i=really_low_sscanf(sp[-args].u.string->str, + sp[-args].u.string->len, + sp[1-args].u.string->str, + sp[1-args].u.string->len, + &matched_chars, + &x); + + if(sp-save_sp > args/2-1) + error("Too few arguments for sscanf format.\n"); + + for(x=0;x<sp-save_sp;x++) + assign_lvalue(save_sp-args+2+x*2,save_sp+x); + pop_n_elems(sp-save_sp +args); + #ifdef DEBUG if(t_flag >2) { @@ -793,7 +926,32 @@ void f_sscanf(INT32 args) if(nonblock) set_nonblocking(2,1); } -#endif - pop_n_elems(args); +#endif push_int(i); } + +void f_sscanf(INT32 args) +{ +#ifdef DEBUG + extern int t_flag; +#endif + INT32 e,i; + int x; + long matched_chars; + struct svalue *save_sp=sp; + struct array *a; + + check_all_args("array_sscanf",args,BIT_STRING, BIT_STRING,0); + + i=really_low_sscanf(sp[-args].u.string->str, + sp[-args].u.string->len, + sp[1-args].u.string->str, + sp[1-args].u.string->len, + &matched_chars, + &x); + + a=aggregate_array(sp-save_sp); + pop_n_elems(args); + push_array(a); +} + diff --git a/src/opcodes.h b/src/opcodes.h index c4e2a97aa067e56b9c9e2fc056a795004ff01865..66b111084c30e517e80c69c2b2627167b5713aa7 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: opcodes.h,v 1.4 1998/03/28 15:07:54 grubba Exp $ + * $Id: opcodes.h,v 1.5 1998/04/16 01:14:17 hubbe Exp $ */ #ifndef OPCODES_H #define OPCODES_H @@ -13,8 +13,9 @@ /* Prototypes begin here */ void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind); void o_index(void); -void cast(struct pike_string *s); +void o_cast(struct pike_string *type, INT32 run_time_type); void f_cast(void); +void o_sscanf(INT32 args); void f_sscanf(INT32 args); /* Prototypes end here */