# This script generates a Python interface for an Apple Macintosh Manager. # It uses the "bgen" package to generate C code. # The function specifications are generated by scanning the mamager's header file, # using the "scantools" package (customized for this particular manager). import string # Declarations that change for each manager #MACHEADERFILE = 'Files.h' # The Apple header file MODNAME = '_File' # The name of the module # The following is *usually* unchanged but may still require tuning MODPREFIX = 'File' # The prefix for module-wide routines INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner OUTPUTFILE = MODNAME + "module.c" # The file generated by this program from macsupport import * # Various integers: SInt64 = Type("SInt64", "L") UInt64 = Type("UInt64", "L") FNMessage = Type("FNMessage", "l") FSAllocationFlags = Type("FSAllocationFlags", "H") FSCatalogInfoBitmap = Type("FSCatalogInfoBitmap", "l") FSIteratorFlags = Type("FSIteratorFlags", "l") FSVolumeRefNum = Type("FSVolumeRefNum", "h") AliasInfoType = Type("AliasInfoType", "h") # Various types of strings: #class UniCharCountBuffer(InputOnlyType): # pass class VarReverseInputBufferType(ReverseInputBufferMixin, VarInputBufferType): pass FullPathName = VarReverseInputBufferType() ConstStr31Param = OpaqueArrayType("Str31", "PyMac_BuildStr255", "PyMac_GetStr255") ConstStr32Param = OpaqueArrayType("Str32", "PyMac_BuildStr255", "PyMac_GetStr255") ConstStr63Param = OpaqueArrayType("Str63", "PyMac_BuildStr255", "PyMac_GetStr255") Str63 = OpaqueArrayType("Str63", "PyMac_BuildStr255", "PyMac_GetStr255") HFSUniStr255 = OpaqueType("HFSUniStr255", "PyMac_BuildHFSUniStr255", "PyMac_GetHFSUniStr255") UInt8_ptr = InputOnlyType("UInt8 *", "s") # Other types: FInfo = OpaqueByValueStructType("FInfo", "PyMac_BuildFInfo", "PyMac_GetFInfo") FInfo_ptr = OpaqueType("FInfo", "PyMac_BuildFInfo", "PyMac_GetFInfo") AliasHandle = OpaqueByValueType("AliasHandle", "Alias") FSSpec = OpaqueType("FSSpec", "FSSpec") FSSpec_ptr = OpaqueType("FSSpec", "FSSpec") FSRef = OpaqueType("FSRef", "FSRef") FSRef_ptr = OpaqueType("FSRef", "FSRef") # To be done: #CatPositionRec #FSCatalogInfo #FSForkInfo #FSIterator #FSVolumeInfo #FSSpecArrayPtr includestuff = includestuff + """ #ifdef WITHOUT_FRAMEWORKS #include #else #include #endif /* Forward declarations */ extern PyObject *FSRef_New(FSRef *itself); extern PyObject *FSSpec_New(FSSpec *itself); extern PyObject *Alias_New(AliasHandle itself); extern int FSRef_Convert(PyObject *v, FSRef *p_itself); extern int FSSpec_Convert(PyObject *v, FSSpec *p_itself); extern int Alias_Convert(PyObject *v, AliasHandle *p_itself); static int myPyMac_GetFSSpec(PyObject *v, FSSpec *spec); static int myPyMac_GetFSRef(PyObject *v, FSRef *fsr); /* ** Parse/generate objsect */ static PyObject * PyMac_BuildHFSUniStr255(HFSUniStr255 *itself) { return Py_BuildValue("u#", itself->unicode, itself->length); } /* ** Parse/generate objsect */ static PyObject * PyMac_BuildFInfo(FInfo *itself) { return Py_BuildValue("O&O&HO&h", PyMac_BuildOSType, itself->fdType, PyMac_BuildOSType, itself->fdCreator, itself->fdFlags, PyMac_BuildPoint, &itself->fdLocation, itself->fdFldr); } static int PyMac_GetFInfo(PyObject *v, FInfo *itself) { return PyArg_ParseTuple(v, "O&O&HO&h", PyMac_GetOSType, &itself->fdType, PyMac_GetOSType, &itself->fdCreator, &itself->fdFlags, PyMac_GetPoint, &itself->fdLocation, &itself->fdFldr); } """ finalstuff = finalstuff + """ static int myPyMac_GetFSSpec(PyObject *v, FSSpec *spec) { Str255 path; short refnum; long parid; OSErr err; FSRef fsr; if (FSSpec_Check(v)) { *spec = ((FSSpecObject *)v)->ob_itself; return 1; } if (PyArg_Parse(v, "(hlO&)", &refnum, &parid, PyMac_GetStr255, &path)) { err = FSMakeFSSpec(refnum, parid, path, spec); if ( err && err != fnfErr ) { PyMac_Error(err); return 0; } return 1; } PyErr_Clear(); #if !TARGET_API_MAC_OSX /* On OS9 we now try a pathname */ if ( PyString_Check(v) ) { /* It's a pathname */ if( !PyArg_Parse(v, "O&", PyMac_GetStr255, &path) ) return 0; refnum = 0; /* XXXX Should get CurWD here?? */ parid = 0; err = FSMakeFSSpec(refnum, parid, path, spec); if ( err && err != fnfErr ) { PyMac_Error(err); return 0; } return 1; } PyErr_Clear(); #endif /* Otherwise we try to go via an FSRef. On OSX we go all the way, ** on OS9 we accept only a real FSRef object */ #if TARGET_API_MAX_OSX if ( myPyMac_GetFSRef(v, &fsr) >= 0 ) { #else if ( PyArg_Parse(v, "O&", FSRef_Convert, &fsr) ) { #endif err = FSGetCatalogInfo(&fsr, kFSCatInfoNone, NULL, NULL, spec, NULL); if (err != noErr) { PyMac_Error(err); return 0; } return 1; } PyErr_SetString(PyExc_TypeError, "FSSpec, FSRef, pathname or (refnum, parid, path) required"); return 0; } static int myPyMac_GetFSRef(PyObject *v, FSRef *fsr) { if (FSRef_Check(v)) { *fsr = ((FSRefObject *)v)->ob_itself; return 1; } #if !TARGET_API_MAC_OSX /* On OSX we now try a pathname */ if ( PyString_Check(args) ) { OSStatus err; if ( (err=FSPathMakeRef(PyString_AsString(v), fsr, NULL)) ) { PyErr_Mac(ErrorObject, err); return 0; } return 1; } /* XXXX Should try unicode here too */ #endif /* Otherwise we try to go via an FSSpec */ if (FSSpec_Check(v)) { if (FSpMakeFSRef(&((FSSpecObject *)v)->ob_itself, fsr)) return 1; return 0; } PyErr_SetString(PyExc_TypeError, "FSRef, FSSpec or pathname required"); return 0; } """ execfile(string.lower(MODPREFIX) + 'typetest.py') # Our object types: class FSSpecDefinition(PEP253Mixin, GlobalObjectDefinition): def __init__(self, name, prefix, itselftype): GlobalObjectDefinition.__init__(self, name, prefix, itselftype) self.argref = "*" # Store FSSpecs, but pass them by address def outputCheckNewArg(self): Output("if (itself == NULL) return PyMac_Error(resNotFound);") def output_tp_newBody(self): Output("PyObject *self;"); Output() Output("if ((self = type->tp_alloc(type, 0)) == NULL) return NULL;") Output("memset(&((%s *)self)->ob_itself, 0, sizeof(%s));", self.objecttype, self.objecttype) Output("return self;") def output_tp_initBody(self): Output("PyObject *v;") Output("char *kw[] = {\"itself\", 0};") Output() Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"O\", kw, &v))") Output("return -1;") Output("if (myPyMac_GetFSSpec(v, &((%s *)self)->ob_itself)) return 0;", self.objecttype) Output("return -1;") class FSRefDefinition(PEP253Mixin, GlobalObjectDefinition): def __init__(self, name, prefix, itselftype): GlobalObjectDefinition.__init__(self, name, prefix, itselftype) self.argref = "*" # Store FSRefs, but pass them by address def outputCheckNewArg(self): Output("if (itself == NULL) return PyMac_Error(resNotFound);") def output_tp_newBody(self): Output("PyObject *self;"); Output() Output("if ((self = type->tp_alloc(type, 0)) == NULL) return NULL;") Output("memset(&((%s *)self)->ob_itself, 0, sizeof(%s));", self.objecttype, self.objecttype) Output("return self;") def output_tp_initBody(self): Output("PyObject *v;") Output("char *kw[] = {\"itself\", 0};") Output() Output("if (!PyArg_ParseTupleAndKeywords(args, kwds, \"O\", kw, &v))") Output("return -1;") Output("if (myPyMac_GetFSRef(v, &((%s *)self)->ob_itself)) return 0;", self.objecttype) Output("return -1;") class AliasDefinition(PEP253Mixin, GlobalObjectDefinition): # XXXX Should inherit from resource? def outputCheckNewArg(self): Output("if (itself == NULL) return PyMac_Error(resNotFound);") def outputStructMembers(self): GlobalObjectDefinition.outputStructMembers(self) Output("void (*ob_freeit)(%s ptr);", self.itselftype) def outputInitStructMembers(self): GlobalObjectDefinition.outputInitStructMembers(self) Output("it->ob_freeit = NULL;") def outputCleanupStructMembers(self): Output("if (self->ob_freeit && self->ob_itself)") OutLbrace() Output("self->ob_freeit(self->ob_itself);") OutRbrace() Output("self->ob_itself = NULL;") def output_tp_newBody(self): Output("PyObject *self;"); Output() Output("if ((self = type->tp_alloc(type, 0)) == NULL) return NULL;") Output("((%s *)self)->ob_itself = NULL;", self.objecttype) Output("return self;") def output_tp_initBody(self): Output("%s itself;", self.itselftype); Output("char *kw[] = {\"itself\", 0};") Output() Output("if (PyArg_ParseTupleAndKeywords(args, kwds, \"O&\", kw, %s_Convert, &itself))", self.prefix) OutLbrace() Output("((%s *)self)->ob_itself = itself;", self.objecttype) Output("return 0;") OutRbrace() Output("return -1;") # Alias methods come in two flavors: those with the alias as arg1 and # those with the alias as arg 2. class Arg2MethodGenerator(MethodGenerator): """Similar to MethodGenerator, but has self as second argument""" def parseArgumentList(self, args): args0, arg1, argsrest = args[:1], args[1], args[2:] t0, n0, m0 = arg1 args = args0 + argsrest if m0 != InMode: raise ValueError, "method's 'self' must be 'InMode'" self.itself = Variable(t0, "_self->ob_itself", SelfMode) FunctionGenerator.parseArgumentList(self, args) self.argumentList.insert(2, self.itself) # From here on it's basically all boiler plate... # Create the generator groups and link them module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff) aliasobject = AliasDefinition('Alias', 'Alias', 'AliasHandle') fsspecobject = FSSpecDefinition('FSSpec', 'FSSpec', 'FSSpec') fsrefobject = FSRefDefinition('FSRef', 'FSRef', 'FSRef') module.addobject(aliasobject) module.addobject(fsspecobject) module.addobject(fsrefobject) # Create the generator classes used to populate the lists Function = OSErrFunctionGenerator Method = OSErrMethodGenerator # Create and populate the lists functions = [] alias_methods = [] fsref_methods = [] fsspec_methods = [] execfile(INPUTFILE) # Manual generators: FSRefMakePath_body = """ OSStatus _err; #define MAXPATHNAME 1024 UInt8 path[MAXPATHNAME]; UInt32 maxPathSize = MAXPATHNAME; _err = FSRefMakePath(&_self->ob_itself, path, maxPathSize); if (_err != noErr) return PyMac_Error(_err); _res = Py_BuildValue("s", path); return _res; """ f = ManualGenerator("FSRefMakePath", FSRefMakePath_body) f.docstring = lambda: "() -> string" fsref_methods.append(f) # add the populated lists to the generator groups # (in a different wordl the scan program would generate this) for f in functions: module.add(f) for f in alias_methods: aliasobject.add(f) for f in fsspec_methods: fsspecobject.add(f) for f in fsref_methods: fsrefobject.add(f) # generate output (open the output file as late as possible) SetOutputFileName(OUTPUTFILE) module.generate()