17dd7cddfSDavid du Colombier %{
27dd7cddfSDavid du Colombier typedef struct Exp Exp;
37dd7cddfSDavid du Colombier enum {
47dd7cddfSDavid du Colombier NUM,
57dd7cddfSDavid du Colombier DOT,
67dd7cddfSDavid du Colombier DOLLAR,
77dd7cddfSDavid du Colombier ADD,
87dd7cddfSDavid du Colombier SUB,
97dd7cddfSDavid du Colombier MUL,
107dd7cddfSDavid du Colombier DIV,
117dd7cddfSDavid du Colombier FRAC,
127dd7cddfSDavid du Colombier NEG,
137dd7cddfSDavid du Colombier };
147dd7cddfSDavid du Colombier
157dd7cddfSDavid du Colombier struct Exp {
167dd7cddfSDavid du Colombier int ty;
177dd7cddfSDavid du Colombier long long n;
187dd7cddfSDavid du Colombier Exp *e1;
197dd7cddfSDavid du Colombier Exp *e2;
207dd7cddfSDavid du Colombier };
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier typedef Exp* Expptr;
237dd7cddfSDavid du Colombier #define YYSTYPE Expptr
247dd7cddfSDavid du Colombier Exp *yyexp;
257dd7cddfSDavid du Colombier %}
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier %token NUMBER
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier %left '+' '-'
307dd7cddfSDavid du Colombier %left '*' '/'
317dd7cddfSDavid du Colombier %left UNARYMINUS '%'
327dd7cddfSDavid du Colombier %%
337dd7cddfSDavid du Colombier top: expr { yyexp = $1; return 0; }
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier expr: NUMBER
367dd7cddfSDavid du Colombier | '.' { $$ = mkOP(DOT, nil, nil); }
377dd7cddfSDavid du Colombier | '$' { $$ = mkOP(DOLLAR, nil, nil); }
387dd7cddfSDavid du Colombier | '(' expr ')' { $$ = $2; }
397dd7cddfSDavid du Colombier | expr '+' expr { $$ = mkOP(ADD, $1, $3); }
407dd7cddfSDavid du Colombier | expr '-' expr { $$ = mkOP(SUB, $1, $3); }
417dd7cddfSDavid du Colombier | expr '*' expr { $$ = mkOP(MUL, $1, $3); }
427dd7cddfSDavid du Colombier | expr '/' expr { $$ = mkOP(DIV, $1, $3); }
437dd7cddfSDavid du Colombier | expr '%' { $$ = mkOP(FRAC, $1, nil); }
447dd7cddfSDavid du Colombier | '-' expr %prec UNARYMINUS { $$ = mkOP(NEG, $2, nil); }
457dd7cddfSDavid du Colombier ;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier %%
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier #include <u.h>
507dd7cddfSDavid du Colombier #include <libc.h>
517dd7cddfSDavid du Colombier #include <ctype.h>
527dd7cddfSDavid du Colombier #include "disk.h"
537dd7cddfSDavid du Colombier #include "edit.h"
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier static Exp*
567dd7cddfSDavid du Colombier mkNUM(vlong x)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier Exp *n;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier n = emalloc(sizeof *n);
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier n->ty = NUM;
637dd7cddfSDavid du Colombier n->n = x;
647dd7cddfSDavid du Colombier return n;
657dd7cddfSDavid du Colombier }
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier static Exp*
mkOP(int ty,Exp * e1,Exp * e2)687dd7cddfSDavid du Colombier mkOP(int ty, Exp *e1, Exp *e2)
697dd7cddfSDavid du Colombier {
707dd7cddfSDavid du Colombier Exp *n;
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier n = emalloc(sizeof *n);
737dd7cddfSDavid du Colombier n->ty = ty;
747dd7cddfSDavid du Colombier n->e1 = e1;
757dd7cddfSDavid du Colombier n->e2 = e2;
767dd7cddfSDavid du Colombier
777dd7cddfSDavid du Colombier return n;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier static char *inp;
817dd7cddfSDavid du Colombier static jmp_buf jmp;
827dd7cddfSDavid du Colombier static vlong dot, size, dollar;
8374f16c81SDavid du Colombier static char** errp;
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier static int
yylex(void)867dd7cddfSDavid du Colombier yylex(void)
877dd7cddfSDavid du Colombier {
88*bfb6eab9SDavid du Colombier int c;
89*bfb6eab9SDavid du Colombier uvlong n;
90*bfb6eab9SDavid du Colombier
917dd7cddfSDavid du Colombier while(isspace(*inp))
927dd7cddfSDavid du Colombier inp++;
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier if(*inp == 0)
957dd7cddfSDavid du Colombier return 0;
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier if(isdigit(*inp)) {
98*bfb6eab9SDavid du Colombier n = strtoull(inp, &inp, 0); /* default unit is sectors */
99*bfb6eab9SDavid du Colombier c = *inp++;
100*bfb6eab9SDavid du Colombier if(isascii(c) && isupper(c))
101*bfb6eab9SDavid du Colombier c = tolower(c);
102*bfb6eab9SDavid du Colombier switch(c) {
103*bfb6eab9SDavid du Colombier case 't':
104*bfb6eab9SDavid du Colombier n *= 1024;
105*bfb6eab9SDavid du Colombier /* fall through */
106*bfb6eab9SDavid du Colombier case 'g':
107*bfb6eab9SDavid du Colombier n *= 1024;
108*bfb6eab9SDavid du Colombier /* fall through */
109*bfb6eab9SDavid du Colombier case 'm':
110*bfb6eab9SDavid du Colombier n *= 1024;
111*bfb6eab9SDavid du Colombier /* fall through */
112*bfb6eab9SDavid du Colombier case 'k':
113*bfb6eab9SDavid du Colombier n *= 2;
114*bfb6eab9SDavid du Colombier break;
115*bfb6eab9SDavid du Colombier default:
116*bfb6eab9SDavid du Colombier --inp;
117*bfb6eab9SDavid du Colombier break;
118*bfb6eab9SDavid du Colombier }
119*bfb6eab9SDavid du Colombier yylval = mkNUM(n);
1207dd7cddfSDavid du Colombier return NUMBER;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier return *inp++;
1237dd7cddfSDavid du Colombier }
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier static void
yyerror(char * s)1267dd7cddfSDavid du Colombier yyerror(char *s)
1277dd7cddfSDavid du Colombier {
12874f16c81SDavid du Colombier *errp = s;
12974f16c81SDavid du Colombier longjmp(jmp, 1);
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier static vlong
eval(Exp * e)1337dd7cddfSDavid du Colombier eval(Exp *e)
1347dd7cddfSDavid du Colombier {
1357dd7cddfSDavid du Colombier vlong i;
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier switch(e->ty) {
1387dd7cddfSDavid du Colombier case NUM:
1397dd7cddfSDavid du Colombier return e->n;
1407dd7cddfSDavid du Colombier case DOT:
1417dd7cddfSDavid du Colombier return dot;
1427dd7cddfSDavid du Colombier case DOLLAR:
1437dd7cddfSDavid du Colombier return dollar;
1447dd7cddfSDavid du Colombier case ADD:
1457dd7cddfSDavid du Colombier return eval(e->e1)+eval(e->e2);
1467dd7cddfSDavid du Colombier case SUB:
1477dd7cddfSDavid du Colombier return eval(e->e1)-eval(e->e2);
1487dd7cddfSDavid du Colombier case MUL:
1497dd7cddfSDavid du Colombier return eval(e->e1)*eval(e->e2);
1507dd7cddfSDavid du Colombier case DIV:
1517dd7cddfSDavid du Colombier i = eval(e->e2);
1527dd7cddfSDavid du Colombier if(i == 0)
1537dd7cddfSDavid du Colombier yyerror("division by zero");
1547dd7cddfSDavid du Colombier return eval(e->e1)/i;
1557dd7cddfSDavid du Colombier case FRAC:
1567dd7cddfSDavid du Colombier return (size*eval(e->e1))/100;
1577dd7cddfSDavid du Colombier case NEG:
1587dd7cddfSDavid du Colombier return -eval(e->e1);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier assert(0);
1617dd7cddfSDavid du Colombier return 0;
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier int yyparse(void);
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier char*
parseexpr(char * s,vlong xdot,vlong xdollar,vlong xsize,vlong * result)1677dd7cddfSDavid du Colombier parseexpr(char *s, vlong xdot, vlong xdollar, vlong xsize, vlong *result)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier char *err;
1707dd7cddfSDavid du Colombier
17174f16c81SDavid du Colombier errp = &err;
17274f16c81SDavid du Colombier if(setjmp(jmp))
1737dd7cddfSDavid du Colombier return err;
1747dd7cddfSDavid du Colombier
1757dd7cddfSDavid du Colombier inp = s;
1767dd7cddfSDavid du Colombier dot = xdot;
1777dd7cddfSDavid du Colombier size = xsize;
1787dd7cddfSDavid du Colombier dollar = xdollar;
1797dd7cddfSDavid du Colombier yyparse();
1807dd7cddfSDavid du Colombier if(yyexp == nil)
1817dd7cddfSDavid du Colombier return "nil yylval?";
1827dd7cddfSDavid du Colombier *result = eval(yyexp);
1837dd7cddfSDavid du Colombier return nil;
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier #ifdef TEST
1877dd7cddfSDavid du Colombier void
main(int argc,char ** argv)1887dd7cddfSDavid du Colombier main(int argc, char **argv)
1897dd7cddfSDavid du Colombier {
1907dd7cddfSDavid du Colombier int i;
1917dd7cddfSDavid du Colombier vlong r;
1927dd7cddfSDavid du Colombier char *e;
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier for(i=1; i<argc; i++)
1957dd7cddfSDavid du Colombier if(e = parseexpr(argv[i], 1000, 1000000, 1000000, &r))
1967dd7cddfSDavid du Colombier print("%s\n", e);
1977dd7cddfSDavid du Colombier else
1987dd7cddfSDavid du Colombier print("%lld\n", r);
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier #endif
201