diff --git a/src/opcodes.c b/src/opcodes.c index 473d38dc8d7555549ecd4a81a20220dcdfae9478..2858026d0004cda3f51f6a437a8030e8ebe6e26a 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -25,7 +25,7 @@ #include "security.h" #include "bignum.h" -RCSID("$Id: opcodes.c,v 1.54 1999/10/29 08:21:48 hubbe Exp $"); +RCSID("$Id: opcodes.c,v 1.55 1999/10/31 20:52:09 grubba Exp $"); void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { @@ -762,557 +762,604 @@ static INLINE float low_parse_IEEE_float(char *b, int sz) #endif -static INT32 really_low_sscanf(char *input, - long input_len, - char *match, - long match_len, - long *chars_matched, - int *success) -{ - struct svalue sval; - int e,cnt,matches,eye,arg; - int no_assign = 0, field_length = 0, minus_flag = 0; - char set[256]; - struct svalue *argp; - - success[0]=0; - - 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]) - { - chars_matched[0]=eye; - return matches; - } - eye++; - } - if(cnt>=match_len) - { - chars_matched[0]=eye; - return matches; - } - #ifdef PIKE_DEBUG - if(match[cnt]!='%' || match[cnt+1]=='%') - { - fatal("Error in sscanf.\n"); - } -#endif - - no_assign=0; - field_length=-1; - minus_flag=0; - - cnt++; - if(cnt>=match_len) - error("Error in sscanf format string.\n"); - - while(1) - { - switch(match[cnt]) - { - case '*': - no_assign=1; - cnt++; - if(cnt>=match_len) - error("Error in sscanf format string.\n"); - continue; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - char *t; - field_length=STRTOL(match+cnt,&t,10); - cnt=t-match; - continue; - } - - case '-': - minus_flag=1; - cnt++; - 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(input_len-eye) - { - 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 && tmp) - { - 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; - } +#define DO_IF_DEBUG(X) X +#else /* !PIKE_DEBUG */ +#define DO_IF_DEBUG(X) +#endif /* PIKE_DEBUG */ - case 'c': - if(field_length == -1) field_length = 1; - if(eye+field_length > input_len) - { - chars_matched[0]=eye; - return matches; - } - sval.type=T_INT; - sval.subtype=NUMBER_NUMBER; - sval.u.integer=0; - if (minus_flag) - { - int x, pos=0; - - while(--field_length >= 0) - { - x = EXTRACT_UCHAR(input+eye); - #ifdef AUTO_BIGNUM - if(INT_TYPE_LSH_OVERFLOW(x, pos)) - { - int lshfun, orfun; - push_int(sval.u.integer); - convert_stack_top_to_bignum(); - lshfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_LSH); - orfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_OR); - - while(field_length-- >= 0) - { - push_int(EXTRACT_UCHAR(input+eye)); - convert_stack_top_to_bignum(); - push_int(pos); - apply_low(sp[-2].u.object, lshfun, 1); - stack_swap(); - pop_stack(); - apply_low(sp[-2].u.object, orfun, 1); - stack_swap(); - pop_stack(); - pos+=8; - eye++; - } - sval=*--sp; - break; - } - else +#define DO_IF_BIGNUM(X) X +#else /* !AUTO_BIGNUM */ +#define DO_IF_BIGNUM(X) #endif /* AUTO_BIGNUM */ - sval.u.integer|=x<<pos; - - pos+=8; - eye++; - } - } - else - while(--field_length >= 0) - { -#ifdef AUTO_BIGNUM - if(INT_TYPE_LSH_OVERFLOW(sval.u.integer, 8)) - { - int lshfun, orfun; - push_int(sval.u.integer); - convert_stack_top_to_bignum(); - lshfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_LSH); - orfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_OR); - - while(field_length-- >= 0) - { - push_int(8); - apply_low(sp[-2].u.object, lshfun, 1); - stack_swap(); - pop_stack(); - push_int(EXTRACT_UCHAR(input+eye)); - apply_low(sp[-2].u.object, orfun, 1); - stack_swap(); - pop_stack(); - eye++; - } - sval=*--sp; - break; - } - else -#endif /* AUTO_BIGNUM */ - sval.u.integer<<=8; - sval.u.integer|=EXTRACT_UCHAR(input+eye); - eye++; - } - break; - - case 'b': - case 'o': - case 'd': - case 'x': - case 'D': - case 'i': - { - char * t; - int base = 0; - - if(eye>=input_len) - { - chars_matched[0]=eye; - return matches; - } - - switch(match[cnt]) - { - case 'b': base = 2; break; - case 'o': base = 8; break; - case 'd': base = 10; break; - case 'x': base = 16; break; - } - - string_to_svalue_inumber(&sval, input+eye, &t, base, field_length); - - if(input + eye == t) - { - chars_matched[0]=eye; - return matches; - } - eye=t-input; - break; - } - case 'f': - { - char * t; - - if(eye>=input_len) - { - chars_matched[0]=eye; - return matches; - } - sval.u.float_number=STRTOD(input+eye,&t); - if(input + eye == t) - { - chars_matched[0]=eye; - return matches; - } - eye=t-input; - sval.type=T_FLOAT; #ifdef __CHECKER__ - sval.subtype=0; -#endif - break; - } +#define DO_IF_CHECKER(X) X +#else /* !__CHECKER__ */ +#define DO_IF_CHECKER(X) +#endif /* __CHECKER__ */ - case 'F': - if(field_length == -1) field_length = 4; - if(field_length != 4 && field_length != 8) - error("Invalid IEEE width %d in sscanf format string.\n", - field_length); - if(eye+field_length > input_len) - { - chars_matched[0]=eye; - return matches; - } - sval.type=T_FLOAT; -#ifdef __CHECKER__ - sval.subtype=0; -#endif - switch(field_length) { - case 4: #ifdef FLOAT_IS_IEEE_BIG - { - float f; - ((char *)&f)[0] = *(input+eye); - ((char *)&f)[1] = *(input+eye+1); - ((char *)&f)[2] = *(input+eye+2); - ((char *)&f)[3] = *(input+eye+3); - sval.u.float_number = f; +#define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \ + { \ + float f; \ + ((char *)&f)[0] = *((INPUT)); \ + ((char *)&f)[1] = *((INPUT)+1); \ + ((char *)&f)[2] = *((INPUT)+2); \ + ((char *)&f)[3] = *((INPUT)+3); \ + (SVAL).u.float_number = f; \ } #else #ifdef FLOAT_IS_IEEE_LITTLE - { - float f; - ((char *)&f)[3] = *(input+eye); - ((char *)&f)[2] = *(input+eye+1); - ((char *)&f)[1] = *(input+eye+2); - ((char *)&f)[0] = *(input+eye+3); - sval.u.float_number = f; +#define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \ + { \ + float f; \ + ((char *)&f)[3] = *((INPUT)); \ + ((char *)&f)[2] = *((INPUT)+1); \ + ((char *)&f)[1] = *((INPUT)+2); \ + ((char *)&f)[0] = *((INPUT)+3); \ + (SVAL).u.float_number = f; \ } #else - sval.u.float_number = low_parse_IEEE_float(input+eye, 4); +#define EXTRACT_FLOAT(SVAL, INPUT, SHIFT) \ + /* FIXME! */ \ + (SVAL).u.float_number = low_parse_IEEE_float((INPUT), 4); #endif #endif - eye += 4; - break; - case 8: + #ifdef DOUBLE_IS_IEEE_BIG - { - double d; - ((char *)&d)[0] = *(input+eye); - ((char *)&d)[1] = *(input+eye+1); - ((char *)&d)[2] = *(input+eye+2); - ((char *)&d)[3] = *(input+eye+3); - ((char *)&d)[4] = *(input+eye+4); - ((char *)&d)[5] = *(input+eye+5); - ((char *)&d)[6] = *(input+eye+6); - ((char *)&d)[7] = *(input+eye+7); - sval.u.float_number = (float)d; +#define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \ + { \ + double d; \ + ((char *)&d)[0] = *((INPUT)); \ + ((char *)&d)[1] = *((INPUT)+1); \ + ((char *)&d)[2] = *((INPUT)+2); \ + ((char *)&d)[3] = *((INPUT)+3); \ + ((char *)&d)[4] = *((INPUT)+4); \ + ((char *)&d)[5] = *((INPUT)+5); \ + ((char *)&d)[6] = *((INPUT)+6); \ + ((char *)&d)[7] = *((INPUT)+7); \ + (SVAL).u.float_number = (float)d; \ } #else #ifdef DOUBLE_IS_IEEE_LITTLE - { - double d; - ((char *)&d)[7] = *(input+eye); - ((char *)&d)[6] = *(input+eye+1); - ((char *)&d)[5] = *(input+eye+2); - ((char *)&d)[4] = *(input+eye+3); - ((char *)&d)[3] = *(input+eye+4); - ((char *)&d)[2] = *(input+eye+5); - ((char *)&d)[1] = *(input+eye+6); - ((char *)&d)[0] = *(input+eye+7); - sval.u.float_number = (float)d; +#define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \ + { \ + double d; \ + ((char *)&d)[7] = *((INPUT)); \ + ((char *)&d)[6] = *((INPUT)+1); \ + ((char *)&d)[5] = *((INPUT)+2); \ + ((char *)&d)[4] = *((INPUT)+3); \ + ((char *)&d)[3] = *((INPUT)+4); \ + ((char *)&d)[2] = *((INPUT)+5); \ + ((char *)&d)[1] = *((INPUT)+6); \ + ((char *)&d)[0] = *((INPUT)+7); \ + (SVAL).u.float_number = (float)d; \ } #else - sval.u.float_number = low_parse_IEEE_float(input+eye, 8); +#define EXTRACT_DOUBLE(SVAL, INPUT, SHIFT) \ + /* FIXME! */ \ + (SVAL).u.float_number = low_parse_IEEE_float((INPUT), 8); #endif #endif - eye += 8; - break; - } - break; - case 's': - if(field_length != -1) - { - if(input_len - eye < field_length) - { - chars_matched[0]=eye; - return matches; - } - - sval.type=T_STRING; -#ifdef __CHECKER__ - sval.subtype=0; -#endif - sval.u.string=make_shared_binary_string(input+eye,field_length); - eye+=field_length; - break; - } - - 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); - eye=input_len; - 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("Illegal 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 'o': - for(e=0;e<256;e++) set[e]=1; - for(e='0';e<='7';e++) set[e]=0; - goto match_set; - - case 'x': - for(e=0;e<256;e++) set[e]=1; - for(e='0';e<='9';e++) set[e]=0; - for(e='a';e<='f';e++) set[e]=0; - goto match_set; - - case 'D': - for(e=0;e<256;e++) set[e]=1; - for(e='0';e<='9';e++) set[e]=0; - set['-']=0; - set['x']=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((unsigned char *)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=my_memmem(end_str_start, - end_str_end-end_str_start, - input+eye, - input_len-eye); - if(!s) - { - chars_matched[0]=eye; - 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) - { - chars_matched[0]=eye; - 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((unsigned char *)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]); - } - break; - } - matches++; - - if(no_assign) - { - free_svalue(&sval); - }else{ - check_stack(1); - *sp++=sval; -#ifdef PIKE_DEBUG - sval.type=99; -#endif - } - } - chars_matched[0]=eye; - success[0]=1; - return matches; +#define make_shared_binary_string0(X,Y) make_shared_binary_string(X,Y) + +#define MK_VERY_LOW_SSCANF(INPUT_SHIFT, MATCH_SHIFT) \ +static INT32 PIKE_CONCAT4(very_low_sscanf_,INPUT_SHIFT,_,MATCH_SHIFT)( \ + PIKE_CONCAT(p_wchar, INPUT_SHIFT) *input, \ + long input_len, \ + PIKE_CONCAT(p_wchar, MATCH_SHIFT) *match, \ + long match_len, \ + long *chars_matched, \ + int *success) \ +{ \ + struct svalue sval; \ + int e,cnt,matches,eye,arg; \ + int no_assign = 0, field_length = 0, minus_flag = 0; \ + char set[256]; \ + struct svalue *argp; \ + \ + success[0]=0; \ + \ + 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]) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + eye++; \ + } \ + if(cnt>=match_len) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + \ + DO_IF_DEBUG( \ + if(match[cnt]!='%' || match[cnt+1]=='%') \ + { \ + fatal("Error in sscanf.\n"); \ + } \ + ); \ + \ + no_assign=0; \ + field_length=-1; \ + minus_flag=0; \ + \ + cnt++; \ + if(cnt>=match_len) \ + error("Error in sscanf format string.\n"); \ + \ + while(1) \ + { \ + switch(match[cnt]) \ + { \ + case '*': \ + no_assign=1; \ + cnt++; \ + if(cnt>=match_len) \ + error("Error in sscanf format string.\n"); \ + continue; \ + \ + case '0': case '1': case '2': case '3': case '4': \ + case '5': case '6': case '7': case '8': case '9': \ + { \ + PCHARP t; \ + field_length = STRTOL_PCHARP(MKPCHARP(match+cnt, MATCH_SHIFT),\ + &t,10); \ + cnt = SUBTRACT_PCHARP(t, MKPCHARP(match, MATCH_SHIFT)); \ + continue; \ + } \ + \ + case '-': \ + minus_flag=1; \ + cnt++; \ + 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(input_len-eye) \ + { \ + int yes; \ + struct svalue *save_sp=sp; \ + PIKE_CONCAT4(very_low_sscanf_, INPUT_SHIFT, _, MATCH_SHIFT)(\ + input+eye, \ + input_len-eye, \ + match+cnt+1, \ + e-cnt-2, \ + &tmp, \ + &yes); \ + if(yes && tmp) \ + { \ + 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) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + sval.type=T_INT; \ + sval.subtype=NUMBER_NUMBER; \ + sval.u.integer=0; \ + if (minus_flag) \ + { \ + int x, pos=0; \ + \ + while(--field_length >= 0) \ + { \ + int lshfun, orfun; \ + x = input[eye]; \ + \ + DO_IF_BIGNUM( \ + if(INT_TYPE_LSH_OVERFLOW(x, pos)) \ + { \ + push_int(sval.u.integer); \ + convert_stack_top_to_bignum(); \ + lshfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_LSH); \ + orfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_OR); \ + \ + while(field_length-- >= 0) \ + { \ + push_int(input[eye]); \ + convert_stack_top_to_bignum(); \ + push_int(pos); \ + apply_low(sp[-2].u.object, lshfun, 1); \ + stack_swap(); \ + pop_stack(); \ + apply_low(sp[-2].u.object, orfun, 1); \ + stack_swap(); \ + pop_stack(); \ + pos+=8; \ + eye++; \ + } \ + sval=*--sp; \ + break; \ + } \ + ); \ + sval.u.integer|=x<<pos; \ + \ + pos+=8; \ + eye++; \ + } \ + } \ + else \ + while(--field_length >= 0) \ + { \ + int lshfun, orfun; \ + DO_IF_BIGNUM( \ + if(INT_TYPE_LSH_OVERFLOW(sval.u.integer, 8)) \ + { \ + push_int(sval.u.integer); \ + convert_stack_top_to_bignum(); \ + lshfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_LSH); \ + orfun=FIND_LFUN(sp[-1].u.object->prog, LFUN_OR); \ + \ + while(field_length-- >= 0) \ + { \ + push_int(8); \ + apply_low(sp[-2].u.object, lshfun, 1); \ + stack_swap(); \ + pop_stack(); \ + push_int(input[eye]); \ + apply_low(sp[-2].u.object, orfun, 1); \ + stack_swap(); \ + pop_stack(); \ + eye++; \ + } \ + sval=*--sp; \ + break; \ + } \ + ); \ + sval.u.integer<<=8; \ + sval.u.integer |= input[eye]; \ + eye++; \ + } \ + break; \ + \ + case 'b': \ + case 'o': \ + case 'd': \ + case 'x': \ + case 'D': \ + case 'i': \ + { \ + int base = 0; \ + PIKE_CONCAT(p_wchar, INPUT_SHIFT) *t; \ + \ + if(eye>=input_len) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + \ + switch(match[cnt]) \ + { \ + case 'b': base = 2; break; \ + case 'o': base = 8; break; \ + case 'd': base = 10; break; \ + case 'x': base = 16; break; \ + } \ + \ + /* FIXME! */ \ + string_to_svalue_inumber(&sval, input+eye, &t, \ + base, field_length); \ + \ + if(input + eye == t) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + eye=t-input; \ + break; \ + } \ + \ + case 'f': \ + { \ + PIKE_CONCAT(p_wchar, INPUT_SHIFT) *t; \ + \ + if(eye>=input_len) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + /* FIXME! */ \ + sval.u.float_number=STRTOD(input+eye,&t); \ + if(input + eye == t) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + eye=t-input; \ + sval.type=T_FLOAT; \ + DO_IF_CHECKER(sval.subtype=0); \ + break; \ + } \ + \ + case 'F': \ + if(field_length == -1) field_length = 4; \ + if(field_length != 4 && field_length != 8) \ + error("Invalid IEEE width %d in sscanf format string.\n", \ + field_length); \ + if(eye+field_length > input_len) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + sval.type=T_FLOAT; \ + DO_IF_CHECKER(sval.subtype=0); \ + switch(field_length) { \ + case 4: \ + EXTRACT_FLOAT(sval, input+eye, INPUT_SHIFT); \ + eye += 4; \ + break; \ + case 8: \ + EXTRACT_DOUBLE(sval, input+eye, INPUT_SHIFT); \ + eye += 8; \ + break; \ + } \ + break; \ + \ + case 's': \ + if(field_length != -1) \ + { \ + if(input_len - eye < field_length) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + \ + sval.type=T_STRING; \ + DO_IF_CHECKER(sval.subtype=0); \ + sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ + INPUT_SHIFT)(input+eye, \ + field_length); \ + eye+=field_length; \ + break; \ + } \ + \ + if(cnt+1>=match_len) \ + { \ + sval.type=T_STRING; \ + DO_IF_CHECKER(sval.subtype=0); \ + sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ + INPUT_SHIFT)(input+eye, \ + input_len-eye); \ + eye=input_len; \ + break; \ + }else{ \ + PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_start; \ + PIKE_CONCAT(p_wchar, MATCH_SHIFT) *end_str_end; \ + PIKE_CONCAT(p_wchar, MATCH_SHIFT) *s=0; \ + PIKE_CONCAT(p_wchar, MATCH_SHIFT) *p=0; \ + 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("Illegal 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 'o': \ + for(e=0;e<256;e++) set[e]=1; \ + for(e='0';e<='7';e++) set[e]=0; \ + goto match_set; \ + \ + case 'x': \ + for(e=0;e<256;e++) set[e]=1; \ + for(e='0';e<='9';e++) set[e]=0; \ + for(e='a';e<='f';e++) set[e]=0; \ + goto match_set; \ + \ + case 'D': \ + for(e=0;e<256;e++) set[e]=1; \ + for(e='0';e<='9';e++) set[e]=0; \ + set['-']=0; \ + set['x']=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 */ \ + /* FIXME! */ \ + 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) \ + { \ + /* FIXME! */ \ + PIKE_CONCAT(p_wchar, INPUT_SHIFT) *s2; \ + s2=my_memmem(end_str_start, \ + end_str_end-end_str_start, \ + input+eye, \ + input_len-eye); \ + if(!s2) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + eye=s2-input; \ + new_eye=eye+end_str_end-end_str_start; \ + }else{ \ + PIKE_CONCAT(p_wchar, INPUT_SHIFT) *p2 = NULL; \ + for(;eye<input_len;eye++) \ + { \ + p2=input+eye; \ + for(s=end_str_start;s<end_str_end;s++,p2++) \ + { \ + if(*s!=*p2) break; \ + if(*s=='%') s++; \ + } \ + if(s==end_str_end) \ + break; \ + } \ + if(eye==input_len) \ + { \ + chars_matched[0]=eye; \ + return matches; \ + } \ + new_eye=p2-input; \ + } \ + \ + sval.type=T_STRING; \ + DO_IF_CHECKER(sval.subtype=0); \ + sval.u.string=PIKE_CONCAT(make_shared_binary_string, \ + INPUT_SHIFT)(input+start, \ + eye-start); \ + \ + cnt=end_str_end-match-1; \ + eye=new_eye; \ + break; \ + } \ + \ + case '[': \ + /* FIXME! */ \ + cnt=read_set(match,cnt+1,set,match_len); \ + \ + match_set: \ + /* FIXME! */ \ + for(e=eye;eye<input_len && !(input[eye]&~0xff) && \ + set[input[eye]];eye++); \ + sval.type=T_STRING; \ + DO_IF_CHECKER(sval.subtype=0); \ + 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(0x%02x)\n", \ + match[cnt], match[cnt]); \ + } \ + break; \ + } \ + matches++; \ + \ + if(no_assign) \ + { \ + free_svalue(&sval); \ + }else{ \ + check_stack(1); \ + *sp++=sval; \ + DO_IF_DEBUG(sval.type=99); \ + } \ + } \ + chars_matched[0]=eye; \ + success[0]=1; \ + return matches; \ } +MK_VERY_LOW_SSCANF(0,0) +MK_VERY_LOW_SSCANF(0,1) +MK_VERY_LOW_SSCANF(0,2) +MK_VERY_LOW_SSCANF(1,0) +MK_VERY_LOW_SSCANF(1,1) +MK_VERY_LOW_SSCANF(1,2) +MK_VERY_LOW_SSCANF(2,0) +MK_VERY_LOW_SSCANF(2,1) +MK_VERY_LOW_SSCANF(2,2) + void o_sscanf(INT32 args) { #ifdef PIKE_DEBUG @@ -1329,12 +1376,94 @@ void o_sscanf(INT32 args) 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); + switch(sp[-args].u.string->size_shift*3 + sp[1-args].u.string->size_shift) { + /* input_shift : match_shift */ + case 0: + /* 0 : 0 */ + i=very_low_sscanf_0_0(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 1: + /* 0 : 1 */ + i=very_low_sscanf_0_1(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 2: + /* 0 : 2 */ + i=very_low_sscanf_0_2(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 3: + /* 1 : 0 */ + i=very_low_sscanf_1_0(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 4: + /* 1 : 1 */ + i=very_low_sscanf_1_1(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 5: + /* 1 : 2 */ + i=very_low_sscanf_1_2(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 6: + /* 2 : 0 */ + i=very_low_sscanf_2_0(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 7: + /* 2 : 1 */ + i=very_low_sscanf_2_1(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 8: + /* 2 : 2 */ + i=very_low_sscanf_2_2(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + default: + error("Unsupported shift-combination to sscanf(): %d:%d\n", + sp[-args].u.string->size_shift, sp[1-args].u.string->size_shift); + break; + } if(sp-save_sp > args/2-1) error("Too few arguments for sscanf format.\n"); @@ -1371,12 +1500,94 @@ void f_sscanf(INT32 args) 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); + switch(sp[-args].u.string->size_shift*3 + sp[1-args].u.string->size_shift) { + /* input_shift : match_shift */ + case 0: + /* 0 : 0 */ + i=very_low_sscanf_0_0(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 1: + /* 0 : 1 */ + i=very_low_sscanf_0_1(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 2: + /* 0 : 2 */ + i=very_low_sscanf_0_2(STR0(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 3: + /* 1 : 0 */ + i=very_low_sscanf_1_0(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 4: + /* 1 : 1 */ + i=very_low_sscanf_1_1(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 5: + /* 1 : 2 */ + i=very_low_sscanf_1_2(STR1(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 6: + /* 2 : 0 */ + i=very_low_sscanf_2_0(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR0(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 7: + /* 2 : 1 */ + i=very_low_sscanf_2_1(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR1(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + case 8: + /* 2 : 2 */ + i=very_low_sscanf_2_2(STR2(sp[-args].u.string), + sp[-args].u.string->len, + STR2(sp[1-args].u.string), + sp[1-args].u.string->len, + &matched_chars, + &x); + break; + default: + error("Unsupported shift-combination to sscanf(): %d:%d\n", + sp[-args].u.string->size_shift, sp[1-args].u.string->size_shift); + break; + } a=aggregate_array(sp-save_sp); pop_n_elems(args);