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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.130 - (hide annotations)
Mon Aug 4 14:32:27 2003 UTC (20 years, 8 months ago) by masse
Branch: MAIN
Changes since 1.129: +4 -4 lines
File MIME type: text/plain
Removed some more "content.ptr".

1 teddy 1.116 /* -*- coding: utf-8; -*- */
2 teddy 1.91 /*
3     stack - an interactive interpreter for a stack-based language
4     Copyright (C) 2002 Mats Alritzson and Teddy Hogeborn
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19    
20     Authors: Mats Alritzson <masse@fukt.bth.se>
21     Teddy Hogeborn <teddy@fukt.bth.se>
22     */
23    
24 teddy 1.88 #include "stack.h"
25 masse 1.1
26 teddy 1.28 /* Initialize a newly created environment */
27     void init_env(environment *env)
28 masse 1.1 {
29 masse 1.46 int i;
30 masse 1.1
31 teddy 1.100 env->gc_limit= 400000;
32 masse 1.87 env->gc_count= 0;
33 masse 1.90 env->gc_ref= NULL;
34 masse 1.87
35 teddy 1.111 env->head= new_val(env);
36 masse 1.1 for(i= 0; i<HASHTBLSIZE; i++)
37 teddy 1.28 env->symbols[i]= NULL;
38 teddy 1.84 env->err= 0;
39     env->in_string= NULL;
40     env->free_string= NULL;
41     env->inputstream= stdin;
42     env->interactive= 1;
43 masse 1.1 }
44    
45 masse 1.95 void printerr(const char* in_string)
46     {
47 teddy 1.48 fprintf(stderr, "Err: %s\n", in_string);
48     }
49    
50 teddy 1.27 /* Returns a pointer to a pointer to an element in the hash table. */
51 teddy 1.28 symbol **hash(hashtbl in_hashtbl, const char *in_string)
52 masse 1.1 {
53 masse 1.46 int i= 0;
54     unsigned int out_hash= 0;
55 teddy 1.18 char key= '\0';
56 teddy 1.28 symbol **position;
57 masse 1.1
58 masse 1.16 while(1){ /* Hash in_string */
59 masse 1.1 key= in_string[i++];
60     if(key=='\0')
61     break;
62     out_hash= out_hash*32+key;
63     }
64    
65     out_hash= out_hash%HASHTBLSIZE;
66     position= &(in_hashtbl[out_hash]);
67    
68 masse 1.25 while(1){
69 teddy 1.18 if(*position==NULL) /* If empty */
70 masse 1.1 return position;
71    
72 teddy 1.18 if(strcmp(in_string, (*position)->id)==0) /* If match */
73 masse 1.1 return position;
74    
75 masse 1.16 position= &((*position)->next); /* Try next */
76 masse 1.1 }
77     }
78    
79 masse 1.95 /* Create new value */
80     value* new_val(environment *env)
81     {
82 masse 1.87 value *nval= malloc(sizeof(value));
83     stackitem *nitem= malloc(sizeof(stackitem));
84    
85 teddy 1.118 assert(nval != NULL);
86     assert(nitem != NULL);
87    
88 masse 1.87 nval->content.ptr= NULL;
89 teddy 1.117 nval->type= empty;
90 masse 1.87
91     nitem->item= nval;
92     nitem->next= env->gc_ref;
93 masse 1.102
94 masse 1.87 env->gc_ref= nitem;
95    
96 teddy 1.101 env->gc_count += sizeof(value);
97 teddy 1.99 nval->gc.flag.mark= 0;
98     nval->gc.flag.protect= 0;
99 masse 1.93
100 masse 1.87 return nval;
101     }
102    
103 masse 1.126
104 masse 1.95 /* Mark values recursively.
105     Marked values are not collected by the GC. */
106 teddy 1.96 inline void gc_mark(value *val)
107 masse 1.95 {
108 masse 1.102 if(val==NULL || val->gc.flag.mark)
109 masse 1.87 return;
110    
111 teddy 1.99 val->gc.flag.mark= 1;
112 masse 1.87
113 masse 1.104 if(val->type==tcons) {
114     gc_mark(CAR(val));
115     gc_mark(CDR(val));
116 masse 1.87 }
117     }
118    
119 teddy 1.96
120 masse 1.95 /* Start GC */
121     extern void gc_init(environment *env)
122     {
123 masse 1.102 stackitem *new_head= NULL, *titem;
124 masse 1.87 symbol *tsymb;
125     int i;
126    
127 masse 1.102 if(env->interactive)
128 teddy 1.101 printf("Garbage collecting.");
129 teddy 1.100
130 masse 1.95 /* Mark values on stack */
131 masse 1.104 gc_mark(env->head);
132 masse 1.87
133 masse 1.102 if(env->interactive)
134 teddy 1.100 printf(".");
135 masse 1.102
136 teddy 1.100
137 masse 1.93 /* Mark values in hashtable */
138 masse 1.102 for(i= 0; i<HASHTBLSIZE; i++)
139     for(tsymb= env->symbols[i]; tsymb!=NULL; tsymb= tsymb->next)
140 masse 1.97 if (tsymb->val != NULL)
141     gc_mark(tsymb->val);
142 masse 1.87
143 masse 1.102
144     if(env->interactive)
145 teddy 1.100 printf(".");
146 masse 1.102
147 masse 1.87 env->gc_count= 0;
148    
149 masse 1.95 while(env->gc_ref!=NULL) { /* Sweep unused values */
150 masse 1.90
151 teddy 1.99 if(!(env->gc_ref->item->gc.no_gc)){ /* neither mark nor protect */
152 masse 1.93
153 teddy 1.116 /* Remove content */
154     switch(env->gc_ref->item->type){
155     case string:
156 masse 1.130 free(env->gc_ref->item->content.string);
157 teddy 1.116 break;
158     case tcons:
159     free(env->gc_ref->item->content.c);
160     break;
161 teddy 1.124 case port:
162 teddy 1.116 case empty:
163     case integer:
164     case tfloat:
165     case func:
166     case symb:
167     /* Symbol strings are freed when walking the hash table */
168 masse 1.126 break;
169 teddy 1.116 }
170 masse 1.102
171 masse 1.93 free(env->gc_ref->item); /* Remove from gc_ref */
172 masse 1.87 titem= env->gc_ref->next;
173 masse 1.93 free(env->gc_ref); /* Remove value */
174 masse 1.87 env->gc_ref= titem;
175 masse 1.97 continue;
176 teddy 1.110 }
177     #ifdef DEBUG
178     printf("Kept value (%p)", env->gc_ref->item);
179     if(env->gc_ref->item->gc.flag.mark)
180     printf(" (marked)");
181     if(env->gc_ref->item->gc.flag.protect)
182     printf(" (protected)");
183     switch(env->gc_ref->item->type){
184     case integer:
185     printf(" integer: %d", env->gc_ref->item->content.i);
186     break;
187     case func:
188 masse 1.128 printf(" func: %p", env->gc_ref->item->content.func);
189 teddy 1.110 break;
190     case symb:
191     printf(" symb: %s", env->gc_ref->item->content.sym->id);
192     break;
193     case tcons:
194 masse 1.127 printf(" tcons: %p\t%p", CAR(env->gc_ref->item),
195     CDR(env->gc_ref->item));
196 teddy 1.110 break;
197     default:
198     printf(" <unknown %d>", (env->gc_ref->item->type));
199     }
200     printf("\n");
201     #endif /* DEBUG */
202 masse 1.102
203     /* Keep values */
204     env->gc_count += sizeof(value);
205     if(env->gc_ref->item->type==string)
206 masse 1.128 env->gc_count += strlen(env->gc_ref->item->content.string)+1;
207 masse 1.97
208     titem= env->gc_ref->next;
209     env->gc_ref->next= new_head;
210     new_head= env->gc_ref;
211 teddy 1.99 new_head->item->gc.flag.mark= 0;
212 masse 1.97 env->gc_ref= titem;
213 masse 1.87 }
214    
215 teddy 1.100 if (env->gc_limit < env->gc_count*2)
216     env->gc_limit= env->gc_count*2;
217 teddy 1.101
218 masse 1.87 env->gc_ref= new_head;
219 teddy 1.100
220 masse 1.102 if(env->interactive)
221 teddy 1.110 printf("done (%d bytes still allocated)\n", env->gc_count);
222 teddy 1.100
223 masse 1.87 }
224    
225 masse 1.126 inline void gc_maybe(environment *env)
226     {
227     if(env->gc_count < env->gc_limit)
228     return;
229     else
230     return gc_init(env);
231     }
232    
233 masse 1.95 /* Protect values from GC */
234 masse 1.98 void protect(value *val)
235 masse 1.90 {
236 masse 1.102 if(val==NULL || val->gc.flag.protect)
237 masse 1.98 return;
238    
239 teddy 1.99 val->gc.flag.protect= 1;
240 masse 1.98
241 masse 1.104 if(val->type==tcons) {
242     protect(CAR(val));
243     protect(CDR(val));
244 masse 1.98 }
245 masse 1.90 }
246    
247 masse 1.95 /* Unprotect values from GC */
248 masse 1.98 void unprotect(value *val)
249 masse 1.90 {
250 masse 1.102 if(val==NULL || !(val->gc.flag.protect))
251 masse 1.98 return;
252    
253 teddy 1.99 val->gc.flag.protect= 0;
254 masse 1.98
255 masse 1.104 if(val->type==tcons) {
256     unprotect(CAR(val));
257     unprotect(CDR(val));
258 masse 1.98 }
259 masse 1.90 }
260    
261 teddy 1.29 /* Push a value onto the stack */
262 masse 1.72 void push_val(environment *env, value *val)
263 teddy 1.29 {
264 masse 1.104 value *new_value= new_val(env);
265 masse 1.102
266 teddy 1.115 new_value->content.c= malloc(sizeof(pair));
267 masse 1.108 assert(new_value->content.c!=NULL);
268 teddy 1.116 env->gc_count += sizeof(pair);
269 masse 1.104 new_value->type= tcons;
270     CAR(new_value)= val;
271     CDR(new_value)= env->head;
272     env->head= new_value;
273 teddy 1.29 }
274    
275 masse 1.95 /* Push an integer onto the stack */
276 masse 1.72 void push_int(environment *env, int in_val)
277 masse 1.1 {
278 masse 1.87 value *new_value= new_val(env);
279 teddy 1.28
280 masse 1.93 new_value->content.i= in_val;
281 teddy 1.28 new_value->type= integer;
282 masse 1.1
283 masse 1.75 push_val(env, new_value);
284 masse 1.1 }
285    
286 masse 1.95 /* Push a floating point number onto the stack */
287 masse 1.93 void push_float(environment *env, float in_val)
288     {
289     value *new_value= new_val(env);
290    
291     new_value->content.f= in_val;
292     new_value->type= tfloat;
293    
294     push_val(env, new_value);
295     }
296    
297 masse 1.14 /* Copy a string onto the stack. */
298 masse 1.72 void push_cstring(environment *env, const char *in_string)
299 masse 1.1 {
300 masse 1.87 value *new_value= new_val(env);
301 teddy 1.101 int length= strlen(in_string)+1;
302 teddy 1.28
303 masse 1.128 new_value->content.string= malloc(length);
304 teddy 1.118 assert(new_value != NULL);
305 teddy 1.101 env->gc_count += length;
306 masse 1.128 strcpy(new_value->content.string, in_string);
307 teddy 1.28 new_value->type= string;
308 masse 1.1
309 masse 1.75 push_val(env, new_value);
310 masse 1.1 }
311    
312 teddy 1.48 /* Mangle a symbol name to a valid C identifier name */
313 masse 1.95 char *mangle_str(const char *old_string)
314     {
315 masse 1.90 char validchars[]= "0123456789abcdef";
316 teddy 1.48 char *new_string, *current;
317    
318 masse 1.90 new_string= malloc((strlen(old_string)*2)+4);
319 teddy 1.118 assert(new_string != NULL);
320 teddy 1.48 strcpy(new_string, "sx_"); /* Stack eXternal */
321 masse 1.90 current= new_string+3;
322 teddy 1.48 while(old_string[0] != '\0'){
323 masse 1.90 current[0]= validchars[(unsigned char)(old_string[0])/16];
324     current[1]= validchars[(unsigned char)(old_string[0])%16];
325     current+= 2;
326 teddy 1.48 old_string++;
327     }
328 masse 1.90 current[0]= '\0';
329 teddy 1.48
330     return new_string; /* The caller must free() it */
331     }
332    
333 masse 1.95 extern void mangle(environment *env)
334     {
335 teddy 1.48 char *new_string;
336    
337 teddy 1.111 if(env->head->type==empty) {
338 teddy 1.48 printerr("Too Few Arguments");
339 masse 1.90 env->err= 1;
340 teddy 1.48 return;
341     }
342    
343 masse 1.104 if(CAR(env->head)->type!=string) {
344 teddy 1.48 printerr("Bad Argument Type");
345 masse 1.90 env->err= 2;
346 teddy 1.48 return;
347     }
348    
349 masse 1.128 new_string= mangle_str(CAR(env->head)->content.string);
350 teddy 1.48
351     toss(env);
352     if(env->err) return;
353    
354 masse 1.81 push_cstring(env, new_string);
355 teddy 1.48 }
356    
357 teddy 1.28 /* Push a symbol onto the stack. */
358 teddy 1.35 void push_sym(environment *env, const char *in_string)
359 masse 1.1 {
360 teddy 1.28 value *new_value; /* A new symbol value */
361     /* ...which might point to... */
362 teddy 1.29 symbol **new_symbol; /* (if needed) A new actual symbol */
363 teddy 1.28 /* ...which, if possible, will be bound to... */
364     value *new_fvalue; /* (if needed) A new function value */
365     /* ...which will point to... */
366     void *funcptr; /* A function pointer */
367    
368     static void *handle= NULL; /* Dynamic linker handle */
369 teddy 1.48 const char *dlerr; /* Dynamic linker error */
370     char *mangled; /* Mangled function name */
371 teddy 1.28
372 masse 1.87 new_value= new_val(env);
373 masse 1.98 protect(new_value);
374 masse 1.93 new_fvalue= new_val(env);
375 masse 1.98 protect(new_fvalue);
376 teddy 1.28
377     /* The new value is a symbol */
378     new_value->type= symb;
379    
380     /* Look up the symbol name in the hash table */
381 teddy 1.29 new_symbol= hash(env->symbols, in_string);
382 masse 1.130 new_value->content.sym= *new_symbol;
383 teddy 1.28
384 teddy 1.30 if(*new_symbol==NULL) { /* If symbol was undefined */
385 teddy 1.28
386     /* Create a new symbol */
387 teddy 1.30 (*new_symbol)= malloc(sizeof(symbol));
388 teddy 1.118 assert((*new_symbol) != NULL);
389 teddy 1.29 (*new_symbol)->val= NULL; /* undefined value */
390     (*new_symbol)->next= NULL;
391     (*new_symbol)->id= malloc(strlen(in_string)+1);
392 teddy 1.118 assert((*new_symbol)->id != NULL);
393 teddy 1.29 strcpy((*new_symbol)->id, in_string);
394 masse 1.1
395 teddy 1.28 /* Intern the new symbol in the hash table */
396 masse 1.130 new_value->content.sym= *new_symbol;
397 masse 1.1
398 teddy 1.28 /* Try to load the symbol name as an external function, to see if
399     we should bind the symbol to a new function pointer value */
400 masse 1.16 if(handle==NULL) /* If no handle */
401 teddy 1.28 handle= dlopen(NULL, RTLD_LAZY);
402 masse 1.6
403 masse 1.90 mangled= mangle_str(in_string); /* mangle the name */
404 teddy 1.86 funcptr= dlsym(handle, mangled); /* and try to find it */
405 masse 1.95
406 masse 1.90 dlerr= dlerror();
407 teddy 1.48 if(dlerr != NULL) { /* If no function was found */
408 teddy 1.86 funcptr= dlsym(handle, in_string); /* Get function pointer */
409 masse 1.90 dlerr= dlerror();
410 teddy 1.48 }
411 masse 1.95
412 teddy 1.48 if(dlerr==NULL) { /* If a function was found */
413 masse 1.90 new_fvalue->type= func; /* The new value is a function pointer */
414 masse 1.128 new_fvalue->content.func= funcptr; /* Store function pointer */
415 teddy 1.29 (*new_symbol)->val= new_fvalue; /* Bind the symbol to the new
416     function value */
417 teddy 1.28 }
418 masse 1.95
419     free(mangled);
420 masse 1.1 }
421 masse 1.95
422 masse 1.75 push_val(env, new_value);
423 masse 1.98 unprotect(new_value); unprotect(new_fvalue);
424 masse 1.1 }
425    
426 teddy 1.114 /* Print a value */
427 teddy 1.124 void print_val(environment *env, value *val, int noquote, stackitem *stack, FILE *stream)
428 masse 1.8 {
429 teddy 1.117 stackitem *titem, *tstack;
430     int depth;
431    
432 teddy 1.113 switch(val->type) {
433 teddy 1.112 case empty:
434 teddy 1.124 if(fprintf(stream, "[]") < 0){
435     perror("print_val");
436     env->err= 5;
437     return;
438     }
439 teddy 1.112 break;
440 teddy 1.28 case integer:
441 teddy 1.124 if(fprintf(stream, "%d", val->content.i) < 0){
442     perror("print_val");
443     env->err= 5;
444     return;
445     }
446 masse 1.93 break;
447     case tfloat:
448 teddy 1.124 if(fprintf(stream, "%f", val->content.f) < 0){
449     perror("print_val");
450     env->err= 5;
451     return;
452     }
453 teddy 1.2 break;
454     case string:
455 teddy 1.124 if(noquote){
456 masse 1.128 if(fprintf(stream, "%s", val->content.string) < 0){
457 teddy 1.124 perror("print_val");
458     env->err= 5;
459     return;
460     }
461     } else { /* quote */
462 masse 1.128 if(fprintf(stream, "\"%s\"", val->content.string) < 0){
463 teddy 1.124 perror("print_val");
464     env->err= 5;
465     return;
466     }
467     }
468 teddy 1.2 break;
469 teddy 1.28 case symb:
470 teddy 1.124 if(fprintf(stream, "%s", val->content.sym->id) < 0){
471     perror("print_val");
472     env->err= 5;
473     return;
474     }
475 masse 1.6 break;
476 teddy 1.35 case func:
477 masse 1.128 if(fprintf(stream, "#<function %p>", val->content.func) < 0){
478 teddy 1.124 perror("print_val");
479     env->err= 5;
480     return;
481     }
482     break;
483     case port:
484 masse 1.128 if(fprintf(stream, "#<port %p>", val->content.p) < 0){
485 teddy 1.124 perror("print_val");
486     env->err= 5;
487     return;
488     }
489 teddy 1.35 break;
490 masse 1.102 case tcons:
491 teddy 1.124 if(fprintf(stream, "[ ") < 0){
492     perror("print_val");
493     env->err= 5;
494     return;
495     }
496 teddy 1.117 tstack= stack;
497 teddy 1.113 do {
498 teddy 1.117 titem=malloc(sizeof(stackitem));
499 teddy 1.118 assert(titem != NULL);
500 teddy 1.117 titem->item=val;
501     titem->next=tstack;
502     tstack=titem; /* Put it on the stack */
503     /* Search a stack of values being printed to see if we are already
504     printing this value */
505     titem=tstack;
506     depth=0;
507     while(titem != NULL && titem->item != CAR(val)){
508     titem=titem->next;
509     depth++;
510     }
511     if(titem != NULL){ /* If we found it on the stack, */
512 teddy 1.124 if(fprintf(stream, "#%d#", depth) < 0){ /* print a depth reference */
513     perror("print_val");
514     env->err= 5;
515     free(titem);
516     return;
517     }
518 teddy 1.117 } else {
519 teddy 1.124 print_val(env, CAR(val), noquote, tstack, stream);
520 teddy 1.117 }
521 teddy 1.114 val= CDR(val);
522     switch(val->type){
523 teddy 1.112 case empty:
524     break;
525     case tcons:
526 teddy 1.117 /* Search a stack of values being printed to see if we are already
527     printing this value */
528     titem=tstack;
529     depth=0;
530     while(titem != NULL && titem->item != val){
531     titem=titem->next;
532     depth++;
533     }
534     if(titem != NULL){ /* If we found it on the stack, */
535 teddy 1.124 if(fprintf(stream, " . #%d#", depth) < 0){ /* print a depth reference */
536     perror("print_val");
537     env->err= 5;
538     goto printval_end;
539     }
540 teddy 1.117 } else {
541 teddy 1.124 if(fprintf(stream, " ") < 0){
542     perror("print_val");
543     env->err= 5;
544     goto printval_end;
545     }
546 teddy 1.117 }
547 teddy 1.112 break;
548     default:
549 teddy 1.124 if(fprintf(stream, " . ") < 0){ /* Improper list */
550     perror("print_val");
551     env->err= 5;
552     goto printval_end;
553     }
554     print_val(env, val, noquote, tstack, stream);
555 teddy 1.112 }
556 teddy 1.117 } while(val->type == tcons && titem == NULL);
557 teddy 1.124
558     printval_end:
559    
560 teddy 1.117 titem=tstack;
561     while(titem != stack){
562     tstack=titem->next;
563     free(titem);
564     titem=tstack;
565     }
566 teddy 1.124
567     if(! (env->err)){
568     if(fprintf(stream, " ]") < 0){
569     perror("print_val");
570     env->err= 5;
571     }
572     }
573 teddy 1.35 break;
574 teddy 1.2 }
575 masse 1.1 }
576    
577 masse 1.26 /* Swap the two top elements on the stack. */
578 teddy 1.28 extern void swap(environment *env)
579 masse 1.26 {
580 masse 1.104 value *temp= env->head;
581 masse 1.26
582 teddy 1.111 if(env->head->type == empty || CDR(env->head)->type == empty) {
583 teddy 1.36 printerr("Too Few Arguments");
584 teddy 1.35 env->err=1;
585 masse 1.26 return;
586 teddy 1.28 }
587 masse 1.26
588 masse 1.104 env->head= CDR(env->head);
589     CDR(temp)= CDR(env->head);
590     CDR(env->head)= temp;
591 masse 1.26 }
592    
593 teddy 1.33 /* Recall a value from a symbol, if bound */
594 teddy 1.31 extern void rcl(environment *env)
595     {
596     value *val;
597    
598 teddy 1.111 if(env->head->type==empty) {
599 teddy 1.36 printerr("Too Few Arguments");
600 masse 1.102 env->err= 1;
601 teddy 1.31 return;
602     }
603    
604 masse 1.104 if(CAR(env->head)->type!=symb) {
605 teddy 1.36 printerr("Bad Argument Type");
606 masse 1.102 env->err= 2;
607 teddy 1.31 return;
608     }
609 teddy 1.35
610 masse 1.105 val= CAR(env->head)->content.sym->val;
611 teddy 1.33 if(val == NULL){
612 teddy 1.36 printerr("Unbound Variable");
613 masse 1.102 env->err= 3;
614 teddy 1.33 return;
615     }
616 teddy 1.110 push_val(env, val); /* Return the symbol's bound value */
617     swap(env);
618     if(env->err) return;
619     toss(env); /* toss the symbol */
620 teddy 1.35 if(env->err) return;
621 teddy 1.31 }
622 masse 1.26
623 masse 1.126
624 teddy 1.29 /* If the top element is a symbol, determine if it's bound to a
625     function value, and if it is, toss the symbol and execute the
626     function. */
627 teddy 1.28 extern void eval(environment *env)
628 masse 1.1 {
629     funcp in_func;
630 masse 1.44 value* temp_val;
631 masse 1.104 value* iterator;
632 masse 1.44
633 teddy 1.80 eval_start:
634    
635 teddy 1.96 gc_maybe(env);
636    
637 teddy 1.111 if(env->head->type==empty) {
638 teddy 1.36 printerr("Too Few Arguments");
639 masse 1.102 env->err= 1;
640 masse 1.1 return;
641 masse 1.17 }
642 masse 1.1
643 masse 1.104 switch(CAR(env->head)->type) {
644 masse 1.46 /* if it's a symbol */
645     case symb:
646 teddy 1.35 rcl(env); /* get its contents */
647     if(env->err) return;
648 masse 1.104 if(CAR(env->head)->type!=symb){ /* don't recurse symbols */
649 teddy 1.64 goto eval_start;
650 teddy 1.29 }
651 teddy 1.59 return;
652 masse 1.22
653 masse 1.46 /* If it's a lone function value, run it */
654     case func:
655 masse 1.128 in_func= CAR(env->head)->content.func;
656 teddy 1.28 toss(env);
657 teddy 1.35 if(env->err) return;
658 masse 1.89 return in_func(env);
659 masse 1.44
660 masse 1.46 /* If it's a list */
661 masse 1.102 case tcons:
662 masse 1.104 temp_val= CAR(env->head);
663 masse 1.98 protect(temp_val);
664 masse 1.93
665     toss(env); if(env->err) return;
666 masse 1.104 iterator= temp_val;
667 masse 1.90
668 teddy 1.111 while(iterator->type != empty) {
669 masse 1.104 push_val(env, CAR(iterator));
670 masse 1.90
671 masse 1.104 if(CAR(env->head)->type==symb
672 masse 1.105 && CAR(env->head)->content.sym->id[0]==';') {
673 masse 1.44 toss(env);
674     if(env->err) return;
675 masse 1.90
676 teddy 1.111 if(CDR(iterator)->type == empty){
677 teddy 1.64 goto eval_start;
678 teddy 1.59 }
679 masse 1.44 eval(env);
680 masse 1.46 if(env->err) return;
681 masse 1.44 }
682 teddy 1.111 if (CDR(iterator)->type == empty || CDR(iterator)->type == tcons)
683 masse 1.104 iterator= CDR(iterator);
684 teddy 1.103 else {
685     printerr("Bad Argument Type"); /* Improper list */
686     env->err= 2;
687     return;
688     }
689 masse 1.44 }
690 masse 1.98 unprotect(temp_val);
691 teddy 1.59 return;
692 masse 1.46
693 teddy 1.116 case empty:
694 teddy 1.124 toss(env);
695 teddy 1.116 case integer:
696     case tfloat:
697     case string:
698 teddy 1.124 case port:
699 teddy 1.59 return;
700 masse 1.26 }
701 masse 1.1 }
702    
703 masse 1.126 /* List all defined words */
704     extern void words(environment *env)
705     {
706     symbol *temp;
707     int i;
708    
709     for(i= 0; i<HASHTBLSIZE; i++) {
710     temp= env->symbols[i];
711     while(temp!=NULL) {
712     #ifdef DEBUG
713     if (temp->val != NULL && temp->val->gc.flag.protect)
714     printf("(protected) ");
715     #endif /* DEBUG */
716     printf("%s ", temp->id);
717     temp= temp->next;
718     }
719     }
720     }
721    
722     /* Quit stack. */
723     extern void quit(environment *env)
724 masse 1.95 {
725 masse 1.126 int i;
726    
727     while(env->head->type != empty)
728     toss(env);
729 teddy 1.40
730 masse 1.126 if (env->err) return;
731     for(i= 0; i<HASHTBLSIZE; i++) {
732     while(env->symbols[i]!= NULL) {
733     forget_sym(&(env->symbols[i]));
734     }
735     env->symbols[i]= NULL;
736 teddy 1.40 }
737    
738 masse 1.126 env->gc_limit= 0;
739     gc_maybe(env);
740    
741     words(env);
742 teddy 1.111
743 masse 1.126 if(env->free_string!=NULL)
744     free(env->free_string);
745    
746     #ifdef __linux__
747     muntrace();
748     #endif
749 teddy 1.40
750 masse 1.126 exit(EXIT_SUCCESS);
751 teddy 1.40 }
752    
753 masse 1.126 /* Internal forget function */
754     void forget_sym(symbol **hash_entry)
755 masse 1.19 {
756 masse 1.126 symbol *temp;
757 teddy 1.111
758 masse 1.126 temp= *hash_entry;
759     *hash_entry= (*hash_entry)->next;
760    
761     free(temp->id);
762     free(temp);
763     }
764 masse 1.93
765 masse 1.126 /* Only to be called by itself function printstack. */
766     void print_st(environment *env, value *stack_head, long counter)
767     {
768     if(CDR(stack_head)->type != empty)
769     print_st(env, CDR(stack_head), counter+1);
770     printf("%ld: ", counter);
771     print_val(env, CAR(stack_head), 0, NULL, stdout);
772     printf("\n");
773 masse 1.1 }
774 teddy 1.55
775 masse 1.126 /* Prints the stack. */
776     extern void printstack(environment *env)
777 masse 1.95 {
778 masse 1.126 if(env->head->type == empty) {
779     printf("Stack Empty\n");
780 masse 1.58 return;
781     }
782    
783 masse 1.126 print_st(env, env->head, 1);
784 teddy 1.56 }
785 masse 1.65
786 masse 1.126 int main(int argc, char **argv)
787 masse 1.95 {
788 masse 1.126 environment myenv;
789 masse 1.89
790 masse 1.126 int c; /* getopt option character */
791 masse 1.89
792 masse 1.126 #ifdef __linux__
793     mtrace();
794     #endif
795 masse 1.89
796 masse 1.126 init_env(&myenv);
797 masse 1.89
798 masse 1.126 myenv.interactive = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO);
799 masse 1.89
800 masse 1.126 while ((c = getopt (argc, argv, "i")) != -1)
801     switch (c)
802     {
803     case 'i':
804     myenv.interactive = 1;
805     break;
806     case '?':
807     fprintf (stderr,
808     "Unknown option character '\\x%x'.\n",
809     optopt);
810     return EX_USAGE;
811     default:
812     abort ();
813     }
814    
815     if (optind < argc) {
816     myenv.interactive = 0;
817     myenv.inputstream= fopen(argv[optind], "r");
818     if(myenv.inputstream== NULL) {
819     perror(argv[0]);
820     exit (EX_NOINPUT);
821 masse 1.89 }
822     }
823    
824 masse 1.126 if(myenv.interactive) {
825 masse 1.130 printf("Stack version $Revision: 1.129 $\n\
826 masse 1.126 Copyright (C) 2002 Mats Alritzson and Teddy Hogeborn\n\
827     Stack comes with ABSOLUTELY NO WARRANTY; for details type 'warranty;'.\n\
828     This is free software, and you are welcome to redistribute it\n\
829     under certain conditions; type 'copying;' for details.\n");
830 masse 1.65 }
831    
832 masse 1.126 while(1) {
833     if(myenv.in_string==NULL) {
834     if (myenv.interactive) {
835     if(myenv.err) {
836     printf("(error %d)\n", myenv.err);
837     myenv.err= 0;
838     }
839     printf("\n");
840     printstack(&myenv);
841     printf("> ");
842     }
843     myenv.err=0;
844     }
845     readstream(&myenv, myenv.inputstream);
846     if (myenv.err) { /* EOF or other error */
847     myenv.err=0;
848     quit(&myenv);
849     } else if(myenv.head->type!=empty
850     && CAR(myenv.head)->type==symb
851     && CAR(myenv.head)->content.sym->id[0] == ';') {
852     toss(&myenv); if(myenv.err) continue;
853     eval(&myenv);
854 teddy 1.103 } else {
855 masse 1.126 gc_maybe(&myenv);
856 teddy 1.103 }
857 masse 1.65 }
858 masse 1.126 quit(&myenv);
859     return EXIT_FAILURE;
860 masse 1.65 }
861 masse 1.66
862 masse 1.126 /* Return copy of a value */
863     value *copy_val(environment *env, value *old_value)
864 masse 1.95 {
865 masse 1.126 value *new_value;
866 masse 1.121
867 masse 1.126 if(old_value==NULL)
868     return NULL;
869 masse 1.95
870 masse 1.126 new_value= new_val(env);
871     new_value->type= old_value->type;
872 masse 1.66
873 masse 1.126 switch(old_value->type){
874     case tfloat:
875     case integer:
876     case func:
877     case symb:
878     case empty:
879     case port:
880     new_value->content= old_value->content;
881     break;
882     case string:
883 masse 1.128 new_value->content.string= strdup(old_value->content.string);
884 masse 1.126 break;
885     case tcons:
886 masse 1.66
887 masse 1.126 new_value->content.c= malloc(sizeof(pair));
888     assert(new_value->content.c!=NULL);
889     env->gc_count += sizeof(pair);
890 masse 1.66
891 masse 1.126 CAR(new_value)= copy_val(env, CAR(old_value)); /* recurse */
892     CDR(new_value)= copy_val(env, CDR(old_value)); /* recurse */
893     break;
894 masse 1.67 }
895 masse 1.66
896 masse 1.126 return new_value;
897 teddy 1.124 }
898    
899     /* read a line from a stream; used by readline */
900     void readlinestream(environment *env, FILE *stream)
901     {
902 masse 1.68 char in_string[101];
903    
904 teddy 1.124 if(fgets(in_string, 100, stream)==NULL) {
905 teddy 1.84 push_cstring(env, "");
906 teddy 1.124 if (! feof(stream)){
907     perror("readline");
908     env->err= 5;
909     }
910     } else {
911 teddy 1.84 push_cstring(env, in_string);
912 teddy 1.124 }
913 masse 1.68 }
914    
915 masse 1.126 /* Reverse (flip) a list */
916     extern void rev(environment *env)
917 masse 1.95 {
918 masse 1.126 value *old_head, *new_head, *item;
919 teddy 1.124
920     if(env->head->type==empty) {
921     printerr("Too Few Arguments");
922     env->err= 1;
923     return;
924     }
925    
926 masse 1.126 if(CAR(env->head)->type==empty)
927     return; /* Don't reverse an empty list */
928    
929     if(CAR(env->head)->type!=tcons) {
930 teddy 1.124 printerr("Bad Argument Type");
931     env->err= 2;
932     return;
933     }
934    
935 masse 1.126 old_head= CAR(env->head);
936     new_head= new_val(env);
937     while(old_head->type != empty) {
938     item= old_head;
939     old_head= CDR(old_head);
940     CDR(item)= new_head;
941     new_head= item;
942     }
943     CAR(env->head)= new_head;
944     }
945    
946     /* Make a list. */
947     extern void pack(environment *env)
948     {
949     value *iterator, *temp, *ending;
950    
951     ending=new_val(env);
952    
953     iterator= env->head;
954     if(iterator->type == empty
955     || (CAR(iterator)->type==symb
956     && CAR(iterator)->content.sym->id[0]=='[')) {
957     temp= ending;
958     toss(env);
959     } else {
960     /* Search for first delimiter */
961     while(CDR(iterator)->type != empty
962     && (CAR(CDR(iterator))->type!=symb
963     || CAR(CDR(iterator))->content.sym->id[0]!='['))
964     iterator= CDR(iterator);
965    
966     /* Extract list */
967     temp= env->head;
968     env->head= CDR(iterator);
969     CDR(iterator)= ending;
970    
971     if(env->head->type != empty)
972     toss(env);
973     }
974    
975     /* Push list */
976 teddy 1.124
977 masse 1.126 push_val(env, temp);
978     rev(env);
979 teddy 1.124 }
980    
981     /* read from a stream; used by "read" and "readport" */
982     void readstream(environment *env, FILE *stream)
983     {
984 teddy 1.78 const char symbform[]= "%[a-zA-Z0-9!$%*+./:<=>?@^_~-]%n";
985     const char strform[]= "\"%[^\"]\"%n";
986     const char intform[]= "%i%n";
987 masse 1.93 const char fltform[]= "%f%n";
988 teddy 1.78 const char blankform[]= "%*[ \t]%n";
989 masse 1.90 const char ebrackform[]= "]%n";
990     const char semicform[]= ";%n";
991     const char bbrackform[]= "[%n";
992 masse 1.68
993 teddy 1.78 int itemp, readlength= -1;
994 masse 1.93 int count= -1;
995     float ftemp;
996 masse 1.68 static int depth= 0;
997 teddy 1.116 char *match;
998 masse 1.68 size_t inlength;
999    
1000 masse 1.70 if(env->in_string==NULL) {
1001 teddy 1.84 if(depth > 0 && env->interactive) {
1002 teddy 1.80 printf("]> ");
1003     }
1004 masse 1.126 readlinestream(env, env->inputstream);
1005     if(env->err) return;
1006 teddy 1.84
1007 masse 1.128 if((CAR(env->head)->content.string)[0]=='\0'){
1008 teddy 1.85 env->err= 4; /* "" means EOF */
1009 teddy 1.84 return;
1010     }
1011 masse 1.68
1012 masse 1.128 env->in_string= malloc(strlen(CAR(env->head)->content.string)+1);
1013 teddy 1.118 assert(env->in_string != NULL);
1014 teddy 1.78 env->free_string= env->in_string; /* Save the original pointer */
1015 masse 1.128 strcpy(env->in_string, CAR(env->head)->content.string);
1016 masse 1.68 toss(env); if(env->err) return;
1017     }
1018    
1019 masse 1.70 inlength= strlen(env->in_string)+1;
1020 masse 1.68 match= malloc(inlength);
1021 teddy 1.118 assert(match != NULL);
1022 masse 1.68
1023 masse 1.93 if(sscanf(env->in_string, blankform, &readlength) != EOF
1024 teddy 1.78 && readlength != -1) {
1025 masse 1.71 ;
1026 masse 1.93 } else if(sscanf(env->in_string, fltform, &ftemp, &readlength) != EOF
1027 teddy 1.78 && readlength != -1) {
1028 masse 1.93 if(sscanf(env->in_string, intform, &itemp, &count) != EOF
1029     && count==readlength) {
1030     push_int(env, itemp);
1031     } else {
1032     push_float(env, ftemp);
1033     }
1034 teddy 1.114 } else if(sscanf(env->in_string, "\"\"%n", &readlength) != EOF
1035     && readlength != -1) {
1036     push_cstring(env, "");
1037 teddy 1.78 } else if(sscanf(env->in_string, strform, match, &readlength) != EOF
1038     && readlength != -1) {
1039 masse 1.72 push_cstring(env, match);
1040 teddy 1.78 } else if(sscanf(env->in_string, symbform, match, &readlength) != EOF
1041     && readlength != -1) {
1042 masse 1.68 push_sym(env, match);
1043 teddy 1.78 } else if(sscanf(env->in_string, ebrackform, &readlength) != EOF
1044     && readlength != -1) {
1045 masse 1.68 pack(env); if(env->err) return;
1046 teddy 1.78 if(depth != 0) depth--;
1047     } else if(sscanf(env->in_string, semicform, &readlength) != EOF
1048     && readlength != -1) {
1049 masse 1.68 push_sym(env, ";");
1050 teddy 1.78 } else if(sscanf(env->in_string, bbrackform, &readlength) != EOF
1051     && readlength != -1) {
1052 masse 1.68 push_sym(env, "[");
1053     depth++;
1054     } else {
1055 teddy 1.78 free(env->free_string);
1056     env->in_string = env->free_string = NULL;
1057     }
1058 masse 1.126 if (env->in_string != NULL) {
1059     env->in_string += readlength;
1060 teddy 1.91 }
1061    
1062 masse 1.126 free(match);
1063 teddy 1.91
1064 masse 1.126 if(depth)
1065     return readstream(env, env->inputstream);
1066 masse 1.95 }
1067 teddy 1.91
1068 masse 1.95 extern void copying(environment *env)
1069     {
1070 teddy 1.111 printf(" GNU GENERAL PUBLIC LICENSE\n\
1071 teddy 1.91 Version 2, June 1991\n\
1072     \n\
1073     Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n\
1074     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\
1075     Everyone is permitted to copy and distribute verbatim copies\n\
1076     of this license document, but changing it is not allowed.\n\
1077     \n\
1078     Preamble\n\
1079     \n\
1080     The licenses for most software are designed to take away your\n\
1081     freedom to share and change it. By contrast, the GNU General Public\n\
1082     License is intended to guarantee your freedom to share and change free\n\
1083     software--to make sure the software is free for all its users. This\n\
1084     General Public License applies to most of the Free Software\n\
1085     Foundation's software and to any other program whose authors commit to\n\
1086     using it. (Some other Free Software Foundation software is covered by\n\
1087     the GNU Library General Public License instead.) You can apply it to\n\
1088     your programs, too.\n\
1089     \n\
1090     When we speak of free software, we are referring to freedom, not\n\
1091     price. Our General Public Licenses are designed to make sure that you\n\
1092     have the freedom to distribute copies of free software (and charge for\n\
1093     this service if you wish), that you receive source code or can get it\n\
1094     if you want it, that you can change the software or use pieces of it\n\
1095     in new free programs; and that you know you can do these things.\n\
1096     \n\
1097     To protect your rights, we need to make restrictions that forbid\n\
1098     anyone to deny you these rights or to ask you to surrender the rights.\n\
1099     These restrictions translate to certain responsibilities for you if you\n\
1100     distribute copies of the software, or if you modify it.\n\
1101     \n\
1102     For example, if you distribute copies of such a program, whether\n\
1103     gratis or for a fee, you must give the recipients all the rights that\n\
1104     you have. You must make sure that they, too, receive or can get the\n\
1105     source code. And you must show them these terms so they know their\n\
1106     rights.\n\
1107     \n\
1108     We protect your rights with two steps: (1) copyright the software, and\n\
1109     (2) offer you this license which gives you legal permission to copy,\n\
1110     distribute and/or modify the software.\n\
1111     \n\
1112     Also, for each author's protection and ours, we want to make certain\n\
1113     that everyone understands that there is no warranty for this free\n\
1114     software. If the software is modified by someone else and passed on, we\n\
1115     want its recipients to know that what they have is not the original, so\n\
1116     that any problems introduced by others will not reflect on the original\n\
1117     authors' reputations.\n\
1118     \n\
1119     Finally, any free program is threatened constantly by software\n\
1120     patents. We wish to avoid the danger that redistributors of a free\n\
1121     program will individually obtain patent licenses, in effect making the\n\
1122     program proprietary. To prevent this, we have made it clear that any\n\
1123     patent must be licensed for everyone's free use or not licensed at all.\n\
1124     \n\
1125     The precise terms and conditions for copying, distribution and\n\
1126     modification follow.\n\
1127     \n\
1128     GNU GENERAL PUBLIC LICENSE\n\
1129     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\
1130     \n\
1131     0. This License applies to any program or other work which contains\n\
1132     a notice placed by the copyright holder saying it may be distributed\n\
1133     under the terms of this General Public License. The \"Program\", below,\n\
1134     refers to any such program or work, and a \"work based on the Program\"\n\
1135     means either the Program or any derivative work under copyright law:\n\
1136     that is to say, a work containing the Program or a portion of it,\n\
1137     either verbatim or with modifications and/or translated into another\n\
1138     language. (Hereinafter, translation is included without limitation in\n\
1139     the term \"modification\".) Each licensee is addressed as \"you\".\n\
1140     \n\
1141     Activities other than copying, distribution and modification are not\n\
1142     covered by this License; they are outside its scope. The act of\n\
1143     running the Program is not restricted, and the output from the Program\n\
1144     is covered only if its contents constitute a work based on the\n\
1145     Program (independent of having been made by running the Program).\n\
1146     Whether that is true depends on what the Program does.\n\
1147     \n\
1148     1. You may copy and distribute verbatim copies of the Program's\n\
1149     source code as you receive it, in any medium, provided that you\n\
1150     conspicuously and appropriately publish on each copy an appropriate\n\
1151     copyright notice and disclaimer of warranty; keep intact all the\n\
1152     notices that refer to this License and to the absence of any warranty;\n\
1153     and give any other recipients of the Program a copy of this License\n\
1154     along with the Program.\n\
1155     \n\
1156     You may charge a fee for the physical act of transferring a copy, and\n\
1157     you may at your option offer warranty protection in exchange for a fee.\n\
1158     \n\
1159     2. You may modify your copy or copies of the Program or any portion\n\
1160     of it, thus forming a work based on the Program, and copy and\n\
1161     distribute such modifications or work under the terms of Section 1\n\
1162     above, provided that you also meet all of these conditions:\n\
1163     \n\
1164     a) You must cause the modified files to carry prominent notices\n\
1165     stating that you changed the files and the date of any change.\n\
1166     \n\
1167     b) You must cause any work that you distribute or publish, that in\n\
1168     whole or in part contains or is derived from the Program or any\n\
1169     part thereof, to be licensed as a whole at no charge to all third\n\
1170     parties under the terms of this License.\n\
1171     \n\
1172     c) If the modified program normally reads commands interactively\n\
1173     when run, you must cause it, when started running for such\n\
1174     interactive use in the most ordinary way, to print or display an\n\
1175     announcement including an appropriate copyright notice and a\n\
1176     notice that there is no warranty (or else, saying that you provide\n\
1177     a warranty) and that users may redistribute the program under\n\
1178     these conditions, and telling the user how to view a copy of this\n\
1179     License. (Exception: if the Program itself is interactive but\n\
1180     does not normally print such an announcement, your work based on\n\
1181     the Program is not required to print an announcement.)\n\
1182     \n\
1183     These requirements apply to the modified work as a whole. If\n\
1184     identifiable sections of that work are not derived from the Program,\n\
1185     and can be reasonably considered independent and separate works in\n\
1186     themselves, then this License, and its terms, do not apply to those\n\
1187     sections when you distribute them as separate works. But when you\n\
1188     distribute the same sections as part of a whole which is a work based\n\
1189     on the Program, the distribution of the whole must be on the terms of\n\
1190     this License, whose permissions for other licensees extend to the\n\
1191     entire whole, and thus to each and every part regardless of who wrote it.\n\
1192     \n\
1193     Thus, it is not the intent of this section to claim rights or contest\n\
1194     your rights to work written entirely by you; rather, the intent is to\n\
1195     exercise the right to control the distribution of derivative or\n\
1196     collective works based on the Program.\n\
1197     \n\
1198     In addition, mere aggregation of another work not based on the Program\n\
1199     with the Program (or with a work based on the Program) on a volume of\n\
1200     a storage or distribution medium does not bring the other work under\n\
1201     the scope of this License.\n\
1202     \n\
1203     3. You may copy and distribute the Program (or a work based on it,\n\
1204     under Section 2) in object code or executable form under the terms of\n\
1205     Sections 1 and 2 above provided that you also do one of the following:\n\
1206     \n\
1207     a) Accompany it with the complete corresponding machine-readable\n\
1208     source code, which must be distributed under the terms of Sections\n\
1209     1 and 2 above on a medium customarily used for software interchange; or,\n\
1210     \n\
1211     b) Accompany it with a written offer, valid for at least three\n\
1212     years, to give any third party, for a charge no more than your\n\
1213     cost of physically performing source distribution, a complete\n\
1214     machine-readable copy of the corresponding source code, to be\n\
1215     distributed under the terms of Sections 1 and 2 above on a medium\n\
1216     customarily used for software interchange; or,\n\
1217     \n\
1218     c) Accompany it with the information you received as to the offer\n\
1219     to distribute corresponding source code. (This alternative is\n\
1220     allowed only for noncommercial distribution and only if you\n\
1221     received the program in object code or executable form with such\n\
1222     an offer, in accord with Subsection b above.)\n\
1223     \n\
1224     The source code for a work means the preferred form of the work for\n\
1225     making modifications to it. For an executable work, complete source\n\
1226     code means all the source code for all modules it contains, plus any\n\
1227     associated interface definition files, plus the scripts used to\n\
1228     control compilation and installation of the executable. However, as a\n\
1229     special exception, the source code distributed need not include\n\
1230     anything that is normally distributed (in either source or binary\n\
1231     form) with the major components (compiler, kernel, and so on) of the\n\
1232     operating system on which the executable runs, unless that component\n\
1233     itself accompanies the executable.\n\
1234     \n\
1235     If distribution of executable or object code is made by offering\n\
1236     access to copy from a designated place, then offering equivalent\n\
1237     access to copy the source code from the same place counts as\n\
1238     distribution of the source code, even though third parties are not\n\
1239     compelled to copy the source along with the object code.\n\
1240     \n\
1241     4. You may not copy, modify, sublicense, or distribute the Program\n\
1242     except as expressly provided under this License. Any attempt\n\
1243     otherwise to copy, modify, sublicense or distribute the Program is\n\
1244     void, and will automatically terminate your rights under this License.\n\
1245     However, parties who have received copies, or rights, from you under\n\
1246     this License will not have their licenses terminated so long as such\n\
1247     parties remain in full compliance.\n\
1248     \n\
1249     5. You are not required to accept this License, since you have not\n\
1250     signed it. However, nothing else grants you permission to modify or\n\
1251     distribute the Program or its derivative works. These actions are\n\
1252     prohibited by law if you do not accept this License. Therefore, by\n\
1253     modifying or distributing the Program (or any work based on the\n\
1254     Program), you indicate your acceptance of this License to do so, and\n\
1255     all its terms and conditions for copying, distributing or modifying\n\
1256     the Program or works based on it.\n\
1257     \n\
1258     6. Each time you redistribute the Program (or any work based on the\n\
1259     Program), the recipient automatically receives a license from the\n\
1260     original licensor to copy, distribute or modify the Program subject to\n\
1261     these terms and conditions. You may not impose any further\n\
1262     restrictions on the recipients' exercise of the rights granted herein.\n\
1263     You are not responsible for enforcing compliance by third parties to\n\
1264     this License.\n\
1265     \n\
1266     7. If, as a consequence of a court judgment or allegation of patent\n\
1267     infringement or for any other reason (not limited to patent issues),\n\
1268     conditions are imposed on you (whether by court order, agreement or\n\
1269     otherwise) that contradict the conditions of this License, they do not\n\
1270     excuse you from the conditions of this License. If you cannot\n\
1271     distribute so as to satisfy simultaneously your obligations under this\n\
1272     License and any other pertinent obligations, then as a consequence you\n\
1273     may not distribute the Program at all. For example, if a patent\n\
1274     license would not permit royalty-free redistribution of the Program by\n\
1275     all those who receive copies directly or indirectly through you, then\n\
1276     the only way you could satisfy both it and this License would be to\n\
1277     refrain entirely from distribution of the Program.\n\
1278     \n\
1279     If any portion of this section is held invalid or unenforceable under\n\
1280     any particular circumstance, the balance of the section is intended to\n\
1281     apply and the section as a whole is intended to apply in other\n\
1282     circumstances.\n\
1283     \n\
1284     It is not the purpose of this section to induce you to infringe any\n\
1285     patents or other property right claims or to contest validity of any\n\
1286     such claims; this section has the sole purpose of protecting the\n\
1287     integrity of the free software distribution system, which is\n\
1288     implemented by public license practices. Many people have made\n\
1289     generous contributions to the wide range of software distributed\n\
1290     through that system in reliance on consistent application of that\n\
1291     system; it is up to the author/donor to decide if he or she is willing\n\
1292     to distribute software through any other system and a licensee cannot\n\
1293     impose that choice.\n\
1294     \n\
1295     This section is intended to make thoroughly clear what is believed to\n\
1296     be a consequence of the rest of this License.\n\
1297     \n\
1298     8. If the distribution and/or use of the Program is restricted in\n\
1299     certain countries either by patents or by copyrighted interfaces, the\n\
1300     original copyright holder who places the Program under this License\n\
1301     may add an explicit geographical distribution limitation excluding\n\
1302     those countries, so that distribution is permitted only in or among\n\
1303     countries not thus excluded. In such case, this License incorporates\n\
1304     the limitation as if written in the body of this License.\n\
1305     \n\
1306     9. The Free Software Foundation may publish revised and/or new versions\n\
1307     of the General Public License from time to time. Such new versions will\n\
1308     be similar in spirit to the present version, but may differ in detail to\n\
1309     address new problems or concerns.\n\
1310     \n\
1311     Each version is given a distinguishing version number. If the Program\n\
1312     specifies a version number of this License which applies to it and \"any\n\
1313     later version\", you have the option of following the terms and conditions\n\
1314     either of that version or of any later version published by the Free\n\
1315     Software Foundation. If the Program does not specify a version number of\n\
1316     this License, you may choose any version ever published by the Free Software\n\
1317     Foundation.\n\
1318     \n\
1319     10. If you wish to incorporate parts of the Program into other free\n\
1320     programs whose distribution conditions are different, write to the author\n\
1321     to ask for permission. For software which is copyrighted by the Free\n\
1322     Software Foundation, write to the Free Software Foundation; we sometimes\n\
1323     make exceptions for this. Our decision will be guided by the two goals\n\
1324     of preserving the free status of all derivatives of our free software and\n\
1325     of promoting the sharing and reuse of software generally.\n");
1326     }
1327    
1328 masse 1.95 extern void warranty(environment *env)
1329     {
1330 teddy 1.91 printf(" NO WARRANTY\n\
1331     \n\
1332     11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n\
1333     FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n\
1334     OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n\
1335     PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n\
1336     OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n\
1337     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n\
1338     TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n\
1339     PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n\
1340     REPAIR OR CORRECTION.\n\
1341     \n\
1342     12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n\
1343     WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n\
1344     REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n\
1345     INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n\
1346     OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n\
1347     TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n\
1348     YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n\
1349     PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n\
1350     POSSIBILITY OF SUCH DAMAGES.\n");
1351 masse 1.123 }
1352    
1353 masse 1.126 /* Discard the top element of the stack. */
1354     extern void toss(environment *env)
1355 masse 1.123 {
1356 masse 1.126 if(env->head->type==empty) {
1357 teddy 1.124 printerr("Too Few Arguments");
1358 masse 1.126 env->err= 1;
1359 teddy 1.124 return;
1360     }
1361 masse 1.126
1362     env->head= CDR(env->head); /* Remove the top stack item */
1363 teddy 1.124 }
1364    

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26