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

Diff of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.100

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26