blob: 2fc744774cf248f068d0f9c0489c45cd906eec9e [file] [log] [blame]
Guido van Rossumb0f3c821994-08-23 13:34:25 +00001/***********************************************************
Jack Jansen42218ce1997-01-31 16:15:11 +00002Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
Guido van Rossum99546991995-01-08 14:33:34 +00003The 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>
Jack Jansen2429c721996-03-07 15:17:11 +000038#include <Fonts.h>
Guido van Rossumb0f3c821994-08-23 13:34:25 +000039
Jack Jansenc76fd391995-02-02 14:27:31 +000040#ifdef __MWERKS__
41#include <SIOUX.h>
Jack Jansen1e8557a1995-11-10 14:51:26 +000042#define USE_SIOUX
Jack Jansen8c693211997-01-07 16:19:42 +000043#if __profile__ == 1
44#include <profiler.h>
45#endif
Jack Jansenc76fd391995-02-02 14:27:31 +000046#endif
47
Jack Jansen0168f271995-10-27 13:32:30 +000048#ifdef THINK_C
49#include <console.h>
50#endif
51
Jack Jansen696c9581995-08-14 12:33:20 +000052#define STARTUP "PythonStartup"
Jack Jansenbac428d1994-12-14 13:47:30 +000053
Jack Jansen696c9581995-08-14 12:33:20 +000054extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
55extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
Jack Jansen3f7d2b41996-09-06 22:21:07 +000056short PyMac_AppRefNum; /* RefNum of application resource fork */
Jack Jansen696c9581995-08-14 12:33:20 +000057
Jack Jansen1d2f8631996-08-02 15:16:16 +000058/* For Py_GetArgcArgv(); set by main() */
Jack Jansen696c9581995-08-14 12:33:20 +000059static char **orig_argv;
60static int orig_argc;
61
Jack Jansen7d5f9e81996-09-07 17:09:31 +000062PyMac_PrefRecord options;
Jack Jansen0168f271995-10-27 13:32:30 +000063
Jack Jansen76ceece1996-08-19 11:18:24 +000064static void Py_Main Py_PROTO((int, char **)); /* Forward */
65void PyMac_Exit Py_PROTO((int)); /* Forward */
66
Jack Jansen01fbc681996-02-28 15:42:47 +000067/* Initialize the Mac toolbox world */
68
69static void
70init_mac_world()
71{
72#ifdef THINK_C
73 printf("\n");
74#else
75 MaxApplZone();
76 InitGraf(&qd.thePort);
77 InitFonts();
78 InitWindows();
79 TEInit();
80 InitDialogs((long)0);
81 InitMenus();
82 InitCursor();
83#endif
84}
85
Jack Jansen7d5f9e81996-09-07 17:09:31 +000086/*
87** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
88*/
Jack Jansen01fbc681996-02-28 15:42:47 +000089static void
Jack Jansen7d5f9e81996-09-07 17:09:31 +000090PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
91{
92 KeyMap rmap;
93 unsigned char *map;
94 short item, type;
95 ControlHandle handle;
96 DialogPtr dialog;
97 Rect rect;
98 int old_argc = *argcp;
99 int i;
100
101 /*
102 ** If the preferences disallows interactive options we return,
103 ** similarly of <option> isn't pressed.
104 */
105 if (p->nointopt) return;
106
107 GetKeys(rmap);
108 map = (unsigned char *)rmap;
109 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
110 return;
111
112 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
113 if ( dialog == NULL ) {
114 printf("Option dialog not found - cannot set options\n");
115 return;
116 }
117 SetDialogDefaultItem(dialog, OPT_OK);
118 SetDialogCancelItem(dialog, OPT_CANCEL);
119
120 /* Set default values */
121#define SET_OPT_ITEM(num, var) \
122 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
Jack Jansen08c3be31997-04-08 15:27:00 +0000123 SetControlValue(handle, (short)p->var);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000124
125 SET_OPT_ITEM(OPT_INSPECT, inspect);
126 SET_OPT_ITEM(OPT_VERBOSE, verbose);
Jack Jansen7330b391997-08-08 14:56:41 +0000127/* SET_OPT_ITEM(OPT_SUPPRESS, suppress_print); */
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000128 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
129 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
130 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
131 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
132 /* The rest are not settable interactively */
133
134#undef SET_OPT_ITEM
135
136 while (1) {
137 handle = NULL;
138 ModalDialog(NULL, &item);
139 if ( item == OPT_OK )
140 break;
141 if ( item == OPT_CANCEL ) {
Jack Jansen08c3be31997-04-08 15:27:00 +0000142 DisposeDialog(dialog);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000143 exit(0);
144 }
145 if ( item == OPT_CMDLINE ) {
146 int new_argc, newer_argc;
147 char **new_argv, **newer_argv;
148
149 new_argc = ccommand(&new_argv);
150 newer_argc = (new_argc-1) + old_argc;
151 newer_argv = malloc((newer_argc+1)*sizeof(char *));
152 if( !newer_argv )
153 Py_FatalError("Cannot malloc argv\n");
154 for(i=0; i<old_argc; i++)
155 newer_argv[i] = (*argvp)[i];
156 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
157 newer_argv[i] = new_argv[i-old_argc+1];
158 *argvp = newer_argv;
159 *argcp = newer_argc;
160
161 /* XXXX Is it not safe to use free() here, apparently */
162 }
163#define OPT_ITEM(num, var) \
164 if ( item == (num) ) { \
165 p->var = !p->var; \
166 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
Jack Jansen08c3be31997-04-08 15:27:00 +0000167 SetControlValue(handle, (short)p->var); \
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000168 }
169
170 OPT_ITEM(OPT_INSPECT, inspect);
171 OPT_ITEM(OPT_VERBOSE, verbose);
Jack Jansen7330b391997-08-08 14:56:41 +0000172/* OPT_ITEM(OPT_SUPPRESS, suppress_print); */
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000173 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
174 OPT_ITEM(OPT_DEBUGGING, debugging);
175 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
176 OPT_ITEM(OPT_KEEPERROR, keep_error);
177
178#undef OPT_ITEM
179 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000180 DisposeDialog(dialog);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000181}
182
183/*
184** Initialization code, shared by interpreter and applets
185*/
186static void
Jack Jansen52ac0371997-01-15 15:49:08 +0000187init_common(int *argcp, char ***argvp, int embedded)
Jack Jansen01fbc681996-02-28 15:42:47 +0000188{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000189 /* Remember resource fork refnum, for later */
190 PyMac_AppRefNum = CurResFile();
191
Jack Jansen01fbc681996-02-28 15:42:47 +0000192 /* Initialize toolboxes */
193 init_mac_world();
194
195#ifdef USE_MAC_SHARED_LIBRARY
196 /* Add the shared library to the stack of resource files */
197 PyMac_AddLibResources();
198#endif
199
200#if defined(USE_GUSI)
201 /* Setup GUSI */
202 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000203 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000204 PyMac_SetGUSIOptions();
Jack Jansena39f1b01997-05-23 15:35:14 +0000205 atexit(PyMac_StopGUSISpin);
Jack Jansen01fbc681996-02-28 15:42:47 +0000206#endif
207
208#ifdef USE_SIOUX
209 /* Set various SIOUX flags. Some are changed later based on options */
Jack Jansencaa7c461997-06-12 10:49:13 +0000210/* SIOUXSettings.standalone = 0; /* XXXX Attempting to keep sioux from eating events */
Jack Jansen01fbc681996-02-28 15:42:47 +0000211 SIOUXSettings.asktosaveonclose = 0;
212 SIOUXSettings.showstatusline = 0;
213 SIOUXSettings.tabspaces = 4;
214#endif
215
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000216 /* Get options from preference file (or from applet resource fork) */
217 options.keep_error = 1; /* default-default */
218 PyMac_PreferenceOptions(&options);
219
Jack Jansen52ac0371997-01-15 15:49:08 +0000220 if ( embedded ) {
221 static char *emb_argv[] = {"embedded-python", 0};
222
223 *argcp = 1;
224 *argvp = emb_argv;
225 } else {
226 /* Create argc/argv. Do it before we go into the options event loop. */
227 *argcp = PyMac_GetArgv(argvp, options.noargs);
228
229 /* Do interactive option setting, if allowed and <option> depressed */
230 PyMac_InteractiveOptions(&options, argcp, argvp);
231 }
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000232
233 /* Copy selected options to where the machine-independent stuff wants it */
234 Py_VerboseFlag = options.verbose;
Jack Jansen7330b391997-08-08 14:56:41 +0000235/* Py_SuppressPrintingFlag = options.suppress_print; */
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000236 Py_DebugFlag = options.debugging;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000237 if ( options.noargs ) {
238 /* don't process events at all without the scripts permission */
239 PyMacSchedParams scp;
240
241 PyMac_GetSchedParams(&scp);
242 scp.process_events = 0;
243 /* Should we disable command-dot as well? */
244 PyMac_SetSchedParams(&scp);
245 }
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000246
247 /* Set buffering */
248 if (options.unbuffered) {
249#ifndef MPW
250 setbuf(stdout, (char *)NULL);
251 setbuf(stderr, (char *)NULL);
252#else
253 /* On MPW (3.2) unbuffered seems to hang */
254 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
255 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
256#endif
257 }
Jack Jansen8c693211997-01-07 16:19:42 +0000258#if __profile__ == 1
259 /* collectSummary or collectDetailed, timebase, #routines, max stack depth */
260 ProfilerInit(collectSummary, bestTimeBase, 2000, 150);
261#endif
Jack Jansen7330b391997-08-08 14:56:41 +0000262
263 /* Tell the rest of python about our argc/argv */
264 orig_argc = *argcp; /* For Py_GetArgcArgv() */
265 orig_argv = *argvp;
266 Py_SetProgramName((*argvp)[0]);
Jack Jansen01fbc681996-02-28 15:42:47 +0000267}
268
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000269/*
270** Inspection mode after script/applet termination
271*/
272static int
273run_inspect()
274{
275 int sts = 0;
276
277 if (options.inspect && isatty((int)fileno(stdin)))
278 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
279 return sts;
280}
Jack Jansen01fbc681996-02-28 15:42:47 +0000281
Jack Jansen696c9581995-08-14 12:33:20 +0000282#ifdef USE_MAC_APPLET_SUPPORT
283/* Applet support */
284
285/* Run a compiled Python Python script from 'PYC ' resource __main__ */
286static int
287run_main_resource()
288{
289 Handle h;
290 long size;
291 PyObject *code;
292 PyObject *result;
293
294 h = GetNamedResource('PYC ', "\p__main__");
295 if (h == NULL) {
296 Alert(NOPYC_ALERT, NULL);
297 return 1;
298 }
299 size = GetResourceSizeOnDisk(h);
300 HLock(h);
301 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
302 HUnlock(h);
303 ReleaseResource(h);
304 if (code == NULL) {
305 PyErr_Print();
306 return 1;
307 }
308 result = PyImport_ExecCodeModule("__main__", code);
309 Py_DECREF(code);
310 if (result == NULL) {
311 PyErr_Print();
312 return 1;
313 }
314 Py_DECREF(result);
315 return 0;
316}
317
318/* Initialization sequence for applets */
319void
320PyMac_InitApplet()
321{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000322 int argc;
323 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000324 int err;
325
Jack Jansen52ac0371997-01-15 15:49:08 +0000326 init_common(&argc, &argv, 0);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000327
Jack Jansen696c9581995-08-14 12:33:20 +0000328 Py_Initialize();
329 PySys_SetArgv(argc, argv);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000330
Jack Jansen696c9581995-08-14 12:33:20 +0000331 err = run_main_resource();
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000332
333 err = (run_inspect() || err);
334
Jack Jansen696c9581995-08-14 12:33:20 +0000335 fflush(stderr);
336 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000337 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000338 /* XXX Should we bother to Py_Exit(sts)? */
339}
340
Jack Jansen52ac0371997-01-15 15:49:08 +0000341/*
342** Hook for embedding python.
343*/
344void
345PyMac_Initialize()
346{
347 int argc;
348 char **argv;
349
350 init_common(&argc, &argv, 1);
351 Py_Initialize();
352 PySys_SetArgv(argc, argv);
353}
354
Jack Jansen696c9581995-08-14 12:33:20 +0000355#endif /* USE_MAC_APPLET_SUPPORT */
356
357/* For normal application */
358void
359PyMac_InitApplication()
360{
361 int argc;
362 char **argv;
363
Jack Jansen52ac0371997-01-15 15:49:08 +0000364 init_common(&argc, &argv, 0);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000365
Jack Jansen696c9581995-08-14 12:33:20 +0000366 if ( argc > 1 ) {
367 /* We're running a script. Attempt to change current directory */
368 char curwd[256], *endp;
369
370 strcpy(curwd, argv[1]);
371 endp = strrchr(curwd, ':');
372 if ( endp && endp > curwd ) {
373 *endp = '\0';
374
375 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000376#ifdef USE_GUSI
377 /* Change MacOS's idea of wd too */
378 PyMac_FixGUSIcd();
379#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000380 }
381 }
382 Py_Main(argc, argv);
383}
384
Jack Jansen696c9581995-08-14 12:33:20 +0000385/* Main program */
386
Jack Jansen76ceece1996-08-19 11:18:24 +0000387static void
Jack Jansen696c9581995-08-14 12:33:20 +0000388Py_Main(argc, argv)
389 int argc;
390 char **argv;
391{
Jack Jansen696c9581995-08-14 12:33:20 +0000392 int sts;
393 char *command = NULL;
394 char *filename = NULL;
395 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000396
Jack Jansen696c9581995-08-14 12:33:20 +0000397 filename = argv[1];
398
399 if (Py_VerboseFlag ||
400 command == NULL && filename == NULL && isatty((int)fileno(fp)))
401 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000402 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000403
404 if (filename != NULL) {
405 if ((fp = fopen(filename, "r")) == NULL) {
406 fprintf(stderr, "%s: can't open file '%s'\n",
407 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000408 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000409 }
410 }
411
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000412 /* We initialize the menubar here, hoping SIOUX is initialized by now */
Jack Jansen3469e991996-09-06 00:30:45 +0000413 PyMac_InitMenuBar();
414
Jack Jansen696c9581995-08-14 12:33:20 +0000415 Py_Initialize();
416
417 PySys_SetArgv(argc-1, argv+1);
418
419 if (filename == NULL && isatty((int)fileno(fp))) {
420 FILE *fp = fopen(STARTUP, "r");
421 if (fp != NULL) {
422 (void) PyRun_SimpleFile(fp, STARTUP);
423 PyErr_Clear();
424 fclose(fp);
425 }
426 }
427 sts = PyRun_AnyFile(
428 fp, filename == NULL ? "<stdin>" : filename) != 0;
429 if (filename != NULL)
430 fclose(fp);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000431
432 if ( filename != NULL || command != NULL )
433 sts = (run_inspect() || sts);
Jack Jansen696c9581995-08-14 12:33:20 +0000434
435 Py_Exit(sts);
436 /*NOTREACHED*/
437}
438
Jack Jansen0168f271995-10-27 13:32:30 +0000439/*
440** Terminate application
441*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000442void
Jack Jansen0168f271995-10-27 13:32:30 +0000443PyMac_Exit(status)
444 int status;
445{
446 int keep;
Jack Jansen8c693211997-01-07 16:19:42 +0000447
448#if __profile__ == 1
449 ProfilerDump("\pPython Profiler Results");
450 ProfilerTerm();
451#endif
Jack Jansen0168f271995-10-27 13:32:30 +0000452 if ( status )
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000453 keep = options.keep_error;
Jack Jansen0168f271995-10-27 13:32:30 +0000454 else
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000455 keep = options.keep_normal;
Jack Jansen0168f271995-10-27 13:32:30 +0000456
Jack Jansen1e8557a1995-11-10 14:51:26 +0000457#ifdef USE_SIOUX
458 if (keep) {
459 SIOUXSettings.standalone = 1;
460 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000461 SIOUXSetTitle("\p\307terminated\310");
Jack Jansencaa7c461997-06-12 10:49:13 +0000462 PyMac_RestoreMenuBar();
Jack Jansene44545f1997-05-07 15:48:54 +0000463#ifdef USE_MSL
464 /*
465 ** Temporary workaround: autocloseonquit clearing does not
466 ** currently work for the MSL/GUSI combo.
467 */
468 while(getchar() > 0);
469#endif
Jack Jansen1e8557a1995-11-10 14:51:26 +0000470 }
Jack Jansen0168f271995-10-27 13:32:30 +0000471 else
472 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000473#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000474#ifdef THINK_C
475 console_options.pause_atexit = keep;
476#endif
477
478 exit(status);
479}
Jack Jansen696c9581995-08-14 12:33:20 +0000480
481/* Return the program name -- some code out there needs this. */
Jack Jansena39f1b01997-05-23 15:35:14 +0000482char *
483Py_GetProgramFullPath()
484{
Jack Jansen7330b391997-08-08 14:56:41 +0000485 return orig_argv[0];
Jack Jansena39f1b01997-05-23 15:35:14 +0000486}
487
Jack Jansen696c9581995-08-14 12:33:20 +0000488
489/* Make the *original* argc/argv available to other modules.
490 This is rare, but it is needed by the secureware extension. */
491
492void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000493Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000494 int *argc;
495 char ***argv;
496{
497 *argc = orig_argc;
498 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000499}
Jack Jansen1d2f8631996-08-02 15:16:16 +0000500
501/* More cruft that shouldn't really be here, used in sysmodule.c */
502
503char *
504Py_GetPrefix()
505{
Jack Jansenac625691997-09-08 13:22:22 +0000506 return PyMac_GetPythonDir();
Jack Jansen1d2f8631996-08-02 15:16:16 +0000507}
508
509char *
510Py_GetExecPrefix()
511{
Jack Jansenac625691997-09-08 13:22:22 +0000512 return PyMac_GetPythonDir();
Jack Jansen1d2f8631996-08-02 15:16:16 +0000513}