blob: 095673e0f3c1f8562403213d6a79d68eeb5d409f [file] [log] [blame]
Guido van Rossumb0f3c821994-08-23 13:34:25 +00001/***********************************************************
Guido van Rossum99546991995-01-08 14:33:34 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumb0f3c821994-08-23 13:34:25 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Jack Jansen696c9581995-08-14 12:33:20 +000025/* Python interpreter main program */
Guido van Rossumb0f3c821994-08-23 13:34:25 +000026
Jack Jansen696c9581995-08-14 12:33:20 +000027#include "Python.h"
28#include "pythonresources.h"
29#include "import.h"
30#include "marshal.h"
Jack Jansenf6865f71996-09-04 15:24:59 +000031#include "macglue.h"
Guido van Rossumb0f3c821994-08-23 13:34:25 +000032
Jack Jansen696c9581995-08-14 12:33:20 +000033#include <Memory.h>
34#include <Resources.h>
Guido van Rossumb0f3c821994-08-23 13:34:25 +000035#include <stdio.h>
Jack Jansen696c9581995-08-14 12:33:20 +000036#include <Events.h>
37#include <Windows.h>
38#include <Desk.h>
Jack Jansen2429c721996-03-07 15:17:11 +000039#include <Fonts.h>
Guido van Rossumb0f3c821994-08-23 13:34:25 +000040
Jack Jansenc76fd391995-02-02 14:27:31 +000041#ifdef __MWERKS__
42#include <SIOUX.h>
Jack Jansen1e8557a1995-11-10 14:51:26 +000043#define USE_SIOUX
Jack Jansenc76fd391995-02-02 14:27:31 +000044#endif
45
Jack Jansen0168f271995-10-27 13:32:30 +000046#ifdef THINK_C
47#include <console.h>
48#endif
49
Jack Jansen696c9581995-08-14 12:33:20 +000050#define STARTUP "PythonStartup"
Jack Jansenbac428d1994-12-14 13:47:30 +000051
Jack Jansen696c9581995-08-14 12:33:20 +000052extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
53extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
54extern int Py_SuppressPrintingFlag; /* For ceval.c, declared in pythonrun.c */
Jack Jansen3f7d2b41996-09-06 22:21:07 +000055short PyMac_AppRefNum; /* RefNum of application resource fork */
Jack Jansen696c9581995-08-14 12:33:20 +000056
57
58/* Subroutines that live in their own file */
Jack Jansena547dca1996-07-10 15:48:25 +000059extern char *Py_GetVersion Py_PROTO((void));
60extern char *Py_GetCopyright Py_PROTO((void));
Jack Jansen696c9581995-08-14 12:33:20 +000061
62
Jack Jansen1d2f8631996-08-02 15:16:16 +000063/* For Py_GetProgramName(); set by main() */
Jack Jansen696c9581995-08-14 12:33:20 +000064static char *argv0;
65
Jack Jansen1d2f8631996-08-02 15:16:16 +000066/* For Py_GetArgcArgv(); set by main() */
Jack Jansen696c9581995-08-14 12:33:20 +000067static char **orig_argv;
68static int orig_argc;
69
Jack Jansen0168f271995-10-27 13:32:30 +000070/* Flags indicating whether stdio window should stay open on termination */
71static int keep_normal;
72static int keep_error = 1;
73
Jack Jansen76ceece1996-08-19 11:18:24 +000074static void Py_Main Py_PROTO((int, char **)); /* Forward */
75void PyMac_Exit Py_PROTO((int)); /* Forward */
76
Jack Jansen01fbc681996-02-28 15:42:47 +000077/* Initialize the Mac toolbox world */
78
79static void
80init_mac_world()
81{
82#ifdef THINK_C
83 printf("\n");
84#else
85 MaxApplZone();
86 InitGraf(&qd.thePort);
87 InitFonts();
88 InitWindows();
89 TEInit();
90 InitDialogs((long)0);
91 InitMenus();
92 InitCursor();
93#endif
94}
95
96/* Initialization code shared by interpreter and applets */
97
98static void
99init_common()
100{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000101 /* Remember resource fork refnum, for later */
102 PyMac_AppRefNum = CurResFile();
103
Jack Jansen01fbc681996-02-28 15:42:47 +0000104 /* Initialize toolboxes */
105 init_mac_world();
106
107#ifdef USE_MAC_SHARED_LIBRARY
108 /* Add the shared library to the stack of resource files */
109 PyMac_AddLibResources();
110#endif
111
112#if defined(USE_GUSI)
113 /* Setup GUSI */
114 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000115 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000116 PyMac_SetGUSIOptions();
Jack Jansen01fbc681996-02-28 15:42:47 +0000117#endif
118
119#ifdef USE_SIOUX
120 /* Set various SIOUX flags. Some are changed later based on options */
121 SIOUXSettings.asktosaveonclose = 0;
122 SIOUXSettings.showstatusline = 0;
123 SIOUXSettings.tabspaces = 4;
124#endif
125
126}
127
128
Jack Jansen696c9581995-08-14 12:33:20 +0000129#ifdef USE_MAC_APPLET_SUPPORT
130/* Applet support */
131
132/* Run a compiled Python Python script from 'PYC ' resource __main__ */
133static int
134run_main_resource()
135{
136 Handle h;
137 long size;
138 PyObject *code;
139 PyObject *result;
140
141 h = GetNamedResource('PYC ', "\p__main__");
142 if (h == NULL) {
143 Alert(NOPYC_ALERT, NULL);
144 return 1;
145 }
146 size = GetResourceSizeOnDisk(h);
147 HLock(h);
148 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
149 HUnlock(h);
150 ReleaseResource(h);
151 if (code == NULL) {
152 PyErr_Print();
153 return 1;
154 }
155 result = PyImport_ExecCodeModule("__main__", code);
156 Py_DECREF(code);
157 if (result == NULL) {
158 PyErr_Print();
159 return 1;
160 }
161 Py_DECREF(result);
162 return 0;
163}
164
165/* Initialization sequence for applets */
166void
167PyMac_InitApplet()
168{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000169 int argc;
170 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000171 int err;
172
Jack Jansen01fbc681996-02-28 15:42:47 +0000173 init_common();
Jack Jansen696c9581995-08-14 12:33:20 +0000174 argc = PyMac_GetArgv(&argv);
175 Py_Initialize();
176 PySys_SetArgv(argc, argv);
177 err = run_main_resource();
178 fflush(stderr);
179 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000180 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000181 /* XXX Should we bother to Py_Exit(sts)? */
182}
183
184#endif /* USE_MAC_APPLET_SUPPORT */
185
186/* For normal application */
187void
188PyMac_InitApplication()
189{
190 int argc;
191 char **argv;
192
Jack Jansen01fbc681996-02-28 15:42:47 +0000193 init_common();
Jack Jansen696c9581995-08-14 12:33:20 +0000194 argc = PyMac_GetArgv(&argv);
195 if ( argc > 1 ) {
196 /* We're running a script. Attempt to change current directory */
197 char curwd[256], *endp;
198
199 strcpy(curwd, argv[1]);
200 endp = strrchr(curwd, ':');
201 if ( endp && endp > curwd ) {
202 *endp = '\0';
203
204 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000205#ifdef USE_GUSI
206 /* Change MacOS's idea of wd too */
207 PyMac_FixGUSIcd();
208#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000209 }
210 }
211 Py_Main(argc, argv);
212}
213
214/*
215** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
216*/
217void
218PyMac_InteractiveOptions(int *inspect, int *verbose, int *suppress_print,
Jack Jansen0168f271995-10-27 13:32:30 +0000219 int *unbuffered, int *debugging, int *keep_normal,
Jack Jansene355c451996-03-12 13:29:04 +0000220 int *keep_error, int *argcp, char ***argvp)
Jack Jansen696c9581995-08-14 12:33:20 +0000221{
222 KeyMap rmap;
223 unsigned char *map;
224 short item, type;
225 ControlHandle handle;
226 DialogPtr dialog;
227 Rect rect;
Jack Jansene355c451996-03-12 13:29:04 +0000228 int old_argc = *argcp;
229 int i;
Jack Jansen696c9581995-08-14 12:33:20 +0000230
Jack Jansena4b7e141996-02-21 16:46:57 +0000231 /* Default-defaults: */
232 *keep_error = 1;
233 /* Get default settings from our preference file */
Jack Jansen01fbc681996-02-28 15:42:47 +0000234 PyMac_PreferenceOptions(inspect, verbose, suppress_print,
235 unbuffered, debugging, keep_normal, keep_error);
Jack Jansena4b7e141996-02-21 16:46:57 +0000236 /* If option is pressed override these */
Jack Jansen696c9581995-08-14 12:33:20 +0000237 GetKeys(rmap);
238 map = (unsigned char *)rmap;
239 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
240 return;
241
242 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
243 if ( dialog == NULL ) {
244 printf("Option dialog not found - cannot set options\n");
245 return;
246 }
Jack Jansene355c451996-03-12 13:29:04 +0000247 SetDialogDefaultItem(dialog, OPT_OK);
248 SetDialogCancelItem(dialog, OPT_CANCEL);
Jack Jansen0168f271995-10-27 13:32:30 +0000249
Jack Jansena4b7e141996-02-21 16:46:57 +0000250 /* Set default values */
251#define SET_OPT_ITEM(num, var) \
252 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
253 SetCtlValue(handle, (short)*(var));
254
255 SET_OPT_ITEM(OPT_INSPECT, inspect);
256 SET_OPT_ITEM(OPT_VERBOSE, verbose);
257 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
258 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
259 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
260 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
261 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
262
263#undef SET_OPT_ITEM
Jack Jansen0168f271995-10-27 13:32:30 +0000264
Jack Jansen696c9581995-08-14 12:33:20 +0000265 while (1) {
266 handle = NULL;
267 ModalDialog(NULL, &item);
268 if ( item == OPT_OK )
269 break;
270 if ( item == OPT_CANCEL ) {
271 DisposDialog(dialog);
272 exit(0);
273 }
Jack Jansene355c451996-03-12 13:29:04 +0000274 if ( item == OPT_CMDLINE ) {
275 int new_argc, newer_argc;
276 char **new_argv, **newer_argv;
277
278 new_argc = ccommand(&new_argv);
279 newer_argc = (new_argc-1) + old_argc;
280 newer_argv = malloc((newer_argc+1)*sizeof(char *));
281 if( !newer_argv )
282 Py_FatalError("Cannot malloc argv\n");
283 for(i=0; i<old_argc; i++)
284 newer_argv[i] = (*argvp)[i];
285 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
286 newer_argv[i] = new_argv[i-old_argc+1];
287 *argvp = newer_argv;
288 *argcp = newer_argc;
289
290 /* XXXX Is it not safe to use free() here, apparently */
291 }
Jack Jansen696c9581995-08-14 12:33:20 +0000292#define OPT_ITEM(num, var) \
293 if ( item == (num) ) { \
294 *(var) = !*(var); \
295 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
296 SetCtlValue(handle, (short)*(var)); \
297 }
298
299 OPT_ITEM(OPT_INSPECT, inspect);
300 OPT_ITEM(OPT_VERBOSE, verbose);
301 OPT_ITEM(OPT_SUPPRESS, suppress_print);
302 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
303 OPT_ITEM(OPT_DEBUGGING, debugging);
Jack Jansen0168f271995-10-27 13:32:30 +0000304 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
305 OPT_ITEM(OPT_KEEPERROR, keep_error);
Jack Jansen696c9581995-08-14 12:33:20 +0000306
307#undef OPT_ITEM
308 }
309 DisposDialog(dialog);
310}
311/* Main program */
312
Jack Jansen76ceece1996-08-19 11:18:24 +0000313static void
Jack Jansen696c9581995-08-14 12:33:20 +0000314Py_Main(argc, argv)
315 int argc;
316 char **argv;
317{
Jack Jansen696c9581995-08-14 12:33:20 +0000318 int sts;
319 char *command = NULL;
320 char *filename = NULL;
321 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000322 int inspect = 0;
323 int unbuffered = 0;
324
Jack Jansene355c451996-03-12 13:29:04 +0000325 PyMac_InteractiveOptions(&inspect, &Py_VerboseFlag, &Py_SuppressPrintingFlag,
326 &unbuffered, &Py_DebugFlag, &keep_normal, &keep_error, &argc, &argv);
327
Jack Jansen1d2f8631996-08-02 15:16:16 +0000328 orig_argc = argc; /* For Py_GetArgcArgv() */
Jack Jansen696c9581995-08-14 12:33:20 +0000329 orig_argv = argv;
Jack Jansen1d2f8631996-08-02 15:16:16 +0000330 argv0 = argv[0]; /* For Py_GetProgramName() */
Jack Jansen696c9581995-08-14 12:33:20 +0000331
332 if (unbuffered) {
333#ifndef MPW
334 setbuf(stdout, (char *)NULL);
335 setbuf(stderr, (char *)NULL);
336#else
337 /* On MPW (3.2) unbuffered seems to hang */
338 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
339 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
340#endif
341 }
342
343 filename = argv[1];
344
345 if (Py_VerboseFlag ||
346 command == NULL && filename == NULL && isatty((int)fileno(fp)))
347 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000348 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000349
350 if (filename != NULL) {
351 if ((fp = fopen(filename, "r")) == NULL) {
352 fprintf(stderr, "%s: can't open file '%s'\n",
353 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000354 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000355 }
356 }
357
Jack Jansen3469e991996-09-06 00:30:45 +0000358 /*
359 ** For reasons I don't fully understand we cannot insert our
360 ** menu earlier. Leave it here, we hope to be rid of Sioux soon anyway.
361 */
362 PyMac_InitMenuBar();
363
Jack Jansen696c9581995-08-14 12:33:20 +0000364 Py_Initialize();
365
366 PySys_SetArgv(argc-1, argv+1);
367
368 if (filename == NULL && isatty((int)fileno(fp))) {
369 FILE *fp = fopen(STARTUP, "r");
370 if (fp != NULL) {
371 (void) PyRun_SimpleFile(fp, STARTUP);
372 PyErr_Clear();
373 fclose(fp);
374 }
375 }
376 sts = PyRun_AnyFile(
377 fp, filename == NULL ? "<stdin>" : filename) != 0;
378 if (filename != NULL)
379 fclose(fp);
380
381 if (inspect && isatty((int)fileno(stdin)) &&
382 (filename != NULL || command != NULL))
383 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
384
385 Py_Exit(sts);
386 /*NOTREACHED*/
387}
388
Jack Jansen0168f271995-10-27 13:32:30 +0000389/*
390** Terminate application
391*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000392void
Jack Jansen0168f271995-10-27 13:32:30 +0000393PyMac_Exit(status)
394 int status;
395{
396 int keep;
397
398 if ( status )
399 keep = keep_error;
400 else
401 keep = keep_normal;
402
Jack Jansen1e8557a1995-11-10 14:51:26 +0000403#ifdef USE_SIOUX
404 if (keep) {
405 SIOUXSettings.standalone = 1;
406 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000407 SIOUXSetTitle("\p\307terminated\310");
Jack Jansen1e8557a1995-11-10 14:51:26 +0000408 }
Jack Jansen0168f271995-10-27 13:32:30 +0000409 else
410 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000411#ifdef USE_GUSI
412 /*
413 ** Workaround for Sioux/GUSI combo: we should not call
414 ** SiouxHandleOneEvent after the window is closed
415 */
416 PyMac_ConsoleIsDead = 1;
417#endif /* USE_GUSI */
418#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000419#ifdef THINK_C
420 console_options.pause_atexit = keep;
421#endif
422
423 exit(status);
424}
Jack Jansen696c9581995-08-14 12:33:20 +0000425
426/* Return the program name -- some code out there needs this. */
427
428char *
Jack Jansen1d2f8631996-08-02 15:16:16 +0000429Py_GetProgramName()
Jack Jansen696c9581995-08-14 12:33:20 +0000430{
431 return argv0;
432}
433
434
435/* Make the *original* argc/argv available to other modules.
436 This is rare, but it is needed by the secureware extension. */
437
438void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000439Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000440 int *argc;
441 char ***argv;
442{
443 *argc = orig_argc;
444 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000445}
Jack Jansen1d2f8631996-08-02 15:16:16 +0000446
447/* More cruft that shouldn't really be here, used in sysmodule.c */
448
449char *
450Py_GetPrefix()
451{
452 return "";
453}
454
455char *
456Py_GetExecPrefix()
457{
458 return "";
459}