/* #includes */ /*{{{C}}}*//*{{{*/ #ifndef NO_POSIX_SOURCE #undef _POSIX_SOURCE #define _POSIX_SOURCE 1 #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 2 #endif #ifdef DMALLOC #include "dmalloc.h" #endif #include #include #include #include #include #include #include "eval.h" #include "main.h" #include "sheet.h" #include "sc.h" /*}}}*/ static const char *s2t_s; static char *s2t_t; static int s2t_term(Sheet *sheet); /* s2t_loc */ /*{{{*/ static int s2t_loc(Sheet *sheet, const char **s, char **t) { int x,y; char label[10],*l; l=label; if (**s>='A' && **s<='Z') { *l++=**s; *(*t)++=**s; x=*(*s)++-'A'; } else return 0; if (**s>='A' && **s<='Z') { *l++=**s; *(*t)++=**s; x=x*26+(*(*s)++-'A'); } if (**s>='0' && **s<='9') { *l++=**s; y=**s-'0'; *(*t)++=*(*s)++; } else return 0; while (**s>='0' && **s<='9') { *l++=**s; y=y*10+(**s-'0'); *(*t)++=*(*s)++; } *l='\0'; if (*getlabel(sheet,x,y,0)=='\0') setlabel(sheet,x,y,0,label,0); return 1; } /*}}}*/ /* s2t_range */ /*{{{*/ static int s2t_range(Sheet *sheet) { if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0; if (*s2t_s==':') { s2t_s++; *s2t_t++=','; if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0; return 1; } else return 0; } /*}}}*/ /* s2t_primary */ /*{{{*/ static int s2t_primary(Sheet *sheet) { if (*s2t_s=='@') /* @function */ /*{{{*/ { ++s2t_s; if (strncmp(s2t_s,"sum(",4)==0) /* @sum(range) -> sum(range) */ /*{{{*/ { s2t_s+=4; *s2t_t++='s'; *s2t_t++='u'; *s2t_t++='m'; *s2t_t++='('; if (s2t_range(sheet)==0) return 0; *s2t_t++=')'; return 1; } /*}}}*/ else if (strncmp(s2t_s,"rnd(",4)==0) /* @rnd(e) -> int(e,-1,1) */ /*{{{*/ { s2t_s+=4; *s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='('; if (s2t_term(sheet)==0) return 0; *s2t_t++=','; *s2t_t++='-'; *s2t_t++='1'; *s2t_t++=','; *s2t_t++='1'; *s2t_t++=')'; return 1; } /*}}}*/ else if (strncmp(s2t_s,"floor(",6)==0) /* @floor(e) -> int(e,-2,-2) */ /*{{{*/ { s2t_s+=6; *s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='('; if (s2t_term(sheet)==0) return 0; *s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='-'; *s2t_t++='2'; *s2t_t++=')'; return 1; } /*}}}*/ else if (strncmp(s2t_s,"ceil(",5)==0) /* @ceil(e) -> int(e,2,2) */ /*{{{*/ { s2t_s+=5; *s2t_t++='i'; *s2t_t++='n'; *s2t_t++='t'; *s2t_t++='('; if (s2t_term(sheet)==0) return 0; *s2t_t++=','; *s2t_t++='2'; *s2t_t++=','; *s2t_t++='2'; *s2t_t++=')'; return 1; } /*}}}*/ else return 0; } /*}}}*/ else if ((*s2t_s>='0' && *s2t_s<='9') || *s2t_s=='.') /* number */ /*{{{*/ { if (*s2t_s=='.') *s2t_t++='0'; else *s2t_t++=*s2t_s++; while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++; if (*s2t_s=='.') { *s2t_t++=*s2t_s++; while (*s2t_s>='0' && *s2t_s<='9') *s2t_t++=*s2t_s++; } else { *s2t_t++='.'; *s2t_t++='0'; } return 1; } /*}}}*/ else if (*s2t_s>='A' && *s2t_s<='Z') /* cell value */ /*{{{*/ { *s2t_t++='@'; *s2t_t++='('; if (s2t_loc(sheet,&s2t_s,&s2t_t)==0) return 0; *s2t_t++=')'; return 1; } /*}}}*/ else if (*s2t_s) return 0; else return 1; } /*}}}*/ /* s2t_powterm */ /*{{{*/ static int s2t_powterm(Sheet *sheet) { if (s2t_primary(sheet)==0) return 0; while (*s2t_s=='^') { *s2t_t++=*s2t_s++; if (s2t_primary(sheet)==0) return 0; } return 1; } /*}}}*/ /* s2t_piterm */ /*{{{*/ static int s2t_piterm(Sheet *sheet) { if (s2t_powterm(sheet)==0) return 0; while (*s2t_s=='*' || *s2t_s=='/') { *s2t_t++=*s2t_s++; if (s2t_powterm(sheet)==0) return 0; } return 1; } /*}}}*/ /* s2t_term */ /*{{{*/ static int s2t_term(Sheet *sheet) { if (s2t_piterm(sheet)==0) return 0; while (*s2t_s=='+' || *s2t_s=='-') { *s2t_t++=*s2t_s++; if (s2t_piterm(sheet)==0) return 0; } return 1; } /*}}}*/ /* loadsc */ /*{{{*/ const char *loadsc(Sheet *sheet, const char *name) { /* variables */ /*{{{*/ static char errbuf[80]; FILE *fp; char buf[256]; int line; size_t width; const char *err; int x,y; /*}}}*/ if ((fp=fopen(name,"r"))==(FILE*)0) return strerror(errno); freesheet(sheet,0); err=(const char*)0; line=1; while (fgets(buf,sizeof(buf),fp)!=(char*)0) { /* remove nl */ /*{{{*/ width=strlen(buf); if (width>0 && buf[width-1]=='\n') buf[width-1]='\0'; /*}}}*/ if (buf[0] && buf[0]!='#') { if (strncmp(buf,"format ",7)==0) /* format col width precision whoknows */ /*{{{*/ { char colstr[3]; int col,colwidth,precision,whoknows; sscanf(buf+7,"%s %d %d %d",colstr,&colwidth,&precision,&whoknows); col=(colstr[0]-'A'); if (colstr[1]) col=col*26+(colstr[1]-'A'); initcell(sheet,col,0,0); CELL_AT(sheet,col,0,0)->adjust=RIGHT; CELL_AT(sheet,col,0,0)->precision=precision; setwidth(sheet,col,0,colwidth); } /*}}}*/ else if (strncmp(buf,"leftstring ",11)==0 || strncmp(buf,"rightstring ",12)==0) /* rightstring/leftstring cell = "string" */ /*{{{*/ { int x,y; const char *s; Token **contents; if (strncmp(buf,"leftstring ",11)==0) s=buf+11; else s=buf+12; x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A'); y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0'); s+=3; contents=scan(&s); if (contents==(Token**)0) { tvecfree(contents); sprintf(errbuf,_("Expression syntax error in line %d"),line); err=errbuf; goto eek; } initcell(sheet,x,y,0); CELL_AT(sheet,x,y,0)->adjust=strncmp(buf,"leftstring ",11) ? RIGHT : LEFT; CELL_AT(sheet,x,y,0)->contents=contents; } /*}}}*/ else if (strncmp(buf,"let ",4)==0) /* let cell = expression */ /*{{{*/ { /* variables */ /*{{{*/ const char *s; Token **contents; char newbuf[512]; /*}}}*/ s=buf+4; x=*s++-'A'; if (*s>='A' && *s<='Z') x=x*26+(*s++-'A'); y=*s++-'0'; while (*s>='0' && *s<='9') y=10*y+(*s++-'0'); if (getcont(sheet,x,y,0,0)==(Token**)0) { s+=3; s2t_s=s; s2t_t=newbuf; if (s2t_term(sheet)==0) { *s2t_t='\0'; if (err==(const char*)0) { sprintf(errbuf,_("Unimplemented SC feature in line %d"),line); err=errbuf; } } *s2t_t='\0'; s=newbuf; contents=scan(&s); if (contents==(Token**)0) { tvecfree(contents); sprintf(errbuf,_("Expression syntax error in line %d"),line); err=errbuf; goto eek; } initcell(sheet,x,y,0); CELL_AT(sheet,x,y,0)->adjust=RIGHT; CELL_AT(sheet,x,y,0)->contents=contents; } } /*}}}*/ } ++line; } /* set precisions for each column */ /*{{{*/ for (x=0; xdimx; ++x) { int prec; prec=getprecision(sheet,x,0,0)==def_precision ? 2 : getprecision(sheet,x,0,0); for (y=1; ydimy; ++y) if (CELL_AT(sheet,x,y,0)) CELL_AT(sheet,x,y,0)->precision=prec; } /*}}}*/ eek: if (fclose(fp)==EOF && err==(const char*)0) err=strerror(errno); sheet->changed=0; cachelabels(sheet); forceupdate(sheet); return err; } /*}}}*/