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.
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"
33: #include "io.h"
34: #include "getopt.h"
35:
36: #ifdef MSDOS
37: jmp_buf throw_jmp_buf;
38: #endif
39:
40: #ifndef DEFAULTPATH
41: # define DEFAULTPATH "/usr/local/lib/gforth:."
42: #endif
43:
44: #ifdef DIRECT_THREADED
45: # define CA(n) (symbols[(n)])
46: #else
47: # define CA(n) ((Cell)(symbols+(n)))
48: #endif
49:
50: #define maxaligned(n) (typeof(n))((((Cell)n)+sizeof(Float)-1)&-sizeof(Float))
51:
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;
57: char *progname;
58:
59:
60: /* image file format:
61: * preamble (is skipped off), size multiple of 8
62: * magig: "gforth00" (means format version 0.0)
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.
66: * size of image with stacks without tags (in bytes)
67: * size of image without stacks and tags (in bytes)
68: * size of data and FP stack (in bytes)
69: * pointer to start of code
70: * pointer into throw (for signal handling)
71: * pointer to dictionary
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,
79: * If the word is between -2 and -5, it's a CFA (:, Create, Constant, User)
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
83: */
84:
85: void relocate(Cell *image, char *bitstring, int size, Label symbols[])
86: {
87: int i=0, j, k, steps=(size/sizeof(Cell))/8;
88: char bits;
89: /* static char bits[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};*/
90:
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) :
102: case CF(DODEFER) :
103: case CF(DOFIELD) : MAKE_CF(image+i,symbols[CF(image[i])]); break;
104: case CF(DODOES) : MAKE_DOES_CF(image+i,image[i+1]+((Cell)image));
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;
111: }
112:
113: Cell *loader(FILE *imagefile)
114: {
115: Cell header[3];
116: Cell *image;
117: Char magic[8];
118: int wholesize;
119: int imagesize; /* everything needed by the image */
120:
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:
130: do
131: {
132: if(fread(magic,sizeof(Char),8,imagefile) < 8) {
133: fprintf(stderr,"This image doesn't seem to be a gforth image.\n");
134: exit(1);
135: }
136: #ifdef DEBUG
137: printf("Magic found: %s\n",magic);
138: #endif
139: }
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: };
160:
161: fread(header,sizeof(Cell),3,imagefile);
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;
180: image=malloc((wholesize>imagesize?wholesize:imagesize)+sizeof(Float));
181: image = maxaligned(image);
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) {
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);
197: exit(1);
198: }
199:
200: CACHE_FLUSH(image,image[1]);
201:
202: return(image);
203: }
204:
205: int go_forth(Cell *image, int stack, Cell *entries)
206: {
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);
211: Xt *ip=(Xt *)((Cell)image[3]);
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));
231: }
232:
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;
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);
252: exit(1);
253: }
254: }
255: return n*m;
256: }
257:
258: int main(int argc, char **argv, char **env)
259: {
260: char *path, *path1;
261: char *imagename="gforth.fi";
262: FILE *image_file;
263: int c, retvalue;
264:
265: #if defined(i386) && defined(ALIGNMENT_CHECK) && !defined(DIRECT_THREADED)
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 */
272: #endif
273:
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: };
291:
292: c = getopt_long(argc, argv, "+i:m:d:r:f:l:p:", opts, &option_index);
293:
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;
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);
334: }
335: else
336: {
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);
341: }
342:
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: }
357: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>