blob: dc14e7ccd3981adf309760e0bf1da2812a8a7dd9 [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_GetArgcArgv(); set by main() */
Jack Jansen696c9581995-08-14 12:33:20 +000064static char **orig_argv;
65static int orig_argc;
66
Jack Jansen7d5f9e81996-09-07 17:09:31 +000067PyMac_PrefRecord options;
Jack Jansen0168f271995-10-27 13:32:30 +000068
Jack Jansen76ceece1996-08-19 11:18:24 +000069static void Py_Main Py_PROTO((int, char **)); /* Forward */
70void PyMac_Exit Py_PROTO((int)); /* Forward */
71
Jack Jansen01fbc681996-02-28 15:42:47 +000072/* Initialize the Mac toolbox world */
73
74static void
75init_mac_world()
76{
77#ifdef THINK_C
78 printf("\n");
79#else
80 MaxApplZone();
81 InitGraf(&qd.thePort);
82 InitFonts();
83 InitWindows();
84 TEInit();
85 InitDialogs((long)0);
86 InitMenus();
87 InitCursor();
88#endif
89}
90
Jack Jansen7d5f9e81996-09-07 17:09:31 +000091/*
92** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
93*/
Jack Jansen01fbc681996-02-28 15:42:47 +000094static void
Jack Jansen7d5f9e81996-09-07 17:09:31 +000095PyMac_InteractiveOptions(PyMac_PrefRecord *p, int *argcp, char ***argvp)
96{
97 KeyMap rmap;
98 unsigned char *map;
99 short item, type;
100 ControlHandle handle;
101 DialogPtr dialog;
102 Rect rect;
103 int old_argc = *argcp;
104 int i;
105
106 /*
107 ** If the preferences disallows interactive options we return,
108 ** similarly of <option> isn't pressed.
109 */
110 if (p->nointopt) return;
111
112 GetKeys(rmap);
113 map = (unsigned char *)rmap;
114 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
115 return;
116
117 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
118 if ( dialog == NULL ) {
119 printf("Option dialog not found - cannot set options\n");
120 return;
121 }
122 SetDialogDefaultItem(dialog, OPT_OK);
123 SetDialogCancelItem(dialog, OPT_CANCEL);
124
125 /* Set default values */
126#define SET_OPT_ITEM(num, var) \
127 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
128 SetCtlValue(handle, (short)p->var);
129
130 SET_OPT_ITEM(OPT_INSPECT, inspect);
131 SET_OPT_ITEM(OPT_VERBOSE, verbose);
132 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
133 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
134 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
135 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
136 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
137 /* The rest are not settable interactively */
138
139#undef SET_OPT_ITEM
140
141 while (1) {
142 handle = NULL;
143 ModalDialog(NULL, &item);
144 if ( item == OPT_OK )
145 break;
146 if ( item == OPT_CANCEL ) {
147 DisposDialog(dialog);
148 exit(0);
149 }
150 if ( item == OPT_CMDLINE ) {
151 int new_argc, newer_argc;
152 char **new_argv, **newer_argv;
153
154 new_argc = ccommand(&new_argv);
155 newer_argc = (new_argc-1) + old_argc;
156 newer_argv = malloc((newer_argc+1)*sizeof(char *));
157 if( !newer_argv )
158 Py_FatalError("Cannot malloc argv\n");
159 for(i=0; i<old_argc; i++)
160 newer_argv[i] = (*argvp)[i];
161 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
162 newer_argv[i] = new_argv[i-old_argc+1];
163 *argvp = newer_argv;
164 *argcp = newer_argc;
165
166 /* XXXX Is it not safe to use free() here, apparently */
167 }
168#define OPT_ITEM(num, var) \
169 if ( item == (num) ) { \
170 p->var = !p->var; \
171 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
172 SetCtlValue(handle, (short)p->var); \
173 }
174
175 OPT_ITEM(OPT_INSPECT, inspect);
176 OPT_ITEM(OPT_VERBOSE, verbose);
177 OPT_ITEM(OPT_SUPPRESS, suppress_print);
178 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
179 OPT_ITEM(OPT_DEBUGGING, debugging);
180 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
181 OPT_ITEM(OPT_KEEPERROR, keep_error);
182
183#undef OPT_ITEM
184 }
185 DisposDialog(dialog);
186}
187
188/*
189** Initialization code, shared by interpreter and applets
190*/
191static void
192init_common(int *argcp, char ***argvp)
Jack Jansen01fbc681996-02-28 15:42:47 +0000193{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000194 /* Remember resource fork refnum, for later */
195 PyMac_AppRefNum = CurResFile();
196
Jack Jansen01fbc681996-02-28 15:42:47 +0000197 /* Initialize toolboxes */
198 init_mac_world();
199
200#ifdef USE_MAC_SHARED_LIBRARY
201 /* Add the shared library to the stack of resource files */
202 PyMac_AddLibResources();
203#endif
204
205#if defined(USE_GUSI)
206 /* Setup GUSI */
207 GUSIDefaultSetup();
Jack Jansenf6865f71996-09-04 15:24:59 +0000208 PyMac_SetGUSISpin();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000209 PyMac_SetGUSIOptions();
Jack Jansen01fbc681996-02-28 15:42:47 +0000210#endif
211
212#ifdef USE_SIOUX
213 /* Set various SIOUX flags. Some are changed later based on options */
214 SIOUXSettings.asktosaveonclose = 0;
215 SIOUXSettings.showstatusline = 0;
216 SIOUXSettings.tabspaces = 4;
217#endif
218
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000219 /* Get options from preference file (or from applet resource fork) */
220 options.keep_error = 1; /* default-default */
221 PyMac_PreferenceOptions(&options);
222
223 /* Create argc/argv. Do it before we go into the options event loop. */
224 *argcp = PyMac_GetArgv(argvp, options.noargs);
225
226 /* Do interactive option setting, if allowed and <option> depressed */
227 PyMac_InteractiveOptions(&options, argcp, argvp);
228
229 /* Copy selected options to where the machine-independent stuff wants it */
230 Py_VerboseFlag = options.verbose;
231 Py_SuppressPrintingFlag = options.suppress_print;
232 Py_DebugFlag = options.debugging;
233 if ( options.noargs )
234 PyMac_DoYieldEnabled = 0;
235
236 /* Set buffering */
237 if (options.unbuffered) {
238#ifndef MPW
239 setbuf(stdout, (char *)NULL);
240 setbuf(stderr, (char *)NULL);
241#else
242 /* On MPW (3.2) unbuffered seems to hang */
243 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
244 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
245#endif
246 }
Jack Jansen01fbc681996-02-28 15:42:47 +0000247}
248
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000249/*
250** Inspection mode after script/applet termination
251*/
252static int
253run_inspect()
254{
255 int sts = 0;
256
257 if (options.inspect && isatty((int)fileno(stdin)))
258 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
259 return sts;
260}
Jack Jansen01fbc681996-02-28 15:42:47 +0000261
Jack Jansen696c9581995-08-14 12:33:20 +0000262#ifdef USE_MAC_APPLET_SUPPORT
263/* Applet support */
264
265/* Run a compiled Python Python script from 'PYC ' resource __main__ */
266static int
267run_main_resource()
268{
269 Handle h;
270 long size;
271 PyObject *code;
272 PyObject *result;
273
274 h = GetNamedResource('PYC ', "\p__main__");
275 if (h == NULL) {
276 Alert(NOPYC_ALERT, NULL);
277 return 1;
278 }
279 size = GetResourceSizeOnDisk(h);
280 HLock(h);
281 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
282 HUnlock(h);
283 ReleaseResource(h);
284 if (code == NULL) {
285 PyErr_Print();
286 return 1;
287 }
288 result = PyImport_ExecCodeModule("__main__", code);
289 Py_DECREF(code);
290 if (result == NULL) {
291 PyErr_Print();
292 return 1;
293 }
294 Py_DECREF(result);
295 return 0;
296}
297
298/* Initialization sequence for applets */
299void
300PyMac_InitApplet()
301{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000302 int argc;
303 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000304 int err;
305
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000306 init_common(&argc, &argv);
307
Jack Jansen696c9581995-08-14 12:33:20 +0000308 Py_Initialize();
309 PySys_SetArgv(argc, argv);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000310
Jack Jansen696c9581995-08-14 12:33:20 +0000311 err = run_main_resource();
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000312
313 err = (run_inspect() || err);
314
Jack Jansen696c9581995-08-14 12:33:20 +0000315 fflush(stderr);
316 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000317 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000318 /* XXX Should we bother to Py_Exit(sts)? */
319}
320
321#endif /* USE_MAC_APPLET_SUPPORT */
322
323/* For normal application */
324void
325PyMac_InitApplication()
326{
327 int argc;
328 char **argv;
329
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000330 init_common(&argc, &argv);
331
Jack Jansen696c9581995-08-14 12:33:20 +0000332 if ( argc > 1 ) {
333 /* We're running a script. Attempt to change current directory */
334 char curwd[256], *endp;
335
336 strcpy(curwd, argv[1]);
337 endp = strrchr(curwd, ':');
338 if ( endp && endp > curwd ) {
339 *endp = '\0';
340
341 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000342#ifdef USE_GUSI
343 /* Change MacOS's idea of wd too */
344 PyMac_FixGUSIcd();
345#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000346 }
347 }
348 Py_Main(argc, argv);
349}
350
Jack Jansen696c9581995-08-14 12:33:20 +0000351/* Main program */
352
Jack Jansen76ceece1996-08-19 11:18:24 +0000353static void
Jack Jansen696c9581995-08-14 12:33:20 +0000354Py_Main(argc, argv)
355 int argc;
356 char **argv;
357{
Jack Jansen696c9581995-08-14 12:33:20 +0000358 int sts;
359 char *command = NULL;
360 char *filename = NULL;
361 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000362
Jack Jansen1d2f8631996-08-02 15:16:16 +0000363 orig_argc = argc; /* For Py_GetArgcArgv() */
Jack Jansen696c9581995-08-14 12:33:20 +0000364 orig_argv = argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000365 filename = argv[1];
366
367 if (Py_VerboseFlag ||
368 command == NULL && filename == NULL && isatty((int)fileno(fp)))
369 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000370 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000371
372 if (filename != NULL) {
373 if ((fp = fopen(filename, "r")) == NULL) {
374 fprintf(stderr, "%s: can't open file '%s'\n",
375 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000376 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000377 }
378 }
379
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000380 /* We initialize the menubar here, hoping SIOUX is initialized by now */
Jack Jansen3469e991996-09-06 00:30:45 +0000381 PyMac_InitMenuBar();
382
Jack Jansen696c9581995-08-14 12:33:20 +0000383 Py_Initialize();
384
385 PySys_SetArgv(argc-1, argv+1);
386
387 if (filename == NULL && isatty((int)fileno(fp))) {
388 FILE *fp = fopen(STARTUP, "r");
389 if (fp != NULL) {
390 (void) PyRun_SimpleFile(fp, STARTUP);
391 PyErr_Clear();
392 fclose(fp);
393 }
394 }
395 sts = PyRun_AnyFile(
396 fp, filename == NULL ? "<stdin>" : filename) != 0;
397 if (filename != NULL)
398 fclose(fp);
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000399
400 if ( filename != NULL || command != NULL )
401 sts = (run_inspect() || sts);
Jack Jansen696c9581995-08-14 12:33:20 +0000402
403 Py_Exit(sts);
404 /*NOTREACHED*/
405}
406
Jack Jansen0168f271995-10-27 13:32:30 +0000407/*
408** Terminate application
409*/
Jack Jansen76ceece1996-08-19 11:18:24 +0000410void
Jack Jansen0168f271995-10-27 13:32:30 +0000411PyMac_Exit(status)
412 int status;
413{
414 int keep;
415
416 if ( status )
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000417 keep = options.keep_error;
Jack Jansen0168f271995-10-27 13:32:30 +0000418 else
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000419 keep = options.keep_normal;
Jack Jansen0168f271995-10-27 13:32:30 +0000420
Jack Jansen1e8557a1995-11-10 14:51:26 +0000421#ifdef USE_SIOUX
422 if (keep) {
423 SIOUXSettings.standalone = 1;
424 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000425 SIOUXSetTitle("\p\307terminated\310");
Jack Jansen1e8557a1995-11-10 14:51:26 +0000426 }
Jack Jansen0168f271995-10-27 13:32:30 +0000427 else
428 SIOUXSettings.autocloseonquit = 1;
Jack Jansenf6865f71996-09-04 15:24:59 +0000429#ifdef USE_GUSI
430 /*
431 ** Workaround for Sioux/GUSI combo: we should not call
432 ** SiouxHandleOneEvent after the window is closed
433 */
434 PyMac_ConsoleIsDead = 1;
435#endif /* USE_GUSI */
436#endif /* USE_SIOUX */
Jack Jansen0168f271995-10-27 13:32:30 +0000437#ifdef THINK_C
438 console_options.pause_atexit = keep;
439#endif
440
441 exit(status);
442}
Jack Jansen696c9581995-08-14 12:33:20 +0000443
444/* Return the program name -- some code out there needs this. */
445
446char *
Jack Jansen1d2f8631996-08-02 15:16:16 +0000447Py_GetProgramName()
Jack Jansen696c9581995-08-14 12:33:20 +0000448{
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000449 return orig_argv[0];
Jack Jansen696c9581995-08-14 12:33:20 +0000450}
451
452
453/* Make the *original* argc/argv available to other modules.
454 This is rare, but it is needed by the secureware extension. */
455
456void
Jack Jansen1d2f8631996-08-02 15:16:16 +0000457Py_GetArgcArgv(argc,argv)
Jack Jansen696c9581995-08-14 12:33:20 +0000458 int *argc;
459 char ***argv;
460{
461 *argc = orig_argc;
462 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000463}
Jack Jansen1d2f8631996-08-02 15:16:16 +0000464
465/* More cruft that shouldn't really be here, used in sysmodule.c */
466
467char *
468Py_GetPrefix()
469{
470 return "";
471}
472
473char *
474Py_GetExecPrefix()
475{
476 return "";
477}