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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.50 - (show annotations)
Thu Feb 7 23:52:20 2002 UTC (22 years, 2 months ago) by teddy
Branch: MAIN
Changes since 1.49: +1 -1 lines
File MIME type: text/plain
(mangle_): Bug fix

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26