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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.131 - (hide annotations)
Tue Aug 5 09:09:51 2003 UTC (20 years, 8 months ago) by masse
Branch: MAIN
Changes since 1.130: +1 -25 lines
File MIME type: text/plain
(mangle) Moved from "stack.c" to "symbols.c".
Makefile: Added tail recursion optimization.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26