blob: 8fd7bd20eab0908324533129092a6ca53ba1bd1c [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 */
56extern int Py_SuppressPrintingFlag; /* For ceval.c, declared in pythonrun.c */
Jack Jansen3f7d2b41996-09-06 22:21:07 +000057short PyMac_AppRefNum; /* RefNum of application resource fork */
Jack Jansen696c9581995-08-14 12:33:20 +000058
59
60/* Subroutines that live in their own file */
Jack Jansena547dca1996-07-10 15:48:25 +000061extern char *Py_GetVersion Py_PROTO((void));
62extern char *Py_GetCopyright Py_PROTO((void));
Jack Jansen696c9581995-08-14 12:33:20 +000063
64
Jack Jansen1d2f8631996-08-02 15:16:16 +000065/* For Py_GetArgcArgv(); set by main() */
Jack Jansen696c9581995-08-14 12:33:20 +000066static char **orig_argv;
67static int orig_argc;
68
Jack Jansen7d5f9e81996-09-07 17:09:31 +000069PyMac_PrefRecord options;
Jack Jansen0168f271995-10-27 13:32:30 +000070
Jack Jansen76ceece1996-08-19 11:18:24 +000071static void Py_Main Py_PROTO((int, char **)); /* Forward */
72void PyMac_Exit Py_PROTO((int)); /* Forward */
73
Jack Jansen01fbc681996-02-28 15:42:47 +000074/* Initialize the Mac toolbox world */
75
76static void
77init_mac_world()
78{
79#ifdef THINK_C
80 printf("\n");
81#else
82 MaxApplZone();
83 InitGraf(&qd.thePort);
84 InitFonts();
85 InitWindows();
86 TEInit();
87 InitDialogs((long)0);
88 InitMenus();
89 InitCursor();
90#endif
91}
92
Jack Jansen7d5f9e81996-09-07 17:09:31 +000093/*
94** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
95*/
Jack Jansen01fbc681996-02-28 15:42:47 +000096static void
Jack Jansen7d5f9e81996-09-07 17:09:31 +000097PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
98{
99 KeyMap rmap;
100 unsigned char *map;
101 short item, type;
102 ControlHandle handle;
103 DialogPtr dialog;
104 Rect rect;
105 int old_argc = *argcp;
106 int i;
107
108 /*
109 ** If the preferences disallows interactive options we return,
110 ** similarly of <option> isn't pressed.
111 */
112 if (p->nointopt) return;
113
114 GetKeys(rmap);
115 map = (unsigned char *)rmap;
116 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
117 return;
118
119 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
120 if ( dialog == NULL ) {
121 printf("Option dialog not found - cannot set options\n");
122 return;
123 }
124 SetDialogDefaultItem(dialog, OPT_OK);
125 SetDialogCancelItem(dialog, OPT_CANCEL);
126
127 /* Set default values */
128#define SET_OPT_ITEM(num, var) \
129 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
Jack Jansen08c3be31997-04-08 15:27:00 +0000130 SetControlValue(handle, (short)p->var);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000131
132 SET_OPT_ITEM(OPT_INSPECT, inspect);
133 SET_OPT_ITEM(OPT_VERBOSE, verbose);
134 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
135 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
136 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
137 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
138 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
139 /* The rest are not settable interactively */
140
141#undef SET_OPT_ITEM
142
143 while (1) {
144 handle = NULL;
145 ModalDialog(NULL, &item);
146 if ( item == OPT_OK )
147 break;
148 if ( item == OPT_CANCEL ) {
Jack Jansen08c3be31997-04-08 15:27:00 +0000149 DisposeDialog(dialog);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000150 exit(0);
151 }
152 if ( item == OPT_CMDLINE ) {
153 int new_argc, newer_argc;
154 char **new_argv, **newer_argv;
155
156 new_argc = ccommand(&new_argv);
157 newer_argc = (new_argc-1) + old_argc;
158 newer_argv = malloc((newer_argc+1)*sizeof(char *));
159 if( !newer_argv )
160 Py_FatalError("Cannot malloc argv\n");
161 for(i=0; i<old_argc; i++)
162 newer_argv[i] = (*argvp)[i];
163 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
164 newer_argv[i] = new_argv[i-old_argc+1];
165 *argvp = newer_argv;
166 *argcp = newer_argc;
167
168 /* XXXX Is it not safe to use free() here, apparently */
169 }
170#define OPT_ITEM(num, var) \
171 if ( item == (num) ) { \
172 p->var = !p->var; \
173 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
Jack Jansen08c3be31997-04-08 15:27:00 +0000174 SetControlValue(handle, (short)p->var); \
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000175 }
176
177 OPT_ITEM(OPT_INSPECT, inspect);
178 OPT_ITEM(OPT_VERBOSE, verbose);
179 OPT_ITEM(OPT_SUPPRESS, suppress_print);
180 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
181 OPT_ITEM(OPT_DEBUGGING, debugging);
182 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
183 OPT_ITEM(OPT_KEEPERROR, keep_error);
184
185#undef OPT_ITEM
186 }
Jack Jansen08c3be31997-04-08 15:27:00 +0000187 DisposeDialog(dialog);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000188}
189
190/*
191** Initialization code, shared by interpreter and applets
192*/
193static void
Jack Jansen52ac0371997-01-15 15:49:08 +0000194init_common(int *argcp, char ***argvp, int embedded)
Jack Jansen01fbc681996-02-28 15:42:47 +0000195{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000196 /* Remember resource fork refnum, for later */
197 PyMac_AppRefNum = CurResFile();
198
Jack Jansen01fbc681996-02-28 15:42:47 +0000199 /* Initialize toolboxes */
200 init_mac_world();
201
202#ifdef USE_MAC_SHARED_LIBRARY
203 /* Add the shared library to the stack of resource files */
204 PyMac_AddLibResources();
205#endif
206
207#if defined(USE_GUSI)
208 /* Setup GUSI */
209 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000210 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000211 PyMac_SetGUSIOptions();
Jack Jansena39f1b01997-05-23 15:35:14 +0000212 atexit(PyMac_StopGUSISpin);
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
Jack Jansen52ac0371997-01-15 15:49:08 +0000226 if ( embedded ) {
227 static char *emb_argv[] = {"embedded-python", 0};
228
229 *argcp = 1;
230 *argvp = emb_argv;
231 } else {
232 /* Create argc/argv. Do it before we go into the options event loop. */
233 *argcp = PyMac_GetArgv(argvp, options.noargs);
234
235 /* Do interactive option setting, if allowed and <option> depressed */
236 PyMac_InteractiveOptions(&options, argcp, argvp);
237 }
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000238
239 /* Copy selected options to where the machine-independent stuff wants it */
240 Py_VerboseFlag = options.verbose;
241 Py_SuppressPrintingFlag = options.suppress_print;
242 Py_DebugFlag = options.debugging;
Jack Jansene3ae0df1997-06-03 15:28:29 +0000243 if ( options.noargs ) {
244 /* don't process events at all without the scripts permission */
245 PyMacSchedParams scp;
246
247 PyMac_GetSchedParams(&scp);
248 scp.process_events = 0;
249 /* Should we disable command-dot as well? */
250 PyMac_SetSchedParams(&scp);
251 }
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000252
253 /* Set buffering */
254 if (options.unbuffered) {
255#ifndef MPW
256 setbuf(stdout, (char *)NULL);
257 setbuf(stderr, (char *)NULL);
258#else
259 /* On MPW (3.2) unbuffered seems to hang */
260 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
261 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
262#endif
263 }
Jack Jansen8c693211997-01-07 16:19:42 +0000264#if __profile__ == 1
265 /* collectSummary or collectDetailed, timebase, #routines, max stack depth */
266 ProfilerInit(collectSummary, bestTimeBase, 2000, 150);
267#endif
Jack Jansen01fbc681996-02-28 15:42:47 +0000268}
269
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000270/*
271** Inspection mode after script/applet termination
272*/
273static int
274run_inspect()
275{
276 int sts = 0;
277
278 if (options.inspect && isatty((int)fileno(stdin)))
279 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
280 return sts;
281}
Jack Jansen01fbc681996-02-28 15:42:47 +0000282
Jack Jansen696c9581995-08-14 12:33:20 +0000283#ifdef USE_MAC_APPLET_SUPPORT
284/* Applet support */
285
286/* Run a compiled Python Python script from 'PYC ' resource __main__ */
287static int
288run_main_resource()
289{
290 Handle h;
291 long size;
292 PyObject *code;
293 PyObject *result;
294
295 h = GetNamedResource('PYC ', "\p__main__");
296 if (h == NULL) {
297 Alert(NOPYC_ALERT, NULL);
298 return 1;
299 }
300 size = GetResourceSizeOnDisk(h);
301 HLock(h);
302 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
303 HUnlock(h);
304 ReleaseResource(h);
305 if (code == NULL) {
306 PyErr_Print();
307 return 1;
308 }
309 result = PyImport_ExecCodeModule("__main__", code);
310 Py_DECREF(code);
311 if (result == NULL) {
312 PyErr_Print();
313 return 1;
314 }
315 Py_DECREF(result);
316 return 0;
317}
318
319/* Initialization sequence for applets */
320void
321PyMac_InitApplet()
322{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000323 int argc;
324 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000325 int err;
326
Jack Jansen52ac0371997-01-15 15:49:08 +0000327 init_common(&argc, &argv, 0);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000328
Jack Jansen696c9581995-08-14 12:33:20 +0000329 Py_Initialize();
330 PySys_SetArgv(argc, argv);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000331
Jack Jansen696c9581995-08-14 12:33:20 +0000332 err = run_main_resource();
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000333
334 err = (run_inspect() || err);
335
Jack Jansen696c9581995-08-14 12:33:20 +0000336 fflush(stderr);
337 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000338 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000339 /* XXX Should we bother to Py_Exit(sts)? */
340}
341
Jack Jansen52ac0371997-01-15 15:49:08 +0000342/*
343** Hook for embedding python.
344*/
345void
346PyMac_Initialize()
347{
348 int argc;
349 char **argv;
350
351 init_common(&argc, &argv, 1);
352 Py_Initialize();
353 PySys_SetArgv(argc, argv);
354}
355
Jack Jansen696c9581995-08-14 12:33:20 +0000356#endif /* USE_MAC_APPLET_SUPPORT */
357
358/* For normal application */
359void
360PyMac_InitApplication()
361{
362 int argc;
363 char **argv;
364
Jack Jansen52ac0371997-01-15 15:49:08 +0000365 init_common(&argc, &argv, 0);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000366
Jack Jansen696c9581995-08-14 12:33:20 +0000367 if ( argc > 1 ) {
368 /* We're running a script. Attempt to change current directory */
369 char curwd[256], *endp;
370
371 strcpy(curwd, argv[1]);
372 endp = strrchr(curwd, ':');
373 if ( endp && endp > curwd ) {
374 *endp = '\0';
375
376 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000377#ifdef USE_GUSI
378 /* Change MacOS's idea of wd too */
379 PyMac_FixGUSIcd();
380#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000381 }
382 }
383 Py_Main(argc, argv);
384}
385
Jack Jansen696c9581995-08-14 12:33:20 +0000386/* Main program */
387
Jack Jansen76ceece1996-08-19 11:18:24 +0000388static void
Jack Jansen696c9581995-08-14 12:33:20 +0000389Py_Main(argc, argv)
390 int argc;
391 char **argv;
392{
Jack Jansen696c9581995-08-14 12:33:20 +0000393 int sts;
394 char *command = NULL;
395 char *filename = NULL;
396 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000397
Jack Jansen1d2f8631996-08-02 15:16:16 +0000398 orig_argc = argc; /* For Py_GetArgcArgv() */
Jack Jansen696c9581995-08-14 12:33:20 +0000399 orig_argv = argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000400 filename = argv[1];
401
402 if (Py_VerboseFlag ||
403 command == NULL && filename == NULL && isatty((int)fileno(fp)))
404 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000405 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000406
407 if (filename != NULL) {
408 if ((fp = fopen(filename, "r")) == NULL) {
409 fprintf(stderr, "%s: can't open file '%s'\n",
410 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000411 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000412 }
413 }
414
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000415 /* We initialize the menubar here, hoping SIOUX is initialized by now */
Jack Jansen3469e991996-09-06 00:30:45 +0000416 PyMac_InitMenuBar();
417
Jack Jansen696c9581995-08-14 12:33:20 +0000418 Py_Initialize();
419
420 PySys_SetArgv(argc-1, argv+1);
421
422 if (filename == NULL && isatty((int)fileno(fp))) {
423 FILE *fp = fopen(STARTUP, "r");
424 if (fp != NULL) {
425 (void) PyRun_SimpleFile(fp, STARTUP);
426 PyErr_Clear();
427 fclose(fp);
428 }
429 }
430 sts = PyRun_AnyFile(
431 fp, filename == NULL ? "<stdin>" : filename) != 0;
432 if (filename != NULL)
433 fclose(fp);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000434
435 if ( filename != NULL || command != NULL )
436 sts = (run_inspect() || sts);
Jack Jansen696c9581995-08-14 12:33:20 +0000437
438 Py_Exit(sts);
439 /*NOTREACHED*/
440}
441
Jack Jansen0168f271995-10-27 13:32:30 +0000442/*
443** Terminate application
444*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000445void
Jack Jansen0168f271995-10-27 13:32:30 +0000446PyMac_Exit(status)
447 int status;
448{
449 int keep;
Jack Jansen8c693211997-01-07 16:19:42 +0000450
451#if __profile__ == 1
452 ProfilerDump("\pPython Profiler Results");
453 ProfilerTerm();
454#endif
Jack Jansen0168f271995-10-27 13:32:30 +0000455 if ( status )
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000456 keep = options.keep_error;
Jack Jansen0168f271995-10-27 13:32:30 +0000457 else
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000458 keep = options.keep_normal;
Jack Jansen0168f271995-10-27 13:32:30 +0000459
Jack Jansen1e8557a1995-11-10 14:51:26 +0000460#ifdef USE_SIOUX
461 if (keep) {
462 SIOUXSettings.standalone = 1;
463 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000464 SIOUXSetTitle("\p\307terminated\310");
Jack Jansene44545f1997-05-07 15:48:54 +0000465#ifdef USE_MSL
466 /*
467 ** Temporary workaround: autocloseonquit clearing does not
468 ** currently work for the MSL/GUSI combo.
469 */
470 while(getchar() > 0);
471#endif
Jack Jansen1e8557a1995-11-10 14:51:26 +0000472 }
Jack Jansen0168f271995-10-27 13:32:30 +0000473 else
474 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000475#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000476#ifdef THINK_C
477 console_options.pause_atexit = keep;
478#endif
479
480 exit(status);
481}
Jack Jansen696c9581995-08-14 12:33:20 +0000482
483/* Return the program name -- some code out there needs this. */
484
485char *
Jack Jansen1d2f8631996-08-02 15:16:16 +0000486Py_GetProgramName()
Jack Jansen696c9581995-08-14 12:33:20 +0000487{
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000488 return orig_argv[0];
Jack Jansen696c9581995-08-14 12:33:20 +0000489}
490
Jack Jansena39f1b01997-05-23 15:35:14 +0000491/* The same, but used differently */
492char *
493Py_GetProgramFullPath()
494{
495 return Py_GetProgramName();
496}
497
Jack Jansen696c9581995-08-14 12:33:20 +0000498
499/* Make the *original* argc/argv available to other modules.
500 This is rare, but it is needed by the secureware extension. */
501
502void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000503Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000504 int *argc;
505 char ***argv;
506{
507 *argc = orig_argc;
508 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000509}
Jack Jansen1d2f8631996-08-02 15:16:16 +0000510
511/* More cruft that shouldn't really be here, used in sysmodule.c */
512
513char *
514Py_GetPrefix()
515{
516 return "";
517}
518
519char *
520Py_GetExecPrefix()
521{
522 return "";
523}