version 1.34, 1996/02/13 11:12:18
|
version 1.35, 1996/04/17 16:39:42
|
Line 21
|
Line 21
|
*/ |
*/ |
|
|
#include "config.h" |
#include "config.h" |
|
#include <errno.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <string.h> |
#include <string.h> |
Line 57 static Cell fsize=0;
|
Line 58 static Cell fsize=0;
|
static Cell lsize=0; |
static Cell lsize=0; |
char *progname; |
char *progname; |
|
|
|
|
/* image file format: |
/* image file format: |
* preamble (is skipped off), size multiple of 8 |
* "#! binary-path -i\n" (e.g., "#! /usr/local/bin/gforth-0.2.0 -i\n") |
* magig: "gforth00" (means format version 0.0) |
* padding to a multiple of 8 |
* "gforth0x" means format 0.1, |
* magic: "gforth1x" means format 0.2, |
* whereas x in 2 4 8 for big endian and 3 5 9 for little endian |
* where x is even for big endian and odd for little endian |
* and x & -2 is the size of the cell in byte. |
* and x & ~1 is the size of the cell in bytes. |
* size of image with stacks without tags (in bytes) |
* padding to max alignment (no padding necessary on current machines) |
* size of image without stacks and tags (in bytes) |
* ImageHeader structure (see below) |
* size of data and FP stack (in bytes) |
* data (size in ImageHeader.image_size) |
* pointer to start of code |
* tags ((if relocatable, 1 bit/data cell) |
* pointer into throw (for signal handling) |
|
* pointer to dictionary |
|
* data (size in image[1]) |
|
* tags (1 bit/data cell) |
|
* |
* |
* tag==1 mean that the corresponding word is an address; |
* tag==1 means that the corresponding word is an address; |
* If the word is >=0, the address is within the image; |
* If the word is >=0, the address is within the image; |
* addresses within the image are given relative to the start of the image. |
* addresses within the image are given relative to the start of the image. |
* If the word is =-1, the address is NIL, |
* If the word =-1 (CF_NIL), the address is NIL, |
* If the word is between -2 and -5, it's a CFA (:, Create, Constant, User) |
* If the word is <CF_NIL and >CF(DODOES), it's a CFA (:, Create, ...) |
* If the word is -7, it's a DOES> CFA |
* If the word =CF(DODOES), it's a DOES> CFA |
* If the word is -8, it's a DOES JUMP |
* If the word =CF(DOESJUMP), it's a DOES JUMP (2 Cells after DOES>, |
* If the word is <-9, it's a primitive |
* possibly containing a jump to dodoes) |
|
* If the word is <CF(DOESJUMP), it's a primitive |
*/ |
*/ |
|
|
|
typedef struct { |
|
Address base; /* base address of image (0 if relocatable) */ |
|
UCell checksum; /* checksum of ca's to protect against some |
|
incompatible binary/executable combinations |
|
(0 if relocatable) */ |
|
UCell image_size; /* all sizes in bytes */ |
|
UCell dict_size; |
|
UCell data_stack_size; |
|
UCell fp_stack_size; |
|
UCell return_stack_size; |
|
UCell locals_stack_size; |
|
Xt *boot_entry; /* initial ip for booting (in BOOT) */ |
|
Xt *throw_entry; /* ip after signal (in THROW) */ |
|
} ImageHeader; |
|
/* the image-header is created in main.fs */ |
|
|
void relocate(Cell *image, char *bitstring, int size, Label symbols[]) |
void relocate(Cell *image, char *bitstring, int size, Label symbols[]) |
{ |
{ |
int i=0, j, k, steps=(size/sizeof(Cell))/8; |
int i=0, j, k, steps=(size/sizeof(Cell))/8; |
Line 111 void relocate(Cell *image, char *bitstri
|
Line 124 void relocate(Cell *image, char *bitstri
|
image[i]+=(Cell)image; |
image[i]+=(Cell)image; |
} |
} |
|
|
Cell *loader(FILE *imagefile) |
UCell checksum(Label symbols[]) |
|
{ |
|
UCell r=0; |
|
Cell i; |
|
|
|
for (i=DOCOL; i<=DOESJUMP; i++) { |
|
r ^= (UCell)(symbols[i]); |
|
r = (r << 5) | (r >> (8*sizeof(Cell)-5)); |
|
} |
|
#ifdef DIRECT_THREADED |
|
/* we have to consider all the primitives */ |
|
for (; symbols[i]!=(Label)0; i++) { |
|
r ^= (UCell)(symbols[i]); |
|
r = (r << 5) | (r >> (8*sizeof(Cell)-5)); |
|
} |
|
#else |
|
/* in indirect threaded code all primitives are accessed through the |
|
symbols table, so we just have to put the base address of symbols |
|
in the checksum */ |
|
r ^= (UCell)symbols; |
|
#endif |
|
return r; |
|
} |
|
|
|
Address loader(FILE *imagefile) |
|
/* returns the address of the image proper (after the preamble) */ |
{ |
{ |
Cell header[3]; |
ImageHeader header; |
Cell *image; |
Address image; |
|
Address imp; /* image+preamble */ |
Char magic[8]; |
Char magic[8]; |
int wholesize; |
Cell wholesize; |
int imagesize; /* everything needed by the image */ |
Cell imagesize; /* everything needed by the image */ |
|
Cell preamblesize=0; |
|
Label *symbols=engine(0,0,0,0,0); |
|
UCell check_sum=checksum(symbols); |
|
|
static char* endsize[10]= |
static char* endianstring[]= { "big","little" }; |
{ |
|
"no size information", "", |
|
"16 bit big endian", "16 bit little endian", |
|
"32 bit big endian", "32 bit little endian", |
|
"n/n", "n/n", |
|
"64 bit big endian", "64 bit little endian", |
|
}; |
|
|
|
do |
do |
{ |
{ |
if(fread(magic,sizeof(Char),8,imagefile) < 8) { |
if(fread(magic,sizeof(Char),8,imagefile) < 8) { |
fprintf(stderr,"This image doesn't seem to be a gforth image.\n"); |
fprintf(stderr,"%s: image doesn't seem to be a Gforth image.\n",progname); |
exit(1); |
exit(1); |
} |
} |
|
preamblesize+=8; |
#ifdef DEBUG |
#ifdef DEBUG |
printf("Magic found: %s\n",magic); |
fprintf(stderr,"Magic found: %-8s\n",magic); |
#endif |
#endif |
} |
} |
while(memcmp(magic,"gforth0",7)); |
while(memcmp(magic,"Gforth1",7)); |
|
|
if(!(magic[7]=='0' || magic[7] == sizeof(Cell) + |
if(magic[7] != sizeof(Cell) + |
#ifdef WORDS_BIGENDIAN |
#ifdef WORDS_BIGENDIAN |
'0' |
'0' |
#else |
#else |
'1' |
'1' |
#endif |
#endif |
)) |
) |
{ fprintf(stderr,"This image is %s, whereas the machine is %s.\n", |
{ fprintf(stderr,"This image is %d bit %s-endian, whereas the machine is %d bit %s-endian.\n", |
endsize[magic[7]-'0'], |
((magic[7]-'0')&~1)*8, endianstring[magic[7]&1], |
endsize[sizeof(Cell) + |
sizeof(Cell)*8, endianstring[ |
#ifdef WORDS_BIGENDIAN |
#ifdef WORDS_BIGENDIAN |
0 |
0 |
#else |
#else |
Line 159 Cell *loader(FILE *imagefile)
|
Line 195 Cell *loader(FILE *imagefile)
|
exit(-2); |
exit(-2); |
}; |
}; |
|
|
fread(header,sizeof(Cell),3,imagefile); |
fread((void *)&header,sizeof(ImageHeader),1,imagefile); |
if (dictsize==0) |
if (dictsize==0) |
dictsize = header[0]; |
dictsize = header.dict_size; |
if (dsize==0) |
if (dsize==0) |
dsize=header[2]; |
dsize=header.data_stack_size; |
if (rsize==0) |
if (rsize==0) |
rsize=header[2]; |
rsize=header.return_stack_size; |
if (fsize==0) |
if (fsize==0) |
fsize=header[2]; |
fsize=header.fp_stack_size; |
if (lsize==0) |
if (lsize==0) |
lsize=header[2]; |
lsize=header.locals_stack_size; |
dictsize=maxaligned(dictsize); |
dictsize=maxaligned(dictsize); |
dsize=maxaligned(dsize); |
dsize=maxaligned(dsize); |
rsize=maxaligned(rsize); |
rsize=maxaligned(rsize); |
lsize=maxaligned(lsize); |
lsize=maxaligned(lsize); |
fsize=maxaligned(fsize); |
fsize=maxaligned(fsize); |
|
|
wholesize = dictsize+dsize+rsize+fsize+lsize; |
wholesize = preamblesize+dictsize+dsize+rsize+fsize+lsize; |
imagesize = header[1]+((header[1]-1)/sizeof(Cell))/8+1; |
imagesize = preamblesize+header.image_size+((header.image_size-1)/sizeof(Cell))/8+1; |
image=malloc((wholesize>imagesize?wholesize:imagesize)+sizeof(Float)); |
image=malloc((wholesize>imagesize?wholesize:imagesize)/*+sizeof(Float)*/); |
image = maxaligned(image); |
/*image = maxaligned(image);*/ |
memset(image,0,wholesize); /* why? - anton */ |
memset(image,0,wholesize); /* why? - anton */ |
image[0]=header[0]; |
rewind(imagefile); /* fseek(imagefile,0L,SEEK_SET); */ |
image[1]=header[1]; |
fread(image,1,imagesize,imagefile); |
image[2]=header[2]; |
|
|
|
fread(image+3,1,header[1]-3*sizeof(Cell),imagefile); |
|
fread(((void *)image)+header[1],1,((header[1]-1)/sizeof(Cell))/8+1, |
|
imagefile); |
|
fclose(imagefile); |
fclose(imagefile); |
|
imp=image+preamblesize; |
|
|
if(image[5]==0) { |
if(header.base==0) { |
relocate(image,(char *)image+header[1],header[1],engine(0,0,0,0,0)); |
relocate((Cell *)imp,imp+header.image_size,header.image_size,symbols); |
|
((ImageHeader *)imp)->checksum=check_sum; |
} |
} |
else if(image[5]!=(Cell)image) { |
else if(header.base!=imp) { |
fprintf(stderr,"%s: Cannot load nonrelocatable image (compiled for address 0x%lx) at address 0x%lx\nThe Gforth installer should look into the INSTALL file\n", progname, (unsigned long)image[5], (unsigned long)image); |
fprintf(stderr,"%s: Cannot load nonrelocatable image (compiled for address 0x%lx) at address 0x%lx\nThe Gforth installer should look into the INSTALL file\n", |
|
progname, (unsigned long)header.base, (unsigned long)imp); |
|
exit(1); |
|
} else if (header.checksum != check_sum) { |
|
fprintf(stderr,"%s: Checksum of image (0x%lx) does not match the executable (0x%lx)\nThe Gforth installer should look into the INSTALL file\n", |
|
progname, (unsigned long)(header.checksum),(unsigned long)check_sum); |
exit(1); |
exit(1); |
} |
} |
|
|
CACHE_FLUSH(image,image[1]); |
((ImageHeader *)imp)->dict_size=dictsize; |
|
((ImageHeader *)imp)->data_stack_size=dsize; |
return(image); |
((ImageHeader *)imp)->return_stack_size=rsize; |
|
((ImageHeader *)imp)->fp_stack_size=fsize; |
|
((ImageHeader *)imp)->locals_stack_size=lsize; |
|
|
|
CACHE_FLUSH(imp, header.imagesize); |
|
|
|
return imp; |
} |
} |
|
|
int go_forth(Cell *image, int stack, Cell *entries) |
int go_forth(Address image, int stack, Cell *entries) |
{ |
{ |
Cell *sp=(Cell*)((void *)image+dictsize+dsize); |
Cell *sp=(Cell*)(image+dictsize+dsize); |
Address lp=(Address)((void *)sp+lsize); |
Address lp=(Address)((void *)sp+lsize); |
Float *fp=(Float *)((void *)lp+fsize); |
Float *fp=(Float *)((void *)lp+fsize); |
Cell *rp=(Cell*)((void *)fp+rsize); |
Cell *rp=(Cell*)((void *)fp+rsize); |
Xt *ip=(Xt *)((Cell)image[3]); |
Xt *ip=(Xt *)(((ImageHeader *)image)->boot_entry); |
int throw_code; |
int throw_code; |
|
|
for(;stack>0;stack--) |
for(;stack>0;stack--) |
Line 225 int go_forth(Cell *image, int stack, Cel
|
Line 269 int go_forth(Cell *image, int stack, Cel
|
|
|
signal_data_stack[7]=throw_code; |
signal_data_stack[7]=throw_code; |
|
|
return((int)engine((Xt *)image[4],signal_data_stack+7, |
return((int)engine(((ImageHeader *)image)->throw_entry,signal_data_stack+7, |
signal_return_stack+8,signal_fp_stack,0)); |
signal_return_stack+8,signal_fp_stack,0)); |
} |
} |
|
|
return((int)engine(ip,sp,rp,fp,lp)); |
return((int)engine(ip,sp,rp,fp,lp)); |
} |
} |
|
|
Line 337 int main(int argc, char **argv, char **e
|
Line 381 int main(int argc, char **argv, char **e
|
else |
else |
{ |
{ |
image_file=fopen(imagename,"rb"); |
image_file=fopen(imagename,"rb"); |
if(image_file==NULL) |
if(image_file==NULL) { |
fprintf(stderr,"%s: cannot open image file %s for reading\n", |
fprintf(stderr,"%s: %s: %s\n", progname, imagename, strerror(errno)); |
progname, imagename); |
exit(1); |
|
} |
} |
} |
|
|
{ |
{ |