git @ Cat's Eye Technologies Maentwrog / 0fb8cbe
Initial import of Maentwrog version 1.0 revision 2007.0930 sources. Cat's Eye Technologies 10 years ago
4 changed file(s) with 1493 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 #include <stdio.h>
1 #include <string.h>
2 #include <ctype.h>
3
4 /*
5 * caparse.c
6 *
7 * cellular automata parser handles 1-character values and operators :
8 *
9 * not !
10 * or |
11 * and &
12 * xor ^
13 * values a, b, c, ... z
14 * parenthesis (, )
15 */
16
17 #define OP_OR 0
18 #define OP_AND 1
19 #define OP_XOR 2
20
21 int caparse(char *string, int values[]);
22 int doper(int state, int oper, int modder);
23
24 main()
25 {
26 int values[26] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0, 0, 0 };
28 char in[255];
29
30 while (!feof(stdin))
31 {
32 gets(in);
33 if (isalpha(in[0])&&in[1]=='=')
34 values[in[0]-'a']=(in[2]-'0');
35 else
36 printf("%d\n", caparse(in, values));
37 }
38
39 }
40
41 int caparse(char *string, int values[])
42 {
43
44 #define sp string[pos]
45
46 int negate = 0;
47 int state = 0;
48 int oper = OP_OR;
49 int pos = 0;
50
51 for (;((sp) && (sp != ')'));pos++)
52 {
53 if (isalpha(sp))
54 {
55 state = doper(state, oper, negate ? !values[sp-'a'] : values[sp-'a']);
56 negate = 0;
57 } else
58 switch (sp)
59 {
60 case '|' : oper = OP_OR; break;
61 case '&' : oper = OP_AND; break;
62 case '^' : oper = OP_XOR; break;
63 case '!' : negate = 1; break;
64 case '(' : pos++;
65 state = doper(state, oper,
66 negate ? !caparse(&sp, values) :
67 caparse(&sp, values));
68 {
69 int bra = 1;
70 while (bra)
71 {
72 if (sp=='(') bra++;
73 if (sp==')') bra--;
74 printf("%d\n", bra);
75 if (bra) pos++;
76 }
77 }
78 break;
79 default : break;
80 }
81 }
82 return state;
83 }
84
85 int doper(int state, int oper, int modder)
86 {
87 switch (oper)
88 {
89 case OP_OR : return(state | modder); break;
90 case OP_AND : return(state & modder); break;
91 case OP_XOR : return(state ^ modder); break;
92 }
93 }
94
0 /*
1 * maentw.c
2 *
3 * Maentwrog (RPN calculator & simple interpreted language)
4 * - derived from rpn, Aug 1993 Chris Pressey
5 * - updated Jul 1997 Chris Pressey, fixed minor bugs
6 * - updated Jul 1998 Chris Pressey, fixed more minor bugs
7 * - and ANSI C-ized: now case sensitive
8 * Usage : maentw maentw-expressions executes and exits
9 * maentw goes into interactive mode
10 * maentw <maentwrog-file runs file through maentw
11 *
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <alloc.h>
17 #include <string.h>
18 #include <ctype.h>
19
20 #define DEFSIZE 1024
21
22 struct stack /* stack structure, for values on stack */
23 {
24 signed long val;
25 struct stack *next;
26 } *head; /* head of stack */
27
28 struct word /* word structure, for words (pre- and user- */
29 { /* defined) */
30 char name[80]; /* name of word */
31 char *macro; /* macro (user-defined; only executed if
32 * fcn==0) */
33 int fcn; /* built-in fcn or 0 for user-defined fcn */
34 struct word *next;
35 } *whead; /* head of words */
36
37 struct vari /* variable structure, for variables */
38 {
39 char name[80]; /* name of variable */
40 signed long value; /* values of variable (signed longs only) */
41 struct vari *next;
42 } *vhead; /* head of variables */
43
44 int debug=0;
45
46 /* prototypes */
47
48 /* word-handling */
49 struct word *addword(char *name, char *macro, int fcn);
50 struct word *lookup(char *name);
51 void initwords(void);
52 void makeword(void);
53
54 /* variable-handling */
55 struct vari *addvari(char *name);
56 struct vari *getvari(char *name);
57 void setvari(char *name, signed long value);
58
59 /* stack-handling */
60 void push(signed long val);
61 signed long pop(void);
62
63 /* functions */
64 void dofunc(struct word * w);
65 void words(void);
66 void vars(void);
67 signed long sizestack(void);
68
69 /* parsing and interpreting */
70 void process(char *s);
71 void procstr(char *s);
72
73 char * strdup(char * s)
74 {
75 char * t;
76 t = (char *)malloc(strlen(s) * sizeof(char));
77 strcpy(t, s);
78 return t;
79 }
80
81 int main(argc, argv)
82 int argc;
83 char **argv;
84 {
85 char s[80];
86 int i;
87
88 head = NULL; /* init */
89 whead = NULL;
90 vhead = NULL;
91 initwords();
92 if (argc != 1)
93 {
94 for(i=2;i<=argc;i++) procstr(argv[i-1]);
95 exit(0);
96 }
97 scanf("%s", s); /* process commands/values from stdin */
98 while (!feof(stdin))
99 {
100 process(s);
101 scanf("%s", s);
102 }
103 return 0;
104 }
105
106 /*
107 * processes the word in s according to parsing rules.
108 *
109 * if word starts with a digit or a -digit, it is converted to a float and put
110 * on the stack.
111 *
112 * if word starts with a = then the variable following equals is assigned the
113 * last value popped off the stack.
114 *
115 * if word starts with a * a variable is defined using that word.
116 *
117 * if word starts with a @, the stack is popped, is checked for the boolean
118 * value, and if true, executes it. (if.)
119 *
120 * if word starts with a $, the stack is popped, and command is repeated
121 * that number of times.
122 *
123 * if word starts with a [, the stack is popped, is checked for the boolean
124 * value, and if true, executes it. Then goes back and pops the stack
125 * again (while.)
126 *
127 * if word is in words list, that function is executed.
128 *
129 * if word is in variables list, the value of it is pushed onto the stack.
130 *
131 * otherwise generates an error.
132 */
133 void process(char *s)
134 {
135 struct word *w;
136 struct vari *v;
137 int i;
138
139 if(debug) printf("%s ", s);
140
141 if (isdigit(s[0]) || ((s[0] == '-') && (isdigit(s[1]))))
142 push(atoi(s));
143 else if (s[0] == '=')
144 setvari(s + 1, pop());
145 else if ((s[0] == '*') && (isalpha(s[1])))
146 addvari(s + 1);
147 else if (s[0] == '@')
148 {
149 if (pop())
150 if (w = lookup(s + 1))
151 dofunc(w);
152 }
153 else if (s[0] == '$')
154 {
155 for(i=pop();i;i--)
156 if (w = lookup(s + 1))
157 dofunc(w);
158 }
159 else if (s[0] == '[')
160 {
161 for(;;)
162 {
163 if (pop())
164 {
165 if (w = lookup(s + 1))
166 dofunc(w);
167 } else break;
168 }
169 }
170 else if (w = lookup(s))
171 dofunc(w);
172 else if (v = getvari(s))
173 push(v->value);
174 else
175 printf("unknown command '%s'\n", s);
176 }
177
178 /*
179 * processes each word in the string s.
180 * strtok doesn't work with recursion :-(
181 */
182 void procstr(char *s)
183 {
184 char *h=strdup(s);
185 char *g, *gg;
186 g = h;
187
188 for (;;)
189 {
190 gg = g;
191 while (!isspace(gg[0])&&gg[0])
192 gg++;
193 if (!gg[0])
194 break;
195 gg[0] = 0;
196
197 process(g);
198
199 gg[0] = ' ';
200 g = gg;
201 while (isspace(g[0])&&g[0])
202 g++;
203 }
204
205 free(h); /* called with strdup(), so we must free */
206 }
207
208 /*
209 * adds a unique word to the list of words.
210 */
211 struct word *addword(char *name, char *macro, int fcn)
212 {
213 struct word *new;
214 for (new = whead; new; new = new->next)
215 if (!strcmp(new->name, name))
216 {
217 printf("already exists\n");
218 return NULL;
219 }
220 new = (struct word *) malloc(sizeof(struct word));
221 strcpy(new->name, name);
222 new->macro = strdup(macro);
223 new->fcn = fcn;
224
225 new->next = whead;
226 whead = new;
227 return new;
228 }
229
230 /*
231 * attempts to find the word 'name' in the words list. returns NULL if it
232 * could not be found.
233 */
234 struct word *lookup(char *name)
235 {
236 struct word *l = whead;
237 struct word *k = NULL;
238
239 while (l)
240 {
241 if (!strcmp(name, l->name))
242 {
243 k = l;
244 l = NULL;
245 } else
246 l = l->next;
247 }
248 return (k);
249 }
250
251 /*
252 * initialize the words list with all the built-in words.
253 */
254 void initwords()
255 {
256 addword("bye", "", 200);
257 addword("rem", "", 199);
258 addword("debug", "", 198);
259 addword("vars", "", 101);
260 addword("words", "", 100);
261
262 addword("free", "", 91);
263 addword("alloc", "", 90);
264
265 addword(";", "", 81);
266 addword(":", "", 80);
267
268 addword("size", "", 50);
269 addword("dup", "", 51);
270 addword("swap", "", 52);
271 addword("pop", "", 53);
272
273 addword("get", "", 45);
274 addword("put", "", 44);
275
276 addword("rnd", "", 40);
277
278 addword(">", "", 22);
279 addword("<", "", 21);
280 addword("==", "", 20);
281
282 addword(".", "", 1);
283 addword("..", "", 6);
284
285 addword("mod", "", 30);
286
287 addword("/", "", 5);
288 addword("*", "", 4);
289 addword("-", "", 3);
290 addword("+", "", 2);
291 }
292
293 /*
294 * makes a word, reading between the : and ;, defining the new word's macro,
295 * and adds it.
296 */
297 void makeword()
298 {
299 char s[80];
300 char t[80];
301 char *y;
302 int size = DEFSIZE;
303
304 y = (char *)malloc(size);
305 scanf("%s", s);
306 strcpy(y, "");
307 scanf("%s", t);
308 while (strcmp(t, ";"))
309 {
310 if ((strlen(y)+strlen(t))>size)
311 {
312 printf("out of memory\n");
313 exit(0);
314 }
315 strcat(y, t);
316 strcat(y, " ");
317 scanf("%s", t);
318 }
319 {
320 char *n = (char *)malloc(strlen(y)+1);
321 /* printf("(usage : %d bytes)\n", strlen(y)+1); */
322 strcpy(n, y);
323 free(y);
324 y = n;
325 }
326 addword(s, y, 0);
327 }
328
329 /*
330 * pushes a value onto the stack.
331 */
332 void push(signed long val)
333 {
334 struct stack *s;
335 s = (struct stack *) malloc(sizeof(struct stack));
336 s->val = val;
337 s->next = head;
338 head = s;
339 }
340
341 /*
342 * pops a value off the stack. generates error and returns 0.0 in case of
343 * underflow.
344 */
345 signed long pop()
346 {
347 signed long v;
348 struct stack *s = head;
349 if (s)
350 {
351 v = head->val;
352 head = head->next;
353 free(s);
354 return v;
355 } else
356 {
357 printf("stack underflow\n");
358 return 0;
359 }
360 }
361
362 /*
363 * adds a unique variable to the vari list.
364 */
365 struct vari *addvari(char *name)
366 {
367 struct vari *v;
368 for (v = vhead; v; v = v->next)
369 if (!strcmp(v->name, name))
370 {
371 printf("already exists\n");
372 return NULL;
373 }
374 v = (struct vari *) malloc(sizeof(struct vari));
375 strcpy(v->name, name);
376 v->next = vhead;
377 vhead = v;
378 return v;
379 }
380
381 /*
382 * gets the value of a variable off the variable list.
383 */
384 struct vari *getvari(char *name)
385 {
386 struct vari *l = vhead;
387 struct vari *k = NULL;
388
389 while (l)
390 {
391 if (!strcmp(name, l->name))
392 {
393 k = l;
394 l = NULL;
395 } else
396 l = l->next;
397 }
398 return (k);
399 }
400
401 /*
402 * sets the value of a variable
403 */
404 void setvari(char *name, signed long value)
405 {
406 struct vari *l = vhead;
407 while (l)
408 {
409 if (!strcmp(name, l->name))
410 {
411 l->value = value;
412 l = NULL;
413 } else
414 l = l->next;
415 }
416 }
417
418 /*
419 * lists all words in mw's words list
420 */
421 void words()
422 {
423 struct word *w;
424 for (w = whead; w; w = w->next)
425 printf("%s ", w->name);
426 printf("\n");
427 }
428
429 signed long sizestack()
430 {
431 signed long total = 0;
432 struct stack *s = head;
433
434 while(s)
435 {
436 total++;
437 s=s->next;
438 }
439 return total;
440 }
441
442 /*
443 * list all variables in mw's vari list
444 */
445 void vars()
446 {
447 struct vari *v;
448 for (v = vhead; v; v = v->next)
449 printf("%-16s %ld\n", v->name, v->value);
450 }
451
452 /*
453 * execute function of a word. if w->fcn is 0, it will run processtr on the
454 * word. otherwise, a built-in function will be called. see the rpn
455 * documentation on built-in functions.
456 */
457 void dofunc(struct word * w)
458 {
459 signed long a, b;
460 signed long *ax;
461 switch (w->fcn)
462 {
463 case 1: /* output (.) */
464 printf("%ld\n", pop());
465 break;
466 case 2: /* add (+) */
467 push(pop() + pop());
468 break;
469 case 3: /* subtract (-) */
470 a = pop();
471 b = pop();
472 push(b - a);
473 break;
474 case 4: /* multiply (*) */
475 push(pop() * pop());
476 break;
477 case 5: /* divide (/) */
478 a = pop();
479 b = pop();
480 push(b / a);
481 break;
482 case 6: /* output ASCII (..) */
483 printf("%c", (char)pop());
484 break;
485 case 20:
486 push(!pop() == !pop());
487 break;
488 case 21:
489 push(pop()>pop());
490 break;
491 case 22:
492 push(pop()<pop());
493 break;
494 case 30:
495 a = pop();
496 b = pop();
497 push(b % a);
498 break;
499 case 40:
500 push(a); /* something random */
501 break;
502 case 44: /* put */
503 a = pop();
504 b = pop();
505 if (b % 4)
506 printf("must be longword boundary\n"); else
507 {
508 ax = (signed long *)b;
509 *ax = a;
510 }
511 break;
512 case 45:
513 a = pop();
514 if (a % 4)
515 printf("must be longword boundary\n"); else
516 {
517 ax = (signed long *)a;
518 push(*ax);
519 }
520 break;
521 case 50:
522 push(sizestack()); /* size of stack (size) */
523 break;
524 case 51: /* duplicate top element (dup) */
525 a = pop();
526 push(a); push (a); break;
527 case 52: /* swap top elements (swap) */
528 a = pop();
529 b = pop();
530 push(a); push (b);
531 break;
532 case 53: /* pop element (pop) */
533 pop();
534 break;
535 case 80: /* define word (: ... ;) */
536 makeword();
537 break;
538 case 81: /* null (;) */
539 break;
540 case 90:
541 a = pop();
542 push((signed long)malloc(a*sizeof(signed long)));
543 break;
544 case 91:
545 free((void *)pop());
546 break;
547 case 100: /* list known words (words) */
548 words();
549 break;
550 case 101: /* list variables (vars) */
551 vars();
552 break;
553 case 198:
554 debug = 1;
555 break;
556 case 199: /* rem */
557 {
558 char t[80];
559 scanf("%s", t);
560 while (strcmp(t, ";"))
561 scanf("%s", t);
562 }
563 break;
564 case 200: /* exit mw (bye) */
565 exit(0);
566 break;
567 default: /* user-defined word */
568 procstr(w->macro);
569 }
570 }
0 /*
1
2 rdp.c
3
4 a recursive decent parser (origins now lost, sorry)
5
6 Chris Pressey, March, like, 7th, 1994
7
8 This program is by no means complete, but it's as far as I'll
9 go in the general case. It should be no problem adapting it
10 to do all sorts of really demented things.
11
12 */
13
14 #define THIS_PROGRAM_IS_NOT_REALLY_AS_CRAPPY_AS_YOU_THINK
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19
20 #define T_DELIMITER 0 /* delimeter token */
21 #define T_VARIABLE 1
22 #define T_CONSTANT 2
23
24 #define T_LENGTH 80
25
26 int toktype; /* type of last token */
27 char token[T_LENGTH]; /* what gettoken returns - a token */
28 char prog[T_LENGTH]; /* the string to parse */
29
30 int t; /* a 'pointer' to the pos in prog[] */
31 int result; /* result of calculations */
32 int vars[26]; /* variables */
33
34 int level2 (int result); /* recursion levels. level 1 is no */
35 int level3 (int result); /* longer needed (it assigned vars) */
36 int level4 (int result);
37 int level5 (int result);
38 int level6 (int result);
39 int primitive (int result);
40
41 /*-------------------------------------------------------------------------*/
42
43 int
44 isdelimeter (char ch)
45 {
46 switch (ch)
47 {
48 case ' ':
49 case '+':
50 case '-':
51 case '/':
52 case '*':
53 case '%':
54 case '=':
55 case '>':
56 case '<':
57 case '(':
58 case ')':
59 case '$':
60 case '!':
61 case '&':
62 case '|':
63 case '^':
64 return 1;
65 break;
66
67 default:
68 return 0;
69 }
70 }
71
72 void
73 gettoken ()
74 {
75 char temp[T_LENGTH];
76
77 strcpy (token, "");
78 token[1] = (char) 0;
79
80 while (isspace (prog[t]))
81 t++;
82 if (prog[t] == '$')
83 strcpy (token, "$");
84 if (isdelimeter (prog[t]))
85 {
86 toktype = T_DELIMITER;
87 token[0] = prog[t++];
88 }
89 else
90 {
91 if (isalpha (prog[t]))
92 {
93 toktype = T_VARIABLE;
94 while (!(isdelimeter (prog[t])))
95 {
96 token[strlen (token) + 1] = (char) 0;
97 token[strlen (token)] = prog[t++];
98 }
99 }
100 else if (isdigit (prog[t]))
101 {
102 toktype = T_CONSTANT;
103 while (!(isdelimeter (prog[t])))
104 {
105 token[strlen (token) + 1] = (char) 0;
106 token[strlen (token)] = prog[t++];
107 }
108 }
109 }
110 }
111
112 void
113 putback ()
114 {
115 t -= strlen (token);
116 }
117
118 void
119 serror (int s)
120 {
121 switch (s)
122 {
123 case 1:
124 printf ("syntax error\n");
125 break;
126 case 2:
127 printf ("mismatched parentheses\n");
128 break;
129 case 3:
130 printf ("expression absent\n");
131 break;
132 }
133 }
134
135 /*
136 if you define a new operator, use
137
138 return (argument op operand)
139
140 if you define a function (eg. sin(x)), use
141
142 return (func(operand))
143
144 if you define a backwards function (eg. x!) use
145
146 return (func(argument))
147
148 unary operators (such as -5 and !(a=b)) are not handled here, but are
149 handled in level5()
150
151 */
152 int
153 arith (char op, int argument, int operand)
154 {
155 switch (op)
156 {
157 case '+':
158 return (argument + operand); /* addition */
159 case '-':
160 return (argument - operand); /* subtraction */
161 case '*':
162 return (argument * operand); /* multiplication */
163 case '/':
164 return (argument / operand); /* division */
165 case '%':
166 return (argument % operand); /* modulus */
167 case '=':
168 return (argument == operand); /* equality */
169 case '>':
170 return (argument > operand); /* superiority */
171 case '<':
172 return (argument < operand); /* inferiority */
173 case '&':
174 return (argument & operand); /* binary AND */
175 case '|':
176 return (argument | operand); /* binary OR */
177 case '^':
178 return (argument ^ operand); /* binary XOR */
179 }
180 }
181
182 int
183 findvar (char *s)
184 {
185 return vars[(int) toupper (s[0]) - (int) 'A'];
186 }
187
188 int
189 getexp (int result)
190 {
191 gettoken ();
192 if (strlen (token))
193 result = level2 (result);
194 else
195 serror (3);
196 return result;
197 }
198
199 int
200 level2 (int result)
201 {
202 char op;
203 int hold = 0;
204
205 result = level3 (result);
206 op = token[0];
207 while ((op == '+') || (op == '-'))
208 {
209 gettoken ();
210 hold = level3 (hold);
211 result = arith (op, result, hold);
212 op = token[0];
213 }
214 return result;
215 }
216
217 int
218 level3 (int result)
219 {
220 char op;
221 int hold = 0;
222
223 result = level4 (result);
224 op = token[0];
225 while ((op == '*') || (op == '/'))
226 {
227 gettoken ();
228 hold = level4 (hold);
229 result = arith (op, result, hold);
230 op = token[0];
231 }
232 return result;
233 }
234
235 int
236 level4 (int result)
237 {
238 int hold = 0;
239 char ch;
240
241 result = level5 (result);
242 ch = token[0];
243 switch (ch)
244 {
245 case '=':
246 case '>':
247 case '<':
248 case '&':
249 case '|':
250 case '^':
251 gettoken ();
252 hold = level4 (hold);
253 result = arith (ch, result, hold);
254 break;
255 }
256 return result;
257 }
258
259 int
260 level5 (int result)
261 {
262 char op;
263 int hold = 0;
264
265 op = ' ';
266 if ((toktype == T_DELIMITER) && ((token[0] == '+') || (token[0] == '-')))
267 {
268 op = token[0];
269 gettoken ();
270 }
271 result = level6 (result);
272 if (op == '-')
273 result *= (-1);
274 if (op == '!')
275 result = !result;
276 return result;
277 }
278
279 int
280 level6 (int result)
281 {
282 if ((token[0] == '(') && (toktype == T_DELIMITER))
283 {
284 gettoken ();
285 result = level2 (result);
286 if (token[0] != ')')
287 serror (2);
288 gettoken ();
289 }
290 else
291 result = primitive (result);
292 return result;
293 }
294
295 int
296 primitive (int result)
297 {
298 if (toktype == T_CONSTANT)
299 result = atoi (token);
300 else if (toktype == T_VARIABLE)
301 result = findvar (token);
302 else
303 serror (1);
304 gettoken ();
305 return result;
306 }
307
308 int
309 main (int argc, char **argv)
310 {
311 {
312 int c;
313 for (c = 0; c <= 25; c++)
314 vars[c] = 0;
315 }
316 t = 0;
317
318 strcpy (prog, argv[1]);
319 strcat (prog, "$");
320 result = getexp (result);
321 printf ("%d\n", result);
322 exit (0);
323
324
325
326
327 #ifdef THIS_PROGRAM_IS_NOT_REALLY_AS_CRAPPY_AS_YOU_THINK
328 }
329 #else
330 }
331 #endif
332
0 /*
1 * rpn.c
2 *
3 * RPN calculator - May 1993 Chris Pressey
4 *
5 * Compilation : acc rpn.c -o rpn
6 *
7 * Usage : rpn rpn-expressions ; executes and exits
8 * rpn ; goes into interactive mode
9 * rpn <rpn-file ; runs rpn-file through rpn
10 *
11 * To do : add size (size stack), sum (sum stack), mean (mean stack), sd (take
12 * standard deviation of stack)
13 *
14 */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <math.h>
20
21 struct stack /* stack structure, for values on stack */
22 {
23 double val;
24 struct stack *next;
25 } *head; /* head of stack */
26
27 struct word /* word structure, for words (pre- and user- */
28 { /* defined) */
29 char name[80]; /* name of word */
30 char macro[80]; /* macro (user-defined; only executed if
31 * fcn==0) */
32 int fcn; /* built-in fcn or 0 for user-defined fcn */
33 struct word *next;
34 } *whead; /* head of words */
35
36 struct vari /* variable structure, for variables */
37 {
38 char name[80]; /* name of variable */
39 double value; /* values of variable (doubles only) */
40 struct vari *next;
41 } *vhead; /* head of variables */
42
43 /* prototypes */
44
45 /* word-handling */
46 struct word *addword(char *name, char *macro, int fcn);
47 struct word *lookup(char *name);
48 void initwords();
49 void makeword();
50
51 /* variable-handling */
52 struct vari *addvari(char *name);
53 struct vari *getvari(char *name);
54 void setvari(char *name, double value);
55
56 /* stack-handling */
57 void push(double val);
58 double pop();
59
60 /* functions */
61 void dofunc(struct word * w);
62 double factorial(double p);
63 double fibonacci(double p);
64 void words();
65 void vars();
66
67 /* parsing and interpreting */
68 void process(char *s);
69 void procstr(char *s);
70
71 main(argc, argv)
72 int argc;
73 char **argv;
74 {
75 char s[80];
76 int i;
77
78 head = NULL; /* init */
79 whead = NULL;
80 vhead = NULL;
81 initwords();
82 if (argc != 1)
83 {
84 for(i=2;i<=argc;i++) procstr(argv[i-1]);
85 exit(0);
86 }
87 scanf("%s", s); /* process commands/values from stdin */
88 while (!feof(stdin))
89 {
90 process(s);
91 scanf("%s", s);
92 }
93 }
94
95 /*
96 * processes the word in s according to parsing rules.
97 *
98 * if word starts with a digit or a -digit, it is converted to a float and put
99 * on the stack.
100 *
101 * if word starts with a = then the variable following equals is assigned the
102 * last value popped off the stack.
103 *
104 * if word starts with a * a variable is defined using that word.
105 *
106 * if word is in words list, that function is executed.
107 *
108 * if word is in variables list, the value of it is pushed onto the stack.
109 *
110 * otherwise generates an error.
111 */
112 void process(char *s)
113 {
114 struct word *w;
115 struct vari *v;
116
117 if (isdigit(s[0]) || ((s[0] == '-') && (isdigit(s[1]))))
118 push(atof(s));
119 else if (s[0] == '=')
120 setvari(s + 1, pop());
121 else if ((s[0] == '*') && (isalpha(s[1])))
122 addvari(s + 1);
123 else if (w = lookup(s))
124 dofunc(w);
125 else if (v = getvari(s))
126 push(v->value);
127 else
128 printf("unknown command '%s'\n", s);
129 }
130
131 /*
132 * processes each word in the string s.
133 */
134 void procstr(char *s)
135 {
136 char *h=strdup(s);
137 char *g;
138 g = strtok(h, " ");
139 while (g)
140 {
141 process(g);
142 g = strtok(NULL, " ");
143 }
144 free(h); /* called with strdup(), so we must free */
145 }
146
147 /*
148 * adds a unique word to the list of words.
149 */
150 struct word *addword(char *name, char *macro, int fcn)
151 {
152 struct word *new;
153 for (new = whead; new; new = new->next)
154 if (!strcmp(new->name, name))
155 {
156 printf("already exists\n");
157 return NULL;
158 }
159 new = (struct word *) malloc(sizeof(struct word));
160 strcpy(new->name, name);
161 strcpy(new->macro, macro);
162 new->fcn = fcn;
163
164 new->next = whead;
165 whead = new;
166 return new;
167 }
168
169 /*
170 * attempts to find the word 'name' in the words list. returns NULL if it
171 * could not be found.
172 */
173 struct word *lookup(char *name)
174 {
175 struct word *l = whead;
176 struct word *k = NULL;
177
178 while (l)
179 {
180 if (!strcmp(name, l->name))
181 {
182 k = l;
183 l = NULL;
184 } else
185 l = l->next;
186 }
187 return (k);
188 }
189
190 /*
191 * initialize the words list with all the built-in words.
192 */
193 void initwords()
194 {
195 addword("bye", "", 200);
196 addword("vars", "", 101);
197 addword("words", "", 100);
198 addword(";", "", 81);
199 addword(":", "", 80);
200
201 addword("sd", "", 53);
202 addword("mean", "", 52);
203 addword("sum", "", 51);
204 addword("size", "", 50);
205
206 addword("!", "", 13);
207 addword("fib", "", 14);
208
209 addword("rnd", "", 40);
210
211 addword("sign", "", 34);
212 addword("abs", "", 33);
213 addword("round", "", 32);
214 addword("frac", "", 31);
215 addword("int", "", 30);
216
217 addword("phi", "", 27);
218 addword("pi", "", 26);
219 addword("atan", "", 25);
220 addword("acos", "", 24);
221 addword("asin", "", 23);
222
223 addword("tan", "", 22);
224 addword("cos", "", 21);
225 addword("sin", "", 20);
226
227 addword("inv", "", 12);
228 addword("exp", "", 11);
229 addword("log", "", 10);
230 addword("ln", "", 9);
231 addword("sqrt", "", 8);
232 addword("sqr", "", 7);
233
234 addword("^", "", 6);
235
236 addword(".", "", 1);
237
238 addword("/", "", 5);
239 addword("*", "", 4);
240 addword("-", "", 3);
241 addword("+", "", 2);
242 }
243
244 /*
245 * makes a word, reading between the : and ;, defining the new word's macro,
246 * and adds it.
247 */
248 void makeword()
249 {
250 char s[80];
251 char t[80];
252 char y[180];
253 scanf("%s", s);
254 strcpy(y, "");
255 scanf("%s", t);
256 while (strcmp(t, ";"))
257 {
258 strcat(y, t);
259 strcat(y, " ");
260 scanf("%s", t);
261 }
262 addword(s, y, 0);
263 }
264
265 /*
266 * pushes a value onto the stack.
267 */
268 void push(double val)
269 {
270 struct stack *s;
271 s = (struct stack *) malloc(sizeof(struct stack));
272 s->val = val;
273 s->next = head;
274 head = s;
275 }
276
277 /*
278 * pops a value off the stack. generates error and returns 0.0 in case of
279 * underflow.
280 */
281 double pop()
282 {
283 double v;
284 struct stack *s = head;
285 if (s)
286 {
287 v = head->val;
288 head = head->next;
289 free(s);
290 return v;
291 } else
292 {
293 printf("stack underflow\n");
294 return 0.0;
295 }
296 }
297
298 /*
299 * adds a unique variable to the vari list.
300 */
301 struct vari *addvari(char *name)
302 {
303 struct vari *v;
304 for (v = vhead; v; v = v->next)
305 if (!strcmp(v->name, name))
306 {
307 printf("already exists\n");
308 return NULL;
309 }
310 v = (struct vari *) malloc(sizeof(struct vari));
311 strcpy(v->name, name);
312 v->next = vhead;
313 vhead = v;
314 }
315
316 /*
317 * gets the value of a variable off the variable list.
318 */
319 struct vari *getvari(char *name)
320 {
321 struct vari *l = vhead;
322 struct vari *k = NULL;
323
324 while (l)
325 {
326 if (!strcmp(name, l->name))
327 {
328 k = l;
329 l = NULL;
330 } else
331 l = l->next;
332 }
333 return (k);
334 }
335
336 /*
337 * sets the value of a variable
338 */
339 void setvari(char *name, double value)
340 {
341 struct vari *l = vhead;
342 while (l)
343 {
344 if (!strcmp(name, l->name))
345 {
346 l->value = value;
347 l = NULL;
348 } else
349 l = l->next;
350 }
351 }
352
353 /*
354 * calculates p!
355 */
356 double factorial(double p)
357 {
358 if (p <= 1.0)
359 return p;
360 else
361 return (p * factorial(p - 1.0));
362 }
363
364 /*
365 * calculates fib(p) (fib(1)==1, fib(2)==1, fib(n)==fib(n-1)+fib(n-2))
366 */
367 double fibonacci(double p)
368 {
369 if (p <= 2.0)
370 return 1.0;
371 else
372 return (fibonacci(p - 1.0) + fibonacci(p - 2.0));
373 }
374
375 /*
376 * lists all words in bf's words list
377 */
378 void words()
379 {
380 struct word *w;
381 for (w = whead; w; w = w->next)
382 printf("%s ", w->name);
383 printf("\n");
384 }
385
386 /*
387 * list all variables in bf's vari list
388 */
389 void vars()
390 {
391 struct vari *v;
392 for (v = vhead; v; v = v->next)
393 printf("%-16s %f\n", v->name, v->value);
394 }
395
396 /*
397 * execute function of a word. if w->fcn is 0, it will run processtr on the
398 * word. otherwise, a built-in function will be called. see the rpn
399 * documentation on built-in functions.
400 */
401 void dofunc(struct word * w)
402 {
403 double a, b;
404 switch (w->fcn)
405 {
406 case 1: /* output (.) */
407 printf("%f\n", pop());
408 break;
409 case 2: /* add (+) */
410 push(pop() + pop());
411 break;
412 case 3: /* subtract (-) */
413 a = pop();
414 b = pop();
415 push(b - a);
416 break;
417 case 4: /* multiply (*) */
418 push(pop() * pop());
419 break;
420 case 5: /* divide (/) */
421 a = pop();
422 b = pop();
423 push(b / a);
424 break;
425 case 6: /* exponential (^) */
426 a = pop();
427 b = pop();
428 push(pow(b, a));
429 break;
430 case 7: /* square (sqr) */
431 a = pop();
432 push(a * a);
433 break;
434 case 8: /* square root (sqrt) */
435 push(sqrt(pop()));
436 break;
437 case 9: /* natural logarithm (ln) */
438 push(log(pop()));
439 break;
440 case 10: /* log base 10 (log) */
441 push(log10(pop()));
442 break;
443 case 11: /* e^x (exp) */
444 push(exp(pop()));
445 break;
446 case 12: /* inversion (inv) */
447 push(1.0 / pop());
448 break;
449 case 13: /* factorial (!) */
450 push(factorial(pop()));
451 break;
452 case 14: /* fibonacci (fib) */
453 push(fibonacci(pop()));
454 break;
455 case 20: /* sine (sin) */
456 push(sin(pop()));
457 break;
458 case 21: /* cosine (cos) */
459 push(cos(pop()));
460 break;
461 case 22: /* tangent (tan) */
462 push(tan(pop()));
463 break;
464 case 23: /* arcsine (asin) */
465 push(asin(pop()));
466 break;
467 case 24: /* arccosine (acos) */
468 push(acos(pop()));
469 break;
470 case 25: /* arctangent (atan) */
471 push(atan(pop()));
472 break;
473 case 26: /* pi (pi) */
474 push(3.1415926);
475 break;
476 case 80: /* define word (: ... ;) */
477 makeword();
478 break;
479 case 81: /* null (;) */
480 break;
481 case 100: /* list known words (words) */
482 words();
483 break;
484 case 101: /* list variables (vars) */
485 vars();
486 break;
487 case 200: /* exit bf (bye) */
488 exit(0);
489 break;
490 default: /* user-defined word */
491 procstr(w->macro);
492 }
493 }