Diff for /gforth/Attic/engine.c between versions 1.1 and 1.41

version 1.1, 1994/02/11 16:30:46 version 1.41, 1997/03/04 17:49:48
Line 1 Line 1
 /*  /* Gforth virtual machine (aka inner interpreter)
   $Id$  
   Copyright 1992 by the ANSI figForth Development Group    Copyright (C) 1995 Free Software Foundation, Inc.
   
     This file is part of Gforth.
   
     Gforth is free software; you can redistribute it and/or
     modify it under the terms of the GNU General Public License
     as published by the Free Software Foundation; either version 2
     of the License, or (at your option) any later version.
   
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
   
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */  */
   
   #include "config.h"
 #include <ctype.h>  #include <ctype.h>
 #include <stdio.h>  #include <stdio.h>
 #include <string.h>  #include <string.h>
Line 12 Line 29
 #include <fcntl.h>  #include <fcntl.h>
 #include <assert.h>  #include <assert.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <time.h>
   #include <sys/time.h>
   #include <unistd.h>
   #include <errno.h>
   #include <pwd.h>
 #include "forth.h"  #include "forth.h"
 #include "io.h"  #include "io.h"
   #include "threading.h"
   
 extern unlink(char *);  #ifndef SEEK_SET
 extern ftruncate(int, int);  /* should be defined in stdio.h, but some systems don't have it */
   #define SEEK_SET 0
   #endif
   
 typedef union {  #define IOR(flag)       ((flag)? -512-errno : 0)
   struct {  
 #ifdef BIG_ENDIAN  
     Cell high;  
     Cell low;  
 #else  
     Cell low;  
     Cell high;  
 #endif;  
   } cells;  
   DCell dcell;  
 } Double_Store;  
   
 typedef struct F83Name {  typedef struct F83Name {
   struct F83Name        *next;  /* the link field for old hands */    struct F83Name        *next;  /* the link field for old hands */
Line 42  typedef struct F83Name { Line 56  typedef struct F83Name {
 #define F83NAME_SMUDGE(np)      (((np)->countetc & 0x40) != 0)  #define F83NAME_SMUDGE(np)      (((np)->countetc & 0x40) != 0)
 #define F83NAME_IMMEDIATE(np)   (((np)->countetc & 0x20) != 0)  #define F83NAME_IMMEDIATE(np)   (((np)->countetc & 0x20) != 0)
   
 /* NEXT and NEXT1 are split into several parts to help scheduling */  Cell *SP;
 #ifdef DIRECT_THREADED  Float *FP;
 #define NEXT1_P1   Address UP=NULL;
 #define NEXT1_P2 ({goto *cfa;})  
 #else  #if 0
 #define NEXT1_P1 ({ca = *cfa;})  /* not used currently */
 #define NEXT1_P2 ({goto *ca;})  int emitcounter;
 #endif  #endif
 #define NEXT_P1 ({cfa = *ip++; NEXT1_P1;})  #define NULLC '\0'
   
 #define NEXT1 ({NEXT1_P1; NEXT1_P2;})  char *cstr(Char *from, UCell size, int clear)
 #define NEXT ({NEXT_P1; NEXT1_P2;})  /* return a C-string corresponding to the Forth string ( FROM SIZE ).
      the C-string lives until the next call of cstr with CLEAR being true */
   {
     static struct cstr_buffer {
       char *buffer;
       size_t size;
     } *buffers=NULL;
     static int nbuffers=0;
     static int used=0;
     struct cstr_buffer *b;
   
     if (buffers==NULL)
       buffers=malloc(0);
     if (clear)
       used=0;
     if (used>=nbuffers) {
       buffers=realloc(buffers,sizeof(struct cstr_buffer)*(used+1));
       buffers[used]=(struct cstr_buffer){malloc(0),0};
       nbuffers=used+1;
     }
     b=&buffers[used];
     if (size+1 > b->size) {
       b->buffer = realloc(b->buffer,size+1);
       b->size = size+1;
     }
     memcpy(b->buffer,from,size);
     b->buffer[size]='\0';
     used++;
     return b->buffer;
   }
   
 #ifdef USE_TOS  char *tilde_cstr(Char *from, UCell size, int clear)
 #define IF_TOS(x) x  /* like cstr(), but perform tilde expansion on the string */
 #else  {
 #define IF_TOS(x)    char *s1,*s2;
 #define TOS (sp[0])    int s1_len, s2_len;
     struct passwd *getpwnam (), *user_entry;
   
     if (size<1 || from[0]!='~')
       return cstr(from, size, clear);
     if (size<2 || from[1]=='/') {
       s1 = (char *)getenv ("HOME");
       if(s1 == NULL)
         s1 = "";
       s2 = from+1;
       s2_len = size-1;
     } else {
       UCell i;
       for (i=1; i<size && from[i]!='/'; i++)
         ;
       {
         char user[i];
         memcpy(user,from+1,i-1);
         user[i-1]='\0';
         user_entry=getpwnam(user);
       }
       if (user_entry==NULL)
         return cstr(from, size, clear);
       s1 = user_entry->pw_dir;
       s2 = from+i;
       s2_len = size-i;
     }
     s1_len = strlen(s1);
     if (s1_len>1 && s1[s1_len-1]=='/')
       s1_len--;
     {
       char path[s1_len+s2_len];
       memcpy(path,s1,s1_len);
       memcpy(path+s1_len,s2,s2_len);
       return cstr(path,s1_len+s2_len,clear);
     }
   }
      
   
   #define NEWLINE '\n'
   
   #ifndef HAVE_RINT
   #define rint(x) floor((x)+0.5)
 #endif  #endif
   
 #ifdef USE_FTOS  static char* fileattr[6]={"r","rb","r+","r+b","w","wb"};
 #define IF_FTOS(x) x  
 #else  #ifndef O_BINARY
 #define IF_FTOS(x)  #define O_BINARY 0
 #define FTOS (fp[0])  #endif
   #ifndef O_TEXT
   #define O_TEXT 0
 #endif  #endif
   
 #define DODOES  (symbols[3])  static int ufileattr[6]= {
     O_RDONLY|O_TEXT, O_RDONLY|O_BINARY,
     O_RDWR  |O_TEXT, O_RDWR  |O_BINARY,
     O_WRONLY|O_TEXT, O_WRONLY|O_BINARY };
   
 int emitcounter;  /* if machine.h has not defined explicit registers, define them as implicit */
 #define NULLC '\0'  #ifndef IPREG
   #define IPREG
   #endif
   #ifndef SPREG
   #define SPREG
   #endif
   #ifndef RPREG
   #define RPREG
   #endif
   #ifndef FPREG
   #define FPREG
   #endif
   #ifndef LPREG
   #define LPREG
   #endif
   #ifndef CFAREG
   #define CFAREG
   #endif
   #ifndef UPREG
   #define UPREG
   #endif
   #ifndef TOSREG
   #define TOSREG
   #endif
   #ifndef FTOSREG
   #define FTOSREG
   #endif
   
 #define cstr(to, from, size)\  #ifndef CPU_DEP1
         {       memcpy(to, from, size);\  # define CPU_DEP1 0
                 to[size]=NULLC;}  #endif
 #define NEWLINE '\n'  
   
 static char* fileattr[6]={"r","rb","r+","r+b","w+","w+b"};  /* declare and compute cfa for certain threading variants */
   /* warning: this is nonsyntactical; it will not work in place of a statement */
   #ifdef CFA_NEXT
   #define DOCFA
   #else
   #define DOCFA   Xt cfa; GETCFA(cfa)
   #endif
   
 Label *engine(Xt *ip, Cell *sp, Cell *rp, Float *fp)  Label *engine(Xt *ip0, Cell *sp0, Cell *rp0, Float *fp0, Address lp0)
 /* executes code at ip, if ip!=NULL  /* executes code at ip, if ip!=NULL
    returns array of machine code labels (for use in a loader), if ip==NULL     returns array of machine code labels (for use in a loader), if ip==NULL
    This is very preliminary, as the bootstrap architecture is not yet decided  
 */  */
 {  {
   Xt cfa;    register Xt *ip IPREG = ip0;
   Address lp=NULL;    register Cell *sp SPREG = sp0;
     register Cell *rp RPREG = rp0;
     register Float *fp FPREG = fp0;
     register Address lp LPREG = lp0;
   #ifdef CFA_NEXT
     register Xt cfa CFAREG;
   #endif
     register Address up UPREG = UP;
     IF_TOS(register Cell TOS TOSREG;)
     IF_FTOS(register Float FTOS FTOSREG;)
   #if defined(DOUBLY_INDIRECT)
     static Label *symbols;
     static void *routines[]= {
   #else /* !defined(DOUBLY_INDIRECT) */
   static Label symbols[]= {    static Label symbols[]= {
   #endif /* !defined(DOUBLY_INDIRECT) */
     &&docol,      &&docol,
     &&docon,      &&docon,
     &&dovar,      &&dovar,
       &&douser,
       &&dodefer,
       &&dofield,
     &&dodoes,      &&dodoes,
       /* the following entry is normally unused;
          it's there because its index indicates a does-handler */
       CPU_DEP1,
 #include "prim_labels.i"  #include "prim_labels.i"
       0
   };    };
 #ifndef DIRECT_THREADED  #ifdef CPU_DEP2
   Label ca;    CPU_DEP2
 #endif  
   IF_TOS(register Cell TOS;)  
   IF_FTOS(Float FTOS;)  
 #ifdef CPU_DEP  
   CPU_DEP;  
 #endif  #endif
   
   if (ip == NULL)  #ifdef DEBUG
     return symbols;    fprintf(stderr,"ip=%x, sp=%x, rp=%x, fp=%x, lp=%x, up=%x\n",
               (unsigned)ip,(unsigned)sp,(unsigned)rp,
             (unsigned)fp,(unsigned)lp,(unsigned)up);
   #endif
   
     if (ip == NULL) {
   #if defined(DOUBLY_INDIRECT)
   #define MAX_SYMBOLS 1000
       int i;
       Cell code_offset = offset_image? 11*sizeof(Cell) : 0;
   
       symbols = (Label *)(malloc(MAX_SYMBOLS*sizeof(Cell)+code_offset)+code_offset);
       for (i=0; i<DOESJUMP+1; i++)
         symbols[i] = (Label)routines[i];
       for (; routines[i]!=0; i++) {
         if (i>=MAX_SYMBOLS) {
           fprintf(stderr,"gforth-ditc: more than %d primitives\n",MAX_SYMBOLS);
           exit(1);
       }
       symbols[i] = &routines[i];
     }
   #endif /* defined(DOUBLY_INDIRECT) */
     return symbols;
   }
   
   IF_TOS(TOS = sp[0]);    IF_TOS(TOS = sp[0]);
   IF_FTOS(FTOS = fp[0]);    IF_FTOS(FTOS = fp[0]);
   prep_terminal();  /*  prep_terminal(); */
     NEXT_P0;
   NEXT;    NEXT;
   
   #ifdef CPU_DEP3
     CPU_DEP3
   #endif
       
  docol:   docol:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   printf("col: %x\n",(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: col: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
 #ifdef undefined  #ifdef CISC_NEXT
   /* this is the simple version */      /* this is the simple version */
   *--rp = (Cell)ip;  
   ip = (Xt *)PFA1(cfa);  
   NEXT;  
 #endif  
   /* this one is important, so we help the compiler optimizing  
      The following version may be better (for scheduling), but probably has  
      problems with code fields employing calls and delay slots  
   */  
   {  
     Xt *current_ip = (Xt *)PFA1(cfa);  
     cfa = *current_ip;  
     NEXT1_P1;  
     *--rp = (Cell)ip;      *--rp = (Cell)ip;
     ip = current_ip+1;      ip = (Xt *)PFA1(cfa);
       NEXT_P0;
       NEXT;
   #else
       /* this one is important, so we help the compiler optimizing
          The following version may be better (for scheduling), but probably has
          problems with code fields employing calls and delay slots
          */
       {
         DEF_CA
         Xt *current_ip = (Xt *)PFA1(cfa);
         cfa = *current_ip;
         NEXT1_P1;
         *--rp = (Cell)ip;
         ip = current_ip+1;
         NEXT1_P2;
       }
   #endif
   }    }
   NEXT1_P2;  
     
  docon:   docon:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   printf("con: %x\n",*(Cell*)PFA1(cfa));      fprintf(stderr,"%08lx: con: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa));
 #endif  #endif
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = *(Cell *)PFA1(cfa);      TOS = *(Cell *)PFA1(cfa);
 #else  #else
   *--sp = *(Cell *)PFA1(cfa);      *--sp = *(Cell *)PFA1(cfa);
 #endif  #endif
     }
     NEXT_P0;
   NEXT;    NEXT;
       
  dovar:   dovar:
     {
       DOCFA;
 #ifdef DEBUG  #ifdef DEBUG
   printf("var: %x\n",(Cell)PFA1(cfa));      fprintf(stderr,"%08lx: var: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
 #endif  #endif
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = (Cell)PFA1(cfa);      TOS = (Cell)PFA1(cfa);
 #else  #else
   *--sp = (Cell)PFA1(cfa);      *--sp = (Cell)PFA1(cfa);
 #endif  #endif
     }
     NEXT_P0;
   NEXT;    NEXT;
       
   /* !! user? */   douser:
     {
       DOCFA;
   #ifdef DEBUG
       fprintf(stderr,"%08lx: user: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
   #endif
   #ifdef USE_TOS
       *sp-- = TOS;
       TOS = (Cell)(up+*(Cell*)PFA1(cfa));
   #else
       *--sp = (Cell)(up+*(Cell*)PFA1(cfa));
   #endif
     }
     NEXT_P0;
     NEXT;
       
    dodefer:
     {
       DOCFA;
   #ifdef DEBUG
       fprintf(stderr,"%08lx: defer: %08lx\n",(Cell)ip,*(Cell*)PFA1(cfa));
   #endif
       EXEC(*(Xt *)PFA1(cfa));
     }
   
    dofield:
     {
       DOCFA;
   #ifdef DEBUG
       fprintf(stderr,"%08lx: field: %08lx\n",(Cell)ip,(Cell)PFA1(cfa));
   #endif
       TOS += *(Cell*)PFA1(cfa); 
     }
     NEXT_P0;
     NEXT;
   
  dodoes:   dodoes:
   /* this assumes the following structure:    /* this assumes the following structure:
      defining-word:       defining-word:
Line 180  Label *engine(Xt *ip, Cell *sp, Cell *rp Line 392  Label *engine(Xt *ip, Cell *sp, Cell *rp
      pfa:       pfa:
             
      */       */
     {
       DOCFA;
   
       /*    fprintf(stderr, "Got CFA %08lx at doescode %08lx/%08lx: does: %08lx\n",cfa,(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));*/
 #ifdef DEBUG  #ifdef DEBUG
   printf("does: %x\n",(Cell)PFA(cfa));      fprintf(stderr,"%08lx/%08lx: does: %08lx\n",(Cell)ip,(Cell)PFA(cfa),(Cell)DOES_CODE1(cfa));
       fflush(stderr);
 #endif  #endif
   *--rp = (Cell)ip;      *--rp = (Cell)ip;
   /* PFA1 might collide with DOES_CODE1 here, so we use PFA */      /* PFA1 might collide with DOES_CODE1 here, so we use PFA */
       ip = DOES_CODE1(cfa);
 #ifdef USE_TOS  #ifdef USE_TOS
   *sp-- = TOS;      *sp-- = TOS;
   TOS = (Cell)PFA(cfa);      TOS = (Cell)PFA(cfa);
 #else  #else
   *--sp = (Cell)PFA(cfa);      *--sp = (Cell)PFA(cfa);
 #endif  #endif
   ip = DOES_CODE1(cfa);      /*    fprintf(stderr,"TOS = %08lx, IP=%08lx\n", TOS, IP);*/
     }
     NEXT_P0;
   NEXT;    NEXT;
     
 #include "primitives.i"  #include "primitives.i"
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.41


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>