Annotation of gforth/main.c, revision 1.31
1.30 anton 1: /* command line interpretation, image loading etc. for Gforth
2:
3:
4: Copyright (C) 1995 Free Software Foundation, Inc.
5:
6: This file is part of Gforth.
7:
8: Gforth is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License
10: as published by the Free Software Foundation; either version 2
11: of the License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1.1 anton 21: */
22:
23: #include <ctype.h>
24: #include <stdio.h>
25: #include <string.h>
26: #include <math.h>
27: #include <sys/types.h>
28: #include <sys/stat.h>
29: #include <fcntl.h>
30: #include <assert.h>
31: #include <stdlib.h>
32: #include "forth.h"
1.5 pazsan 33: #include "io.h"
1.20 anton 34: #include "getopt.h"
1.2 pazsan 35:
1.22 pazsan 36: #ifdef MSDOS
37: jmp_buf throw_jmp_buf;
38: #endif
39:
1.10 anton 40: #ifndef DEFAULTPATH
1.16 pazsan 41: # define DEFAULTPATH "/usr/local/lib/gforth:."
1.10 anton 42: #endif
43:
1.1 anton 44: #ifdef DIRECT_THREADED
1.16 pazsan 45: # define CA(n) (symbols[(n)])
1.1 anton 46: #else
1.21 pazsan 47: # define CA(n) ((Cell)(symbols+(n)))
1.1 anton 48: #endif
49:
1.23 pazsan 50: #define maxaligned(n) (typeof(n))((((Cell)n)+sizeof(Float)-1)&-sizeof(Float))
1.10 anton 51:
1.21 pazsan 52: static Cell dictsize=0;
53: static Cell dsize=0;
54: static Cell rsize=0;
55: static Cell fsize=0;
56: static Cell lsize=0;
1.10 anton 57: char *progname;
58:
59:
1.1 anton 60: /* image file format:
1.18 pazsan 61: * preamble (is skipped off), size multiple of 8
62: * magig: "gforth00" (means format version 0.0)
1.25 pazsan 63: * "gforth0x" means format 0.1,
64: * whereas x in 2 4 8 for big endian and 3 5 9 for little endian
65: * and x & -2 is the size of the cell in byte.
1.1 anton 66: * size of image with stacks without tags (in bytes)
67: * size of image without stacks and tags (in bytes)
1.5 pazsan 68: * size of data and FP stack (in bytes)
1.1 anton 69: * pointer to start of code
1.7 anton 70: * pointer into throw (for signal handling)
1.16 pazsan 71: * pointer to dictionary
1.1 anton 72: * data (size in image[1])
73: * tags (1 bit/data cell)
74: *
75: * tag==1 mean that the corresponding word is an address;
76: * If the word is >=0, the address is within the image;
77: * addresses within the image are given relative to the start of the image.
78: * If the word is =-1, the address is NIL,
1.2 pazsan 79: * If the word is between -2 and -5, it's a CFA (:, Create, Constant, User)
1.24 pazsan 80: * If the word is -7, it's a DOES> CFA
81: * If the word is -8, it's a DOES JUMP
82: * If the word is <-9, it's a primitive
1.1 anton 83: */
84:
1.10 anton 85: void relocate(Cell *image, char *bitstring, int size, Label symbols[])
1.1 anton 86: {
1.16 pazsan 87: int i=0, j, k, steps=(size/sizeof(Cell))/8;
88: char bits;
1.5 pazsan 89: /* static char bits[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};*/
90:
1.16 pazsan 91: for(k=0; k<=steps; k++)
92: for(j=0, bits=bitstring[k]; j<8; j++, i++, bits<<=1)
93: if(bits & 0x80)
94: if(image[i]<0)
95: switch(image[i])
96: {
97: case CF_NIL : image[i]=0; break;
98: case CF(DOCOL) :
99: case CF(DOVAR) :
100: case CF(DOCON) :
101: case CF(DOUSER) :
1.24 pazsan 102: case CF(DODEFER) :
1.28 anton 103: case CF(DOFIELD) : MAKE_CF(image+i,symbols[CF(image[i])]); break;
1.21 pazsan 104: case CF(DODOES) : MAKE_DOES_CF(image+i,image[i+1]+((Cell)image));
1.16 pazsan 105: break;
106: case CF(DOESJUMP): MAKE_DOES_HANDLER(image+i); break;
107: default : image[i]=(Cell)CA(CF(image[i]));
108: }
109: else
110: image[i]+=(Cell)image;
1.1 anton 111: }
112:
1.10 anton 113: Cell *loader(FILE *imagefile)
114: {
1.16 pazsan 115: Cell header[3];
116: Cell *image;
1.18 pazsan 117: Char magic[8];
1.16 pazsan 118: int wholesize;
119: int imagesize; /* everything needed by the image */
1.18 pazsan 120:
1.25 pazsan 121: static char* endsize[10]=
122: {
123: "no size information", "",
124: "16 bit big endian", "16 bit little endian",
125: "32 bit big endian", "32 bit little endian",
126: "n/n", "n/n",
127: "64 bit big endian", "64 bit little endian",
128: };
129:
1.18 pazsan 130: do
131: {
132: if(fread(magic,sizeof(Char),8,imagefile) < 8) {
1.25 pazsan 133: fprintf(stderr,"This image doesn't seem to be a gforth image.\n");
1.18 pazsan 134: exit(1);
135: }
136: #ifdef DEBUG
137: printf("Magic found: %s\n",magic);
138: #endif
139: }
1.25 pazsan 140: while(memcmp(magic,"gforth0",7));
141:
142: if(!(magic[7]=='0' || magic[7] == sizeof(Cell) +
143: #ifdef WORDS_BIGENDIAN
144: '0'
145: #else
146: '1'
147: #endif
148: ))
149: { fprintf(stderr,"This image is %s, whereas the machine is %s.\n",
150: endsize[magic[7]-'0'],
151: endsize[sizeof(Cell) +
152: #ifdef WORDS_BIGENDIAN
153: 0
154: #else
155: 1
156: #endif
157: ]);
158: exit(-2);
159: };
1.18 pazsan 160:
161: fread(header,sizeof(Cell),3,imagefile);
1.16 pazsan 162: if (dictsize==0)
163: dictsize = header[0];
164: if (dsize==0)
165: dsize=header[2];
166: if (rsize==0)
167: rsize=header[2];
168: if (fsize==0)
169: fsize=header[2];
170: if (lsize==0)
171: lsize=header[2];
172: dictsize=maxaligned(dictsize);
173: dsize=maxaligned(dsize);
174: rsize=maxaligned(rsize);
175: lsize=maxaligned(lsize);
176: fsize=maxaligned(fsize);
177:
178: wholesize = dictsize+dsize+rsize+fsize+lsize;
179: imagesize = header[1]+((header[1]-1)/sizeof(Cell))/8+1;
1.23 pazsan 180: image=malloc((wholesize>imagesize?wholesize:imagesize)+sizeof(Float));
181: image = maxaligned(image);
1.16 pazsan 182: memset(image,0,wholesize); /* why? - anton */
183: image[0]=header[0];
184: image[1]=header[1];
185: image[2]=header[2];
186:
187: fread(image+3,1,header[1]-3*sizeof(Cell),imagefile);
188: fread(((void *)image)+header[1],1,((header[1]-1)/sizeof(Cell))/8+1,
189: imagefile);
190: fclose(imagefile);
191:
192: if(image[5]==0) {
193: relocate(image,(char *)image+header[1],header[1],engine(0,0,0,0,0));
194: }
195: else if(image[5]!=(Cell)image) {
1.28 anton 196: 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, image[5], (Cell)image);
1.16 pazsan 197: exit(1);
198: }
1.1 anton 199:
1.16 pazsan 200: CACHE_FLUSH(image,image[1]);
201:
202: return(image);
1.1 anton 203: }
204:
1.10 anton 205: int go_forth(Cell *image, int stack, Cell *entries)
1.1 anton 206: {
1.15 anton 207: Cell *sp=(Cell*)((void *)image+dictsize+dsize);
208: Address lp=(Address)((void *)sp+lsize);
209: Float *fp=(Float *)((void *)lp+fsize);
210: Cell *rp=(Cell*)((void *)fp+rsize);
1.21 pazsan 211: Xt *ip=(Xt *)((Cell)image[3]);
1.15 anton 212: int throw_code;
213:
214: for(;stack>0;stack--)
215: *--sp=entries[stack-1];
216:
217: install_signal_handlers(); /* right place? */
218:
219: if ((throw_code=setjmp(throw_jmp_buf))) {
220: static Cell signal_data_stack[8];
221: static Cell signal_return_stack[8];
222: static Float signal_fp_stack[1];
223:
224: signal_data_stack[7]=throw_code;
225:
226: return((int)engine((Xt *)image[4],signal_data_stack+7,
227: signal_return_stack+8,signal_fp_stack,0));
228: }
229:
230: return((int)engine(ip,sp,rp,fp,lp));
1.1 anton 231: }
232:
1.10 anton 233: int convsize(char *s, int elemsize)
234: /* converts s of the format #+u (e.g. 25k) into the number of bytes.
235: the unit u can be one of bekM, where e stands for the element
236: size. default is e */
237: {
238: char *endp;
239: int n,m;
240:
241: m = elemsize;
242: n = strtoul(s,&endp,0);
243: if (endp!=NULL) {
244: if (strcmp(endp,"b")==0)
245: m=1;
246: else if (strcmp(endp,"k")==0)
247: m=1024;
248: else if (strcmp(endp,"M")==0)
249: m=1024*1024;
1.31 ! anton 250: else if (strcmp(endp,"e")!=0 && strcmp(endp,"")!=0) {
! 251: fprintf(stderr,"%s: cannot grok size specification %s: invalid unit \"%s\"\n", progname, s, endp);
1.10 anton 252: exit(1);
253: }
254: }
255: return n*m;
256: }
257:
1.1 anton 258: int main(int argc, char **argv, char **env)
259: {
1.16 pazsan 260: char *path, *path1;
261: char *imagename="gforth.fi";
262: FILE *image_file;
263: int c, retvalue;
1.10 anton 264:
1.14 anton 265: #if defined(i386) && defined(ALIGNMENT_CHECK) && !defined(DIRECT_THREADED)
1.30 anton 266: /* turn on alignment checks on the 486.
267: * on the 386 this should have no effect. */
268: __asm__("pushfl; popl %eax; orl $0x40000, %eax; pushl %eax; popfl;");
269: /* this is unusable with Linux' libc.4.6.27, because this library is
270: not alignment-clean; we would have to replace some library
271: functions (e.g., memcpy) to make it work */
1.6 anton 272: #endif
1.2 pazsan 273:
1.16 pazsan 274: progname = argv[0];
275: if ((path=getenv("GFORTHPATH"))==NULL)
276: path = strcpy(malloc(strlen(DEFAULTPATH)+1),DEFAULTPATH);
277: opterr=0;
278: while (1) {
279: int option_index=0;
280: static struct option opts[] = {
281: {"image-file", required_argument, NULL, 'i'},
282: {"dictionary-size", required_argument, NULL, 'm'},
283: {"data-stack-size", required_argument, NULL, 'd'},
284: {"return-stack-size", required_argument, NULL, 'r'},
285: {"fp-stack-size", required_argument, NULL, 'f'},
286: {"locals-stack-size", required_argument, NULL, 'l'},
287: {"path", required_argument, NULL, 'p'},
288: {0,0,0,0}
289: /* no-init-file, no-rc? */
290: };
1.10 anton 291:
1.17 pazsan 292: c = getopt_long(argc, argv, "+i:m:d:r:f:l:p:", opts, &option_index);
1.12 pazsan 293:
1.16 pazsan 294: if (c==EOF)
295: break;
296: if (c=='?') {
297: optind--;
298: break;
299: }
300: switch (c) {
301: case 'i': imagename = optarg; break;
302: case 'm': dictsize = convsize(optarg,sizeof(Cell)); break;
303: case 'd': dsize = convsize(optarg,sizeof(Cell)); break;
304: case 'r': rsize = convsize(optarg,sizeof(Cell)); break;
305: case 'f': fsize = convsize(optarg,sizeof(Float)); break;
306: case 'l': lsize = convsize(optarg,sizeof(Cell)); break;
307: case 'p': path = optarg; break;
308: }
309: }
310: path1=path;
1.29 pazsan 311:
312: if(strchr(imagename, '/')==NULL)
313: {
314: do {
315: char *pend=strchr(path, ':');
316: if (pend==NULL)
317: pend=path+strlen(path);
318: if (strlen(path)==0) {
319: fprintf(stderr,"%s: cannot open image file %s in path %s for reading\n",
320: progname, imagename, path1);
321: exit(1);
322: }
323: {
324: int dirlen=pend-path;
325: char fullfilename[dirlen+strlen(imagename)+2];
326: memcpy(fullfilename, path, dirlen);
327: if (fullfilename[dirlen-1]!='/')
328: fullfilename[dirlen++]='/';
329: strcpy(fullfilename+dirlen,imagename);
330: image_file=fopen(fullfilename,"rb");
331: }
332: path=pend+(*pend==':');
333: } while (image_file==NULL);
1.16 pazsan 334: }
1.29 pazsan 335: else
1.16 pazsan 336: {
1.29 pazsan 337: image_file=fopen(imagename,"rb");
338: if(image_file==NULL)
339: fprintf(stderr,"%s: cannot open image file %s for reading\n",
340: progname, imagename);
1.16 pazsan 341: }
1.29 pazsan 342:
1.16 pazsan 343: {
344: Cell environ[]= {
345: (Cell)argc-(optind-1),
346: (Cell)(argv+(optind-1)),
347: (Cell)path1};
348: argv[optind-1] = progname;
349: /*
350: for (i=0; i<environ[0]; i++)
351: printf("%s\n", ((char **)(environ[1]))[i]);
352: */
353: retvalue=go_forth(loader(image_file),3,environ);
354: deprep_terminal();
355: exit(retvalue);
356: }
1.1 anton 357: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>