cfad47cfa3/tads3/vminit.cpp

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
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
 */
58
void vm_init_base(vm_globals **vmg, const vm_init_options *opts)
59
{
60
    vm_globals *vmg__;
61
    char disp_mapname[32];
62
    char filename_mapname[32];
63
    char filecont_mapname[32];
64
    CResLoader *map_loader;
65
    int disp_map_err;
66
    const char *charset = opts->charset;
67
    
68
    /* 
69
     *   Allocate globals according to build-time configuration, then
70
     *   assign the global pointer to a local named vmg__.  This will
71
     *   ensure that the globals are accessible for all of the different
72
     *   build-time configurations.  
73
     */
74
    vmg__ = *vmg = vmglob_alloc();
75
76
    /* initialize the error stack */
77
    err_init(VM_ERR_STACK_BYTES);
78
79
    /* get the character map loader from the host interface */
80
    map_loader = opts->hostifc->get_cmap_res_loader();
81
82
    /* if an external message set hasn't been loaded, try loading one */
83
    if (!err_is_message_file_loaded() && map_loader != 0)
84
    {
85
        osfildef *fp;
86
        
87
        /* try finding a message file */
88
        fp = map_loader->open_res_file(VM_ERR_MSG_FNAME, 0,
89
                                       VM_ERR_MSG_RESTYPE);
90
        if (fp != 0)
91
        {
92
            /* 
93
             *   try loading it - if that fails, we'll just be left with
94
             *   the built-in messages, so we won't have lost anything for
95
             *   trying 
96
             */
97
            err_load_vm_message_file(fp);
98
            
99
            /* we're done with the file */
100
            osfcls(fp);
101
        }
102
    }
103
104
    /* remember the host interface */
105
    G_host_ifc = opts->hostifc;
106
107
    /* we don't have a resource loader for program resources yet */
108
    G_res_loader = 0;
109
110
    /* create the object table */
111
    VM_IFELSE_ALLOC_PRE_GLOBAL(G_obj_table = new CVmObjTable(),
112
                               G_obj_table->init());
113
114
    /* 
115
     *   Create the memory manager.  Empirically, our hybrid heap allocator
116
     *   is faster than the standard C++ run-time library's allocator on many
117
     *   platforms, so use it instead of hte basic 'malloc' allocator. 
118
     */
119
    G_varheap = new CVmVarHeapHybrid();
120
    // G_varheap = new CVmVarHeapMalloc(); to use the system 'malloc' instead
121
    G_mem = new CVmMemory(vmg_ G_varheap);
122
123
    /* create a stack */
124
    VM_IFELSE_ALLOC_PRE_GLOBAL(
125
        G_stk = new CVmStack(VM_STACK_SIZE, vm_init_stack_reserve()),
126
        G_stk->init());
127
128
    /* create the undo manager */
129
    G_undo = new CVmUndo(VM_UNDO_MAX_RECORDS, VM_UNDO_MAX_SAVEPTS);
130
131
    /* create the metafile and function set tables */
132
    G_meta_table = new CVmMetaTable(5);
133
    G_bif_table = new CVmBifTable(5);
134
135
    /* initialize the metaclass registration tables */
136
    vm_register_metaclasses();
137
138
    /* initialize the TadsObject class */
139
    CVmObjTads::class_init(vmg0_);
140
141
    /* create the byte-code interpreter */
142
    VM_IFELSE_ALLOC_PRE_GLOBAL(G_interpreter = new CVmRun(),
143
                               G_interpreter->init());
144
145
    /* presume we won't create debugger information */
146
    G_debugger = 0;
147
    G_srcf_table = 0;
148
149
    /* initialize the debugger if present */
150
    vm_init_debugger(vmg0_);
151
152
    /* create the source file table */
153
    G_srcf_table = new CVmSrcfTable();
154
155
    /* create the pre-defined object mapper */
156
    VM_IFELSE_ALLOC_PRE_GLOBAL(G_predef = new CVmPredef, G_predef->reset());
157
158
    /* presume we're in normal execution mode (not preinit) */
159
    G_preinit_mode = FALSE;
160
161
    /* allocate the TADS intrinsic function set's globals */
162
    G_bif_tads_globals = new CVmBifTADSGlobals(vmg0_);
163
164
    /* allocate the BigNumber register cache */
165
    G_bignum_cache = new CVmBigNumCache(32);
166
167
    /* no image loader yet */
168
    G_image_loader = 0;
169
170
    /*
171
     *   If the caller explicitly specified a character set, use it.
172
     *   Otherwise, ask the OS layer for the default character set we
173
     *   should use. 
174
     */
175
    if (charset == 0)
176
    {
177
        /* the user did not specify a mapping - ask the OS for the default */
178
        os_get_charmap(disp_mapname, OS_CHARMAP_DISPLAY);
179
180
        /* use the name we got from the OS */
181
        charset = disp_mapname;
182
183
        /* there's no explicit global character set name setting to store */
184
        G_disp_cset_name = 0;
185
    }
186
    else
187
    {
188
        /* save the global character set name */
189
        G_disp_cset_name = lib_copy_str(charset);
190
    }
191
192
    /* create the display character maps */
193
    G_cmap_from_ui = CCharmapToUni::load(map_loader, charset);
194
    G_cmap_to_ui = CCharmapToLocal::load(map_loader, charset);
195
196
    /* create the filename character maps */
197
    os_get_charmap(filename_mapname, OS_CHARMAP_FILENAME);
198
    G_cmap_from_fname = CCharmapToUni::load(map_loader, filename_mapname);
199
    G_cmap_to_fname = CCharmapToLocal::load(map_loader, filename_mapname);
200
201
    /* create the file-contents character maps */
202
    os_get_charmap(filecont_mapname, OS_CHARMAP_FILECONTENTS);
203
    G_cmap_from_file = CCharmapToUni::load(map_loader, filecont_mapname);
204
    G_cmap_to_file = CCharmapToLocal::load(map_loader, filecont_mapname);
205
206
    /* 
207
     *   If the caller specified a separate log-file character set, create
208
     *   the mapping.  Otherwise, just use the to-file mapper for log files.
209
     */
210
    if (opts->log_charset != 0)
211
    {
212
        /* load the specified log file output mapping */
213
        G_cmap_to_log = CCharmapToLocal::load(map_loader, opts->log_charset);
214
    }
215
    else
216
    {
217
        /* no log file mapping is specified, so use the generic file map */
218
        if ((G_cmap_to_log = G_cmap_to_file) != 0)
219
            G_cmap_to_log->add_ref();
220
    }
221
222
    /* make a note of whether we had any problems loading the maps */
223
    disp_map_err = (G_cmap_from_ui == 0 || G_cmap_to_ui == 0);
224
225
    /* if we failed to create any of the maps, load defaults */
226
    if (G_cmap_from_ui == 0)
227
        G_cmap_from_ui = CCharmapToUni::load(map_loader, "us-ascii");
228
    if (G_cmap_to_ui == 0)
229
        G_cmap_to_ui = CCharmapToLocal::load(map_loader, "us-ascii");
230
    if (G_cmap_from_fname == 0)
231
        G_cmap_from_fname = CCharmapToUni::load(map_loader, "us-ascii");
232
    if (G_cmap_to_fname == 0)
233
        G_cmap_to_fname = CCharmapToLocal::load(map_loader, "us-ascii");
234
    if (G_cmap_from_file == 0)
235
        G_cmap_from_file = CCharmapToUni::load(map_loader, "us-ascii");
236
    if (G_cmap_to_file == 0)
237
        G_cmap_to_file = CCharmapToLocal::load(map_loader, "us-ascii");
238
    if (G_cmap_to_log == 0)
239
        G_cmap_to_log = CCharmapToLocal::load(map_loader, "us-ascii");
240
241
    /* create the primary console */
242
    G_console = opts->clientifc->create_console(VMGLOB_ADDR);
243
244
    /* 
245
     *   if we had any trouble opening the display character mapping file,
246
     *   make a note that we are using a default mapping 
247
     */
248
    if (disp_map_err)
249
    {
250
        const char *msg;
251
        char buf[256];
252
253
        /* get the message */
254
        msg = err_get_msg(vm_messages, vm_message_count,
255
                          VMERR_NO_CHARMAP_FILE, TRUE);
256
257
        /* format it */
258
        sprintf(buf, msg, charset);
259
260
        /* display it */
261
        opts->clientifc->display_error(VMGLOB_ADDR, buf, TRUE);
262
    }
263
}
264
265
/* ------------------------------------------------------------------------ */
266
/*
267
 *   Terminate the VM 
268
 */
