blob: 12fcf71e8403a22c4fbe4c0ad7b92a5faf5f300c [file] [log] [blame]
Jack Jansen12fce3e1995-08-14 12:31:44 +00001#include "Python.h"
2#include "osdefs.h"
3
4#include "pythonresources.h"
5
6
7/* Return the initial python search path. This is called once from
8** initsys() to initialize sys.path.
9**
10** If USE_BUILTIN_PATH is defined the path defined here is used
11** (after prepending the python home dir to each item).
12** If it is not defined the path is gotten from a resource in the
13** Preferences file.
14**
15** XXXX This code needs cleaning up. The routines here have moved
16** around quite a bit, and they're pretty messy for that reason.
17*/
18
19#include <Files.h>
20#include <Aliases.h>
21#include <Folders.h>
22#include <Resources.h>
23#include <TextUtils.h>
24
25#define PYTHONPATH "\
26:\n\
27:Lib\n\
28:Lib:stdwin\n\
29:Lib:test\n\
30:Lib:mac"
31
32
33char *
34getpythonpath()
35{
36 /* Modified by Jack to do something a bit more sensible:
37 ** - Prepend the python home-directory (which is obtained from a Preferences
38 ** resource)
39 ** - Add :
40 */
41 static char *pythonpath;
42 char *curwd;
43 char *p, *endp;
44 int newlen;
45 extern char *PyMac_GetPythonDir();
46#ifndef USE_BUILTIN_PATH
47 extern char *PyMac_GetPythonPath();
48#endif
49
50 if ( pythonpath ) return pythonpath;
51 curwd = PyMac_GetPythonDir();
52#ifndef USE_BUILTIN_PATH
53 if ( pythonpath = PyMac_GetPythonPath(curwd) )
54 return pythonpath;
55 printf("Warning: No pythonpath resource found, using builtin default\n");
56#endif
57 p = PYTHONPATH;
58 endp = p;
59 pythonpath = malloc(2);
60 if ( pythonpath == NULL ) return PYTHONPATH;
61 strcpy(pythonpath, ":");
62 while (*endp) {
63 endp = strchr(p, '\n');
64 if ( endp == NULL )
65 endp = p + strlen(p);
66 newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p);
67 pythonpath = realloc(pythonpath, newlen+1);
68 if ( pythonpath == NULL ) return PYTHONPATH;
69 strcat(pythonpath, "\n");
70 if ( *p == ':' ) {
71 p++;
72 strcat(pythonpath, curwd);
73 strncat(pythonpath, p, (endp-p));
74 newlen--; /* Ok, ok, we've allocated one byte too much */
75 } else {
76 /* We've allocated too much in this case */
77 newlen -= strlen(curwd);
78 pythonpath = realloc(pythonpath, newlen+1);
79 if ( pythonpath == NULL ) return PYTHONPATH;
80 strncat(pythonpath, p, (endp-p));
81 }
82 pythonpath[newlen] = '\0';
83 p = endp + 1;
84 }
85 return pythonpath;
86}
87
88
89/*
90** Return the name of the Python directory
91*/
92char *
93PyMac_GetPythonDir()
94{
95 int item;
96 static char name[256];
97 AliasHandle handle;
98 FSSpec dirspec;
99 int ok = 0;
100 Boolean modified = 0, cannotmodify = 0;
101 short oldrh, prefrh;
102 short prefdirRefNum;
103 long prefdirDirID;
104
105 /*
106 ** Remember old resource file and try to open preferences file
107 ** in the preferences folder. If it doesn't exist we try to create
108 ** it. If anything fails here we limp on, but set cannotmodify so
109 ** we don't try to store things later on.
110 */
111 oldrh = CurResFile();
112 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
113 &prefdirDirID) != noErr ) {
114 /* Something wrong with preferences folder */
115 cannotmodify = 1;
116 } else {
117 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython Preferences", &dirspec);
118 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
119 if ( prefrh == -1 ) {
120#ifdef USE_MAC_MODPREFS
121 /* It doesn't exist. Try to create it */
122 FSpCreateResFile(&dirspec, 'PYTH', 'pref', 0);
123 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
124 if ( prefrh == -1 ) {
125 /* This is strange, what should we do now? */
126 cannotmodify = 1;
127 } else {
128 UseResFile(prefrh);
129 }
130#else
131 printf("Error: no Preferences file. Attempting to limp on...\n");
132 name[0] = 0;
133 getwd(name);
134 return name;
135#endif
136 }
137 }
138 /* So, we've opened our preferences file, we hope. Look for the alias */
139 handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID);
140 if ( handle ) {
141 /* It exists. Resolve it (possibly updating it) */
142 if ( ResolveAlias(NULL, handle, &dirspec, &modified) == noErr ) {
143 ok = 1;
144 }
145 }
146 if ( !ok ) {
147#ifdef USE_MAC_MODPREFS
148 /* No luck, so far. ask the user for help */
149 item = Alert(NOPYTHON_ALERT, NULL);
150 if ( item == YES_ITEM ) {
151 /* The user wants to point us to a directory. Let her do so */
152 ok = PyMac_GetDirectory(&dirspec);
153 if ( ok )
154 modified = 1;
155 } else if ( item == CURWD_ITEM ) {
156 /* The user told us the current directory is fine. Build an FSSpec for it */
157 if ( getwd(name) ) {
158 if ( FSMakeFSSpec(0, 0, Pstring(name), &dirspec) == 0 ) {
159 ok = 1;
160 modified = 1;
161 }
162 }
163 }
164 if ( handle ) {
165 /* Set the (old, invalid) alias record to the new data */
166 UpdateAlias(NULL, &dirspec, handle, &modified);
167 }
168#else
169 printf("Error: corrupted Preferences file. Attempting to limp on...\n");
170 name[0] = 0;
171 getwd(name);
172 return name;
173#endif
174 }
175#ifdef USE_MAC_MODPREFS
176 if ( ok && modified && !cannotmodify) {
177 /* We have a new, valid fsspec and we can update the preferences file. Do so. */
178 if ( !handle ) {
179 if (NewAlias(NULL, &dirspec, &handle) == 0 )
180 AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p");
181 } else {
182 ChangedResource((Handle)handle);
183 }
184 UpdateResFile(prefrh);
185 }
186#endif
187 if ( !cannotmodify ) {
188 /* This means we have the resfile open. Close it. */
189 CloseResFile(prefrh);
190 }
191 /* Back to the old resource file */
192 UseResFile(oldrh);
193 /* Now turn the fsspec into a path to give back to our caller */
194 if ( ok ) {
195 ok = (nfullpath(&dirspec, name) == 0);
196 if ( ok ) strcat(name, ":");
197 }
198 if ( !ok ) {
199 /* If all fails, we return the current directory */
200 name[0] = 0;
201 (void)getwd(name);
202 }
203 return name;
204}
205
206#ifndef USE_BUILTIN_PATH
207char *
208PyMac_GetPythonPath(dir)
209char *dir;
210{
211 FSSpec dirspec;
212 short oldrh, prefrh = -1;
213 short prefdirRefNum;
214 long prefdirDirID;
215 char *rv;
216 int i, newlen;
217 Str255 pathitem;
218
219 /*
220 ** Remember old resource file and try to open preferences file
221 ** in the preferences folder.
222 */
223 oldrh = CurResFile();
224 if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum,
225 &prefdirDirID) == noErr ) {
226 (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, "\pPython Preferences", &dirspec);
227 prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm);
228 }
229 /* At this point, we may or may not have the preferences file open, and it
230 ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't
231 ** exist we use the one from the application (the default).
232 ** We put an initial '\n' in front of the path that we don't return to the caller
233 */
234 if( (rv = malloc(2)) == NULL )
235 goto out;
236 strcpy(rv, "\n");
237 for(i=1; ; i++) {
238 GetIndString(pathitem, PYTHONPATH_ID, i);
239 if( pathitem[0] == 0 )
240 break;
241 if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) {
242 /* We have to put the directory in place */
243 newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2;
244 if( (rv=realloc(rv, newlen)) == NULL)
245 goto out;
246 strcat(rv, dir);
247 /* Skip a colon at the beginning of the item */
248 if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) {
249 memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10);
250 newlen--;
251 } else {
252 memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9);
253 }
254 rv[newlen-2] = '\n';
255 rv[newlen-1] = 0;
256 } else {
257 /* Use as-is */
258 newlen = strlen(rv) + (pathitem[0]) + 2;
259 if( (rv=realloc(rv, newlen)) == NULL)
260 goto out;
261 memcpy(rv+strlen(rv), pathitem+1, pathitem[0]);
262 rv[newlen-2] = '\n';
263 rv[newlen-1] = 0;
264 }
265 }
266 if( strlen(rv) == 1) {
267 free(rv);
268 rv = NULL;
269 }
270 if ( rv ) {
271 rv[strlen(rv)-1] = 0;
272 rv++;
273 }
274out:
275 if ( prefrh ) {
276 CloseResFile(prefrh);
277 UseResFile(oldrh);
278 }
279 return rv;
280}
281#endif /* !USE_BUILTIN_PATH */
282