2 17e5fb89 2004-04-21 devnull #include <u.h>
3 17e5fb89 2004-04-21 devnull #include <libc.h>
4 17e5fb89 2004-04-21 devnull #include <bio.h>
8 17e5fb89 2004-04-21 devnull Ndim = 15, /* number of dimensions */
9 17e5fb89 2004-04-21 devnull Nsym = 40, /* size of a name */
10 17e5fb89 2004-04-21 devnull Nvar = 203, /* hash table size */
11 cbeb0b26 2006-04-01 devnull Maxe = 695 /* log of largest number */
14 17e5fb89 2004-04-21 devnull typedef struct Var Var;
15 17e5fb89 2004-04-21 devnull typedef struct Node Node;
16 17e5fb89 2004-04-21 devnull typedef struct Prefix Prefix;
18 17e5fb89 2004-04-21 devnull struct Node
20 17e5fb89 2004-04-21 devnull double val;
21 17e5fb89 2004-04-21 devnull schar dim[Ndim];
23 17e5fb89 2004-04-21 devnull struct Var
25 17e5fb89 2004-04-21 devnull Rune name[Nsym];
26 17e5fb89 2004-04-21 devnull Node node;
27 17e5fb89 2004-04-21 devnull Var* link;
29 17e5fb89 2004-04-21 devnull struct Prefix
31 17e5fb89 2004-04-21 devnull double val;
32 17e5fb89 2004-04-21 devnull char* name;
33 17e5fb89 2004-04-21 devnull Rune* pname;
36 17e5fb89 2004-04-21 devnull char buf[100];
37 17e5fb89 2004-04-21 devnull int digval;
38 17e5fb89 2004-04-21 devnull Biobuf* fi;
39 17e5fb89 2004-04-21 devnull Biobuf linebuf;
40 17e5fb89 2004-04-21 devnull Var* fund[Ndim];
41 17e5fb89 2004-04-21 devnull Rune line[1000];
42 17e5fb89 2004-04-21 devnull ulong lineno;
43 17e5fb89 2004-04-21 devnull int linep;
44 17e5fb89 2004-04-21 devnull int nerrors;
45 17e5fb89 2004-04-21 devnull Node one;
46 17e5fb89 2004-04-21 devnull int peekrune;
47 17e5fb89 2004-04-21 devnull Node retnode1;
48 17e5fb89 2004-04-21 devnull Node retnode2;
49 17e5fb89 2004-04-21 devnull Node retnode;
50 17e5fb89 2004-04-21 devnull Rune sym[Nsym];
51 17e5fb89 2004-04-21 devnull Var* vars[Nvar];
52 17e5fb89 2004-04-21 devnull int vflag;
54 17e5fb89 2004-04-21 devnull #define div unitsdiv
56 17e5fb89 2004-04-21 devnull extern void add(Node*, Node*, Node*);
57 17e5fb89 2004-04-21 devnull extern void div(Node*, Node*, Node*);
58 17e5fb89 2004-04-21 devnull extern int specialcase(Node*, Node*, Node*);
59 17e5fb89 2004-04-21 devnull extern double fadd(double, double);
60 17e5fb89 2004-04-21 devnull extern double fdiv(double, double);
61 17e5fb89 2004-04-21 devnull extern double fmul(double, double);
62 17e5fb89 2004-04-21 devnull extern int gdigit(void*);
63 17e5fb89 2004-04-21 devnull extern Var* lookup(int);
64 17e5fb89 2004-04-21 devnull extern void main(int, char*[]);
65 17e5fb89 2004-04-21 devnull extern void mul(Node*, Node*, Node*);
66 17e5fb89 2004-04-21 devnull extern void ofile(void);
67 17e5fb89 2004-04-21 devnull extern double pname(void);
68 17e5fb89 2004-04-21 devnull extern void printdim(char*, int, int);
69 17e5fb89 2004-04-21 devnull extern int ralpha(int);
70 17e5fb89 2004-04-21 devnull extern int readline(void);
71 17e5fb89 2004-04-21 devnull extern void sub(Node*, Node*, Node*);
72 17e5fb89 2004-04-21 devnull extern int Ufmt(Fmt*);
73 17e5fb89 2004-04-21 devnull extern void xpn(Node*, Node*, int);
74 17e5fb89 2004-04-21 devnull extern void yyerror(char*, ...);
75 17e5fb89 2004-04-21 devnull extern int yylex(void);
76 17e5fb89 2004-04-21 devnull extern int yyparse(void);
78 17e5fb89 2004-04-21 devnull typedef Node* indnode;
79 17e5fb89 2004-04-21 devnull /* #pragma varargck type "U" indnode */
84 17e5fb89 2004-04-21 devnull Node node;
85 17e5fb89 2004-04-21 devnull Var* var;
86 17e5fb89 2004-04-21 devnull int numb;
87 17e5fb89 2004-04-21 devnull double val;
90 17e5fb89 2004-04-21 devnull %type <node> prog expr expr0 expr1 expr2 expr3 expr4
92 17e5fb89 2004-04-21 devnull %token <val> VAL
93 17e5fb89 2004-04-21 devnull %token <var> VAR
94 17e5fb89 2004-04-21 devnull %token <numb> SUP
97 17e5fb89 2004-04-21 devnull ':' VAR expr
101 17e5fb89 2004-04-21 devnull f = $2->node.dim[0];
102 17e5fb89 2004-04-21 devnull $2->node = $3;
103 17e5fb89 2004-04-21 devnull $2->node.dim[0] = 1;
105 17e5fb89 2004-04-21 devnull yyerror("redefinition of %S", $2->name);
107 17e5fb89 2004-04-21 devnull if(vflag)
108 17e5fb89 2004-04-21 devnull print("%S\t%U\n", $2->name, &$2->node);
110 17e5fb89 2004-04-21 devnull | ':' VAR '#'
112 17e5fb89 2004-04-21 devnull int f, i;
114 17e5fb89 2004-04-21 devnull for(i=1; i<Ndim; i++)
115 17e5fb89 2004-04-21 devnull if(fund[i] == 0)
117 17e5fb89 2004-04-21 devnull if(i >= Ndim) {
118 17e5fb89 2004-04-21 devnull yyerror("too many dimensions");
119 17e5fb89 2004-04-21 devnull i = Ndim-1;
121 17e5fb89 2004-04-21 devnull fund[i] = $2;
123 17e5fb89 2004-04-21 devnull f = $2->node.dim[0];
124 17e5fb89 2004-04-21 devnull $2->node = one;
125 17e5fb89 2004-04-21 devnull $2->node.dim[0] = 1;
126 17e5fb89 2004-04-21 devnull $2->node.dim[i] = 1;
128 17e5fb89 2004-04-21 devnull yyerror("redefinition of %S", $2->name);
130 17e5fb89 2004-04-21 devnull if(vflag)
131 17e5fb89 2004-04-21 devnull print("%S\t#\n", $2->name);
133 17e5fb89 2004-04-21 devnull | '?' expr
135 17e5fb89 2004-04-21 devnull retnode1 = $2;
139 17e5fb89 2004-04-21 devnull retnode1 = one;
144 17e5fb89 2004-04-21 devnull | expr '+' expr4
146 17e5fb89 2004-04-21 devnull add(&$$, &$1, &$3);
148 17e5fb89 2004-04-21 devnull | expr '-' expr4
150 17e5fb89 2004-04-21 devnull sub(&$$, &$1, &$3);
155 17e5fb89 2004-04-21 devnull | expr4 '*' expr3
157 17e5fb89 2004-04-21 devnull mul(&$$, &$1, &$3);
159 17e5fb89 2004-04-21 devnull | expr4 '/' expr3
161 17e5fb89 2004-04-21 devnull div(&$$, &$1, &$3);
166 17e5fb89 2004-04-21 devnull | expr3 expr2
168 17e5fb89 2004-04-21 devnull mul(&$$, &$1, &$2);
173 17e5fb89 2004-04-21 devnull | expr2 SUP
175 17e5fb89 2004-04-21 devnull xpn(&$$, &$1, $2);
177 17e5fb89 2004-04-21 devnull | expr2 '^' expr1
181 17e5fb89 2004-04-21 devnull for(i=1; i<Ndim; i++)
182 17e5fb89 2004-04-21 devnull if($3.dim[i]) {
183 17e5fb89 2004-04-21 devnull yyerror("exponent has units");
184 17e5fb89 2004-04-21 devnull $$ = $1;
187 17e5fb89 2004-04-21 devnull if(i >= Ndim) {
188 17e5fb89 2004-04-21 devnull i = $3.val;
189 17e5fb89 2004-04-21 devnull if(i != $3.val)
190 17e5fb89 2004-04-21 devnull yyerror("exponent not integral");
191 17e5fb89 2004-04-21 devnull xpn(&$$, &$1, i);
197 17e5fb89 2004-04-21 devnull | expr1 '|' expr0
199 17e5fb89 2004-04-21 devnull div(&$$, &$1, &$3);
205 17e5fb89 2004-04-21 devnull if($1->node.dim[0] == 0) {
206 17e5fb89 2004-04-21 devnull yyerror("undefined %S", $1->name);
207 17e5fb89 2004-04-21 devnull $$ = one;
209 17e5fb89 2004-04-21 devnull $$ = $1->node;
213 17e5fb89 2004-04-21 devnull $$ = one;
214 17e5fb89 2004-04-21 devnull $$.val = $1;
216 17e5fb89 2004-04-21 devnull | '(' expr ')'
218 17e5fb89 2004-04-21 devnull $$ = $2;
223 17e5fb89 2004-04-21 devnull yylex(void)
225 17e5fb89 2004-04-21 devnull int c, i;
227 17e5fb89 2004-04-21 devnull c = peekrune;
228 17e5fb89 2004-04-21 devnull peekrune = ' ';
231 17e5fb89 2004-04-21 devnull if((c >= '0' && c <= '9') || c == '.')
232 17e5fb89 2004-04-21 devnull goto numb;
233 17e5fb89 2004-04-21 devnull if(ralpha(c))
234 17e5fb89 2004-04-21 devnull goto alpha;
235 17e5fb89 2004-04-21 devnull switch(c) {
236 17e5fb89 2004-04-21 devnull case ' ':
237 17e5fb89 2004-04-21 devnull case '\t':
238 17e5fb89 2004-04-21 devnull c = line[linep++];
239 17e5fb89 2004-04-21 devnull goto loop;
240 17e5fb89 2004-04-21 devnull case 0xd7:
241 17e5fb89 2004-04-21 devnull return 0x2a;
242 17e5fb89 2004-04-21 devnull case 0xf7:
243 17e5fb89 2004-04-21 devnull return 0x2f;
244 17e5fb89 2004-04-21 devnull case 0xb9:
245 17e5fb89 2004-04-21 devnull case 0x2071:
246 17e5fb89 2004-04-21 devnull yylval.numb = 1;
247 17e5fb89 2004-04-21 devnull return SUP;
248 17e5fb89 2004-04-21 devnull case 0xb2:
249 17e5fb89 2004-04-21 devnull case 0x2072:
250 17e5fb89 2004-04-21 devnull yylval.numb = 2;
251 17e5fb89 2004-04-21 devnull return SUP;
252 17e5fb89 2004-04-21 devnull case 0xb3:
253 17e5fb89 2004-04-21 devnull case 0x2073:
254 17e5fb89 2004-04-21 devnull yylval.numb = 3;
255 17e5fb89 2004-04-21 devnull return SUP;
257 17e5fb89 2004-04-21 devnull return c;
260 17e5fb89 2004-04-21 devnull memset(sym, 0, sizeof(sym));
261 17e5fb89 2004-04-21 devnull for(i=0;; i++) {
262 17e5fb89 2004-04-21 devnull if(i < nelem(sym))
263 17e5fb89 2004-04-21 devnull sym[i] = c;
264 17e5fb89 2004-04-21 devnull c = line[linep++];
265 17e5fb89 2004-04-21 devnull if(!ralpha(c))
268 17e5fb89 2004-04-21 devnull sym[nelem(sym)-1] = 0;
269 17e5fb89 2004-04-21 devnull peekrune = c;
270 17e5fb89 2004-04-21 devnull yylval.var = lookup(0);
271 17e5fb89 2004-04-21 devnull return VAR;
274 17e5fb89 2004-04-21 devnull digval = c;
275 17e5fb89 2004-04-21 devnull yylval.val = fmtcharstod(gdigit, 0);
276 17e5fb89 2004-04-21 devnull return VAL;
280 17e5fb89 2004-04-21 devnull main(int argc, char *argv[])
282 17e5fb89 2004-04-21 devnull char *file;
284 17e5fb89 2004-04-21 devnull ARGBEGIN {
285 17e5fb89 2004-04-21 devnull default:
286 17e5fb89 2004-04-21 devnull print("usage: units [-v] [file]\n");
287 17e5fb89 2004-04-21 devnull exits("usage");
288 17e5fb89 2004-04-21 devnull case 'v':
289 17e5fb89 2004-04-21 devnull vflag = 1;
291 17e5fb89 2004-04-21 devnull } ARGEND
293 17e5fb89 2004-04-21 devnull file = unsharp("#9/lib/units");
294 17e5fb89 2004-04-21 devnull if(argc > 0)
295 17e5fb89 2004-04-21 devnull file = argv[0];
296 17e5fb89 2004-04-21 devnull fi = Bopen(file, OREAD);
297 17e5fb89 2004-04-21 devnull if(fi == 0) {
298 17e5fb89 2004-04-21 devnull print("cant open: %s\n", file);
299 17e5fb89 2004-04-21 devnull exits("open");
301 17e5fb89 2004-04-21 devnull fmtinstall('U', Ufmt);
302 17e5fb89 2004-04-21 devnull one.val = 1;
305 17e5fb89 2004-04-21 devnull * read the 'units' file to
306 17e5fb89 2004-04-21 devnull * develope a database
308 17e5fb89 2004-04-21 devnull lineno = 0;
309 17e5fb89 2004-04-21 devnull for(;;) {
310 17e5fb89 2004-04-21 devnull lineno++;
311 17e5fb89 2004-04-21 devnull if(readline())
313 17e5fb89 2004-04-21 devnull if(line[0] == 0 || line[0] == '/')
314 17e5fb89 2004-04-21 devnull continue;
315 17e5fb89 2004-04-21 devnull peekrune = ':';
316 17e5fb89 2004-04-21 devnull yyparse();
320 17e5fb89 2004-04-21 devnull * read the console to
321 17e5fb89 2004-04-21 devnull * print ratio of pairs
323 17e5fb89 2004-04-21 devnull Bterm(fi);
324 17e5fb89 2004-04-21 devnull fi = &linebuf;
325 17e5fb89 2004-04-21 devnull Binit(fi, 0, OREAD);
326 17e5fb89 2004-04-21 devnull lineno = 0;
327 17e5fb89 2004-04-21 devnull for(;;) {
328 17e5fb89 2004-04-21 devnull if(lineno & 1)
329 17e5fb89 2004-04-21 devnull print("you want: ");
331 17e5fb89 2004-04-21 devnull print("you have: ");
332 17e5fb89 2004-04-21 devnull if(readline())
334 17e5fb89 2004-04-21 devnull peekrune = '?';
335 17e5fb89 2004-04-21 devnull nerrors = 0;
336 17e5fb89 2004-04-21 devnull yyparse();
337 17e5fb89 2004-04-21 devnull if(nerrors)
338 17e5fb89 2004-04-21 devnull continue;
339 17e5fb89 2004-04-21 devnull if(lineno & 1) {
340 17e5fb89 2004-04-21 devnull if(specialcase(&retnode, &retnode2, &retnode1))
341 17e5fb89 2004-04-21 devnull print("\tis %U\n", &retnode);
343 17e5fb89 2004-04-21 devnull div(&retnode, &retnode2, &retnode1);
344 17e5fb89 2004-04-21 devnull print("\t* %U\n", &retnode);
345 17e5fb89 2004-04-21 devnull div(&retnode, &retnode1, &retnode2);
346 17e5fb89 2004-04-21 devnull print("\t/ %U\n", &retnode);
349 17e5fb89 2004-04-21 devnull retnode2 = retnode1;
350 17e5fb89 2004-04-21 devnull lineno++;
352 17e5fb89 2004-04-21 devnull print("\n");
353 17e5fb89 2004-04-21 devnull exits(0);
357 17e5fb89 2004-04-21 devnull * all characters that have some
358 17e5fb89 2004-04-21 devnull * meaning. rest are usable as names
361 17e5fb89 2004-04-21 devnull ralpha(int c)
363 17e5fb89 2004-04-21 devnull switch(c) {
365 17e5fb89 2004-04-21 devnull case '+':
366 17e5fb89 2004-04-21 devnull case '-':
367 17e5fb89 2004-04-21 devnull case '*':
368 17e5fb89 2004-04-21 devnull case '/':
369 17e5fb89 2004-04-21 devnull case '[':
370 17e5fb89 2004-04-21 devnull case ']':
371 17e5fb89 2004-04-21 devnull case '(':
372 17e5fb89 2004-04-21 devnull case ')':
373 17e5fb89 2004-04-21 devnull case '^':
374 17e5fb89 2004-04-21 devnull case ':':
375 17e5fb89 2004-04-21 devnull case '?':
376 17e5fb89 2004-04-21 devnull case ' ':
377 17e5fb89 2004-04-21 devnull case '\t':
378 17e5fb89 2004-04-21 devnull case '.':
379 17e5fb89 2004-04-21 devnull case '|':
380 17e5fb89 2004-04-21 devnull case '#':
381 17e5fb89 2004-04-21 devnull case 0xb9:
382 17e5fb89 2004-04-21 devnull case 0x2071:
383 17e5fb89 2004-04-21 devnull case 0xb2:
384 17e5fb89 2004-04-21 devnull case 0x2072:
385 17e5fb89 2004-04-21 devnull case 0xb3:
386 17e5fb89 2004-04-21 devnull case 0x2073:
387 17e5fb89 2004-04-21 devnull case 0xd7:
388 17e5fb89 2004-04-21 devnull case 0xf7:
389 17e5fb89 2004-04-21 devnull return 0;
391 17e5fb89 2004-04-21 devnull return 1;
395 17e5fb89 2004-04-21 devnull gdigit(void *v)
399 17e5fb89 2004-04-21 devnull USED(v);
400 17e5fb89 2004-04-21 devnull c = digval;
402 17e5fb89 2004-04-21 devnull digval = 0;
403 17e5fb89 2004-04-21 devnull return c;
405 17e5fb89 2004-04-21 devnull c = line[linep++];
406 17e5fb89 2004-04-21 devnull peekrune = c;
407 17e5fb89 2004-04-21 devnull return c;
411 17e5fb89 2004-04-21 devnull yyerror(char *fmt, ...)
413 17e5fb89 2004-04-21 devnull va_list arg;
416 17e5fb89 2004-04-21 devnull * hack to intercept message from yaccpar
418 17e5fb89 2004-04-21 devnull if(strcmp(fmt, "syntax error") == 0) {
419 17e5fb89 2004-04-21 devnull yyerror("syntax error, last name: %S", sym);
422 17e5fb89 2004-04-21 devnull va_start(arg, fmt);
423 17e5fb89 2004-04-21 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
424 17e5fb89 2004-04-21 devnull va_end(arg);
425 17e5fb89 2004-04-21 devnull print("%ld: %S\n\t%s\n", lineno, line, buf);
426 17e5fb89 2004-04-21 devnull nerrors++;
427 17e5fb89 2004-04-21 devnull if(nerrors > 5) {
428 17e5fb89 2004-04-21 devnull print("too many errors\n");
429 17e5fb89 2004-04-21 devnull exits("errors");
434 17e5fb89 2004-04-21 devnull add(Node *c, Node *a, Node *b)
436 17e5fb89 2004-04-21 devnull int i, d;
438 17e5fb89 2004-04-21 devnull for(i=0; i<Ndim; i++) {
439 17e5fb89 2004-04-21 devnull d = a->dim[i];
440 17e5fb89 2004-04-21 devnull c->dim[i] = d;
441 17e5fb89 2004-04-21 devnull if(d != b->dim[i])
442 17e5fb89 2004-04-21 devnull yyerror("add must be like units");
444 17e5fb89 2004-04-21 devnull c->val = fadd(a->val, b->val);
448 17e5fb89 2004-04-21 devnull sub(Node *c, Node *a, Node *b)
450 17e5fb89 2004-04-21 devnull int i, d;
452 17e5fb89 2004-04-21 devnull for(i=0; i<Ndim; i++) {
453 17e5fb89 2004-04-21 devnull d = a->dim[i];
454 17e5fb89 2004-04-21 devnull c->dim[i] = d;
455 17e5fb89 2004-04-21 devnull if(d != b->dim[i])
456 17e5fb89 2004-04-21 devnull yyerror("sub must be like units");
458 17e5fb89 2004-04-21 devnull c->val = fadd(a->val, -b->val);
462 17e5fb89 2004-04-21 devnull mul(Node *c, Node *a, Node *b)
466 17e5fb89 2004-04-21 devnull for(i=0; i<Ndim; i++)
467 17e5fb89 2004-04-21 devnull c->dim[i] = a->dim[i] + b->dim[i];
468 17e5fb89 2004-04-21 devnull c->val = fmul(a->val, b->val);
472 17e5fb89 2004-04-21 devnull div(Node *c, Node *a, Node *b)
476 17e5fb89 2004-04-21 devnull for(i=0; i<Ndim; i++)
477 17e5fb89 2004-04-21 devnull c->dim[i] = a->dim[i] - b->dim[i];
478 17e5fb89 2004-04-21 devnull c->val = fdiv(a->val, b->val);
482 17e5fb89 2004-04-21 devnull xpn(Node *c, Node *a, int b)
486 17e5fb89 2004-04-21 devnull *c = one;
487 17e5fb89 2004-04-21 devnull if(b < 0) {
489 17e5fb89 2004-04-21 devnull for(i=0; i<b; i++)
490 17e5fb89 2004-04-21 devnull div(c, c, a);
492 17e5fb89 2004-04-21 devnull for(i=0; i<b; i++)
493 17e5fb89 2004-04-21 devnull mul(c, c, a);
497 17e5fb89 2004-04-21 devnull specialcase(Node *c, Node *a, Node *b)
499 17e5fb89 2004-04-21 devnull int i, d, d1, d2;
503 17e5fb89 2004-04-21 devnull for(i=1; i<Ndim; i++) {
504 17e5fb89 2004-04-21 devnull d = a->dim[i];
506 17e5fb89 2004-04-21 devnull if(d != 1 || d1)
507 17e5fb89 2004-04-21 devnull return 0;
510 17e5fb89 2004-04-21 devnull d = b->dim[i];
512 17e5fb89 2004-04-21 devnull if(d != 1 || d2)
513 17e5fb89 2004-04-21 devnull return 0;
517 17e5fb89 2004-04-21 devnull if(d1 == 0 || d2 == 0)
518 17e5fb89 2004-04-21 devnull return 0;
520 17e5fb89 2004-04-21 devnull if(memcmp(fund[d1]->name, L"°C", 3*sizeof(Rune)) == 0 &&
521 17e5fb89 2004-04-21 devnull memcmp(fund[d2]->name, L"°F", 3*sizeof(Rune)) == 0 &&
522 17e5fb89 2004-04-21 devnull b->val == 1) {
523 17e5fb89 2004-04-21 devnull memcpy(c->dim, b->dim, sizeof(c->dim));
524 17e5fb89 2004-04-21 devnull c->val = a->val * 9. / 5. + 32.;
525 17e5fb89 2004-04-21 devnull return 1;
528 17e5fb89 2004-04-21 devnull if(memcmp(fund[d1]->name, L"°F", 3*sizeof(Rune)) == 0 &&
529 17e5fb89 2004-04-21 devnull memcmp(fund[d2]->name, L"°C", 3*sizeof(Rune)) == 0 &&
530 17e5fb89 2004-04-21 devnull b->val == 1) {
531 17e5fb89 2004-04-21 devnull memcpy(c->dim, b->dim, sizeof(c->dim));
532 17e5fb89 2004-04-21 devnull c->val = (a->val - 32.) * 5. / 9.;
533 17e5fb89 2004-04-21 devnull return 1;
535 17e5fb89 2004-04-21 devnull return 0;
539 17e5fb89 2004-04-21 devnull printdim(char *str, int d, int n)
544 17e5fb89 2004-04-21 devnull v = fund[d];
546 17e5fb89 2004-04-21 devnull sprint(strchr(str, 0), " %S", v->name);
548 17e5fb89 2004-04-21 devnull sprint(strchr(str, 0), " [%d]", d);
549 17e5fb89 2004-04-21 devnull switch(n) {
553 17e5fb89 2004-04-21 devnull strcat(str, "²");
556 17e5fb89 2004-04-21 devnull strcat(str, "³");
558 17e5fb89 2004-04-21 devnull default:
559 17e5fb89 2004-04-21 devnull sprint(strchr(str, 0), "^%d", n);
565 17e5fb89 2004-04-21 devnull Ufmt(Fmt *fp)
567 17e5fb89 2004-04-21 devnull char str[200];
568 17e5fb89 2004-04-21 devnull Node *n;
569 17e5fb89 2004-04-21 devnull int f, i, d;
571 17e5fb89 2004-04-21 devnull n = va_arg(fp->args, Node*);
572 17e5fb89 2004-04-21 devnull sprint(str, "%g", n->val);
575 17e5fb89 2004-04-21 devnull for(i=1; i<Ndim; i++) {
576 17e5fb89 2004-04-21 devnull d = n->dim[i];
577 17e5fb89 2004-04-21 devnull if(d > 0)
578 17e5fb89 2004-04-21 devnull printdim(str, i, d);
580 17e5fb89 2004-04-21 devnull if(d < 0)
585 17e5fb89 2004-04-21 devnull strcat(str, " /");
586 17e5fb89 2004-04-21 devnull for(i=1; i<Ndim; i++) {
587 17e5fb89 2004-04-21 devnull d = n->dim[i];
588 17e5fb89 2004-04-21 devnull if(d < 0)
589 17e5fb89 2004-04-21 devnull printdim(str, i, -d);
593 17e5fb89 2004-04-21 devnull return fmtstrcpy(fp, str);
597 17e5fb89 2004-04-21 devnull readline(void)
599 17e5fb89 2004-04-21 devnull int i, c;
601 17e5fb89 2004-04-21 devnull linep = 0;
602 17e5fb89 2004-04-21 devnull for(i=0;; i++) {
603 17e5fb89 2004-04-21 devnull c = Bgetrune(fi);
604 17e5fb89 2004-04-21 devnull if(c < 0)
605 17e5fb89 2004-04-21 devnull return 1;
606 17e5fb89 2004-04-21 devnull if(c == '\n')
608 17e5fb89 2004-04-21 devnull if(i < nelem(line))
609 17e5fb89 2004-04-21 devnull line[i] = c;
611 17e5fb89 2004-04-21 devnull if(i >= nelem(line))
612 17e5fb89 2004-04-21 devnull i = nelem(line)-1;
613 17e5fb89 2004-04-21 devnull line[i] = 0;
614 17e5fb89 2004-04-21 devnull return 0;
618 17e5fb89 2004-04-21 devnull lookup(int f)
621 17e5fb89 2004-04-21 devnull Var *v, *w;
622 17e5fb89 2004-04-21 devnull double p;
623 17e5fb89 2004-04-21 devnull ulong h;
626 17e5fb89 2004-04-21 devnull for(i=0; sym[i]; i++)
627 17e5fb89 2004-04-21 devnull h = h*13 + sym[i];
628 17e5fb89 2004-04-21 devnull h %= nelem(vars);
630 17e5fb89 2004-04-21 devnull for(v=vars[h]; v; v=v->link)
631 17e5fb89 2004-04-21 devnull if(memcmp(sym, v->name, sizeof(sym)) == 0)
632 17e5fb89 2004-04-21 devnull return v;
634 17e5fb89 2004-04-21 devnull return 0;
635 17e5fb89 2004-04-21 devnull v = malloc(sizeof(*v));
636 17e5fb89 2004-04-21 devnull if(v == nil) {
637 17e5fb89 2004-04-21 devnull fprint(2, "out of memory\n");
638 17e5fb89 2004-04-21 devnull exits("mem");
640 17e5fb89 2004-04-21 devnull memset(v, 0, sizeof(*v));
641 17e5fb89 2004-04-21 devnull memcpy(v->name, sym, sizeof(sym));
642 17e5fb89 2004-04-21 devnull v->link = vars[h];
643 17e5fb89 2004-04-21 devnull vars[h] = v;
646 17e5fb89 2004-04-21 devnull for(;;) {
647 17e5fb89 2004-04-21 devnull p = fmul(p, pname());
648 17e5fb89 2004-04-21 devnull if(p == 0)
650 17e5fb89 2004-04-21 devnull w = lookup(1);
652 17e5fb89 2004-04-21 devnull v->node = w->node;
653 17e5fb89 2004-04-21 devnull v->node.val = fmul(v->node.val, p);
657 17e5fb89 2004-04-21 devnull return v;
660 17e5fb89 2004-04-21 devnull Prefix prefix[] =
662 17e5fb89 2004-04-21 devnull 1e-24, "yocto", 0,
663 17e5fb89 2004-04-21 devnull 1e-21, "zepto", 0,
664 17e5fb89 2004-04-21 devnull 1e-18, "atto", 0,
665 17e5fb89 2004-04-21 devnull 1e-15, "femto", 0,
666 17e5fb89 2004-04-21 devnull 1e-12, "pico", 0,
667 17e5fb89 2004-04-21 devnull 1e-9, "nano", 0,
668 17e5fb89 2004-04-21 devnull 1e-6, "micro", 0,
669 17e5fb89 2004-04-21 devnull 1e-6, "μ", 0,
670 17e5fb89 2004-04-21 devnull 1e-3, "milli", 0,
671 17e5fb89 2004-04-21 devnull 1e-2, "centi", 0,
672 17e5fb89 2004-04-21 devnull 1e-1, "deci", 0,
673 17e5fb89 2004-04-21 devnull 1e1, "deka", 0,
674 17e5fb89 2004-04-21 devnull 1e2, "hecta", 0,
675 17e5fb89 2004-04-21 devnull 1e2, "hecto", 0,
676 17e5fb89 2004-04-21 devnull 1e3, "kilo", 0,
677 17e5fb89 2004-04-21 devnull 1e6, "mega", 0,
678 17e5fb89 2004-04-21 devnull 1e6, "meg", 0,
679 17e5fb89 2004-04-21 devnull 1e9, "giga", 0,
680 17e5fb89 2004-04-21 devnull 1e12, "tera", 0,
681 17e5fb89 2004-04-21 devnull 1e15, "peta", 0,
682 17e5fb89 2004-04-21 devnull 1e18, "exa", 0,
683 17e5fb89 2004-04-21 devnull 1e21, "zetta", 0,
684 17e5fb89 2004-04-21 devnull 1e24, "yotta", 0,
685 17e5fb89 2004-04-21 devnull 0, 0, 0,
689 17e5fb89 2004-04-21 devnull pname(void)
691 17e5fb89 2004-04-21 devnull Rune *p;
692 17e5fb89 2004-04-21 devnull int i, j, c;
695 17e5fb89 2004-04-21 devnull * rip off normal prefixs
697 17e5fb89 2004-04-21 devnull if(prefix[0].pname == nil){
698 17e5fb89 2004-04-21 devnull for(i=0; prefix[i].name; i++)
699 17e5fb89 2004-04-21 devnull prefix[i].pname = runesmprint("%s", prefix[i].name);
702 17e5fb89 2004-04-21 devnull for(i=0; p=prefix[i].pname; i++) {
703 17e5fb89 2004-04-21 devnull for(j=0; c=p[j]; j++)
704 17e5fb89 2004-04-21 devnull if(c != sym[j])
705 17e5fb89 2004-04-21 devnull goto no;
706 17e5fb89 2004-04-21 devnull memmove(sym, sym+j, (Nsym-j)*sizeof(*sym));
707 17e5fb89 2004-04-21 devnull memset(sym+(Nsym-j), 0, j*sizeof(*sym));
708 17e5fb89 2004-04-21 devnull return prefix[i].val;
713 17e5fb89 2004-04-21 devnull * rip off 's' suffixes
715 17e5fb89 2004-04-21 devnull for(j=0; sym[j]; j++)
718 17e5fb89 2004-04-21 devnull /* j>1 is special hack to disallow ms finding m */
719 17e5fb89 2004-04-21 devnull if(j > 1 && sym[j] == 's') {
720 17e5fb89 2004-04-21 devnull sym[j] = 0;
721 17e5fb89 2004-04-21 devnull return 1;
723 17e5fb89 2004-04-21 devnull return 0;
727 17e5fb89 2004-04-21 devnull * careful floating point
730 17e5fb89 2004-04-21 devnull fmul(double a, double b)
732 17e5fb89 2004-04-21 devnull double l;
734 17e5fb89 2004-04-21 devnull if(a <= 0) {
735 17e5fb89 2004-04-21 devnull if(a == 0)
736 17e5fb89 2004-04-21 devnull return 0;
737 17e5fb89 2004-04-21 devnull l = log(-a);
739 17e5fb89 2004-04-21 devnull l = log(a);
741 17e5fb89 2004-04-21 devnull if(b <= 0) {
742 17e5fb89 2004-04-21 devnull if(b == 0)
743 17e5fb89 2004-04-21 devnull return 0;
744 17e5fb89 2004-04-21 devnull l += log(-b);
746 17e5fb89 2004-04-21 devnull l += log(b);
748 17e5fb89 2004-04-21 devnull if(l > Maxe) {
749 17e5fb89 2004-04-21 devnull yyerror("overflow in multiply");
750 17e5fb89 2004-04-21 devnull return 1;
752 17e5fb89 2004-04-21 devnull if(l < -Maxe) {
753 17e5fb89 2004-04-21 devnull yyerror("underflow in multiply");
754 17e5fb89 2004-04-21 devnull return 0;
756 17e5fb89 2004-04-21 devnull return a*b;
760 17e5fb89 2004-04-21 devnull fdiv(double a, double b)
762 17e5fb89 2004-04-21 devnull double l;
764 17e5fb89 2004-04-21 devnull if(a <= 0) {
765 17e5fb89 2004-04-21 devnull if(a == 0)
766 17e5fb89 2004-04-21 devnull return 0;
767 17e5fb89 2004-04-21 devnull l = log(-a);
769 17e5fb89 2004-04-21 devnull l = log(a);
771 17e5fb89 2004-04-21 devnull if(b <= 0) {
772 17e5fb89 2004-04-21 devnull if(b == 0) {
773 17e5fb89 2004-04-21 devnull yyerror("division by zero");
774 17e5fb89 2004-04-21 devnull return 1;
776 17e5fb89 2004-04-21 devnull l -= log(-b);
778 17e5fb89 2004-04-21 devnull l -= log(b);
780 17e5fb89 2004-04-21 devnull if(l > Maxe) {
781 17e5fb89 2004-04-21 devnull yyerror("overflow in divide");
782 17e5fb89 2004-04-21 devnull return 1;
784 17e5fb89 2004-04-21 devnull if(l < -Maxe) {
785 17e5fb89 2004-04-21 devnull yyerror("underflow in divide");
786 17e5fb89 2004-04-21 devnull return 0;
788 17e5fb89 2004-04-21 devnull return a/b;
792 17e5fb89 2004-04-21 devnull fadd(double a, double b)
794 17e5fb89 2004-04-21 devnull return a + b;