orig rh72
[nethome.git] / src / ev.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <assert.h>
5
6 #define NDEBUG
7
8 #define BUFSIZE 1024
9
10 #define bail(arg...) do { fprintf(stderr, ##arg); exit(EXIT_FAILURE); } while (0)
11
12 char *arg;
13
14 int istack[BUFSIZE];
15 char opstack[BUFSIZE];
16 int istackp,opstackp;
17
18 #ifdef NDEBUG
19 #define dump(x)
20 #else
21 static void dump(char *pref)
22 {
23 int i;
24         fprintf(stderr,"%s: i[",pref);
25         for (i=0;i<istackp;i++) {
26                 if (i) fputc(',',stderr);
27                 fprintf(stderr,"%d",istack[i]);
28                 }
29         fprintf(stderr,"],op=[");
30         for (i=0;i<opstackp;i++) fputc(opstack[i],stderr);
31         fprintf(stderr,"]\n");
32 }
33 #endif
34
35 static char lex(int *ip)
36 {
37 char c;
38 long l;
39
40         while (isspace(*arg)) arg++;
41         switch (*arg) {
42                 case 0: case '+': case '-': case '*': case '/': case '(': case ')':
43                         c=*arg;
44                         if (c) arg++;
45                         return(c);
46                 case '0' ... '9':
47                         l=strtol(arg,&arg,10);
48                         *ip=l;
49                         return 'n';
50                 default:
51                         bail("Invalid characted in string: %s\n",arg);
52                 }
53 }
54
55 static int oppri(char op)
56 {
57         switch (op) {
58                 case 0: return(0);
59                 case '+': case '-': return (10);
60                 case '*': case '/': return (20);
61                 case '(': return (2);
62                 case ')': return (5);
63                 default: assert(0);
64                 }
65 }
66
67 static void evalit(void)
68 {
69         dump("evalit()");
70         assert(opstackp); opstackp--;
71         if (istackp<2) 
72                 if (opstack[opstackp]!='(') bail("2 arguments for operator '%c' required!\n",opstack[opstackp]);
73                 else bail("Stray '('!\n");
74         istackp--;
75         switch (opstack[opstackp]) {
76                 case '+': istack[istackp-1]+=istack[istackp]; break;
77                 case '-': istack[istackp-1]-=istack[istackp]; break;
78                 case '*': istack[istackp-1]*=istack[istackp]; break;
79                 case '/': 
80                         if (!istack[istackp]) bail("Division of %d by zero not supported!\n",istack[istackp-1]);
81                         istack[istackp-1]/=istack[istackp];
82                         break;
83                 }
84 }
85
86 static void pushop(char op)
87 {
88 int mypri=oppri(op);
89         while (opstackp && op!='(' && oppri(opstack[opstackp-1])>=mypri)
90                 evalit();
91         if (!op) return;
92         if (op==')') {
93                 if (!opstackp || opstack[opstackp-1]!='(')
94                         bail("Not enough content for brackets-inside space!\n");
95                 opstackp--;
96                 return;
97                 }
98         if (opstackp>=BUFSIZE) bail("Too many operators (%d is max)!\n",BUFSIZE);
99         opstack[opstackp++]=op;
100 }
101
102 static void process(void)
103 {
104 char lastop,op;
105 int curi;
106
107         istackp=opstackp=0;
108         for (lastop=0;;lastop=op) switch (op=lex(&curi)) {
109                 case 'n':
110                         if (lastop=='n') bail("Two successive numbers not permitted!\n");
111                         if (istackp>=BUFSIZE) bail("Too many operators (%d is max)!\n",BUFSIZE);
112                         istack[istackp++]=curi;
113                         break;
114                 case '(':
115                         if (lastop=='n') bail("Open-bracket not permitted after number!\n");
116                         pushop(op);
117                         break;
118                 case '+': case '-': case '*': case '/': case ')': pushop(op); break;
119                 case 0:
120                         pushop(op);
121                         if (istackp!=1||opstackp)
122                                 bail("Machine not in sane state on the end of expression, ints=%d,ops=%d!\n",istackp,opstackp);
123                         printf("%d\n",istack[0]);
124                         return;
125                 default: assert(0);
126                 }
127 }
128
129 int main(int argc,char **argv)
130 {
131 int argn;
132         for (argn=1;argn<argc;argn++) {
133                 arg=argv[argn];
134                 process();
135                 }
136         return(EXIT_SUCCESS);
137 }