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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.98 - (show annotations)
Sun Mar 10 09:13:36 2002 UTC (22 years, 1 month ago) by masse
Branch: MAIN
Changes since 1.97: +59 -43 lines
File MIME type: text/plain
(protect, unprotect): Changed behaviour to mimic gc_mark. All callers changed.

1 /*
2 stack - an interactive interpreter for a stack-based language
3 Copyright (C) 2002 Mats Alritzson and Teddy Hogeborn
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Authors: Mats Alritzson <masse@fukt.bth.se>
20 Teddy Hogeborn <teddy@fukt.bth.se>
21 */
22
23 /* printf, sscanf, fgets, fprintf, fopen, perror */
24 #include <stdio.h>
25 /* exit, EXIT_SUCCESS, malloc, free */
26 #include <stdlib.h>
27 /* NULL */
28 #include <stddef.h>
29 /* dlopen, dlsym, dlerror */
30 #include <dlfcn.h>
31 /* strcmp, strcpy, strlen, strcat, strdup */
32 #include <string.h>
33 /* getopt, STDIN_FILENO, STDOUT_FILENO, usleep */
34 #include <unistd.h>
35 /* EX_NOINPUT, EX_USAGE */
36 #include <sysexits.h>
37 /* mtrace, muntrace */
38 #include <mcheck.h>
39 /* ioctl */
40 #include <sys/ioctl.h>
41 /* KDMKTONE */
42 #include <linux/kd.h>
43
44 #include "stack.h"
45
46 /* Initialize a newly created environment */
47 void init_env(environment *env)
48 {
49 int i;
50
51 env->gc_limit= 200;
52 env->gc_count= 0;
53 env->gc_ref= NULL;
54
55 env->head= NULL;
56 for(i= 0; i<HASHTBLSIZE; i++)
57 env->symbols[i]= NULL;
58 env->err= 0;
59 env->in_string= NULL;
60 env->free_string= NULL;
61 env->inputstream= stdin;
62 env->interactive= 1;
63 }
64
65 void printerr(const char* in_string)
66 {
67 fprintf(stderr, "Err: %s\n", in_string);
68 }
69
70 /* Discard the top element of the stack. */
71 extern void toss(environment *env)
72 {
73 stackitem *temp= env->head;
74
75 if((env->head)==NULL) {
76 printerr("Too Few Arguments");
77 env->err= 1;
78 return;
79 }
80
81 env->head= env->head->next; /* Remove the top stack item */
82 free(temp); /* Free the old top stack item */
83
84 env->gc_limit--;
85 }
86
87 /* Returns a pointer to a pointer to an element in the hash table. */
88 symbol **hash(hashtbl in_hashtbl, const char *in_string)
89 {
90 int i= 0;
91 unsigned int out_hash= 0;
92 char key= '\0';
93 symbol **position;
94
95 while(1){ /* Hash in_string */
96 key= in_string[i++];
97 if(key=='\0')
98 break;
99 out_hash= out_hash*32+key;
100 }
101
102 out_hash= out_hash%HASHTBLSIZE;
103 position= &(in_hashtbl[out_hash]);
104
105 while(1){
106 if(*position==NULL) /* If empty */
107 return position;
108
109 if(strcmp(in_string, (*position)->id)==0) /* If match */
110 return position;
111
112 position= &((*position)->next); /* Try next */
113 }
114 }
115
116 /* Create new value */
117 value* new_val(environment *env)
118 {
119 value *nval= malloc(sizeof(value));
120 stackitem *nitem= malloc(sizeof(stackitem));
121
122 nval->content.ptr= NULL;
123
124 nitem->item= nval;
125 nitem->next= env->gc_ref;
126 env->gc_ref= nitem;
127
128 env->gc_count++;
129 nval->gc_garb= 1;
130
131 return nval;
132 }
133
134 /* Mark values recursively.
135 Marked values are not collected by the GC. */
136 inline void gc_mark(value *val)
137 {
138 stackitem *iterator;
139
140 if(val->gc_garb==0)
141 return;
142
143 val->gc_garb= 0;
144
145 if(val->type==list) {
146 iterator= val->content.ptr;
147
148 while(iterator!=NULL) {
149 gc_mark(iterator->item);
150 iterator= iterator->next;
151 }
152 }
153 }
154
155 inline void gc_maybe(environment *env)
156 {
157 if(env->gc_count < env->gc_limit)
158 return;
159 else
160 return gc_init(env);
161 }
162
163 /* Start GC */
164 extern void gc_init(environment *env)
165 {
166 stackitem *new_head= NULL, *titem, *iterator;
167 symbol *tsymb;
168 int i;
169
170 /* Mark values on stack */
171 iterator= env->head;
172 while(iterator!=NULL) {
173 gc_mark(iterator->item);
174 iterator= iterator->next;
175 }
176
177 /* Mark values in hashtable */
178 for(i= 0; i<HASHTBLSIZE; i++) {
179 tsymb= env->symbols[i];
180 while(tsymb!=NULL) {
181 if (tsymb->val != NULL)
182 gc_mark(tsymb->val);
183 tsymb= tsymb->next;
184 }
185 }
186
187 env->gc_count= 0;
188
189 while(env->gc_ref!=NULL) { /* Sweep unused values */
190
191 if(env->gc_ref->item->gc_garb
192 && !(env->gc_ref->item->gc_protect)) {
193
194 switch(env->gc_ref->item->type) { /* Remove content */
195 case string:
196 free(env->gc_ref->item->content.ptr);
197 break;
198 case list:
199 while(env->gc_ref->item->content.ptr!=NULL) {
200 titem= env->gc_ref->item->content.ptr;
201 env->gc_ref->item->content.ptr= titem->next;
202 free(titem);
203 }
204 default:
205 }
206 free(env->gc_ref->item); /* Remove from gc_ref */
207 titem= env->gc_ref->next;
208 free(env->gc_ref); /* Remove value */
209 env->gc_ref= titem;
210 continue;
211 }
212
213 /* Keep values */
214 titem= env->gc_ref->next;
215 env->gc_ref->next= new_head;
216 new_head= env->gc_ref;
217 new_head->item->gc_garb= 1;
218 env->gc_ref= titem;
219 env->gc_count++;
220 }
221
222 env->gc_limit= env->gc_count*2;
223 env->gc_ref= new_head;
224 }
225
226 /* Protect values from GC */
227 void protect(value *val)
228 {
229 stackitem *iterator;
230
231 if(val->gc_protect)
232 return;
233
234 val->gc_protect= 1;
235
236 if(val->type==list) {
237 iterator= val->content.ptr;
238
239 while(iterator!=NULL) {
240 protect(iterator->item);
241 iterator= iterator->next;
242 }
243 }
244 }
245
246 /* Unprotect values from GC */
247 void unprotect(value *val)
248 {
249 stackitem *iterator;
250
251 if(!(val->gc_protect))
252 return;
253
254 val->gc_protect= 0;
255
256 if(val->type==list) {
257 iterator= val->content.ptr;
258
259 while(iterator!=NULL) {
260 unprotect(iterator->item);
261 iterator= iterator->next;
262 }
263 }
264 }
265
266 /* Push a value onto the stack */
267 void push_val(environment *env, value *val)
268 {
269 stackitem *new_item= malloc(sizeof(stackitem));
270 new_item->item= val;
271 new_item->next= env->head;
272 env->head= new_item;
273 }
274
275 /* Push an integer onto the stack */
276 void push_int(environment *env, int in_val)
277 {
278 value *new_value= new_val(env);
279
280 new_value->content.i= in_val;
281 new_value->type= integer;
282
283 push_val(env, new_value);
284 }
285
286 /* Push a floating point number onto the stack */
287 void push_float(environment *env, float in_val)
288 {
289 value *new_value= new_val(env);
290
291 new_value->content.f= in_val;
292 new_value->type= tfloat;
293
294 push_val(env, new_value);
295 }
296
297 /* Copy a string onto the stack. */
298 void push_cstring(environment *env, const char *in_string)
299 {
300 value *new_value= new_val(env);
301
302 new_value->content.ptr= malloc(strlen(in_string)+1);
303 strcpy(new_value->content.ptr, in_string);
304 new_value->type= string;
305
306 push_val(env, new_value);
307 }
308
309 /* Mangle a symbol name to a valid C identifier name */
310 char *mangle_str(const char *old_string)
311 {
312 char validchars[]= "0123456789abcdef";
313 char *new_string, *current;
314
315 new_string= malloc((strlen(old_string)*2)+4);
316 strcpy(new_string, "sx_"); /* Stack eXternal */
317 current= new_string+3;
318 while(old_string[0] != '\0'){
319 current[0]= validchars[(unsigned char)(old_string[0])/16];
320 current[1]= validchars[(unsigned char)(old_string[0])%16];
321 current+= 2;
322 old_string++;
323 }
324 current[0]= '\0';
325
326 return new_string; /* The caller must free() it */
327 }
328
329 extern void mangle(environment *env)
330 {
331 char *new_string;
332
333 if((env->head)==NULL) {
334 printerr("Too Few Arguments");
335 env->err= 1;
336 return;
337 }
338
339 if(env->head->item->type!=string) {
340 printerr("Bad Argument Type");
341 env->err= 2;
342 return;
343 }
344
345 new_string= mangle_str((const char *)(env->head->item->content.ptr));
346
347 toss(env);
348 if(env->err) return;
349
350 push_cstring(env, new_string);
351 }
352
353 /* Push a symbol onto the stack. */
354 void push_sym(environment *env, const char *in_string)
355 {
356 value *new_value; /* A new symbol value */
357 /* ...which might point to... */
358 symbol **new_symbol; /* (if needed) A new actual symbol */
359 /* ...which, if possible, will be bound to... */
360 value *new_fvalue; /* (if needed) A new function value */
361 /* ...which will point to... */
362 void *funcptr; /* A function pointer */
363
364 static void *handle= NULL; /* Dynamic linker handle */
365 const char *dlerr; /* Dynamic linker error */
366 char *mangled; /* Mangled function name */
367
368 new_value= new_val(env);
369 protect(new_value);
370 new_fvalue= new_val(env);
371 protect(new_fvalue);
372
373 /* The new value is a symbol */
374 new_value->type= symb;
375
376 /* Look up the symbol name in the hash table */
377 new_symbol= hash(env->symbols, in_string);
378 new_value->content.ptr= *new_symbol;
379
380 if(*new_symbol==NULL) { /* If symbol was undefined */
381
382 /* Create a new symbol */
383 (*new_symbol)= malloc(sizeof(symbol));
384 (*new_symbol)->val= NULL; /* undefined value */
385 (*new_symbol)->next= NULL;
386 (*new_symbol)->id= malloc(strlen(in_string)+1);
387 strcpy((*new_symbol)->id, in_string);
388
389 /* Intern the new symbol in the hash table */
390 new_value->content.ptr= *new_symbol;
391
392 /* Try to load the symbol name as an external function, to see if
393 we should bind the symbol to a new function pointer value */
394 if(handle==NULL) /* If no handle */
395 handle= dlopen(NULL, RTLD_LAZY);
396
397 mangled= mangle_str(in_string); /* mangle the name */
398 funcptr= dlsym(handle, mangled); /* and try to find it */
399
400 dlerr= dlerror();
401 if(dlerr != NULL) { /* If no function was found */
402 funcptr= dlsym(handle, in_string); /* Get function pointer */
403 dlerr= dlerror();
404 }
405
406 if(dlerr==NULL) { /* If a function was found */
407 new_fvalue->type= func; /* The new value is a function pointer */
408 new_fvalue->content.ptr= funcptr; /* Store function pointer */
409 (*new_symbol)->val= new_fvalue; /* Bind the symbol to the new
410 function value */
411 }
412
413 free(mangled);
414 }
415
416 push_val(env, new_value);
417 unprotect(new_value); unprotect(new_fvalue);
418 }
419
420 /* Print newline. */
421 extern void nl()
422 {
423 printf("\n");
424 }
425
426 /* Gets the type of a value */
427 extern void type(environment *env)
428 {
429 int typenum;
430
431 if((env->head)==NULL) {
432 printerr("Too Few Arguments");
433 env->err=1;
434 return;
435 }
436 typenum=env->head->item->type;
437 toss(env);
438 switch(typenum){
439 case integer:
440 push_sym(env, "integer");
441 break;
442 case tfloat:
443 push_sym(env, "float");
444 break;
445 case string:
446 push_sym(env, "string");
447 break;
448 case symb:
449 push_sym(env, "symbol");
450 break;
451 case func:
452 push_sym(env, "function");
453 break;
454 case list:
455 push_sym(env, "list");
456 break;
457 }
458 }
459
460 /* Prints the top element of the stack. */
461 void print_h(stackitem *stack_head, int noquote)
462 {
463 switch(stack_head->item->type) {
464 case integer:
465 printf("%d", stack_head->item->content.i);
466 break;
467 case tfloat:
468 printf("%f", stack_head->item->content.f);
469 break;
470 case string:
471 if(noquote)
472 printf("%s", (char*)stack_head->item->content.ptr);
473 else
474 printf("\"%s\"", (char*)stack_head->item->content.ptr);
475 break;
476 case symb:
477 printf("%s", ((symbol *)(stack_head->item->content.ptr))->id);
478 break;
479 case func:
480 printf("#<function %p>", (funcp)(stack_head->item->content.ptr));
481 break;
482 case list:
483 /* A list is just a stack, so make stack_head point to it */
484 stack_head=(stackitem *)(stack_head->item->content.ptr);
485 printf("[ ");
486 while(stack_head != NULL) {
487 print_h(stack_head, noquote);
488 printf(" ");
489 stack_head=stack_head->next;
490 }
491 printf("]");
492 break;
493 }
494 }
495
496 extern void print_(environment *env)
497 {
498 if(env->head==NULL) {
499 printerr("Too Few Arguments");
500 env->err=1;
501 return;
502 }
503 print_h(env->head, 0);
504 nl();
505 }
506
507 /* Prints the top element of the stack and then discards it. */
508 extern void print(environment *env)
509 {
510 print_(env);
511 if(env->err) return;
512 toss(env);
513 }
514
515 extern void princ_(environment *env)
516 {
517 if(env->head==NULL) {
518 printerr("Too Few Arguments");
519 env->err=1;
520 return;
521 }
522 print_h(env->head, 1);
523 }
524
525 /* Prints the top element of the stack and then discards it. */
526 extern void princ(environment *env)
527 {
528 princ_(env);
529 if(env->err) return;
530 toss(env);
531 }
532
533 /* Only to be called by function printstack. */
534 void print_st(stackitem *stack_head, long counter)
535 {
536 if(stack_head->next != NULL)
537 print_st(stack_head->next, counter+1);
538 printf("%ld: ", counter);
539 print_h(stack_head, 0);
540 nl();
541 }
542
543 /* Prints the stack. */
544 extern void printstack(environment *env)
545 {
546 if(env->head == NULL) {
547 printf("Stack Empty\n");
548 return;
549 }
550
551 print_st(env->head, 1);
552 }
553
554 /* Swap the two top elements on the stack. */
555 extern void swap(environment *env)
556 {
557 stackitem *temp= env->head;
558
559 if(env->head==NULL || env->head->next==NULL) {
560 printerr("Too Few Arguments");
561 env->err=1;
562 return;
563 }
564
565 env->head= env->head->next;
566 temp->next= env->head->next;
567 env->head->next= temp;
568 }
569
570 /* Rotate the first three elements on the stack. */
571 extern void rot(environment *env)
572 {
573 stackitem *temp= env->head;
574
575 if(env->head==NULL || env->head->next==NULL
576 || env->head->next->next==NULL) {
577 printerr("Too Few Arguments");
578 env->err=1;
579 return;
580 }
581
582 env->head= env->head->next->next;
583 temp->next->next= env->head->next;
584 env->head->next= temp;
585 }
586
587 /* Recall a value from a symbol, if bound */
588 extern void rcl(environment *env)
589 {
590 value *val;
591
592 if(env->head == NULL) {
593 printerr("Too Few Arguments");
594 env->err=1;
595 return;
596 }
597
598 if(env->head->item->type!=symb) {
599 printerr("Bad Argument Type");
600 env->err=2;
601 return;
602 }
603
604 val=((symbol *)(env->head->item->content.ptr))->val;
605 if(val == NULL){
606 printerr("Unbound Variable");
607 env->err=3;
608 return;
609 }
610 protect(val);
611 toss(env); /* toss the symbol */
612 if(env->err) return;
613 push_val(env, val); /* Return its bound value */
614 unprotect(val);
615 }
616
617 /* If the top element is a symbol, determine if it's bound to a
618 function value, and if it is, toss the symbol and execute the
619 function. */
620 extern void eval(environment *env)
621 {
622 funcp in_func;
623 value* temp_val;
624 stackitem* iterator;
625
626 eval_start:
627
628 gc_maybe(env);
629
630 if(env->head==NULL) {
631 printerr("Too Few Arguments");
632 env->err=1;
633 return;
634 }
635
636 switch(env->head->item->type) {
637 /* if it's a symbol */
638 case symb:
639 rcl(env); /* get its contents */
640 if(env->err) return;
641 if(env->head->item->type!=symb){ /* don't recurse symbols */
642 goto eval_start;
643 }
644 return;
645
646 /* If it's a lone function value, run it */
647 case func:
648 in_func= (funcp)(env->head->item->content.ptr);
649 toss(env);
650 if(env->err) return;
651 return in_func(env);
652
653 /* If it's a list */
654 case list:
655 temp_val= env->head->item;
656 protect(temp_val);
657
658 toss(env); if(env->err) return;
659 iterator= (stackitem*)temp_val->content.ptr;
660
661 while(iterator!=NULL) {
662 push_val(env, iterator->item);
663
664 if(env->head->item->type==symb
665 && strcmp(";", ((symbol*)(env->head->item->content.ptr))->id)==0) {
666 toss(env);
667 if(env->err) return;
668
669 if(iterator->next == NULL){
670 goto eval_start;
671 }
672 eval(env);
673 if(env->err) return;
674 }
675 iterator= iterator->next;
676 }
677 unprotect(temp_val);
678 return;
679
680 default:
681 return;
682 }
683 }
684
685 /* Reverse (flip) a list */
686 extern void rev(environment *env)
687 {
688 stackitem *old_head, *new_head, *item;
689
690 if((env->head)==NULL) {
691 printerr("Too Few Arguments");
692 env->err= 1;
693 return;
694 }
695
696 if(env->head->item->type!=list) {
697 printerr("Bad Argument Type");
698 env->err= 2;
699 return;
700 }
701
702 old_head= (stackitem *)(env->head->item->content.ptr);
703 new_head= NULL;
704 while(old_head != NULL){
705 item= old_head;
706 old_head= old_head->next;
707 item->next= new_head;
708 new_head= item;
709 }
710 env->head->item->content.ptr= new_head;
711 }
712
713 /* Make a list. */
714 extern void pack(environment *env)
715 {
716 stackitem *iterator, *temp;
717 value *pack;
718
719 iterator= env->head;
720 pack= new_val(env);
721 protect(pack);
722
723 if(iterator==NULL
724 || (iterator->item->type==symb
725 && ((symbol*)(iterator->item->content.ptr))->id[0]=='[')) {
726 temp= NULL;
727 toss(env);
728 } else {
729 /* Search for first delimiter */
730 while(iterator->next!=NULL
731 && (iterator->next->item->type!=symb
732 || ((symbol*)(iterator->next->item->content.ptr))->id[0]!='['))
733 iterator= iterator->next;
734
735 /* Extract list */
736 temp= env->head;
737 env->head= iterator->next;
738 iterator->next= NULL;
739
740 pack->type= list;
741 pack->content.ptr= temp;
742
743 if(env->head!=NULL)
744 toss(env);
745 }
746
747 /* Push list */
748
749 push_val(env, pack);
750 rev(env);
751
752 unprotect(pack);
753 }
754
755 /* Relocate elements of the list on the stack. */
756 extern void expand(environment *env)
757 {
758 stackitem *temp, *new_head;
759
760 /* Is top element a list? */
761 if(env->head==NULL) {
762 printerr("Too Few Arguments");
763 env->err= 1;
764 return;
765 }
766 if(env->head->item->type!=list) {
767 printerr("Bad Argument Type");
768 env->err= 2;
769 return;
770 }
771
772 rev(env);
773
774 if(env->err)
775 return;
776
777 /* The first list element is the new stack head */
778 new_head= temp= env->head->item->content.ptr;
779
780 toss(env);
781
782 /* Find the end of the list */
783 while(temp->next!=NULL)
784 temp= temp->next;
785
786 /* Connect the tail of the list with the old stack head */
787 temp->next= env->head;
788 env->head= new_head; /* ...and voila! */
789
790 }
791
792 /* Compares two elements by reference. */
793 extern void eq(environment *env)
794 {
795 void *left, *right;
796 int result;
797
798 if((env->head)==NULL || env->head->next==NULL) {
799 printerr("Too Few Arguments");
800 env->err= 1;
801 return;
802 }
803
804 left= env->head->item->content.ptr;
805 swap(env);
806 right= env->head->item->content.ptr;
807 result= (left==right);
808
809 toss(env); toss(env);
810 push_int(env, result);
811 }
812
813 /* Negates the top element on the stack. */
814 extern void not(environment *env)
815 {
816 int val;
817
818 if((env->head)==NULL) {
819 printerr("Too Few Arguments");
820 env->err= 1;
821 return;
822 }
823
824 if(env->head->item->type!=integer) {
825 printerr("Bad Argument Type");
826 env->err= 2;
827 return;
828 }
829
830 val= env->head->item->content.i;
831 toss(env);
832 push_int(env, !val);
833 }
834
835 /* Compares the two top elements on the stack and return 0 if they're the
836 same. */
837 extern void neq(environment *env)
838 {
839 eq(env);
840 not(env);
841 }
842
843 /* Give a symbol some content. */
844 extern void def(environment *env)
845 {
846 symbol *sym;
847
848 /* Needs two values on the stack, the top one must be a symbol */
849 if(env->head==NULL || env->head->next==NULL) {
850 printerr("Too Few Arguments");
851 env->err= 1;
852 return;
853 }
854
855 if(env->head->item->type!=symb) {
856 printerr("Bad Argument Type");
857 env->err= 2;
858 return;
859 }
860
861 /* long names are a pain */
862 sym= env->head->item->content.ptr;
863
864 /* Bind the symbol to the value */
865 sym->val= env->head->next->item;
866
867 toss(env); toss(env);
868 }
869
870 /* Quit stack. */
871 extern void quit(environment *env)
872 {
873 int i;
874
875 clear(env);
876
877 if (env->err) return;
878 for(i= 0; i<HASHTBLSIZE; i++) {
879 while(env->symbols[i]!= NULL) {
880 forget_sym(&(env->symbols[i]));
881 }
882 env->symbols[i]= NULL;
883 }
884
885 env->gc_limit= 0;
886 gc_maybe(env);
887
888 if(env->free_string!=NULL)
889 free(env->free_string);
890
891 muntrace();
892
893 exit(EXIT_SUCCESS);
894 }
895
896 /* Clear stack */
897 extern void clear(environment *env)
898 {
899 while(env->head!=NULL)
900 toss(env);
901 }
902
903 /* List all defined words */
904 extern void words(environment *env)
905 {
906 symbol *temp;
907 int i;
908
909 for(i= 0; i<HASHTBLSIZE; i++) {
910 temp= env->symbols[i];
911 while(temp!=NULL) {
912 printf("%s\n", temp->id);
913 temp= temp->next;
914 }
915 }
916 }
917
918 /* Internal forget function */
919 void forget_sym(symbol **hash_entry)
920 {
921 symbol *temp;
922
923 temp= *hash_entry;
924 *hash_entry= (*hash_entry)->next;
925
926 free(temp->id);
927 free(temp);
928 }
929
930 /* Forgets a symbol (remove it from the hash table) */
931 extern void forget(environment *env)
932 {
933 char* sym_id;
934 stackitem *stack_head= env->head;
935
936 if(stack_head==NULL) {
937 printerr("Too Few Arguments");
938 env->err=1;
939 return;
940 }
941
942 if(stack_head->item->type!=symb) {
943 printerr("Bad Argument Type");
944 env->err=2;
945 return;
946 }
947
948 sym_id= ((symbol*)(stack_head->item->content.ptr))->id;
949 toss(env);
950
951 return forget_sym(hash(env->symbols, sym_id));
952 }
953
954 /* Returns the current error number to the stack */
955 extern void errn(environment *env)
956 {
957 push_int(env, env->err);
958 }
959
960 int main(int argc, char **argv)
961 {
962 environment myenv;
963
964 int c; /* getopt option character */
965
966 mtrace();
967
968 init_env(&myenv);
969
970 myenv.interactive = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
971
972 while ((c = getopt (argc, argv, "i")) != -1)
973 switch (c)
974 {
975 case 'i':
976 myenv.interactive = 1;
977 break;
978 case '?':
979 fprintf (stderr,
980 "Unknown option character `\\x%x'.\n",
981 optopt);
982 return EX_USAGE;
983 default:
984 abort ();
985 }
986
987 if (optind < argc) {
988 myenv.interactive = 0;
989 myenv.inputstream= fopen(argv[optind], "r");
990 if(myenv.inputstream== NULL) {
991 perror(argv[0]);
992 exit (EX_NOINPUT);
993 }
994 }
995
996 if(myenv.interactive) {
997 printf("Stack version $Revision: 1.97 $\n\
998 Copyright (C) 2002 Mats Alritzson and Teddy Hogeborn\n\
999 Stack comes with ABSOLUTELY NO WARRANTY; for details type `warranty;'.\n\
1000 This is free software, and you are welcome to redistribute it\n\
1001 under certain conditions; type `copying;' for details.\n");
1002 }
1003
1004 while(1) {
1005 if(myenv.in_string==NULL) {
1006 if (myenv.interactive) {
1007 if(myenv.err) {
1008 printf("(error %d)\n", myenv.err);
1009 }
1010 nl();
1011 printstack(&myenv);
1012 printf("> ");
1013 }
1014 myenv.err=0;
1015 }
1016 sx_72656164(&myenv);
1017 if (myenv.err==4) {
1018 return EXIT_SUCCESS; /* EOF */
1019 } else if(myenv.head!=NULL
1020 && myenv.head->item->type==symb
1021 && ((symbol*)(myenv.head->item->content.ptr))->id[0]==';') {
1022 toss(&myenv); /* No error check in main */
1023 eval(&myenv);
1024 }
1025 gc_maybe(&myenv);
1026 }
1027 quit(&myenv);
1028 return EXIT_FAILURE;
1029 }
1030
1031 /* "+" */
1032 extern void sx_2b(environment *env)
1033 {
1034 int a, b;
1035 float fa, fb;
1036 size_t len;
1037 char* new_string;
1038 value *a_val, *b_val;
1039
1040 if((env->head)==NULL || env->head->next==NULL) {
1041 printerr("Too Few Arguments");
1042 env->err= 1;
1043 return;
1044 }
1045
1046 if(env->head->item->type==string
1047 && env->head->next->item->type==string) {
1048 a_val= env->head->item;
1049 b_val= env->head->next->item;
1050 protect(a_val); protect(b_val);
1051 toss(env); if(env->err) return;
1052 toss(env); if(env->err) return;
1053 len= strlen(a_val->content.ptr)+strlen(b_val->content.ptr)+1;
1054 new_string= malloc(len);
1055 strcpy(new_string, b_val->content.ptr);
1056 strcat(new_string, a_val->content.ptr);
1057 push_cstring(env, new_string);
1058 unprotect(a_val); unprotect(b_val);
1059 free(new_string);
1060
1061 return;
1062 }
1063
1064 if(env->head->item->type==integer
1065 && env->head->next->item->type==integer) {
1066 a=env->head->item->content.i;
1067 toss(env); if(env->err) return;
1068 b=env->head->item->content.i;
1069 toss(env); if(env->err) return;
1070 push_int(env, b+a);
1071
1072 return;
1073 }
1074
1075 if(env->head->item->type==tfloat
1076 && env->head->next->item->type==tfloat) {
1077 fa= env->head->item->content.f;
1078 toss(env); if(env->err) return;
1079 fb= env->head->item->content.f;
1080 toss(env); if(env->err) return;
1081 push_float(env, fb+fa);
1082
1083 return;
1084 }
1085
1086 if(env->head->item->type==tfloat
1087 && env->head->next->item->type==integer) {
1088 fa= env->head->item->content.f;
1089 toss(env); if(env->err) return;
1090 b= env->head->item->content.i;
1091 toss(env); if(env->err) return;
1092 push_float(env, b+fa);
1093
1094 return;
1095 }
1096
1097 if(env->head->item->type==integer
1098 && env->head->next->item->type==tfloat) {
1099 a= env->head->item->content.i;
1100 toss(env); if(env->err) return;
1101 fb= env->head->item->content.f;
1102 toss(env); if(env->err) return;
1103 push_float(env, fb+a);
1104
1105 return;
1106 }
1107
1108 printerr("Bad Argument Type");
1109 env->err=2;
1110 }
1111
1112 /* "-" */
1113 extern void sx_2d(environment *env)
1114 {
1115 int a, b;
1116 float fa, fb;
1117
1118 if((env->head)==NULL || env->head->next==NULL) {
1119 printerr("Too Few Arguments");
1120 env->err=1;
1121 return;
1122 }
1123
1124 if(env->head->item->type==integer
1125 && env->head->next->item->type==integer) {
1126 a=env->head->item->content.i;
1127 toss(env); if(env->err) return;
1128 b=env->head->item->content.i;
1129 toss(env); if(env->err) return;
1130 push_int(env, b-a);
1131
1132 return;
1133 }
1134
1135 if(env->head->item->type==tfloat
1136 && env->head->next->item->type==tfloat) {
1137 fa= env->head->item->content.f;
1138 toss(env); if(env->err) return;
1139 fb= env->head->item->content.f;
1140 toss(env); if(env->err) return;
1141 push_float(env, fb-fa);
1142
1143 return;
1144 }
1145
1146 if(env->head->item->type==tfloat
1147 && env->head->next->item->type==integer) {
1148 fa= env->head->item->content.f;
1149 toss(env); if(env->err) return;
1150 b= env->head->item->content.i;
1151 toss(env); if(env->err) return;
1152 push_float(env, b-fa);
1153
1154 return;
1155 }
1156
1157 if(env->head->item->type==integer
1158 && env->head->next->item->type==tfloat) {
1159 a= env->head->item->content.i;
1160 toss(env); if(env->err) return;
1161 fb= env->head->item->content.f;
1162 toss(env); if(env->err) return;
1163 push_float(env, fb-a);
1164
1165 return;
1166 }
1167
1168 printerr("Bad Argument Type");
1169 env->err=2;
1170 }
1171
1172 /* ">" */
1173 extern void sx_3e(environment *env)
1174 {
1175 int a, b;
1176 float fa, fb;
1177
1178 if((env->head)==NULL || env->head->next==NULL) {
1179 printerr("Too Few Arguments");
1180 env->err=1;
1181 return;
1182 }
1183
1184 if(env->head->item->type==integer
1185 && env->head->next->item->type==integer) {
1186 a=env->head->item->content.i;
1187 toss(env); if(env->err) return;
1188 b=env->head->item->content.i;
1189 toss(env); if(env->err) return;
1190 push_int(env, b>a);
1191
1192 return;
1193 }
1194
1195 if(env->head->item->type==tfloat
1196 && env->head->next->item->type==tfloat) {
1197 fa= env->head->item->content.f;
1198 toss(env); if(env->err) return;
1199 fb= env->head->item->content.f;
1200 toss(env); if(env->err) return;
1201 push_int(env, fb>fa);
1202
1203 return;
1204 }
1205
1206 if(env->head->item->type==tfloat
1207 && env->head->next->item->type==integer) {
1208 fa= env->head->item->content.f;
1209 toss(env); if(env->err) return;
1210 b= env->head->item->content.i;
1211 toss(env); if(env->err) return;
1212 push_int(env, b>fa);
1213
1214 return;
1215 }
1216
1217 if(env->head->item->type==integer
1218 && env->head->next->item->type==tfloat) {
1219 a= env->head->item->content.i;
1220 toss(env); if(env->err) return;
1221 fb= env->head->item->content.f;
1222 toss(env); if(env->err) return;
1223 push_int(env, fb>a);
1224
1225 return;
1226 }
1227
1228 printerr("Bad Argument Type");
1229 env->err=2;
1230 }
1231
1232 /* "<" */
1233 extern void sx_3c(environment *env)
1234 {
1235 swap(env); if(env->err) return;
1236 sx_3e(env);
1237 }
1238
1239 /* "<=" */
1240 extern void sx_3c3d(environment *env)
1241 {
1242 sx_3e(env); if(env->err) return;
1243 not(env);
1244 }
1245
1246 /* ">=" */
1247 extern void sx_3e3d(environment *env)
1248 {
1249 sx_3c(env); if(env->err) return;
1250 not(env);
1251 }
1252
1253 /* Return copy of a value */
1254 value *copy_val(environment *env, value *old_value)
1255 {
1256 stackitem *old_item, *new_item, *prev_item;
1257 value *new_value;
1258
1259 protect(old_value);
1260 new_value= new_val(env);
1261 protect(new_value);
1262 new_value->type= old_value->type;
1263
1264 switch(old_value->type){
1265 case tfloat:
1266 case integer:
1267 case func:
1268 case symb:
1269 new_value->content= old_value->content;
1270 break;
1271 case string:
1272 (char *)(new_value->content.ptr)=
1273 strdup((char *)(old_value->content.ptr));
1274 break;
1275 case list:
1276 new_value->content.ptr= NULL;
1277
1278 prev_item= NULL;
1279 old_item= (stackitem*)(old_value->content.ptr);
1280
1281 while(old_item != NULL) { /* While list is not empty */
1282 new_item= malloc(sizeof(stackitem));
1283 new_item->item= copy_val(env, old_item->item); /* recurse */
1284 new_item->next= NULL;
1285 if(prev_item != NULL) /* If this wasn't the first item */
1286 prev_item->next= new_item; /* point the previous item to the
1287 new item */
1288 else
1289 new_value->content.ptr= new_item;
1290 old_item= old_item->next;
1291 prev_item= new_item;
1292 }
1293 break;
1294 }
1295
1296 unprotect(old_value); unprotect(new_value);
1297
1298 return new_value;
1299 }
1300
1301 /* "dup"; duplicates an item on the stack */
1302 extern void sx_647570(environment *env)
1303 {
1304 if((env->head)==NULL) {
1305 printerr("Too Few Arguments");
1306 env->err= 1;
1307 return;
1308 }
1309 push_val(env, copy_val(env, env->head->item));
1310 }
1311
1312 /* "if", If-Then */
1313 extern void sx_6966(environment *env)
1314 {
1315 int truth;
1316
1317 if((env->head)==NULL || env->head->next==NULL) {
1318 printerr("Too Few Arguments");
1319 env->err= 1;
1320 return;
1321 }
1322
1323 if(env->head->next->item->type != integer) {
1324 printerr("Bad Argument Type");
1325 env->err=2;
1326 return;
1327 }
1328
1329 swap(env);
1330 if(env->err) return;
1331
1332 truth=env->head->item->content.i;
1333
1334 toss(env);
1335 if(env->err) return;
1336
1337 if(truth)
1338 eval(env);
1339 else
1340 toss(env);
1341 }
1342
1343 /* If-Then-Else */
1344 extern void ifelse(environment *env)
1345 {
1346 int truth;
1347
1348 if((env->head)==NULL || env->head->next==NULL
1349 || env->head->next->next==NULL) {
1350 printerr("Too Few Arguments");
1351 env->err=1;
1352 return;
1353 }
1354
1355 if(env->head->next->next->item->type != integer) {
1356 printerr("Bad Argument Type");
1357 env->err=2;
1358 return;
1359 }
1360
1361 rot(env);
1362 if(env->err) return;
1363
1364 truth=env->head->item->content.i;
1365
1366 toss(env);
1367 if(env->err) return;
1368
1369 if(!truth)
1370 swap(env);
1371 if(env->err) return;
1372
1373 toss(env);
1374 if(env->err) return;
1375
1376 eval(env);
1377 }
1378
1379 /* "while" */
1380 extern void sx_7768696c65(environment *env)
1381 {
1382 int truth;
1383 value *loop, *test;
1384
1385 if((env->head)==NULL || env->head->next==NULL) {
1386 printerr("Too Few Arguments");
1387 env->err=1;
1388 return;
1389 }
1390
1391 loop= env->head->item;
1392 protect(loop);
1393 toss(env); if(env->err) return;
1394
1395 test= env->head->item;
1396 protect(test);
1397 toss(env); if(env->err) return;
1398
1399 do {
1400 push_val(env, test);
1401 eval(env);
1402
1403 if(env->head->item->type != integer) {
1404 printerr("Bad Argument Type");
1405 env->err= 2;
1406 return;
1407 }
1408
1409 truth= env->head->item->content.i;
1410 toss(env); if(env->err) return;
1411
1412 if(truth) {
1413 push_val(env, loop);
1414 eval(env);
1415 } else {
1416 toss(env);
1417 }
1418
1419 } while(truth);
1420
1421 unprotect(loop); unprotect(test);
1422 }
1423
1424
1425 /* "for"; for-loop */
1426 extern void sx_666f72(environment *env)
1427 {
1428 value *loop;
1429 int foo1, foo2;
1430
1431 if(env->head==NULL || env->head->next==NULL
1432 || env->head->next->next==NULL) {
1433 printerr("Too Few Arguments");
1434 env->err= 1;
1435 return;
1436 }
1437
1438 if(env->head->next->item->type!=integer
1439 || env->head->next->next->item->type!=integer) {
1440 printerr("Bad Argument Type");
1441 env->err= 2;
1442 return;
1443 }
1444
1445 loop= env->head->item;
1446 protect(loop);
1447 toss(env); if(env->err) return;
1448
1449 foo2= env->head->item->content.i;
1450 toss(env); if(env->err) return;
1451
1452 foo1= env->head->item->content.i;
1453 toss(env); if(env->err) return;
1454
1455 if(foo1<=foo2) {
1456 while(foo1<=foo2) {
1457 push_int(env, foo1);
1458 push_val(env, loop);
1459 eval(env); if(env->err) return;
1460 foo1++;
1461 }
1462 } else {
1463 while(foo1>=foo2) {
1464 push_int(env, foo1);
1465 push_val(env, loop);
1466 eval(env); if(env->err) return;
1467 foo1--;
1468 }
1469 }
1470 unprotect(loop);
1471 }
1472
1473 /* Variant of for-loop */
1474 extern void foreach(environment *env)
1475 {
1476 value *loop, *foo;
1477 stackitem *iterator;
1478
1479 if((env->head)==NULL || env->head->next==NULL) {
1480 printerr("Too Few Arguments");
1481 env->err= 1;
1482 return;
1483 }
1484
1485 if(env->head->next->item->type != list) {
1486 printerr("Bad Argument Type");
1487 env->err= 2;
1488 return;
1489 }
1490
1491 loop= env->head->item;
1492 protect(loop);
1493 toss(env); if(env->err) return;
1494
1495 foo= env->head->item;
1496 protect(foo);
1497 toss(env); if(env->err) return;
1498
1499 iterator= foo->content.ptr;
1500
1501 while(iterator!=NULL) {
1502 push_val(env, iterator->item);
1503 push_val(env, loop);
1504 eval(env); if(env->err) return;
1505 iterator= iterator->next;
1506 }
1507 unprotect(loop); unprotect(foo);
1508 }
1509
1510 /* "to" */
1511 extern void to(environment *env)
1512 {
1513 int ending, start, i;
1514 stackitem *iterator, *temp;
1515 value *pack;
1516
1517 if((env->head)==NULL || env->head->next==NULL) {
1518 printerr("Too Few Arguments");
1519 env->err=1;
1520 return;
1521 }
1522
1523 if(env->head->item->type!=integer
1524 || env->head->next->item->type!=integer) {
1525 printerr("Bad Argument Type");
1526 env->err=2;
1527 return;
1528 }
1529
1530 ending= env->head->item->content.i;
1531 toss(env); if(env->err) return;
1532 start= env->head->item->content.i;
1533 toss(env); if(env->err) return;
1534
1535 push_sym(env, "[");
1536
1537 if(ending>=start) {
1538 for(i= ending; i>=start; i--)
1539 push_int(env, i);
1540 } else {
1541 for(i= ending; i<=start; i++)
1542 push_int(env, i);
1543 }
1544
1545 iterator= env->head;
1546 pack= new_val(env);
1547 protect(pack);
1548
1549 if(iterator==NULL
1550 || (iterator->item->type==symb
1551 && ((symbol*)(iterator->item->content.ptr))->id[0]=='[')) {
1552 temp= NULL;
1553 toss(env);
1554 } else {
1555 /* Search for first delimiter */
1556 while(iterator->next!=NULL
1557 && (iterator->next->item->type!=symb
1558 || ((symbol*)(iterator->next->item->content.ptr))->id[0]!='['))
1559 iterator= iterator->next;
1560
1561 /* Extract list */
1562 temp= env->head;
1563 env->head= iterator->next;
1564 iterator->next= NULL;
1565
1566 pack->type= list;
1567 pack->content.ptr= temp;
1568
1569 if(env->head!=NULL)
1570 toss(env);
1571 }
1572
1573 /* Push list */
1574
1575 push_val(env, pack);
1576
1577 unprotect(pack);
1578 }
1579
1580 /* Read a string */
1581 extern void readline(environment *env)
1582 {
1583 char in_string[101];
1584
1585 if(fgets(in_string, 100, env->inputstream)==NULL)
1586 push_cstring(env, "");
1587 else
1588 push_cstring(env, in_string);
1589 }
1590
1591 /* "read"; Read a value and place on stack */
1592 extern void sx_72656164(environment *env)
1593 {
1594 const char symbform[]= "%[a-zA-Z0-9!$%*+./:<=>?@^_~-]%n";
1595 const char strform[]= "\"%[^\"]\"%n";
1596 const char intform[]= "%i%n";
1597 const char fltform[]= "%f%n";
1598 const char blankform[]= "%*[ \t]%n";
1599 const char ebrackform[]= "]%n";
1600 const char semicform[]= ";%n";
1601 const char bbrackform[]= "[%n";
1602
1603 int itemp, readlength= -1;
1604 int count= -1;
1605 float ftemp;
1606 static int depth= 0;
1607 char *match, *ctemp;
1608 size_t inlength;
1609
1610 if(env->in_string==NULL) {
1611 if(depth > 0 && env->interactive) {
1612 printf("]> ");
1613 }
1614 readline(env); if(env->err) return;
1615
1616 if(((char *)(env->head->item->content.ptr))[0]=='\0'){
1617 env->err= 4; /* "" means EOF */
1618 return;
1619 }
1620
1621 env->in_string= malloc(strlen(env->head->item->content.ptr)+1);
1622 env->free_string= env->in_string; /* Save the original pointer */
1623 strcpy(env->in_string, env->head->item->content.ptr);
1624 toss(env); if(env->err) return;
1625 }
1626
1627 inlength= strlen(env->in_string)+1;
1628 match= malloc(inlength);
1629
1630 if(sscanf(env->in_string, blankform, &readlength) != EOF
1631 && readlength != -1) {
1632 ;
1633 } else if(sscanf(env->in_string, fltform, &ftemp, &readlength) != EOF
1634 && readlength != -1) {
1635 if(sscanf(env->in_string, intform, &itemp, &count) != EOF
1636 && count==readlength) {
1637 push_int(env, itemp);
1638 } else {
1639 push_float(env, ftemp);
1640 }
1641 } else if(sscanf(env->in_string, strform, match, &readlength) != EOF
1642 && readlength != -1) {
1643 push_cstring(env, match);
1644 } else if(sscanf(env->in_string, symbform, match, &readlength) != EOF
1645 && readlength != -1) {
1646 push_sym(env, match);
1647 } else if(sscanf(env->in_string, ebrackform, &readlength) != EOF
1648 && readlength != -1) {
1649 pack(env); if(env->err) return;
1650 if(depth != 0) depth--;
1651 } else if(sscanf(env->in_string, semicform, &readlength) != EOF
1652 && readlength != -1) {
1653 push_sym(env, ";");
1654 } else if(sscanf(env->in_string, bbrackform, &readlength) != EOF
1655 && readlength != -1) {
1656 push_sym(env, "[");
1657 depth++;
1658 } else {
1659 free(env->free_string);
1660 env->in_string = env->free_string = NULL;
1661 }
1662 if (env->in_string != NULL) {
1663 env->in_string += readlength;
1664 }
1665
1666 free(match);
1667
1668 if(depth)
1669 return sx_72656164(env);
1670 }
1671
1672 extern void beep(environment *env)
1673 {
1674 int freq, dur, period, ticks;
1675
1676 if((env->head)==NULL || env->head->next==NULL) {
1677 printerr("Too Few Arguments");
1678 env->err=1;
1679 return;
1680 }
1681
1682 if(env->head->item->type!=integer
1683 || env->head->next->item->type!=integer) {
1684 printerr("Bad Argument Type");
1685 env->err=2;
1686 return;
1687 }
1688
1689 dur=env->head->item->content.i;
1690 toss(env);
1691 freq=env->head->item->content.i;
1692 toss(env);
1693
1694 period=1193180/freq; /* convert freq from Hz to period
1695 length */
1696 ticks=dur*.001193180; /* convert duration from µseconds to
1697 timer ticks */
1698
1699 /* ticks=dur/1000; */
1700
1701 /* if (ioctl(STDOUT_FILENO, KDMKTONE, (125<<16) + 0x637)==0) */
1702 switch (ioctl(STDOUT_FILENO, KDMKTONE, (ticks<<16) | period)){
1703 case 0:
1704 usleep(dur);
1705 return;
1706 case -1:
1707 perror("beep");
1708 env->err=5;
1709 return;
1710 default:
1711 abort();
1712 }
1713 }
1714
1715 /* "wait" */
1716 extern void sx_77616974(environment *env)
1717 {
1718 int dur;
1719
1720 if((env->head)==NULL) {
1721 printerr("Too Few Arguments");
1722 env->err=1;
1723 return;
1724 }
1725
1726 if(env->head->item->type!=integer) {
1727 printerr("Bad Argument Type");
1728 env->err=2;
1729 return;
1730 }
1731
1732 dur=env->head->item->content.i;
1733 toss(env);
1734
1735 usleep(dur);
1736 }
1737
1738 extern void copying(environment *env)
1739 {
1740 printf("GNU GENERAL PUBLIC LICENSE\n\
1741 Version 2, June 1991\n\
1742 \n\
1743 Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
1744 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
1745 Everyone is permitted to copy and distribute verbatim copies\n\
1746 of this license document, but changing it is not allowed.\n\
1747 \n\
1748 Preamble\n\
1749 \n\
1750 The licenses for most software are designed to take away your\n\
1751 freedom to share and change it. By contrast, the GNU General Public\n\
1752 License is intended to guarantee your freedom to share and change free\n\
1753 software--to make sure the software is free for all its users. This\n\
1754 General Public License applies to most of the Free Software\n\
1755 Foundation's software and to any other program whose authors commit to\n\
1756 using it. (Some other Free Software Foundation software is covered by\n\
1757 the GNU Library General Public License instead.) You can apply it to\n\
1758 your programs, too.\n\
1759 \n\
1760 When we speak of free software, we are referring to freedom, not\n\
1761 price. Our General Public Licenses are designed to make sure that you\n\
1762 have the freedom to distribute copies of free software (and charge for\n\
1763 this service if you wish), that you receive source code or can get it\n\
1764 if you want it, that you can change the software or use pieces of it\n\
1765 in new free programs; and that you know you can do these things.\n\
1766 \n\
1767 To protect your rights, we need to make restrictions that forbid\n\
1768 anyone to deny you these rights or to ask you to surrender the rights.\n\
1769 These restrictions translate to certain responsibilities for you if you\n\
1770 distribute copies of the software, or if you modify it.\n\
1771 \n\
1772 For example, if you distribute copies of such a program, whether\n\
1773 gratis or for a fee, you must give the recipients all the rights that\n\
1774 you have. You must make sure that they, too, receive or can get the\n\
1775 source code. And you must show them these terms so they know their\n\
1776 rights.\n\
1777 \n\
1778 We protect your rights with two steps: (1) copyright the software, and\n\
1779 (2) offer you this license which gives you legal permission to copy,\n\
1780 distribute and/or modify the software.\n\
1781 \n\
1782 Also, for each author's protection and ours, we want to make certain\n\
1783 that everyone understands that there is no warranty for this free\n\
1784 software. If the software is modified by someone else and passed on, we\n\
1785 want its recipients to know that what they have is not the original, so\n\
1786 that any problems introduced by others will not reflect on the original\n\
1787 authors' reputations.\n\
1788 \n\
1789 Finally, any free program is threatened constantly by software\n\
1790 patents. We wish to avoid the danger that redistributors of a free\n\
1791 program will individually obtain patent licenses, in effect making the\n\
1792 program proprietary. To prevent this, we have made it clear that any\n\
1793 patent must be licensed for everyone's free use or not licensed at all.\n\
1794 \n\
1795 The precise terms and conditions for copying, distribution and\n\
1796 modification follow.\n\
1797 \n\
1798 GNU GENERAL PUBLIC LICENSE\n\
1799 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
1800 \n\
1801 0. This License applies to any program or other work which contains\n\
1802 a notice placed by the copyright holder saying it may be distributed\n\
1803 under the terms of this General Public License. The \"Program\", below,\n\
1804 refers to any such program or work, and a \"work based on the Program\"\n\
1805 means either the Program or any derivative work under copyright law:\n\
1806 that is to say, a work containing the Program or a portion of it,\n\
1807 either verbatim or with modifications and/or translated into another\n\
1808 language. (Hereinafter, translation is included without limitation in\n\
1809 the term \"modification\".) Each licensee is addressed as \"you\".\n\
1810 \n\
1811 Activities other than copying, distribution and modification are not\n\
1812 covered by this License; they are outside its scope. The act of\n\
1813 running the Program is not restricted, and the output from the Program\n\
1814 is covered only if its contents constitute a work based on the\n\
1815 Program (independent of having been made by running the Program).\n\
1816 Whether that is true depends on what the Program does.\n\
1817 \n\
1818 1. You may copy and distribute verbatim copies of the Program's\n\
1819 source code as you receive it, in any medium, provided that you\n\
1820 conspicuously and appropriately publish on each copy an appropriate\n\
1821 copyright notice and disclaimer of warranty; keep intact all the\n\
1822 notices that refer to this License and to the absence of any warranty;\n\
1823 and give any other recipients of the Program a copy of this License\n\
1824 along with the Program.\n\
1825 \n\
1826 You may charge a fee for the physical act of transferring a copy, and\n\
1827 you may at your option offer warranty protection in exchange for a fee.\n\
1828 \n\
1829 2. You may modify your copy or copies of the Program or any portion\n\
1830 of it, thus forming a work based on the Program, and copy and\n\
1831 distribute such modifications or work under the terms of Section 1\n\
1832 above, provided that you also meet all of these conditions:\n\
1833 \n\
1834 a) You must cause the modified files to carry prominent notices\n\
1835 stating that you changed the files and the date of any change.\n\
1836 \n\
1837 b) You must cause any work that you distribute or publish, that in\n\
1838 whole or in part contains or is derived from the Program or any\n\
1839 part thereof, to be licensed as a whole at no charge to all third\n\
1840 parties under the terms of this License.\n\
1841 \n\
1842 c) If the modified program normally reads commands interactively\n\
1843 when run, you must cause it, when started running for such\n\
1844 interactive use in the most ordinary way, to print or display an\n\
1845 announcement including an appropriate copyright notice and a\n\
1846 notice that there is no warranty (or else, saying that you provide\n\
1847 a warranty) and that users may redistribute the program under\n\
1848 these conditions, and telling the user how to view a copy of this\n\
1849 License. (Exception: if the Program itself is interactive but\n\
1850 does not normally print such an announcement, your work based on\n\
1851 the Program is not required to print an announcement.)\n\
1852 \n\
1853 These requirements apply to the modified work as a whole. If\n\
1854 identifiable sections of that work are not derived from the Program,\n\
1855 and can be reasonably considered independent and separate works in\n\
1856 themselves, then this License, and its terms, do not apply to those\n\
1857 sections when you distribute them as separate works. But when you\n\
1858 distribute the same sections as part of a whole which is a work based\n\
1859 on the Program, the distribution of the whole must be on the terms of\n\
1860 this License, whose permissions for other licensees extend to the\n\
1861 entire whole, and thus to each and every part regardless of who wrote it.\n\
1862 \n\
1863 Thus, it is not the intent of this section to claim rights or contest\n\
1864 your rights to work written entirely by you; rather, the intent is to\n\
1865 exercise the right to control the distribution of derivative or\n\
1866 collective works based on the Program.\n\
1867 \n\
1868 In addition, mere aggregation of another work not based on the Program\n\
1869 with the Program (or with a work based on the Program) on a volume of\n\
1870 a storage or distribution medium does not bring the other work under\n\
1871 the scope of this License.\n\
1872 \n\
1873 3. You may copy and distribute the Program (or a work based on it,\n\
1874 under Section 2) in object code or executable form under the terms of\n\
1875 Sections 1 and 2 above provided that you also do one of the following:\n\
1876 \n\
1877 a) Accompany it with the complete corresponding machine-readable\n\
1878 source code, which must be distributed under the terms of Sections\n\
1879 1 and 2 above on a medium customarily used for software interchange; or,\n\
1880 \n\
1881 b) Accompany it with a written offer, valid for at least three\n\
1882 years, to give any third party, for a charge no more than your\n\
1883 cost of physically performing source distribution, a complete\n\
1884 machine-readable copy of the corresponding source code, to be\n\
1885 distributed under the terms of Sections 1 and 2 above on a medium\n\
1886 customarily used for software interchange; or,\n\
1887 \n\
1888 c) Accompany it with the information you received as to the offer\n\
1889 to distribute corresponding source code. (This alternative is\n\
1890 allowed only for noncommercial distribution and only if you\n\
1891 received the program in object code or executable form with such\n\
1892 an offer, in accord with Subsection b above.)\n\
1893 \n\
1894 The source code for a work means the preferred form of the work for\n\
1895 making modifications to it. For an executable work, complete source\n\
1896 code means all the source code for all modules it contains, plus any\n\
1897 associated interface definition files, plus the scripts used to\n\
1898 control compilation and installation of the executable. However, as a\n\
1899 special exception, the source code distributed need not include\n\
1900 anything that is normally distributed (in either source or binary\n\
1901 form) with the major components (compiler, kernel, and so on) of the\n\
1902 operating system on which the executable runs, unless that component\n\
1903 itself accompanies the executable.\n\
1904 \n\
1905 If distribution of executable or object code is made by offering\n\
1906 access to copy from a designated place, then offering equivalent\n\
1907 access to copy the source code from the same place counts as\n\
1908 distribution of the source code, even though third parties are not\n\
1909 compelled to copy the source along with the object code.\n\
1910 \n\
1911 4. You may not copy, modify, sublicense, or distribute the Program\n\
1912 except as expressly provided under this License. Any attempt\n\
1913 otherwise to copy, modify, sublicense or distribute the Program is\n\
1914 void, and will automatically terminate your rights under this License.\n\
1915 However, parties who have received copies, or rights, from you under\n\
1916 this License will not have their licenses terminated so long as such\n\
1917 parties remain in full compliance.\n\
1918 \n\
1919 5. You are not required to accept this License, since you have not\n\
1920 signed it. However, nothing else grants you permission to modify or\n\
1921 distribute the Program or its derivative works. These actions are\n\
1922 prohibited by law if you do not accept this License. Therefore, by\n\
1923 modifying or distributing the Program (or any work based on the\n\
1924 Program), you indicate your acceptance of this License to do so, and\n\
1925 all its terms and conditions for copying, distributing or modifying\n\
1926 the Program or works based on it.\n\
1927 \n\
1928 6. Each time you redistribute the Program (or any work based on the\n\
1929 Program), the recipient automatically receives a license from the\n\
1930 original licensor to copy, distribute or modify the Program subject to\n\
1931 these terms and conditions. You may not impose any further\n\
1932 restrictions on the recipients' exercise of the rights granted herein.\n\
1933 You are not responsible for enforcing compliance by third parties to\n\
1934 this License.\n\
1935 \n\
1936 7. If, as a consequence of a court judgment or allegation of patent\n\
1937 infringement or for any other reason (not limited to patent issues),\n\
1938 conditions are imposed on you (whether by court order, agreement or\n\
1939 otherwise) that contradict the conditions of this License, they do not\n\
1940 excuse you from the conditions of this License. If you cannot\n\
1941 distribute so as to satisfy simultaneously your obligations under this\n\
1942 License and any other pertinent obligations, then as a consequence you\n\
1943 may not distribute the Program at all. For example, if a patent\n\
1944 license would not permit royalty-free redistribution of the Program by\n\
1945 all those who receive copies directly or indirectly through you, then\n\
1946 the only way you could satisfy both it and this License would be to\n\
1947 refrain entirely from distribution of the Program.\n\
1948 \n\
1949 If any portion of this section is held invalid or unenforceable under\n\
1950 any particular circumstance, the balance of the section is intended to\n\
1951 apply and the section as a whole is intended to apply in other\n\
1952 circumstances.\n\
1953 \n\
1954 It is not the purpose of this section to induce you to infringe any\n\
1955 patents or other property right claims or to contest validity of any\n\
1956 such claims; this section has the sole purpose of protecting the\n\
1957 integrity of the free software distribution system, which is\n\
1958 implemented by public license practices. Many people have made\n\
1959 generous contributions to the wide range of software distributed\n\
1960 through that system in reliance on consistent application of that\n\
1961 system; it is up to the author/donor to decide if he or she is willing\n\
1962 to distribute software through any other system and a licensee cannot\n\
1963 impose that choice.\n\
1964 \n\
1965 This section is intended to make thoroughly clear what is believed to\n\
1966 be a consequence of the rest of this License.\n\
1967 \n\
1968 8. If the distribution and/or use of the Program is restricted in\n\
1969 certain countries either by patents or by copyrighted interfaces, the\n\
1970 original copyright holder who places the Program under this License\n\
1971 may add an explicit geographical distribution limitation excluding\n\
1972 those countries, so that distribution is permitted only in or among\n\
1973 countries not thus excluded. In such case, this License incorporates\n\
1974 the limitation as if written in the body of this License.\n\
1975 \n\
1976 9. The Free Software Foundation may publish revised and/or new versions\n\
1977 of the General Public License from time to time. Such new versions will\n\
1978 be similar in spirit to the present version, but may differ in detail to\n\
1979 address new problems or concerns.\n\
1980 \n\
1981 Each version is given a distinguishing version number. If the Program\n\
1982 specifies a version number of this License which applies to it and \"any\n\
1983 later version\", you have the option of following the terms and conditions\n\
1984 either of that version or of any later version published by the Free\n\
1985 Software Foundation. If the Program does not specify a version number of\n\
1986 this License, you may choose any version ever published by the Free Software\n\
1987 Foundation.\n\
1988 \n\
1989 10. If you wish to incorporate parts of the Program into other free\n\
1990 programs whose distribution conditions are different, write to the author\n\
1991 to ask for permission. For software which is copyrighted by the Free\n\
1992 Software Foundation, write to the Free Software Foundation; we sometimes\n\
1993 make exceptions for this. Our decision will be guided by the two goals\n\
1994 of preserving the free status of all derivatives of our free software and\n\
1995 of promoting the sharing and reuse of software generally.\n");
1996 }
1997
1998 extern void warranty(environment *env)
1999 {
2000 printf(" NO WARRANTY\n\
2001 \n\
2002 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
2003 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n\
2004 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
2005 PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
2006 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
2007 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n\
2008 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n\
2009 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
2010 REPAIR OR CORRECTION.\n\
2011 \n\
2012 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
2013 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
2014 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
2015 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
2016 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
2017 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
2018 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
2019 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
2020 POSSIBILITY OF SUCH DAMAGES.\n");
2021 }
2022
2023 /* "*" */
2024 extern void sx_2a(environment *env)
2025 {
2026 int a, b;
2027 float fa, fb;
2028
2029 if((env->head)==NULL || env->head->next==NULL) {
2030 printerr("Too Few Arguments");
2031 env->err=1;
2032 return;
2033 }
2034
2035 if(env->head->item->type==integer
2036 && env->head->next->item->type==integer) {
2037 a=env->head->item->content.i;
2038 toss(env); if(env->err) return;
2039 b=env->head->item->content.i;
2040 toss(env); if(env->err) return;
2041 push_int(env, b*a);
2042
2043 return;
2044 }
2045
2046 if(env->head->item->type==tfloat
2047 && env->head->next->item->type==tfloat) {
2048 fa= env->head->item->content.f;
2049 toss(env); if(env->err) return;
2050 fb= env->head->item->content.f;
2051 toss(env); if(env->err) return;
2052 push_float(env, fb*fa);
2053
2054 return;
2055 }
2056
2057 if(env->head->item->type==tfloat
2058 && env->head->next->item->type==integer) {
2059 fa= env->head->item->content.f;
2060 toss(env); if(env->err) return;
2061 b= env->head->item->content.i;
2062 toss(env); if(env->err) return;
2063 push_float(env, b*fa);
2064
2065 return;
2066 }
2067
2068 if(env->head->item->type==integer
2069 && env->head->next->item->type==tfloat) {
2070 a= env->head->item->content.i;
2071 toss(env); if(env->err) return;
2072 fb= env->head->item->content.f;
2073 toss(env); if(env->err) return;
2074 push_float(env, fb*a);
2075
2076 return;
2077 }
2078
2079 printerr("Bad Argument Type");
2080 env->err=2;
2081 }
2082
2083 /* "/" */
2084 extern void sx_2f(environment *env)
2085 {
2086 int a, b;
2087 float fa, fb;
2088
2089 if((env->head)==NULL || env->head->next==NULL) {
2090 printerr("Too Few Arguments");
2091 env->err=1;
2092 return;
2093 }
2094
2095 if(env->head->item->type==integer
2096 && env->head->next->item->type==integer) {
2097 a=env->head->item->content.i;
2098 toss(env); if(env->err) return;
2099 b=env->head->item->content.i;
2100 toss(env); if(env->err) return;
2101 push_float(env, b/a);
2102
2103 return;
2104 }
2105
2106 if(env->head->item->type==tfloat
2107 && env->head->next->item->type==tfloat) {
2108 fa= env->head->item->content.f;
2109 toss(env); if(env->err) return;
2110 fb= env->head->item->content.f;
2111 toss(env); if(env->err) return;
2112 push_float(env, fb/fa);
2113
2114 return;
2115 }
2116
2117 if(env->head->item->type==tfloat
2118 && env->head->next->item->type==integer) {
2119 fa= env->head->item->content.f;
2120 toss(env); if(env->err) return;
2121 b= env->head->item->content.i;
2122 toss(env); if(env->err) return;
2123 push_float(env, b/fa);
2124
2125 return;
2126 }
2127
2128 if(env->head->item->type==integer
2129 && env->head->next->item->type==tfloat) {
2130 a= env->head->item->content.i;
2131 toss(env); if(env->err) return;
2132 fb= env->head->item->content.f;
2133 toss(env); if(env->err) return;
2134 push_float(env, fb/a);
2135
2136 return;
2137 }
2138
2139 printerr("Bad Argument Type");
2140 env->err=2;
2141 }
2142
2143 /* "mod" */
2144 extern void mod(environment *env)
2145 {
2146 int a, b;
2147
2148 if((env->head)==NULL || env->head->next==NULL) {
2149 printerr("Too Few Arguments");
2150 env->err= 1;
2151 return;
2152 }
2153
2154 if(env->head->item->type==integer
2155 && env->head->next->item->type==integer) {
2156 a= env->head->item->content.i;
2157 toss(env); if(env->err) return;
2158 b= env->head->item->content.i;
2159 toss(env); if(env->err) return;
2160 push_int(env, b%a);
2161
2162 return;
2163 }
2164
2165 printerr("Bad Argument Type");
2166 env->err=2;
2167 }
2168
2169 /* "div" */
2170 extern void sx_646976(environment *env)
2171 {
2172 int a, b;
2173
2174 if((env->head)==NULL || env->head->next==NULL) {
2175 printerr("Too Few Arguments");
2176 env->err= 1;
2177 return;
2178 }
2179
2180 if(env->head->item->type==integer
2181 && env->head->next->item->type==integer) {
2182 a= env->head->item->content.i;
2183 toss(env); if(env->err) return;
2184 b= env->head->item->content.i;
2185 toss(env); if(env->err) return;
2186 push_int(env, (int)b/a);
2187
2188 return;
2189 }
2190
2191 printerr("Bad Argument Type");
2192 env->err= 2;
2193 }

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26