import sys, os, imp try: import template except ImportError: # Make sure autoclutter can be found even though it isn't installed yet. file, path, descr = imp.find_module("template") template = imp.load_module("template", file, path, descr) def hasUInt64(): # Anything but win32 and MSVC 6 return not (sys.platform == "win32" and sys.version.find("MSC") >= 0 and sys.version.find("v.13") < 0) def hasFloat128(): return False def all_types(): _all_types = ["Bool", "Int8", "UInt8", "Int16", "UInt16", "Int32", "UInt32", "Float32", "Float64", "Complex32","Complex64"] _all_types.append("Int64") if hasUInt64(): _all_types.append("UInt64") return _all_types """This program generates multiple c source code files It handles the tedium of all the repetitive code dealing with types and particularly combinations of types with types and types with functions. $Id: basecode.py,v 1.7 2005/06/14 21:28:31 jaytmiller Exp $ """ #*********************************************************************# # # # DATA SECTION # # # #*********************************************************************# # Of course, the warning below does not apply to this file! _HEADER = \ ''' /* W W AAA RRRR N N III N N GGG !!! ** W W A A R R NN N I NN N G G !!! ** W W W AAAAA RRRR N N N I N N N G ! ** W W W A A R R N NN I N NN G GG ** W W A A R R N N III N N GGG !!! ** ** WARNING: This file is program generated by codegenerator.py. ** ** DO NOT EDIT THIS FILE! Any changes made to this file will be lost! */ #include #include #include "libnumarray.h" ''' _TYPE_SEPARATOR = \ ''' /****************** *******************/ ''' _METHODS_DEF = \ ''' static PyMethodDef Methods[] = { \t{NULL, NULL} /* Sentinel */ }; ''' _ADDMETHOD_TEMPLATE = \ '''\t{ "%s", %s, METH_VARARGS}, ''' _TAIL = \ ''' /* platform independent*/ #ifdef MS_WIN32 __declspec(dllexport) #endif void init(void) { PyObject *m, *d, *functions; m = Py_InitModule("", Methods); d = PyModule_GetDict(m); import_libnumarray(); functions = init_funcDict(); PyDict_SetItemString(d, "functionDict", functions); Py_DECREF(functions); ADD_VERSION(m); } ''' #*********************************************************************# # data for filling function table # #*********************************************************************# _CFUNCDICT_HEADER = \ ''' static PyObject *init_funcDict(void) { PyObject *dict; dict = PyDict_New(); ''' _ADDCFUNC_TEMPLATE = \ ''' NA_add_cfunc(dict, "%s", (void *) &%s_descr); ''' _CFUNCDICT_TAIL = \ ''' return dict; } ''' # ============================================================================ # IMPORTANT: no <>-sugared strings below this point # translate --> %(var)s in templates seen *so far* template.sugar_dict(globals()) # ============================================================================ #*********************************************************************# # # # PROGRAM SECTION # # # #*********************************************************************# """ The classes below assemble the various elements defined in the previous part of the module into the final C modules. Each subclass of CodeGenerator works basically the same way: It is constructed by supplying optional module unique header, tail, and function separator. When called, a CodeGenerator builds up two lists of strings by calling its "bodygenerator()" method. Looping over a parameter table, the bodygenerator builds: 1. A code list containing the instantiated header and emitted function bodies. This is the bulk of the code. 2. A function list containing the C struct initializers which are used to register the function bodies with python. These are necessarily in a seperate textual segment so that they may be joined in an array and looped over at initialization time. In general, templates are instantiated by formatting them either using a CodeGenerator instance dict, or a Params instance dict. After generating its two lists, a CodeGenerator combines them into the complete C code for a python module and writes the code out to the specified file. CodeGenerator subclasses customize behavior by overriding the "bodygenerator" and "addcfunc" methods. Each "bodygenerator" tends to be tailored to the parameter table used to specify the cfuncs for the module. Several of the codegenerators (cconv, ufunc, bytes) are supported by a "Params" class, instances of which act as table records. As the body generator loops over the parameter table, it creates a Params instance from each record. The Params instance dictionary then provides a source of keyword values to instantiate the code template. See ConvParams, ByteParams, and UfuncParams. Each is essentially a struct. In general, template instantiation is performed by string substitution using the python %(identifier)s syntax. The %(indentifer)s syntax permits a string to be formatted using a dictionary to supply identifier values. """ class CodeGenerator: """Generates source code using supplied functions and code templates""" _cfuncdict_header=_CFUNCDICT_HEADER _cfuncdict_tail=_CFUNCDICT_TAIL _addcfunc_template=_ADDCFUNC_TEMPLATE _methods_def=_METHODS_DEF _addmethod_template=_ADDMETHOD_TEMPLATE def __init__(self, header=_HEADER, tail=_TAIL, config=None, separator=_TYPE_SEPARATOR): self.header = header self.tail = tail self.separator = separator self.config = config self.module_methods = "" def gen_header(self): self.codelist = [ self.header % self.__dict__] self.funclist = [ self._cfuncdict_header ] def gen_trailer(self): self.funclist.append(self._cfuncdict_tail) self.codelist.append(self._methods_def % self.__dict__) self.codelist.extend(self.funclist) self.codelist.append(self.tail % self.__dict__) def emit_code(self, file): sourcecode = "".join(self.codelist) if file: f = open(file,"w") f.write(sourcecode) f.close() else: return sourcecode def __call__(self, file=None, Type=None): self.gen_header() if Type is None: self.gen_body() else: self.gen_body(Type) self.gen_trailer() return self.emit_code(file) def addcfunc(self, name, key=None): if key is None: key = name self.funclist.append(self._addcfunc_template % (key, name)) def addmethod(self, name, key=None): if key is None: key = name self.module_methods += (self._addmethod_template % (key, name))