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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.95 - (show annotations)
Sun Mar 10 06:34:01 2002 UTC (22 years, 1 month ago) by masse
Branch: MAIN
Changes since 1.94: +123 -63 lines
File MIME type: text/plain
Cosmetic changes.
stack.c (to): Rewritten to mimic behaviour of "pack".

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26