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