1 # This script generates a Python interface for an Apple Macintosh Manager. 2 # It uses the "bgen" package to generate C code. 3 # The function specifications are generated by scanning the mamager's header file, 4 # using the "scantools" package (customized for this particular manager). 5 6 import string 7 8 # Declarations that change for each manager 9 MACHEADERFILE = 'Lists.h' # The Apple header file 10 MODNAME = '_List' # The name of the module 11 OBJECTNAME = 'List' # The basic name of the objects used here 12 KIND = 'Handle' # Usually 'Ptr' or 'Handle' 13 14 # The following is *usually* unchanged but may still require tuning 15 MODPREFIX = 'List' # The prefix for module-wide routines 16 OBJECTTYPE = "ListHandle" # The C type used to represent them 17 OBJECTPREFIX = MODPREFIX + 'Obj' # The prefix for object methods 18 INPUTFILE = string.lower(MODPREFIX) + 'gen.py' # The file generated by the scanner 19 OUTPUTFILE = MODNAME + "module.c" # The file generated by this program 20 21 from macsupport import * 22 23 # Create the type objects 24 ListHandle = OpaqueByValueType("ListHandle", "ListObj") 25 ListRef = ListHandle # Obsolete, but used in Lists.h 26 Cell = Point 27 ListBounds = Rect 28 ListBounds_ptr = Rect_ptr 29 30 ListDefSpec = ListDefSpec_ptr = OpaqueType("ListDefSpec", "PyMac_BuildListDefSpec", "PyMac_GetListDefSpec") 31 32 VarOutBufferShortsize = VarHeapOutputBufferType('char', 'short', 's') # (buf, &len) 33 InBufferShortsize = VarInputBufferType('char', 'short', 's') # (buf, len) 34 35 RgnHandle = OpaqueByValueType("RgnHandle", "ResObj") 36 DataHandle = OpaqueByValueType("DataHandle", "ResObj") 37 Handle = OpaqueByValueType("Handle", "ResObj") 38 CGrafPtr = OpaqueByValueType("CGrafPtr", "GrafObj") 39 EventModifiers = Type("EventModifiers", "H") 40 41 includestuff = includestuff + """ 42 #include <Carbon/Carbon.h> 43 44 #ifdef USE_TOOLBOX_OBJECT_GLUE 45 extern PyObject *_ListObj_New(ListHandle); 46 extern int _ListObj_Convert(PyObject *, ListHandle *); 47 48 #define ListObj_New _ListObj_New 49 #define ListObj_Convert _ListObj_Convert 50 #endif 51 52 #define as_List(x) ((ListHandle)x) 53 #define as_Resource(lh) ((Handle)lh) 54 55 static ListDefUPP myListDefFunctionUPP; 56 57 """ 58 59 initstuff = initstuff + """ 60 myListDefFunctionUPP = NewListDefUPP((ListDefProcPtr)myListDefFunction); 61 62 PyMac_INIT_TOOLBOX_OBJECT_NEW(ListHandle, ListObj_New); 63 PyMac_INIT_TOOLBOX_OBJECT_CONVERT(ListHandle, ListObj_Convert); 64 """ 65 66 class ListMethodGenerator(MethodGenerator): 67 """Similar to MethodGenerator, but has self as last argument""" 68 69 def parseArgumentList(self, args): 70 args, a0 = args[:-1], args[-1] 71 t0, n0, m0 = a0 72 if m0 != InMode: 73 raise ValueError, "method's 'self' must be 'InMode'" 74 self.itself = Variable(t0, "_self->ob_itself", SelfMode) 75 FunctionGenerator.parseArgumentList(self, args) 76 self.argumentList.append(self.itself) 77 78 class MyObjectDefinition(PEP253Mixin, GlobalObjectDefinition): 79 # XXXX Should inherit from Resource 80 getsetlist = [( 81 'listFlags', 82 'return Py_BuildValue("l", (long)GetListFlags(self->ob_itself) & 0xff);', 83 'if (!PyArg_Parse(v, "B", &(*self->ob_itself)->listFlags)) return -1;', 84 None, 85 ), ( 86 'selFlags', 87 'return Py_BuildValue("l", (long)GetListSelectionFlags(self->ob_itself) & 0xff);', 88 'if (!PyArg_Parse(v, "B", &(*self->ob_itself)->selFlags)) return -1;', 89 None, 90 ), ( 91 'cellSize', 92 'return Py_BuildValue("O&", PyMac_BuildPoint, (*self->ob_itself)->cellSize);', 93 'if (!PyArg_Parse(v, "O&", PyMac_GetPoint, &(*self->ob_itself)->cellSize)) return -1;', 94 None 95 )] 96 97 def outputStructMembers(self): 98 ObjectDefinition.outputStructMembers(self) 99 Output("PyObject *ob_ldef_func;") 100 Output("int ob_must_be_disposed;") 101 102 def outputCheckNewArg(self): 103 Output("""if (itself == NULL) { 104 PyErr_SetString(List_Error,"Cannot create null List"); 105 return NULL; 106 }""") 107 108 def outputInitStructMembers(self): 109 ObjectDefinition.outputInitStructMembers(self) 110 Output("it->ob_ldef_func = NULL;") 111 Output("it->ob_must_be_disposed = 1;") 112 Output("SetListRefCon(itself, (long)it);") 113 114 def outputFreeIt(self, itselfname): 115 Output("Py_XDECREF(self->ob_ldef_func);") 116 Output("self->ob_ldef_func = NULL;") 117 Output("SetListRefCon(self->ob_itself, (long)0);") 118 Output("if (self->ob_must_be_disposed && %s) LDispose(%s);", itselfname, itselfname) 119 120 # From here on it's basically all boiler plate... 121 122 finalstuff = finalstuff + """ 123 static void myListDefFunction(SInt16 message, 124 Boolean selected, 125 Rect *cellRect, 126 Cell theCell, 127 SInt16 dataOffset, 128 SInt16 dataLen, 129 ListHandle theList) 130 { 131 PyObject *listDefFunc, *args, *rv=NULL; 132 ListObject *self; 133 134 self = (ListObject*)GetListRefCon(theList); 135 if (self == NULL || self->ob_itself != theList) 136 return; /* nothing we can do */ 137 listDefFunc = self->ob_ldef_func; 138 if (listDefFunc == NULL) 139 return; /* nothing we can do */ 140 args = Py_BuildValue("hbO&O&hhO", message, 141 selected, 142 PyMac_BuildRect, cellRect, 143 PyMac_BuildPoint, theCell, 144 dataOffset, 145 dataLen, 146 self); 147 if (args != NULL) { 148 rv = PyEval_CallObject(listDefFunc, args); 149 Py_DECREF(args); 150 } 151 if (rv == NULL) { 152 PySys_WriteStderr("error in list definition callback:\\n"); 153 PyErr_Print(); 154 } else { 155 Py_DECREF(rv); 156 } 157 } 158 """ 159 160 # Create the generator groups and link them 161 module = MacModule(MODNAME, MODPREFIX, includestuff, finalstuff, initstuff) 162 object = MyObjectDefinition(OBJECTNAME, OBJECTPREFIX, OBJECTTYPE) 163 module.addobject(object) 164 165 # Create the generator classes used to populate the lists 166 Function = FunctionGenerator 167 Method = ListMethodGenerator 168 169 # Create and populate the lists 170 functions = [] 171 methods = [] 172 execfile(INPUTFILE) 173 174 # Function to convert any handle to a list and vv. 175 ##f = Function(ListHandle, 'as_List', (Handle, 'h', InMode)) 176 as_List_body = """ 177 Handle h; 178 ListObject *l; 179 if (!PyArg_ParseTuple(_args, "O&", ResObj_Convert, &h)) 180 return NULL; 181 l = (ListObject *)ListObj_New(as_List(h)); 182 l->ob_must_be_disposed = 0; 183 _res = Py_BuildValue("O", l); 184 return _res; 185 """ 186 f = ManualGenerator("as_List", as_List_body) 187 f.docstring = lambda: "(Resource)->List.\nReturns List object (which is not auto-freed!)" 188 functions.append(f) 189 190 f = Method(Handle, 'as_Resource', (ListHandle, 'lh', InMode)) 191 methods.append(f) 192 193 # Manual generator for CreateCustomList, due to callback ideosyncracies 194 CreateCustomList_body = """\ 195 Rect rView; 196 Rect dataBounds; 197 Point cellSize; 198 199 PyObject *listDefFunc; 200 ListDefSpec theSpec; 201 WindowPtr theWindow; 202 Boolean drawIt; 203 Boolean hasGrow; 204 Boolean scrollHoriz; 205 Boolean scrollVert; 206 ListHandle outList; 207 208 if (!PyArg_ParseTuple(_args, "O&O&O&(iO)O&bbbb", 209 PyMac_GetRect, &rView, 210 PyMac_GetRect, &dataBounds, 211 PyMac_GetPoint, &cellSize, 212 &theSpec.defType, &listDefFunc, 213 WinObj_Convert, &theWindow, 214 &drawIt, 215 &hasGrow, 216 &scrollHoriz, 217 &scrollVert)) 218 return NULL; 219 220 221 /* Carbon applications use the CreateCustomList API */ 222 theSpec.u.userProc = myListDefFunctionUPP; 223 CreateCustomList(&rView, 224 &dataBounds, 225 cellSize, 226 &theSpec, 227 theWindow, 228 drawIt, 229 hasGrow, 230 scrollHoriz, 231 scrollVert, 232 &outList); 233 234 235 _res = ListObj_New(outList); 236 if (_res == NULL) 237 return NULL; 238 Py_INCREF(listDefFunc); 239 ((ListObject*)_res)->ob_ldef_func = listDefFunc; 240 return _res;\ 241 """ 242 243 f = ManualGenerator("CreateCustomList", CreateCustomList_body); 244 f.docstring = lambda: "(Rect rView, Rect dataBounds, Point cellSize, ListDefSpec theSpec, WindowPtr theWindow, Boolean drawIt, Boolean hasGrow, Boolean scrollHoriz, Boolean scrollVert) -> (ListHandle outList)" 245 module.add(f) 246 247 # add the populated lists to the generator groups 248 # (in a different wordl the scan program would generate this) 249 for f in functions: module.add(f) 250 for f in methods: object.add(f) 251 252 253 # generate output (open the output file as late as possible) 254 SetOutputFileName(OUTPUTFILE) 255 module.generate() 256