blob: b4648726dd1a301e8401062290bf6549f15205a5 [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 Jansen7d5f9e81996-09-07 17:09:31 +000063/* #define OBSOLETE_ARGCARGV 1 /* I think this is not needed anymore... */
Jack Jansen696c9581995-08-14 12:33:20 +000064
Jack Jansen7d5f9e81996-09-07 17:09:31 +000065#ifdef OBSOLETE_ARGCARGV
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;
Jack Jansen7d5f9e81996-09-07 17:09:31 +000069#endif
Jack Jansen696c9581995-08-14 12:33:20 +000070
Jack Jansen7d5f9e81996-09-07 17:09:31 +000071PyMac_PrefRecord options;
Jack Jansen0168f271995-10-27 13:32:30 +000072
Jack Jansen76ceece1996-08-19 11:18:24 +000073static void Py_Main Py_PROTO((int, char **)); /* Forward */
74void PyMac_Exit Py_PROTO((int)); /* Forward */
75
Jack Jansen01fbc681996-02-28 15:42:47 +000076/* Initialize the Mac toolbox world */
77
78static void
79init_mac_world()
80{
81#ifdef THINK_C
82 printf("\n");
83#else
84 MaxApplZone();
85 InitGraf(&qd.thePort);
86 InitFonts();
87 InitWindows();
88 TEInit();
89 InitDialogs((long)0);
90 InitMenus();
91 InitCursor();
92#endif
93}
94
Jack Jansen7d5f9e81996-09-07 17:09:31 +000095/*
96** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
97*/
Jack Jansen01fbc681996-02-28 15:42:47 +000098static void
Jack Jansen7d5f9e81996-09-07 17:09:31 +000099PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
100{
101 KeyMap rmap;
102 unsigned char *map;
103 short item, type;
104 ControlHandle handle;
105 DialogPtr dialog;
106 Rect rect;
107 int old_argc = *argcp;
108 int i;
109
110 /*
111 ** If the preferences disallows interactive options we return,
112 ** similarly of <option> isn't pressed.
113 */
114 if (p->nointopt) return;
115
116 GetKeys(rmap);
117 map = (unsigned char *)rmap;
118 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
119 return;
120
121 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
122 if ( dialog == NULL ) {
123 printf("Option dialog not found - cannot set options\n");
124 return;
125 }
126 SetDialogDefaultItem(dialog, OPT_OK);
127 SetDialogCancelItem(dialog, OPT_CANCEL);
128
129 /* Set default values */
130#define SET_OPT_ITEM(num, var) \
131 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
132 SetCtlValue(handle, (short)p->var);
133
134 SET_OPT_ITEM(OPT_INSPECT, inspect);
135 SET_OPT_ITEM(OPT_VERBOSE, verbose);
136 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
137 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
138 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
139 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
140 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
141 /* The rest are not settable interactively */
142
143#undef SET_OPT_ITEM
144
145 while (1) {
146 handle = NULL;
147 ModalDialog(NULL, &item);
148 if ( item == OPT_OK )
149 break;
150 if ( item == OPT_CANCEL ) {
151 DisposDialog(dialog);
152 exit(0);
153 }
154 if ( item == OPT_CMDLINE ) {
155 int new_argc, newer_argc;
156 char **new_argv, **newer_argv;
157
158 new_argc = ccommand(&new_argv);
159 newer_argc = (new_argc-1) + old_argc;
160 newer_argv = malloc((newer_argc+1)*sizeof(char *));
161 if( !newer_argv )
162 Py_FatalError("Cannot malloc argv\n");
163 for(i=0; i<old_argc; i++)
164 newer_argv[i] = (*argvp)[i];
165 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
166 newer_argv[i] = new_argv[i-old_argc+1];
167 *argvp = newer_argv;
168 *argcp = newer_argc;
169
170 /* XXXX Is it not safe to use free() here, apparently */
171 }
172#define OPT_ITEM(num, var) \
173 if ( item == (num) ) { \
174 p->var = !p->var; \
175 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
176 SetCtlValue(handle, (short)p->var); \
177 }
178
179 OPT_ITEM(OPT_INSPECT, inspect);
180 OPT_ITEM(OPT_VERBOSE, verbose);
181 OPT_ITEM(OPT_SUPPRESS, suppress_print);
182 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
183 OPT_ITEM(OPT_DEBUGGING, debugging);
184 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
185 OPT_ITEM(OPT_KEEPERROR, keep_error);
186
187#undef OPT_ITEM
188 }
189 DisposDialog(dialog);
190}
191
192/*
193** Initialization code, shared by interpreter and applets
194*/
195static void
196init_common(int *argcp, char ***argvp)
Jack Jansen01fbc681996-02-28 15:42:47 +0000197{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000198 /* Remember resource fork refnum, for later */
199 PyMac_AppRefNum = CurResFile();
200
Jack Jansen01fbc681996-02-28 15:42:47 +0000201 /* Initialize toolboxes */
202 init_mac_world();
203
204#ifdef USE_MAC_SHARED_LIBRARY
205 /* Add the shared library to the stack of resource files */
206 PyMac_AddLibResources();
207#endif
208
209#if defined(USE_GUSI)
210 /* Setup GUSI */
211 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000212 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000213 PyMac_SetGUSIOptions();
Jack Jansen01fbc681996-02-28 15:42:47 +0000214#endif
215
216#ifdef USE_SIOUX
217 /* Set various SIOUX flags. Some are changed later based on options */
218 SIOUXSettings.asktosaveonclose = 0;
219 SIOUXSettings.showstatusline = 0;
220 SIOUXSettings.tabspaces = 4;
221#endif
222
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000223 /* Get options from preference file (or from applet resource fork) */
224 options.keep_error = 1; /* default-default */
225 PyMac_PreferenceOptions(&options);
226
227 /* Create argc/argv. Do it before we go into the options event loop. */
228 *argcp = PyMac_GetArgv(argvp, options.noargs);
229
230 /* Do interactive option setting, if allowed and <option> depressed */
231 PyMac_InteractiveOptions(&options, argcp, argvp);
232
233 /* Copy selected options to where the machine-independent stuff wants it */
234 Py_VerboseFlag = options.verbose;
235 Py_SuppressPrintingFlag = options.suppress_print;
236 Py_DebugFlag = options.debugging;
237 if ( options.noargs )
238 PyMac_DoYieldEnabled = 0;
239
240 /* Set buffering */
241 if (options.unbuffered) {
242#ifndef MPW
243 setbuf(stdout, (char *)NULL);
244 setbuf(stderr, (char *)NULL);
245#else
246 /* On MPW (3.2) unbuffered seems to hang */
247 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
248 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
249#endif
250 }
Jack Jansen01fbc681996-02-28 15:42:47 +0000251}
252
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000253/*
254** Inspection mode after script/applet termination
255*/
256static int
257run_inspect()
258{
259 int sts = 0;
260
261 if (options.inspect && isatty((int)fileno(stdin)))
262 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
263 return sts;
264}
Jack Jansen01fbc681996-02-28 15:42:47 +0000265
Jack Jansen696c9581995-08-14 12:33:20 +0000266#ifdef USE_MAC_APPLET_SUPPORT
267/* Applet support */
268
269/* Run a compiled Python Python script from 'PYC ' resource __main__ */
270static int
271run_main_resource()
272{
273 Handle h;
274 long size;
275 PyObject *code;
276 PyObject *result;
277
278 h = GetNamedResource('PYC ', "\p__main__");
279 if (h == NULL) {
280 Alert(NOPYC_ALERT, NULL);
281 return 1;
282 }
283 size = GetResourceSizeOnDisk(h);
284 HLock(h);
285 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
286 HUnlock(h);
287 ReleaseResource(h);
288 if (code == NULL) {
289 PyErr_Print();
290 return 1;
291 }
292 result = PyImport_ExecCodeModule("__main__", code);
293 Py_DECREF(code);
294 if (result == NULL) {
295 PyErr_Print();
296 return 1;
297 }
298 Py_DECREF(result);
299 return 0;
300}
301
302/* Initialization sequence for applets */
303void
304PyMac_InitApplet()
305{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000306 int argc;
307 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000308 int err;
309
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000310 init_common(&argc, &argv);
311
Jack Jansen696c9581995-08-14 12:33:20 +0000312 Py_Initialize();
313 PySys_SetArgv(argc, argv);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000314
Jack Jansen696c9581995-08-14 12:33:20 +0000315 err = run_main_resource();
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000316
317 err = (run_inspect() || err);
318
Jack Jansen696c9581995-08-14 12:33:20 +0000319 fflush(stderr);
320 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000321 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000322 /* XXX Should we bother to Py_Exit(sts)? */
323}
324
325#endif /* USE_MAC_APPLET_SUPPORT */
326
327/* For normal application */
328void
329PyMac_InitApplication()
330{
331 int argc;
332 char **argv;
333
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000334 init_common(&argc, &argv);
335
Jack Jansen696c9581995-08-14 12:33:20 +0000336 if ( argc > 1 ) {
337 /* We're running a script. Attempt to change current directory */
338 char curwd[256], *endp;
339
340 strcpy(curwd, argv[1]);
341 endp = strrchr(curwd, ':');
342 if ( endp && endp > curwd ) {
343 *endp = '\0';
344
345 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000346#ifdef USE_GUSI
347 /* Change MacOS's idea of wd too */
348 PyMac_FixGUSIcd();
349#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000350 }
351 }
352 Py_Main(argc, argv);
353}
354
Jack Jansen696c9581995-08-14 12:33:20 +0000355/* Main program */
356
Jack Jansen76ceece1996-08-19 11:18:24 +0000357static void
Jack Jansen696c9581995-08-14 12:33:20 +0000358Py_Main(argc, argv)
359 int argc;
360 char **argv;
361{
Jack Jansen696c9581995-08-14 12:33:20 +0000362 int sts;
363 char *command = NULL;
364 char *filename = NULL;
365 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000366
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000367#ifdef OBSOLETE_ARGCARGV
Jack Jansen1d2f8631996-08-02 15:16:16 +0000368 orig_argc = argc; /* For Py_GetArgcArgv() */
Jack Jansen696c9581995-08-14 12:33:20 +0000369 orig_argv = argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000370#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000371 filename = argv[1];
372
373 if (Py_VerboseFlag ||
374 command == NULL && filename == NULL && isatty((int)fileno(fp)))
375 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000376 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000377
378 if (filename != NULL) {
379 if ((fp = fopen(filename, "r")) == NULL) {
380 fprintf(stderr, "%s: can't open file '%s'\n",
381 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000382 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000383 }
384 }
385
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000386 /* We initialize the menubar here, hoping SIOUX is initialized by now */
Jack Jansen3469e991996-09-06 00:30:45 +0000387 PyMac_InitMenuBar();
388
Jack Jansen696c9581995-08-14 12:33:20 +0000389 Py_Initialize();
390
391 PySys_SetArgv(argc-1, argv+1);
392
393 if (filename == NULL && isatty((int)fileno(fp))) {
394 FILE *fp = fopen(STARTUP, "r");
395 if (fp != NULL) {
396 (void) PyRun_SimpleFile(fp, STARTUP);
397 PyErr_Clear();
398 fclose(fp);
399 }
400 }
401 sts = PyRun_AnyFile(
402 fp, filename == NULL ? "<stdin>" : filename) != 0;
403 if (filename != NULL)
404 fclose(fp);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000405
406 if ( filename != NULL || command != NULL )
407 sts = (run_inspect() || sts);
Jack Jansen696c9581995-08-14 12:33:20 +0000408
409 Py_Exit(sts);
410 /*NOTREACHED*/
411}
412
Jack Jansen0168f271995-10-27 13:32:30 +0000413/*
414** Terminate application
415*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000416void
Jack Jansen0168f271995-10-27 13:32:30 +0000417PyMac_Exit(status)
418 int status;
419{
420 int keep;
421
422 if ( status )
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000423 keep = options.keep_error;
Jack Jansen0168f271995-10-27 13:32:30 +0000424 else
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000425 keep = options.keep_normal;
Jack Jansen0168f271995-10-27 13:32:30 +0000426
Jack Jansen1e8557a1995-11-10 14:51:26 +0000427#ifdef USE_SIOUX
428 if (keep) {
429 SIOUXSettings.standalone = 1;
430 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000431 SIOUXSetTitle("\p\307terminated\310");
Jack Jansen1e8557a1995-11-10 14:51:26 +0000432 }
Jack Jansen0168f271995-10-27 13:32:30 +0000433 else
434 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000435#ifdef USE_GUSI
436 /*
437 ** Workaround for Sioux/GUSI combo: we should not call
438 ** SiouxHandleOneEvent after the window is closed
439 */
440 PyMac_ConsoleIsDead = 1;
441#endif /* USE_GUSI */
442#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000443#ifdef THINK_C
444 console_options.pause_atexit = keep;
445#endif
446
447 exit(status);
448}
Jack Jansen696c9581995-08-14 12:33:20 +0000449
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000450#ifdef OBSOLETE_ARGCARGV
Jack Jansen696c9581995-08-14 12:33:20 +0000451/* Return the program name -- some code out there needs this. */
452
453char *
Jack Jansen1d2f8631996-08-02 15:16:16 +0000454Py_GetProgramName()
Jack Jansen696c9581995-08-14 12:33:20 +0000455{
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000456 return orig_argv[0];
Jack Jansen696c9581995-08-14 12:33:20 +0000457}
458
459
460/* Make the *original* argc/argv available to other modules.
461 This is rare, but it is needed by the secureware extension. */
462
463void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000464Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000465 int *argc;
466 char ***argv;
467{
468 *argc = orig_argc;
469 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000470}
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000471#endif /* OBSOLETE_ARGCARGV */
Jack Jansen1d2f8631996-08-02 15:16:16 +0000472
473/* More cruft that shouldn't really be here, used in sysmodule.c */
474
475char *
476Py_GetPrefix()
477{
478 return "";
479}
480
481char *
482Py_GetExecPrefix()
483{
484 return "";
485}