Annotation of gforth/engine/main.c, revision 1.12
1.1 anton 1: /* command line interpretation, image loading etc. for Gforth
2:
3:
1.12 ! anton 4: Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
1.1 anton 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 "config.h"
24: #include <errno.h>
25: #include <ctype.h>
26: #include <stdio.h>
1.2 pazsan 27: #include <unistd.h>
1.1 anton 28: #include <string.h>
29: #include <math.h>
30: #include <sys/types.h>
31: #include <sys/stat.h>
32: #include <fcntl.h>
33: #include <assert.h>
34: #include <stdlib.h>
1.11 pazsan 35: #ifndef STANDALONE
1.1 anton 36: #if HAVE_SYS_MMAN_H
37: #include <sys/mman.h>
38: #endif
1.11 pazsan 39: #endif
1.1 anton 40: #include "forth.h"
41: #include "io.h"
42: #include "getopt.h"
1.11 pazsan 43: #ifdef STANDALONE
44: #include <systypes.h>
45: #endif
1.1 anton 46:
47: #define PRIM_VERSION 1
48: /* increment this whenever the primitives change in an incompatible way */
49:
50: #ifdef MSDOS
51: jmp_buf throw_jmp_buf;
52: # ifndef DEFAULTPATH
53: # define DEFAULTPATH "."
54: # endif
55: #endif
56:
57: #if defined(DIRECT_THREADED)
58: # define CA(n) (symbols[(n)])
59: #else
60: # define CA(n) ((Cell)(symbols+(n)))
61: #endif
62:
63: #define maxaligned(n) (typeof(n))((((Cell)n)+sizeof(Float)-1)&-sizeof(Float))
64:
65: static UCell dictsize=0;
66: static UCell dsize=0;
67: static UCell rsize=0;
68: static UCell fsize=0;
69: static UCell lsize=0;
70: int offset_image=0;
1.4 anton 71: int die_on_signal=0;
1.1 anton 72: static int clear_dictionary=0;
73: static int debug=0;
74: static size_t pagesize=0;
75: char *progname;
76:
77: /* image file format:
78: * "#! binary-path -i\n" (e.g., "#! /usr/local/bin/gforth-0.3.0 -i\n")
79: * padding to a multiple of 8
80: * magic: "Gforth1x" means format 0.2,
81: * where x is even for big endian and odd for little endian
82: * and x & ~1 is the size of the cell in bytes.
83: * padding to max alignment (no padding necessary on current machines)
84: * ImageHeader structure (see below)
85: * data (size in ImageHeader.image_size)
86: * tags ((if relocatable, 1 bit/data cell)
87: *
88: * tag==1 means that the corresponding word is an address;
89: * If the word is >=0, the address is within the image;
90: * addresses within the image are given relative to the start of the image.
91: * If the word =-1 (CF_NIL), the address is NIL,
92: * If the word is <CF_NIL and >CF(DODOES), it's a CFA (:, Create, ...)
93: * If the word =CF(DODOES), it's a DOES> CFA
94: * If the word =CF(DOESJUMP), it's a DOES JUMP (2 Cells after DOES>,
95: * possibly containing a jump to dodoes)
96: * If the word is <CF(DOESJUMP), it's a primitive
97: */
98:
99: typedef struct {
100: Address base; /* base address of image (0 if relocatable) */
101: UCell checksum; /* checksum of ca's to protect against some
102: incompatible binary/executable combinations
103: (0 if relocatable) */
104: UCell image_size; /* all sizes in bytes */
105: UCell dict_size;
106: UCell data_stack_size;
107: UCell fp_stack_size;
108: UCell return_stack_size;
109: UCell locals_stack_size;
110: Xt *boot_entry; /* initial ip for booting (in BOOT) */
111: Xt *throw_entry; /* ip after signal (in THROW) */
112: Cell unused1; /* possibly tib stack size */
113: Cell unused2;
114: Address data_stack_base; /* this and the following fields are initialized by the loader */
115: Address fp_stack_base;
116: Address return_stack_base;
117: Address locals_stack_base;
118: } ImageHeader;
119: /* the image-header is created in main.fs */
120:
1.10 pazsan 121: void relocate(Cell *image, const char *bitstring, int size, Label symbols[])
1.1 anton 122: {
123: int i=0, j, k, steps=(size/sizeof(Cell))/8;
1.11 pazsan 124: Cell token;
1.1 anton 125: char bits;
126: /* static char bits[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};*/
127:
128: /* printf("relocating %x[%x]\n", image, size); */
129:
130: for(k=0; k<=steps; k++)
131: for(j=0, bits=bitstring[k]; j<8; j++, i++, bits<<=1) {
132: /* fprintf(stderr,"relocate: image[%d]\n", i);*/
133: if(bits & 0x80) {
134: /* fprintf(stderr,"relocate: image[%d]=%d\n", i, image[i]);*/
1.11 pazsan 135: if((token=image[i])<0)
136: switch(token)
1.1 anton 137: {
138: case CF_NIL : image[i]=0; break;
139: #if !defined(DOUBLY_INDIRECT)
140: case CF(DOCOL) :
141: case CF(DOVAR) :
142: case CF(DOCON) :
143: case CF(DOUSER) :
144: case CF(DODEFER) :
1.11 pazsan 145: case CF(DOFIELD) : MAKE_CF(image+i,symbols[CF(token)]); break;
1.1 anton 146: case CF(DOESJUMP): MAKE_DOES_HANDLER(image+i); break;
147: #endif /* !defined(DOUBLY_INDIRECT) */
148: case CF(DODOES) :
149: MAKE_DOES_CF(image+i,image[i+1]+((Cell)image));
150: break;
151: default :
152: /* printf("Code field generation image[%x]:=CA(%x)\n",
153: i, CF(image[i])); */
1.11 pazsan 154: image[i]=(Cell)CA(CF(token));
1.1 anton 155: }
156: else
157: image[i]+=(Cell)image;
158: }
159: }
160: }
161:
162: UCell checksum(Label symbols[])
163: {
164: UCell r=PRIM_VERSION;
165: Cell i;
166:
167: for (i=DOCOL; i<=DOESJUMP; i++) {
168: r ^= (UCell)(symbols[i]);
169: r = (r << 5) | (r >> (8*sizeof(Cell)-5));
170: }
171: #ifdef DIRECT_THREADED
172: /* we have to consider all the primitives */
173: for (; symbols[i]!=(Label)0; i++) {
174: r ^= (UCell)(symbols[i]);
175: r = (r << 5) | (r >> (8*sizeof(Cell)-5));
176: }
177: #else
178: /* in indirect threaded code all primitives are accessed through the
179: symbols table, so we just have to put the base address of symbols
180: in the checksum */
181: r ^= (UCell)symbols;
182: #endif
183: return r;
184: }
185:
1.3 anton 186: Address verbose_malloc(Cell size)
187: {
188: Address r;
189: /* leave a little room (64B) for stack underflows */
190: if ((r = malloc(size+64))==NULL) {
191: perror(progname);
192: exit(1);
193: }
194: r = (Address)((((Cell)r)+(sizeof(Float)-1))&(-sizeof(Float)));
195: if (debug)
196: fprintf(stderr, "malloc succeeds, address=$%lx\n", (long)r);
197: return r;
198: }
199:
1.1 anton 200: Address my_alloc(Cell size)
201: {
1.5 jwilke 202: #if HAVE_MMAP
1.1 anton 203: static Address next_address=0;
204: Address r;
205:
206: #if defined(MAP_ANON)
207: if (debug)
208: fprintf(stderr,"try mmap($%lx, $%lx, ..., MAP_ANON, ...); ", (long)next_address, (long)size);
209: r=mmap(next_address, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
210: #else /* !defined(MAP_ANON) */
211: /* Ultrix (at least does not define MAP_FILE and MAP_PRIVATE (both are
212: apparently defaults*/
213: #ifndef MAP_FILE
214: # define MAP_FILE 0
215: #endif
216: #ifndef MAP_PRIVATE
217: # define MAP_PRIVATE 0
218: #endif
219: static int dev_zero=-1;
220:
221: if (dev_zero == -1)
222: dev_zero = open("/dev/zero", O_RDONLY);
223: if (dev_zero == -1) {
224: r = (Address)-1;
225: if (debug)
226: fprintf(stderr, "open(\"/dev/zero\"...) failed (%s), no mmap; ",
227: strerror(errno));
228: } else {
229: if (debug)
230: fprintf(stderr,"try mmap($%lx, $%lx, ..., MAP_FILE, dev_zero, ...); ", (long)next_address, (long)size);
231: r=mmap(next_address, size, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, dev_zero, 0);
232: }
233: #endif /* !defined(MAP_ANON) */
234:
235: if (r != (Address)-1) {
236: if (debug)
237: fprintf(stderr, "success, address=$%lx\n", (long) r);
238: if (pagesize != 0)
239: next_address = (Address)(((((Cell)r)+size-1)&-pagesize)+2*pagesize); /* leave one page unmapped */
240: return r;
241: }
242: if (debug)
243: fprintf(stderr, "failed: %s\n", strerror(errno));
244: #endif /* HAVE_MMAP */
1.3 anton 245: /* use malloc as fallback */
246: return verbose_malloc(size);
1.1 anton 247: }
248:
1.3 anton 249: #if (defined(mips) && !defined(INDIRECT_THREADED))
250: /* the 256MB jump restriction on the MIPS architecture makes the
251: combination of direct threading and mmap unsafe. */
252: #define dict_alloc(size) verbose_malloc(size)
253: #else
254: #define dict_alloc(size) my_alloc(size)
255: #endif
256:
1.10 pazsan 257: void set_stack_sizes(ImageHeader * header)
258: {
259: if (dictsize==0)
260: dictsize = header->dict_size;
261: if (dsize==0)
262: dsize = header->data_stack_size;
263: if (rsize==0)
264: rsize = header->return_stack_size;
265: if (fsize==0)
266: fsize = header->fp_stack_size;
267: if (lsize==0)
268: lsize = header->locals_stack_size;
269: dictsize=maxaligned(dictsize);
270: dsize=maxaligned(dsize);
271: rsize=maxaligned(rsize);
272: lsize=maxaligned(lsize);
273: fsize=maxaligned(fsize);
274: }
275:
276: void alloc_stacks(ImageHeader * header)
277: {
278: header->dict_size=dictsize;
279: header->data_stack_size=dsize;
280: header->fp_stack_size=fsize;
281: header->return_stack_size=rsize;
282: header->locals_stack_size=lsize;
283:
284: header->data_stack_base=my_alloc(dsize);
285: header->fp_stack_base=my_alloc(fsize);
286: header->return_stack_base=my_alloc(rsize);
287: header->locals_stack_base=my_alloc(lsize);
288: }
289:
1.11 pazsan 290: int go_forth(Address image, int stack, Cell *entries)
291: {
292: Cell *sp=(Cell*)(((ImageHeader *)image)->data_stack_base + dsize);
293: Float *fp=(Float *)(((ImageHeader *)image)->fp_stack_base + fsize);
294: Cell *rp=(Cell *)(((ImageHeader *)image)->return_stack_base + rsize);
295: Address lp=((ImageHeader *)image)->locals_stack_base + lsize;
296: Xt *ip=(Xt *)(((ImageHeader *)image)->boot_entry);
297: int throw_code;
298:
299: /* ensure that the cached elements (if any) are accessible */
300: IF_TOS(sp--);
301: IF_FTOS(fp--);
302:
303: for(;stack>0;stack--)
304: *--sp=entries[stack-1];
305:
306: #if !defined(MSDOS) && !defined(_WIN32) && !defined(__EMX__)
307: get_winsize();
308: #endif
309:
310: install_signal_handlers(); /* right place? */
311:
312: if ((throw_code=setjmp(throw_jmp_buf))) {
313: static Cell signal_data_stack[8];
314: static Cell signal_return_stack[8];
315: static Float signal_fp_stack[1];
316:
317: signal_data_stack[7]=throw_code;
318:
319: return((int)engine(((ImageHeader *)image)->throw_entry,signal_data_stack+7,
320: signal_return_stack+8,signal_fp_stack,0));
321: }
322:
323: return((int)engine(ip,sp,rp,fp,lp));
324: }
325:
326: #ifndef INCLUDE_IMAGE
1.1 anton 327: Address loader(FILE *imagefile, char* filename)
328: /* returns the address of the image proper (after the preamble) */
329: {
330: ImageHeader header;
331: Address image;
332: Address imp; /* image+preamble */
333: Char magic[9];
334: Cell preamblesize=0;
335: Label *symbols = engine(0,0,0,0,0);
1.6 pazsan 336: Cell data_offset = offset_image ? 56*sizeof(Cell) : 0;
1.1 anton 337: UCell check_sum;
338: static char* endianstring[]= { "big","little" };
339:
340: #ifndef DOUBLY_INDIRECT
341: check_sum = checksum(symbols);
342: #else /* defined(DOUBLY_INDIRECT) */
343: check_sum = (UCell)symbols;
344: #endif /* defined(DOUBLY_INDIRECT) */
1.10 pazsan 345:
346: do {
347: if(fread(magic,sizeof(Char),8,imagefile) < 8) {
348: fprintf(stderr,"%s: image %s doesn't seem to be a Gforth (>=0.2) image.\n",
349: progname, filename);
350: exit(1);
1.1 anton 351: }
1.10 pazsan 352: preamblesize+=8;
353: } while(memcmp(magic,"Gforth1",7));
1.1 anton 354: if (debug) {
355: magic[8]='\0';
356: fprintf(stderr,"Magic found: %s\n", magic);
357: }
358:
359: if(magic[7] != sizeof(Cell) +
360: #ifdef WORDS_BIGENDIAN
361: '0'
362: #else
363: '1'
364: #endif
365: )
366: { fprintf(stderr,"This image is %d bit %s-endian, whereas the machine is %d bit %s-endian.\n",
367: ((magic[7]-'0')&~1)*8, endianstring[magic[7]&1],
1.5 jwilke 368: (int) sizeof(Cell)*8, endianstring[
1.1 anton 369: #ifdef WORDS_BIGENDIAN
370: 0
371: #else
372: 1
373: #endif
374: ]);
375: exit(-2);
376: };
377:
378: fread((void *)&header,sizeof(ImageHeader),1,imagefile);
1.10 pazsan 379:
380: set_stack_sizes(&header);
1.1 anton 381:
382: #if HAVE_GETPAGESIZE
383: pagesize=getpagesize(); /* Linux/GNU libc offers this */
384: #elif HAVE_SYSCONF && defined(_SC_PAGESIZE)
385: pagesize=sysconf(_SC_PAGESIZE); /* POSIX.4 */
386: #elif PAGESIZE
387: pagesize=PAGESIZE; /* in limits.h according to Gallmeister's POSIX.4 book */
388: #endif
389: if (debug)
1.5 jwilke 390: fprintf(stderr,"pagesize=%ld\n",(unsigned long) pagesize);
1.1 anton 391:
1.3 anton 392: image = dict_alloc(preamblesize+dictsize+data_offset)+data_offset;
1.1 anton 393: rewind(imagefile); /* fseek(imagefile,0L,SEEK_SET); */
394: if (clear_dictionary)
1.10 pazsan 395: memset(image, 0, dictsize);
396: fread(image, 1, preamblesize+header.image_size, imagefile);
1.1 anton 397: imp=image+preamblesize;
398: if(header.base==0) {
399: Cell reloc_size=((header.image_size-1)/sizeof(Cell))/8+1;
400: char reloc_bits[reloc_size];
1.10 pazsan 401: fread(reloc_bits, 1, reloc_size, imagefile);
402: relocate((Cell *)imp, reloc_bits, header.image_size, symbols);
1.1 anton 403: #if 0
404: { /* let's see what the relocator did */
405: FILE *snapshot=fopen("snapshot.fi","wb");
406: fwrite(image,1,imagesize,snapshot);
407: fclose(snapshot);
408: }
409: #endif
410: }
411: else if(header.base!=imp) {
412: fprintf(stderr,"%s: Cannot load nonrelocatable image (compiled for address $%lx) at address $%lx\n",
413: progname, (unsigned long)header.base, (unsigned long)imp);
414: exit(1);
415: }
416: if (header.checksum==0)
417: ((ImageHeader *)imp)->checksum=check_sum;
418: else if (header.checksum != check_sum) {
419: fprintf(stderr,"%s: Checksum of image ($%lx) does not match the executable ($%lx)\n",
420: progname, (unsigned long)(header.checksum),(unsigned long)check_sum);
421: exit(1);
422: }
423: fclose(imagefile);
424:
1.10 pazsan 425: alloc_stacks((ImageHeader *)imp);
1.1 anton 426:
427: CACHE_FLUSH(imp, header.image_size);
428:
429: return imp;
430: }
431:
432: int onlypath(char *file)
1.10 pazsan 433: {
434: int i;
1.1 anton 435: i=strlen(file);
1.10 pazsan 436: while (i) {
437: if (file[i]=='\\' || file[i]=='/') break;
438: i--;
439: }
440: return i;
1.1 anton 441: }
442:
443: FILE *openimage(char *fullfilename)
1.10 pazsan 444: {
445: FILE *image_file;
446:
1.1 anton 447: image_file=fopen(fullfilename,"rb");
448: if (image_file!=NULL && debug)
1.10 pazsan 449: fprintf(stderr, "Opened image file: %s\n", fullfilename);
450: return image_file;
1.1 anton 451: }
452:
453: FILE *checkimage(char *path, int len, char *imagename)
1.10 pazsan 454: {
455: int dirlen=len;
1.1 anton 456: char fullfilename[dirlen+strlen(imagename)+2];
1.10 pazsan 457:
1.1 anton 458: memcpy(fullfilename, path, dirlen);
459: if (fullfilename[dirlen-1]!='/')
460: fullfilename[dirlen++]='/';
461: strcpy(fullfilename+dirlen,imagename);
1.10 pazsan 462: return openimage(fullfilename);
1.1 anton 463: }
464:
1.10 pazsan 465: FILE * open_image_file(char * imagename, char * path)
1.1 anton 466: {
1.10 pazsan 467: FILE * image_file=NULL;
468:
469: if(strchr(imagename, '/')==NULL) {
470: /* first check the directory where the exe file is in !! 01may97jaw */
471: if (onlypath(progname))
472: image_file=checkimage(progname, onlypath(progname), imagename);
473: if (!image_file)
474: do {
475: char *pend=strchr(path, PATHSEP);
476: if (pend==NULL)
477: pend=path+strlen(path);
478: if (strlen(path)==0) break;
479: image_file=checkimage(path, pend-path, imagename);
480: path=pend+(*pend==PATHSEP);
481: } while (image_file==NULL);
482: } else {
483: image_file=openimage(imagename);
484: }
1.1 anton 485:
1.10 pazsan 486: if (!image_file) {
487: fprintf(stderr,"%s: cannot open image file %s in path %s for reading\n",
488: progname, imagename, path);
489: exit(1);
1.7 anton 490: }
491:
1.10 pazsan 492: return image_file;
493: }
1.11 pazsan 494: #endif
495:
496: #ifdef HAS_OS
497: UCell convsize(char *s, UCell elemsize)
498: /* converts s of the format [0-9]+[bekMGT]? (e.g. 25k) into the number
499: of bytes. the letter at the end indicates the unit, where e stands
500: for the element size. default is e */
501: {
502: char *endp;
503: UCell n,m;
504:
505: m = elemsize;
506: n = strtoul(s,&endp,0);
507: if (endp!=NULL) {
508: if (strcmp(endp,"b")==0)
509: m=1;
510: else if (strcmp(endp,"k")==0)
511: m=1024;
512: else if (strcmp(endp,"M")==0)
513: m=1024*1024;
514: else if (strcmp(endp,"G")==0)
515: m=1024*1024*1024;
516: else if (strcmp(endp,"T")==0) {
517: #if (SIZEOF_CHAR_P > 4)
518: m=1024*1024*1024*1024;
519: #else
520: fprintf(stderr,"%s: size specification \"%s\" too large for this machine\n", progname, endp);
521: exit(1);
522: #endif
523: } else if (strcmp(endp,"e")!=0 && strcmp(endp,"")!=0) {
524: fprintf(stderr,"%s: cannot grok size specification %s: invalid unit \"%s\"\n", progname, s, endp);
525: exit(1);
526: }
527: }
528: return n*m;
529: }
1.10 pazsan 530:
531: void gforth_args(int argc, char ** argv, char ** path, char ** imagename)
532: {
533: int c;
534:
1.1 anton 535: opterr=0;
536: while (1) {
537: int option_index=0;
538: static struct option opts[] = {
539: {"image-file", required_argument, NULL, 'i'},
540: {"dictionary-size", required_argument, NULL, 'm'},
541: {"data-stack-size", required_argument, NULL, 'd'},
542: {"return-stack-size", required_argument, NULL, 'r'},
543: {"fp-stack-size", required_argument, NULL, 'f'},
544: {"locals-stack-size", required_argument, NULL, 'l'},
545: {"path", required_argument, NULL, 'p'},
546: {"version", no_argument, NULL, 'v'},
547: {"help", no_argument, NULL, 'h'},
548: /* put something != 0 into offset_image */
549: {"offset-image", no_argument, &offset_image, 1},
550: {"no-offset-im", no_argument, &offset_image, 0},
551: {"clear-dictionary", no_argument, &clear_dictionary, 1},
1.4 anton 552: {"die-on-signal", no_argument, &die_on_signal, 1},
1.1 anton 553: {"debug", no_argument, &debug, 1},
554: {0,0,0,0}
555: /* no-init-file, no-rc? */
556: };
557:
558: c = getopt_long(argc, argv, "+i:m:d:r:f:l:p:vh", opts, &option_index);
559:
560: if (c==EOF)
561: break;
562: if (c=='?') {
563: optind--;
564: break;
565: }
566: switch (c) {
1.10 pazsan 567: case 'i': *imagename = optarg; break;
1.1 anton 568: case 'm': dictsize = convsize(optarg,sizeof(Cell)); break;
569: case 'd': dsize = convsize(optarg,sizeof(Cell)); break;
570: case 'r': rsize = convsize(optarg,sizeof(Cell)); break;
571: case 'f': fsize = convsize(optarg,sizeof(Float)); break;
572: case 'l': lsize = convsize(optarg,sizeof(Cell)); break;
1.10 pazsan 573: case 'p': *path = optarg; break;
1.8 anton 574: case 'v': fprintf(stderr, "gforth %s\n", VERSION); exit(0);
1.1 anton 575: case 'h':
576: fprintf(stderr, "Usage: %s [engine options] [image arguments]\n\
577: Engine Options:\n\
1.10 pazsan 578: --clear-dictionary Initialize the dictionary with 0 bytes\n\
579: -d SIZE, --data-stack-size=SIZE Specify data stack size\n\
580: --debug Print debugging information during startup\n\
581: --die-on-signal exit instead of CATCHing some signals\n\
582: -f SIZE, --fp-stack-size=SIZE Specify floating point stack size\n\
583: -h, --help Print this message and exit\n\
584: -i FILE, --image-file=FILE Use image FILE instead of `gforth.fi'\n\
585: -l SIZE, --locals-stack-size=SIZE Specify locals stack size\n\
586: -m SIZE, --dictionary-size=SIZE Specify Forth dictionary size\n\
587: --no-offset-im Load image at normal position\n\
588: --offset-image Load image at a different position\n\
589: -p PATH, --path=PATH Search path for finding image and sources\n\
590: -r SIZE, --return-stack-size=SIZE Specify return stack size\n\
591: -v, --version Print version and exit\n\
1.1 anton 592: SIZE arguments consist of an integer followed by a unit. The unit can be\n\
1.10 pazsan 593: `b' (byte), `e' (element; default), `k' (KB), `M' (MB), `G' (GB) or `T' (TB).\n",
594: argv[0]);
595: optind--;
596: return;
597: exit(0);
1.1 anton 598: }
599: }
1.10 pazsan 600: }
1.11 pazsan 601: #endif
1.10 pazsan 602:
603: #ifdef INCLUDE_IMAGE
604: extern Cell image[];
605: extern const char reloc_bits[];
606: #endif
607:
608: int main(int argc, char **argv, char **env)
609: {
610: char *path = getenv("GFORTHPATH") ? : DEFAULTPATH;
611: char *imagename="gforth.fi";
612: FILE *image_file;
613: #ifndef INCLUDE_IMAGE
614: Address image;
615: #endif
616: int retvalue;
617:
618: #if defined(i386) && defined(ALIGNMENT_CHECK) && !defined(DIRECT_THREADED)
619: /* turn on alignment checks on the 486.
620: * on the 386 this should have no effect. */
621: __asm__("pushfl; popl %eax; orl $0x40000, %eax; pushl %eax; popfl;");
622: /* this is unusable with Linux' libc.4.6.27, because this library is
623: not alignment-clean; we would have to replace some library
624: functions (e.g., memcpy) to make it work. Also GCC doesn't try to keep
625: the stack FP-aligned. */
626: #endif
627:
628: /* buffering of the user output device */
1.11 pazsan 629: #ifdef _IONBF
1.10 pazsan 630: if (isatty(fileno(stdout))) {
631: fflush(stdout);
632: setvbuf(stdout,NULL,_IONBF,0);
1.1 anton 633: }
1.11 pazsan 634: #endif
1.1 anton 635:
1.10 pazsan 636: progname = argv[0];
637:
1.11 pazsan 638: #ifdef HAS_OS
1.10 pazsan 639: gforth_args(argc, argv, &path, &imagename);
1.11 pazsan 640: #endif
1.10 pazsan 641:
642: #ifdef INCLUDE_IMAGE
643: set_stack_sizes((ImageHeader *)image);
644: relocate(image, reloc_bits, ((ImageHeader*)&image)->image_size, (Label*)engine(0, 0, 0, 0, 0));
645: alloc_stacks((ImageHeader *)image);
646: #else
647: image_file = open_image_file(imagename, path);
648: image = loader(image_file, imagename);
649: #endif
1.1 anton 650:
651: {
1.10 pazsan 652: char path2[strlen(path)+1];
1.1 anton 653: char *p1, *p2;
654: Cell environ[]= {
655: (Cell)argc-(optind-1),
656: (Cell)(argv+(optind-1)),
1.10 pazsan 657: (Cell)strlen(path),
1.1 anton 658: (Cell)path2};
659: argv[optind-1] = progname;
660: /*
661: for (i=0; i<environ[0]; i++)
662: printf("%s\n", ((char **)(environ[1]))[i]);
663: */
664: /* make path OS-independent by replacing path separators with NUL */
1.10 pazsan 665: for (p1=path, p2=path2; *p1!='\0'; p1++, p2++)
1.1 anton 666: if (*p1==PATHSEP)
667: *p2 = '\0';
668: else
669: *p2 = *p1;
670: *p2='\0';
1.10 pazsan 671: retvalue = go_forth(image, 4, environ);
1.1 anton 672: deprep_terminal();
673: exit(retvalue);
674: }
675: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>