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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.52 - (show annotations)
Thu Feb 7 23:55:21 2002 UTC (22 years, 2 months ago) by teddy
Branch: MAIN
Changes since 1.51: +3 -5 lines
File MIME type: text/plain
Headers: Updated comments.  Removed <assert.h>.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26