######################################################################### 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 arraysfrom warnings import warnpy3kwarnpy3k("the cgen module has been removed in Python 3.0", stacklevel=2)del warnpy3kimport stringimport sys# Function to print to stderr#def err(*args):savestdout = sys.stdouttry:sys.stdout = sys.stderrfor i in args:print i,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 Falsefor c in s:if not c in digits: return Falsereturn 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 numberif not sub:# The subscript is just a numberreturn type, mode, num, ''if sub[:1] == '*':# There is a factor prefixsub = sub[1:]else:raise arg_error, ('\'*\' expected', sub)if sub == 'retval':# size is retval -- must be a reply argumentif 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 = 0n_out_args = 0#for a_type, a_mode, a_factor, a_sub in database:if a_mode == 's':n_in_args = n_in_args + 1elif a_mode == 'r':n_out_args = n_out_args + 1else:# Can't happenraise 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 '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 arrayn = 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 = 0for 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 + 1else: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_typeif 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 arrayprint '\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 arrayprint '(!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 variableprint '(!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 + 1if n_out_args == 1:for i in range(len(database)):a_type, a_mode, a_factor, a_sub = database[i]if a_mode == 'r':breakelse: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 = 0if type <> 'void':print '\t PyTuple_SetItem(v,',print repr(i_out) + ',',print mkobject(type, 'retval') + ');'i_out = i_out + 1for 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 + 1print '\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 argumentsys.stdin = open(arg, 'r')# Input line numberlno = 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+1words = string.split(line)#if part == 1:## In part 1, copy everything literally# except look for a line of just '%%'#if words == ['%%']:part = part + 1else:## 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 linecontinueif not words:continue # skip empty lineelif words[0] == 'if':# if XXX rest# if !XXX restif words[1][0] == '!':if words[1][1:] in defined_archs:continueelif words[1] not in defined_archs:continuewords = words[2:]if words[0] == '#include':print lineelif words[0][:1] == '#':pass # ignore commentelif 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 '/*',for w in words: print w,print '*/'generate(words[0], words[1], database)except arg_error, msg:err('Line', lno, ':', msg)print 'static struct PyMethodDef gl_methods[] = {'for func in functions:print '\t{"' + func + '", gl_' + func + '},'print '\t{NULL, NULL} /* Sentinel */'print '};'print 'void'print 'initgl()'print '{'print '\t(void) Py_InitModule("gl", gl_methods);'print '}'
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。