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