blob: 00573091a010806b7f002004a0bf7e0be31dc5da [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"
Guido van Rossumb0f3c821994-08-23 13:34:25 +000031
Jack Jansen696c9581995-08-14 12:33:20 +000032#include <Memory.h>
33#include <Resources.h>
Guido van Rossumb0f3c821994-08-23 13:34:25 +000034#include <stdio.h>
Jack Jansen696c9581995-08-14 12:33:20 +000035#include <Events.h>
36#include <Windows.h>
37#include <Desk.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 Jansenc76fd391995-02-02 14:27:31 +000043#endif
44
Jack Jansen0168f271995-10-27 13:32:30 +000045#ifdef THINK_C
46#include <console.h>
47#endif
48
Jack Jansen696c9581995-08-14 12:33:20 +000049#define STARTUP "PythonStartup"
Jack Jansenbac428d1994-12-14 13:47:30 +000050
Jack Jansen696c9581995-08-14 12:33:20 +000051extern int Py_DebugFlag; /* For parser.c, declared in pythonrun.c */
52extern int Py_VerboseFlag; /* For import.c, declared in pythonrun.c */
53extern int Py_SuppressPrintingFlag; /* For ceval.c, declared in pythonrun.c */
54
55
56/* Subroutines that live in their own file */
Jack Jansena547dca1996-07-10 15:48:25 +000057extern char *Py_GetVersion Py_PROTO((void));
58extern char *Py_GetCopyright Py_PROTO((void));
Jack Jansen696c9581995-08-14 12:33:20 +000059
60
61/* For getprogramname(); set by main() */
62static char *argv0;
63
64/* For getargcargv(); set by main() */
65static char **orig_argv;
66static int orig_argc;
67
Jack Jansen0168f271995-10-27 13:32:30 +000068/* Flags indicating whether stdio window should stay open on termination */
69static int keep_normal;
70static int keep_error = 1;
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
91/* Initialization code shared by interpreter and applets */
92
93static void
94init_common()
95{
96
97 /* Initialize toolboxes */
98 init_mac_world();
99
100#ifdef USE_MAC_SHARED_LIBRARY
101 /* Add the shared library to the stack of resource files */
102 PyMac_AddLibResources();
103#endif
104
105#if defined(USE_GUSI)
106 /* Setup GUSI */
107 GUSIDefaultSetup();
108#endif
109
110#ifdef USE_SIOUX
111 /* Set various SIOUX flags. Some are changed later based on options */
112 SIOUXSettings.asktosaveonclose = 0;
113 SIOUXSettings.showstatusline = 0;
114 SIOUXSettings.tabspaces = 4;
115#endif
116
117}
118
119
Jack Jansen696c9581995-08-14 12:33:20 +0000120#ifdef USE_MAC_APPLET_SUPPORT
121/* Applet support */
122
123/* Run a compiled Python Python script from 'PYC ' resource __main__ */
124static int
125run_main_resource()
126{
127 Handle h;
128 long size;
129 PyObject *code;
130 PyObject *result;
131
132 h = GetNamedResource('PYC ', "\p__main__");
133 if (h == NULL) {
134 Alert(NOPYC_ALERT, NULL);
135 return 1;
136 }
137 size = GetResourceSizeOnDisk(h);
138 HLock(h);
139 code = PyMarshal_ReadObjectFromString(*h + 8, (int)(size - 8));
140 HUnlock(h);
141 ReleaseResource(h);
142 if (code == NULL) {
143 PyErr_Print();
144 return 1;
145 }
146 result = PyImport_ExecCodeModule("__main__", code);
147 Py_DECREF(code);
148 if (result == NULL) {
149 PyErr_Print();
150 return 1;
151 }
152 Py_DECREF(result);
153 return 0;
154}
155
156/* Initialization sequence for applets */
157void
158PyMac_InitApplet()
159{
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000160 int argc;
161 char **argv;
Jack Jansen696c9581995-08-14 12:33:20 +0000162 int err;
163
Jack Jansen01fbc681996-02-28 15:42:47 +0000164 init_common();
Jack Jansen696c9581995-08-14 12:33:20 +0000165 argc = PyMac_GetArgv(&argv);
166 Py_Initialize();
167 PySys_SetArgv(argc, argv);
168 err = run_main_resource();
169 fflush(stderr);
170 fflush(stdout);
Jack Jansen0168f271995-10-27 13:32:30 +0000171 PyMac_Exit(err);
Jack Jansen696c9581995-08-14 12:33:20 +0000172 /* XXX Should we bother to Py_Exit(sts)? */
173}
174
175#endif /* USE_MAC_APPLET_SUPPORT */
176
177/* For normal application */
178void
179PyMac_InitApplication()
180{
181 int argc;
182 char **argv;
183
Jack Jansen01fbc681996-02-28 15:42:47 +0000184 init_common();
Jack Jansen696c9581995-08-14 12:33:20 +0000185 argc = PyMac_GetArgv(&argv);
186 if ( argc > 1 ) {
187 /* We're running a script. Attempt to change current directory */
188 char curwd[256], *endp;
189
190 strcpy(curwd, argv[1]);
191 endp = strrchr(curwd, ':');
192 if ( endp && endp > curwd ) {
193 *endp = '\0';
194
195 chdir(curwd);
Jack Jansen378815c1996-03-06 16:21:34 +0000196#ifdef USE_GUSI
197 /* Change MacOS's idea of wd too */
198 PyMac_FixGUSIcd();
199#endif
Jack Jansen696c9581995-08-14 12:33:20 +0000200 }
201 }
202 Py_Main(argc, argv);
203}
204
205/*
206** PyMac_InteractiveOptions - Allow user to set options if option key is pressed
207*/
208void
209PyMac_InteractiveOptions(int *inspect, int *verbose, int *suppress_print,
Jack Jansen0168f271995-10-27 13:32:30 +0000210 int *unbuffered, int *debugging, int *keep_normal,
Jack Jansene355c451996-03-12 13:29:04 +0000211 int *keep_error, int *argcp, char ***argvp)
Jack Jansen696c9581995-08-14 12:33:20 +0000212{
213 KeyMap rmap;
214 unsigned char *map;
215 short item, type;
216 ControlHandle handle;
217 DialogPtr dialog;
218 Rect rect;
Jack Jansene355c451996-03-12 13:29:04 +0000219 int old_argc = *argcp;
220 int i;
Jack Jansen696c9581995-08-14 12:33:20 +0000221
Jack Jansena4b7e141996-02-21 16:46:57 +0000222 /* Default-defaults: */
223 *keep_error = 1;
224 /* Get default settings from our preference file */
Jack Jansen01fbc681996-02-28 15:42:47 +0000225 PyMac_PreferenceOptions(inspect, verbose, suppress_print,
226 unbuffered, debugging, keep_normal, keep_error);
Jack Jansena4b7e141996-02-21 16:46:57 +0000227 /* If option is pressed override these */
Jack Jansen696c9581995-08-14 12:33:20 +0000228 GetKeys(rmap);
229 map = (unsigned char *)rmap;
230 if ( ( map[0x3a>>3] & (1<<(0x3a&7)) ) == 0 ) /* option key is 3a */
231 return;
232
233 dialog = GetNewDialog(OPT_DIALOG, NULL, (WindowPtr)-1);
234 if ( dialog == NULL ) {
235 printf("Option dialog not found - cannot set options\n");
236 return;
237 }
Jack Jansene355c451996-03-12 13:29:04 +0000238 SetDialogDefaultItem(dialog, OPT_OK);
239 SetDialogCancelItem(dialog, OPT_CANCEL);
Jack Jansen0168f271995-10-27 13:32:30 +0000240
Jack Jansena4b7e141996-02-21 16:46:57 +0000241 /* Set default values */
242#define SET_OPT_ITEM(num, var) \
243 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
244 SetCtlValue(handle, (short)*(var));
245
246 SET_OPT_ITEM(OPT_INSPECT, inspect);
247 SET_OPT_ITEM(OPT_VERBOSE, verbose);
248 SET_OPT_ITEM(OPT_SUPPRESS, suppress_print);
249 SET_OPT_ITEM(OPT_UNBUFFERED, unbuffered);
250 SET_OPT_ITEM(OPT_DEBUGGING, debugging);
251 SET_OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
252 SET_OPT_ITEM(OPT_KEEPERROR, keep_error);
253
254#undef SET_OPT_ITEM
Jack Jansen0168f271995-10-27 13:32:30 +0000255
Jack Jansen696c9581995-08-14 12:33:20 +0000256 while (1) {
257 handle = NULL;
258 ModalDialog(NULL, &item);
259 if ( item == OPT_OK )
260 break;
261 if ( item == OPT_CANCEL ) {
262 DisposDialog(dialog);
263 exit(0);
264 }
Jack Jansene355c451996-03-12 13:29:04 +0000265 if ( item == OPT_CMDLINE ) {
266 int new_argc, newer_argc;
267 char **new_argv, **newer_argv;
268
269 new_argc = ccommand(&new_argv);
270 newer_argc = (new_argc-1) + old_argc;
271 newer_argv = malloc((newer_argc+1)*sizeof(char *));
272 if( !newer_argv )
273 Py_FatalError("Cannot malloc argv\n");
274 for(i=0; i<old_argc; i++)
275 newer_argv[i] = (*argvp)[i];
276 for(i=old_argc; i<=newer_argc; i++) /* Copy the NULL too */
277 newer_argv[i] = new_argv[i-old_argc+1];
278 *argvp = newer_argv;
279 *argcp = newer_argc;
280
281 /* XXXX Is it not safe to use free() here, apparently */
282 }
Jack Jansen696c9581995-08-14 12:33:20 +0000283#define OPT_ITEM(num, var) \
284 if ( item == (num) ) { \
285 *(var) = !*(var); \
286 GetDialogItem(dialog, (num), &type, (Handle *)&handle, &rect); \
287 SetCtlValue(handle, (short)*(var)); \
288 }
289
290 OPT_ITEM(OPT_INSPECT, inspect);
291 OPT_ITEM(OPT_VERBOSE, verbose);
292 OPT_ITEM(OPT_SUPPRESS, suppress_print);
293 OPT_ITEM(OPT_UNBUFFERED, unbuffered);
294 OPT_ITEM(OPT_DEBUGGING, debugging);
Jack Jansen0168f271995-10-27 13:32:30 +0000295 OPT_ITEM(OPT_KEEPNORMAL, keep_normal);
296 OPT_ITEM(OPT_KEEPERROR, keep_error);
Jack Jansen696c9581995-08-14 12:33:20 +0000297
298#undef OPT_ITEM
299 }
300 DisposDialog(dialog);
301}
302/* Main program */
303
304int
305Py_Main(argc, argv)
306 int argc;
307 char **argv;
308{
Jack Jansen696c9581995-08-14 12:33:20 +0000309 int sts;
310 char *command = NULL;
311 char *filename = NULL;
312 FILE *fp = stdin;
Jack Jansen696c9581995-08-14 12:33:20 +0000313 int inspect = 0;
314 int unbuffered = 0;
315
Jack Jansene355c451996-03-12 13:29:04 +0000316 PyMac_InteractiveOptions(&inspect, &Py_VerboseFlag, &Py_SuppressPrintingFlag,
317 &unbuffered, &Py_DebugFlag, &keep_normal, &keep_error, &argc, &argv);
318
Jack Jansen696c9581995-08-14 12:33:20 +0000319 orig_argc = argc; /* For getargcargv() */
320 orig_argv = argv;
321 argv0 = argv[0]; /* For getprogramname() */
Jack Jansen696c9581995-08-14 12:33:20 +0000322
323 if (unbuffered) {
324#ifndef MPW
325 setbuf(stdout, (char *)NULL);
326 setbuf(stderr, (char *)NULL);
327#else
328 /* On MPW (3.2) unbuffered seems to hang */
329 setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
330 setvbuf(stderr, (char *)NULL, _IOLBF, BUFSIZ);
331#endif
332 }
333
334 filename = argv[1];
335
336 if (Py_VerboseFlag ||
337 command == NULL && filename == NULL && isatty((int)fileno(fp)))
338 fprintf(stderr, "Python %s\n%s\n",
Jack Jansena547dca1996-07-10 15:48:25 +0000339 Py_GetVersion(), Py_GetCopyright());
Jack Jansen696c9581995-08-14 12:33:20 +0000340
341 if (filename != NULL) {
342 if ((fp = fopen(filename, "r")) == NULL) {
343 fprintf(stderr, "%s: can't open file '%s'\n",
344 argv[0], filename);
Jack Jansen0168f271995-10-27 13:32:30 +0000345 PyMac_Exit(2);
Jack Jansen696c9581995-08-14 12:33:20 +0000346 }
347 }
348
349 Py_Initialize();
350
351 PySys_SetArgv(argc-1, argv+1);
352
353 if (filename == NULL && isatty((int)fileno(fp))) {
354 FILE *fp = fopen(STARTUP, "r");
355 if (fp != NULL) {
356 (void) PyRun_SimpleFile(fp, STARTUP);
357 PyErr_Clear();
358 fclose(fp);
359 }
360 }
361 sts = PyRun_AnyFile(
362 fp, filename == NULL ? "<stdin>" : filename) != 0;
363 if (filename != NULL)
364 fclose(fp);
365
366 if (inspect && isatty((int)fileno(stdin)) &&
367 (filename != NULL || command != NULL))
368 sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
369
370 Py_Exit(sts);
371 /*NOTREACHED*/
372}
373
Jack Jansen0168f271995-10-27 13:32:30 +0000374/*
375** Terminate application
376*/
377PyMac_Exit(status)
378 int status;
379{
380 int keep;
381
382 if ( status )
383 keep = keep_error;
384 else
385 keep = keep_normal;
386
Jack Jansen1e8557a1995-11-10 14:51:26 +0000387#ifdef USE_SIOUX
388 if (keep) {
389 SIOUXSettings.standalone = 1;
390 SIOUXSettings.autocloseonquit = 0;
Jack Jansen415571c1996-03-25 15:46:03 +0000391 SIOUXSetTitle("\p\307terminated\310");
Jack Jansen1e8557a1995-11-10 14:51:26 +0000392 }
Jack Jansen0168f271995-10-27 13:32:30 +0000393 else
394 SIOUXSettings.autocloseonquit = 1;
395#endif
396#ifdef THINK_C
397 console_options.pause_atexit = keep;
398#endif
399
400 exit(status);
401}
Jack Jansen696c9581995-08-14 12:33:20 +0000402
403/* Return the program name -- some code out there needs this. */
404
405char *
406getprogramname()
407{
408 return argv0;
409}
410
411
412/* Make the *original* argc/argv available to other modules.
413 This is rare, but it is needed by the secureware extension. */
414
415void
416getargcargv(argc,argv)
417 int *argc;
418 char ***argv;
419{
420 *argc = orig_argc;
421 *argv = orig_argv;
Guido van Rossumb0f3c821994-08-23 13:34:25 +0000422}