| 
									
										
										
										
											1994-08-01 11:34:53 +00:00
										 |  |  | ######################################################################## | 
					
						
							| 
									
										
										
										
											2000-07-01 00:16:13 +00:00
										 |  |  | # Copyright (c) 2000, BeOpen.com. | 
					
						
							|  |  |  | # Copyright (c) 1995-2000, Corporation for National Research Initiatives. | 
					
						
							|  |  |  | # Copyright (c) 1990-1995, Stichting Mathematisch Centrum. | 
					
						
							|  |  |  | # All rights reserved. | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2000-07-01 00:16:13 +00:00
										 |  |  | # See the file "Misc/COPYRIGHT" for information on usage and | 
					
						
							|  |  |  | # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. | 
					
						
							| 
									
										
										
										
											1994-08-01 11:34:53 +00:00
										 |  |  | ######################################################################## | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # Python script to parse cstubs file for gl and generate C stubs. | 
					
						
							| 
									
										
										
										
											1991-08-16 08:57:40 +00:00
										 |  |  | # usage: python cgen.py <cstubs >glmodule.c | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											1991-10-20 20:28:02 +00:00
										 |  |  | # NOTE: You  must first make a python binary without the "GL" option | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | #       before you can run this, when building Python for the first time. | 
					
						
							|  |  |  | #       See comments in the Makefile. | 
					
						
							| 
									
										
										
										
											1991-10-20 20:28:02 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # 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 | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											1995-07-07 22:39:14 +00:00
										 |  |  | def err(*args): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     savestdout = sys.stdout | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         sys.stdout = sys.stderr | 
					
						
							|  |  |  |         for i in args: | 
					
						
							|  |  |  |             print i, | 
					
						
							|  |  |  |         print | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         sys.stdout = savestdout | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     n = '' | 
					
						
							|  |  |  |     while s and s[0] in digits: | 
					
						
							|  |  |  |         n = n + s[0] | 
					
						
							|  |  |  |         s = s[1:] | 
					
						
							|  |  |  |     return n, s | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Function to check if a string is a number | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | def isnum(s): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     if not s: return False | 
					
						
							|  |  |  |     for c in s: | 
					
						
							|  |  |  |         if not c in digits: return False | 
					
						
							|  |  |  |     return True | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Allowed function return types | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | return_types = ['void', 'short', 'long'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Allowed function argument types | 
					
						
							|  |  |  | # | 
					
						
							| 
									
										
										
										
											1993-12-21 17:06:12 +00:00
										 |  |  | arg_types = ['char', 'string', 'short', 'u_short', 'float', 'long', 'double'] | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Need to classify arguments as follows | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | #       simple input variable | 
					
						
							|  |  |  | #       simple output variable | 
					
						
							|  |  |  | #       input array | 
					
						
							|  |  |  | #       output array | 
					
						
							|  |  |  | #       input giving size of some array | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # Array dimensions can be specified as follows | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | #       constant | 
					
						
							|  |  |  | #       argN | 
					
						
							|  |  |  | #       constant * argN | 
					
						
							|  |  |  | #       retval | 
					
						
							|  |  |  | #       constant * retval | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # 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: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | #       python input arguments | 
					
						
							|  |  |  | #       C stub arguments (in & out) | 
					
						
							|  |  |  | #       python output arguments (really return values) | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # 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): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     # | 
					
						
							|  |  |  |     # 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 | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     # | 
					
						
							|  |  |  |     # 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 '}' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Subroutine to return a function call to mknew<type>object(<arg>) | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | def mkobject(type, arg): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     if type[:9] == 'unsigned ': | 
					
						
							|  |  |  |         type = type[9:] | 
					
						
							|  |  |  |         return 'mknew' + type + 'object((' + type + ') ' + arg + ')' | 
					
						
							|  |  |  |     return 'mknew' + type + 'object(' + arg + ')' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-12-21 17:06:12 +00:00
										 |  |  | defined_archs = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # usage: cgen [ -Dmach ... ] [ file ] | 
					
						
							|  |  |  | for arg in sys.argv[1:]: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     if arg[:2] == '-D': | 
					
						
							|  |  |  |         defined_archs.append(arg[2:]) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         # Open optional file argument | 
					
						
							|  |  |  |         sys.stdin = open(arg, 'r') | 
					
						
							| 
									
										
										
										
											1992-09-11 23:55:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | # Input line number | 
					
						
							|  |  |  | lno = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Input is divided in two parts, separated by a line containing '%%'. | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | #       <part1>         -- literally copied to stdout | 
					
						
							|  |  |  | #       <part2>         -- stub definitions | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Variable indicating the current input part. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | part = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Main loop over the input | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | while 1: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     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) | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print | 
					
						
							| 
									
										
										
										
											1997-04-29 15:39:28 +00:00
										 |  |  | print 'static struct PyMethodDef gl_methods[] = {' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | for func in functions: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     print '\t{"' + func + '", gl_' + func + '},' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | print '\t{NULL, NULL} /* Sentinel */' | 
					
						
							|  |  |  | print '};' | 
					
						
							|  |  |  | print | 
					
						
							| 
									
										
										
										
											1996-12-09 18:51:51 +00:00
										 |  |  | print 'void' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | print 'initgl()' | 
					
						
							|  |  |  | print '{' | 
					
						
							| 
									
										
										
										
											1997-04-29 21:34:16 +00:00
										 |  |  | print '\t(void) Py_InitModule("gl", gl_methods);' | 
					
						
							| 
									
										
										
										
											1990-10-14 12:07:46 +00:00
										 |  |  | print '}' |