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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26