diff options
Diffstat (limited to 'Modules/cgen.py')
-rw-r--r-- | Modules/cgen.py | 520 |
1 files changed, 0 insertions, 520 deletions
diff --git a/Modules/cgen.py b/Modules/cgen.py deleted file mode 100644 index 93c21b1..0000000 --- a/Modules/cgen.py +++ /dev/null @@ -1,520 +0,0 @@ -######################################################################## -# Copyright (c) 2000, BeOpen.com. -# Copyright (c) 1995-2000, Corporation for National Research Initiatives. -# Copyright (c) 1990-1995, Stichting Mathematisch Centrum. -# All rights reserved. -# -# See the file "Misc/COPYRIGHT" for information on usage and -# redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. -######################################################################## - -# Python script to parse cstubs file for gl and generate C stubs. -# usage: python cgen.py <cstubs >glmodule.c -# -# NOTE: You must first make a python binary without the "GL" option -# before you can run this, when building Python for the first time. -# See comments in the Makefile. -# -# XXX BUG return arrays generate wrong code -# XXX need to change error returns into gotos to free mallocked arrays - - -import string -import sys - - -# Function to print to stderr -# -def err(*args): - savestdout = sys.stdout - try: - sys.stdout = sys.stderr - for i in args: - print i, - print - finally: - sys.stdout = savestdout - - -# The set of digits that form a number -# -digits = '0123456789' - - -# Function to extract a string of digits from the front of the string. -# Returns the leading string of digits and the remaining string. -# If no number is found, returns '' and the original string. -# -def getnum(s): - n = '' - while s and s[0] in digits: - n = n + s[0] - s = s[1:] - return n, s - - -# Function to check if a string is a number -# -def isnum(s): - if not s: return False - for c in s: - if not c in digits: return False - return True - - -# Allowed function return types -# -return_types = ['void', 'short', 'long'] - - -# Allowed function argument types -# -arg_types = ['char', 'string', 'short', 'u_short', 'float', 'long', 'double'] - - -# Need to classify arguments as follows -# simple input variable -# simple output variable -# input array -# output array -# input giving size of some array -# -# Array dimensions can be specified as follows -# constant -# argN -# constant * argN -# retval -# constant * retval -# -# The dimensions given as constants * something are really -# arrays of points where points are 2- 3- or 4-tuples -# -# We have to consider three lists: -# python input arguments -# C stub arguments (in & out) -# python output arguments (really return values) -# -# There is a mapping from python input arguments to the input arguments -# of the C stub, and a further mapping from C stub arguments to the -# python return values - - -# Exception raised by checkarg() and generate() -# -arg_error = 'bad arg' - - -# Function to check one argument. -# Arguments: the type and the arg "name" (really mode plus subscript). -# Raises arg_error if something's wrong. -# Return type, mode, factor, rest of subscript; factor and rest may be empty. -# -def checkarg(type, arg): - # - # Turn "char *x" into "string x". - # - if type == 'char' and arg[0] == '*': - type = 'string' - arg = arg[1:] - # - # Check that the type is supported. - # - if type not in arg_types: - raise arg_error, ('bad type', type) - if type[:2] == 'u_': - type = 'unsigned ' + type[2:] - # - # Split it in the mode (first character) and the rest. - # - mode, rest = arg[:1], arg[1:] - # - # The mode must be 's' for send (= input) or 'r' for return argument. - # - if mode not in ('r', 's'): - raise arg_error, ('bad arg mode', mode) - # - # Is it a simple argument: if so, we are done. - # - if not rest: - return type, mode, '', '' - # - # Not a simple argument; must be an array. - # The 'rest' must be a subscript enclosed in [ and ]. - # The subscript must be one of the following forms, - # otherwise we don't handle it (where N is a number): - # N - # argN - # retval - # N*argN - # N*retval - # - if rest[:1] != '[' or rest[-1:] != ']': - raise arg_error, ('subscript expected', rest) - sub = rest[1:-1] - # - # Is there a leading number? - # - num, sub = getnum(sub) - if num: - # There is a leading number - if not sub: - # The subscript is just a number - return type, mode, num, '' - if sub[:1] == '*': - # There is a factor prefix - sub = sub[1:] - else: - raise arg_error, ('\'*\' expected', sub) - if sub == 'retval': - # size is retval -- must be a reply argument - if mode != 'r': - raise arg_error, ('non-r mode with [retval]', mode) - elif not isnum(sub) and (sub[:3] != 'arg' or not isnum(sub[3:])): - raise arg_error, ('bad subscript', sub) - # - return type, mode, num, sub - - -# List of functions for which we have generated stubs -# -functions = [] - - -# Generate the stub for the given function, using the database of argument -# information build by successive calls to checkarg() -# -def generate(type, func, database): - # - # Check that we can handle this case: - # no variable size reply arrays yet - # - n_in_args = 0 - n_out_args = 0 - # - for a_type, a_mode, a_factor, a_sub in database: - if a_mode == 's': - n_in_args = n_in_args + 1 - elif a_mode == 'r': - n_out_args = n_out_args + 1 - else: - # Can't happen - raise arg_error, ('bad a_mode', a_mode) - if (a_mode == 'r' and a_sub) or a_sub == 'retval': - err('Function', func, 'too complicated:', - a_type, a_mode, a_factor, a_sub) - print '/* XXX Too complicated to generate code for */' - return - # - functions.append(func) - # - # Stub header - # - print - print 'static PyObject *' - print 'gl_' + func + '(self, args)' - print '\tPyObject *self;' - print '\tPyObject *args;' - print '{' - # - # Declare return value if any - # - if type != 'void': - print '\t' + type, 'retval;' - # - # Declare arguments - # - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - print '\t' + a_type, - brac = ket = '' - if a_sub and not isnum(a_sub): - if a_factor: - brac = '(' - ket = ')' - print brac + '*', - print 'arg' + repr(i+1) + ket, - if a_sub and isnum(a_sub): - print '[', a_sub, ']', - if a_factor: - print '[', a_factor, ']', - print ';' - # - # Find input arguments derived from array sizes - # - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 's' and a_sub[:3] == 'arg' and isnum(a_sub[3:]): - # Sending a variable-length array - n = eval(a_sub[3:]) - if 1 <= n <= len(database): - b_type, b_mode, b_factor, b_sub = database[n-1] - if b_mode == 's': - database[n-1] = b_type, 'i', a_factor, repr(i) - n_in_args = n_in_args - 1 - # - # Assign argument positions in the Python argument list - # - in_pos = [] - i_in = 0 - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 's': - in_pos.append(i_in) - i_in = i_in + 1 - else: - in_pos.append(-1) - # - # Get input arguments - # - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_type[:9] == 'unsigned ': - xtype = a_type[9:] - else: - xtype = a_type - if a_mode == 'i': - # - # Implicit argument; - # a_factor is divisor if present, - # a_sub indicates which arg (`database index`) - # - j = eval(a_sub) - print '\tif', - print '(!geti' + xtype + 'arraysize(args,', - print repr(n_in_args) + ',', - print repr(in_pos[j]) + ',', - if xtype != a_type: - print '('+xtype+' *)', - print '&arg' + repr(i+1) + '))' - print '\t\treturn NULL;' - if a_factor: - print '\targ' + repr(i+1), - print '= arg' + repr(i+1), - print '/', a_factor + ';' - elif a_mode == 's': - if a_sub and not isnum(a_sub): - # Allocate memory for varsize array - print '\tif ((arg' + repr(i+1), '=', - if a_factor: - print '('+a_type+'(*)['+a_factor+'])', - print 'PyMem_NEW(' + a_type, ',', - if a_factor: - print a_factor, '*', - print a_sub, ')) == NULL)' - print '\t\treturn PyErr_NoMemory();' - print '\tif', - if a_factor or a_sub: # Get a fixed-size array array - print '(!geti' + xtype + 'array(args,', - print repr(n_in_args) + ',', - print repr(in_pos[i]) + ',', - if a_factor: print a_factor, - if a_factor and a_sub: print '*', - if a_sub: print a_sub, - print ',', - if (a_sub and a_factor) or xtype != a_type: - print '('+xtype+' *)', - print 'arg' + repr(i+1) + '))' - else: # Get a simple variable - print '(!geti' + xtype + 'arg(args,', - print repr(n_in_args) + ',', - print repr(in_pos[i]) + ',', - if xtype != a_type: - print '('+xtype+' *)', - print '&arg' + repr(i+1) + '))' - print '\t\treturn NULL;' - # - # Begin of function call - # - if type != 'void': - print '\tretval =', func + '(', - else: - print '\t' + func + '(', - # - # Argument list - # - for i in range(len(database)): - if i > 0: print ',', - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 'r' and not a_factor: - print '&', - print 'arg' + repr(i+1), - # - # End of function call - # - print ');' - # - # Free varsize arrays - # - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 's' and a_sub and not isnum(a_sub): - print '\tPyMem_DEL(arg' + repr(i+1) + ');' - # - # Return - # - if n_out_args: - # - # Multiple return values -- construct a tuple - # - if type != 'void': - n_out_args = n_out_args + 1 - if n_out_args == 1: - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 'r': - break - else: - raise arg_error, 'expected r arg not found' - print '\treturn', - print mkobject(a_type, 'arg' + repr(i+1)) + ';' - else: - print '\t{ PyObject *v = PyTuple_New(', - print n_out_args, ');' - print '\t if (v == NULL) return NULL;' - i_out = 0 - if type != 'void': - print '\t PyTuple_SetItem(v,', - print repr(i_out) + ',', - print mkobject(type, 'retval') + ');' - i_out = i_out + 1 - for i in range(len(database)): - a_type, a_mode, a_factor, a_sub = database[i] - if a_mode == 'r': - print '\t PyTuple_SetItem(v,', - print repr(i_out) + ',', - s = mkobject(a_type, 'arg' + repr(i+1)) - print s + ');' - i_out = i_out + 1 - print '\t return v;' - print '\t}' - else: - # - # Simple function return - # Return None or return value - # - if type == 'void': - print '\tPy_INCREF(Py_None);' - print '\treturn Py_None;' - else: - print '\treturn', mkobject(type, 'retval') + ';' - # - # Stub body closing brace - # - print '}' - - -# Subroutine to return a function call to mknew<type>object(<arg>) -# -def mkobject(type, arg): - if type[:9] == 'unsigned ': - type = type[9:] - return 'mknew' + type + 'object((' + type + ') ' + arg + ')' - return 'mknew' + type + 'object(' + arg + ')' - - -defined_archs = [] - -# usage: cgen [ -Dmach ... ] [ file ] -for arg in sys.argv[1:]: - if arg[:2] == '-D': - defined_archs.append(arg[2:]) - else: - # Open optional file argument - sys.stdin = open(arg, 'r') - - -# Input line number -lno = 0 - - -# Input is divided in two parts, separated by a line containing '%%'. -# <part1> -- literally copied to stdout -# <part2> -- stub definitions - -# Variable indicating the current input part. -# -part = 1 - -# Main loop over the input -# -while 1: - try: - line = raw_input() - except EOFError: - break - # - lno = lno+1 - words = string.split(line) - # - if part == 1: - # - # In part 1, copy everything literally - # except look for a line of just '%%' - # - if words == ['%%']: - part = part + 1 - else: - # - # Look for names of manually written - # stubs: a single percent followed by the name - # of the function in Python. - # The stub name is derived by prefixing 'gl_'. - # - if words and words[0][0] == '%': - func = words[0][1:] - if (not func) and words[1:]: - func = words[1] - if func: - functions.append(func) - else: - print line - continue - if not words: - continue # skip empty line - elif words[0] == 'if': - # if XXX rest - # if !XXX rest - if words[1][0] == '!': - if words[1][1:] in defined_archs: - continue - elif words[1] not in defined_archs: - continue - words = words[2:] - if words[0] == '#include': - print line - elif words[0][:1] == '#': - pass # ignore comment - elif words[0] not in return_types: - err('Line', lno, ': bad return type :', words[0]) - elif len(words) < 2: - err('Line', lno, ': no funcname :', line) - else: - if len(words) % 2 != 0: - err('Line', lno, ': odd argument list :', words[2:]) - else: - database = [] - try: - for i in range(2, len(words), 2): - x = checkarg(words[i], words[i+1]) - database.append(x) - print - print '/*', - for w in words: print w, - print '*/' - generate(words[0], words[1], database) - except arg_error, msg: - err('Line', lno, ':', msg) - - -print -print 'static struct PyMethodDef gl_methods[] = {' -for func in functions: - print '\t{"' + func + '", gl_' + func + '},' -print '\t{NULL, NULL} /* Sentinel */' -print '};' -print -print 'void' -print 'initgl()' -print '{' -print '\t(void) Py_InitModule("gl", gl_methods);' -print '}' |