From 0bc4cf6b34beed14dc76afd238a468d0a18b848d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Tue, 13 Oct 1998 22:51:20 -0700 Subject: [PATCH] lots of wide-string stuff Rev: bin/test_pike.pike:1.14 Rev: src/array.c:1.41 Rev: src/builtin_functions.c:1.129 Rev: src/modules/sprintf/sprintf.c:1.28 Rev: src/operators.c:1.43 Rev: src/pike_memory.c:1.27 Rev: src/stralloc.c:1.43 Rev: src/stralloc.h:1.21 Rev: src/testsuite.in:1.126 --- bin/test_pike.pike | 4 +- src/array.c | 17 +- src/builtin_functions.c | 78 ++++--- src/modules/sprintf/sprintf.c | 405 ++++++++++++++++++++-------------- src/operators.c | 160 +++++++------- src/pike_memory.c | 4 +- src/stralloc.c | 217 ++++++++++++++---- src/stralloc.h | 68 +++++- src/testsuite.in | 53 ++++- 9 files changed, 664 insertions(+), 342 deletions(-) diff --git a/bin/test_pike.pike b/bin/test_pike.pike index be45085c1e..31b09c37c1 100755 --- a/bin/test_pike.pike +++ b/bin/test_pike.pike @@ -1,6 +1,6 @@ #!/usr/local/bin/pike -/* $Id: test_pike.pike,v 1.13 1998/04/17 05:04:49 hubbe Exp $ */ +/* $Id: test_pike.pike,v 1.14 1998/10/14 05:47:06 hubbe Exp $ */ #include <simulate.h> @@ -121,7 +121,7 @@ int main(int argc, string *argv) if(verbose) { - werror("Doing test "+(e+1)+"\n"); + werror("Doing test %d (%d total)\n",e+1,successes+errors+1); if(verbose>1) werror(test+"\n"); } diff --git a/src/array.c b/src/array.c index f7ff3ceec9..4dab2f2b14 100644 --- a/src/array.c +++ b/src/array.c @@ -19,7 +19,7 @@ #include "gc.h" #include "main.h" -RCSID("$Id: array.c,v 1.40 1998/10/11 11:18:50 hubbe Exp $"); +RCSID("$Id: array.c,v 1.41 1998/10/14 05:48:44 hubbe Exp $"); struct array empty_array= { @@ -1424,7 +1424,7 @@ struct array *explode(struct pike_string *str, struct pike_string *implode(struct array *a,struct pike_string *del) { INT32 len,e, inited; - char *r; + PCHARP r; struct pike_string *ret,*tmp; int max_shift=0; @@ -1439,10 +1439,11 @@ struct pike_string *implode(struct array *a,struct pike_string *del) max_shift=ITEM(a)[e].u.string->size_shift; } } + if(del->size_shift > max_shift) max_shift=del->size_shift; if(len) len-=del->len; ret=begin_wide_shared_string(len,max_shift); - r=ret->str; + r=MKPCHARP_STR(ret); inited=0; for(e=0;e<a->size;e++) { @@ -1450,17 +1451,17 @@ struct pike_string *implode(struct array *a,struct pike_string *del) { if(inited) { - pike_string_cpy(r,max_shift,del); - r+=del->len << max_shift; + pike_string_cpy(r,del); + INC_PCHARP(r,del->len); } inited=1; tmp=ITEM(a)[e].u.string; - pike_string_cpy(r,max_shift,tmp); - r+=tmp->len << max_shift; + pike_string_cpy(r,tmp); + INC_PCHARP(r,tmp->len); len++; } } - return end_shared_string(ret); + return low_end_shared_string(ret); } struct array *copy_array_recursively(struct array *a,struct processing *p) diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 741423ffaa..3bdc252e87 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.128 1998/10/11 11:18:50 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.129 1998/10/14 05:48:45 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -132,6 +132,7 @@ void f_ctime(INT32 args) push_string(make_shared_string(ctime(&i))); } +/* FIXME: wide char support ! */ void f_lower_case(INT32 args) { INT32 i; @@ -152,6 +153,7 @@ void f_lower_case(INT32 args) push_string(end_shared_string(ret)); } +/* FIXME: wide char support ! */ void f_upper_case(INT32 args) { INT32 i; @@ -217,7 +219,6 @@ void f_search(INT32 args) case T_STRING: { char *ptr; - INT32 len; if(sp[1-args].type != T_STRING) PIKE_ERROR("search", "Bad argument 2.\n", sp, args); @@ -231,20 +232,13 @@ void f_search(INT32 args) if(start<0) PIKE_ERROR("search", "Start must be greater or equal to zero.\n", sp, args); } - len=sp[-args].u.string->len - start; if(len<0) PIKE_ERROR("search", "Start must not be greater than the length of the string.\n", sp, args); - if(len>0 && (ptr=my_memmem(sp[1-args].u.string->str, - sp[1-args].u.string->len, - sp[-args].u.string->str+start, - len))) - { - start=ptr-sp[-args].u.string->str; - }else{ - start=-1; - } + start=string_search(sp[-args].u.string, + sp[1-args].u.string, + start); pop_n_elems(args); push_int(start); break; @@ -1135,10 +1129,26 @@ void f_reverse(INT32 args) { INT32 e; struct pike_string *s; - s=begin_shared_string(sp[-args].u.string->len); - for(e=0;e<sp[-args].u.string->len;e++) - s->str[e]=sp[-args].u.string->str[sp[-args].u.string->len-1-e]; - s=end_shared_string(s); + s=begin_wide_shared_string(sp[-args].u.string->len, + sp[-args].u.string->size_shift); + switch(sp[-args].u.string->size_shift) + { + case 0: + for(e=0;e<sp[-args].u.string->len;e++) + STR0(s)[e]=STR0(sp[-args].u.string)[sp[-args].u.string->len-1-e]; + break; + + case 1: + for(e=0;e<sp[-args].u.string->len;e++) + STR1(s)[e]=STR1(sp[-args].u.string)[sp[-args].u.string->len-1-e]; + break; + + case 2: + for(e=0;e<sp[-args].u.string->len;e++) + STR2(s)[e]=STR2(sp[-args].u.string)[sp[-args].u.string->len-1-e]; + break; + } + s=low_end_shared_string(s); pop_n_elems(args); push_string(s); break; @@ -1360,12 +1370,17 @@ void f_replace(INT32 args) void f_compile(INT32 args) { struct program *p; + if(args < 1) PIKE_ERROR("compile", "Too few arguments.\n", sp, args); if(sp[-args].type != T_STRING) PIKE_ERROR("compile", "Bad argument 1.\n", sp, args); + if(sp[-args].u.string->size_shift) + PIKE_ERROR("compile", "Wide strings not supported yet.\n", sp, args); + + p=compile(sp[-args].u.string); pop_n_elems(args); push_program(p); @@ -1808,33 +1823,34 @@ static void f_mktime (INT32 args) /* Check if the string s[0..len[ matches the glob m[0..mlen[ */ -static int does_match(char *s, int len, char *m, int mlen) +static int does_match(struct pike_string *s,int j, + struct pike_string *m,int i) { - int i,j; - for (i=j=0; i<mlen; i++) + for (; i<m->len; i++) { - switch (m[i]) + switch (index_shared_string(m,i)) { case '?': - if(j++>=len) return 0; + if(j++>=s->len) return 0; break; case '*': i++; - if (i==mlen) return 1; /* slut */ + if (i==m->len) return 1; /* slut */ - for (;j<len;j++) - if (does_match(s+j,len-j,m+i,mlen-i)) + for (;j<s->len;j++) + if (does_match(s,j,m,i)) return 1; return 0; default: - if(j>=len || m[i]!=s[j]) return 0; + if(j>=s->len || + index_shared_string(m,i)!=index_shared_string(s,j)) return 0; j++; } } - return j==len; + return j==s->len; } void f_glob(INT32 args) @@ -1858,10 +1874,7 @@ void f_glob(INT32 args) switch(sp[1-args].type) { case T_STRING: - i=does_match(sp[1-args].u.string->str, - sp[1-args].u.string->len, - glob->str, - glob->len); + i=does_match(sp[1-args].u.string,0,glob,0); pop_n_elems(2); push_int(i); break; @@ -1874,10 +1887,7 @@ void f_glob(INT32 args) if(ITEM(a)[i].type != T_STRING) PIKE_ERROR("glob", "Bad argument 2.\n", sp, args); - if(does_match(ITEM(a)[i].u.string->str, - ITEM(a)[i].u.string->len, - glob->str, - glob->len)) + if(does_match(ITEM(a)[i].u.string,0,glob,0)) { add_ref(ITEM(a)[i].u.string); push_string(ITEM(a)[i].u.string); diff --git a/src/modules/sprintf/sprintf.c b/src/modules/sprintf/sprintf.c index fa9e8f0d3b..4d530ae716 100644 --- a/src/modules/sprintf/sprintf.c +++ b/src/modules/sprintf/sprintf.c @@ -3,6 +3,9 @@ ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/ + +/* TODO: use ONERROR to cleanup fsp */ + /* Pike Sprintf v2.0 By Fredrik Hubinette (Profezzorn@nannymud) Should be reasonably compatible and somewhat faster than v1.05+ of Lynscar's @@ -96,7 +99,7 @@ */ #include "global.h" -RCSID("$Id: sprintf.c,v 1.27 1998/08/07 16:29:07 grubba Exp $"); +RCSID("$Id: sprintf.c,v 1.28 1998/10/14 05:51:20 hubbe Exp $"); #include "error.h" #include "array.h" #include "svalue.h" @@ -107,6 +110,7 @@ RCSID("$Id: sprintf.c,v 1.27 1998/08/07 16:29:07 grubba Exp $"); #include "interpret.h" #include "pike_memory.h" #include "pike_macros.h" +#include <ctype.h> #ifdef PC #undef PC @@ -126,17 +130,17 @@ RCSID("$Id: sprintf.c,v 1.27 1998/08/07 16:29:07 grubba Exp $"); struct format_info { char *fi_free_string; - char *b; + PCHARP b; int len; int width; int precision; - char *pad_string; + PCHARP pad_string; int pad_length; int column_entries; short flags; - short pos_pad; - short column_width; - short column_modulo; + char pos_pad; + int column_width; + int column_modulo; }; static struct format_info format_info_stack[FORMAT_INFO_STACK_SIZE]; @@ -340,57 +344,62 @@ INLINE static void low_write_IEEE_float(char *b, double d, int sz) /* Position a string inside a field with fill */ -INLINE static void fix_field(char *b, +INLINE static void fix_field(struct string_builder *r, + PCHARP b, int len, int flags, int width, - char *pad_string, + PCHARP pad_string, int pad_length, char pos_pad) { int e,d; if(!width) { - if(pos_pad && b[0]!='-') my_putchar(pos_pad); - my_binary_strcat(b,len); + if(pos_pad && EXTRACT_PCHARP(b)!='-') string_builder_putchar(r,pos_pad); + string_builder_append(r,b,len); return; } d=0; - if(!(flags & DO_TRUNC) && len+(pos_pad && b[0]!='-')>=width) + if(!(flags & DO_TRUNC) && len+(pos_pad && EXTRACT_PCHARP(b)!='-')>=width) { - if(pos_pad && b[0]!='-') my_putchar(pos_pad); - my_binary_strcat(b,len); + if(pos_pad && EXTRACT_PCHARP(b)!='-') string_builder_putchar(r,pos_pad); + string_builder_append(r,b,len); return; } if(flags & ZERO_PAD) /* zero pad is kind of special... */ { - if(b[0]=='-') + if(EXTRACT_PCHARP(b)=='-') { - my_putchar('-'); - b++; + string_builder_putchar(r,'-'); + INC_PCHARP(b,1); len--; width--; }else{ if(pos_pad) { - my_putchar(pos_pad); + string_builder_putchar(r,pos_pad); width--; } } - for(;width>len;width--) my_putchar('0'); - my_binary_strcat(b,len); +#if 1 + string_builder_fill(r,width-len,MKPCHARP("0",0),1,0); +#else + for(;width>len;width--) string_builder_putchar(r,'0'); +#endif + string_builder_append(r,b,len); return; } if(flags & FIELD_CENTER) { e=len; - if(pos_pad && b[0]!='-') e++; + if(pos_pad && EXTRACT_PCHARP(b)!='-') e++; e=(width-e)/2; if(e>0) { - memfill(make_buf_space(e), e, pad_string, pad_length, 0); + string_builder_fill(r,e,pad_string, pad_length, 0); width-=e; } flags|=FIELD_LEFT; @@ -398,11 +407,18 @@ INLINE static void fix_field(char *b, if(flags & FIELD_LEFT) { - if(pos_pad && b[0]!='-') { my_putchar(pos_pad); width--; d++; } + if(pos_pad && EXTRACT_PCHARP(b)!='-') + { + string_builder_putchar(r,pos_pad); + width--; + d++; + } + d+=MINIMUM(width,len); while(len && width) { - my_putchar(*(b++)); + string_builder_putchar(r,EXTRACT_PCHARP(b)); + INC_PCHARP(b,1); len--; width--; } @@ -410,7 +426,7 @@ INLINE static void fix_field(char *b, if(width>0) { d%=pad_length; - memfill(make_buf_space(width), width, pad_string, pad_length, d); + string_builder_fill(r,width,pad_string,pad_length,d); } return; @@ -418,22 +434,22 @@ INLINE static void fix_field(char *b, /* Right-justification */ - if(pos_pad && b[0]!='-') len++; + if(pos_pad && EXTRACT_PCHARP(b)!='-') len++; e=width-len; if(e>0) { - memfill(make_buf_space(e), e, pad_string, pad_length, 0); + string_builder_fill(r,e,pad_string, pad_length, 0); width-=e; } - if(pos_pad && b[0]!='-' && len==width) + if(pos_pad && EXTRACT_PCHARP(b)!='-' && len==width) { - my_putchar(pos_pad); + string_builder_putchar(r,pos_pad); len--; width--; } - b+=len-width; - my_binary_strcat(b,width); + INC_PCHARP(b,len-width); + string_builder_append(r,b,width); } static struct svalue temp_svalue = { T_INT }; @@ -468,12 +484,13 @@ static void sprintf_error(char *s,...) * if there is more for next line. */ -INLINE static int do_one(struct format_info *f) +INLINE static int do_one(struct string_builder *r, + struct format_info *f) { - char *rest; + PCHARP rest; int e,d,lastspace; - rest=NULL; + rest.ptr=0; if(f->flags & (LINEBREAK|ROUGH_LINEBREAK)) { if(!f->width) @@ -481,28 +498,40 @@ INLINE static int do_one(struct format_info *f) lastspace=-1; for(e=0;e<f->len && e<=f->width;e++) { - if(f->b[e]=='\n') + switch(INDEX_PCHARP(f->b,e)) { - lastspace=e; - rest=f->b+e+1; - break; - } - if(f->b[e]==' ' && (f->flags & LINEBREAK)) - { - lastspace=e; - rest=f->b+e+1; + case '\n': + lastspace=e; + rest=ADD_PCHARP(f->b,e+1); + break; + + case ' ': + if(f->flags & LINEBREAK) + { + lastspace=e; + rest=ADD_PCHARP(f->b,e+1); + } + default: + continue; } + break; } if(e==f->len && f->len<=f->width) { lastspace=e; - rest=f->b+lastspace; + rest=ADD_PCHARP(f->b,lastspace); }else if(lastspace==-1){ lastspace=MINIMUM(f->width,f->len); - rest=f->b+lastspace; + rest=ADD_PCHARP(f->b,lastspace); } - fix_field(f->b,lastspace,f->flags,f->width,f->pad_string, - f->pad_length,f->pos_pad); + fix_field(r, + f->b, + lastspace, + f->flags, + f->width, + f->pad_string, + f->pad_length, + f->pos_pad); } else if(f->flags & INVERSE_COLUMN_MODE) { @@ -512,33 +541,45 @@ INLINE static int do_one(struct format_info *f) if(!f->column_width || e<1) e=1; rest=f->b; - for(d=0;rest[d] && e;d++) + for(d=0;INDEX_PCHARP(rest,d) && e;d++) { #if 0 if(rest != f->b) fix_field(" ",1,0,1," ",1,0); #endif - while(rest[d] && rest[d]!='\n') d++; - fix_field(rest,d,f->flags,f->column_width,f->pad_string, - f->pad_length,f->pos_pad); + while(INDEX_PCHARP(rest,d) && INDEX_PCHARP(rest,d)!='\n') + d++; + + fix_field(r, + rest, + d, + f->flags, + f->column_width, + f->pad_string, + f->pad_length, + f->pos_pad); e--; - rest+=d; + INC_PCHARP(rest,d); d=-1; - if(*rest) rest++; + if(EXTRACT_PCHARP(rest)) INC_PCHARP(rest,1); } } else if(f->flags & COLUMN_MODE) { int mod,col; + PCHARP end; + if(!f->width) sprintf_error("Must have field width for column mode.\n"); mod=f->column_modulo; col=f->width/(f->column_width+1); if(!f->column_width || col<1) col=1; rest=f->b; - for(d=0;rest && d<col;d++) + end=ADD_PCHARP(rest,f->len); + + for(d=0;rest.ptr && d<col;d++) { #if 0 if(rest != f->b) @@ -546,51 +587,52 @@ INLINE static int do_one(struct format_info *f) #endif /* Find end of entry */ - for(e=0;rest[e] && rest[e]!='\n';e++); + for(e=0;COMPARE_PCHARP(rest,<,end) && INDEX_PCHARP(rest,e)!='\n';e++); - fix_field(rest,e,f->flags,f->column_width, + fix_field(r,rest,e,f->flags,f->column_width, f->pad_string,f->pad_length,f->pos_pad); f->column_entries--; /* Advance to after entry */ - rest+=e; - if(!*rest) break; - rest++; + INC_PCHARP(rest,e); + if(!COMPARE_PCHARP(rest,<,end)) break; + INC_PCHARP(rest,1); for(e=1;e<mod;e++) { - char *s=STRCHR(rest,'\n'); - if(s) + PCHARP s=MEMCHR_PCHARP(rest,'\n',SUBTRACT_PCHARP(end,rest)); + if(s.ptr) { - rest=s+1; + rest=ADD_PCHARP(s,1); }else{ - rest=0; + rest.ptr=0; break; } } } if(f->column_entries>0) { - for(rest=f->b;*rest && *rest!='\n';rest++); - if(*rest) rest++; + for(rest=f->b;COMPARE_PCHARP(rest,>=,end) && + EXTRACT_PCHARP(rest)!='\n';INC_PCHARP(rest,1)); + if(COMPARE_PCHARP(rest,<,end)) INC_PCHARP(rest,1); }else{ - rest=NULL; + rest.ptr=0; } } else { - fix_field(f->b,f->len,f->flags,f->width,f->pad_string,f->pad_length,f->pos_pad); + fix_field(r,f->b,f->len,f->flags,f->width,f->pad_string,f->pad_length,f->pos_pad); } if(f->flags & REPEAT) return 0; - if(rest) + if(rest.ptr) { - f->len-=rest-f->b; + f->len-=SUBTRACT_PCHARP(rest,f->b); f->b=rest; }else{ f->len=0; - f->b=""; + f->b=MKPCHARP("",0); } return f->len>0; } @@ -632,26 +674,28 @@ INLINE static int do_one(struct format_info *f) #define DO_OP() \ if(fsp->flags & SNURKEL) \ { \ + ONERROR _e; \ struct array *_v; \ - string _b; \ - _b.str=0; \ - _b.len=0; \ + struct string_builder _b; \ + init_string_builder(&_b,0); \ + SET_ONERROR(_e, free_string_builder, &_b); \ GET_ARRAY(_v); \ for(tmp=0;tmp<_v->size;tmp++) \ { \ struct svalue *save_sp=sp; \ array_index_no_free(sp,_v,tmp); \ sp++; \ - _b=low_pike_sprintf(begin,a-begin+1,sp-1,1,_b,nosnurkel+1); \ + low_pike_sprintf(&_b,begin,SUBTRACT_PCHARP(a,begin)+1,sp-1,1,nosnurkel+1); \ if(save_sp < sp) pop_stack(); \ } \ - fsp->b=_b.str; \ - fsp->len=_b.len; \ - fsp->fi_free_string=fsp->b; \ - fsp->pad_string=" "; \ + fsp->b=MKPCHARP_STR(_b.s); \ + fsp->len=_b.s->len; \ + fsp->fi_free_string=(char *)_b.s; \ + fsp->pad_string=MKPCHARP(" ",0); \ fsp->pad_length=1; \ fsp->column_width=0; \ fsp->pos_pad=fsp->flags=fsp->width=fsp->precision=0; \ + UNSET_ONERROR(_e); \ break; \ } @@ -661,24 +705,26 @@ INLINE static int do_one(struct format_info *f) * the buffer in save_objectII.c */ -static string low_pike_sprintf(char *format, - int format_len, - struct svalue *argp, - int num_arg, - string prefix, - int nosnurkel) +static void low_pike_sprintf(struct string_builder *r, + PCHARP format, + int format_len, + struct svalue *argp, + int num_arg, + int nosnurkel) { int argument=0; int tmp,setwhat,pos,d,e; - char *a,*begin; - char buffer[40]; + char buffer[140]; struct format_info *f,*start; float tf; struct svalue *arg=0; /* pushback argument */ struct svalue *lastarg=0; + PCHARP a,begin; + PCHARP format_end=ADD_PCHARP(format,format_len); + start=fsp; - for(a=format;a<format+format_len;a++) + for(a=format;COMPARE_PCHARP(a,<,format_end);INC_PCHARP(a,1)) { int num_snurkel; @@ -689,19 +735,20 @@ static string low_pike_sprintf(char *format, #endif if(fsp-format_info_stack==FORMAT_INFO_STACK_SIZE) sprintf_error("Sprintf stack overflow.\n"); - fsp->pad_string=" "; + fsp->pad_string=MKPCHARP(" ",0); fsp->pad_length=1; - fsp->fi_free_string=NULL; + fsp->fi_free_string=0; fsp->column_width=0; fsp->pos_pad=fsp->flags=fsp->width=fsp->precision=0; - if(*a!='%') + if(EXTRACT_PCHARP(a)!='%') { - for(e=0;a[e]!='%' && a+e<format+format_len;e++); + for(e=0;INDEX_PCHARP(a,e)!='%' && + COMPARE_PCHARP(ADD_PCHARP(a,e),<,format_end);e++); fsp->b=a; fsp->len=e; fsp->width=e; - a+=e-1; + INC_PCHARP(a,e-1); continue; } num_snurkel=0; @@ -709,12 +756,19 @@ static string low_pike_sprintf(char *format, setwhat=pos=0; begin=a; - for(a++;;a++) + for(INC_PCHARP(a,1);;INC_PCHARP(a,1)) { - switch(*a) +/* fprintf(stderr,"sprintf-flop: %d (%c)\n",EXTRACT_PCHARP(a),EXTRACT_PCHARP(a)); */ + switch(EXTRACT_PCHARP(a)) { default: - sprintf_error("Error in format string.\n"); + if(EXTRACT_PCHARP(a) < 256 && + isprint(EXTRACT_PCHARP(a))) + { + sprintf_error("Error in format string, %c is not a format.\n",EXTRACT_PCHARP(a)); + }else{ + sprintf_error("Error in format string, \\%o is not a format.\n",EXTRACT_PCHARP(a)); + } fatal("Foo, you shouldn't be here!\n"); /* First the modifiers */ @@ -723,8 +777,8 @@ static string low_pike_sprintf(char *format, case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - tmp=STRTOL(a,&a,10); - a--; + tmp=STRTOL_PCHARP(a,&a,10); + INC_PCHARP(a,-1); goto got_arg; case '*': @@ -766,22 +820,25 @@ static string low_pike_sprintf(char *format, case '\'': tmp=0; - for(a++;a[tmp]!='\'';tmp++) - if(a >= format + format_len ) + for(INC_PCHARP(a,1);INDEX_PCHARP(a,tmp)!='\'';tmp++) + { +/* fprintf(stderr,"Sprinf-glop: %d (%c)\n",INDEX_PCHARP(a,tmp),INDEX_PCHARP(a,tmp)); */ + if(COMPARE_PCHARP(a,>=,format_end)) sprintf_error("Unfinished pad string in format string.\n"); + } if(tmp) { fsp->pad_string=a; fsp->pad_length=tmp; } - a+=tmp; + INC_PCHARP(a,tmp); continue; case '~': { struct pike_string *s; GET_STRING(s); - fsp->pad_string=s->str; + fsp->pad_string=MKPCHARP_STR(s); fsp->pad_length=s->len; continue; } @@ -797,21 +854,21 @@ static string low_pike_sprintf(char *format, case '{': { struct array *w; - string b; + struct string_builder b; #ifdef DEBUG struct format_info *fsp_save=fsp; #endif DO_OP(); for(e=1,tmp=1;tmp;e++) { - if(!a[e]) + if(!INDEX_PCHARP(a,e)) { sprintf_error("Missing %%} in format string.\n"); break; /* UNREACHED */ } - if(a[e]=='%') + if(INDEX_PCHARP(a,e)=='%') { - switch(a[e+1]) + switch(INDEX_PCHARP(a,e+1)) { case '%': e++; break; case '}': tmp--; break; @@ -823,11 +880,12 @@ static string low_pike_sprintf(char *format, GET_ARRAY(w); if(!w->size) { - fsp->b=""; + fsp->b=MKPCHARP("",0); fsp->len=0; }else{ - b.str=NULL; - b.len=0; + ONERROR err; + init_string_builder(&b,0); + SET_ONERROR(err,free_string_builder,&b); for(tmp=0;tmp<w->size;tmp++) { struct svalue *s; @@ -844,7 +902,7 @@ static string low_pike_sprintf(char *format, array_index_no_free(sp,w,tmp); sp++; } - b=low_pike_sprintf(a+1,e-2,s,sp-s,b,0); + low_pike_sprintf(&b,ADD_PCHARP(a,1),e-2,s,sp-s,0); pop_n_elems(sp-s); } #ifdef DEBUG @@ -853,22 +911,24 @@ static string low_pike_sprintf(char *format, if(fsp!=fsp_save) fatal("sprintf: fsp incorrect after recursive sprintf.\n"); #endif - fsp->b=b.str; - fsp->len=b.len; - fsp->fi_free_string=fsp->b; + fsp->b=MKPCHARP_STR(b.s); + fsp->len=b.s->len; + fsp->fi_free_string=(char *)b.s; + UNSET_ONERROR(err); } - a+=e; + + INC_PCHARP(a,e); break; } case '%': - fsp->b="%"; + fsp->b=MKPCHARP("%",0); fsp->len=fsp->width=1; break; case 'n': DO_OP(); - fsp->b=""; + fsp->b=MKPCHARP("",0); fsp->len=0; break; @@ -877,23 +937,25 @@ static string low_pike_sprintf(char *format, struct svalue *t; DO_OP(); GET_SVALUE(t); - fsp->b=get_name_of_type(t->type); - fsp->len=strlen(fsp->b); + fsp->b=MKPCHARP(get_name_of_type(t->type),0); + fsp->len=strlen((char *)fsp->b.ptr); break; } case 'c': { INT32 l,tmp; + char *x; DO_OP(); l=1; if(fsp->width > 0) l=fsp->width; - fsp->b=(char *)alloca(l); + x=(char *)alloca(l); + fsp->b=MKPCHARP(x,0); fsp->len=l; GET_INT(tmp); while(--l>=0) { - fsp->b[l]=tmp & 0xff; + x[l]=tmp & 0xff; tmp>>=8; } break; @@ -904,36 +966,45 @@ static string low_pike_sprintf(char *format, case 'u': case 'x': case 'X': + { + char *x; DO_OP(); GET_INT(tmp); buffer[0]='%'; - buffer[1]=*a; + buffer[1]=EXTRACT_PCHARP(a); buffer[2]=0; - fsp->b=(char *)alloca(100); - sprintf(fsp->b,buffer,tmp); - fsp->len=strlen(fsp->b); + x=(char *)alloca(100); + fsp->b=MKPCHARP(x,0); + sprintf(x,buffer,tmp); + fsp->len=strlen(x); break; + } case 'e': case 'f': case 'g': case 'E': case 'G': + { + char *x; DO_OP(); - fsp->b=(char *)xalloc(100+MAXIMUM(fsp->width,8)+ + x=(char *)xalloc(100+MAXIMUM(fsp->width,8)+ MAXIMUM(fsp->precision,3)); - sprintf(buffer,"%%*.*%c",*a); + fsp->b=MKPCHARP(x,0); + sprintf(buffer,"%%*.*%c",EXTRACT_PCHARP(a)); GET_FLOAT(tf); - sprintf(fsp->b,buffer, + sprintf(x,buffer, fsp->width?fsp->width:8, fsp->precision?fsp->precision:3,tf); - fsp->len=strlen(fsp->b); - fsp->fi_free_string=fsp->b; + fsp->len=strlen(x); + fsp->fi_free_string=x; break; + } case 'F': { INT32 l; + char *x; #if defined(DOUBLE_IS_IEEE_LITTLE) || defined(DOUBLE_IS_IEEE_BIG) double td; #endif @@ -942,42 +1013,43 @@ static string low_pike_sprintf(char *format, if(fsp->width > 0) l=fsp->width; if(l != 4 && l != 8) sprintf_error("Invalid IEEE width %d.\n", l); - fsp->b=(char *)alloca(l); + x=(char *)alloca(l); + fsp->b=MKPCHARP(x,0); fsp->len=l; GET_FLOAT(tf); switch(l) { case 4: #ifdef FLOAT_IS_IEEE_BIG - MEMCPY(fsp->b, &tf, 4); + MEMCPY(x, &tf, 4); #else #ifdef FLOAT_IS_IEEE_LITTLE - fsp->b[0] = ((char *)&tf)[3]; - fsp->b[1] = ((char *)&tf)[2]; - fsp->b[2] = ((char *)&tf)[1]; - fsp->b[3] = ((char *)&tf)[0]; + x[0] = ((char *)&tf)[3]; + x[1] = ((char *)&tf)[2]; + x[2] = ((char *)&tf)[1]; + x[3] = ((char *)&tf)[0]; #else - low_write_IEEE_float(fsp->b, (double)tf, 4); + low_write_IEEE_float(x, (double)tf, 4); #endif #endif break; case 8: #ifdef DOUBLE_IS_IEEE_BIG td = (double)tf; - MEMCPY(fsp->b, &td, 8); + MEMCPY(x, &td, 8); #else #ifdef DOUBLE_IS_IEEE_LITTLE td = (double)tf; - fsp->b[0] = ((char *)&td)[7]; - fsp->b[1] = ((char *)&td)[6]; - fsp->b[2] = ((char *)&td)[5]; - fsp->b[3] = ((char *)&td)[4]; - fsp->b[4] = ((char *)&td)[3]; - fsp->b[5] = ((char *)&td)[2]; - fsp->b[6] = ((char *)&td)[1]; - fsp->b[7] = ((char *)&td)[0]; + x[0] = ((char *)&td)[7]; + x[1] = ((char *)&td)[6]; + x[2] = ((char *)&td)[5]; + x[3] = ((char *)&td)[4]; + x[4] = ((char *)&td)[3]; + x[5] = ((char *)&td)[2]; + x[6] = ((char *)&td)[1]; + x[7] = ((char *)&td)[0]; #else - low_write_IEEE_float(fsp->b, (double)tf, 8); + low_write_IEEE_float(x, (double)tf, 8); #endif #endif } @@ -993,9 +1065,9 @@ static string low_pike_sprintf(char *format, init_buf(); describe_svalue(t,0,0); s=complex_free_buf(); - fsp->b=s.str; + fsp->b=MKPCHARP(s.str,0); fsp->len=s.len; - fsp->fi_free_string=fsp->b; + fsp->fi_free_string=s.str; break; } @@ -1004,7 +1076,7 @@ static string low_pike_sprintf(char *format, struct pike_string *s; DO_OP(); GET_STRING(s); - fsp->b=s->str; + fsp->b=MKPCHARP_STR(s); fsp->len=s->len; break; } @@ -1024,7 +1096,7 @@ static string low_pike_sprintf(char *format, tmp=1; for(max_len=nr=e=0;e<f->len;e++) { - if(f->b[e]=='\n') + if(INDEX_PCHARP(f->b,e)=='\n') { nr++; if(max_len<tmp) max_len=tmp; @@ -1048,18 +1120,17 @@ static string low_pike_sprintf(char *format, if((f[1].flags & MULTILINE) && !(f[0].flags & (MULTILINE|MULTI_LINE_BREAK))) { - if(! MEMCHR(f->b, '\n', f->len)) f->flags|=MULTI_LINE; + if(! MEMCHR_PCHARP(f->b, '\n', f->len).ptr ) f->flags|=MULTI_LINE; } } - init_buf_with_string(prefix); for(f=start+1;f<=fsp;) { - for(;f<=fsp && !(f->flags&MULTILINE);f++) do_one(f); + for(;f<=fsp && !(f->flags&MULTILINE);f++) do_one(r,f); do { d=0; - for(e=0;f+e<=fsp && (f[e].flags & MULTILINE);e++) d|=do_one(f+e); - if(d) my_putchar('\n'); + for(e=0;f+e<=fsp && (f[e].flags & MULTILINE);e++) d|=do_one(r,f+e); + if(d) string_builder_putchar(r,'\n'); }while(d); for(;f<=fsp && (f->flags&MULTILINE); f++); @@ -1075,10 +1146,10 @@ static string low_pike_sprintf(char *format, fsp->fi_free_string=0; fsp--; } - return complex_free_buf(); } -/* An C-callable pike_sprintf */ + +/* An C-callable pike_sprintf string pike_sprintf(char *format,struct svalue *argp,int num_arg) { string prefix; @@ -1089,15 +1160,15 @@ string pike_sprintf(char *format,struct svalue *argp,int num_arg) fsp=format_info_stack-1; return low_pike_sprintf(format,strlen(format),argp,num_arg,prefix,0); } + */ /* The efun */ void f_sprintf(INT32 num_arg) { + ONERROR tmp; struct pike_string *ret; struct svalue *argp; - string s; - s.str=0; - s.len=0; + struct string_builder r; argp=sp-num_arg; free_sprintf_strings(); @@ -1106,14 +1177,16 @@ void f_sprintf(INT32 num_arg) if(argp[0].type != T_STRING) error("Bad argument 1 to sprintf.\n"); - s=low_pike_sprintf(argp->u.string->str, - argp->u.string->len, - argp+1, - num_arg-1, - s, - 0); - ret=make_shared_binary_string(s.str, s.len); - free(s.str); + init_string_builder(&r,0); + SET_ONERROR(tmp, free_string_builder, &r); + low_pike_sprintf(&r, + MKPCHARP_STR(argp->u.string), + argp->u.string->len, + argp+1, + num_arg-1, + 0); + UNSET_ONERROR(tmp); + ret=finish_string_builder(&r); free_svalue(&temp_svalue); temp_svalue.type=T_INT; diff --git a/src/operators.c b/src/operators.c index ce21f31d9f..d8fc9aae74 100644 --- a/src/operators.c +++ b/src/operators.c @@ -5,7 +5,7 @@ \*/ #include "global.h" #include <math.h> -RCSID("$Id: operators.c,v 1.42 1998/10/12 22:55:10 hubbe Exp $"); +RCSID("$Id: operators.c,v 1.43 1998/10/14 05:48:45 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -25,6 +25,7 @@ RCSID("$Id: operators.c,v 1.42 1998/10/12 22:55:10 hubbe Exp $"); #include "object.h" #include "pike_types.h" #include "module_support.h" +#include "pike_macros.h" #define COMPARISON(ID,NAME,FUN) \ void ID(INT32 args) \ @@ -139,7 +140,7 @@ void f_add(INT32 args) case BIT_STRING: { struct pike_string *r; - char *buf; + PCHARP buf; INT32 tmp; int max_shift=0; @@ -156,11 +157,11 @@ void f_add(INT32 args) tmp=sp[-args].u.string->len; r=new_realloc_shared_string(sp[-args].u.string,size,max_shift); sp[-args].type=T_INT; - buf=r->str+(tmp<<max_shift); + buf=MKPCHARP_STR_OFF(r,tmp); for(e=-args+1;e<0;e++) { - pike_string_cpy(buf,max_shift,sp[e].u.string); - buf+=sp[e].u.string->len << max_shift; + pike_string_cpy(buf,sp[e].u.string); + INC_PCHARP(buf,sp[e].u.string->len); } sp[-args].u.string=end_shared_string(r); sp[-args].type=T_STRING; @@ -175,7 +176,7 @@ void f_add(INT32 args) case BIT_STRING | BIT_FLOAT | BIT_INT: { struct pike_string *r; - char *buf; + PCHARP buf; char buffer[50]; int max_shift=0; size=0; @@ -200,7 +201,7 @@ void f_add(INT32 args) } r=begin_wide_shared_string(size,max_shift); - buf=r->str; + buf=MKPCHARP_STR(r); size=0; for(e=-args;e<0;e++) @@ -208,8 +209,8 @@ void f_add(INT32 args) switch(sp[e].type) { case T_STRING: - pike_string_cpy(buf,max_shift,sp[e].u.string); - buf+=sp[e].u.string->len<<max_shift; + pike_string_cpy(buf,sp[e].u.string); + INC_PCHARP(buf,sp[e].u.string->len); break; case T_INT: @@ -221,14 +222,23 @@ void f_add(INT32 args) append_buffer: switch(max_shift) { - case 0: convert_0_to_0((p_wchar0 *)buf,buffer,strlen(buffer)); break; - case 1: convert_0_to_1((p_wchar1 *)buf,buffer,strlen(buffer)); break; - case 2: convert_0_to_2((p_wchar2 *)buf,buffer,strlen(buffer)); break; + case 0: + convert_0_to_0((p_wchar0 *)buf.ptr,buffer,strlen(buffer)); + break; + + case 1: + convert_0_to_1((p_wchar1 *)buf.ptr,buffer,strlen(buffer)); + break; + + case 2: + convert_0_to_2((p_wchar2 *)buf.ptr,buffer,strlen(buffer)); + break; + } - buf+=strlen(buffer)<<max_shift; + INC_PCHARP(buf,strlen(buffer)); } } - r->len=(buf-r->str)>>max_shift; + r->len=SUBTRACT_PCHARP(buf,MKPCHARP_STR(r)); low_set_index(r,r->len,0); r=end_shared_string(r); pop_n_elems(args); @@ -671,21 +681,37 @@ void o_and(void) push_array(a); return; } - case T_STRING: - { - struct pike_string *s; - INT32 len, i; - len = sp[-2].u.string->len; - if (len != sp[-1].u.string->len) - PIKE_ERROR("`&", "Bitwise AND on strings of different lengths.\n", sp, 2); - s = begin_shared_string(len); - for (i=0; i<len; i++) - s->str[i] = sp[-2].u.string->str[i] & sp[-1].u.string->str[i]; - pop_n_elems(2); - push_string(end_shared_string(s)); - return; - } +#define STRING_BITOP(OP,STROP) \ + case T_STRING: \ + { \ + struct pike_string *s; \ + INT32 len, i; \ + \ + len = sp[-2].u.string->len; \ + if (len != sp[-1].u.string->len) \ + PIKE_ERROR("`" #OP, "Bitwise "STROP \ + " on strings of different lengths.\n", sp, 2); \ + if(!sp[-2].u.string->size_shift && !sp[-1].u.string->size_shift) \ + { \ + s = begin_shared_string(len); \ + for (i=0; i<len; i++) \ + s->str[i] = sp[-2].u.string->str[i] OP sp[-1].u.string->str[i]; \ + }else{ \ + s = begin_wide_shared_string(len, \ + MAXIMUM(sp[-2].u.string->size_shift, \ + sp[-1].u.string->size_shift)); \ + for (i=0; i<len; i++) \ + low_set_index(s,i,index_shared_string(sp[-2].u.string,i) OP \ + index_shared_string(sp[-1].u.string,i)); \ + } \ + pop_n_elems(2); \ + push_string(end_shared_string(s)); \ + return; \ + } + + STRING_BITOP(&,"AND") + default: PIKE_ERROR("`&", "Bitwise and on illegal type.\n", sp, 2); } @@ -837,21 +863,7 @@ void o_or(void) return; } - case T_STRING: - { - struct pike_string *s; - INT32 len, i; - - len = sp[-2].u.string->len; - if (len != sp[-1].u.string->len) - PIKE_ERROR("`|", "Bitwise OR on strings of different lengths.\n", sp, 2); - s = begin_shared_string(len); - for (i=0; i<len; i++) - s->str[i] = sp[-2].u.string->str[i] | sp[-1].u.string->str[i]; - pop_n_elems(2); - push_string(end_shared_string(s)); - return; - } + STRING_BITOP(|,"OR") default: PIKE_ERROR("`|", "Bitwise or on illegal type.\n", sp, 2); @@ -941,21 +953,7 @@ void o_xor(void) return; } - case T_STRING: - { - struct pike_string *s; - INT32 len, i; - - len = sp[-2].u.string->len; - if (len != sp[-1].u.string->len) - PIKE_ERROR("`^", "Bitwise XOR on strings of different lengths.\n", sp, 2); - s = begin_shared_string(len); - for (i=0; i<len; i++) - s->str[i] = sp[-2].u.string->str[i] ^ sp[-1].u.string->str[i]; - pop_n_elems(2); - push_string(end_shared_string(s)); - return; - } + STRING_BITOP(^,"XOR") default: PIKE_ERROR("`^", "Bitwise XOR on illegal type.\n", sp, 2); @@ -1091,15 +1089,17 @@ void o_multiply(void) { struct pike_string *ret; char *pos; - INT32 e; + INT32 e,len; if(sp[-1].u.integer < 0) PIKE_ERROR("`*", "Cannot multiply string by negative number.\n", sp, 2); - ret=begin_shared_string(sp[-2].u.string->len * sp[-1].u.integer); + ret=begin_wide_shared_string(sp[-2].u.string->len * sp[-1].u.integer, + sp[-2].u.string->size_shift); pos=ret->str; - for(e=0;e<sp[-1].u.integer;e++,pos+=sp[-2].u.string->len) - MEMCPY(pos,sp[-2].u.string->str,sp[-2].u.string->len); + len=sp[-2].u.string->len << sp[-2].u.string->size_shift; + for(e=0;e<sp[-1].u.integer;e++,pos+=len) + MEMCPY(pos,sp[-2].u.string->str,len); pop_n_elems(2); - push_string(end_shared_string(ret)); + push_string(low_end_shared_string(ret)); return; } @@ -1201,8 +1201,7 @@ void o_divide(void) case TWO_TYPES(T_STRING,T_INT): { struct array *a; - char *pos=sp[-2].u.string->str; - INT32 size,e,len; + INT32 size,e,len,pos=0; len=sp[-1].u.integer; if(!len) @@ -1219,7 +1218,7 @@ void o_divide(void) a=allocate_array(size); for(e=0;e<size;e++) { - a->item[e].u.string=make_shared_binary_string(pos,len); + a->item[e].u.string=string_slice(sp[-2].u.string, pos,len); a->item[e].type=T_STRING; pos+=len; } @@ -1248,16 +1247,16 @@ void o_divide(void) for(last=sp[-2].u.string->len,e=0;e<size-1;e++) { pos=sp[-2].u.string->len - (INT32)((e+1)*len); - a->item[size-1-e].u.string=make_shared_binary_string( - sp[-2].u.string->str + pos, - last-pos); + a->item[size-1-e].u.string=string_slice(sp[-2].u.string, + pos, + last-pos); a->item[size-1-e].type=T_STRING; last=pos; } pos=0; - a->item[0].u.string=make_shared_binary_string( - sp[-2].u.string->str + pos, - last-pos); + a->item[0].u.string=string_slice(sp[-2].u.string, + pos, + last-pos); a->item[0].type=T_STRING; }else{ size=(INT32)ceil( ((double)sp[-2].u.string->len) / len); @@ -1266,16 +1265,16 @@ void o_divide(void) for(last=0,e=0;e<size-1;e++) { pos=(INT32)((e+1)*len); - a->item[e].u.string=make_shared_binary_string( - sp[-2].u.string->str + last, - pos-last); + a->item[e].u.string=string_slice(sp[-2].u.string, + last, + pos-last); a->item[e].type=T_STRING; last=pos; } pos=sp[-2].u.string->len; - a->item[e].u.string=make_shared_binary_string( - sp[-2].u.string->str + last, - pos-last); + a->item[e].u.string=string_slice(sp[-2].u.string, + last, + pos-last); a->item[e].type=T_STRING; } a->type_field=BIT_STRING; @@ -1489,7 +1488,7 @@ void o_mod(void) tmp=s->len % tmp; base=s->len - tmp; } - s=make_shared_binary_string(s->str + base, tmp); + s=string_slice(s, base, tmp); pop_n_elems(2); push_string(s); return; @@ -1649,6 +1648,9 @@ void o_compl(void) struct pike_string *s; INT32 len, i; + if(sp[-1].u.string->size_shift) + error("`~ cannot handle wide strings.\n"); + len = sp[-1].u.string->len; s = begin_shared_string(len); for (i=0; i<len; i++) diff --git a/src/pike_memory.c b/src/pike_memory.c index fd28c52ec8..896a5535f6 100644 --- a/src/pike_memory.c +++ b/src/pike_memory.c @@ -9,7 +9,7 @@ #include "pike_macros.h" #include "gc.h" -RCSID("$Id: pike_memory.c,v 1.26 1998/10/11 11:18:52 hubbe Exp $"); +RCSID("$Id: pike_memory.c,v 1.27 1998/10/14 05:48:46 hubbe Exp $"); /* strdup() is used by several modules, so let's provide it */ #ifndef HAVE_STRDUP @@ -561,7 +561,7 @@ void memfill(char *to, while(tolen>0) { tmp=MINIMUM(tolen, fromlen); - MEMCPY(to, from, MINIMUM(tolen, fromlen)); + MEMCPY(to, from, tmp); fromlen+=tmp; tolen-=tmp; to+=tmp; diff --git a/src/stralloc.c b/src/stralloc.c index a38128b8c0..e08d4ed995 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -15,7 +15,7 @@ #include <ctype.h> -RCSID("$Id: stralloc.c,v 1.42 1998/10/11 22:34:02 hubbe Exp $"); +RCSID("$Id: stralloc.c,v 1.43 1998/10/14 05:48:46 hubbe Exp $"); #define BEGIN_HASH_SIZE 997 #define MAX_AVG_LINK_LENGTH 3 @@ -164,49 +164,48 @@ int generic_compare_strings(const void *a,int alen, int asize, } -void generic_memcpy(void *to, int to_shift, - void *from, int from_shift, +void generic_memcpy(PCHARP to, + PCHARP from, int len) { - switch(TWO_SIZES(from_shift,to_shift)) + switch(TWO_SIZES(from.shift,to.shift)) { case TWO_SIZES(0,0): - convert_0_to_0((p_wchar0 *)to,(p_wchar0 *)from,len); + convert_0_to_0((p_wchar0 *)to.ptr,(p_wchar0 *)from.ptr,len); break; case TWO_SIZES(0,1): - convert_0_to_1((p_wchar1 *)to,(p_wchar0 *)from,len); + convert_0_to_1((p_wchar1 *)to.ptr,(p_wchar0 *)from.ptr,len); break; case TWO_SIZES(0,2): - convert_0_to_2((p_wchar2 *)to,(p_wchar0 *)from,len); + convert_0_to_2((p_wchar2 *)to.ptr,(p_wchar0 *)from.ptr,len); break; case TWO_SIZES(1,0): - convert_1_to_0((p_wchar0 *)to,(p_wchar1 *)from,len); + convert_1_to_0((p_wchar0 *)to.ptr,(p_wchar1 *)from.ptr,len); break; case TWO_SIZES(1,1): - convert_1_to_1((p_wchar1 *)to,(p_wchar1 *)from,len); + convert_1_to_1((p_wchar1 *)to.ptr,(p_wchar1 *)from.ptr,len); break; case TWO_SIZES(1,2): - convert_1_to_2((p_wchar2 *)to,(p_wchar1 *)from,len); + convert_1_to_2((p_wchar2 *)to.ptr,(p_wchar1 *)from.ptr,len); break; case TWO_SIZES(2,0): - convert_2_to_0((p_wchar0 *)to,(p_wchar2 *)from,len); + convert_2_to_0((p_wchar0 *)to.ptr,(p_wchar2 *)from.ptr,len); break; case TWO_SIZES(2,1): - convert_2_to_1((p_wchar1 *)to,(p_wchar2 *)from,len); + convert_2_to_1((p_wchar1 *)to.ptr,(p_wchar2 *)from.ptr,len); break; case TWO_SIZES(2,2): - convert_2_to_2((p_wchar2 *)to,(p_wchar2 *)from,len); + convert_2_to_2((p_wchar2 *)to.ptr,(p_wchar2 *)from.ptr,len); break; } } -INLINE void pike_string_cpy(void *to, - int to_shift, - struct pike_string *from) +INLINE void pike_string_cpy(PCHARP to, + struct pike_string *from) { - generic_memcpy(to,to_shift,from->str,from->size_shift,from->len); + generic_memcpy(to,MKPCHARP_STR(from),from->len); } static void locate_problem(int (*isproblem)(struct pike_string *)) @@ -1028,7 +1027,7 @@ struct pike_string *new_realloc_shared_string(struct pike_string *a, INT32 size, if(shift == a->size_shift) return realloc_shared_string(a,size); r=begin_wide_shared_string(size,shift); - pike_string_cpy(r->str,shift,a); + pike_string_cpy(MKPCHARP_STR(r),a); free_string(a); return r; } @@ -1181,11 +1180,14 @@ struct pike_string *add_shared_strings(struct pike_string *a, struct pike_string *b) { struct pike_string *ret; + PCHARP tmp; int target_size=MAXIMUM(a->size_shift,b->size_shift); ret=begin_wide_shared_string(a->len+b->len,target_size); - pike_string_cpy(ret->str,ret->size_shift,a); - pike_string_cpy(ret->str+(a->len<<target_size),ret->size_shift,b); + tmp=MKPCHARP_STR(ret); + pike_string_cpy(tmp,a); + INC_PCHARP(tmp,a->len); + pike_string_cpy(tmp,b); return end_shared_string(ret); } @@ -1222,13 +1224,13 @@ int string_search(struct pike_string *haystack, needle->str, needle->len, needle->size_shift, - haystack->len, + haystack->len-start, haystack->size_shift); r=(char *)generic_memory_search(&s, - haystack->str, - haystack->len, + haystack->str+(start<<haystack->size_shift), + haystack->len-start, haystack->size_shift); if(!r) return -1; @@ -1274,7 +1276,8 @@ struct pike_string *string_replace(struct pike_string *str, struct pike_string *to) { struct pike_string *ret; - char *s,*tmp,*r,*end; + char *s,*tmp,*end; + PCHARP r; int shift; struct generic_mem_searcher searcher; @@ -1288,14 +1291,12 @@ struct pike_string *string_replace(struct pike_string *str, if(!del->len) { - int e; - int pos; + int e,pos; ret=begin_wide_shared_string(str->len + to->len * (str->len -1),shift); low_set_index(ret,0,index_shared_string(str,0)); - pos=1; - for(e=1;e<str->len;e++) + for(pos=e=1;e<str->len;e++) { - pike_string_cpy(ret->str+(pos<<shift),shift,to); + pike_string_cpy(MKPCHARP_STR_OFF(ret,pos),to); pos+=to->len; low_set_index(ret,pos++,index_shared_string(str,e)); } @@ -1341,20 +1342,20 @@ struct pike_string *string_replace(struct pike_string *str, ret=begin_wide_shared_string(str->len + (to->len-del->len)*delimeters, shift); } s=str->str; - r=ret->str; + r=MKPCHARP_STR(ret); while((tmp=(char *)generic_memory_search(&searcher, s, (end-s)>>str->size_shift, str->size_shift))) { - generic_memcpy(r,shift,s,str->size_shift,(tmp-s)>>str->size_shift); - r+=tmp-s; - pike_string_cpy(r,shift,to); - r+=to->len << shift; + generic_memcpy(r,MKPCHARP(s,str->size_shift),(tmp-s)>>str->size_shift); + INC_PCHARP(r,(tmp-s)>>str->size_shift); + pike_string_cpy(r,to); + INC_PCHARP(r,to->len); s=tmp+(del->len << str->size_shift); } - generic_memcpy(r,shift,s,str->size_shift,(end-s)>>str->size_shift); + generic_memcpy(r,MKPCHARP(s,str->size_shift),(end-s)>>str->size_shift); return end_shared_string(ret); } @@ -1468,7 +1469,7 @@ static void string_build_mkspace(struct string_builder *s, int chars, int mag) struct pike_string *n; int l=s->s->len+chars+s->malloced; n=begin_wide_shared_string(l,mag); - pike_string_cpy(n->str,mag,s->s); + pike_string_cpy(MKPCHARP_STR(n),s->s); n->len=s->s->len; s->malloced=l; free((char *)s->s); @@ -1509,7 +1510,7 @@ void string_builder_putchar(struct string_builder *s, int ch) void string_builder_binary_strcat(struct string_builder *s, char *str, INT32 len) { - string_build_mkspace(s,len,1); + string_build_mkspace(s,len,0); switch(s->s->size_shift) { case 0: convert_0_to_0(STR0(s->s)+s->s->len,str,len); break; @@ -1522,6 +1523,69 @@ void string_builder_binary_strcat(struct string_builder *s, char *str, INT32 len } +void string_builder_append(struct string_builder *s, + PCHARP from, + INT32 len) +{ + string_build_mkspace(s,len,from.shift); + generic_memcpy(MKPCHARP_STR_OFF(s->s,s->s->len), from, len); + s->s->len+=len; +} + +void string_builder_fill(struct string_builder *s, + int howmany, + PCHARP from, + INT32 len, + INT32 offset) +{ + INT32 tmp; +#ifdef DEBUG + if(len<=0) + fatal("Cannot fill with zero length strings!\n"); +#endif + if(howmany<=0) return; + + if(!s->s->size_shift && + len == 1 && + (!from.shift || !min_magnitude(EXTRACT_PCHARP(from)))) + { + MEMSET(string_builder_allocate(s,howmany,0), + EXTRACT_PCHARP(from), + howmany); + return; + } + + string_build_mkspace(s,howmany,from.shift); + tmp=MINIMUM(howmany, len - offset); + + generic_memcpy(MKPCHARP_STR_OFF(s->s,s->s->len), + ADD_PCHARP(from,offset), + tmp); + s->s->len+=tmp; + howmany-=tmp; + if(howmany > 0) + { + void *new_from; + PCHARP to; + tmp=MINIMUM(howmany, len); + to=MKPCHARP_STR_OFF(s->s,s->s->len); + generic_memcpy(to,from, tmp); + s->s->len+=tmp; + howmany-=tmp; + + while(howmany > 0) + { + tmp=MINIMUM(len, howmany); + MEMCPY(s->s->str + (s->s->len << s->s->size_shift), + to.ptr, + tmp << s->s->size_shift); + len+=tmp; + howmany-=tmp; + s->s->len+=tmp; + } + } +} + void string_builder_strcat(struct string_builder *s, char *str) { string_builder_binary_strcat(s,str,strlen(str)); @@ -1531,9 +1595,7 @@ void string_builder_shared_strcat(struct string_builder *s, struct pike_string * { string_build_mkspace(s,str->len,s->s->size_shift); - pike_string_cpy(s->s->str + (s->s->len << s->s->size_shift), - s->s->size_shift, - str); + pike_string_cpy(MKPCHARP_STR_OFF(s->s,s->s->len), str); s->known_shift=MAXIMUM(s->known_shift,str->size_shift); s->s->len+=str->len; } @@ -1545,6 +1607,11 @@ void reset_string_builder(struct string_builder *s) s->s->len=0; } +void free_string_builder(struct string_builder *s) +{ + free((char *)s->s); +} + struct pike_string *finish_string_builder(struct string_builder *s) { low_set_index(s->s,s->s->len,0); @@ -1553,3 +1620,73 @@ struct pike_string *finish_string_builder(struct string_builder *s) return end_shared_string(s->s); } +PCHARP MEMCHR_PCHARP(PCHARP ptr, int chr, int len) +{ + switch(ptr.shift) + { + case 0: return MKPCHARP(MEMCHR0(ptr.ptr,chr,len),0); + case 1: return MKPCHARP(MEMCHR1(ptr.ptr,chr,len),1); + case 2: return MKPCHARP(MEMCHR2(ptr.ptr,chr,len),2); + default: + fatal("Illegal shift in MEMCHR_PCHARP.\n"); + } +} + +#define DIGIT(x) (isdigit(x) ? (x) - '0' : \ + islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') +#define MBASE ('z' - 'a' + 1 + 10) + +long STRTOL_PCHARP(PCHARP str, PCHARP *ptr, int base) +{ + register long val; + register int c; + int xx, neg = 0; + + if (ptr) *ptr = str; + if (base < 0 || base > MBASE) return 0; + if (!isalnum(c = EXTRACT_PCHARP(str))) + { + while (ISSPACE(c)) + { + INC_PCHARP(str,1); + c=EXTRACT_PCHARP(str); + } + switch (c) + { + case '-': + neg++; + case '+': /* fall-through */ + INC_PCHARP(str,1); + c=EXTRACT_PCHARP(str); + } + } + + if (!base) + { + if (c != '0') + base = 10; + else if (INDEX_PCHARP(str,1) == 'x' || INDEX_PCHARP(str,1) == 'X') + base = 16; + else + base = 8; + } + + if (!isalnum(c) || (xx = DIGIT(c)) >= base) + return 0; /* no number formed */ + if (base == 16 && c == '0' && isxdigit(INDEX_PCHARP(str,2)) && + (INDEX_PCHARP(str,1) == 'x' || INDEX_PCHARP(str,1) == 'X')) + { + INC_PCHARP(str,2); + c = EXTRACT_PCHARP(str); /* skip over leading "0x" or "0X" */ + } + val=-DIGIT(c); + while(1) + { + INC_PCHARP(str,1); + c=EXTRACT_PCHARP(str); + if(!(isalnum(c) && (xx=DIGIT(c)) < base)) break; + val = base * val - xx; + } + if (ptr) *ptr = str; + return (neg ? val : -val); +} diff --git a/src/stralloc.h b/src/stralloc.h index a410faabcb..d2de73691d 100644 --- a/src/stralloc.h +++ b/src/stralloc.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: stralloc.h,v 1.20 1998/10/11 22:34:02 hubbe Exp $ + * $Id: stralloc.h,v 1.21 1998/10/14 05:48:46 hubbe Exp $ */ #ifndef STRALLOC_H #define STRALLOC_H @@ -53,6 +53,52 @@ struct pike_string *debug_findstring(const struct pike_string *foo); #define STR2(X) ((p_wchar2 *)(X)->str) #endif +#define INDEX_CHARP(PTR,IND,SHIFT) \ + ((SHIFT)==0?((p_wchar0 *)(PTR))[(IND)]:(SHIFT)==1?((p_wchar1 *)(PTR))[(IND)]:((p_wchar2 *)(PTR))[(IND)]) + +#define SET_INDEX_CHARP(PTR,IND,SHIFT,VAL) \ + ((SHIFT)==0?((p_wchar0 *)(PTR))[(IND)]=(VAL):(SHIFT)==1?((p_wchar1 *)(PTR))[(IND)]=(VAL):((p_wchar2 *)(PTR))[(IND)]=(VAL)) + + +#define EXTRACT_CHARP(PTR,SHIFT) INDEX_CHARP((PTR),0,(SHIFT)) +#define CHARP_ADD(PTR,X,SHIFT) (PTR)+=(X)<<(SHIFT) + +typedef struct p_wchar_p +{ + void *ptr; + int shift; +} PCHARP; + +#define INDEX_PCHARP(X,Y) INDEX_CHARP((X).ptr,(Y),(X).shift) +#define SET_INDEX_PCHARP(X,Y,Z) INDEX_CHARP((X).ptr,(Y),(X).shift,(Z)) +#define EXTRACT_PCHARP(X) INDEX_CHARP((X).ptr,(0),(X).shift) +#define INC_PCHARP(X,Y) (((char *)(X).ptr)+=(Y) << (X).shift) + +#define LOW_COMPARE_PCHARP(X,CMP,Y) (((char *)((X).ptr)) CMP ((char *)((Y).ptr))) +#define LOW_SUBTRACT_PCHARP(X,Y) LOW_COMPARE_PCHARP((X),-,(Y)) + +#ifdef DEBUG +#define SUBTRACT_PCHARP(X,Y) ((X).shift!=(Y).shift?(fatal("Subtracting different size charp!\n")),0:LOW_SUBTRACT_PCHARP((X),(Y))) +#define COMPARE_PCHARP(X,CMP,Y) ((X).shift!=(Y).shift?(fatal("Subtracting different size charp!\n")),0:LOW_COMPARE_PCHARP((X),CMP,(Y))) +#else +#define SUBTRACT_PCHARP(X,Y) LOW_SUBTRACT_PCHARP((X),(Y)) +#define COMPARE_PCHARP(X,CMP,Y) LOW_COMPARE_PCHARP((X),CMP,(Y)) +#endif + +static INLINE PCHARP MKPCHARP(void *ptr, int shift) +{ + PCHARP tmp; + tmp.ptr=ptr; + tmp.shift=shift; + return tmp; +} + +#define MKPCHARP_OFF(PTR,SHIFT,OFF) MKPCHARP( ((char *)(PTR)) + ((OFF)<<(SHIFT)), (SHIFT)) +#define MKPCHARP_STR(STR) MKPCHARP((STR)->str, (STR)->size_shift) +#define MKPCHARP_STR_OFF(STR,OFF) \ + MKPCHARP((STR)->str + ((OFF)<<(STR)->size_shift), (STR)->size_shift) +#define ADD_PCHARP(PTR,I) MKPCHARP_OFF((PTR).ptr,(PTR).shift,(I)) + #ifdef DEBUG_MALLOC #define reference_shared_string(s) do { struct pike_string *S_=(s); debug_malloc_touch(S_); S_->refs++; }while(0) #define copy_shared_string(to,s) do { struct pike_string *S_=(to)=(s); debug_malloc_touch(S_); S_->refs++; }while(0) @@ -120,12 +166,11 @@ CONVERT(2,1) int generic_compare_strings(const void *a,int alen, int asize, const void *b,int blen, int bsize); -void generic_memcpy(void *to, int to_shift, - void *from, int from_shift, +void generic_memcpy(PCHARP to, + PCHARP from, int len); -INLINE void pike_string_cpy(void *to, - int to_shift, - struct pike_string *from); +INLINE void pike_string_cpy(PCHARP to, + struct pike_string *from); struct pike_string *binary_findstring(const char *foo, INT32 l); struct pike_string *findstring(const char *foo); struct pike_string *debug_begin_shared_string(int len); @@ -180,10 +225,21 @@ void gc_mark_all_strings(void); void init_string_builder(struct string_builder *s, int mag); void string_builder_putchar(struct string_builder *s, int ch); void string_builder_binary_strcat(struct string_builder *s, char *str, INT32 len); +void string_builder_append(struct string_builder *s, + PCHARP from, + INT32 len); +void string_builder_fill(struct string_builder *s, + int howmany, + PCHARP from, + INT32 len, + INT32 offset); void string_builder_strcat(struct string_builder *s, char *str); void string_builder_shared_strcat(struct string_builder *s, struct pike_string *str); void reset_string_builder(struct string_builder *s); +void free_string_builder(struct string_builder *s); struct pike_string *finish_string_builder(struct string_builder *s); +PCHARP MEMCHR_PCHARP(PCHARP ptr, int chr, int len); +long STRTOL_PCHARP(PCHARP str, PCHARP *ptr, int base); /* Prototypes end here */ #ifdef DEBUG_MALLOC diff --git a/src/testsuite.in b/src/testsuite.in index a9a1eff9a5..27e6e04a22 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -stest_true([["$Id: testsuite.in,v 1.125 1998/10/12 22:57:13 hubbe Exp $"]]) +stest_true([["$Id: testsuite.in,v 1.126 1998/10/14 05:48:47 hubbe Exp $"]]) cond([[all_constants()->_verify_internals]], [[ test_do(_verify_internals()) @@ -1059,6 +1059,7 @@ test_eq(10-3.0,7.0) test_eq(3-10.0,-7.0) test_eq(10.0-3,7.0) test_eq(3.0-10,-7.0) +test_eq(034567 - 10000,4711) test_eq("foobargazonk"-"o","fbargaznk") test_equal(({"foo","bar","gazonk"})-({"foo","gazonk"}),({"bar"})) test_equal(({"c","foo","bar","gazonk","a","b",})-({"foo","gazonk"}),({"c","bar","a","b"})) @@ -1084,9 +1085,20 @@ test_eq(2*2.0*2.0*2.0*2.0,32.0) test_eq(3.0*4,12.0) test_eq(4.0*3,12.0) test_eq(2.0*2*2.0*2*2.0,32.0) + test_eq(({"foo","bar","gazonk"})*"-","foo-bar-gazonk") test_eq(({"f\777\777","bar","gaz\777nk"})*"-","f\777\777-bar-gaz\777nk") test_eq(({"f\7777777\7777777","bar","gaz\7777777nk"})*"-","f\7777777\7777777-bar-gaz\7777777nk") + +test_eq(({"foo","bar","gazonk"})*"\777","foo\777bar\777gazonk") +test_eq(({"f\777\777","bar","gaz\777nk"})*"\777","f\777\777\777bar\777gaz\777nk") +test_eq(({"f\7777777\7777777","bar","gaz\7777777nk"})*"\777","f\7777777\7777777\777bar\777gaz\7777777nk") + +test_eq(({"foo","bar","gazonk"})*"\7777777","foo\7777777bar\7777777gazonk") +test_eq(({"f\777\777","bar","gaz\777nk"})*"\7777777","f\777\777\7777777bar\7777777gaz\777nk") +test_eq(({"f\7777777\7777777","bar","gaz\7777777nk"})*"\7777777","f\7777777\7777777\7777777bar\7777777gaz\7777777nk") + + test_equal( ({ ({1}), ({2}), ({3}) })*({8}), ({1,8,2,8,3})) test_equal( ({ 1 })*3, ({1,1,1}) ) test_equal( "foo"*3, "foofoofoo" ) @@ -1132,6 +1144,30 @@ test_equal("foobargazonk"/5.0,({"fooba","rgazo","nk"})) test_equal("foobargazonk"/-5.0,({"fo","obarg","azonk"})) test_equal("foobargazonk"/2.5,({"fo","oba","rg","azo","nk"})) +test_equal("f\777\777bargaz\777nk"/1,"f\777\777bargaz\777nk"/"") +test_equal("f\777\777bargaz\777nk"/2,({"f\777","\777b","ar","ga","z\777","nk"})) +test_equal("f\777\777bargaz\777nk"/3,({"f\777\777","bar","gaz","\777nk"})) +test_equal("f\777\777bargaz\777nk"/4,({"f\777\777b","arga","z\777nk"})) +test_equal("f\777\777bargaz\777nk"/5,({"f\777\777ba","rgaz\777"})) +test_equal("f\777\777bargaz\777nk"/-6,({"f\777\777bar","gaz\777nk"})) +test_equal("f\777\777bargaz\777nk"/-7,({"rgaz\777nk"})) + +test_equal("f\777\777bargaz\777nk"/5.0,({"f\777\777ba","rgaz\777","nk"})) +test_equal("f\777\777bargaz\777nk"/-5.0,({"f\777","\777barg","az\777nk"})) +test_equal("f\777\777bargaz\777nk"/2.5,({"f\777","\777ba","rg","az\777","nk"})) + +test_equal("f\7777777\7777777bargaz\7777777nk"/1,"f\7777777\7777777bargaz\7777777nk"/"") +test_equal("f\7777777\7777777bargaz\7777777nk"/2,({"f\7777777","\7777777b","ar","ga","z\7777777","nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/3,({"f\7777777\7777777","bar","gaz","\7777777nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/4,({"f\7777777\7777777b","arga","z\7777777nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/5,({"f\7777777\7777777ba","rgaz\7777777"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/-6,({"f\7777777\7777777bar","gaz\7777777nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/-7,({"rgaz\7777777nk"})) + +test_equal("f\7777777\7777777bargaz\7777777nk"/5.0,({"f\7777777\7777777ba","rgaz\7777777","nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/-5.0,({"f\7777777","\7777777barg","az\7777777nk"})) +test_equal("f\7777777\7777777bargaz\7777777nk"/2.5,({"f\7777777","\7777777ba","rg","az\7777777","nk"})) + test_equal(({1,2,3})/1,({ ({1}), ({2}), ({3}) })) test_equal(({1,2,3})/2,({ ({1,2}) })) test_equal(({1,2,3})/-2,({ ({2,3}) })) @@ -1168,6 +1204,10 @@ test_eval_error(return 15.0 % 0.0) test_eq("foobargazonk"%5,"nk") test_eq("foobargazonk"%-5,"fo") +test_eq("f\777\777bargaz\777nk"%5,"nk") +test_eq("f\777\777bargaz\777nk"%-5,"f\777") +test_eq("f\7777777\7777777bargaz\7777777nk"%5,"nk") +test_eq("f\7777777\7777777bargaz\7777777nk"%-5,"f\7777777") test_equal(({1,2,3})%2,({3})) test_equal(({1,2,3})%-2,({1})) @@ -2266,6 +2306,8 @@ test_equal(replace(([1:2,3:4,5:1,2:3]),3,-1),([1:2,3:4,5:1,2:-1])) // - reverse test_eq(reverse("reverse"),"esrever") +test_eq(reverse("r\777v\777rs\777"),"\777sr\777v\777r") +test_eq(reverse("r\7777777v\7777777rs\7777777"),"\7777777sr\7777777v\7777777r") test_eq(reverse(""),"") test_eq(reverse("a"),"a") test_equal(reverse(({1,5,9})),({9,5,1})) @@ -2301,6 +2343,7 @@ test_eq(search(([1:2,3:4,5:6,7:8]),8),7) // test large searches (find string, size, pattern) define(test_search,[[ +test_eq(sprintf($1+"%'"+$3+"'*n",$2)[..strlen($1)-1],$1) test_eq(search(sprintf($1+"%'"+$3+"'*n",$2),$1),0) test_eq(search(sprintf("%'"+$3+"'*n" ,$2),$1),-1) test_eq(search(sprintf("%'"+$3+"'*n"+$1,$2),$1),$2) @@ -2337,10 +2380,10 @@ test_search4("\345-------------------") test_search4(sprintf("%'argel-bargel glop-glyf?'2000n")) dnl these can be uncommented when sprintf handles wide strings -dnl test_search4("\34567-------------------") -dnl test_search4("\345677777-------------------") -dnl test_search4("kapit\3333l>") -dnl test_search4("kapit\3333333l>") +test_search4("\34567-------------------") +test_search4("\345677777-------------------") +test_search4("kapit\3333l>") +test_search4("kapit\3333333l>") // - sizeof -- GitLab