1026 lines · python
1#!/usr/bin/env python2 3from __future__ import absolute_import, division, print_function4from pprint import pprint5import random, atexit, time6from random import randrange7import re8 9from Enumeration import *10from TypeGen import *11 12####13 14 15class TypePrinter(object):16 def __init__(17 self,18 output,19 outputHeader=None,20 outputTests=None,21 outputDriver=None,22 headerName=None,23 info=None,24 ):25 self.output = output26 self.outputHeader = outputHeader27 self.outputTests = outputTests28 self.outputDriver = outputDriver29 self.writeBody = outputHeader or outputTests or outputDriver30 self.types = {}31 self.testValues = {}32 self.testReturnValues = {}33 self.layoutTests = []34 self.declarations = set()35 36 if info:37 for f in (38 self.output,39 self.outputHeader,40 self.outputTests,41 self.outputDriver,42 ):43 if f:44 print(info, file=f)45 46 if self.writeBody:47 print("#include <stdio.h>\n", file=self.output)48 if self.outputTests:49 print("#include <stdio.h>", file=self.outputTests)50 print("#include <string.h>", file=self.outputTests)51 print("#include <assert.h>\n", file=self.outputTests)52 53 if headerName:54 for f in (self.output, self.outputTests, self.outputDriver):55 if f is not None:56 print('#include "%s"\n' % (headerName,), file=f)57 58 if self.outputDriver:59 print("#include <stdio.h>", file=self.outputDriver)60 print("#include <stdlib.h>\n", file=self.outputDriver)61 print("int main(int argc, char **argv) {", file=self.outputDriver)62 print(" int index = -1;", file=self.outputDriver)63 print(" if (argc > 1) index = atoi(argv[1]);", file=self.outputDriver)64 65 def finish(self):66 if self.layoutTests:67 print("int main(int argc, char **argv) {", file=self.output)68 print(" int index = -1;", file=self.output)69 print(" if (argc > 1) index = atoi(argv[1]);", file=self.output)70 for i, f in self.layoutTests:71 print(" if (index == -1 || index == %d)" % i, file=self.output)72 print(" %s();" % f, file=self.output)73 print(" return 0;", file=self.output)74 print("}", file=self.output)75 76 if self.outputDriver:77 print(' printf("DONE\\n");', file=self.outputDriver)78 print(" return 0;", file=self.outputDriver)79 print("}", file=self.outputDriver)80 81 def addDeclaration(self, decl):82 if decl in self.declarations:83 return False84 85 self.declarations.add(decl)86 if self.outputHeader:87 print(decl, file=self.outputHeader)88 else:89 print(decl, file=self.output)90 if self.outputTests:91 print(decl, file=self.outputTests)92 return True93 94 def getTypeName(self, T):95 name = self.types.get(T)96 if name is None:97 # Reserve slot98 self.types[T] = None99 self.types[T] = name = T.getTypeName(self)100 return name101 102 def writeLayoutTest(self, i, ty):103 tyName = self.getTypeName(ty)104 tyNameClean = tyName.replace(" ", "_").replace("*", "star")105 fnName = "test_%s" % tyNameClean106 107 print("void %s(void) {" % fnName, file=self.output)108 self.printSizeOfType(" %s" % fnName, tyName, ty, self.output)109 self.printAlignOfType(" %s" % fnName, tyName, ty, self.output)110 self.printOffsetsOfType(" %s" % fnName, tyName, ty, self.output)111 print("}", file=self.output)112 print(file=self.output)113 114 self.layoutTests.append((i, fnName))115 116 def writeFunction(self, i, FT):117 args = ", ".join(118 ["%s arg%d" % (self.getTypeName(t), i) for i, t in enumerate(FT.argTypes)]119 )120 if not args:121 args = "void"122 123 if FT.returnType is None:124 retvalName = None125 retvalTypeName = "void"126 else:127 retvalTypeName = self.getTypeName(FT.returnType)128 if self.writeBody or self.outputTests:129 retvalName = self.getTestReturnValue(FT.returnType)130 131 fnName = "fn%d" % (FT.index,)132 if self.outputHeader:133 print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputHeader)134 elif self.outputTests:135 print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputTests)136 137 print("%s %s(%s)" % (retvalTypeName, fnName, args), end=" ", file=self.output)138 if self.writeBody:139 print("{", file=self.output)140 141 for i, t in enumerate(FT.argTypes):142 self.printValueOfType(" %s" % fnName, "arg%d" % i, t)143 144 if retvalName is not None:145 print(" return %s;" % (retvalName,), file=self.output)146 print("}", file=self.output)147 else:148 print("{}", file=self.output)149 print(file=self.output)150 151 if self.outputDriver:152 print(" if (index == -1 || index == %d) {" % i, file=self.outputDriver)153 print(" extern void test_%s(void);" % fnName, file=self.outputDriver)154 print(" test_%s();" % fnName, file=self.outputDriver)155 print(" }", file=self.outputDriver)156 157 if self.outputTests:158 if self.outputHeader:159 print("void test_%s(void);" % (fnName,), file=self.outputHeader)160 161 if retvalName is None:162 retvalTests = None163 else:164 retvalTests = self.getTestValuesArray(FT.returnType)165 tests = [self.getTestValuesArray(ty) for ty in FT.argTypes]166 print("void test_%s(void) {" % (fnName,), file=self.outputTests)167 168 if retvalTests is not None:169 print(170 ' printf("%s: testing return.\\n");' % (fnName,),171 file=self.outputTests,172 )173 print(174 " for (int i=0; i<%d; ++i) {" % (retvalTests[1],),175 file=self.outputTests,176 )177 args = ", ".join(["%s[%d]" % (t, randrange(l)) for t, l in tests])178 print(" %s RV;" % (retvalTypeName,), file=self.outputTests)179 print(180 " %s = %s[i];" % (retvalName, retvalTests[0]),181 file=self.outputTests,182 )183 print(" RV = %s(%s);" % (fnName, args), file=self.outputTests)184 self.printValueOfType(185 " %s_RV" % fnName,186 "RV",187 FT.returnType,188 output=self.outputTests,189 indent=4,190 )191 self.checkTypeValues(192 "RV",193 "%s[i]" % retvalTests[0],194 FT.returnType,195 output=self.outputTests,196 indent=4,197 )198 print(" }", file=self.outputTests)199 200 if tests:201 print(202 ' printf("%s: testing arguments.\\n");' % (fnName,),203 file=self.outputTests,204 )205 for i, (array, length) in enumerate(tests):206 for j in range(length):207 args = ["%s[%d]" % (t, randrange(l)) for t, l in tests]208 args[i] = "%s[%d]" % (array, j)209 print(210 " %s(%s);"211 % (212 fnName,213 ", ".join(args),214 ),215 file=self.outputTests,216 )217 print("}", file=self.outputTests)218 219 def getTestReturnValue(self, type):220 typeName = self.getTypeName(type)221 info = self.testReturnValues.get(typeName)222 if info is None:223 name = "%s_retval" % (typeName.replace(" ", "_").replace("*", "star"),)224 print("%s %s;" % (typeName, name), file=self.output)225 if self.outputHeader:226 print("extern %s %s;" % (typeName, name), file=self.outputHeader)227 elif self.outputTests:228 print("extern %s %s;" % (typeName, name), file=self.outputTests)229 info = self.testReturnValues[typeName] = name230 return info231 232 def getTestValuesArray(self, type):233 typeName = self.getTypeName(type)234 info = self.testValues.get(typeName)235 if info is None:236 name = "%s_values" % (typeName.replace(" ", "_").replace("*", "star"),)237 print("static %s %s[] = {" % (typeName, name), file=self.outputTests)238 length = 0239 for item in self.getTestValues(type):240 print("\t%s," % (item,), file=self.outputTests)241 length += 1242 print("};", file=self.outputTests)243 info = self.testValues[typeName] = (name, length)244 return info245 246 def getTestValues(self, t):247 if isinstance(t, BuiltinType):248 if t.name == "float":249 for i in ["0.0", "-1.0", "1.0"]:250 yield i + "f"251 elif t.name == "double":252 for i in ["0.0", "-1.0", "1.0"]:253 yield i254 elif t.name in ("void *"):255 yield "(void*) 0"256 yield "(void*) -1"257 else:258 yield "(%s) 0" % (t.name,)259 yield "(%s) -1" % (t.name,)260 yield "(%s) 1" % (t.name,)261 elif isinstance(t, EnumType):262 for i in range(0, len(t.enumerators)):263 yield "enum%dval%d_%d" % (t.index, i, t.unique_id)264 elif isinstance(t, RecordType):265 nonPadding = [f for f in t.fields if not f.isPaddingBitField()]266 267 if not nonPadding:268 yield "{ }"269 return270 271 # FIXME: Use designated initializers to access non-first272 # fields of unions.273 if t.isUnion:274 for v in self.getTestValues(nonPadding[0]):275 yield "{ %s }" % v276 return277 278 fieldValues = [list(v) for v in map(self.getTestValues, nonPadding)]279 for i, values in enumerate(fieldValues):280 for v in values:281 elements = [random.choice(fv) for fv in fieldValues]282 elements[i] = v283 yield "{ %s }" % (", ".join(elements))284 285 elif isinstance(t, ComplexType):286 for t in self.getTestValues(t.elementType):287 yield "%s + %s * 1i" % (t, t)288 elif isinstance(t, ArrayType):289 values = list(self.getTestValues(t.elementType))290 if not values:291 yield "{ }"292 for i in range(t.numElements):293 for v in values:294 elements = [random.choice(values) for i in range(t.numElements)]295 elements[i] = v296 yield "{ %s }" % (", ".join(elements))297 else:298 raise NotImplementedError('Cannot make tests values of type: "%s"' % (t,))299 300 def printSizeOfType(self, prefix, name, t, output=None, indent=2):301 print(302 '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'303 % (indent, "", prefix, name, name),304 file=output,305 )306 307 def printAlignOfType(self, prefix, name, t, output=None, indent=2):308 print(309 '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'310 % (indent, "", prefix, name, name),311 file=output,312 )313 314 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):315 if isinstance(t, RecordType):316 for i, f in enumerate(t.fields):317 if f.isBitField():318 continue319 fname = "field%d" % i320 print(321 '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'322 % (indent, "", prefix, name, fname, name, fname),323 file=output,324 )325 326 def printValueOfType(self, prefix, name, t, output=None, indent=2):327 if output is None:328 output = self.output329 if isinstance(t, BuiltinType):330 value_expr = name331 if t.name.split(" ")[-1] == "_Bool":332 # Hack to work around PR5579.333 value_expr = "%s ? 2 : 0" % name334 335 if t.name.endswith("long long"):336 code = "lld"337 elif t.name.endswith("long"):338 code = "ld"339 elif t.name.split(" ")[-1] in ("_Bool", "char", "short", "int", "unsigned"):340 code = "d"341 elif t.name in ("float", "double"):342 code = "f"343 elif t.name == "long double":344 code = "Lf"345 else:346 code = "p"347 print(348 '%*sprintf("%s: %s = %%%s\\n", %s);'349 % (indent, "", prefix, name, code, value_expr),350 file=output,351 )352 elif isinstance(t, EnumType):353 print(354 '%*sprintf("%s: %s = %%d\\n", %s);' % (indent, "", prefix, name, name),355 file=output,356 )357 elif isinstance(t, RecordType):358 if not t.fields:359 print(360 '%*sprintf("%s: %s (empty)\\n");' % (indent, "", prefix, name),361 file=output,362 )363 for i, f in enumerate(t.fields):364 if f.isPaddingBitField():365 continue366 fname = "%s.field%d" % (name, i)367 self.printValueOfType(prefix, fname, f, output=output, indent=indent)368 elif isinstance(t, ComplexType):369 self.printValueOfType(370 prefix,371 "(__real %s)" % name,372 t.elementType,373 output=output,374 indent=indent,375 )376 self.printValueOfType(377 prefix,378 "(__imag %s)" % name,379 t.elementType,380 output=output,381 indent=indent,382 )383 elif isinstance(t, ArrayType):384 for i in range(t.numElements):385 # Access in this fashion as a hackish way to portably386 # access vectors.387 if t.isVector:388 self.printValueOfType(389 prefix,390 "((%s*) &%s)[%d]" % (t.elementType, name, i),391 t.elementType,392 output=output,393 indent=indent,394 )395 else:396 self.printValueOfType(397 prefix,398 "%s[%d]" % (name, i),399 t.elementType,400 output=output,401 indent=indent,402 )403 else:404 raise NotImplementedError('Cannot print value of type: "%s"' % (t,))405 406 def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):407 prefix = "foo"408 if output is None:409 output = self.output410 if isinstance(t, BuiltinType):411 print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output)412 elif isinstance(t, EnumType):413 print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output)414 elif isinstance(t, RecordType):415 for i, f in enumerate(t.fields):416 if f.isPaddingBitField():417 continue418 self.checkTypeValues(419 "%s.field%d" % (nameLHS, i),420 "%s.field%d" % (nameRHS, i),421 f,422 output=output,423 indent=indent,424 )425 if t.isUnion:426 break427 elif isinstance(t, ComplexType):428 self.checkTypeValues(429 "(__real %s)" % nameLHS,430 "(__real %s)" % nameRHS,431 t.elementType,432 output=output,433 indent=indent,434 )435 self.checkTypeValues(436 "(__imag %s)" % nameLHS,437 "(__imag %s)" % nameRHS,438 t.elementType,439 output=output,440 indent=indent,441 )442 elif isinstance(t, ArrayType):443 for i in range(t.numElements):444 # Access in this fashion as a hackish way to portably445 # access vectors.446 if t.isVector:447 self.checkTypeValues(448 "((%s*) &%s)[%d]" % (t.elementType, nameLHS, i),449 "((%s*) &%s)[%d]" % (t.elementType, nameRHS, i),450 t.elementType,451 output=output,452 indent=indent,453 )454 else:455 self.checkTypeValues(456 "%s[%d]" % (nameLHS, i),457 "%s[%d]" % (nameRHS, i),458 t.elementType,459 output=output,460 indent=indent,461 )462 else:463 raise NotImplementedError('Cannot print value of type: "%s"' % (t,))464 465 466import sys467 468 469def main():470 from optparse import OptionParser, OptionGroup471 472 parser = OptionParser("%prog [options] {indices}")473 parser.add_option(474 "",475 "--mode",476 dest="mode",477 help="autogeneration mode (random or linear) [default %default]",478 type="choice",479 choices=("random", "linear"),480 default="linear",481 )482 parser.add_option(483 "",484 "--count",485 dest="count",486 help="autogenerate COUNT functions according to MODE",487 type=int,488 default=0,489 )490 parser.add_option(491 "",492 "--min",493 dest="minIndex",494 metavar="N",495 help="start autogeneration with the Nth function type [default %default]",496 type=int,497 default=0,498 )499 parser.add_option(500 "",501 "--max",502 dest="maxIndex",503 metavar="N",504 help="maximum index for random autogeneration [default %default]",505 type=int,506 default=10000000,507 )508 parser.add_option(509 "",510 "--seed",511 dest="seed",512 help="random number generator seed [default %default]",513 type=int,514 default=1,515 )516 parser.add_option(517 "",518 "--use-random-seed",519 dest="useRandomSeed",520 help="use random value for initial random number generator seed",521 action="store_true",522 default=False,523 )524 parser.add_option(525 "",526 "--skip",527 dest="skipTests",528 help="add a test index to skip",529 type=int,530 action="append",531 default=[],532 )533 parser.add_option(534 "-o",535 "--output",536 dest="output",537 metavar="FILE",538 help="write output to FILE [default %default]",539 type=str,540 default="-",541 )542 parser.add_option(543 "-O",544 "--output-header",545 dest="outputHeader",546 metavar="FILE",547 help="write header file for output to FILE [default %default]",548 type=str,549 default=None,550 )551 parser.add_option(552 "-T",553 "--output-tests",554 dest="outputTests",555 metavar="FILE",556 help="write function tests to FILE [default %default]",557 type=str,558 default=None,559 )560 parser.add_option(561 "-D",562 "--output-driver",563 dest="outputDriver",564 metavar="FILE",565 help="write test driver to FILE [default %default]",566 type=str,567 default=None,568 )569 parser.add_option(570 "",571 "--test-layout",572 dest="testLayout",573 metavar="FILE",574 help="test structure layout",575 action="store_true",576 default=False,577 )578 579 group = OptionGroup(parser, "Type Enumeration Options")580 # Builtins - Ints581 group.add_option(582 "",583 "--no-char",584 dest="useChar",585 help="do not generate char types",586 action="store_false",587 default=True,588 )589 group.add_option(590 "",591 "--no-short",592 dest="useShort",593 help="do not generate short types",594 action="store_false",595 default=True,596 )597 group.add_option(598 "",599 "--no-int",600 dest="useInt",601 help="do not generate int types",602 action="store_false",603 default=True,604 )605 group.add_option(606 "",607 "--no-long",608 dest="useLong",609 help="do not generate long types",610 action="store_false",611 default=True,612 )613 group.add_option(614 "",615 "--no-long-long",616 dest="useLongLong",617 help="do not generate long long types",618 action="store_false",619 default=True,620 )621 group.add_option(622 "",623 "--no-unsigned",624 dest="useUnsigned",625 help="do not generate unsigned integer types",626 action="store_false",627 default=True,628 )629 630 # Other builtins631 group.add_option(632 "",633 "--no-bool",634 dest="useBool",635 help="do not generate bool types",636 action="store_false",637 default=True,638 )639 group.add_option(640 "",641 "--no-float",642 dest="useFloat",643 help="do not generate float types",644 action="store_false",645 default=True,646 )647 group.add_option(648 "",649 "--no-double",650 dest="useDouble",651 help="do not generate double types",652 action="store_false",653 default=True,654 )655 group.add_option(656 "",657 "--no-long-double",658 dest="useLongDouble",659 help="do not generate long double types",660 action="store_false",661 default=True,662 )663 group.add_option(664 "",665 "--no-void-pointer",666 dest="useVoidPointer",667 help="do not generate void* types",668 action="store_false",669 default=True,670 )671 672 # Enumerations673 group.add_option(674 "",675 "--no-enums",676 dest="useEnum",677 help="do not generate enum types",678 action="store_false",679 default=True,680 )681 682 # Derived types683 group.add_option(684 "",685 "--no-array",686 dest="useArray",687 help="do not generate record types",688 action="store_false",689 default=True,690 )691 group.add_option(692 "",693 "--no-complex",694 dest="useComplex",695 help="do not generate complex types",696 action="store_false",697 default=True,698 )699 group.add_option(700 "",701 "--no-record",702 dest="useRecord",703 help="do not generate record types",704 action="store_false",705 default=True,706 )707 group.add_option(708 "",709 "--no-union",710 dest="recordUseUnion",711 help="do not generate union types",712 action="store_false",713 default=True,714 )715 group.add_option(716 "",717 "--no-vector",718 dest="useVector",719 help="do not generate vector types",720 action="store_false",721 default=True,722 )723 group.add_option(724 "",725 "--no-bit-field",726 dest="useBitField",727 help="do not generate bit-field record members",728 action="store_false",729 default=True,730 )731 group.add_option(732 "",733 "--no-builtins",734 dest="useBuiltins",735 help="do not use any types",736 action="store_false",737 default=True,738 )739 740 # Tuning741 group.add_option(742 "",743 "--no-function-return",744 dest="functionUseReturn",745 help="do not generate return types for functions",746 action="store_false",747 default=True,748 )749 group.add_option(750 "",751 "--vector-types",752 dest="vectorTypes",753 help="comma separated list of vector types (e.g., v2i32) [default %default]",754 action="store",755 type=str,756 default="v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32",757 metavar="N",758 )759 group.add_option(760 "",761 "--bit-fields",762 dest="bitFields",763 help="comma separated list 'type:width' bit-field specifiers [default %default]",764 action="store",765 type=str,766 default=("char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24"),767 )768 group.add_option(769 "",770 "--max-args",771 dest="functionMaxArgs",772 help="maximum number of arguments per function [default %default]",773 action="store",774 type=int,775 default=4,776 metavar="N",777 )778 group.add_option(779 "",780 "--max-array",781 dest="arrayMaxSize",782 help="maximum array size [default %default]",783 action="store",784 type=int,785 default=4,786 metavar="N",787 )788 group.add_option(789 "",790 "--max-record",791 dest="recordMaxSize",792 help="maximum number of fields per record [default %default]",793 action="store",794 type=int,795 default=4,796 metavar="N",797 )798 group.add_option(799 "",800 "--max-record-depth",801 dest="recordMaxDepth",802 help="maximum nested structure depth [default %default]",803 action="store",804 type=int,805 default=None,806 metavar="N",807 )808 parser.add_option_group(group)809 (opts, args) = parser.parse_args()810 811 if not opts.useRandomSeed:812 random.seed(opts.seed)813 814 # Construct type generator815 builtins = []816 if opts.useBuiltins:817 ints = []818 if opts.useChar:819 ints.append(("char", 1))820 if opts.useShort:821 ints.append(("short", 2))822 if opts.useInt:823 ints.append(("int", 4))824 # FIXME: Wrong size.825 if opts.useLong:826 ints.append(("long", 4))827 if opts.useLongLong:828 ints.append(("long long", 8))829 if opts.useUnsigned:830 ints = [("unsigned %s" % i, s) for i, s in ints] + [831 ("signed %s" % i, s) for i, s in ints832 ]833 builtins.extend(ints)834 835 if opts.useBool:836 builtins.append(("_Bool", 1))837 if opts.useFloat:838 builtins.append(("float", 4))839 if opts.useDouble:840 builtins.append(("double", 8))841 if opts.useLongDouble:842 builtins.append(("long double", 16))843 # FIXME: Wrong size.844 if opts.useVoidPointer:845 builtins.append(("void*", 4))846 847 btg = FixedTypeGenerator([BuiltinType(n, s) for n, s in builtins])848 849 bitfields = []850 for specifier in opts.bitFields.split(","):851 if not specifier.strip():852 continue853 name, width = specifier.strip().split(":", 1)854 bitfields.append(BuiltinType(name, None, int(width)))855 bftg = FixedTypeGenerator(bitfields)856 857 charType = BuiltinType("char", 1)858 shortType = BuiltinType("short", 2)859 intType = BuiltinType("int", 4)860 longlongType = BuiltinType("long long", 8)861 floatType = BuiltinType("float", 4)862 doubleType = BuiltinType("double", 8)863 sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])864 865 atg = AnyTypeGenerator()866 artg = AnyTypeGenerator()867 868 def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):869 atg.addGenerator(btg)870 if useBitField and opts.useBitField:871 atg.addGenerator(bftg)872 if useRecord and opts.useRecord:873 assert subgen874 atg.addGenerator(875 RecordTypeGenerator(876 subfieldgen, opts.recordUseUnion, opts.recordMaxSize877 )878 )879 if opts.useComplex:880 # FIXME: Allow overriding builtins here881 atg.addGenerator(ComplexTypeGenerator(sbtg))882 if useArray and opts.useArray:883 assert subgen884 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))885 if opts.useVector:886 vTypes = []887 for i, t in enumerate(opts.vectorTypes.split(",")):888 m = re.match("v([1-9][0-9]*)([if][1-9][0-9]*)", t.strip())889 if not m:890 parser.error("Invalid vector type: %r" % t)891 count, kind = m.groups()892 count = int(count)893 type = {894 "i8": charType,895 "i16": shortType,896 "i32": intType,897 "i64": longlongType,898 "f32": floatType,899 "f64": doubleType,900 }.get(kind)901 if not type:902 parser.error("Invalid vector type: %r" % t)903 vTypes.append(ArrayType(i, True, type, count * type.size))904 905 atg.addGenerator(FixedTypeGenerator(vTypes))906 if opts.useEnum:907 atg.addGenerator(EnumTypeGenerator([None, "-1", "1", "1u"], 1, 4))908 909 if opts.recordMaxDepth is None:910 # Fully recursive, just avoid top-level arrays.911 subFTG = AnyTypeGenerator()912 subTG = AnyTypeGenerator()913 atg = AnyTypeGenerator()914 makeGenerator(subFTG, atg, atg, True, True, True)915 makeGenerator(subTG, atg, subFTG, True, True, False)916 makeGenerator(atg, subTG, subFTG, True, False, False)917 else:918 # Make a chain of type generators, each builds smaller919 # structures.920 base = AnyTypeGenerator()921 fbase = AnyTypeGenerator()922 makeGenerator(base, None, None, False, False, False)923 makeGenerator(fbase, None, None, False, False, True)924 for i in range(opts.recordMaxDepth):925 n = AnyTypeGenerator()926 fn = AnyTypeGenerator()927 makeGenerator(n, base, fbase, True, True, False)928 makeGenerator(fn, base, fbase, True, True, True)929 base = n930 fbase = fn931 atg = AnyTypeGenerator()932 makeGenerator(atg, base, fbase, True, False, False)933 934 if opts.testLayout:935 ftg = atg936 else:937 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)938 939 # Override max,min,count if finite940 if opts.maxIndex is None:941 if ftg.cardinality is aleph0:942 opts.maxIndex = 10000000943 else:944 opts.maxIndex = ftg.cardinality945 opts.maxIndex = min(opts.maxIndex, ftg.cardinality)946 opts.minIndex = max(0, min(opts.maxIndex - 1, opts.minIndex))947 if not opts.mode == "random":948 opts.count = min(opts.count, opts.maxIndex - opts.minIndex)949 950 if opts.output == "-":951 output = sys.stdout952 else:953 output = open(opts.output, "w")954 atexit.register(lambda: output.close())955 956 outputHeader = None957 if opts.outputHeader:958 outputHeader = open(opts.outputHeader, "w")959 atexit.register(lambda: outputHeader.close())960 961 outputTests = None962 if opts.outputTests:963 outputTests = open(opts.outputTests, "w")964 atexit.register(lambda: outputTests.close())965 966 outputDriver = None967 if opts.outputDriver:968 outputDriver = open(opts.outputDriver, "w")969 atexit.register(lambda: outputDriver.close())970 971 info = ""972 info += "// %s\n" % (" ".join(sys.argv),)973 info += "// Generated: %s\n" % (time.strftime("%Y-%m-%d %H:%M"),)974 info += "// Cardinality of function generator: %s\n" % (ftg.cardinality,)975 info += "// Cardinality of type generator: %s\n" % (atg.cardinality,)976 977 if opts.testLayout:978 info += "\n#include <stdio.h>"979 980 P = TypePrinter(981 output,982 outputHeader=outputHeader,983 outputTests=outputTests,984 outputDriver=outputDriver,985 headerName=opts.outputHeader,986 info=info,987 )988 989 def write(N):990 try:991 FT = ftg.get(N)992 except RuntimeError as e:993 if e.args[0] == "maximum recursion depth exceeded":994 print(995 "WARNING: Skipped %d, recursion limit exceeded (bad arguments?)"996 % (N,),997 file=sys.stderr,998 )999 return1000 raise1001 if opts.testLayout:1002 P.writeLayoutTest(N, FT)1003 else:1004 P.writeFunction(N, FT)1005 1006 if args:1007 [write(int(a)) for a in args]1008 1009 skipTests = set(opts.skipTests)1010 for i in range(opts.count):1011 if opts.mode == "linear":1012 index = opts.minIndex + i1013 else:1014 index = opts.minIndex + int(1015 (opts.maxIndex - opts.minIndex) * random.random()1016 )1017 if index in skipTests:1018 continue1019 write(index)1020 1021 P.finish()1022 1023 1024if __name__ == "__main__":1025 main()1026