cfad47cfa3/tads3/vmmain.h

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
/* $Header$ */
2
3
/* 
4
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
5
 *   
6
 *   Please see the accompanying license file, LICENSE.TXT, for information
7
 *   on using and copying this software.  
8
 */
9
/*
10
Name
11
  vmmain.h - main entrypoint to run a T3 image file
12
Function
13
  
14
Notes
15
  
16
Modified
17
  10/07/99 MJRoberts  - Creation
18
*/
19
20
#ifndef VMMAIN_H
21
#define VMMAIN_H
22
23
#include "vmglob.h"
24
25
/*
26
 *   Parse a command line to determine the name of the game file specified by
27
 *   the arguments.  If we can find a game file specification, we'll fill in
28
 *   'buf' with the filename and return true; if there's no file name
29
 *   specified, we'll return false.
30
 *   
31
 *   Note that our parsing will work for TADS 2 or TADS 3 interpreter command
32
 *   lines, so this routine can be used to extract the filename from an
33
 *   ambiguous command line in order to check the file for its type and
34
 *   thereby resolve which interpreter to use.
35
 *   
36
 *   Note that the filename might not come directly from the command
37
 *   arguments, since it might be implied.  If there's no game file directly
38
 *   specified, but there is an explicit "-r" option to restore a saved game,
39
 *   we'll pull the game filename out of the saved game file if possible.
40
 *   Saved game files in both TADS 2 and TADS 3 can store the original game
41
 *   file name that was being executed at the time the game was saved.  
42
 */
43
int vm_get_game_arg(int argc, const char *const *argv,
44
                    char *buf, size_t buflen);
45
46
/*
47
 *   Given a game file argument, determine which engine (TADS 2 or TADS 3)
48
 *   should be used to run the game.
49
 *   
50
 *   We'll first check to see if the given file exists.  If it does, we'll
51
 *   read header information from the file to try to identify the game.  If
52
 *   the file does not exist, we will proceed to check default suffixes, if
53
 *   the suffix arguments are non-null.
54
 *   
55
 *   If defexts is not null, it gives an array of default filename suffix
56
 *   strings, suitable for use with os_defext().  When the name as given
57
 *   doesn't refer to an existing file, we'll try looking for files with
58
 *   these suffixes, one at a time.
59
 *   
60
 *   Returns one of the VM_GGT_xxx codes.
61
 *   
62
 *   If the return value is 2 or 3, we'll fill in the actual_filename buffer
63
 *   with the full name of the file; if we added a default suffix, the
64
 *   suffix will be included in this result.  
65
 */
66
int vm_get_game_type(const char *filename,
67
                     char *actual_filename,
68
                     size_t actual_filename_buffer_length,
69
                     const char *const *defexts, size_t defext_count);
70
71
/*
72
 *   Returns codes for vm_get_game_type() 
73
 */
74
75
/* game type is TADS 2 */
76
#define VM_GGT_TADS2          2
77
78
/* game type is TADS 3 */
79
#define VM_GGT_TADS3          3
80
81
/* game file not found (even after trying default extensions) */
82
#define VM_GGT_NOT_FOUND    (-1)
83
84
/* game file exists but isn't a valid tads 2 or tads 3 game */
85
#define VM_GGT_INVALID      (-2)
86
87
/* 
88
 *   ambiguous filename - the exact filename doesn't exist, and more than
89
 *   one default suffix version exists 
90
 */
91
#define VM_GGT_AMBIG        (-3)
92
93
/* 
94
 *   determine if a VM_GGT_xxx code refers to a valid engine version:
95
 *   returns true if the code is an engine version, false if the code is an
96
 *   error indication 
97
 */
