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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.46 - (hide annotations)
Thu Feb 7 03:56:39 2002 UTC (22 years, 2 months ago) by masse
Branch: MAIN
Changes since 1.45: +45 -38 lines
File MIME type: text/plain
Cosmetic changes.
(eval) Added possibility to eval strings.
(environment) Now contains non_eval_flag.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26