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