1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
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 <Python.h>
#include <stdio.h>
#include "libnumarray.h"
'''
_TYPE_SEPARATOR = \
'''
/****************** <typename> *******************/
'''
_METHODS_DEF = \
'''
static PyMethodDef <module>Methods[] = {
<module_methods>
\t{NULL, NULL} /* Sentinel */
};
'''
_ADDMETHOD_TEMPLATE = \
'''\t{ "%s", %s, METH_VARARGS},
'''
_TAIL = \
'''
/* platform independent*/
#ifdef MS_WIN32
__declspec(dllexport)
#endif
void init<module>(void) {
PyObject *m, *d, *functions;
m = Py_InitModule("<module>", <module>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> --> %(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))
|