269
void vm_terminate(vm_globals *vmg__, CVmMainClientIfc *clientifc)
270
{
271
    /* tell the debugger to shut down, if necessary */
272
    vm_terminate_debug_shutdown(vmg0_);
273
    
274
    /* drop all undo information */
275
    G_undo->drop_undo(vmg0_);
276
277
    /* delete the main console */
278
    clientifc->delete_console(VMGLOB_ADDR, G_console);
279
280
    /* release references on the character mappers */
281
    G_cmap_from_fname->release_ref();
282
    G_cmap_to_fname->release_ref();
283
    G_cmap_from_ui->release_ref();
284
    G_cmap_to_ui->release_ref();
285
    G_cmap_from_file->release_ref();
286
    G_cmap_to_file->release_ref();
287
    G_cmap_to_log->release_ref();
288
289
    /* delete the saved UI character set name, if any */
290
    lib_free_str(G_disp_cset_name);
291
292
    /* delete the BigNumber register cache */
293
    delete G_bignum_cache;
294
295
    /* delete the TADS intrinsic function set's globals */
296
    delete G_bif_tads_globals;
297
298
    /* delete the predefined object table */
299
    VM_IF_ALLOC_PRE_GLOBAL(delete G_predef);
300
301
    /* delete the interpreter */
302
    VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_interpreter,
303
                               G_interpreter->terminate());
304
305
    /* terminate the TadsObject class */
306
    CVmObjTads::class_term(vmg0_);
307
308
    /* delete the source file table */
309
    delete G_srcf_table;
310
311
    /* delete debugger objects */
312
    vm_terminate_debug_delete(vmg0_);
313
314
    /* delete the constant pools */
315
    VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_code_pool,
316
                               G_code_pool->terminate());
317
    VM_IFELSE_ALLOC_PRE_GLOBAL(delete G_const_pool,
318
                               G_const_pool->terminate());
319
320
    /* delete the dependency tables */
321
    delete G_meta_table;
322
    delete G_bif_table;
323
324
    /* delete the undo manager */
325
    delete G_undo;
326
327
    /* delete the stack */
328
    VM_IF_ALLOC_PRE_GLOBAL(delete G_stk);
329
330
    /* delete the object table */
331
    G_obj_table->delete_obj_table(vmg0_);
332
    VM_IF_ALLOC_PRE_GLOBAL(delete G_obj_table);
333
334
    /* delete the memory manager and heap manager */
335
    delete G_mem;
336
    delete G_varheap;
337
338
    /* delete the error context */
339
    err_terminate();
340
341
    /* delete the globals */
342
    vmglob_delete(vmg__);
343
}
344