351 lines
8.3 KiB
C
351 lines
8.3 KiB
C
/* #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 "parser.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;
|
|
Location tmp;
|
|
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';
|
|
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
|
if (*getlabel(CELL_AT(sheet, tmp))=='\0') setlabel(sheet, tmp, 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;
|
|
Cell *cell;
|
|
Location tmp;
|
|
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');
|
|
OLOCATION(tmp);
|
|
tmp[X] = col;
|
|
cell = initcellofsheet(sheet, tmp);
|
|
cell->adjust = RIGHT;
|
|
cell->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 == EMPTY_TVEC)
|
|
{
|
|
tvecfree(contents);
|
|
sprintf(errbuf, _("Expression syntax error in line %d"), line);
|
|
err = errbuf;
|
|
goto eek;
|
|
}
|
|
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
|
cell = initcellofsheet(sheet, tmp);
|
|
cell->adjust = strncmp(buf, "leftstring ", 11) ? RIGHT : LEFT;
|
|
cell->tok[BASE_CONT] = eval_safe(contents, LITERAL);
|
|
tvecfree(contents);
|
|
if (cell->tok[BASE_CONT].type == EEK)
|
|
{
|
|
sprintf(errbuf, _("Parse error in line %d: %s"),
|
|
line, cell->tok[BASE_CONT].u.err);
|
|
tfree(&(cell->tok[BASE_CONT]));
|
|
err = errbuf;
|
|
goto eek;
|
|
}
|
|
}
|
|
/*}}}*/
|
|
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');
|
|
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
|
if (gettok(CELL_ATC(sheet,x,y,0), BASE_CONT).type == EMPTY)
|
|
{
|
|
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;
|
|
}
|
|
tmp[X] = x; tmp[Y] = y; tmp[Z] = 0;
|
|
cell = initcellofsheet(sheet, tmp);
|
|
cell->adjust = RIGHT;
|
|
cell->tok[BASE_CONT] = eval_safe(contents, LITERAL);
|
|
tvecfree(contents);
|
|
if (cell->tok[BASE_CONT].type == EEK)
|
|
{
|
|
sprintf(errbuf, _("Parse error in line %d: %s"),
|
|
line, cell->tok[BASE_CONT].u.err);
|
|
tfree(&(cell->tok[BASE_CONT]));
|
|
err = errbuf;
|
|
goto eek;
|
|
}
|
|
}
|
|
}
|
|
/*}}}*/
|
|
}
|
|
++line;
|
|
}
|
|
/* set precisions for each column */ /*{{{*/
|
|
for (x=0; x<sheet->dimx; ++x)
|
|
{
|
|
int prec;
|
|
|
|
prec=getprecision(CELL_ATC(sheet,x,0,0))==def_precision ? 2 : getprecision(CELL_ATC(sheet,x,0,0));
|
|
for (y=1; y<sheet->dimy; ++y) if (CELL_ATC(sheet,x,y,0)) CELL_ATC(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;
|
|
}
|
|
/*}}}*/
|