diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/python-2.6.1/Modules/cgen.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/python-2.6.1/Modules/cgen.py Fri Jul 31 15:01:17 2009 +0100 @@ -0,0 +1,523 @@ +######################################################################## +# 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 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 +from warnings import warnpy3k +warnpy3k("the cgen module has been removed in Python 3.0", stacklevel=2) +del warnpy3k + + +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 mknewobject() +# +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 '%%'. +# -- literally copied to stdout +# -- 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 '}'