#include "Python.h" #include "osdefs.h" #include "macglue.h" #include "pythonresources.h" /* Return the initial python search path. This is called once from ** initsys() to initialize sys.path. ** ** If USE_BUILTIN_PATH is defined the path defined here is used ** (after prepending the python home dir to each item). ** If it is not defined the path is gotten from a resource in the ** Preferences file. ** ** XXXX This code needs cleaning up. The routines here have moved ** around quite a bit, and they're pretty messy for that reason. */ #include #include #include #include #include #include #ifdef USE_GUSI #include #endif #define PYTHONPATH "\ :\n\ :Lib\n\ :Lib:stdwin\n\ :Lib:test\n\ :Lib:mac" static void getpreffilefss(FSSpec *fssp) { static int diditbefore=0; static FSSpec fss; short prefdirRefNum; long prefdirDirID; Handle namehandle; if ( !diditbefore ) { if ( FindFolder(kOnSystemDisk, 'pref', kDontCreateFolder, &prefdirRefNum, &prefdirDirID) != noErr ) { /* Something wrong with preferences folder */ (void)StopAlert(NOPREFDIR_ID, NULL); exit(1); } if ( (namehandle=GetNamedResource('STR ', PREFFILENAME_NAME)) == NULL ) { (void)StopAlert(NOPREFNAME_ID, NULL); exit(1); } HLock(namehandle); (void)FSMakeFSSpec(prefdirRefNum, prefdirDirID, (unsigned char *)*namehandle, &fss); HUnlock(namehandle); ReleaseResource(namehandle); diditbefore = 1; } *fssp = fss; } char * Py_GetPath() { /* Modified by Jack to do something a bit more sensible: ** - Prepend the python home-directory (which is obtained from a Preferences ** resource) ** - Add : */ static char *pythonpath; char *p, *endp; int newlen; char *curwd; staticforward char *PyMac_GetPythonDir(); #ifndef USE_BUILTIN_PATH staticforward char *PyMac_GetPythonPath(); #endif if ( pythonpath ) return pythonpath; #ifndef USE_BUILTIN_PATH if ( pythonpath = PyMac_GetPythonPath() ) return pythonpath; printf("Warning: No pythonpath resource found, using builtin default\n"); #endif curwd = PyMac_GetPythonDir(); p = PYTHONPATH; endp = p; pythonpath = malloc(2); if ( pythonpath == NULL ) return PYTHONPATH; strcpy(pythonpath, ":"); while (*endp) { endp = strchr(p, '\n'); if ( endp == NULL ) endp = p + strlen(p); newlen = strlen(pythonpath) + 1 + strlen(curwd) + (endp-p); pythonpath = realloc(pythonpath, newlen+1); if ( pythonpath == NULL ) return PYTHONPATH; strcat(pythonpath, "\n"); if ( *p == ':' ) { p++; strcat(pythonpath, curwd); strncat(pythonpath, p, (endp-p)); newlen--; /* Ok, ok, we've allocated one byte too much */ } else { /* We've allocated too much in this case */ newlen -= strlen(curwd); pythonpath = realloc(pythonpath, newlen+1); if ( pythonpath == NULL ) return PYTHONPATH; strncat(pythonpath, p, (endp-p)); } pythonpath[newlen] = '\0'; p = endp + 1; } return pythonpath; } /* ** Open/create the Python Preferences file, return the handle */ static short PyMac_OpenPrefFile() { AliasHandle handle; FSSpec dirspec; short prefrh; OSErr err; getpreffilefss(&dirspec); prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm); if ( prefrh < 0 ) { #if 0 action = CautionAlert(NOPREFFILE_ID, NULL); if ( action == NOPREFFILE_NO ) exit(1); #endif FSpCreateResFile(&dirspec, 'Pyth', 'pref', 0); prefrh = FSpOpenResFile(&dirspec, fsRdWrShPerm); if ( prefrh == -1 ) { /* This "cannot happen":-) */ printf("Cannot create preferences file, error %d\n", ResError()); exit(1); } if ( (err=PyMac_init_process_location()) != 0 ) { printf("Cannot get application location, error %d\n", err); exit(1); } dirspec = PyMac_ApplicationFSSpec; dirspec.name[0] = 0; if ((err=NewAlias(NULL, &dirspec, &handle)) != 0 ) { printf("Cannot make alias to application directory, error %d\n", err); exit(1); } AddResource((Handle)handle, 'alis', PYTHONHOME_ID, "\p"); UpdateResFile(prefrh); } else { UseResFile(prefrh); } return prefrh; } /* ** Return the name of the Python directory */ static char * PyMac_GetPythonDir() { static int diditbefore = 0; static char name[256] = {':', '\0'}; AliasHandle handle; FSSpec dirspec; Boolean modified = 0; short oldrh, prefrh = -1, homerh; if ( diditbefore ) return name; oldrh = CurResFile(); /* First look for an override in the application file */ UseResFile(PyMac_AppRefNum); handle = (AliasHandle)Get1Resource('alis', PYTHONHOMEOVERRIDE_ID); if ( handle != NULL ) { homerh = PyMac_AppRefNum; } else { /* Try to open preferences file in the preferences folder. */ prefrh = PyMac_OpenPrefFile(); handle = (AliasHandle)Get1Resource('alis', PYTHONHOME_ID); if ( handle == NULL ) { (void)StopAlert(BADPREFFILE_ID, NULL); diditbefore=1; return ":"; } homerh = prefrh; } /* It exists. Resolve it (possibly updating it) */ if ( ResolveAlias(NULL, handle, &dirspec, &modified) != noErr ) { (void)StopAlert(BADPREFFILE_ID, NULL); diditbefore=1; return ":"; } if ( modified ) { ChangedResource((Handle)handle); UpdateResFile(homerh); } if ( prefrh != -1 ) CloseResFile(prefrh); UseResFile(oldrh); if ( PyMac_GetFullPath(&dirspec, name) == 0 ) { strcat(name, ":"); } else { /* If all fails, we return the current directory */ printf("Python home dir exists but I cannot find the pathname!!\n"); name[0] = 0; (void)getwd(name); } diditbefore = 1; return name; } #ifndef USE_BUILTIN_PATH static char * PyMac_GetPythonPath() { short oldrh, prefrh = -1; char *rv; int i, newlen; Str255 pathitem; int resource_id; OSErr err; Handle h; oldrh = CurResFile(); /* ** This is a bit tricky. We check here whether the application file ** contains an override. This is to forestall us finding another STR# resource ** with "our" id and using that for path initialization */ UseResFile(PyMac_AppRefNum); SetResLoad(0); if ( (h=Get1Resource('STR#', PYTHONPATHOVERRIDE_ID)) ) { ReleaseResource(h); resource_id = PYTHONPATHOVERRIDE_ID; } else { resource_id = PYTHONPATH_ID; } SetResLoad(1); UseResFile(oldrh); /* Open the preferences file only if there is no override */ if ( resource_id != PYTHONPATHOVERRIDE_ID ) prefrh = PyMac_OpenPrefFile(); /* At this point, we may or may not have the preferences file open, and it ** may or may not contain a sys.path STR# resource. We don't care, if it doesn't ** exist we use the one from the application (the default). ** We put an initial '\n' in front of the path that we don't return to the caller */ if( (rv = malloc(2)) == NULL ) goto out; strcpy(rv, "\n"); for(i=1; ; i++) { GetIndString(pathitem, resource_id, i); if( pathitem[0] == 0 ) break; if ( pathitem[0] >= 9 && strncmp((char *)pathitem+1, "$(PYTHON)", 9) == 0 ) { /* We have to put the directory in place */ char *dir = PyMac_GetPythonDir(); newlen = strlen(rv) + strlen(dir) + (pathitem[0]-9) + 2; if( (rv=realloc(rv, newlen)) == NULL) goto out; strcat(rv, dir); /* Skip a colon at the beginning of the item */ if ( pathitem[0] > 9 && pathitem[1+9] == ':' ) { memcpy(rv+strlen(rv), pathitem+1+10, pathitem[0]-10); newlen--; } else { memcpy(rv+strlen(rv), pathitem+1+9, pathitem[0]-9); } rv[newlen-2] = '\n'; rv[newlen-1] = 0; } else if ( pathitem[0] >= 14 && strncmp((char *)pathitem+1, "$(APPLICATION)", 14) == 0 ) { /* This is the application itself */ if ( (err=PyMac_init_process_location()) != 0 ) { printf("Cannot get application location, error %d\n", err); exit(1); } newlen = strlen(rv) + strlen(PyMac_ApplicationPath) + 2; if( (rv=realloc(rv, newlen)) == NULL) goto out; strcpy(rv+strlen(rv), PyMac_ApplicationPath); rv[newlen-2] = '\n'; rv[newlen-1] = 0; } else { /* Use as-is */ newlen = strlen(rv) + (pathitem[0]) + 2; if( (rv=realloc(rv, newlen)) == NULL) goto out; memcpy(rv+strlen(rv), pathitem+1, pathitem[0]); rv[newlen-2] = '\n'; rv[newlen-1] = 0; } } if( strlen(rv) == 1) { free(rv); rv = NULL; } if ( rv ) { rv[strlen(rv)-1] = 0; rv++; } out: if ( prefrh != -1) CloseResFile(prefrh); UseResFile(oldrh); return rv; } #endif /* !USE_BUILTIN_PATH */ void PyMac_PreferenceOptions(PyMac_PrefRecord *pr) { short oldrh, prefrh = -1; Handle handle; int size; char *p; oldrh = CurResFile(); /* Attempt to load overrides from application */ UseResFile(PyMac_AppRefNum); handle = Get1Resource('Popt', PYTHONOPTIONSOVERRIDE_ID); UseResFile(oldrh); /* Otherwise get options from prefs file or any other open resource file */ if ( handle == NULL ) { prefrh = PyMac_OpenPrefFile(); handle = GetResource('Popt', PYTHONOPTIONS_ID); } if ( handle == NULL ) { return; } HLock(handle); size = GetHandleSize(handle); p = (char *)*handle; if ( size > POPT_INSPECT ) pr->inspect = p[POPT_INSPECT]; if ( size > POPT_VERBOSE ) pr->verbose = p[POPT_VERBOSE]; if ( size > POPT_SUPPRESS ) pr->suppress_print = p[POPT_SUPPRESS]; if ( size > POPT_UNBUFFERED ) pr->unbuffered = p[POPT_UNBUFFERED]; if ( size > POPT_DEBUGGING ) pr->debugging = p[POPT_DEBUGGING]; if ( size > POPT_KEEPNORM ) pr->keep_normal = p[POPT_KEEPNORM]; if ( size > POPT_KEEPERR ) pr->keep_error = p[POPT_KEEPERR]; if ( size > POPT_NOINTOPT ) pr->nointopt = p[POPT_NOINTOPT]; if ( size > POPT_NOARGS ) pr->noargs = p[POPT_NOARGS]; HUnlock(handle); if ( prefrh != -1) CloseResFile(prefrh); UseResFile(oldrh); } #ifdef USE_GUSI void PyMac_SetGUSIOptions() { Handle h; short oldrh, prefrh = -1; oldrh = CurResFile(); /* Try override from the application resource fork */ UseResFile(PyMac_AppRefNum); h = Get1Resource('GU\267I', GUSIOPTIONSOVERRIDE_ID); UseResFile(oldrh); /* If that didn't work try nonoverride from anywhere */ if ( h == NULL ) { prefrh = PyMac_OpenPrefFile(); h = GetResource('GU\267I', GUSIOPTIONS_ID); } if ( h ) GUSILoadConfiguration(h); if ( prefrh != -1) CloseResFile(prefrh); UseResFile(oldrh); } #endif /* USE_GUSI */