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