1 /*
2 * tclAppInit.c --
3 *
4 * Provides a default version of the main program and Tcl_AppInit
5 * function for Tcl applications (without Tk). Note that this program
6 * must be built in Win32 console mode to work properly.
7 *
8 * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
9 * Copyright (c) 1998-1999 by Scriptics Corporation.
10 *
11 * See the file "license.terms" for information on usage and redistribution of
12 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 */
14
15 #include "tcl.h"
16 #include <windows.h>
17 #include <locale.h>
18
19 #ifdef TCL_TEST
20 extern Tcl_PackageInitProc Procbodytest_Init;
21 extern Tcl_PackageInitProc Procbodytest_SafeInit;
22 extern Tcl_PackageInitProc Tcltest_Init;
23 extern Tcl_PackageInitProc TclObjTest_Init;
24 #endif /* TCL_TEST */
25
26 #if defined(__GNUC__)
27 int _CRT_glob = 0;
28 static void setargv(int *argcPtr, char ***argvPtr);
29 #endif /* __GNUC__ */
30
31 /*
32 *----------------------------------------------------------------------
33 *
34 * main --
35 *
36 * This is the main program for the application.
37 *
38 * Results:
39 * None: Tcl_Main never returns here, so this function never returns
40 * either.
41 *
42 * Side effects:
43 * Whatever the application does.
44 *
45 *----------------------------------------------------------------------
46 */
47
48 int
main(int argc,char * argv[])49 main(
50 int argc,
51 char *argv[])
52 {
53 /*
54 * The following #if block allows you to change the AppInit function by
55 * using a #define of TCL_LOCAL_APPINIT instead of rewriting this entire
56 * file. The #if checks for that #define and uses Tcl_AppInit if it
57 * doesn't exist.
58 */
59
60 #ifndef TCL_LOCAL_APPINIT
61 #define TCL_LOCAL_APPINIT Tcl_AppInit
62 #endif
63 extern int TCL_LOCAL_APPINIT (Tcl_Interp *interp);
64
65 /*
66 * The following #if block allows you to change how Tcl finds the startup
67 * script, prime the library or encoding paths, fiddle with the argv,
68 * etc., without needing to rewrite Tcl_Main()
69 */
70
71 #ifdef TCL_LOCAL_MAIN_HOOK
72 extern int TCL_LOCAL_MAIN_HOOK (int *argc, char ***argv);
73 #endif
74
75 char *p;
76
77 /*
78 * Set up the default locale to be standard "C" locale so parsing is
79 * performed correctly.
80 */
81
82 #if defined(__GNUC__)
83 setargv( &argc, &argv );
84 #endif
85 setlocale(LC_ALL, "C");
86
87 /*
88 * Forward slashes substituted for backslashes.
89 */
90
91 for (p = argv[0]; *p != '\0'; p++) {
92 if (*p == '\\') {
93 *p = '/';
94 }
95 }
96
97 #ifdef TCL_LOCAL_MAIN_HOOK
98 TCL_LOCAL_MAIN_HOOK(&argc, &argv);
99 #endif
100
101 Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
102
103 return 0; /* Needed only to prevent compiler warning. */
104 }
105
106 /*
107 *----------------------------------------------------------------------
108 *
109 * Tcl_AppInit --
110 *
111 * This function performs application-specific initialization. Most
112 * applications, especially those that incorporate additional packages,
113 * will have their own version of this function.
114 *
115 * Results:
116 * Returns a standard Tcl completion code, and leaves an error message in
117 * the interp's result if an error occurs.
118 *
119 * Side effects:
120 * Depends on the startup script.
121 *
122 *----------------------------------------------------------------------
123 */
124
125 int
Tcl_AppInit(Tcl_Interp * interp)126 Tcl_AppInit(
127 Tcl_Interp *interp) /* Interpreter for application. */
128 {
129 if (Tcl_Init(interp) == TCL_ERROR) {
130 return TCL_ERROR;
131 }
132
133 #ifdef TCL_TEST
134 if (Tcltest_Init(interp) == TCL_ERROR) {
135 return TCL_ERROR;
136 }
137 Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, NULL);
138 if (TclObjTest_Init(interp) == TCL_ERROR) {
139 return TCL_ERROR;
140 }
141 if (Procbodytest_Init(interp) == TCL_ERROR) {
142 return TCL_ERROR;
143 }
144 Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init,
145 Procbodytest_SafeInit);
146 #endif /* TCL_TEST */
147
148 #if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES
149 {
150 extern Tcl_PackageInitProc Registry_Init;
151 extern Tcl_PackageInitProc Dde_Init;
152 extern Tcl_PackageInitProc Dde_SafeInit;
153
154 if (Registry_Init(interp) == TCL_ERROR) {
155 return TCL_ERROR;
156 }
157 Tcl_StaticPackage(interp, "registry", Registry_Init, NULL);
158
159 if (Dde_Init(interp) == TCL_ERROR) {
160 return TCL_ERROR;
161 }
162 Tcl_StaticPackage(interp, "dde", Dde_Init, Dde_SafeInit);
163 }
164 #endif
165
166 /*
167 * Call the init functions for included packages. Each call should look
168 * like this:
169 *
170 * if (Mod_Init(interp) == TCL_ERROR) {
171 * return TCL_ERROR;
172 * }
173 *
174 * where "Mod" is the name of the module.
175 */
176
177 /*
178 * Call Tcl_CreateCommand for application-specific commands, if they
179 * weren't already created by the init functions called above.
180 */
181
182 /*
183 * Specify a user-specific startup file to invoke if the application is
184 * run interactively. Typically the startup file is "~/.apprc" where "app"
185 * is the name of the application. If this line is deleted then no
186 * user-specific startup file will be run under any conditions.
187 */
188
189 Tcl_SetVar(interp, "tcl_rcFileName", "~/tclshrc.tcl", TCL_GLOBAL_ONLY);
190 return TCL_OK;
191 }
192
193 /*
194 *-------------------------------------------------------------------------
195 *
196 * setargv --
197 *
198 * Parse the Windows command line string into argc/argv. Done here
199 * because we don't trust the builtin argument parser in crt0. Windows
200 * applications are responsible for breaking their command line into
201 * arguments.
202 *
203 * 2N backslashes + quote -> N backslashes + begin quoted string
204 * 2N + 1 backslashes + quote -> literal
205 * N backslashes + non-quote -> literal
206 * quote + quote in a quoted string -> single quote
207 * quote + quote not in quoted string -> empty string
208 * quote -> begin quoted string
209 *
210 * Results:
211 * Fills argcPtr with the number of arguments and argvPtr with the array
212 * of arguments.
213 *
214 * Side effects:
215 * Memory allocated.
216 *
217 *--------------------------------------------------------------------------
218 */
219
220 #if defined(__GNUC__)
221 static void
setargv(int * argcPtr,char *** argvPtr)222 setargv(
223 int *argcPtr, /* Filled with number of argument strings. */
224 char ***argvPtr) /* Filled with argument strings (malloc'd). */
225 {
226 char *cmdLine, *p, *arg, *argSpace;
227 char **argv;
228 int argc, size, inquote, copy, slashes;
229
230 cmdLine = GetCommandLine(); /* INTL: BUG */
231
232 /*
233 * Precompute an overly pessimistic guess at the number of arguments in
234 * the command line by counting non-space spans.
235 */
236
237 size = 2;
238 for (p = cmdLine; *p != '\0'; p++) {
239 if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
240 size++;
241 while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
242 p++;
243 }
244 if (*p == '\0') {
245 break;
246 }
247 }
248 }
249 argSpace = (char *) ckalloc(
250 (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1));
251 argv = (char **) argSpace;
252 argSpace += size * sizeof(char *);
253 size--;
254
255 p = cmdLine;
256 for (argc = 0; argc < size; argc++) {
257 argv[argc] = arg = argSpace;
258 while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
259 p++;
260 }
261 if (*p == '\0') {
262 break;
263 }
264
265 inquote = 0;
266 slashes = 0;
267 while (1) {
268 copy = 1;
269 while (*p == '\\') {
270 slashes++;
271 p++;
272 }
273 if (*p == '"') {
274 if ((slashes & 1) == 0) {
275 copy = 0;
276 if ((inquote) && (p[1] == '"')) {
277 p++;
278 copy = 1;
279 } else {
280 inquote = !inquote;
281 }
282 }
283 slashes >>= 1;
284 }
285
286 while (slashes) {
287 *arg = '\\';
288 arg++;
289 slashes--;
290 }
291
292 if ((*p == '\0') || (!inquote &&
293 ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */
294 break;
295 }
296 if (copy != 0) {
297 *arg = *p;
298 arg++;
299 }
300 p++;
301 }
302 *arg = '\0';
303 argSpace = arg + 1;
304 }
305 argv[argc] = NULL;
306
307 *argcPtr = argc;
308 *argvPtr = argv;
309 }
310 #endif /* __GNUC__ */
311
312 /*
313 * Local Variables:
314 * mode: c
315 * c-basic-offset: 4
316 * fill-column: 78
317 * End:
318 */
319