/* * $Id: string.c,v 1.5 2000/08/10 21:02:51 danny Exp $ * * Copyright © 1990, 1992, 1993 Free Software Foundation, Inc. * * This file is part of Oleo, the GNU Spreadsheet. * * Oleo is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * Oleo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Oleo; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef WITH_DMALLOC #include #endif #include #include "funcdef.h" #define obstack_chunk_alloc ck_malloc #define obstack_chunk_free free #include "obstack.h" #include "sysdef.h" #include "global.h" #include "cell.h" #include "eval.h" #include "errors.h" struct value { int type; union vals x; }; #define Float x.c_d #define String x.c_s #define Int x.c_l #define Value x.c_i #define Rng x.c_r #define ERROR(x) \ { \ p->Value=x; \ p->type=TYP_ERR;\ return; \ } extern struct obstack tmp_mem; extern char *flt_to_str(); static void do_edit (numarg,p) int numarg; struct value * p; { int mm; int add_len; int tmp_len; char *ptr1,*ptr2,*retp; int off1,off2; if(numarg<3) ERROR(BAD_INPUT); for(mm=3,add_len=0;mmString); tmp_len=strlen(p->String); off1=(p+1)->Int; off2=(p+2)->Int; if(off1==0 || tmp_len < ((off1<0) ? -off1 : off1) || off2==0 || tmp_len < ((off2<0) ? -off2 : off2)) ERROR(OUT_OF_RANGE); ptr1=p->String + (off1>0 ? off1-1 : tmp_len+off1); ptr2=p->String + 1 + (off2>0 ? off2-1 : tmp_len+off2); if(ptr1>ptr2) ERROR(OUT_OF_RANGE); retp=obstack_alloc(&tmp_mem,add_len+tmp_len-(ptr2-ptr1)); strncpy(retp,p->String,ptr1-p->String); retp[ptr1-p->String]='\0'; for(mm=3;mmString); strcat(retp,ptr2); p->String=retp; p->type=TYP_STR; } static void do_repeat (p) struct value * p; { char *str = (p )->String; long num = (p+1)->Int; char *ret; char *strptr; int len; if(num<0) ERROR(OUT_OF_RANGE); len=strlen(str); ret=strptr=obstack_alloc(&tmp_mem,len*num+1); while(num--) { if (len) bcopy(str,strptr,len); strptr+=len; } *strptr=0; p->String=ret; } static void do_len (p) struct value * p; { long ret; char *ptr; for(ret=0,ptr=p->String;*ptr;ret++,ptr++) ; p->Int=ret; p->type=TYP_INT; } static void do_up_str (p) struct value * p; { char *s1,*s2; char *strptr; strptr=obstack_alloc(&tmp_mem,strlen(p->String)+1); for(s1=strptr,s2=p->String;*s2;s2++) *s1++ = (islower(*s2) ? toupper(*s2) : *s2); *s1=0; p->String=strptr; } static void do_dn_str (p) struct value * p; { char *s1,*s2; char *strptr; strptr=obstack_alloc(&tmp_mem,strlen(p->String)+1); for(s1=strptr,s2=p->String;*s2;s2++) *s1++ = (isupper(*s2) ? tolower(*s2) : *s2); *s1=0; p->String=strptr; } static void do_cp_str (p) struct value * p; { char *strptr; char *s1,*s2; int wstart=1; strptr=obstack_alloc(&tmp_mem,strlen(p->String)+1); for(s1=strptr,s2=p->String;*s2;s2++) { if(!isalpha(*s2)) { wstart=1; *s1++= *s2; } else if(wstart) { *s1++ = (islower(*s2) ? toupper(*s2) : *s2); wstart=0; } else *s1++ = (isupper(*s2) ? tolower(*s2) : *s2); } *s1=0; p->String=strptr; } static void do_trim_str (p) struct value * p; { char *s1,*s2; int sstart=0; char *strptr; strptr=obstack_alloc(&tmp_mem,strlen(p->String)+1); for(s1=strptr,s2=p->String;*s2;s2++) { if(!isascii(*s2) || !isprint(*s2)) continue; if(*s2==' ') { if(sstart) { *s1++= *s2; sstart=0; } } else { sstart=1; *s1++= *s2; } } *s1=0; p->String=strptr; } static void do_concat ( numarg,p) int numarg; struct value * p; { int cur_string; char *s; char buf[40]; CELLREF crow,ccol; CELL *cell_ptr; for(cur_string=0;cur_stringcell_str,strlen(cell_ptr->cell_str)); break; case TYP_INT: sprintf(buf,"%ld",cell_ptr->cell_int); (void)obstack_grow(&tmp_mem,buf,strlen(buf)); break; case TYP_FLT: s=flt_to_str(cell_ptr->cell_flt); (void)obstack_grow(&tmp_mem,s,strlen(s)); break; default: (void)obstack_finish(&tmp_mem); ERROR(NON_STRING); } } break; case TYP_STR: s=p[cur_string].String; (void)obstack_grow(&tmp_mem,s,strlen(s)); break; case TYP_INT: sprintf(buf,"%ld",p[cur_string].Int); (void)obstack_grow(&tmp_mem,buf,strlen(buf)); break; case TYP_FLT: s=flt_to_str(p[cur_string].Float); (void)obstack_grow(&tmp_mem,s,strlen(s)); break; default: (void)obstack_finish(&tmp_mem); ERROR(NON_STRING); } } (void)obstack_1grow(&tmp_mem,0); p->type=TYP_STR; p->String=(char *)obstack_finish(&tmp_mem); } static void do_mid (p) struct value * p; { char *str = (p )->String; long from = (p+1)->Int-1; long len = (p+2)->Int; char *ptr1; int tmp; tmp=strlen(str); if(from<0 || len<0) ERROR(OUT_OF_RANGE); ptr1=(char *)obstack_alloc(&tmp_mem,len+1); if(from>=tmp || len==0) ptr1[0]='\0'; else { strncpy(ptr1,str+from,len); ptr1[len]='\0'; } p->String=ptr1; } static void do_substr (p) struct value * p; { long off1 = (p )->Int; long off2 = (p+1)->Int; char *str = (p+2)->String; char *ptr1, *ptr2; int tmp; char *ret; tmp=strlen(str); if(off1==0 || tmp < ((off1<0) ? -off1 : off1) || off2==0 || tmp < ((off2<0) ? -off2 : off2)) ERROR(OUT_OF_RANGE); ptr1=str + (off1>0 ? off1-1 : tmp+(off1)); ptr2=str + (off2>0 ? off2-1 : tmp+(off2)); if(ptr1>ptr2) ERROR(OUT_OF_RANGE); tmp=(ptr2-ptr1)+1; ret=(char *)obstack_alloc(&tmp_mem,tmp+1); strncpy(ret,ptr1,tmp); ret[tmp]=0; p->String=ret; p->type=TYP_STR; } static void do_strstr (p) struct value * p; { char *strptr = (p )->String; char *str1 = (p+1)->String; long off = (p+2)->Int; char *ret; if(off<1 || strlen(strptr)<=off-1) ERROR(OUT_OF_RANGE); ret=(char *)strstr(strptr+off-1,str1); p->Value= ret ? 1 + ret-strptr : 0; p->type=TYP_INT; } struct function string_funs[] = { { C_FN1, X_A1, "S", do_len, "len" }, /* 1 */ { C_FN3, X_A3, "SSI", do_strstr, "find" }, /* 2 */ { C_FN1, X_A1, "S", do_up_str, "strupr" }, /* 3 */ { C_FN1, X_A1, "S", do_dn_str, "strlwr" }, /* 4 */ { C_FN1, X_A1, "S", do_cp_str, "strcap" }, /* 5 */ { C_FN1, X_A1, "S", do_trim_str, "trim" }, /* 6 */ { C_FN3, X_A3, "IIS", do_substr, "substr" }, /* 7 */ { C_FN3, X_A3, "SII", do_mid, "mid" }, /* 8 */ { C_FN2, X_A2, "SI", do_repeat, "repeat" }, /* 9 */ { C_FNN, X_AN, "EEEE", do_concat, "concat" }, /* 10 */ { C_FNN, X_AN, "SIIS", do_edit, "edit" }, /* 11 */ { 0, 0, {0}, 0, 0 } }; int init_string_function_count(void) { return sizeof(string_funs) / sizeof(struct function) - 1; }