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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.44 - (hide annotations)
Thu Feb 7 01:01:02 2002 UTC (22 years, 2 months ago) by masse
Branch: MAIN
Changes since 1.43: +25 -1 lines
File MIME type: text/plain
(eval) Added functionality to evaluate a list.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26