teapot-spreadsheet/sc.c

321 lines
7.5 KiB
C
Raw Normal View History

/* #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 <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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; x<sheet->dimx; ++x)
{
int prec;
prec=getprecision(sheet,x,0,0)==def_precision ? 2 : getprecision(sheet,x,0,0);
for (y=1; y<sheet->dimy; ++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;
}
/*}}}*/