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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.91 - (show annotations)
Thu Mar 7 03:28:29 2002 UTC (22 years, 1 month ago) by teddy
Branch: MAIN
Changes since 1.90: +385 -2 lines
File MIME type: text/plain
GPL stuff:
stack.c, stack.h, Makefile: Added notices
stack.c (copying, warranty): New functions.
stack.h (copying, warranty): - '' -

Other stuff:
Makefile (stack): New explicit rule to depend on "stack.h" too.
(mtrace): Depend on "stack", not "all".
(check): New target.
stack.c (main): Don't return error on EOF.
(beep, wait): New functions.
stack.h (beep, wait): - '' -

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26