8 Ndim = 15, /* number of dimensions */
9 Nsym = 40, /* size of a name */
10 Nvar = 203, /* hash table size */
11 Maxe = 695, /* log of largest number */
14 typedef struct Var Var;
15 typedef struct Node Node;
16 typedef struct Prefix Prefix;
53 extern void add(Node*, Node*, Node*);
54 extern void div(Node*, Node*, Node*);
55 extern int specialcase(Node*, Node*, Node*);
56 extern double fadd(double, double);
57 extern double fdiv(double, double);
58 extern double fmul(double, double);
59 extern int gdigit(void*);
60 extern Var* lookup(int);
61 extern void main(int, char*[]);
62 extern void mul(Node*, Node*, Node*);
63 extern void ofile(void);
64 extern double pname(void);
65 extern void printdim(char*, int, int);
66 extern int ralpha(int);
67 extern int readline(void);
68 extern void sub(Node*, Node*, Node*);
69 extern int Ufmt(Fmt*);
70 extern void xpn(Node*, Node*, int);
71 extern void yyerror(char*, ...);
72 extern int yylex(void);
73 extern int yyparse(void);
75 typedef Node* indnode;
76 #pragma varargck type "U" indnode
87 %type <node> prog expr expr0 expr1 expr2 expr3 expr4
102 yyerror("redefinition of %S", $2->name);
105 print("%S\t%U\n", $2->name, &$2->node);
111 for(i=1; i<Ndim; i++)
115 yyerror("too many dimensions");
125 yyerror("redefinition of %S", $2->name);
128 print("%S\t#\n", $2->name);
178 for(i=1; i<Ndim; i++)
180 yyerror("exponent has units");
187 yyerror("exponent not integral");
202 if($1->node.dim[0] == 0) {
203 yyerror("undefined %S", $1->name);
228 if((c >= '0' && c <= '9') || c == '.')
257 memset(sym, 0, sizeof(sym));
265 sym[nelem(sym)-1] = 0;
267 yylval.var = lookup(0);
272 yylval.val = charstod(gdigit, 0);
277 main(int argc, char *argv[])
283 print("usage: units [-v] [file]\n");
293 fi = Bopen(file, OREAD);
295 print("cant open: %s\n", file);
298 fmtinstall('U', Ufmt);
302 * read the 'units' file to
303 * develope a database
310 if(line[0] == 0 || line[0] == '/')
317 * read the console to
318 * print ratio of pairs
337 if(specialcase(&retnode, &retnode2, &retnode1))
338 print("\tis %U\n", &retnode);
340 div(&retnode, &retnode2, &retnode1);
341 print("\t* %U\n", &retnode);
342 div(&retnode, &retnode1, &retnode2);
343 print("\t/ %U\n", &retnode);
354 * all characters that have some
355 * meaning. rest are usable as names
407 yyerror(char *fmt, ...)
412 * hack to intercept message from yaccpar
414 if(strcmp(fmt, "syntax error") == 0) {
415 yyerror("syntax error, last name: %S", sym);
419 vseprint(buf, buf+sizeof(buf), fmt, arg);
421 print("%ld: %S\n\t%s\n", lineno, line, buf);
424 print("too many errors\n");
430 add(Node *c, Node *a, Node *b)
434 for(i=0; i<Ndim; i++) {
438 yyerror("add must be like units");
440 c->val = fadd(a->val, b->val);
444 sub(Node *c, Node *a, Node *b)
448 for(i=0; i<Ndim; i++) {
452 yyerror("sub must be like units");
454 c->val = fadd(a->val, -b->val);
458 mul(Node *c, Node *a, Node *b)
462 for(i=0; i<Ndim; i++)
463 c->dim[i] = a->dim[i] + b->dim[i];
464 c->val = fmul(a->val, b->val);
468 div(Node *c, Node *a, Node *b)
472 for(i=0; i<Ndim; i++)
473 c->dim[i] = a->dim[i] - b->dim[i];
474 c->val = fdiv(a->val, b->val);
478 xpn(Node *c, Node *a, int b)
493 specialcase(Node *c, Node *a, Node *b)
499 for(i=1; i<Ndim; i++) {
513 if(d1 == 0 || d2 == 0)
516 if(memcmp(fund[d1]->name, L"°C", 3*sizeof(Rune)) == 0 &&
517 memcmp(fund[d2]->name, L"°F", 3*sizeof(Rune)) == 0 &&
519 memcpy(c->dim, b->dim, sizeof(c->dim));
520 c->val = a->val * 9. / 5. + 32.;
524 if(memcmp(fund[d1]->name, L"°F", 3*sizeof(Rune)) == 0 &&
525 memcmp(fund[d2]->name, L"°C", 3*sizeof(Rune)) == 0 &&
527 memcpy(c->dim, b->dim, sizeof(c->dim));
528 c->val = (a->val - 32.) * 5. / 9.;
535 printdim(char *str, int d, int n)
542 sprint(strchr(str, 0), " %S", v->name);
544 sprint(strchr(str, 0), " [%d]", d);
555 sprint(strchr(str, 0), "^%d", n);
567 n = va_arg(fp->args, Node*);
568 sprint(str, "%g", n->val);
571 for(i=1; i<Ndim; i++) {
582 for(i=1; i<Ndim; i++) {
585 printdim(str, i, -d);
589 return fmtstrcpy(fp, str);
622 for(i=0; sym[i]; i++)
626 for(v=vars[h]; v; v=v->link)
627 if(memcmp(sym, v->name, sizeof(sym)) == 0)
631 v = malloc(sizeof(*v));
633 fprint(2, "out of memory\n");
636 memset(v, 0, sizeof(*v));
637 memcpy(v->name, sym, sizeof(sym));
643 p = fmul(p, pname());
649 v->node.val = fmul(v->node.val, p);
691 * rip off normal prefixs
693 for(i=0; p=prefix[i].pname; i++) {
694 for(j=0; c=p[j]; j++)
697 memmove(sym, sym+j, (Nsym-j)*sizeof(*sym));
698 memset(sym+(Nsym-j), 0, j*sizeof(*sym));
699 return prefix[i].val;
704 * rip off 's' suffixes
706 for(j=0; sym[j]; j++)
709 /* j>1 is special hack to disallow ms finding m */
710 if(j > 1 && sym[j] == 's') {
718 * careful floating point
721 fmul(double a, double b)
740 yyerror("overflow in multiply");
744 yyerror("underflow in multiply");
751 fdiv(double a, double b)
764 yyerror("division by zero");
772 yyerror("overflow in divide");
776 yyerror("underflow in divide");
783 fadd(double a, double b)