Imported Upstream version 0.1beta
[debian/yforth] / yforth.c
1 /* yForth? - Written by Luca Padovani (C) 1996/97
2  * ------------------------------------------------------------------------
3  * This software is FreeWare as long as it comes with this header in each
4  * source file, anyway you can use it or any part of it whatever
5  * you want. It comes without any warranty, so use it at your own risk.
6  * ------------------------------------------------------------------------
7  * Module name:     yforth.c
8  * Abstract:        Main program
9  */
10
11 #include <setjmp.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include "yforth.h"
15 #include "defaults.h"
16 #include "core.h"
17 #include "block.h"
18 #include "search.h"
19 #include "ver.h"
20 #include "file.h"
21
22 jmp_buf warm_start_jump, cold_start_jump;
23
24 Char *dp0;                          /* Data-Space base pointer */
25 Cell dspace_size = DEF_DSPACE_SIZE; /* Data-Space size */
26 Cell dstack_size = DEF_DSTACK_SIZE, /* Data-Stack size */
27      rstack_size = DEF_RSTACK_SIZE, /* Return-stack size */
28      fstack_size = DEF_FSTACK_SIZE; /* Floating-stack size */
29 Cell tib_size    = DEF_TIB_SIZE;    /* TIB size */
30 Cell in_pnos, pnos_size;            /* Pictured Numeric Output String */
31 Char *pnos, *p_pnos;                /* Ptrs inside PNOS */
32 Cell pad_size    = DEF_PAD_SIZE;    /* PAD size */
33
34 static char *file_name,             /* Ptr to file name on command line, if present */
35             *image_file;            /* Ptr to image file name on cmd line, if present */
36
37 static int silent,
38     image_file_loaded;
39
40 static struct image_header hd;
41
42 void print_version() {
43     printf("yForth? v%d.%d%s - Written by Luca Padovani (C) 1996.\n\
44 This software is Freeware, use it at your own risk.\n",
45         VER_HI, VER_LO, VER_TEST);
46 }
47
48 void print_help(void) {
49         print_version();
50         printf("Usage: yForth [options] [file name]\n\
51 -d<n>   Data-Space size         -s<n>   Data-Stack size\n\
52 -r<n>   Return-Stack size       -f<n>   Floating-Stack size\n\
53 -t<n>   TIB size                -p<n>   PAD size\n\
54 -h,-H   This help               -q      Quiet\n\
55 -i<file> Image file\n\
56 All sizes are expressed in cells.\n");
57 }
58
59 /* do_parameters: processes parameters passed on command line */
60 void do_parameters(int argc, char *argv[]) {
61         int i = 1;
62     while (argc-- > 1) {
63                 if (argv[i][0] == '-')
64                         switch (argv[i][1]) {
65                                 case 'd': dspace_size = atoi(argv[i] + 2); break;
66                                 case 's': dstack_size = atoi(argv[i] + 2); break;
67                                 case 'r': rstack_size = atoi(argv[i] + 2); break;
68                                 case 'f': fstack_size = atoi(argv[i] + 2); break;
69                                 case 't': tib_size = atoi(argv[i] + 2); break;
70                                 case 'p': pad_size = atoi(argv[i] + 2); break;
71                                 case 'q': silent = 1; break;
72                                 case 'i': image_file = argv[i] + 2; break;
73                                 case 'h':
74                                 case 'H':
75                                         print_help();
76                                         exit(0);
77                                         break;
78                                 default:
79                     fprintf(stderr, "%c unknown option, use -h for help.\n");
80                                         exit(0);
81                                         break;
82                         }
83                 else {
84                         file_name = argv[i];
85                         break;
86                 }
87         }
88 }
89
90 /* default_parameters: adjust environment parameters in case they do not
91  * fall into required range
92  */
93 void default_parameters(void) {
94         dspace_size = max(MIN_DSPACE_SIZE, dspace_size);
95         dstack_size = max(MIN_DSTACK_SIZE, dstack_size);
96         rstack_size = max(MIN_RSTACK_SIZE, rstack_size);
97         fstack_size = max(MIN_FSTACK_SIZE, fstack_size);
98         tib_size = max(MIN_TIB_SIZE, tib_size);
99         pad_size = max(MIN_PAD_SIZE, pad_size);
100 }
101
102 /* load_image_file: loads image file named "name" into the dictionary. Loading
103  * is divided in two parts: when "header" is set to 1 the file is opened and
104  * the header is loaded into the structure "hd". Then some checks are made
105  * to adjust parameters in case of a corrupted image.
106  * Finally, when "load_image_file" is called with "header" set to 0, the
107  * actual loading is performed. Note that pointers inside the dictionary
108  * are absolute, so an image file can be loaded only if the allocated
109  * memory is placed at the same address when it's been saved. Furthermore,
110  * the same image file cannot be loaded thru different version of the
111  * executable file "yForth".
112  */
113 int load_image_file(char *name, int header) {
114         FILE *f = fopen(name, "rb");
115         int res = 1;
116         if (f) {
117                 if (header) {
118                         if (fread(&hd, sizeof(struct image_header), 1, f)) {
119                                 if (hd.ver_hi != VER_HI || hd.ver_lo != VER_LO)
120                                         if (!silent)
121                         fprintf(stderr, "Warning: different image file version (%d.%d).\n",
122                                                 hd.ver_hi, hd.ver_lo);
123                                 if (hd.pattern != VERSION_PATTERN)
124                                         if (!silent)
125                                                 fprintf(stderr, "Warning: different version pattern (Image: %x).\n",
126                                                         hd.pattern); 
127                                 res = 0;
128             } else fprintf(stderr, "Error: can't read image file header.\n");
129                 } else {
130                         fseek(f, sizeof(struct image_header), SEEK_SET);
131                         if (hd.base == dp0) {
132                                 struct voc_marker vm;
133                                 if (fread(&vm, sizeof(struct voc_marker), 1, f) < 1 ||
134                                         fread(dp0, sizeof(Cell), hd.dspace_size, f) != hd.dspace_size)
135                     fprintf(stderr, "Error: can't read image file.\n");
136                                 else {
137                                         load_vocabulary(&vm);
138                                         res = 0;
139                                 }
140             } else fprintf(stderr, "Error: can't load image file with base %u at %u.\n",
141                                 hd.base, dp0);
142                 }
143                 fclose(f);
144     } else fprintf(stderr, "Can't open image file (%s).\n", name);
145         return (res);
146 }
147
148 main(int argc, char *argv[]) {
149         do_parameters(argc, argv);
150         if (image_file) {
151                 if (load_image_file(image_file, 1)) exit(-1);
152         } else fopen(argv[0], "rb");
153         /* !!! WARNING !!! Previous line opens a file even if no image-file
154          * is specified. This is because in some system data space would 
155          * result unaligned in subsequent loadings. I have to find a more
156          * smart trick here...
157          */ 
158
159         default_parameters();
160 #if BLOCK_DEF
161         open_block_file("YFORTH.BLK");
162 #endif
163         init_stacks(dstack_size, rstack_size, fstack_size);
164         if (image_file && dspace_size < hd.dspace_size) {
165                 if (!silent)
166             fprintf(stderr, "Warning: can't restrict dictionary to %u cells, now is %u cells.\n",
167                         dspace_size, hd.dspace_size);
168                 dspace_size = max(dspace_size, hd.dspace_size);
169         }
170         init_data_space(dspace_size);
171         init_tib(tib_size);
172         init_pad(pad_size);
173         init_pnos();
174         init_signals();
175
176         silent |= setjmp(cold_start_jump);
177         if (image_file)
178                 if (load_image_file(image_file, 0)) exit(-1);
179
180     /* Note that after a cold start the vocabulary is reloaded */
181
182         if (!silent) {
183                 print_version();
184                 /*
185                 printf("Cell: %d  Double-Cell: %d  Char: %d  Real: %d\n",
186                         sizeof(Cell), sizeof(DCell), sizeof(Char), sizeof(Real));
187                 */
188         }
189         init_forth_environment(!image_file);
190         if (!setjmp(warm_start_jump) && file_name) load_file(file_name);
191         _quit();
192         return 0;
193 }
194