1 #ifdef RCSID
2 static char RCSid[] =
3 "$Header: d:/cvsroot/tads/tads3/VMINIT.CPP,v 1.3 1999/07/11 00:46:58 MJRoberts Exp $";
4 #endif
5
6 /*
7 * Copyright (c) 1999, 2002 Michael J. Roberts. All Rights Reserved.
8 *
9 * Please see the accompanying license file, LICENSE.TXT, for information
10 * on using and copying this software.
11 */
12 /*
13 Name
14 vminit.cpp - initialize and terminate VM processing
15 Function
16 Provides functions to create and destroy global objects for a VM
17 session.
18 Notes
19
20 Modified
21 04/06/99 MJRoberts - Creation
22 */
23
24 #include <string.h>
25
26 #include "t3std.h"
27 #include "charmap.h"
28 #include "vminit.h"
29 #include "vmerr.h"
30 #include "vmfile.h"
31 #include "vmimage.h"
32 #include "vmpool.h"
33 #include "vmobj.h"
34 #include "vmstack.h"
35 #include "vmundo.h"
36 #include "vmmeta.h"
37 #include "vmbif.h"
38 #include "vmrun.h"
39 #include "vmpredef.h"
40 #include "vmmcreg.h"
41 #include "vmbiftad.h"
42 #include "resload.h"
43 #include "vmhost.h"
44 #include "vmconsol.h"
45 #include "vmbignum.h"
46 #include "vmsrcf.h"
47 #include "vmparam.h"
48 #include "vmmain.h"
49 #include "vmtobj.h"
50
51
52 /* ------------------------------------------------------------------------ */
53 /*
54 * Perform base initialization. This is an internal routine called only
55 * by higher-level initialization routines; we perform all of the
56 * generic, configuration-independent initialization.
57 */
vm_init_base(vm_globals ** vmg,class CVmHostIfc * hostifc,class CVmMainClientIfc * clientifc,const char * charset)58 void vm_init_base(vm_globals **vmg, class CVmHostIfc *hostifc,
59 class CVmMainClientIfc *clientifc,
60 const char *charset)
61 {
62 vm_globals *vmg__;
63 char disp_mapname[32];
64 char filename_mapname[32];
65 char filecont_mapname[32];
66 CResLoader *map_loader;
67 int file_map_err;
68 int disp_map_err;
69
70 /*
71 * Allocate globals according to build-time configuration, then
72 * assign the global pointer to a local named vmg__. This will
73 * ensure that the globals are accessible for all of the different
74 * build-time configurations.
75 */
76 vmg__ = *vmg = vmglob_alloc();
77
78 /* initialize the error stack */
79 err_init(VM_ERR_STACK_BYTES);
80
81 /* get the character map loader from the host interface */
82 map_loader = hostifc->get_cmap_res_loader();
83
84 /* if an external message set hasn't been loaded, try loading one */
85 if (!err_is_message_file_loaded() && map_loader != 0)
86 {
87 osfildef *fp;
88
89 /* try finding a message file */
90 fp = map_loader->open_res_file(VM_ERR_MSG_FNAME, 0,
91 VM_ERR_MSG_RESTYPE);
92 if (fp != 0)
93 {
94 /*
95 * try loading it - if that fails, we'll just be left with
96 * the built-in messages, so we won't have lost anything for
97 * trying
98 */
99 err_load_vm_message_file(fp);
100
101 /* we're done with the file */
102 osfcls(fp);
103 }
104 }
105
106 /* remember the host interface */
107 G_host_ifc = hostifc;
108
109 /* we don't have a resource loader for program resources yet */
110 G_res_loader = 0;
111
112 /* create the object table */
113 VM_IFELSE_ALLOC_PRE_GLOBAL(G_obj_table = new CVmObjTable(),
114 G_obj_table->init());
115
116 /*
117 * Create the memory manager. Empirically, our hybrid heap allocator
118 * is faster than the standard C++ run-time library's allocator on many
119 * platforms, so use it instead of hte basic 'malloc' allocator.
120 */
121 G_varheap = new CVmVarHeapHybrid();
122 // G_varheap = new CVmVarHeapMalloc(); to use the system 'malloc' instead
123 G_mem = new CVmMemory(vmg_ G_varheap);
124
125 /* create a stack */
126 VM_IFELSE_ALLOC_PRE_GLOBAL(
127 G_stk = new CVmStack(VM_STACK_SIZE, vm_init_stack_reserve()),
128 G_stk->init());
129
130 /* create the undo manager */
131 G_undo = new CVmUndo(VM_UNDO_MAX_RECORDS, VM_UNDO_MAX_SAVEPTS);
132
133 /* create the metafile and function set tables */
134 G_meta_table = new CVmMetaTable(5);
135 G_bif_table = new CVmBifTable(5);
136
137 /* initialize the metaclass registration tables */
138 vm_register_metaclasses();
139
140 /* initialize the TadsObject class */
141 CVmObjTads::class_init(vmg0_);
142
143 /* create the byte-code interpreter */
144 VM_IFELSE_ALLOC_PRE_GLOBAL(G_interpreter = new CVmRun(),
145 G_interpreter->init());
146
147 /* presume we won't create debugger information */
148 G_debugger = 0;
149 G_srcf_table = 0;
150
151 /* initialize the debugger if present */
152 vm_init_debugger(vmg0_);
153
154 /* create the source file table */
155 G_srcf_table = new CVmSrcfTable();
156
157 /* create the pre-defined object mapper */
158 VM_IFELSE_ALLOC_PRE_GLOBAL(G_predef = new CVmPredef, G_predef->reset());
159
160 /* presume we're in normal execution mode (not preinit) */
161 G_preinit_mode = FALSE;
162
163 /* allocate the TADS intrinsic function set's globals */
164 G_bif_tads_globals = new CVmBifTADSGlobals(vmg0_);
165
166 /* allocate the BigNumber register cache */
167 G_bignum_cache = new CVmBigNumCache(32);
168
169 /* no image loader yet */
170 G_image_loader = 0;
171
172 /*
173 * If the caller explicitly specified a character set, use it.
174 * Otherwise, ask the OS layer for the default character set we
175 * should use.
176 */
177 if (charset == 0)
178 {
179 /* the user did not specify a mapping - ask the OS for the default */
180 os_get_charmap(disp_mapname, OS_CHARMAP_DISPLAY);
181
182 /* use the name we got from the OS */
183 charset = disp_mapname;
184
185 /* there's no explicit global character set name setting to store */
186 G_disp_cset_name = 0;
187 }
188 else
189 {
190 /* save the global character set name */
191 G_disp_cset_name = lib_copy_str(charset);
192 }
193
194 /* create the display character maps */
195 G_cmap_from_ui = CCharmapToUni::load(map_loader, charset);
196 G_cmap_to_ui = CCharmapToLocal::load(map_loader, charset);
197
198 /* create the filename character maps */
199 os_get_charmap(filename_mapname, OS_CHARMAP_FILENAME);
200 G_cmap_from_fname = CCharmapToUni::load(map_loader, filename_mapname);
201 G_cmap_to_fname = CCharmapToLocal::load(map_loader, filename_mapname);
202
203 /* create the file-contents character maps */
204 os_get_charmap(filecont_mapname, OS_CHARMAP_FILECONTENTS);
205 G_cmap_from_file = CCharmapToUni::load(map_loader, filecont_mapname);
206 G_cmap_to_file = CCharmapToLocal::load(map_loader, filecont_mapname);
207
208 /* make a note of whether we had any problems loading the maps */
209 disp_map_err = (G_cmap_from_ui == 0 || G_cmap_to_ui == 0);
210 file_map_err = (G_cmap_from_fname == 0 || G_cmap_to_fname == 0);
211
212 /* if we failed to create any of the maps, load defaults */
213 if (G_cmap_from_ui == 0)
214 G_cmap_from_ui = CCharmapToUni::load(map_loader, "us-ascii");
215 if (G_cmap_to_ui == 0)
216 G_cmap_to_ui = CCharmapToLocal::load(map_loader, "us-ascii");
217 if (G_cmap_from_fname == 0)
218 G_cmap_from_fname = CCharmapToUni::load(map_loader, "us-ascii");
219 if (G_cmap_to_fname == 0)
220 G_cmap_to_fname = CCharmapToLocal::load(map_loader, "us-ascii");
221 if (G_cmap_from_file == 0)
222 G_cmap_from_file = CCharmapToUni::load(map_loader, "us-ascii");
223 if (G_cmap_to_file == 0)
224 G_cmap_to_file = CCharmapToLocal::load(map_loader, "us-ascii");
225
226 /* create the primary console */
227 G_console = clientifc->create_console(VMGLOB_ADDR);
228
229 /*
230 * if we had any trouble opening the display character mapping file,
231 * make a note that we are using a default mapping
232 */
233 if (disp_map_err)
234 {
235 const char *msg;
236 char buf[256];
237
238 /* get the message */
239 msg = err_get_msg(vm_messages, vm_message_count,
240 VMERR_NO_CHARMAP_FILE, TRUE);
241
242 /* format it */
243 sprintf(buf, msg, charset);
244
245 /* display it */
246 clientifc->display_error(VMGLOB_ADDR, buf, TRUE);
247 }
248 }
249
250 /* ------------------------------------------------------------------------ */
251 /*
252 * Terminate the VM
253 */
vm_terminate(vm_globals * vmg__,CVmMainClientIfc * clientifc)254 void vm_terminate(vm_globals *vmg__, CVmMainClientIfc *clientifc)
255 {
256 /* tell the debugger to shut down, if necessary */
257 vm_terminate_debug_shutdown(vmg0_);
258
259 /* drop all undo information */
260 G_undo->drop_undo(vmg0_);
261
262 /* delete the main console */
263 clientifc->delete_console(VMGLOB_ADDR, G_console);
264
265 /* release references on the character mappers */
266 G_cmap_from_fname->release_ref();
267 G_cmap_to_fname->release_ref();
268 G_cmap_from_ui->release_ref();
269 G_cmap_to_ui->release_ref();
270 G_cmap_from_file->release_ref();
271 G_cmap_to_file->release_ref();
272
273 /* delete the saved UI character set name, if any */
274 lib_free_str(G_disp_cset_name);
275
276 /* delete the BigNumber register cache */
277 delete G_bignum_cache;
278
279 /* delete the TADS intrinsic function set's globals */
280 delete G_bif_tads_globals;
281
282 /* delete the predefined object table */
283 VM_IF_ALLOC_PRE_GLOBAL(delete G_predef);
284
285 /* delete the interpreter */
286 VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_interpreter,
287 G_interpreter->terminate());
288
289 /* terminate the TadsObject class */
290 CVmObjTads::class_term(vmg0_);
291
292 /* delete the source file table */
293 delete G_srcf_table;
294
295 /* delete debugger objects */
296 vm_terminate_debug_delete(vmg0_);
297
298 /* delete the constant pools */
299 VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_code_pool,
300 G_code_pool->terminate());
301 VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_const_pool,
302 G_const_pool->terminate());
303
304 /* delete the dependency tables */
305 delete G_meta_table;
306 delete G_bif_table;
307
308 /* delete the undo manager */
309 delete G_undo;
310
311 /* delete the stack */
312 VM_IF_ALLOC_PRE_GLOBAL(delete G_stk);
313
314 /* delete the object table */
315 G_obj_table->delete_obj_table(vmg0_);
316 VM_IF_ALLOC_PRE_GLOBAL(delete G_obj_table);
317
318 /* delete the memory manager and heap manager */
319 delete G_mem;
320 delete G_varheap;
321
322 /* delete the error context */
323 err_terminate();
324
325 /* delete the globals */
326 vmglob_delete(vmg__);
327 }
328
329