98
#define vm_ggt_is_valid(code) ((code) > 0)
99
100
101
/*
102
 *   Execute an image file.  We'll return zero on success, or a VM error code
103
 *   on failure.  If an error occurs, we'll fill in 'errbuf' with the text of
104
 *   a message describing the problem.
105
 *   
106
 *   If 'load_from_exe' is true, the image filename given is actually the
107
 *   name of the native executable file that we're running, and we should
108
 *   load the image file that's attached to the native executable file via
109
 *   the system-specific os_exeseek() mechanism.
110
 *   
111
 *   If 'script_file' is not null, we'll read console input from the given
112
 *   file.  If 'log_file' is not null, we'll log console output to the given
113
 *   file.  If 'cmd_log_file' is not null, we'll log each line we read from
114
 *   the console to the given command logging file.  
115
 *   
116
 *   'charset' optionally selects a character set to use for text displayed
117
 *   to or read from the user interface.  If this is null, we'll use the
118
 *   current system character set as indicated by the osifc layer.  'charset'
119
 *   should usually be null unless explicitly specified by the user.  
120
 */
121
int vm_run_image(class CVmMainClientIfc *clientifc,
122
                 const char *image_file_name,
123
                 class CVmHostIfc *hostifc,
124
                 const char *const *prog_argv, int prog_argc,
125
                 const char *script_file, int script_quiet,
126
                 const char *log_file, const char *cmd_log_file,
127
                 int load_from_exe, int show_banner,
128
                 const char *charset, const char *log_charset,
129
                 const char *saved_state, const char *res_dir);
130
131
/*
132
 *   Execute an image file using argc/argv conventions.  We'll parse the
133
 *   command line and invoke the program.
134
 *   
135
 *   The 'executable_name' is the name of the host program; this is used to
136
 *   prepare "usage" messages.
137
 *   
138
 *   If 'defext' is true, we'll try adding a default extension ("t3",
139
 *   formerly "t3x") to the name of the image file we find if the given
140
 *   filename doesn't exist.  We'll always check to see if the file exists
141
 *   with the exact given name before we do this, so that we don't add an
142
 *   extension where none is needed.  If the caller doesn't want us to try
143
 *   adding an extension at all, pass in 'defext' as false.
144
 *   
145
 *   If 'test_mode' is true, we'll make some small changes to the program
146
 *   invocation protocol appropriate to running system tests.  In
147
 *   particular, we'll build the program argument list with only the root
148
 *   name of the image file, not the full path - this allows the program to
149
 *   display the argument list without any dependencies on local path name
150
 *   conventions or the local directory structure, allowing for more easily
151
 *   portable test scripts.
152
 *   
153
 *   If 'hostifc' is null, we'll provide our own default interface.  The
154
 *   caller can provide a custom host interface by passing in a non-null
155
 *   'hostifc' value.  
156
 */
157
int vm_run_image_main(class CVmMainClientIfc *clientifc,
158
                      const char *executable_name,
159
                      int argc, char **argv, int defext, int test_mode,
160
                      class CVmHostIfc *hostifc);
161
162
/*
163
 *   VM Main client services interface.  Callers of the vm_run_image
164
 *   functions must provide an implementation of this interface. 
165
 */
