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 == '.')
272 memset(sym, 0, sizeof(sym));
280 sym[nelem(sym)-1] = 0;
282 yylval.var = lookup(0);
287 yylval.val = charstod(gdigit, 0);
292 main(int argc, char *argv[])
298 print("usage: units [-v] [file]\n");
308 fi = Bopen(file, OREAD);
310 print("cant open: %s\n", file);
313 fmtinstall('U', Ufmt);
317 * read the 'units' file to
318 * develope a database
325 if(line[0] == 0 || line[0] == '/')
332 * read the console to
333 * print ratio of pairs
352 if(specialcase(&retnode, &retnode2, &retnode1))
353 print("\tis %U\n", &retnode);
355 div(&retnode, &retnode2, &retnode1);
356 print("\t* %U\n", &retnode);
357 div(&retnode, &retnode1, &retnode2);
358 print("\t/ %U\n", &retnode);
369 * all characters that have some
370 * meaning. rest are usable as names
425 yyerror(char *fmt, ...)
430 * hack to intercept message from yaccpar
432 if(strcmp(fmt, "syntax error") == 0) {
433 yyerror("syntax error, last name: %S", sym);
437 vseprint(buf, buf+sizeof(buf), fmt, arg);
439 print("%ld: %S\n\t%s\n", lineno, line, buf);
442 print("too many errors\n");
448 add(Node *c, Node *a, Node *b)
452 for(i=0; i<Ndim; i++) {
456 yyerror("add must be like units");
458 c->val = fadd(a->val, b->val);
462 sub(Node *c, Node *a, Node *b)
466 for(i=0; i<Ndim; i++) {
470 yyerror("sub must be like units");
472 c->val = fadd(a->val, -b->val);
476 mul(Node *c, Node *a, Node *b)
480 for(i=0; i<Ndim; i++)
481 c->dim[i] = a->dim[i] + b->dim[i];
482 c->val = fmul(a->val, b->val);
486 div(Node *c, Node *a, Node *b)
490 for(i=0; i<Ndim; i++)
491 c->dim[i] = a->dim[i] - b->dim[i];
492 c->val = fdiv(a->val, b->val);
496 xpn(Node *c, Node *a, int b)
511 specialcase(Node *c, Node *a, Node *b)
517 for(i=1; i<Ndim; i++) {
531 if(d1 == 0 || d2 == 0)
534 if(memcmp(fund[d1]->name, L"°C", 3*sizeof(Rune)) == 0 &&
535 memcmp(fund[d2]->name, L"°F", 3*sizeof(Rune)) == 0 &&
537 memcpy(c->dim, b->dim, sizeof(c->dim));
538 c->val = a->val * 9. / 5. + 32.;
542 if(memcmp(fund[d1]->name, L"°F", 3*sizeof(Rune)) == 0 &&
543 memcmp(fund[d2]->name, L"°C", 3*sizeof(Rune)) == 0 &&
545 memcpy(c->dim, b->dim, sizeof(c->dim));
546 c->val = (a->val - 32.) * 5. / 9.;
553 printdim(char *str, int d, int n)
560 sprint(strchr(str, 0), " %S", v->name);
562 sprint(strchr(str, 0), " [%d]", d);
591 sprint(strchr(str, 0), "^%d", n);
603 n = va_arg(fp->args, Node*);
604 sprint(str, "%g", n->val);
607 for(i=1; i<Ndim; i++) {
618 for(i=1; i<Ndim; i++) {
621 printdim(str, i, -d);
625 return fmtstrcpy(fp, str);
658 for(i=0; sym[i]; i++)
662 for(v=vars[h]; v; v=v->link)
663 if(memcmp(sym, v->name, sizeof(sym)) == 0)
667 v = malloc(sizeof(*v));
669 fprint(2, "out of memory\n");
672 memset(v, 0, sizeof(*v));
673 memcpy(v->name, sym, sizeof(sym));
679 p = fmul(p, pname());
685 v->node.val = fmul(v->node.val, p);
727 * rip off normal prefixs
729 for(i=0; p=prefix[i].pname; i++) {
730 for(j=0; c=p[j]; j++)
733 memmove(sym, sym+j, (Nsym-j)*sizeof(*sym));
734 memset(sym+(Nsym-j), 0, j*sizeof(*sym));
735 return prefix[i].val;
740 * rip off 's' suffixes
742 for(j=0; sym[j]; j++)
745 /* j>1 is special hack to disallow ms finding m */
746 if(j > 1 && sym[j] == 's') {
754 * careful floating point
757 fmul(double a, double b)
776 yyerror("overflow in multiply");
780 yyerror("underflow in multiply");
787 fdiv(double a, double b)
800 yyerror("division by zero");
808 yyerror("overflow in divide");
812 yyerror("underflow in divide");
819 fadd(double a, double b)