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