/[cvs]/stack/stack.c
ViewVC logotype

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.47 - (hide annotations)
Thu Feb 7 04:11:10 2002 UTC (22 years, 2 months ago) by masse
Branch: MAIN
Changes since 1.46: +9 -8 lines
File MIME type: text/plain
(eval) Cosmetic changes.

1 masse 1.1 /* printf */
2     #include <stdio.h>
3     /* EXIT_SUCCESS */
4     #include <stdlib.h>
5     /* NULL */
6     #include <stddef.h>
7 teddy 1.3 /* dlopen, dlsym, dlerror */
8 masse 1.1 #include <dlfcn.h>
9 teddy 1.18 /* assert */
10     #include <assert.h>
11 masse 1.47 /* strcat */
12     #include <string.h>
13 masse 1.1
14     #define HASHTBLSIZE 65536
15    
16 teddy 1.28 /* First, define some types. */
17    
18     /* A value of some type */
19     typedef struct {
20 masse 1.16 enum {
21 teddy 1.28 integer,
22 teddy 1.18 string,
23 masse 1.16 func, /* Function pointer */
24 teddy 1.28 symb,
25 masse 1.16 list
26 teddy 1.18 } type; /* Type of stack element */
27    
28 masse 1.1 union {
29 teddy 1.28 void *ptr; /* Pointer to the content */
30 masse 1.16 int val; /* ...or an integer */
31     } content; /* Stores a pointer or an integer */
32 masse 1.1
33 teddy 1.28 int refcount; /* Reference counter */
34    
35     } value;
36    
37     /* A symbol with a name and possible value */
38     /* (These do not need reference counters, they are kept unique by
39     hashing.) */
40     typedef struct symbol_struct {
41     char *id; /* Symbol name */
42     value *val; /* The value (if any) bound to it */
43     struct symbol_struct *next; /* In case of hashing conflicts, a */
44     } symbol; /* symbol is a kind of stack item. */
45    
46     /* A type for a hash table for symbols */
47     typedef symbol *hashtbl[HASHTBLSIZE]; /* Hash table declaration */
48    
49     /* An item (value) on a stack */
50     typedef struct stackitem_struct
51     {
52     value *item; /* The value on the stack */
53     struct stackitem_struct *next; /* Next item */
54 masse 1.1 } stackitem;
55    
56 teddy 1.28 /* An environment; gives access to the stack and a hash table of
57     defined symbols */
58     typedef struct {
59     stackitem *head; /* Head of the stack */
60     hashtbl symbols; /* Hash table of all variable bindings */
61 teddy 1.33 int err; /* Error flag */
62 masse 1.46 int non_eval_flag;
63 teddy 1.28 } environment;
64    
65     /* A type for pointers to external functions */
66     typedef void (*funcp)(environment *); /* funcp is a pointer to a void
67     function (environment *) */
68 masse 1.1
69 teddy 1.28 /* Initialize a newly created environment */
70     void init_env(environment *env)
71 masse 1.1 {
72 masse 1.46 int i;
73 masse 1.1
74 masse 1.46 env->err= 0;
75     env->non_eval_flag= 0;
76 masse 1.1 for(i= 0; i<HASHTBLSIZE; i++)
77 teddy 1.28 env->symbols[i]= NULL;
78 masse 1.1 }
79    
80 teddy 1.27 /* Returns a pointer to a pointer to an element in the hash table. */
81 teddy 1.28 symbol **hash(hashtbl in_hashtbl, const char *in_string)
82 masse 1.1 {
83 masse 1.46 int i= 0;
84     unsigned int out_hash= 0;
85 teddy 1.18 char key= '\0';
86 teddy 1.28 symbol **position;
87 masse 1.1
88 masse 1.16 while(1){ /* Hash in_string */
89 masse 1.1 key= in_string[i++];
90     if(key=='\0')
91     break;
92     out_hash= out_hash*32+key;
93     }
94    
95     out_hash= out_hash%HASHTBLSIZE;
96     position= &(in_hashtbl[out_hash]);
97    
98 masse 1.25 while(1){
99 teddy 1.18 if(*position==NULL) /* If empty */
100 masse 1.1 return position;
101    
102 teddy 1.18 if(strcmp(in_string, (*position)->id)==0) /* If match */
103 masse 1.1 return position;
104    
105 masse 1.16 position= &((*position)->next); /* Try next */
106 masse 1.1 }
107     }
108    
109 masse 1.14 /* Generic push function. */
110 teddy 1.35 void push(stackitem** stack_head, stackitem* in_item)
111 masse 1.1 {
112     in_item->next= *stack_head;
113     *stack_head= in_item;
114     }
115    
116 teddy 1.29 /* Push a value onto the stack */
117     void push_val(stackitem **stack_head, value *val)
118     {
119     stackitem *new_item= malloc(sizeof(stackitem));
120     new_item->item= val;
121     val->refcount++;
122     push(stack_head, new_item);
123     }
124    
125 teddy 1.28 /* Push an integer onto the stack. */
126 teddy 1.35 void push_int(stackitem **stack_head, int in_val)
127 masse 1.1 {
128 teddy 1.28 value *new_value= malloc(sizeof(value));
129     stackitem *new_item= malloc(sizeof(stackitem));
130     new_item->item= new_value;
131    
132     new_value->content.val= in_val;
133     new_value->type= integer;
134     new_value->refcount=1;
135 masse 1.1
136     push(stack_head, new_item);
137     }
138    
139 masse 1.14 /* Copy a string onto the stack. */
140 teddy 1.35 void push_cstring(stackitem **stack_head, const char *in_string)
141 masse 1.1 {
142 teddy 1.28 value *new_value= malloc(sizeof(value));
143     stackitem *new_item= malloc(sizeof(stackitem));
144     new_item->item=new_value;
145    
146     new_value->content.ptr= malloc(strlen(in_string)+1);
147     strcpy(new_value->content.ptr, in_string);
148     new_value->type= string;
149     new_value->refcount=1;
150 masse 1.1
151     push(stack_head, new_item);
152     }
153    
154 teddy 1.28 /* Push a symbol onto the stack. */
155 teddy 1.35 void push_sym(environment *env, const char *in_string)
156 masse 1.1 {
157 teddy 1.28 stackitem *new_item; /* The new stack item */
158     /* ...which will contain... */
159     value *new_value; /* A new symbol value */
160     /* ...which might point to... */
161 teddy 1.29 symbol **new_symbol; /* (if needed) A new actual symbol */
162 teddy 1.28 /* ...which, if possible, will be bound to... */
163     value *new_fvalue; /* (if needed) A new function value */
164     /* ...which will point to... */
165     void *funcptr; /* A function pointer */
166    
167     static void *handle= NULL; /* Dynamic linker handle */
168    
169     /* Create a new stack item containing a new value */
170     new_item= malloc(sizeof(stackitem));
171     new_value= malloc(sizeof(value));
172     new_item->item=new_value;
173    
174     /* The new value is a symbol */
175     new_value->type= symb;
176     new_value->refcount= 1;
177    
178     /* Look up the symbol name in the hash table */
179 teddy 1.29 new_symbol= hash(env->symbols, in_string);
180     new_value->content.ptr= *new_symbol;
181 teddy 1.28
182 teddy 1.30 if(*new_symbol==NULL) { /* If symbol was undefined */
183 teddy 1.28
184     /* Create a new symbol */
185 teddy 1.30 (*new_symbol)= malloc(sizeof(symbol));
186 teddy 1.29 (*new_symbol)->val= NULL; /* undefined value */
187     (*new_symbol)->next= NULL;
188     (*new_symbol)->id= malloc(strlen(in_string)+1);
189     strcpy((*new_symbol)->id, in_string);
190 masse 1.1
191 teddy 1.28 /* Intern the new symbol in the hash table */
192 teddy 1.29 new_value->content.ptr= *new_symbol;
193 masse 1.1
194 teddy 1.28 /* Try to load the symbol name as an external function, to see if
195     we should bind the symbol to a new function pointer value */
196 masse 1.16 if(handle==NULL) /* If no handle */
197 teddy 1.28 handle= dlopen(NULL, RTLD_LAZY);
198 masse 1.6
199 teddy 1.28 funcptr= dlsym(handle, in_string); /* Get function pointer */
200     if(dlerror()==NULL) { /* If a function was found */
201     new_fvalue= malloc(sizeof(value)); /* Create a new value */
202     new_fvalue->type=func; /* The new value is a function pointer */
203     new_fvalue->content.ptr=funcptr; /* Store function pointer */
204 teddy 1.29 (*new_symbol)->val= new_fvalue; /* Bind the symbol to the new
205     function value */
206 teddy 1.28 new_fvalue->refcount= 1;
207     }
208 masse 1.1 }
209 teddy 1.28 push(&(env->head), new_item);
210 masse 1.1 }
211    
212 masse 1.17 void printerr(const char* in_string) {
213     fprintf(stderr, "Err: %s\n", in_string);
214     }
215    
216 teddy 1.28 /* Throw away a value */
217     void free_val(value *val){
218     stackitem *item, *temp;
219    
220     val->refcount--; /* Decrease the reference count */
221     if(val->refcount == 0){
222     switch (val->type){ /* and free the contents if necessary */
223     case string:
224     free(val->content.ptr);
225 teddy 1.37 break;
226 teddy 1.28 case list: /* lists needs to be freed recursively */
227     item=val->content.ptr;
228     while(item != NULL) { /* for all stack items */
229     free_val(item->item); /* free the value */
230     temp=item->next; /* save next ptr */
231     free(item); /* free the stackitem */
232     item=temp; /* go to next stackitem */
233     }
234     free(val); /* Free the actual list value */
235     break;
236     default:
237     break;
238     }
239     }
240     }
241    
242 masse 1.14 /* Discard the top element of the stack. */
243 teddy 1.28 extern void toss(environment *env)
244 masse 1.1 {
245 teddy 1.28 stackitem *temp= env->head;
246 masse 1.1
247 teddy 1.28 if((env->head)==NULL) {
248 teddy 1.36 printerr("Too Few Arguments");
249 teddy 1.35 env->err=1;
250 masse 1.7 return;
251 masse 1.17 }
252 masse 1.7
253 teddy 1.28 free_val(env->head->item); /* Free the value */
254     env->head= env->head->next; /* Remove the top stack item */
255     free(temp); /* Free the old top stack item */
256 masse 1.1 }
257    
258 masse 1.14 /* Print newline. */
259 masse 1.34 extern void nl()
260 masse 1.8 {
261     printf("\n");
262     }
263 masse 1.1
264 teddy 1.37 /* Gets the type of a value */
265     extern void type(environment *env){
266     int typenum;
267    
268     if((env->head)==NULL) {
269     printerr("Too Few Arguments");
270     env->err=1;
271     return;
272     }
273     typenum=env->head->item->type;
274     toss(env);
275     switch(typenum){
276     case integer:
277     push_sym(env, "integer");
278     break;
279     case string:
280     push_sym(env, "string");
281     break;
282     case symb:
283     push_sym(env, "symbol");
284     break;
285     case func:
286     push_sym(env, "function");
287     break;
288     case list:
289     push_sym(env, "list");
290     break;
291     default:
292     push_sym(env, "unknown");
293     break;
294     }
295     }
296    
297 masse 1.14 /* Prints the top element of the stack. */
298 teddy 1.28 void print_h(stackitem *stack_head)
299 masse 1.8 {
300 teddy 1.28 switch(stack_head->item->type) {
301     case integer:
302     printf("%d", stack_head->item->content.val);
303 teddy 1.2 break;
304     case string:
305 teddy 1.28 printf("\"%s\"", (char*)stack_head->item->content.ptr);
306 teddy 1.2 break;
307 teddy 1.28 case symb:
308 teddy 1.45 printf("%s", ((symbol *)(stack_head->item->content.ptr))->id);
309 masse 1.6 break;
310 teddy 1.35 case func:
311     printf("#<function %p>", (funcp)(stack_head->item->content.ptr));
312     break;
313     case list:
314 teddy 1.38 /* A list is just a stack, so make stack_head point to it */
315     stack_head=(stackitem *)(stack_head->item->content.ptr);
316     printf("[ ");
317     while(stack_head != NULL) {
318     print_h(stack_head);
319     printf(" ");
320     stack_head=stack_head->next;
321     }
322 teddy 1.39 printf("]");
323 teddy 1.35 break;
324 masse 1.7 default:
325 teddy 1.38 printf("#<unknown %p>", (stack_head->item->content.ptr));
326 teddy 1.2 break;
327     }
328 masse 1.1 }
329    
330 teddy 1.28 extern void print_(environment *env) {
331 teddy 1.35 if(env->head==NULL) {
332 teddy 1.36 printerr("Too Few Arguments");
333 teddy 1.35 env->err=1;
334     return;
335     }
336 teddy 1.28 print_h(env->head);
337     }
338    
339 masse 1.14 /* Prints the top element of the stack and then discards it. */
340 teddy 1.28 extern void print(environment *env)
341 masse 1.8 {
342 teddy 1.28 print_(env);
343 teddy 1.35 if(env->err) return;
344 teddy 1.28 toss(env);
345 masse 1.8 }
346    
347 masse 1.14 /* Only to be called by function printstack. */
348 teddy 1.28 void print_st(stackitem *stack_head, long counter)
349 masse 1.8 {
350     if(stack_head->next != NULL)
351     print_st(stack_head->next, counter+1);
352     printf("%ld: ", counter);
353 teddy 1.28 print_h(stack_head);
354 masse 1.8 nl();
355     }
356    
357 masse 1.14 /* Prints the stack. */
358 teddy 1.28 extern void printstack(environment *env)
359 masse 1.1 {
360 teddy 1.35 if(env->head == NULL) {
361     return;
362 masse 1.1 }
363 teddy 1.35 print_st(env->head, 1);
364     nl();
365 masse 1.1 }
366    
367 masse 1.26 /* Swap the two top elements on the stack. */
368 teddy 1.28 extern void swap(environment *env)
369 masse 1.26 {
370 teddy 1.28 stackitem *temp= env->head;
371 masse 1.26
372 masse 1.46 if(env->head==NULL || env->head->next==NULL) {
373 teddy 1.36 printerr("Too Few Arguments");
374 teddy 1.35 env->err=1;
375 masse 1.26 return;
376 teddy 1.28 }
377 masse 1.26
378 teddy 1.28 env->head= env->head->next;
379     temp->next= env->head->next;
380     env->head->next= temp;
381 masse 1.26 }
382    
383 teddy 1.33 /* Recall a value from a symbol, if bound */
384 teddy 1.31 extern void rcl(environment *env)
385     {
386     value *val;
387    
388     if(env->head == NULL) {
389 teddy 1.36 printerr("Too Few Arguments");
390 teddy 1.35 env->err=1;
391 teddy 1.31 return;
392     }
393    
394     if(env->head->item->type!=symb) {
395 teddy 1.36 printerr("Bad Argument Type");
396     env->err=2;
397 teddy 1.31 return;
398     }
399 teddy 1.35
400 teddy 1.31 val=((symbol *)(env->head->item->content.ptr))->val;
401 teddy 1.33 if(val == NULL){
402 teddy 1.36 printerr("Unbound Variable");
403     env->err=3;
404 teddy 1.33 return;
405     }
406 teddy 1.31 toss(env); /* toss the symbol */
407 teddy 1.35 if(env->err) return;
408 teddy 1.31 push_val(&(env->head), val); /* Return its bound value */
409     }
410 masse 1.26
411 masse 1.46 void stack_read(environment*, char*);
412    
413 teddy 1.29 /* If the top element is a symbol, determine if it's bound to a
414     function value, and if it is, toss the symbol and execute the
415     function. */
416 teddy 1.28 extern void eval(environment *env)
417 masse 1.1 {
418     funcp in_func;
419 masse 1.44 value* temp_val;
420     stackitem* iterator;
421 masse 1.47 char* temp_string;
422 masse 1.44
423 teddy 1.29 if(env->head==NULL) {
424 teddy 1.36 printerr("Too Few Arguments");
425 teddy 1.35 env->err=1;
426 masse 1.1 return;
427 masse 1.17 }
428 masse 1.1
429 masse 1.46 switch(env->head->item->type) {
430     /* if it's a symbol */
431     case symb:
432 teddy 1.35 rcl(env); /* get its contents */
433     if(env->err) return;
434     if(env->head->item->type!=symb){ /* don't recurse symbols */
435     eval(env); /* evaluate the value */
436 teddy 1.29 return;
437     }
438 masse 1.46 break;
439 masse 1.22
440 masse 1.46 /* If it's a lone function value, run it */
441     case func:
442 teddy 1.29 in_func= (funcp)(env->head->item->content.ptr);
443 teddy 1.28 toss(env);
444 teddy 1.35 if(env->err) return;
445 teddy 1.28 (*in_func)(env);
446 masse 1.46 break;
447 masse 1.44
448 masse 1.46 /* If it's a list */
449     case list:
450 masse 1.44 temp_val= env->head->item;
451     env->head->item->refcount++;
452     toss(env);
453     if(env->err) return;
454     iterator= (stackitem*)temp_val->content.ptr;
455     while(iterator!=NULL && iterator->item!=NULL) {
456     push_val(&(env->head), iterator->item);
457     if(env->head->item->type==symb
458     && strcmp(";", ((symbol*)(env->head->item->content.ptr))->id)==0) {
459     toss(env);
460     if(env->err) return;
461     eval(env);
462 masse 1.46 if(env->err) return;
463 masse 1.44 }
464     iterator= iterator->next;
465     }
466     free_val(temp_val);
467 masse 1.46 break;
468    
469     /* If it's a string */
470     case string:
471     temp_val= env->head->item;
472     env->head->item->refcount++;
473     toss(env);
474     if(env->err) return;
475 masse 1.47 temp_string= malloc(strlen((char*)temp_val->content.ptr)+5);
476     strcat(temp_string, "[ ");
477     strcat(temp_string, (char*)temp_val->content.ptr);
478     strcat(temp_string, " ]");
479     stack_read(env, temp_string);
480 masse 1.46 eval(env);
481     if(env->err) return;
482     free_val(temp_val);
483 masse 1.47 free(temp_string);
484 masse 1.46 break;
485    
486     default:
487 masse 1.26 }
488 masse 1.1 }
489    
490 masse 1.44 /* Reverse (flip) a list */
491 teddy 1.40 extern void rev(environment *env){
492     stackitem *old_head, *new_head, *item;
493    
494     if((env->head)==NULL) {
495     printerr("Too Few Arguments");
496     env->err=1;
497     return;
498     }
499    
500     if(env->head->item->type!=list) {
501     printerr("Bad Argument Type");
502     env->err=2;
503     return;
504     }
505    
506     old_head=(stackitem *)(env->head->item->content.ptr);
507     new_head=NULL;
508     while(old_head != NULL){
509     item=old_head;
510     old_head=old_head->next;
511     item->next=new_head;
512     new_head=item;
513     }
514     env->head->item->content.ptr=new_head;
515     }
516    
517 masse 1.19 /* Make a list. */
518 teddy 1.28 extern void pack(environment *env)
519 masse 1.19 {
520     void* delimiter;
521 teddy 1.28 stackitem *iterator, *temp;
522     value *pack;
523 masse 1.19
524 teddy 1.28 delimiter= env->head->item->content.ptr; /* Get delimiter */
525     toss(env);
526 masse 1.19
527 teddy 1.28 iterator= env->head;
528 masse 1.19
529 teddy 1.28 if(iterator==NULL || iterator->item->content.ptr==delimiter) {
530 masse 1.24 temp= NULL;
531 teddy 1.28 toss(env);
532 masse 1.24 } else {
533     /* Search for first delimiter */
534 teddy 1.28 while(iterator->next!=NULL
535     && iterator->next->item->content.ptr!=delimiter)
536 masse 1.24 iterator= iterator->next;
537    
538     /* Extract list */
539 teddy 1.28 temp= env->head;
540     env->head= iterator->next;
541 masse 1.24 iterator->next= NULL;
542    
543 teddy 1.28 if(env->head!=NULL)
544     toss(env);
545 masse 1.24 }
546 masse 1.19
547     /* Push list */
548 teddy 1.28 pack= malloc(sizeof(value));
549 masse 1.19 pack->type= list;
550     pack->content.ptr= temp;
551 teddy 1.28 pack->refcount= 1;
552    
553     temp= malloc(sizeof(stackitem));
554     temp->item= pack;
555 masse 1.19
556 teddy 1.28 push(&(env->head), temp);
557 teddy 1.40 rev(env);
558 masse 1.19 }
559    
560 masse 1.14 /* Parse input. */
561 teddy 1.37 void stack_read(environment *env, char *in_line)
562 masse 1.1 {
563     char *temp, *rest;
564     int itemp;
565     size_t inlength= strlen(in_line)+1;
566     int convert= 0;
567    
568     temp= malloc(inlength);
569     rest= malloc(inlength);
570    
571 masse 1.15 do {
572 masse 1.43 /* If comment */
573     if((convert= sscanf(in_line, "#%[^\n\r]", rest))) {
574     free(temp); free(rest);
575     return;
576     }
577    
578 masse 1.16 /* If string */
579 masse 1.15 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
580 teddy 1.28 push_cstring(&(env->head), temp);
581 masse 1.15 break;
582     }
583 teddy 1.28 /* If integer */
584 masse 1.15 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
585 teddy 1.29 push_int(&(env->head), itemp);
586 masse 1.15 break;
587     }
588 masse 1.16 /* Escape ';' with '\' */
589 masse 1.15 if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) {
590 teddy 1.28 temp[1]= '\0';
591     push_sym(env, temp);
592 masse 1.15 break;
593     }
594 masse 1.16 /* If symbol */
595 masse 1.34 if((convert= sscanf(in_line, "%[^][ ;\n\r]%[^\n\r]", temp, rest))) {
596 teddy 1.28 push_sym(env, temp);
597 masse 1.15 break;
598     }
599 masse 1.19 /* If single char */
600     if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest))) {
601     if(*temp==';') {
602 masse 1.46 if(!env->non_eval_flag) {
603 teddy 1.28 eval(env); /* Evaluate top element */
604 masse 1.20 break;
605     }
606    
607 teddy 1.28 push_sym(env, ";");
608 masse 1.19 break;
609     }
610    
611     if(*temp==']') {
612 teddy 1.28 push_sym(env, "[");
613     pack(env);
614 masse 1.46 if(env->non_eval_flag)
615     env->non_eval_flag--;
616 masse 1.20 break;
617     }
618    
619     if(*temp=='[') {
620 teddy 1.28 push_sym(env, "[");
621 masse 1.46 env->non_eval_flag++;
622 masse 1.19 break;
623     }
624 masse 1.15 }
625     } while(0);
626    
627 masse 1.1 free(temp);
628    
629     if(convert<2) {
630     free(rest);
631 teddy 1.37 return;
632 masse 1.1 }
633    
634 teddy 1.28 stack_read(env, rest);
635 masse 1.1
636     free(rest);
637 masse 1.7 }
638 masse 1.1
639 masse 1.16 /* Relocate elements of the list on the stack. */
640 teddy 1.28 extern void expand(environment *env)
641 masse 1.1 {
642 masse 1.8 stackitem *temp, *new_head;
643    
644 masse 1.16 /* Is top element a list? */
645 teddy 1.36 if(env->head==NULL) {
646     printerr("Too Few Arguments");
647 teddy 1.35 env->err=1;
648 masse 1.8 return;
649 masse 1.17 }
650 teddy 1.36 if(env->head->item->type!=list) {
651     printerr("Bad Argument Type");
652     env->err=2;
653     return;
654     }
655 masse 1.43
656     rev(env);
657    
658     if(env->err)
659     return;
660 masse 1.8
661 masse 1.16 /* The first list element is the new stack head */
662 teddy 1.28 new_head= temp= env->head->item->content.ptr;
663 masse 1.8
664 teddy 1.28 env->head->item->refcount++;
665     toss(env);
666 masse 1.24
667 teddy 1.28 /* Find the end of the list */
668 masse 1.8 while(temp->next!=NULL)
669     temp= temp->next;
670    
671 teddy 1.28 /* Connect the tail of the list with the old stack head */
672     temp->next= env->head;
673     env->head= new_head; /* ...and voila! */
674    
675 teddy 1.5 }
676 masse 1.11
677 masse 1.14 /* Compares two elements by reference. */
678 teddy 1.28 extern void eq(environment *env)
679 masse 1.11 {
680     void *left, *right;
681     int result;
682    
683 teddy 1.28 if((env->head)==NULL || env->head->next==NULL) {
684 teddy 1.36 printerr("Too Few Arguments");
685 teddy 1.35 env->err=1;
686 masse 1.11 return;
687 masse 1.17 }
688 masse 1.11
689 teddy 1.28 left= env->head->item->content.ptr;
690     swap(env);
691     right= env->head->item->content.ptr;
692 masse 1.11 result= (left==right);
693    
694 teddy 1.28 toss(env); toss(env);
695 teddy 1.29 push_int(&(env->head), result);
696 masse 1.11 }
697    
698 masse 1.14 /* Negates the top element on the stack. */
699 teddy 1.28 extern void not(environment *env)
700 masse 1.11 {
701 teddy 1.28 int val;
702 masse 1.11
703 teddy 1.36 if((env->head)==NULL) {
704     printerr("Too Few Arguments");
705 teddy 1.35 env->err=1;
706 masse 1.11 return;
707 masse 1.17 }
708 masse 1.11
709 teddy 1.36 if(env->head->item->type!=integer) {
710     printerr("Bad Argument Type");
711     env->err=2;
712     return;
713     }
714    
715 teddy 1.28 val= env->head->item->content.val;
716     toss(env);
717 teddy 1.29 push_int(&(env->head), !val);
718 masse 1.11 }
719    
720 masse 1.14 /* Compares the two top elements on the stack and return 0 if they're the
721     same. */
722 teddy 1.28 extern void neq(environment *env)
723 masse 1.11 {
724 teddy 1.28 eq(env);
725     not(env);
726 masse 1.11 }
727 masse 1.12
728 masse 1.14 /* Give a symbol some content. */
729 teddy 1.28 extern void def(environment *env)
730 masse 1.12 {
731 teddy 1.28 symbol *sym;
732 masse 1.12
733 teddy 1.28 /* Needs two values on the stack, the top one must be a symbol */
734 teddy 1.36 if(env->head==NULL || env->head->next==NULL) {
735     printerr("Too Few Arguments");
736 teddy 1.35 env->err=1;
737 masse 1.12 return;
738 masse 1.17 }
739 masse 1.12
740 teddy 1.36 if(env->head->item->type!=symb) {
741     printerr("Bad Argument Type");
742     env->err=2;
743     return;
744     }
745    
746 teddy 1.28 /* long names are a pain */
747     sym=env->head->item->content.ptr;
748    
749     /* if the symbol was bound to something else, throw it away */
750     if(sym->val != NULL)
751     free_val(sym->val);
752    
753     /* Bind the symbol to the value */
754     sym->val= env->head->next->item;
755     sym->val->refcount++; /* Increase the reference counter */
756 masse 1.12
757 teddy 1.28 toss(env); toss(env);
758 masse 1.12 }
759 masse 1.10
760 masse 1.14 /* Quit stack. */
761 teddy 1.28 extern void quit(environment *env)
762 teddy 1.5 {
763     exit(EXIT_SUCCESS);
764 masse 1.24 }
765    
766     /* Clear stack */
767 teddy 1.28 extern void clear(environment *env)
768 masse 1.24 {
769 teddy 1.28 while(env->head!=NULL)
770     toss(env);
771 masse 1.1 }
772    
773 teddy 1.33 /* List all defined words */
774 masse 1.32 extern void words(environment *env)
775     {
776     symbol *temp;
777     int i;
778    
779     for(i= 0; i<HASHTBLSIZE; i++) {
780     temp= env->symbols[i];
781     while(temp!=NULL) {
782     printf("%s\n", temp->id);
783     temp= temp->next;
784     }
785     }
786     }
787 masse 1.34
788     /* Forgets a symbol (remove it from the hash table) */
789     extern void forget(environment *env)
790     {
791     char* sym_id;
792     stackitem *stack_head= env->head;
793     symbol **hash_entry, *temp;
794    
795 teddy 1.36 if(stack_head==NULL) {
796     printerr("Too Few Arguments");
797     env->err=1;
798     return;
799     }
800    
801     if(stack_head->item->type!=symb) {
802     printerr("Bad Argument Type");
803     env->err=2;
804 masse 1.34 return;
805     }
806    
807     sym_id= ((symbol*)(stack_head->item->content.ptr))->id;
808     toss(env);
809    
810     hash_entry= hash(env->symbols, sym_id);
811     temp= *hash_entry;
812     *hash_entry= (*hash_entry)->next;
813    
814     if(temp->val!=NULL) {
815     free_val(temp->val);
816     }
817     free(temp->id);
818     free(temp);
819 teddy 1.36 }
820    
821     /* Returns the current error number to the stack */
822     extern void errn(environment *env){
823     push_int(&(env->head), env->err);
824     }
825 masse 1.32
826 masse 1.1 int main()
827     {
828 teddy 1.28 environment myenv;
829 masse 1.1 char in_string[100];
830    
831 teddy 1.28 init_env(&myenv);
832 masse 1.1
833     printf("okidok\n ");
834    
835     while(fgets(in_string, 100, stdin) != NULL) {
836 teddy 1.28 stack_read(&myenv, in_string);
837 teddy 1.35 if(myenv.err) {
838     printf("(error %d) ", myenv.err);
839     myenv.err=0;
840     }
841 masse 1.1 printf("okidok\n ");
842     }
843 teddy 1.41 quit(&myenv);
844 teddy 1.42 return EXIT_FAILURE;
845 masse 1.1 }

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26