aboutsummaryrefslogtreecommitdiff
path: root/src/cgen
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgen')
-rw-r--r--src/cgen694
1 files changed, 347 insertions, 347 deletions
diff --git a/src/cgen b/src/cgen
index c2f0d0c..1e345d1 100644
--- a/src/cgen
+++ b/src/cgen
@@ -12,14 +12,14 @@ 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
+ 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
@@ -32,20 +32,20 @@ digits = '0123456789'
# 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
+ 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 0
- for c in s:
- if not c in digits: return 0
- return 1
+ if not s: return 0
+ for c in s:
+ if not c in digits: return 0
+ return 1
# Allowed function return types
@@ -59,26 +59,26 @@ arg_types = ['char', 'string', '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
+# 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
+# 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)
+# 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
@@ -96,67 +96,67 @@ arg_error = 'bad arg'
# 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)
- #
- # 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 sub[:3] <> 'arg' or not isnum(sub[3:]):
- raise arg_error, ('bad subscript', sub)
- #
- return type, mode, num, sub
+ #
+ # 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)
+ #
+ # 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 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
@@ -168,208 +168,208 @@ functions = []
# 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':
- e = 'Function', func, 'too complicated:'
- err(e + (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 object *'
- print 'gl_' + func + '(self, args)'
- print '\tobject *self;'
- print '\tobject *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,
- if a_sub:
- print '*',
- print 'arg' + `i+1`,
- if a_factor and not a_sub:
- 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, `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_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' + a_type + 'arraysize(args,',
- print `n_in_args` + ',',
- print `in_pos[j]` + ',',
- print '&arg' + `i+1` + '))'
- print '\t\treturn NULL;'
- if a_factor:
- print '\targ' + `i+1`,
- print '= arg' + `i+1`,
- print '/', a_factor + ';'
- elif a_mode = 's':
- if a_sub: # Allocate memory for varsize array
- print '\tif ((arg' + `i+1`, '=',
- print 'NEW(' + a_type + ',',
- if a_factor: print a_factor, '*',
- print a_sub, ')) == NULL)'
- print '\t\treturn err_nomem();'
- print '\tif',
- if a_factor or a_sub: # Get a fixed-size array array
- print '(!geti' + a_type + 'array(args,',
- print `n_in_args` + ',',
- print `in_pos[i]` + ',',
- if a_factor: print a_factor,
- if a_factor and a_sub: print '*',
- if a_sub: print a_sub,
- print ', arg' + `i+1` + '))'
- else: # Get a simple variable
- print '(!geti' + a_type + 'arg(args,',
- print `n_in_args` + ',',
- print `in_pos[i]` + ',',
- print '&arg' + `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' + `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:
- print '\tDEL(arg' + `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' + `i+1`) + ';'
- else:
- print '\t{ object *v = newtupleobject(',
- print n_out_args, ');'
- print '\t if (v == NULL) return NULL;'
- i_out = 0
- if type <> 'void':
- print '\t settupleitem(v,',
- print `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 settupleitem(v,',
- print `i_out` + ',',
- s = mkobject(a_type, 'arg' + `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 '\tINCREF(None);'
- print '\treturn None;'
- else:
- print '\treturn', mkobject(type, 'retval') + ';'
- #
- # Stub body closing brace
- #
- print '}'
+ #
+ # 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':
+ e = 'Function', func, 'too complicated:'
+ err(e + (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 object *'
+ print 'gl_' + func + '(self, args)'
+ print '\tobject *self;'
+ print '\tobject *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,
+ if a_sub:
+ print '*',
+ print 'arg' + `i+1`,
+ if a_factor and not a_sub:
+ 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, `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_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' + a_type + 'arraysize(args,',
+ print `n_in_args` + ',',
+ print `in_pos[j]` + ',',
+ print '&arg' + `i+1` + '))'
+ print '\t\treturn NULL;'
+ if a_factor:
+ print '\targ' + `i+1`,
+ print '= arg' + `i+1`,
+ print '/', a_factor + ';'
+ elif a_mode = 's':
+ if a_sub: # Allocate memory for varsize array
+ print '\tif ((arg' + `i+1`, '=',
+ print 'NEW(' + a_type + ',',
+ if a_factor: print a_factor, '*',
+ print a_sub, ')) == NULL)'
+ print '\t\treturn err_nomem();'
+ print '\tif',
+ if a_factor or a_sub: # Get a fixed-size array array
+ print '(!geti' + a_type + 'array(args,',
+ print `n_in_args` + ',',
+ print `in_pos[i]` + ',',
+ if a_factor: print a_factor,
+ if a_factor and a_sub: print '*',
+ if a_sub: print a_sub,
+ print ', arg' + `i+1` + '))'
+ else: # Get a simple variable
+ print '(!geti' + a_type + 'arg(args,',
+ print `n_in_args` + ',',
+ print `in_pos[i]` + ',',
+ print '&arg' + `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' + `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:
+ print '\tDEL(arg' + `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' + `i+1`) + ';'
+ else:
+ print '\t{ object *v = newtupleobject(',
+ print n_out_args, ');'
+ print '\t if (v == NULL) return NULL;'
+ i_out = 0
+ if type <> 'void':
+ print '\t settupleitem(v,',
+ print `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 settupleitem(v,',
+ print `i_out` + ',',
+ s = mkobject(a_type, 'arg' + `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 '\tINCREF(None);'
+ print '\treturn 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):
- return 'mknew' + type + 'object(' + arg + ')'
+ return 'mknew' + type + 'object(' + arg + ')'
# Input line number
@@ -377,8 +377,8 @@ lno = 0
# Input is divided in two parts, separated by a line containing '%%'.
-# <part1> -- literally copied to stdout
-# <part2> -- stub definitions
+# <part1> -- literally copied to stdout
+# <part2> -- stub definitions
# Variable indicating the current input part.
#
@@ -387,68 +387,68 @@ 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
- elif not words:
- pass # skip empty line
- elif 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)
+ 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
+ elif not words:
+ pass # skip empty line
+ elif 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 methodlist gl_methods[] = {'
for func in functions:
- print '\t{"' + func + '", gl_' + func + '},'
+ print '\t{"' + func + '", gl_' + func + '},'
print '\t{NULL, NULL} /* Sentinel */'
print '};'
print