Home | History | Annotate | Download | only in list
      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