blob: 80918fd6db07d0bcdf40e587baeac83b083ea329 [file] [log] [blame]
Jack Jansen42218ce1997-01-31 16:15:11 +00001/***********************************************************
2Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
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 or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
Jack Jansen12fce3e1995-08-14 12:31:44 +000032#include "Python.h"
33#include "osdefs.h"
Jack Jansen3f7d2b41996-09-06 22:21:07 +000034#include "macglue.h"
Jack Jansen12fce3e1995-08-14 12:31:44 +000035#include "pythonresources.h"
36
37
38/* Return the initial python search path. This is called once from
39** initsys() to initialize sys.path.
40**
41** If USE_BUILTIN_PATH is defined the path defined here is used
42** (after prepending the python home dir to each item).
43** If it is not defined the path is gotten from a resource in the
44** Preferences file.
45**
46** XXXX This code needs cleaning up. The routines here have moved
47** around quite a bit, and they're pretty messy for that reason.
48*/
49
50#include <Files.h>
51#include <Aliases.h>
52#include <Folders.h>
53#include <Resources.h>
54#include <TextUtils.h>
Jack Jansenb39be211995-09-01 11:48:10 +000055#include <Dialogs.h>
Jack Jansen12fce3e1995-08-14 12:31:44 +000056
Jack Jansen3f7d2b41996-09-06 22:21:07 +000057#ifdef USE_GUSI
58#include <GUSI.h>
59#endif
60
Jack Jansen12fce3e1995-08-14 12:31:44 +000061#define PYTHONPATH "\
62:\n\
63:Lib\n\
64:Lib:stdwin\n\
65:Lib:test\n\
66:Lib:mac"
67
Jack Jansen83c74df1996-10-22 15:25:42 +000068static void
69getpreffilefss(FSSpec *fssp)
70{
71 static int diditbefore=0;
72 static FSSpec fss;
73 short prefdirRefNum;
74 long prefdirDirID;
75 Handle namehandle;
76
77 if ( !diditbefore ) {
78 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
79 &prefdirDirID) != noErr ) {
80 /* Something wrong with preferences folder */
81 (void)StopAlert(NOPREFDIR_ID, NULL);
82 exit(1);
83 }
84
85 if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) {
86 (void)StopAlert(NOPREFNAME_ID, NULL);
87 exit(1);
88 }
89
90 HLock(namehandle);
91 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, (unsigned char *)*namehandle, &fss);
92 HUnlock(namehandle);
93 ReleaseResource(namehandle);
94 diditbefore = 1;
95 }
96 *fssp = fss;
97}
Jack Jansen12fce3e1995-08-14 12:31:44 +000098
99char *
Jack Jansena547dca1996-07-10 15:48:25 +0000100Py_GetPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000101{
102 /* Modified by Jack to do something a bit more sensible:
103 ** - Prepend the python home-directory (which is obtained from a Preferences
104 ** resource)
105 ** - Add :
106 */
107 static char *pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000108 char *p, *endp;
109 int newlen;
Jack Jansen83c74df1996-10-22 15:25:42 +0000110 char *curwd;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000111#ifndef USE_BUILTIN_PATH
Jack Jansen01fbc681996-02-28 15:42:47 +0000112 staticforward char *PyMac_GetPythonPath();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000113#endif
114
115 if ( pythonpath ) return pythonpath;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000116#ifndef USE_BUILTIN_PATH
Jack Jansen83c74df1996-10-22 15:25:42 +0000117 if ( pythonpath = PyMac_GetPythonPath() )
Jack Jansen12fce3e1995-08-14 12:31:44 +0000118 return pythonpath;
119 printf("Warning: No pythonpath resource found, using builtin default\n");
120#endif
Jack Jansen83c74df1996-10-22 15:25:42 +0000121 curwd = PyMac_GetPythonDir();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000122 p = PYTHONPATH;
123 endp = p;
124 pythonpath = malloc(2);
125 if ( pythonpath == NULL ) return PYTHONPATH;
126 strcpy(pythonpath, ":");
127 while (*endp) {
128 endp = strchr(p, '\n');
129 if ( endp == NULL )
130 endp = p + strlen(p);
131 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
132 pythonpath = realloc(pythonpath, newlen+1);
133 if ( pythonpath == NULL ) return PYTHONPATH;
134 strcat(pythonpath, "\n");
135 if ( *p == ':' ) {
136 p++;
137 strcat(pythonpath, curwd);
138 strncat(pythonpath, p, (endp-p));
139 newlen--; /* Ok, ok, we've allocated one byte too much */
140 } else {
141 /* We've allocated too much in this case */
142 newlen -= strlen(curwd);
143 pythonpath = realloc(pythonpath, newlen+1);
144 if ( pythonpath == NULL ) return PYTHONPATH;
145 strncat(pythonpath, p, (endp-p));
146 }
147 pythonpath[newlen] = '\0';
148 p = endp + 1;
149 }
150 return pythonpath;
151}
152
Jack Jansen83c74df1996-10-22 15:25:42 +0000153
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000154/*
155** Open/create the Python Preferences file, return the handle
156*/
Jack Jansen01fbc681996-02-28 15:42:47 +0000157static short
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000158PyMac_OpenPrefFile()
159{
160 AliasHandle handle;
161 FSSpec dirspec;
162 short prefrh;
Jack Jansenb39be211995-09-01 11:48:10 +0000163 OSErr err;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000164
Jack Jansen83c74df1996-10-22 15:25:42 +0000165 getpreffilefss(&dirspec);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000166 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
167 if ( prefrh < 0 ) {
Jack Jansen83c74df1996-10-22 15:25:42 +0000168#if 0
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000169 action = CautionAlert(NOPREFFILE_ID, NULL);
170 if ( action == NOPREFFILE_NO )
171 exit(1);
Jack Jansen83c74df1996-10-22 15:25:42 +0000172#endif
Jack Jansen532e3c21996-02-21 15:36:26 +0000173 FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000174 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
175 if ( prefrh == -1 ) {
176 /* This "cannot happen":-) */
Jack Jansenb39be211995-09-01 11:48:10 +0000177 printf("Cannot create preferences file, error %d\n", ResError());
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000178 exit(1);
179 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000180 if ( (err=PyMac_init_process_location()) != 0 ) {
181 printf("Cannot get application location, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000182 exit(1);
183 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000184 dirspec = PyMac_ApplicationFSSpec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000185 dirspec.name[0] = 0;
Jack Jansenb39be211995-09-01 11:48:10 +0000186 if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) {
187 printf("Cannot make alias to application directory, error %d\n", err);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000188 exit(1);
189 }
190 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
191 UpdateResFile(prefrh);
192
193 } else {
194 UseResFile(prefrh);
195 }
196 return prefrh;
197}
Jack Jansen12fce3e1995-08-14 12:31:44 +0000198
199/*
200** Return the name of the Python directory
201*/
Jack Jansen5b3c9711997-09-08 13:22:49 +0000202char *
Jack Jansen12fce3e1995-08-14 12:31:44 +0000203PyMac_GetPythonDir()
204{
Jack Jansen83c74df1996-10-22 15:25:42 +0000205 static int diditbefore = 0;
206 static char name[256] = {':', '\0'};
Jack Jansen12fce3e1995-08-14 12:31:44 +0000207 AliasHandle handle;
208 FSSpec dirspec;
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000209 Boolean modified = 0;
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000210 short oldrh, prefrh = -1, homerh;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000211
Jack Jansen83c74df1996-10-22 15:25:42 +0000212 if ( diditbefore )
213 return name;
214
Jack Jansen12fce3e1995-08-14 12:31:44 +0000215 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000216
217 /* First look for an override in the application file */
218 UseResFile(PyMac_AppRefNum);
219 handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID);
Jack Jansen0072b8d1998-05-07 13:08:58 +0000220 UseResFile(oldrh);
Jack Jansena486a551996-04-04 15:39:18 +0000221 if ( handle != NULL ) {
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000222 homerh = PyMac_AppRefNum;
223 } else {
224 /* Try to open preferences file in the preferences folder. */
Jack Jansena486a551996-04-04 15:39:18 +0000225 prefrh = PyMac_OpenPrefFile();
Jack Jansena486a551996-04-04 15:39:18 +0000226 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
227 if ( handle == NULL ) {
228 (void)StopAlert(BADPREFFILE_ID, NULL);
Jack Jansen83c74df1996-10-22 15:25:42 +0000229 diditbefore=1;
230 return ":";
Jack Jansena486a551996-04-04 15:39:18 +0000231 }
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000232 homerh = prefrh;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000233 }
Jack Jansen0072b8d1998-05-07 13:08:58 +0000234 /* It exists. Resolve it (possibly updating it) */
235 if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000236 (void)StopAlert(BADPREFFILE_ID, NULL);
Jack Jansen83c74df1996-10-22 15:25:42 +0000237 diditbefore=1;
238 return ":";
Jack Jansen12fce3e1995-08-14 12:31:44 +0000239 }
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000240 if ( modified ) {
241 ChangedResource((Handle)handle);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000242 UpdateResFile(homerh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000243 }
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000244 if ( prefrh != -1 ) CloseResFile(prefrh);
245 UseResFile(oldrh);
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000246
Jack Jansen26ee1261996-11-09 18:45:18 +0000247 if ( PyMac_GetFullPath(&dirspec, name) == 0 ) {
Jack Jansen41fa7ea1995-08-31 13:59:36 +0000248 strcat(name, ":");
249 } else {
250 /* If all fails, we return the current directory */
251 printf("Python home dir exists but I cannot find the pathname!!\n");
Jack Jansen12fce3e1995-08-14 12:31:44 +0000252 name[0] = 0;
253 (void)getwd(name);
254 }
Jack Jansen83c74df1996-10-22 15:25:42 +0000255 diditbefore = 1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000256 return name;
257}
258
259#ifndef USE_BUILTIN_PATH
Jack Jansen5b3c9711997-09-08 13:22:49 +0000260char *
Jack Jansen83c74df1996-10-22 15:25:42 +0000261PyMac_GetPythonPath()
Jack Jansen12fce3e1995-08-14 12:31:44 +0000262{
Jack Jansen12fce3e1995-08-14 12:31:44 +0000263 short oldrh, prefrh = -1;
Jack Jansen12fce3e1995-08-14 12:31:44 +0000264 char *rv;
265 int i, newlen;
266 Str255 pathitem;
Jack Jansena486a551996-04-04 15:39:18 +0000267 int resource_id;
268 OSErr err;
Jack Jansenf12e7091996-09-05 15:19:24 +0000269 Handle h;
270
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000271 oldrh = CurResFile();
Jack Jansenf12e7091996-09-05 15:19:24 +0000272 /*
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000273 ** This is a bit tricky. We check here whether the application file
Jack Jansenf12e7091996-09-05 15:19:24 +0000274 ** contains an override. This is to forestall us finding another STR# resource
275 ** with "our" id and using that for path initialization
276 */
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000277 UseResFile(PyMac_AppRefNum);
Jack Jansenf12e7091996-09-05 15:19:24 +0000278 SetResLoad(0);
279 if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) {
280 ReleaseResource(h);
281 resource_id = PYTHONPATHOVERRIDE_ID;
282 } else {
283 resource_id = PYTHONPATH_ID;
284 }
285 SetResLoad(1);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000286 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000287
Jack Jansen83c74df1996-10-22 15:25:42 +0000288 /* Open the preferences file only if there is no override */
289 if ( resource_id != PYTHONPATHOVERRIDE_ID )
290 prefrh = PyMac_OpenPrefFile();
Jack Jansen12fce3e1995-08-14 12:31:44 +0000291 /* At this point, we may or may not have the preferences file open, and it
292 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
293 ** exist we use the one from the application (the default).
294 ** We put an initial '\n' in front of the path that we don't return to the caller
295 */
296 if( (rv = malloc(2)) == NULL )
297 goto out;
298 strcpy(rv, "\n");
Jack Jansenf12e7091996-09-05 15:19:24 +0000299
Jack Jansen12fce3e1995-08-14 12:31:44 +0000300 for(i=1; ; i++) {
Jack Jansena486a551996-04-04 15:39:18 +0000301 GetIndString(pathitem, resource_id, i);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000302 if( pathitem[0] == 0 )
303 break;
304 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
305 /* We have to put the directory in place */
Jack Jansen83c74df1996-10-22 15:25:42 +0000306 char *dir = PyMac_GetPythonDir();
307
Jack Jansen12fce3e1995-08-14 12:31:44 +0000308 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
309 if( (rv=realloc(rv, newlen)) == NULL)
310 goto out;
311 strcat(rv, dir);
312 /* Skip a colon at the beginning of the item */
313 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
314 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
315 newlen--;
316 } else {
317 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
318 }
319 rv[newlen-2] = '\n';
320 rv[newlen-1] = 0;
Jack Jansena486a551996-04-04 15:39:18 +0000321 } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) {
322 /* This is the application itself */
Jack Jansena486a551996-04-04 15:39:18 +0000323
Jack Jansen26ee1261996-11-09 18:45:18 +0000324 if ( (err=PyMac_init_process_location()) != 0 ) {
325 printf("Cannot get application location, error %d\n", err);
Jack Jansena486a551996-04-04 15:39:18 +0000326 exit(1);
327 }
Jack Jansen26ee1261996-11-09 18:45:18 +0000328
329 newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2;
Jack Jansena486a551996-04-04 15:39:18 +0000330 if( (rv=realloc(rv, newlen)) == NULL)
331 goto out;
Jack Jansen26ee1261996-11-09 18:45:18 +0000332 strcpy(rv+strlen(rv), PyMac_ApplicationPath);
Jack Jansena486a551996-04-04 15:39:18 +0000333 rv[newlen-2] = '\n';
334 rv[newlen-1] = 0;
335
Jack Jansen12fce3e1995-08-14 12:31:44 +0000336 } else {
337 /* Use as-is */
338 newlen = strlen(rv) + (pathitem[0]) + 2;
339 if( (rv=realloc(rv, newlen)) == NULL)
340 goto out;
341 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
342 rv[newlen-2] = '\n';
343 rv[newlen-1] = 0;
344 }
345 }
346 if( strlen(rv) == 1) {
347 free(rv);
348 rv = NULL;
349 }
350 if ( rv ) {
351 rv[strlen(rv)-1] = 0;
352 rv++;
353 }
354out:
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000355 if ( prefrh != -1) CloseResFile(prefrh);
356 UseResFile(oldrh);
Jack Jansen12fce3e1995-08-14 12:31:44 +0000357 return rv;
358}
359#endif /* !USE_BUILTIN_PATH */
360
Jack Jansena4b7e141996-02-21 16:46:57 +0000361void
Jack Jansen7d5f9e81996-09-07 17:09:31 +0000362PyMac_PreferenceOptions(PyMac_PrefRecord *pr)
Jack Jansena4b7e141996-02-21 16:46:57 +0000363{
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000364 short oldrh, prefrh = -1;
Jack Jansena4b7e141996-02-21 16:46:57 +0000365 Handle handle;
366 int size;
Jack Jansen5b3c9711997-09-08 13:22:49 +0000367 PyMac_PrefRecord *p;
368 int action;
Jack Jansena4b7e141996-02-21 16:46:57 +0000369
370
371 oldrh = CurResFile();
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000372
373 /* Attempt to load overrides from application */
374 UseResFile(PyMac_AppRefNum);
375 handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID);
376 UseResFile(oldrh);
377
378 /* Otherwise get options from prefs file or any other open resource file */
379 if ( handle == NULL ) {
380 prefrh = PyMac_OpenPrefFile();
Jack Jansena486a551996-04-04 15:39:18 +0000381 handle = GetResource('Popt', PYTHONOPTIONS_ID);
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000382 }
Jack Jansena4b7e141996-02-21 16:46:57 +0000383 if ( handle == NULL ) {
384 return;
385 }
386 HLock(handle);
387 size = GetHandleSize(handle);
Jack Jansen5b3c9711997-09-08 13:22:49 +0000388 p = (PyMac_PrefRecord *)*handle;
389 if ( p->version == POPT_VERSION_CURRENT && size == sizeof(PyMac_PrefRecord) ) {
390 *pr = *p;
391 } else {
392 action = CautionAlert(BADPREFERENCES_ID, NULL);
393 if ( action == BADPREF_DELETE ) {
394 OSErr err;
395
396 RemoveResource(handle);
397 if ( (err=ResError()) ) printf("RemoveResource: %d\n", err);
398 if ( prefrh != -1 ) {
399 UpdateResFile(prefrh);
400 if ( (err=ResError()) ) printf("UpdateResFile: %d\n", err);
401 }
402 } else if ( action == BADPREF_QUIT )
403 exit(1);
404 }
Jack Jansena4b7e141996-02-21 16:46:57 +0000405 HUnlock(handle);
406
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000407 if ( prefrh != -1) CloseResFile(prefrh);
Jack Jansena4b7e141996-02-21 16:46:57 +0000408 UseResFile(oldrh);
409}
Jack Jansen3f7d2b41996-09-06 22:21:07 +0000410
411#ifdef USE_GUSI
412void
413PyMac_SetGUSIOptions()
414{
415 Handle h;
416 short oldrh, prefrh = -1;
417
418 oldrh = CurResFile();
419
420 /* Try override from the application resource fork */
421 UseResFile(PyMac_AppRefNum);
422 h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID);
423 UseResFile(oldrh);
424
425 /* If that didn't work try nonoverride from anywhere */
426 if ( h == NULL ) {
427 prefrh = PyMac_OpenPrefFile();
428 h = GetResource('GU\267I', GUSIOPTIONS_ID);
429 }
430 if ( h ) GUSILoadConfiguration(h);
431 if ( prefrh != -1) CloseResFile(prefrh);
432 UseResFile(oldrh);
433}
434#endif /* USE_GUSI */