%{#include <u.h>#include <libc.h>#include <bio.h> enum{ Ndim = 15, /* number of dimensions */ Nsym = 40, /* size of a name */ Nvar = 203, /* hash table size */ Maxe = 695, /* log of largest number */}; typedef struct Var Var;typedef struct Node Node;typedef struct Prefix Prefix; struct Node{ double val; schar dim[Ndim];};struct Var{ Rune name[Nsym]; Node node; Var* link;};struct Prefix{ double val; Rune* pname;}; char buf[100];int digval;Biobuf* fi;Biobuf linebuf;Var* fund[Ndim];Rune line[1000];ulong lineno;int linep;int nerrors;Node one;int peekrune;Node retnode1;Node retnode2;Node retnode;Rune sym[Nsym];Var* vars[Nvar];int vflag; extern void add(Node*, Node*, Node*);extern void div(Node*, Node*, Node*);extern int specialcase(Node*, Node*, Node*);extern double fadd(double, double);extern double fdiv(double, double);extern double fmul(double, double);extern int gdigit(void*);extern Var* lookup(int);extern void main(int, char*[]);extern void mul(Node*, Node*, Node*);extern void ofile(void);extern double pname(void);extern void printdim(char*, int, int);extern int ralpha(int);extern int readline(void);extern void sub(Node*, Node*, Node*);extern int Ufmt(Fmt*);extern void xpn(Node*, Node*, int);extern void yyerror(char*, ...);extern int yylex(void);extern int yyparse(void); typedef Node* indnode;#pragma varargck type "U" indnode %}%union{ Node node; Var* var; int numb; double val;} %type <node> prog expr expr0 expr1 expr2 expr3 expr4 %token <val> VAL%token <var> VAR%token <numb> SUP%%prog: ':' VAR expr { int f; f = $2->node.dim[0]; $2->node = $3; $2->node.dim[0] = 1; if(f) yyerror("redefinition of %S", $2->name); else if(vflag) print("%S\t%U\n", $2->name, &$2->node); }| ':' VAR '#' { int f, i; for(i=1; i<Ndim; i++) if(fund[i] == 0) break; if(i >= Ndim) { yyerror("too many dimensions"); i = Ndim-1; } fund[i] = $2; f = $2->node.dim[0]; $2->node = one; $2->node.dim[0] = 1; $2->node.dim[i] = 1; if(f) yyerror("redefinition of %S", $2->name); else if(vflag) print("%S\t#\n", $2->name); }| '?' expr { retnode1 = $2; }| '?' { retnode1 = one; } expr: expr4| expr '+' expr4 { add(&$$, &$1, &$3); }| expr '-' expr4 { sub(&$$, &$1, &$3); } expr4: expr3| expr4 '*' expr3 { mul(&$$, &$1, &$3); }| expr4 '/' expr3 { div(&$$, &$1, &$3); } expr3: expr2| expr3 expr2 { mul(&$$, &$1, &$2); } expr2: expr1| expr2 SUP { xpn(&$$, &$1, $2); }| expr2 '^' expr1 { int i; for(i=1; i<Ndim; i++) if($3.dim[i]) { yyerror("exponent has units"); $$ = $1; break; } if(i >= Ndim) { i = $3.val; if(i != $3.val) yyerror("exponent not integral"); xpn(&$$, &$1, i); } } expr1: expr0| expr1 '|' expr0 { div(&$$, &$1, &$3); } expr0: VAR { if($1->node.dim[0] == 0) { yyerror("undefined %S", $1->name); $$ = one; } else $$ = $1->node; }| VAL { $$ = one; $$.val = $1; }| '(' expr ')' { $$ = $2; }%% intyylex(void){ int c, i; c = peekrune; peekrune = ' '; loop: if((c >= '0' && c <= '9') || c == '.') goto numb; if(ralpha(c)) goto alpha; switch(c) { case ' ': case '\t': c = line[linep++]; goto loop; case L'×': return '*'; case L'÷': return '/'; case L'¹': case L'ⁱ': yylval.numb = 1; return SUP; case L'²': case L'': yylval.numb = 2; return SUP; case L'³': case L'': yylval.numb = 3; return SUP; } return c; alpha: memset(sym, 0, sizeof(sym)); for(i=0;; i++) { if(i < nelem(sym)) sym[i] = c; c = line[linep++]; if(!ralpha(c)) break; } sym[nelem(sym)-1] = 0; peekrune = c; yylval.var = lookup(0); return VAR; numb: digval = c; yylval.val = charstod(gdigit, 0); return VAL;} voidmain(int argc, char *argv[]){ char *file; ARGBEGIN { default: print("usage: units [-v] [file]\n"); exits("usage"); case 'v': vflag = 1; break; } ARGEND file = "/lib/units"; if(argc > 0) file = argv[0]; fi = Bopen(file, OREAD); if(fi == 0) { print("cant open: %s\n", file); exits("open"); } fmtinstall('U', Ufmt); one.val = 1; /* * read the 'units' file to * develope a database */ lineno = 0; for(;;) { lineno++; if(readline()) break; if(line[0] == 0 || line[0] == '/') continue; peekrune = ':'; yyparse(); } /* * read the console to * print ratio of pairs */ Bterm(fi); fi = &linebuf; Binit(fi, 0, OREAD); lineno = 0; for(;;) { if(lineno & 1) print("you want: "); else print("you have: "); if(readline()) break; peekrune = '?'; nerrors = 0; yyparse(); if(nerrors) continue; if(lineno & 1) { if(specialcase(&retnode, &retnode2, &retnode1)) print("\tis %U\n", &retnode); else { div(&retnode, &retnode2, &retnode1); print("\t* %U\n", &retnode); div(&retnode, &retnode1, &retnode2); print("\t/ %U\n", &retnode); } } else retnode2 = retnode1; lineno++; } print("\n"); exits(0);} /* * all characters that have some * meaning. rest are usable as names */intralpha(int c){ switch(c) { case 0: case '+': case '-': case '*': case '/': case '[': case ']': case '(': case ')': case '^': case ':': case '?': case ' ': case '\t': case '.': case '|': case '#': case L'¹': case L'ⁱ': case L'²': case L'': case L'³': case L'': case L'×': case L'÷': return 0; } return 1;} intgdigit(void*){ int c; c = digval; if(c) { digval = 0; return c; } c = line[linep++]; peekrune = c; return c;} voidyyerror(char *fmt, ...){ va_list arg; /* * hack to intercept message from yaccpar */ if(strcmp(fmt, "syntax error") == 0) { yyerror("syntax error, last name: %S", sym); return; } va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); print("%ld: %S\n\t%s\n", lineno, line, buf); nerrors++; if(nerrors > 5) { print("too many errors\n"); exits("errors"); }} voidadd(Node *c, Node *a, Node *b){ int i, d; for(i=0; i<Ndim; i++) { d = a->dim[i]; c->dim[i] = d; if(d != b->dim[i]) yyerror("add must be like units"); } c->val = fadd(a->val, b->val);} voidsub(Node *c, Node *a, Node *b){ int i, d; for(i=0; i<Ndim; i++) { d = a->dim[i]; c->dim[i] = d; if(d != b->dim[i]) yyerror("sub must be like units"); } c->val = fadd(a->val, -b->val);} voidmul(Node *c, Node *a, Node *b){ int i; for(i=0; i<Ndim; i++) c->dim[i] = a->dim[i] + b->dim[i]; c->val = fmul(a->val, b->val);} voiddiv(Node *c, Node *a, Node *b){ int i; for(i=0; i<Ndim; i++) c->dim[i] = a->dim[i] - b->dim[i]; c->val = fdiv(a->val, b->val);} voidxpn(Node *c, Node *a, int b){ int i; *c = one; if(b < 0) { b = -b; for(i=0; i<b; i++) div(c, c, a); } else for(i=0; i<b; i++) mul(c, c, a);} intspecialcase(Node *c, Node *a, Node *b){ int i, d, d1, d2; d1 = 0; d2 = 0; for(i=1; i<Ndim; i++) { d = a->dim[i];Lines 1–500 of 786. Load more
%{ #include <u.h> #include <libc.h> #include <bio.h> enum { Ndim = 15, /* number of dimensions */ Nsym = 40, /* size of a name */ Nvar = 203, /* hash table size */ Maxe = 695, /* log of largest number */ }; typedef struct Var Var; typedef struct Node Node; typedef struct Prefix Prefix; struct Node { double val; schar dim[Ndim]; }; struct Var { Rune name[Nsym]; Node node; Var* link; }; struct Prefix { double val; Rune* pname; }; char buf[100]; int digval; Biobuf* fi; Biobuf linebuf; Var* fund[Ndim]; Rune line[1000]; ulong lineno; int linep; int nerrors; Node one; int peekrune; Node retnode1; Node retnode2; Node retnode; Rune sym[Nsym]; Var* vars[Nvar]; int vflag; extern void add(Node*, Node*, Node*); extern void div(Node*, Node*, Node*); extern int specialcase(Node*, Node*, Node*); extern double fadd(double, double); extern double fdiv(double, double); extern double fmul(double, double); extern int gdigit(void*); extern Var* lookup(int); extern void main(int, char*[]); extern void mul(Node*, Node*, Node*); extern void ofile(void); extern double pname(void); extern void printdim(char*, int, int); extern int ralpha(int); extern int readline(void); extern void sub(Node*, Node*, Node*); extern int Ufmt(Fmt*); extern void xpn(Node*, Node*, int); extern void yyerror(char*, ...); extern int yylex(void); extern int yyparse(void); typedef Node* indnode; #pragma varargck type "U" indnode %} %union { Node node; Var* var; int numb; double val; } %type <node> prog expr expr0 expr1 expr2 expr3 expr4 %token <val> VAL %token <var> VAR %token <numb> SUP %% prog: ':' VAR expr { int f; f = $2->node.dim[0]; $2->node = $3; $2->node.dim[0] = 1; if(f) yyerror("redefinition of %S", $2->name); else if(vflag) print("%S\t%U\n", $2->name, &$2->node); } | ':' VAR '#' { int f, i; for(i=1; i<Ndim; i++) if(fund[i] == 0) break; if(i >= Ndim) { yyerror("too many dimensions"); i = Ndim-1; } fund[i] = $2; f = $2->node.dim[0]; $2->node = one; $2->node.dim[0] = 1; $2->node.dim[i] = 1; if(f) yyerror("redefinition of %S", $2->name); else if(vflag) print("%S\t#\n", $2->name); } | '?' expr { retnode1 = $2; } | '?' { retnode1 = one; } expr: expr4 | expr '+' expr4 { add(&$$, &$1, &$3); } | expr '-' expr4 { sub(&$$, &$1, &$3); } expr4: expr3 | expr4 '*' expr3 { mul(&$$, &$1, &$3); } | expr4 '/' expr3 { div(&$$, &$1, &$3); } expr3: expr2 | expr3 expr2 { mul(&$$, &$1, &$2); } expr2: expr1 | expr2 SUP { xpn(&$$, &$1, $2); } | expr2 '^' expr1 { int i; for(i=1; i<Ndim; i++) if($3.dim[i]) { yyerror("exponent has units"); $$ = $1; break; } if(i >= Ndim) { i = $3.val; if(i != $3.val) yyerror("exponent not integral"); xpn(&$$, &$1, i); } } expr1: expr0 | expr1 '|' expr0 { div(&$$, &$1, &$3); } expr0: VAR { if($1->node.dim[0] == 0) { yyerror("undefined %S", $1->name); $$ = one; } else $$ = $1->node; } | VAL { $$ = one; $$.val = $1; } | '(' expr ')' { $$ = $2; } %% int yylex(void) { int c, i; c = peekrune; peekrune = ' '; loop: if((c >= '0' && c <= '9') || c == '.') goto numb; if(ralpha(c)) goto alpha; switch(c) { case ' ': case '\t': c = line[linep++]; goto loop; case L'×': return '*'; case L'÷': return '/'; case L'¹': case L'ⁱ': yylval.numb = 1; return SUP; case L'²': case L'': yylval.numb = 2; return SUP; case L'³': case L'': yylval.numb = 3; return SUP; } return c; alpha: memset(sym, 0, sizeof(sym)); for(i=0;; i++) { if(i < nelem(sym)) sym[i] = c; c = line[linep++]; if(!ralpha(c)) break; } sym[nelem(sym)-1] = 0; peekrune = c; yylval.var = lookup(0); return VAR; numb: digval = c; yylval.val = charstod(gdigit, 0); return VAL; } void main(int argc, char *argv[]) { char *file; ARGBEGIN { default: print("usage: units [-v] [file]\n"); exits("usage"); case 'v': vflag = 1; break; } ARGEND file = "/lib/units"; if(argc > 0) file = argv[0]; fi = Bopen(file, OREAD); if(fi == 0) { print("cant open: %s\n", file); exits("open"); } fmtinstall('U', Ufmt); one.val = 1; /* * read the 'units' file to * develope a database */ lineno = 0; for(;;) { lineno++; if(readline()) break; if(line[0] == 0 || line[0] == '/') continue; peekrune = ':'; yyparse(); } /* * read the console to * print ratio of pairs */ Bterm(fi); fi = &linebuf; Binit(fi, 0, OREAD); lineno = 0; for(;;) { if(lineno & 1) print("you want: "); else print("you have: "); if(readline()) break; peekrune = '?'; nerrors = 0; yyparse(); if(nerrors) continue; if(lineno & 1) { if(specialcase(&retnode, &retnode2, &retnode1)) print("\tis %U\n", &retnode); else { div(&retnode, &retnode2, &retnode1); print("\t* %U\n", &retnode); div(&retnode, &retnode1, &retnode2); print("\t/ %U\n", &retnode); } } else retnode2 = retnode1; lineno++; } print("\n"); exits(0); } /* * all characters that have some * meaning. rest are usable as names */ int ralpha(int c) { switch(c) { case 0: case '+': case '-': case '*': case '/': case '[': case ']': case '(': case ')': case '^': case ':': case '?': case ' ': case '\t': case '.': case '|': case '#': case L'¹': case L'ⁱ': case L'²': case L'': case L'³': case L'': case L'×': case L'÷': return 0; } return 1; } int gdigit(void*) { int c; c = digval; if(c) { digval = 0; return c; } c = line[linep++]; peekrune = c; return c; } void yyerror(char *fmt, ...) { va_list arg; /* * hack to intercept message from yaccpar */ if(strcmp(fmt, "syntax error") == 0) { yyerror("syntax error, last name: %S", sym); return; } va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); print("%ld: %S\n\t%s\n", lineno, line, buf); nerrors++; if(nerrors > 5) { print("too many errors\n"); exits("errors"); } } void add(Node *c, Node *a, Node *b) { int i, d; for(i=0; i<Ndim; i++) { d = a->dim[i]; c->dim[i] = d; if(d != b->dim[i]) yyerror("add must be like units"); } c->val = fadd(a->val, b->val); } void sub(Node *c, Node *a, Node *b) { int i, d; for(i=0; i<Ndim; i++) { d = a->dim[i]; c->dim[i] = d; if(d != b->dim[i]) yyerror("sub must be like units"); } c->val = fadd(a->val, -b->val); } void mul(Node *c, Node *a, Node *b) { int i; for(i=0; i<Ndim; i++) c->dim[i] = a->dim[i] + b->dim[i]; c->val = fmul(a->val, b->val); } void div(Node *c, Node *a, Node *b) { int i; for(i=0; i<Ndim; i++) c->dim[i] = a->dim[i] - b->dim[i]; c->val = fdiv(a->val, b->val); } void xpn(Node *c, Node *a, int b) { int i; *c = one; if(b < 0) { b = -b; for(i=0; i<b; i++) div(c, c, a); } else for(i=0; i<b; i++) mul(c, c, a); } int specialcase(Node *c, Node *a, Node *b) { int i, d, d1, d2; d1 = 0; d2 = 0; for(i=1; i<Ndim; i++) { d = a->dim[i];