Home | History | Annotate | Download | only in ABITest
      1 #!/usr/bin/env python
      2 
      3 from pprint import pprint
      4 import random, atexit, time
      5 from random import randrange
      6 import re
      7 
      8 from Enumeration import *
      9 from TypeGen import *
     10 
     11 ####
     12 
     13 class TypePrinter:
     14     def __init__(self, output, outputHeader=None, 
     15                  outputTests=None, outputDriver=None,
     16                  headerName=None, info=None):
     17         self.output = output
     18         self.outputHeader = outputHeader
     19         self.outputTests = outputTests
     20         self.outputDriver = outputDriver
     21         self.writeBody = outputHeader or outputTests or outputDriver
     22         self.types = {}
     23         self.testValues = {}
     24         self.testReturnValues = {}
     25         self.layoutTests = []
     26         self.declarations = set()
     27 
     28         if info:
     29             for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver):
     30                 if f:
     31                     print >>f,info
     32 
     33         if self.writeBody:
     34             print >>self.output, '#include <stdio.h>\n'
     35             if self.outputTests:
     36                 print >>self.outputTests, '#include <stdio.h>'
     37                 print >>self.outputTests, '#include <string.h>'
     38                 print >>self.outputTests, '#include <assert.h>\n'
     39 
     40         if headerName:
     41             for f in (self.output,self.outputTests,self.outputDriver):
     42                 if f is not None:
     43                     print >>f, '#include "%s"\n'%(headerName,)
     44         
     45         if self.outputDriver:
     46             print >>self.outputDriver, '#include <stdio.h>'
     47             print >>self.outputDriver, '#include <stdlib.h>\n'
     48             print >>self.outputDriver, 'int main(int argc, char **argv) {'
     49             print >>self.outputDriver, '  int index = -1;'
     50             print >>self.outputDriver, '  if (argc > 1) index = atoi(argv[1]);'
     51             
     52     def finish(self):
     53         if self.layoutTests:
     54             print >>self.output, 'int main(int argc, char **argv) {'
     55             print >>self.output, '  int index = -1;'
     56             print >>self.output, '  if (argc > 1) index = atoi(argv[1]);'
     57             for i,f in self.layoutTests:
     58                 print >>self.output, '  if (index == -1 || index == %d)' % i
     59                 print >>self.output, '    %s();' % f
     60             print >>self.output, '  return 0;'
     61             print >>self.output, '}' 
     62 
     63         if self.outputDriver:
     64             print >>self.outputDriver, '  printf("DONE\\n");'
     65             print >>self.outputDriver, '  return 0;'
     66             print >>self.outputDriver, '}'        
     67 
     68     def addDeclaration(self, decl):
     69         if decl in self.declarations:
     70             return False
     71 
     72         self.declarations.add(decl)
     73         if self.outputHeader:
     74             print >>self.outputHeader, decl
     75         else:
     76             print >>self.output, decl
     77             if self.outputTests:
     78                 print >>self.outputTests, decl
     79         return True
     80 
     81     def getTypeName(self, T):
     82         name = self.types.get(T)
     83         if name is None:            
     84             # Reserve slot
     85             self.types[T] = None
     86             self.types[T] = name = T.getTypeName(self)
     87         return name
     88     
     89     def writeLayoutTest(self, i, ty):
     90         tyName = self.getTypeName(ty)
     91         tyNameClean = tyName.replace(' ','_').replace('*','star')
     92         fnName = 'test_%s' % tyNameClean
     93             
     94         print >>self.output,'void %s(void) {' % fnName
     95         self.printSizeOfType('    %s'%fnName, tyName, ty, self.output)
     96         self.printAlignOfType('    %s'%fnName, tyName, ty, self.output)
     97         self.printOffsetsOfType('    %s'%fnName, tyName, ty, self.output)
     98         print >>self.output,'}'
     99         print >>self.output
    100         
    101         self.layoutTests.append((i,fnName))
    102         
    103     def writeFunction(self, i, FT):
    104         args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)])
    105         if not args:
    106             args = 'void'
    107 
    108         if FT.returnType is None:
    109             retvalName = None
    110             retvalTypeName = 'void'
    111         else:
    112             retvalTypeName = self.getTypeName(FT.returnType)
    113             if self.writeBody or self.outputTests:
    114                 retvalName = self.getTestReturnValue(FT.returnType)
    115 
    116         fnName = 'fn%d'%(FT.index,)
    117         if self.outputHeader:
    118             print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args)
    119         elif self.outputTests:
    120             print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args)
    121             
    122         print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args),
    123         if self.writeBody:
    124             print >>self.output, '{'
    125             
    126             for i,t in enumerate(FT.argTypes):
    127                 self.printValueOfType('    %s'%fnName, 'arg%d'%i, t)
    128 
    129             if retvalName is not None:
    130                 print >>self.output, '  return %s;'%(retvalName,)
    131             print >>self.output, '}'
    132         else:
    133             print >>self.output, '{}'
    134         print >>self.output
    135 
    136         if self.outputDriver:
    137             print >>self.outputDriver, '  if (index == -1 || index == %d) {' % i
    138             print >>self.outputDriver, '    extern void test_%s(void);' % fnName
    139             print >>self.outputDriver, '    test_%s();' % fnName
    140             print >>self.outputDriver, '   }'
    141             
    142         if self.outputTests:
    143             if self.outputHeader:
    144                 print >>self.outputHeader, 'void test_%s(void);'%(fnName,)
    145 
    146             if retvalName is None:
    147                 retvalTests = None
    148             else:
    149                 retvalTests = self.getTestValuesArray(FT.returnType)
    150             tests = map(self.getTestValuesArray, FT.argTypes)
    151             print >>self.outputTests, 'void test_%s(void) {'%(fnName,)
    152 
    153             if retvalTests is not None:
    154                 print >>self.outputTests, '  printf("%s: testing return.\\n");'%(fnName,)
    155                 print >>self.outputTests, '  for (int i=0; i<%d; ++i) {'%(retvalTests[1],)
    156                 args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests])
    157                 print >>self.outputTests, '    %s RV;'%(retvalTypeName,)
    158                 print >>self.outputTests, '    %s = %s[i];'%(retvalName, retvalTests[0])
    159                 print >>self.outputTests, '    RV = %s(%s);'%(fnName, args)
    160                 self.printValueOfType('  %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4)
    161                 self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4)
    162                 print >>self.outputTests, '  }'
    163             
    164             if tests:
    165                 print >>self.outputTests, '  printf("%s: testing arguments.\\n");'%(fnName,)
    166             for i,(array,length) in enumerate(tests):
    167                 for j in range(length):
    168                     args = ['%s[%d]'%(t,randrange(l)) for t,l in tests]
    169                     args[i] = '%s[%d]'%(array,j)
    170                     print >>self.outputTests, '  %s(%s);'%(fnName, ', '.join(args),)
    171             print >>self.outputTests, '}'
    172 
    173     def getTestReturnValue(self, type):
    174         typeName = self.getTypeName(type)        
    175         info = self.testReturnValues.get(typeName)
    176         if info is None:
    177             name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),)
    178             print >>self.output, '%s %s;'%(typeName,name)
    179             if self.outputHeader:
    180                 print >>self.outputHeader, 'extern %s %s;'%(typeName,name)
    181             elif self.outputTests:                
    182                 print >>self.outputTests, 'extern %s %s;'%(typeName,name)
    183             info = self.testReturnValues[typeName] = name
    184         return info
    185 
    186     def getTestValuesArray(self, type):
    187         typeName = self.getTypeName(type)        
    188         info = self.testValues.get(typeName)
    189         if info is None:
    190             name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),)
    191             print >>self.outputTests, 'static %s %s[] = {'%(typeName,name)
    192             length = 0
    193             for item in self.getTestValues(type):
    194                 print >>self.outputTests, '\t%s,'%(item,)
    195                 length += 1
    196             print >>self.outputTests,'};'
    197             info = self.testValues[typeName] = (name,length)
    198         return info
    199 
    200     def getTestValues(self, t):
    201         if isinstance(t, BuiltinType):
    202             if t.name=='float':
    203                 for i in ['0.0','-1.0','1.0']:
    204                     yield i+'f'
    205             elif t.name=='double':
    206                 for i in ['0.0','-1.0','1.0']:
    207                     yield i
    208             elif t.name in ('void *'):
    209                 yield '(void*) 0'
    210                 yield '(void*) -1'
    211             else:
    212                 yield '(%s) 0'%(t.name,)
    213                 yield '(%s) -1'%(t.name,)
    214                 yield '(%s) 1'%(t.name,)
    215         elif isinstance(t, EnumType):
    216             for i in range(0, len(t.enumerators)):
    217                 yield 'enum%dval%d' % (t.index, i)
    218         elif isinstance(t, RecordType):
    219             nonPadding = [f for f in t.fields 
    220                           if not f.isPaddingBitField()]
    221 
    222             if not nonPadding:
    223                 yield '{ }'
    224                 return
    225 
    226             # FIXME: Use designated initializers to access non-first
    227             # fields of unions.
    228             if t.isUnion:
    229                 for v in self.getTestValues(nonPadding[0]):
    230                     yield '{ %s }' % v
    231                 return
    232 
    233             fieldValues = map(list, map(self.getTestValues, nonPadding))
    234             for i,values in enumerate(fieldValues):
    235                 for v in values:
    236                     elements = map(random.choice,fieldValues)
    237                     elements[i] = v
    238                     yield '{ %s }'%(', '.join(elements))
    239 
    240         elif isinstance(t, ComplexType):
    241             for t in self.getTestValues(t.elementType):
    242                 yield '%s + %s * 1i'%(t,t)
    243         elif isinstance(t, ArrayType):
    244             values = list(self.getTestValues(t.elementType))
    245             if not values:
    246                 yield '{ }'
    247             for i in range(t.numElements):
    248                 for v in values:
    249                     elements = [random.choice(values) for i in range(t.numElements)]
    250                     elements[i] = v
    251                     yield '{ %s }'%(', '.join(elements))
    252         else:
    253             raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,)
    254 
    255     def printSizeOfType(self, prefix, name, t, output=None, indent=2):
    256         print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name) 
    257     def printAlignOfType(self, prefix, name, t, output=None, indent=2):
    258         print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name) 
    259     def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
    260         if isinstance(t, RecordType):
    261             for i,f in enumerate(t.fields):
    262                 if f.isBitField():
    263                     continue
    264                 fname = 'field%d' % i
    265                 print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname) 
    266                 
    267     def printValueOfType(self, prefix, name, t, output=None, indent=2):
    268         if output is None:
    269             output = self.output
    270         if isinstance(t, BuiltinType):
    271             value_expr = name
    272             if t.name.split(' ')[-1] == '_Bool':
    273                 # Hack to work around PR5579.
    274                 value_expr = "%s ? 2 : 0" % name
    275 
    276             if t.name.endswith('long long'):
    277                 code = 'lld'
    278             elif t.name.endswith('long'):
    279                 code = 'ld'
    280             elif t.name.split(' ')[-1] in ('_Bool','char','short',
    281                                            'int','unsigned'):
    282                 code = 'd'
    283             elif t.name in ('float','double'):
    284                 code = 'f'
    285             elif t.name == 'long double':
    286                 code = 'Lf'
    287             else:
    288                 code = 'p'
    289             print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(
    290                 indent, '', prefix, name, code, value_expr)
    291         elif isinstance(t, EnumType):
    292             print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name)
    293         elif isinstance(t, RecordType):
    294             if not t.fields:
    295                 print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name) 
    296             for i,f in enumerate(t.fields):
    297                 if f.isPaddingBitField():
    298                     continue
    299                 fname = '%s.field%d'%(name,i)
    300                 self.printValueOfType(prefix, fname, f, output=output, indent=indent)
    301         elif isinstance(t, ComplexType):
    302             self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent)
    303             self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent)
    304         elif isinstance(t, ArrayType):
    305             for i in range(t.numElements):
    306                 # Access in this fashion as a hackish way to portably
    307                 # access vectors.
    308                 if t.isVector:
    309                     self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent)
    310                 else:
    311                     self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent)                    
    312         else:
    313             raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
    314 
    315     def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
    316         prefix = 'foo'
    317         if output is None:
    318             output = self.output
    319         if isinstance(t, BuiltinType):
    320             print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
    321         elif isinstance(t, EnumType):
    322             print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
    323         elif isinstance(t, RecordType):
    324             for i,f in enumerate(t.fields):
    325                 if f.isPaddingBitField():
    326                     continue
    327                 self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i), 
    328                                      f, output=output, indent=indent)
    329                 if t.isUnion:
    330                     break
    331         elif isinstance(t, ComplexType):
    332             self.checkTypeValues('(__real %s)'%nameLHS, '(__real %s)'%nameRHS, t.elementType, output=output,indent=indent)
    333             self.checkTypeValues('(__imag %s)'%nameLHS, '(__imag %s)'%nameRHS, t.elementType, output=output,indent=indent)
    334         elif isinstance(t, ArrayType):
    335             for i in range(t.numElements):
    336                 # Access in this fashion as a hackish way to portably
    337                 # access vectors.
    338                 if t.isVector:
    339                     self.checkTypeValues('((%s*) &%s)[%d]'%(t.elementType,nameLHS,i), 
    340                                          '((%s*) &%s)[%d]'%(t.elementType,nameRHS,i), 
    341                                          t.elementType, output=output,indent=indent)
    342                 else:
    343                     self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i), 
    344                                          t.elementType, output=output,indent=indent)                    
    345         else:
    346             raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
    347 
    348 import sys
    349 
    350 def main():
    351     from optparse import OptionParser, OptionGroup
    352     parser = OptionParser("%prog [options] {indices}")
    353     parser.add_option("", "--mode", dest="mode",
    354                       help="autogeneration mode (random or linear) [default %default]",
    355                       type='choice', choices=('random','linear'), default='linear')
    356     parser.add_option("", "--count", dest="count",
    357                       help="autogenerate COUNT functions according to MODE",
    358                       type=int, default=0)
    359     parser.add_option("", "--min", dest="minIndex", metavar="N",
    360                       help="start autogeneration with the Nth function type  [default %default]",
    361                       type=int, default=0)
    362     parser.add_option("", "--max", dest="maxIndex", metavar="N",
    363                       help="maximum index for random autogeneration  [default %default]",
    364                       type=int, default=10000000)
    365     parser.add_option("", "--seed", dest="seed",
    366                       help="random number generator seed [default %default]",
    367                       type=int, default=1)
    368     parser.add_option("", "--use-random-seed", dest="useRandomSeed",
    369                       help="use random value for initial random number generator seed",
    370                       action='store_true', default=False)
    371     parser.add_option("", "--skip", dest="skipTests",
    372                       help="add a test index to skip",
    373                       type=int, action='append', default=[])
    374     parser.add_option("-o", "--output", dest="output", metavar="FILE",
    375                       help="write output to FILE  [default %default]",
    376                       type=str, default='-')
    377     parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE",
    378                       help="write header file for output to FILE  [default %default]",
    379                       type=str, default=None)
    380     parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE",
    381                       help="write function tests to FILE  [default %default]",
    382                       type=str, default=None)
    383     parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE",
    384                       help="write test driver to FILE  [default %default]",
    385                       type=str, default=None)
    386     parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE",
    387                       help="test structure layout",
    388                       action='store_true', default=False)
    389 
    390     group = OptionGroup(parser, "Type Enumeration Options")
    391     # Builtins - Ints
    392     group.add_option("", "--no-char", dest="useChar",
    393                      help="do not generate char types",
    394                      action="store_false", default=True)
    395     group.add_option("", "--no-short", dest="useShort",
    396                      help="do not generate short types",
    397                      action="store_false", default=True)
    398     group.add_option("", "--no-int", dest="useInt",
    399                      help="do not generate int types",
    400                      action="store_false", default=True)
    401     group.add_option("", "--no-long", dest="useLong",
    402                      help="do not generate long types",
    403                      action="store_false", default=True)
    404     group.add_option("", "--no-long-long", dest="useLongLong",
    405                      help="do not generate long long types",
    406                      action="store_false", default=True)
    407     group.add_option("", "--no-unsigned", dest="useUnsigned",
    408                      help="do not generate unsigned integer types",
    409                      action="store_false", default=True)
    410 
    411     # Other builtins
    412     group.add_option("", "--no-bool", dest="useBool",
    413                      help="do not generate bool types",
    414                      action="store_false", default=True)
    415     group.add_option("", "--no-float", dest="useFloat",
    416                      help="do not generate float types",
    417                      action="store_false", default=True)
    418     group.add_option("", "--no-double", dest="useDouble",
    419                      help="do not generate double types",
    420                      action="store_false", default=True)
    421     group.add_option("", "--no-long-double", dest="useLongDouble",
    422                      help="do not generate long double types",
    423                      action="store_false", default=True)
    424     group.add_option("", "--no-void-pointer", dest="useVoidPointer",
    425                      help="do not generate void* types",
    426                      action="store_false", default=True)
    427 
    428     # Enumerations
    429     group.add_option("", "--no-enums", dest="useEnum",
    430                      help="do not generate enum types",
    431                      action="store_false", default=True)
    432 
    433     # Derived types
    434     group.add_option("", "--no-array", dest="useArray",
    435                      help="do not generate record types",
    436                      action="store_false", default=True)
    437     group.add_option("", "--no-complex", dest="useComplex",
    438                      help="do not generate complex types",
    439                      action="store_false", default=True)
    440     group.add_option("", "--no-record", dest="useRecord",
    441                      help="do not generate record types",
    442                      action="store_false", default=True)
    443     group.add_option("", "--no-union", dest="recordUseUnion",
    444                      help="do not generate union types",
    445                      action="store_false", default=True)
    446     group.add_option("", "--no-vector", dest="useVector",
    447                      help="do not generate vector types",
    448                      action="store_false", default=True)
    449     group.add_option("", "--no-bit-field", dest="useBitField",
    450                      help="do not generate bit-field record members",
    451                      action="store_false", default=True)
    452     group.add_option("", "--no-builtins", dest="useBuiltins",
    453                      help="do not use any types",
    454                      action="store_false", default=True)
    455 
    456     # Tuning 
    457     group.add_option("", "--no-function-return", dest="functionUseReturn",
    458                      help="do not generate return types for functions",
    459                      action="store_false", default=True)
    460     group.add_option("", "--vector-types", dest="vectorTypes",
    461                      help="comma separated list of vector types (e.g., v2i32) [default %default]",
    462                      action="store", type=str, default='v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32', metavar="N")
    463     group.add_option("", "--bit-fields", dest="bitFields",
    464                      help="comma separated list 'type:width' bit-field specifiers [default %default]",
    465                      action="store", type=str, default=(
    466             "char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24"))
    467     group.add_option("", "--max-args", dest="functionMaxArgs",
    468                      help="maximum number of arguments per function [default %default]",
    469                      action="store", type=int, default=4, metavar="N")
    470     group.add_option("", "--max-array", dest="arrayMaxSize",
    471                      help="maximum array size [default %default]",
    472                      action="store", type=int, default=4, metavar="N")
    473     group.add_option("", "--max-record", dest="recordMaxSize",
    474                      help="maximum number of fields per record [default %default]",
    475                      action="store", type=int, default=4, metavar="N")
    476     group.add_option("", "--max-record-depth", dest="recordMaxDepth",
    477                      help="maximum nested structure depth [default %default]",
    478                      action="store", type=int, default=None, metavar="N")
    479     parser.add_option_group(group)
    480     (opts, args) = parser.parse_args()
    481 
    482     if not opts.useRandomSeed:
    483         random.seed(opts.seed)
    484 
    485     # Contruct type generator
    486     builtins = []
    487     if opts.useBuiltins:
    488         ints = []
    489         if opts.useChar: ints.append(('char',1))
    490         if opts.useShort: ints.append(('short',2))
    491         if opts.useInt: ints.append(('int',4))
    492         # FIXME: Wrong size.
    493         if opts.useLong: ints.append(('long',4))
    494         if opts.useLongLong: ints.append(('long long',8))
    495         if opts.useUnsigned: 
    496             ints = ([('unsigned %s'%i,s) for i,s in ints] + 
    497                     [('signed %s'%i,s) for i,s in ints])
    498         builtins.extend(ints)
    499 
    500         if opts.useBool: builtins.append(('_Bool',1))
    501         if opts.useFloat: builtins.append(('float',4))
    502         if opts.useDouble: builtins.append(('double',8))
    503         if opts.useLongDouble: builtins.append(('long double',16))
    504         # FIXME: Wrong size.
    505         if opts.useVoidPointer:  builtins.append(('void*',4))
    506 
    507     btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins])
    508 
    509     bitfields = []
    510     for specifier in opts.bitFields.split(','):
    511         if not specifier.strip():
    512             continue
    513         name,width = specifier.strip().split(':', 1)
    514         bitfields.append(BuiltinType(name,None,int(width)))
    515     bftg = FixedTypeGenerator(bitfields)
    516 
    517     charType = BuiltinType('char',1)
    518     shortType = BuiltinType('short',2)
    519     intType = BuiltinType('int',4)
    520     longlongType = BuiltinType('long long',8)
    521     floatType = BuiltinType('float',4)
    522     doubleType = BuiltinType('double',8)
    523     sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])
    524 
    525     atg = AnyTypeGenerator()
    526     artg = AnyTypeGenerator()
    527     def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
    528         atg.addGenerator(btg)
    529         if useBitField and opts.useBitField:
    530             atg.addGenerator(bftg)
    531         if useRecord and opts.useRecord:
    532             assert subgen 
    533             atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion, 
    534                                                  opts.recordMaxSize))
    535         if opts.useComplex:
    536             # FIXME: Allow overriding builtins here
    537             atg.addGenerator(ComplexTypeGenerator(sbtg))
    538         if useArray and opts.useArray:
    539             assert subgen 
    540             atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))
    541         if opts.useVector:
    542             vTypes = []
    543             for i,t in enumerate(opts.vectorTypes.split(',')):
    544                 m = re.match('v([1-9][0-9]*)([if][1-9][0-9]*)', t.strip())
    545                 if not m:
    546                     parser.error('Invalid vector type: %r' % t)
    547                 count,kind = m.groups()
    548                 count = int(count)
    549                 type = { 'i8'  : charType, 
    550                          'i16' : shortType, 
    551                          'i32' : intType, 
    552                          'i64' : longlongType,
    553                          'f32' : floatType, 
    554                          'f64' : doubleType,
    555                          }.get(kind)
    556                 if not type:
    557                     parser.error('Invalid vector type: %r' % t)
    558                 vTypes.append(ArrayType(i, True, type, count * type.size))
    559                 
    560             atg.addGenerator(FixedTypeGenerator(vTypes))
    561         if opts.useEnum:
    562             atg.addGenerator(EnumTypeGenerator([None, '-1', '1', '1u'], 1, 4))
    563 
    564     if opts.recordMaxDepth is None: 
    565         # Fully recursive, just avoid top-level arrays.
    566         subFTG = AnyTypeGenerator()
    567         subTG = AnyTypeGenerator()
    568         atg = AnyTypeGenerator()
    569         makeGenerator(subFTG, atg, atg, True, True, True)
    570         makeGenerator(subTG, atg, subFTG, True, True, False)
    571         makeGenerator(atg, subTG, subFTG, True, False, False)
    572     else:
    573         # Make a chain of type generators, each builds smaller
    574         # structures.
    575         base = AnyTypeGenerator()
    576         fbase = AnyTypeGenerator()
    577         makeGenerator(base, None, None, False, False, False)
    578         makeGenerator(fbase, None, None, False, False, True)
    579         for i in range(opts.recordMaxDepth):
    580             n = AnyTypeGenerator()
    581             fn = AnyTypeGenerator()
    582             makeGenerator(n, base, fbase, True, True, False)
    583             makeGenerator(fn, base, fbase, True, True, True)
    584             base = n
    585             fbase = fn
    586         atg = AnyTypeGenerator()
    587         makeGenerator(atg, base, fbase, True, False, False)
    588 
    589     if opts.testLayout:
    590         ftg = atg
    591     else:
    592         ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)
    593 
    594     # Override max,min,count if finite
    595     if opts.maxIndex is None:
    596         if ftg.cardinality is aleph0:
    597             opts.maxIndex = 10000000
    598         else:
    599             opts.maxIndex = ftg.cardinality
    600     opts.maxIndex = min(opts.maxIndex, ftg.cardinality)
    601     opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex))
    602     if not opts.mode=='random':
    603         opts.count = min(opts.count, opts.maxIndex-opts.minIndex)
    604 
    605     if opts.output=='-':
    606         output = sys.stdout
    607     else:
    608         output = open(opts.output,'w')
    609         atexit.register(lambda: output.close())
    610         
    611     outputHeader = None
    612     if opts.outputHeader:
    613         outputHeader = open(opts.outputHeader,'w')
    614         atexit.register(lambda: outputHeader.close())
    615         
    616     outputTests = None
    617     if opts.outputTests:
    618         outputTests = open(opts.outputTests,'w')
    619         atexit.register(lambda: outputTests.close())
    620 
    621     outputDriver = None
    622     if opts.outputDriver:
    623         outputDriver = open(opts.outputDriver,'w')
    624         atexit.register(lambda: outputDriver.close())
    625 
    626     info = ''
    627     info += '// %s\n'%(' '.join(sys.argv),)
    628     info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),)
    629     info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,)
    630     info += '// Cardinality of type generator: %s\n'%(atg.cardinality,)
    631 
    632     if opts.testLayout:
    633         info += '\n#include <stdio.h>'
    634     
    635     P = TypePrinter(output, 
    636                     outputHeader=outputHeader,
    637                     outputTests=outputTests,
    638                     outputDriver=outputDriver,
    639                     headerName=opts.outputHeader,                    
    640                     info=info)
    641 
    642     def write(N):
    643         try:
    644             FT = ftg.get(N)
    645         except RuntimeError,e:
    646             if e.args[0]=='maximum recursion depth exceeded':
    647                 print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,)
    648                 return
    649             raise
    650         if opts.testLayout:
    651             P.writeLayoutTest(N, FT)
    652         else:
    653             P.writeFunction(N, FT)
    654 
    655     if args:
    656         [write(int(a)) for a in args]
    657 
    658     skipTests = set(opts.skipTests)
    659     for i in range(opts.count):
    660         if opts.mode=='linear':
    661             index = opts.minIndex + i
    662         else:
    663             index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random())
    664         if index in skipTests:
    665             continue
    666         write(index)
    667 
    668     P.finish()
    669 
    670 if __name__=='__main__':
    671     main()
    672 
    673