blob: 583ed1ae4b7931d5b4bcdf6c26cab2dc9e65934f [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 Jansen8c693211997-01-07 16:19:42 +000044#if __profile__ == 1
45#include <profiler.h>
46#endif
Jack Jansenc76fd391995-02-02 14:27:31 +000047#endif
48
Jack Jansen0168f271995-10-27 13:32:30 +000049#ifdef THINK_C
50#include <console.h>
51#endif
52
Jack Jansen696c9581995-08-14 12:33:20 +000053#define STARTUP "PythonStartup"
Jack Jansenbac428d1994-12-14 13:47:30 +000054
Jack Jansen696c9581995-08-14 12:33:20 +000055extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
56extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
57extern int Py_SuppressPrintingFlag; /* For ceval.c, declared in pythonrun.c */
Jack Jansen3f7d2b41996-09-06 22:21:07 +000058short PyMac_AppRefNum; /* RefNum of application resource fork */
Jack Jansen696c9581995-08-14 12:33:20 +000059
60
61/* Subroutines that live in their own file */
Jack Jansena547dca1996-07-10 15:48:25 +000062extern char *Py_GetVersion Py_PROTO((void));
63extern char *Py_GetCopyright Py_PROTO((void));
Jack Jansen696c9581995-08-14 12:33:20 +000064
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 Jansen7d5f9e81996-09-07 17:09:31 +000070PyMac_PrefRecord options;
Jack Jansen0168f271995-10-27 13:32:30 +000071
Jack Jansen76ceece1996-08-19 11:18:24 +000072static void Py_Main Py_PROTO((int, char **)); /* Forward */
73void PyMac_Exit Py_PROTO((int)); /* Forward */
74
Jack Jansen01fbc681996-02-28 15:42:47 +000075/* Initialize the Mac toolbox world */
76
77static void
78init_mac_world()
79{
80#ifdef THINK_C
81 printf("\n");
82#else
83 MaxApplZone();
84 InitGraf(&qd.thePort);
85 InitFonts();
86 InitWindows();
87 TEInit();
88 InitDialogs((long)0);
89 InitMenus();
90 InitCursor();
91#endif
92}
93
Jack Jansen7d5f9e81996-09-07 17:09:31 +000094/*
95** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
96*/
Jack Jansen01fbc681996-02-28 15:42:47 +000097static void
Jack Jansen7d5f9e81996-09-07 17:09:31 +000098PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
99{
100 KeyMap rmap;
101 unsigned char *map;
102 short item, type;
103 ControlHandle handle;
104 DialogPtr dialog;
105 Rect rect;
106 int old_argc = *argcp;
107 int i;
108
109 /*
110 ** If the preferences disallows interactive options we return,
111 ** similarly of <option> isn't pressed.
112 */
113 if (p->nointopt) return;
114
115 GetKeys(rmap);
116 map = (unsigned char *)rmap;
117 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
118 return;
119
120 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
121 if ( dialog == NULL ) {
122 printf("Option dialog not found - cannot set options\n");
123 return;
124 }
125 SetDialogDefaultItem(dialog, OPT_OK);
126 SetDialogCancelItem(dialog, OPT_CANCEL);
127
128 /* Set default values */
129#define SET_OPT_ITEM(num, var) \
130 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
131 SetCtlValue(handle, (short)p->var);
132
133 SET_OPT_ITEM(OPT_INSPECT, inspect);
134 SET_OPT_ITEM(OPT_VERBOSE, verbose);
135 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
136 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
137 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
138 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
139 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
140 /* The rest are not settable interactively */
141
142#undef SET_OPT_ITEM
143
144 while (1) {
145 handle = NULL;
146 ModalDialog(NULL, &item);
147 if ( item == OPT_OK )
148 break;
149 if ( item == OPT_CANCEL ) {
150 DisposDialog(dialog);
151 exit(0);
152 }
153 if ( item == OPT_CMDLINE ) {
154 int new_argc, newer_argc;
155 char **new_argv, **newer_argv;
156
157 new_argc = ccommand(&new_argv);
158 newer_argc = (new_argc-1) + old_argc;
159 newer_argv = malloc((newer_argc+1)*sizeof(char *));
160 if( !newer_argv )
161 Py_FatalError("Cannot malloc argv\n");
162 for(i=0; i<old_argc; i++)
163 newer_argv[i] = (*argvp)[i];
164 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
165 newer_argv[i] = new_argv[i-old_argc+1];
166 *argvp = newer_argv;
167 *argcp = newer_argc;
168
169 /* XXXX Is it not safe to use free() here, apparently */
170 }
171#define OPT_ITEM(num, var) \
172 if ( item == (num) ) { \
173 p->var = !p->var; \
174 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
175 SetCtlValue(handle, (short)p->var); \
176 }
177
178 OPT_ITEM(OPT_INSPECT, inspect);
179 OPT_ITEM(OPT_VERBOSE, verbose);
180 OPT_ITEM(OPT_SUPPRESS, suppress_print);
181 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
182 OPT_ITEM(OPT_DEBUGGING, debugging);
183 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
184 OPT_ITEM(OPT_KEEPERROR, keep_error);
185
186#undef OPT_ITEM
187 }
188 DisposDialog(dialog);
189}
190
191/*
192** Initialization code, shared by interpreter and applets
193*/
194static void
195init_common(int *argcp, char ***argvp)
Jack Jansen01fbc681996-02-28 15:42:47 +0000196{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000197 /* Remember resource fork refnum, for later */
198 PyMac_AppRefNum = CurResFile();
199
Jack Jansen01fbc681996-02-28 15:42:47 +0000200 /* Initialize toolboxes */
201 init_mac_world();
202
203#ifdef USE_MAC_SHARED_LIBRARY
204 /* Add the shared library to the stack of resource files */
205 PyMac_AddLibResources();
206#endif
207
208#if defined(USE_GUSI)
209 /* Setup GUSI */
210 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000211 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000212 PyMac_SetGUSIOptions();
Jack Jansen01fbc681996-02-28 15:42:47 +0000213#endif
214
215#ifdef USE_SIOUX
216 /* Set various SIOUX flags. Some are changed later based on options */
217 SIOUXSettings.asktosaveonclose = 0;
218 SIOUXSettings.showstatusline = 0;
219 SIOUXSettings.tabspaces = 4;
220#endif
221
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000222 /* Get options from preference file (or from applet resource fork) */
223 options.keep_error = 1; /* default-default */
224 PyMac_PreferenceOptions(&options);
225
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
232 /* Copy selected options to where the machine-independent stuff wants it */
233 Py_VerboseFlag = options.verbose;
234 Py_SuppressPrintingFlag = options.suppress_print;
235 Py_DebugFlag = options.debugging;
236 if ( options.noargs )
237 PyMac_DoYieldEnabled = 0;
238
239 /* Set buffering */
240 if (options.unbuffered) {
241#ifndef MPW
242 setbuf(stdout, (char *)NULL);
243 setbuf(stderr, (char *)NULL);
244#else
245 /* On MPW (3.2) unbuffered seems to hang */
246 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
247 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
248#endif
249 }
Jack Jansen8c693211997-01-07 16:19:42 +0000250#if __profile__ == 1
251 /* collectSummary or collectDetailed, timebase, #routines, max stack depth */
252 ProfilerInit(collectSummary, bestTimeBase, 2000, 150);
253#endif
Jack Jansen01fbc681996-02-28 15:42:47 +0000254}
255
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000256/*
257** Inspection mode after script/applet termination
258*/
259static int
260run_inspect()
261{
262 int sts = 0;
263
264 if (options.inspect && isatty((int)fileno(stdin)))
265 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
266 return sts;
267}
Jack Jansen01fbc681996-02-28 15:42:47 +0000268
Jack Jansen696c9581995-08-14 12:33:20 +0000269#ifdef USE_MAC_APPLET_SUPPORT
270/* Applet support */
271
272/* Run a compiled Python Python script from 'PYC ' resource __main__ */
273static int
274run_main_resource()
275{
276 Handle h;
277 long size;
278 PyObject *code;
279 PyObject *result;
280
281 h = GetNamedResource('PYC ', "\p__main__");
282 if (h == NULL) {
283 Alert(NOPYC_ALERT, NULL);
284 return 1;
285 }
286 size = GetResourceSizeOnDisk(h);
287 HLock(h);
288 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
289 HUnlock(h);
290 ReleaseResource(h);
291 if (code == NULL) {
292 PyErr_Print();
293 return 1;
294 }
295 result = PyImport_ExecCodeModule("__main__", code);
296 Py_DECREF(code);
297 if (result == NULL) {
298 PyErr_Print();
299 return 1;
300 }
301 Py_DECREF(result);
302 return 0;
303}
304
305/* Initialization sequence for applets */
306void
307PyMac_InitApplet()
308{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000309 int argc;
310 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000311 int err;
312
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000313 init_common(&argc, &argv);
314
Jack Jansen696c9581995-08-14 12:33:20 +0000315 Py_Initialize();
316 PySys_SetArgv(argc, argv);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000317
Jack Jansen696c9581995-08-14 12:33:20 +0000318 err = run_main_resource();
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000319
320 err = (run_inspect() || err);
321
Jack Jansen696c9581995-08-14 12:33:20 +0000322 fflush(stderr);
323 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000324 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000325 /* XXX Should we bother to Py_Exit(sts)? */
326}
327
328#endif /* USE_MAC_APPLET_SUPPORT */
329
330/* For normal application */
331void
332PyMac_InitApplication()
333{
334 int argc;
335 char **argv;
336
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000337 init_common(&argc, &argv);
338
Jack Jansen696c9581995-08-14 12:33:20 +0000339 if ( argc > 1 ) {
340 /* We're running a script. Attempt to change current directory */
341 char curwd[256], *endp;
342
343 strcpy(curwd, argv[1]);
344 endp = strrchr(curwd, ':');
345 if ( endp && endp > curwd ) {
346 *endp = '\0';
347
348 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000349#ifdef USE_GUSI
350 /* Change MacOS's idea of wd too */
351 PyMac_FixGUSIcd();
352#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000353 }
354 }
355 Py_Main(argc, argv);
356}
357
Jack Jansen696c9581995-08-14 12:33:20 +0000358/* Main program */
359
Jack Jansen76ceece1996-08-19 11:18:24 +0000360static void
Jack Jansen696c9581995-08-14 12:33:20 +0000361Py_Main(argc, argv)
362 int argc;
363 char **argv;
364{
Jack Jansen696c9581995-08-14 12:33:20 +0000365 int sts;
366 char *command = NULL;
367 char *filename = NULL;
368 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000369
Jack Jansen1d2f8631996-08-02 15:16:16 +0000370 orig_argc = argc; /* For Py_GetArgcArgv() */
Jack Jansen696c9581995-08-14 12:33:20 +0000371 orig_argv = argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000372 filename = argv[1];
373
374 if (Py_VerboseFlag ||
375 command == NULL && filename == NULL && isatty((int)fileno(fp)))
376 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000377 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000378
379 if (filename != NULL) {
380 if ((fp = fopen(filename, "r")) == NULL) {
381 fprintf(stderr, "%s: can't open file '%s'\n",
382 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000383 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000384 }
385 }
386
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000387 /* We initialize the menubar here, hoping SIOUX is initialized by now */
Jack Jansen3469e991996-09-06 00:30:45 +0000388 PyMac_InitMenuBar();
389
Jack Jansen696c9581995-08-14 12:33:20 +0000390 Py_Initialize();
391
392 PySys_SetArgv(argc-1, argv+1);
393
394 if (filename == NULL && isatty((int)fileno(fp))) {
395 FILE *fp = fopen(STARTUP, "r");
396 if (fp != NULL) {
397 (void) PyRun_SimpleFile(fp, STARTUP);
398 PyErr_Clear();
399 fclose(fp);
400 }
401 }
402 sts = PyRun_AnyFile(
403 fp, filename == NULL ? "<stdin>" : filename) != 0;
404 if (filename != NULL)
405 fclose(fp);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000406
407 if ( filename != NULL || command != NULL )
408 sts = (run_inspect() || sts);
Jack Jansen696c9581995-08-14 12:33:20 +0000409
410 Py_Exit(sts);
411 /*NOTREACHED*/
412}
413
Jack Jansen0168f271995-10-27 13:32:30 +0000414/*
415** Terminate application
416*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000417void
Jack Jansen0168f271995-10-27 13:32:30 +0000418PyMac_Exit(status)
419 int status;
420{
421 int keep;
Jack Jansen8c693211997-01-07 16:19:42 +0000422
423#if __profile__ == 1
424 ProfilerDump("\pPython Profiler Results");
425 ProfilerTerm();
426#endif
Jack Jansen0168f271995-10-27 13:32:30 +0000427 if ( status )
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000428 keep = options.keep_error;
Jack Jansen0168f271995-10-27 13:32:30 +0000429 else
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000430 keep = options.keep_normal;
Jack Jansen0168f271995-10-27 13:32:30 +0000431
Jack Jansen1e8557a1995-11-10 14:51:26 +0000432#ifdef USE_SIOUX
433 if (keep) {
434 SIOUXSettings.standalone = 1;
435 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000436 SIOUXSetTitle("\p\307terminated\310");
Jack Jansen1e8557a1995-11-10 14:51:26 +0000437 }
Jack Jansen0168f271995-10-27 13:32:30 +0000438 else
439 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000440#ifdef USE_GUSI
441 /*
442 ** Workaround for Sioux/GUSI combo: we should not call
443 ** SiouxHandleOneEvent after the window is closed
444 */
445 PyMac_ConsoleIsDead = 1;
446#endif /* USE_GUSI */
447#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000448#ifdef THINK_C
449 console_options.pause_atexit = keep;
450#endif
451
452 exit(status);
453}
Jack Jansen696c9581995-08-14 12:33:20 +0000454
455/* Return the program name -- some code out there needs this. */
456
457char *
Jack Jansen1d2f8631996-08-02 15:16:16 +0000458Py_GetProgramName()
Jack Jansen696c9581995-08-14 12:33:20 +0000459{
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000460 return orig_argv[0];
Jack Jansen696c9581995-08-14 12:33:20 +0000461}
462
463
464/* Make the *original* argc/argv available to other modules.
465 This is rare, but it is needed by the secureware extension. */
466
467void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000468Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000469 int *argc;
470 char ***argv;
471{
472 *argc = orig_argc;
473 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000474}
Jack Jansen1d2f8631996-08-02 15:16:16 +0000475
476/* More cruft that shouldn't really be here, used in sysmodule.c */
477
478char *
479Py_GetPrefix()
480{
481 return "";
482}
483
484char *
485Py_GetExecPrefix()
486{
487 return "";
488}