1 #ifdef RCSID
2 static char RCSid[] =
3 "$Header$";
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 vmcl23.cpp - command line entrypoint for combined TADS 2/3 interpreter
15 Function
16 This is a command-line entrypoint wrapper for executing a compiled
17 TADS 2 or TADS 3 program. This can be used on command-line OS's (DOS,
18 Unix, etc) where a graphical user interface is not needed.
19
20 If a graphical user interface to execute a VM program is required,
21 this module should not be used. Instead, an OS-specific version must be
22 written; the OS version obtain the name of the program to run (via a file
23 selector or by communication with the graphical shell, for example), then
24 must initialize the VM, invoke vm_run_image(), then terminate the VM. The
25 OS version must, in other words, do pretty much everything this version
26 does, but should use its own OS-specific means to obtain the name of the
27 image file to run rather than reading it from argc/argv.
28 Notes
29
30 Modified
31 10/07/99 MJRoberts - Creation
32 */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36
37 #include "os.h"
38
39 /* tads 2 headers */
40 #include "trd.h"
41
42 /* tads 3 headers */
43 #include "t3std.h"
44 #include "vmmain.h"
45 #include "vmvsn.h"
46 #include "vmmaincn.h"
47 #include "vmhostsi.h"
48
49
50 /* ------------------------------------------------------------------------ */
51 /*
52 * Check for a "-plain" option; if it's there, set the terminal to plain
53 * text mode. We must make this check before doing anything else, because
54 * os_plain() must be called prior to os_init() if it's going to be called
55 * at all.
56 */
check_plain_option(int argc,char ** argv)57 static void check_plain_option(int argc, char **argv)
58 {
59 int i;
60
61 /* scan the argument list for the "-plain" option */
62 for (i = 1 ; i < argc ; ++i)
63 {
64 if (strcmp(argv[i], "-plain") == 0)
65 {
66 /* set plain text mode in the OS layer */
67 os_plain();
68
69 /* we've found what we're looking for - no need to look further */
70 break;
71 }
72 }
73 }
74
75
76 /* ------------------------------------------------------------------------ */
77 /*
78 * Invoke the tads 2 main entrypoint with the given command-line arguments
79 */
main_t2(int argc,char ** argv)80 static int main_t2(int argc, char **argv)
81 {
82 int stat;
83
84 /* check for a "-plain" option */
85 check_plain_option(argc, argv);
86
87 /* initialize the OS layer */
88 os_init(&argc, argv, 0, 0, 0);
89
90 /* install the break handler */
91 os_instbrk(1);
92
93 /* invoke the tads 2 main entrypoint */
94 stat = os0main2(argc, argv, trdmain, "", 0, 0);
95
96 /* done with the break handler */
97 os_instbrk(0);
98
99 /* uninitialize the OS layer */
100 os_uninit();
101
102 /* return the status */
103 return stat;
104 }
105
106 /* ------------------------------------------------------------------------ */
107 /*
108 * Invoke the T3 VM with the given command-line arguments
109 */
main_t3(int argc,char ** argv)110 static int main_t3(int argc, char **argv)
111 {
112 CVmMainClientConsole clientifc;
113 int stat;
114 CVmHostIfc *hostifc = new CVmHostIfcStdio(argv[0]);
115
116 /* check for a "-plain" option */
117 check_plain_option(argc, argv);
118
119 /*
120 * Initialize the OS layer. Since this is a command-line-only
121 * implementation, there's no need to ask the OS layer to try to get
122 * us a filename to run, so pass in null for the prompt and filename
123 * buffer.
124 */
125 os_init(&argc, argv, 0, 0, 0);
126
127 /* invoke the basic entrypoint */
128 stat = vm_run_image_main(&clientifc, "t3run", argc, argv,
129 TRUE, FALSE, hostifc);
130
131 /* uninitialize the OS layer */
132 os_uninit();
133
134 /* done with the host interface */
135 delete hostifc;
136
137 /* show any unfreed memory */
138 t3_list_memory_blocks(0);
139
140 /* exit with status code */
141 os_term(stat);
142
143 /* we shouldn't get here, but in case os_term doesn't really exit... */
144 return stat;
145 }
146
147 /* ------------------------------------------------------------------------ */
148 /*
149 * Main entrypoint
150 */
main(int argc,char ** argv)151 int main(int argc, char **argv)
152 {
153 int stat;
154 static const char *defexts[] = { "gam", "t3" };
155 char prog_arg[OSFNMAX];
156 char fname[OSFNMAX];
157 int engine_ver;
158
159 /*
160 * if one of our special usage message arguments was given, show the
161 * usage
162 */
163 if (argc == 2 && stricmp(argv[1], "-help2") == 0)
164 {
165 /* invoke the tads 2 main entrypoint with no arguments */
166 main_t2(1, argv);
167
168 /* that's all we need to do with this option */
169 os_term(OSEXSUCC);
170 }
171 else if (argc == 2 && stricmp(argv[1], "-help3") == 0)
172 {
173 /* invoke the tads 3 main entrypoint with no arguments */
174 main_t3(1, argv);
175
176 /* that's all we need to do with this option */
177 os_term(OSEXSUCC);
178 }
179
180 /* look at the arguments and try to find the program name */
181 if (!vm_get_game_arg(argc, argv, prog_arg, sizeof(prog_arg)))
182 {
183 /*
184 * there's no game file name specified or implied - show the
185 * generic combined v2/v3 usage message
186 */
187 /* copyright-date-string */
188 printf("TADS Interpreter - "
189 "Copyright (c) 1993, 2004 Michael J. Roberts\n"
190 "TADS 2 VM version " TADS_RUNTIME_VERSION " / "
191 "T3 VM version " T3VM_VSN_STRING "\n\n");
192
193 printf("Error: you didn't specify a game file name on the command "
194 "line, or the command\n"
195 "options are incorrect. You must specify the name of "
196 "the game file you would\n"
197 "like to run.\n"
198 "\n"
199 "If you'd like a list of command-line options for TADS 2 "
200 "games, specify -help2\n"
201 "instead of giving a game file name. Or, if you'd like a "
202 "list of command-line\n"
203 "options for TADS 3, specify -help3.\n");
204
205 /* pause (if desired by OS layer) and exit */
206 os_expause();
207 os_term(OSEXFAIL);
208 }
209
210 /* determine the type of the game we have */
211 engine_ver = vm_get_game_type(prog_arg, fname, sizeof(fname),
212 defexts,
213 sizeof(defexts)/sizeof(defexts[0]));
214
215 /* presume failure */
216 stat = OSEXFAIL;
217
218 /* see what we have */
219 switch(engine_ver)
220 {
221 case VM_GGT_TADS2:
222 /* run the game using the TADS 2 engine */
223 stat = main_t2(argc, argv);
224 break;
225
226 case VM_GGT_TADS3:
227 /* run the game using the TADS 3 engine */
228 stat = main_t3(argc, argv);
229 break;
230
231 case VM_GGT_INVALID:
232 /* invalid file type */
233 printf("The file you have selected (%s) is not a valid game file.\n",
234 fname);
235 break;
236
237 case VM_GGT_NOT_FOUND:
238 /* file not found */
239 printf("The game file (%s) cannot be found.\n", prog_arg);
240 break;
241
242 case VM_GGT_AMBIG:
243 /* ambiguous file */
244 printf("The game file (%s) cannot be found exactly as given, "
245 "but multiple game\n"
246 "files with this name and different default suffixes "
247 "(.gam, .t3) exist.\n"
248 "Please specify the full name of the file, including the "
249 "suffix, that you\n"
250 "wish to use.\n",
251 prog_arg);
252 break;
253 }
254
255 /* pause (if desired by OS layer) and terminate with our status code */
256 os_expause();
257 os_term(stat);
258 return stat;
259 }
260
261