166
class CVmMainClientIfc
167
{
168
public:
169
    /* 
170
     *   Set "plain" mode.  This should set the console to plain ASCII output
171
     *   mode, if appropriate.  Note that this can be called before
172
     *   client_init(), and no globals are generally present at this point.
173
     *   
174
     *   In most cases, this can make a call to os_plain() to set the
175
     *   OS-level console to plain mode.  Non-console applications generally
176
     *   need not do anything here at all.  
177
     */
178
    virtual void set_plain_mode() = 0;
179
180
    /*
181
     *   Create the main system console, if desired.  This is called during
182
     *   VM initialization, so it is called prior to client_init().  Returns
183
     *   the main console object, if desired.  If no main console is desired
184
     *   for this application, return null.  
185
     */
186
    virtual class CVmConsoleMain *create_console(
187
        struct vm_globals *globals) = 0;
188
189
    /*
190
     *   Delete the console, if we created one.  This is called during VM
191
     *   termination, so it's called after client_terminate().  If
192
     *   create_console() doesn't create a console, this routine need do
193
     *   nothing.  
194
     */
195
    virtual void delete_console(struct vm_globals *globals,
196
                                class CVmConsoleMain *console) = 0;
197
198
    /* 
199
     *   Initialization - we'll invoke this immediately after initializing
200
     *   the VM (via vm_initialize), so the client can perform any global
201
     *   initialization desired.  The globals are valid at this point because
202
     *   we have completed VM initialization.
203
     *   
204
     *   If script_file is non-null, it gives the name of a file to use as
205
     *   the source of console input.  The client implementation should set
206
     *   up accordingly; if the standard console (G_console) is being used,
207
     *   the client can simply use G_console->open_script_file() to set up
208
     *   scripting.
209
     *   
210
     *   If log_file is non-null, it gives the name of a file to use to log
211
     *   console output.  The client shoudl set up logging; if the standard
212
     *   console if being used, G_console->open_log_file() will do the trick.
213
     *   
214
     *   If cmd_log_file is non-null, it gives the name of a file to use to
215
     *   log commands read from the input (i.e., only command input should be
216
     *   logged, not other console output).  If the standard console is being
217
     *   used, G_console->open_command_log() will set things up properly.
218
     *   
219
     *   If banner_str is non-null, it gives a VM banner string that should
220
     *   be displayed to the user.  If the standard console is being used,
221
     *   this can be displayed using G_console->format_text().
222
     *   
223
     *   The parameters (script_file, log_file, cmd_log_file, and the
224
     *   presence or absence of banner_str) are taken from the startup
225
     *   parameters.  For a command-line version, for example, these come
226
     *   from command line options.  So, these are necessarily passed down in
227
     *   some form from the client to begin with; so a client that never
228
     *   passes these to vm_run_image() or vm_run_image_main() doesn't need
229
     *   to handle these parameters at all here.  
230
     */
231
    virtual void client_init(struct vm_globals *globals,
232
                             const char *script_file, int script_quiet,
233
                             const char *log_file,
234
                             const char *cmd_log_file,
235
                             const char *banner_str) = 0;
236
237
    /*
238
     *   Termination - we'll invoke this immediately before terminating the
239
     *   VM (via vm_terminate).  Globals are still valid at this point, but
240
     *   will be destroyed after this returns. 
241
     */
242
    virtual void client_terminate(struct vm_globals *globals) = 0;
243
    
244
    /* 
245
     *   pre-execution notification - we'll invoke this function just before
246
     *   starting execution in the loaded image 
247
     */
248
    virtual void pre_exec(struct vm_globals *globals) = 0;
249
250
    /* 
251
     *   terminate - we'll invoke this just after execution in the loaded
252
     *   image terminates 
253
     */
254
    virtual void post_exec(struct vm_globals *globals) = 0;
255
256
    /* 
257
     *   Terminate with error - we'll invoke this upon catching an
258
     *   exception that the image file doesn't handle and which thus
259
     *   terminates execution.  Note that if this is called, post_exec()
260
     *   will not be called; however, if post_exec() itself throws an
261
     *   exception, we'll invoke this routine.  
262
     */
263
    virtual void post_exec_err(struct vm_globals *globals) = 0;
264
265
    /* 
266
     *   Display an error message.  We'll call this with a complete error
267
     *   message to display.  Note that we won't add a newline at the end of
268
     *   the message, so if the message is to be displayed on a stdio-style
269
     *   terminal, this routine should display a newline after the message.
270
     *   
271
     *   If the implementation normally writes the text to the main output
272
     *   console (G_console), it must take into the account the possibility
273
     *   that we have not opened a system console at all (i.e., G_console
274
     *   could be null), or have not allocated any globals at all (i.e.,
275
     *   'globals' could be null).
276
     *   
277
     *   If 'add_blank_line' is true, the implementation should add a blank
278
     *   line after the error, if appropriate for the display device.  If
279
     *   we're displaying the message in an alert box on a GUI, for example,
280
     *   this can be ignored.  
281
     */
282
    virtual void display_error(struct vm_globals *globals,
283
                               const char *msg, int add_blank_line) = 0;
284
};
285
286
#endif /* VMMAIN_H */
287