From 1e2260fcb4647ec84753427e1a92c59e8f0c0171 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Mon, 13 Jul 1998 13:37:12 +0000 Subject: All import-related code has moved to macimport.c. There's also new support for importing code fragments: if a file on sys.path contains a PYD resource with resourcename equal to the name of the module to be imported this PYD resource should contain a (pascal) string with the name of a code fragment to load. This allows freezing Python programs without access to source or a development environment. --- Mac/Python/macglue.c | 224 -------------------------- Mac/Python/macimport.c | 416 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 416 insertions(+), 224 deletions(-) create mode 100644 Mac/Python/macimport.c diff --git a/Mac/Python/macglue.c b/Mac/Python/macglue.c index 2dc6cfa..3252cf0 100644 --- a/Mac/Python/macglue.c +++ b/Mac/Python/macglue.c @@ -685,230 +685,6 @@ SIOUXDoAboutBox(void) DisposeDialog(theDialog); } -/* -** Returns true if the argument has a resource fork, and it contains -** a 'PYC ' resource of the correct name -*/ -int -PyMac_FindResourceModule(obj, module, filename) -PyStringObject *obj; -char *module; -char *filename; -{ - FSSpec fss; - FInfo finfo; - short oldrh, filerh; - int ok; - Handle h; - -#ifdef INTERN_STRINGS - /* - ** If we have interning find_module takes care of interning all - ** sys.path components. We then keep a record of all sys.path - ** components for which GetFInfo has failed (usually because the - ** component in question is a folder), and we don't try opening these - ** as resource files again. - */ -#define MAXPATHCOMPONENTS 32 - static PyStringObject *not_a_file[MAXPATHCOMPONENTS]; - static int max_not_a_file = 0; - int i; - - if ( obj->ob_sinterned ) { - for( i=0; i< max_not_a_file; i++ ) - if ( obj == not_a_file[i] ) - return 0; - } -#endif /* INTERN_STRINGS */ - - if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) { - /* - ** Special case: the application itself. Use a shortcut to - ** forestall opening and closing the application numerous times - ** (which is dead slow when running from CDROM) - */ - oldrh = CurResFile(); - UseResFile(PyMac_AppRefNum); - filerh = -1; - } else { - if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr || - FSpGetFInfo(&fss, &finfo) != noErr ) { -#ifdef INTERN_STRINGS - if ( max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned ) - not_a_file[max_not_a_file++] = obj; -#endif /* INTERN_STRINGS */ - /* doesn't exist or is folder */ - return 0; - } - oldrh = CurResFile(); - filerh = FSpOpenResFile(&fss, fsRdPerm); - if ( filerh == -1 ) - return 0; - UseResFile(filerh); - } - SetResLoad(0); - h = Get1NamedResource('PYC ', Pstring(module)); - SetResLoad(1); - ok = (h != NULL); - if ( filerh != -1 ) - CloseResFile(filerh); - UseResFile(oldrh); - return ok; -} - -/* -** Load the specified module from a resource -*/ -PyObject * -PyMac_LoadResourceModule(module, filename) -char *module; -char *filename; -{ - FSSpec fss; - FInfo finfo; - short oldrh, filerh; - Handle h; - OSErr err; - PyObject *m, *co; - long num, size; - - if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) { - /* - ** Special case: the application itself. Use a shortcut to - ** forestall opening and closing the application numerous times - ** (which is dead slow when running from CDROM) - */ - oldrh = CurResFile(); - UseResFile(PyMac_AppRefNum); - filerh = -1; - } else { - if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr ) - goto error; - if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr ) - goto error; - oldrh = CurResFile(); - filerh = FSpOpenResFile(&fss, fsRdPerm); - if ( filerh == -1 ) { - err = ResError(); - goto error; - } - UseResFile(filerh); - } - h = Get1NamedResource('PYC ', Pstring(module)); - if ( h == NULL ) { - err = ResError(); - goto error; - } - HLock(h); - /* - ** XXXX The next few lines are intimately tied to the format of pyc - ** files. I'm not sure whether this code should be here or in import.c -- Jack - */ - size = GetHandleSize(h); - if ( size < 8 ) { - PyErr_SetString(PyExc_ImportError, "Resource too small"); - co = NULL; - } else { - num = (*h)[0] & 0xff; - num = num | (((*h)[1] & 0xff) << 8); - num = num | (((*h)[2] & 0xff) << 16); - num = num | (((*h)[3] & 0xff) << 24); - if ( num != PyImport_GetMagicNumber() ) { - PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource"); - co = NULL; - } else { - co = PyMarshal_ReadObjectFromString((*h)+8, size-8); - } - } - HUnlock(h); - if ( filerh != -1 ) - CloseResFile(filerh); - UseResFile(oldrh); - if ( co ) { - m = PyImport_ExecCodeModule(module, co); - Py_DECREF(co); - } else { - m = NULL; - } - if (Py_VerboseFlag) - fprintf(stderr, "import %s # pyc resource from %s\n", - module, filename); - return m; -error: - { - char buf[512]; - - sprintf(buf, "%s: %s", filename, PyMac_StrError(err)); - PyErr_SetString(PyExc_ImportError, buf); - return NULL; - } -} - -/* -** Look for a module in a single folder. Upon entry buf and len -** point to the folder to search, upon exit they refer to the full -** pathname of the module found (if any). -*/ -struct filedescr * -PyMac_FindModuleExtension(char *buf, int *lenp, char *module) -{ - struct filedescr *fdp; - unsigned char fnbuf[64]; - int modnamelen = strlen(module); - FSSpec fss; - short refnum; - long dirid; - - /* - ** Copy the module name to the buffer (already :-terminated) - ** We also copy the first suffix, if this matches immedeately we're - ** lucky and return immedeately. - */ - if ( !_PyImport_Filetab[0].suffix ) - return 0; - -#if 0 - /* Pre 1.5a4 */ - strcpy(buf+*lenp, module); - strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix); -#else - strcpy(buf+*lenp, _PyImport_Filetab[0].suffix); -#endif - if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr ) - return _PyImport_Filetab; - /* - ** We cannot check for fnfErr (unfortunately), it can mean either that - ** the file doesn't exist (fine, we try others) or the path leading to it. - */ - refnum = fss.vRefNum; - dirid = fss.parID; - if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */ - return 0; - /* - ** We now have the folder parameters. Setup the field for the filename - */ - if ( modnamelen > 54 ) return 0; /* Leave room for extension */ - strcpy((char *)fnbuf+1, module); - - for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) { - strcpy((char *)fnbuf+1+modnamelen, fdp->suffix); - fnbuf[0] = strlen((char *)fnbuf+1); - if (Py_VerboseFlag > 1) - fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix); - if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) { - /* Found it. */ -#if 0 - strcpy(buf+*lenp+modnamelen, fdp->suffix); -#else - strcpy(buf+*lenp, fdp->suffix); -#endif - *lenp = strlen(buf); - return fdp; - } - } - return 0; -} - #if 0 int PyMac_FileExists(char *name) diff --git a/Mac/Python/macimport.c b/Mac/Python/macimport.c new file mode 100644 index 0000000..ce6b49e --- /dev/null +++ b/Mac/Python/macimport.c @@ -0,0 +1,416 @@ +/*********************************************************** +Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam, +The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + + +#include "Python.h" + +#include "macglue.h" +#include "marshal.h" +#include "import.h" +#include "importdl.h" + +#include "pythonresources.h" + +#include +#include +#include +#if 0 +#include /* for Set(Current)A5 */ +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include + +typedef void (*dl_funcptr)(); +#define FUNCNAME_PATTERN "init%.200s" + +/* +** findnamedresource - Common code for the various *ResourceModule functions. +** Check whether a file contains a resource of the correct name and type, and +** optionally return the value in it. +*/ +static int +findnamedresource( + PyStringObject *obj, + char *module, + char *filename, + OSType restype, + StringPtr dataptr) +{ + FSSpec fss; + FInfo finfo; + short oldrh, filerh; + int ok; + Handle h; + +#ifdef INTERN_STRINGS + /* + ** If we have interning find_module takes care of interning all + ** sys.path components. We then keep a record of all sys.path + ** components for which GetFInfo has failed (usually because the + ** component in question is a folder), and we don't try opening these + ** as resource files again. + */ +#define MAXPATHCOMPONENTS 32 + static PyStringObject *not_a_file[MAXPATHCOMPONENTS]; + static int max_not_a_file = 0; + int i; + + if (obj && obj->ob_sinterned ) { + for( i=0; i< max_not_a_file; i++ ) + if ( obj == not_a_file[i] ) + return 0; + } +#endif /* INTERN_STRINGS */ + + if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) { + /* + ** Special case: the application itself. Use a shortcut to + ** forestall opening and closing the application numerous times + ** (which is dead slow when running from CDROM) + */ + oldrh = CurResFile(); + UseResFile(PyMac_AppRefNum); + filerh = -1; + } else { + if ( FSMakeFSSpec(0, 0, Pstring(filename), &fss) != noErr || + FSpGetFInfo(&fss, &finfo) != noErr ) { +#ifdef INTERN_STRINGS + if ( obj && max_not_a_file < MAXPATHCOMPONENTS && obj->ob_sinterned ) + not_a_file[max_not_a_file++] = obj; +#endif /* INTERN_STRINGS */ + /* doesn't exist or is folder */ + return 0; + } + oldrh = CurResFile(); + filerh = FSpOpenResFile(&fss, fsRdPerm); + if ( filerh == -1 ) + return 0; + UseResFile(filerh); + } + if ( dataptr == NULL ) + SetResLoad(0); + h = Get1NamedResource(restype, Pstring(module)); + SetResLoad(1); + ok = (h != NULL); + if ( ok && dataptr != NULL ) { + HLock(h); + *dataptr = **h; + memcpy(dataptr+1, (*h)+1, (int)*dataptr); + HUnlock(h); + } + if ( filerh != -1 ) + CloseResFile(filerh); + UseResFile(oldrh); + return ok; +} + +/* +** Returns true if the argument has a resource fork, and it contains +** a 'PYC ' resource of the correct name +*/ +int +PyMac_FindResourceModule(obj, module, filename) +PyStringObject *obj; +char *module; +char *filename; +{ + int ok; + + ok = findnamedresource(obj, module, filename, 'PYC ', (StringPtr)0); + return ok; +} + +/* +** Returns true if the argument has a resource fork, and it contains +** a 'PYD ' resource of the correct name +*/ +int +PyMac_FindCodeResourceModule(obj, module, filename) +PyStringObject *obj; +char *module; +char *filename; +{ + int ok; + + ok = findnamedresource(obj, module, filename, 'PYD ', (StringPtr)0); + return ok; +} + + +/* +** Load the specified module from a code resource +*/ +PyObject * +PyMac_LoadCodeResourceModule(name, pathname) + char *name; + char *pathname; +{ + PyObject *m; + char funcname[258]; + char *lastdot, *shortname, *packagecontext; + dl_funcptr p = NULL; + Str255 fragmentname; + CFragConnectionID connID; + Ptr mainAddr; + Str255 errMessage; + OSErr err; + char buf[512]; + Ptr symAddr; + CFragSymbolClass class; + + if ((m = _PyImport_FindExtension(name, name)) != NULL) { + Py_INCREF(m); + return m; + } + lastdot = strrchr(name, '.'); + if (lastdot == NULL) { + packagecontext = NULL; + shortname = name; + } + else { + packagecontext = name; + shortname = lastdot+1; + } + sprintf(funcname, FUNCNAME_PATTERN, shortname); + if( !findnamedresource((PyStringObject *)0, shortname, pathname, 'PYD ', fragmentname)) { + PyErr_SetString(PyExc_ImportError, "PYD resource not found"); + return NULL; + } + + /* Load the fragment + (or return the connID if it is already loaded */ + err = GetSharedLibrary(fragmentname, kCompiledCFragArch, + kLoadCFrag, &connID, &mainAddr, + errMessage); + if ( err ) { + sprintf(buf, "%.*s: %.200s", + errMessage[0], errMessage+1, + PyMac_StrError(err)); + PyErr_SetString(PyExc_ImportError, buf); + return NULL; + } + /* Locate the address of the correct init function */ + err = FindSymbol(connID, Pstring(funcname), &symAddr, &class); + if ( err ) { + sprintf(buf, "%s: %.200s", + funcname, PyMac_StrError(err)); + PyErr_SetString(PyExc_ImportError, buf); + return NULL; + } + p = (dl_funcptr)symAddr; + if (p == NULL) { + PyErr_Format(PyExc_ImportError, + "dynamic module does not define init function (%.200s)", + funcname); + return NULL; + } + _Py_PackageContext = packagecontext; + (*p)(); + _Py_PackageContext = NULL; + if (PyErr_Occurred()) + return NULL; + if (_PyImport_FixupExtension(name, name) == NULL) + return NULL; + + m = PyDict_GetItemString(PyImport_GetModuleDict(), name); + if (m == NULL) { + PyErr_SetString(PyExc_SystemError, + "dynamic module not initialized properly"); + return NULL; + } +#if 0 + /* Remember the filename as the __file__ attribute */ + d = PyModule_GetDict(m); + s = PyString_FromString(pathname); + if (s == NULL || PyDict_SetItemString(d, "__file__", s) != 0) + PyErr_Clear(); /* Not important enough to report */ + Py_XDECREF(s); +#endif + if (Py_VerboseFlag) + fprintf(stderr, + "import %s # pyd fragment %#s loaded from %s\n", + name, fragmentname, pathname); + Py_INCREF(m); + return m; +} + +/* +** Load the specified module from a resource +*/ +PyObject * +PyMac_LoadResourceModule(module, filename) +char *module; +char *filename; +{ + FSSpec fss; + FInfo finfo; + short oldrh, filerh; + Handle h; + OSErr err; + PyObject *m, *co; + long num, size; + + if ( strcmp(filename, PyMac_ApplicationPath) == 0 ) { + /* + ** Special case: the application itself. Use a shortcut to + ** forestall opening and closing the application numerous times + ** (which is dead slow when running from CDROM) + */ + oldrh = CurResFile(); + UseResFile(PyMac_AppRefNum); + filerh = -1; + } else { + if ( (err=FSMakeFSSpec(0, 0, Pstring(filename), &fss)) != noErr ) + goto error; + if ( (err=FSpGetFInfo(&fss, &finfo)) != noErr ) + goto error; + oldrh = CurResFile(); + filerh = FSpOpenResFile(&fss, fsRdPerm); + if ( filerh == -1 ) { + err = ResError(); + goto error; + } + UseResFile(filerh); + } + h = Get1NamedResource('PYC ', Pstring(module)); + if ( h == NULL ) { + err = ResError(); + goto error; + } + HLock(h); + /* + ** XXXX The next few lines are intimately tied to the format of pyc + ** files. I'm not sure whether this code should be here or in import.c -- Jack + */ + size = GetHandleSize(h); + if ( size < 8 ) { + PyErr_SetString(PyExc_ImportError, "Resource too small"); + co = NULL; + } else { + num = (*h)[0] & 0xff; + num = num | (((*h)[1] & 0xff) << 8); + num = num | (((*h)[2] & 0xff) << 16); + num = num | (((*h)[3] & 0xff) << 24); + if ( num != PyImport_GetMagicNumber() ) { + PyErr_SetString(PyExc_ImportError, "Bad MAGIC in resource"); + co = NULL; + } else { + co = PyMarshal_ReadObjectFromString((*h)+8, size-8); + } + } + HUnlock(h); + if ( filerh != -1 ) + CloseResFile(filerh); + UseResFile(oldrh); + if ( co ) { + m = PyImport_ExecCodeModule(module, co); + Py_DECREF(co); + } else { + m = NULL; + } + if (Py_VerboseFlag) + fprintf(stderr, "import %s # pyc resource from %s\n", + module, filename); + return m; +error: + { + char buf[512]; + + sprintf(buf, "%s: %s", filename, PyMac_StrError(err)); + PyErr_SetString(PyExc_ImportError, buf); + return NULL; + } +} + +/* +** Look for a module in a single folder. Upon entry buf and len +** point to the folder to search, upon exit they refer to the full +** pathname of the module found (if any). +*/ +struct filedescr * +PyMac_FindModuleExtension(char *buf, int *lenp, char *module) +{ + struct filedescr *fdp; + unsigned char fnbuf[64]; + int modnamelen = strlen(module); + FSSpec fss; + short refnum; + long dirid; + + /* + ** Copy the module name to the buffer (already :-terminated) + ** We also copy the first suffix, if this matches immedeately we're + ** lucky and return immedeately. + */ + if ( !_PyImport_Filetab[0].suffix ) + return 0; + +#if 0 + /* Pre 1.5a4 */ + strcpy(buf+*lenp, module); + strcpy(buf+*lenp+modnamelen, _PyImport_Filetab[0].suffix); +#else + strcpy(buf+*lenp, _PyImport_Filetab[0].suffix); +#endif + if ( FSMakeFSSpec(0, 0, Pstring(buf), &fss) == noErr ) + return _PyImport_Filetab; + /* + ** We cannot check for fnfErr (unfortunately), it can mean either that + ** the file doesn't exist (fine, we try others) or the path leading to it. + */ + refnum = fss.vRefNum; + dirid = fss.parID; + if ( refnum == 0 || dirid == 0 ) /* Fail on nonexistent dir */ + return 0; + /* + ** We now have the folder parameters. Setup the field for the filename + */ + if ( modnamelen > 54 ) return 0; /* Leave room for extension */ + strcpy((char *)fnbuf+1, module); + + for( fdp = _PyImport_Filetab+1; fdp->suffix; fdp++ ) { + strcpy((char *)fnbuf+1+modnamelen, fdp->suffix); + fnbuf[0] = strlen((char *)fnbuf+1); + if (Py_VerboseFlag > 1) + fprintf(stderr, "# trying %s%s\n", buf, fdp->suffix); + if ( FSMakeFSSpec(refnum, dirid, fnbuf, &fss) == noErr ) { + /* Found it. */ +#if 0 + strcpy(buf+*lenp+modnamelen, fdp->suffix); +#else + strcpy(buf+*lenp, fdp->suffix); +#endif + *lenp = strlen(buf); + return fdp; + } + } + return 0; +} -- cgit v0.12