# Tools for generating files of C functions. import sys # Output functions Outfp = sys.stdout def setfile(filename): global Outfp Outfp = open(filename, 'w') def write(*args): for s in args: Outfp.write(s) def writef(fmt, *args): write(fmt % args) # Stuff for doing various things to types defined in typedefs from typedefs import * def declare(type, name): if name == '0': return s = typedefs[type][DCL] if s: write('\t', s%{'arg':name}, ';\n') def check(type, name, returntype = ''): dict = {'arg': name} if type == 'argdict': if returntype == 'Widget': dict['w'] = 'NULL' else: dict['w'] = 'w' s = typedefs[type][CHK] if not s: pass elif s[-1] == ';': write('\t', s%{'arg':name}, '\n') else: write('\tif (!', s % dict, ') {\n') write('\t\tif (!PyErr_Occurred())\n') if type == '*': write('\t\t\tPyErr_SetString(PyExc_RuntimeError, "', 'widget already destroyed");\n') else: write('\t\t\tPyErr_SetString(PyExc_TypeError, "', name, ' should be ', type, '");\n') write('\t\treturn NULL;\n') write('\t}\n') def extract(type, name): s = typedefs[type][EXT] if '%' in s: return s%{'arg':name} elif s: return s else: return name def create(type, name): s = typedefs[type][CRE] if s: return s%{'arg':name} else: return 'Py_None' def cleanup(type, name): item = typedefs[type] if len(item) > CLE: s = item[CLE] if s: write('\t', s%{'arg':name}, ';\n') # Stuff to generate wrappers around C functions and add them to method chain Prefix = None SaveList = List = [] Lists = [] Skip = None def setprefix(prefix, skip): global Prefix, List, SaveList, Skip Prefix = prefix Skip = skip List = SaveList del List[:] write('\n') write('/* automatically generated by ', sys.argv[0], ' */\n') write('/* ', 'Methods for ', Prefix, ' objects */\n') write('\n') def setlist(list = None): global List if list is None: List = SaveList else: List = list def dotaggedfunction(tag, returntype, fname, *argtypes): write('#if ', tag, '\n') apply(dofunction, (returntype, fname) + argtypes) write('#endif /* ', tag, ' */\n') List[-1] = (tag, List[-1]) def dofunction(returntype, fname, *argtypes): pname = fname if pname[:len(Skip)] == Skip: pname = pname[len(Skip):] if '*' in argtypes: otype = Prefix else: otype = '' # # -- function heading write('static PyObject *\n') write(Prefix, '_', pname, '(') if otype: write(otype, 'object *self, ') else: write('PyObject *self, ') write('PyObject *args)\n') write('{\n') # # -- declare result retlist = [] if returntype <> 'void': if returntype == 'SUCCESS': r = 'Boolean' else: retlist.append((returntype, 'result')) r = returntype write('\t', r, ' result;\n') # # -- declare arguments, collect argument info arglist = [] fmtlist = '' nextarg = 1 winitialized = wCinitialized = 0 newargtypes = [] argdict = None for argtype in argtypes: if argtype == '*': argname = 'self' elif argtype[-1] == '0': argname = '0' else: argname = 'arg%d' % nextarg nextarg = nextarg + 1 if argtype[:7] == 'argdict': import string argdict = string.splitfields(argtype[8:], ',') if argdict[0] == '': del argdict[0] write('\tWidget w;\n') if len(argdict) > 0: write('\tWidgetClass wClist[%d];\n' % len(argdict)) else: write('\tWidgetClass wClist[1];\n') argtype = 'argdict' arglist.append((argtype, argname)) if argtype[0] == '>': # output parameter argtype = argtype[1:] retlist.append((argtype, argname)) else: # input parameter fmtlist = fmtlist + typedefs[argtype][FMT] declare(argtype, argname) newargtypes.append(argtype) argtypes = tuple(newargtypes) if len(retlist) > 1: write('\tPyObject *retval;\n') elif returntype not in ('void', 'SUCCESS') and \ len(typedefs[returntype]) > RCL: write('\tPyObject *retval;\n') if argdict is not None and len(argdict) > 0: for i in range(len(argdict)): write('\twClist[%d] = %s;\n' % (i, argdict[i])) wCinitialized = 1 if returntype == 'Widget' and argdict is None: write('\tPyObject *dict = NULL;\n') # # -- extract arguments, return if failure write('\tif (!PyArg_ParseTuple(args, "', fmtlist, '"') for argtype, argname in arglist: if argname not in ('0', 'self') and argtype[0] != '>': write(',\n') write('\t\t\t&', argname) write('))\n') write('\t\treturn NULL;\n') # # -- check structure arguments, return if failure for argtype, argname in arglist: if argtype[0] == '>': continue check(argtype, argname, returntype) if 'argdict' not in argtypes: continue if argtype == '*': write('\tw = self->ob_widget;\n') winitialized = 1 if not wCinitialized and \ 'WidgetClass' not in argtypes: write('\twClist[0] = XtClass(w);\n') wCinitialized = 1 elif argtype == 'Widget': write('\tw = getwidgetvalue(', argname, ');\n') winitialized = 1 if not wCinitialized and \ 'WidgetClass' not in argtypes and \ '*' not in argtypes: write('\twClist[0] = XtClass(w);\n') wCinitialized = 1 elif argtype == 'WidgetClass': if not winitialized and '*' not in argtypes and \ 'Widget' not in argtypes: write('\tw = NULL;\n') winitialized = 1 write('\twClist[0] = getwclassvalue(', argname, ');\n') wCinitialized = 1 # # -- call the function, with setjmp handling around write('\tif (!setjmp(jump_where)) {\n') write('\t\tjump_flag = 1;\n') write('\t\t') if returntype != 'void': write('result = ') write(fname, '(') sep = '' for argtype, argname in arglist: if argtype == 'argdict': if not winitialized and not wCinitialized: raise RuntimeError, \ '\'argdict\' must be preceded by Widget or WidgetClass arg' if argtype == '*' and 'argdict' in argtypes: write(sep, 'w') else: write(sep) if argtype[0] == '>': write('&') argtype = argtype[1:] write(extract(argtype, argname)) sep = ',\n\t\t\t' write(');\n') write('\t\tjump_flag = 0;\n') write('\t}\n') # # -- clean up afterwards for argtype, argname in arglist: if argtype[0] == '>': argtype = argtype[1:] cleanup(argtype, argname) # # -- error return if long-jumped write('\tif (jump_flag || PyErr_Occurred()) { jump_flag = 0; return NULL; }\n') # # -- do something about argdicts if fname[2:2+6] == 'Create' and 'argdict' in argtypes: for argtype, argname in arglist: if argtype == 'argdict': ## write('\tinit_res_dict(result, wClist, sizeof(wClist)/sizeof(wClist[0]));\n') break if returntype == 'SUCCESS': write('\tif (!result) {\n') write('\t\tPy_INCREF(Py_None);\n') write('\t\treturn Py_None;\n') write('\t}\n') # # return result if len(retlist) > 1: write('\tretval = PyTuple_New(',`len(retlist)`,');\n') for i in range(len(retlist)): argtype, argname = retlist[i] write('\tPyTuple_SetItem(retval, ', `i`, ', ', create(argtype, argname),');\n') write('\tif (PyErr_Occurred()) {\n') write('\t\tPy_XDECREF(retval);\n') write('\t\treturn NULL;\n') write('\t}\n') write('\treturn retval;\n') elif len(retlist) == 1: if returntype not in ('void', 'SUCCESS') and \ len(typedefs[returntype]) > RCL: write('\tretval = ', create(retlist[0][0], retlist[0][1]), ';\n') s = typedefs[returntype][RCL] if s: write('\t', s%{'arg':retlist[0][1]}, ';\n') write('\treturn retval;\n') else: write('\treturn ', create(retlist[0][0], retlist[0][1]), ';\n') else: write('\tPy_INCREF(Py_None);\n\treturn Py_None;\n') # # -- end of function body write('}\n') write('\n') # # -- administration List.append(pname) def mytaggedfunction(tag, returntype_unused, fname, *args_unused): apply(myfunction, (returntype_unused, fname) +args_unused) List[-1] = (tag, List[-1]) def myfunction(returntype_unused, fname, *args_unused): pname = fname if pname[:len(Skip)] == Skip: pname = pname[len(Skip):] List.append(pname) def listsort(a, b): if type(a) == type(()): a = a[1] if type(b) == type(()): b = b[1] if a < b: return -1 elif a == b: return 0 else: return 1 def dolist(listname = None, widgetClass = None, superchain = 'widget'): if listname is None: listname = Prefix write('static PyMethodDef ', listname, '_methods[] = {\n') List.sort(listsort) for pname in List: tag = '' if type(pname) == type(()): tag, pname = pname if tag: write('#if ', tag, '\n') writef('\t{"%s", (PyCFunction)%s_%s, 1},\n', pname, Prefix, pname) if tag: write('#endif /* ', tag, ' */\n') write('\t{0, 0} /* Sentinel */\n') write('};\n') if widgetClass: if type(widgetClass) == type(''): widgetClass = [widgetClass] write('PyMethodChain ', listname, '_methodchain = {\n') write('\t', listname, '_methods,\n') write('\t&', superchain, '_methodchain,\n') write('};\n') Lists.append((listname, widgetClass)) write('\n') del List[:] if listname is not Prefix or widgetClass is not None: setlist() def dotaggedlist(tag, listname = None, widgetClass = None, superchain = 'widget'): write('#if ', tag, '\n') dolist(listname, widgetClass, superchain) write('#endif /* ', tag, ' */\n') if widgetClass: Lists[-1] = (tag, Lists[-1]) # Stuff to generate complete widget set modules (e.g. Xm, Xaw) Widgets = [] Mname, Wname, Cname, Includef, Classnamef, Mskip = \ None, None, None, None, None, None def initwidgetset(mname, wname, cname, includef, classnamef, mskip): global Mname, Wname, Cname, Includef, Classnamef, Widgets, Mskip Mname, Wname, Cname, Includef, Classnamef, Mskip = \ mname, wname, cname, includef, classnamef, mskip del Widgets[:] def widgetset(mname, wname, cname, includef, classnamef, mskip): initwidgetset(mname, wname, cname, includef, classnamef, mskip) setfile(Mname + 'module.c') write('/* Widget Set ', Mname, ' */\n') write('\n') write('#include "Python.h"\n') write('#include "modsupport.h"\n') write('#include "import.h"\n') write('#include "widgetobject.h"\n') write('\n') write('#define is_optwidgetobject(x)\t((x) == Py_None || is_widgetobject(x))\n') write('#define getoptwidgetvalue(x)\t((x) == Py_None ? NULL : getwidgetvalue(x))\n') write('\n') def setmoduleprefix(): setprefix(Mname, Mskip) def setwidgetprefix(): setprefix(Wname, Mskip) def setwclassprefix(): setprefix(Cname, Mskip) def dotaggedwidget(tag, name, fname = '', cname = ''): write('#if ', tag, '\n') dowidget(name, fname, cname) write('#endif /* ', tag, ' */\n') Widgets[-1] = (tag, Widgets[-1]) def dowidget(name, fname = '', cname = ''): if fname == '': fname = name if cname == '': if type(Classnamef) == type(''): cname = Classnamef % name else: cname = Classnamef(name) cname = cname + 'WidgetClass' if fname <> None: include = Includef % fname write('#include ', include, '\n') write('\n') Widgets.append((name, cname)) initextras = [] def endwidgetset(listname = None): if listname is None: listname = Wname write('\n') write('PyMethodChain ', listname, '_methodchain = {\n') write('\t', listname, '_methods,\n') write('\tNULL,\n') write('};\n') write('PyMethodChain ', Cname, '_methodchain = {\n') write('\t', Cname, '_methods,\n') write('\t&wclass_methodchain,\n') write('};\n') write('\n') write('void\ninit', Mname, '()\n{\n') write('\tPyObject *m, *d;\n') write('\tm = PyImport_ImportModule("Xt");\n') write('\tif (m == NULL)\n') write('\t\tPy_FatalError("can\'t import module Xt for %s");\n' % Mname) write('\tPy_DECREF(m);\n') write('\tm = Py_InitModule("', Mname, '", ', Mname, '_methods);\n') write('\td = PyModule_GetDict(m);\n') write('\tadd_widget_methodchain(&', listname, '_methodchain);\n') makewidgets() write('}\n') def widgetsort(a, b): if type(a[1]) == type(()): a = a[1] if type(b[1]) == type(()): b = b[1] a = a[0] b = b[0] if a < b: return -1 elif a == b: return 0 else: return 1 def makewidgets(): Widgets.sort(widgetsort) for entry in Widgets: tag = '' if type(entry[1]) == type(()): tag, (name, cname) = entry else: name, cname = entry if tag: write('#if ', tag, '\n') write('\tPyDict_SetItemString(d, "', name, '",\n') write('\t\t(PyObject*)newwclassobject(', cname, ',\n') write('\t\t\t&', Cname, '_methodchain));\n') if tag: write('#endif /* ', tag, ' */\n') for line in initextras: write('\t' + line + '\n'); for entry in Lists: tag = None if type(entry[1]) == type(()): tag, entry = entry name, wClist = entry if tag: write('#if ', tag, '\n') for wC in wClist: write('\twidgetchainlist(', wC, ', &', name, '_methodchain);\n') if tag: write('#endif /* ', tag, ' */\n')