|  | #!/usr/bin/env python | 
|  |  | 
|  | from __future__ import absolute_import, division, print_function | 
|  | from pprint import pprint | 
|  | import random, atexit, time | 
|  | from random import randrange | 
|  | import re | 
|  |  | 
|  | from Enumeration import * | 
|  | from TypeGen import * | 
|  |  | 
|  | #### | 
|  |  | 
|  |  | 
|  | class TypePrinter(object): | 
|  | def __init__( | 
|  | self, | 
|  | output, | 
|  | outputHeader=None, | 
|  | outputTests=None, | 
|  | outputDriver=None, | 
|  | headerName=None, | 
|  | info=None, | 
|  | ): | 
|  | self.output = output | 
|  | self.outputHeader = outputHeader | 
|  | self.outputTests = outputTests | 
|  | self.outputDriver = outputDriver | 
|  | self.writeBody = outputHeader or outputTests or outputDriver | 
|  | self.types = {} | 
|  | self.testValues = {} | 
|  | self.testReturnValues = {} | 
|  | self.layoutTests = [] | 
|  | self.declarations = set() | 
|  |  | 
|  | if info: | 
|  | for f in ( | 
|  | self.output, | 
|  | self.outputHeader, | 
|  | self.outputTests, | 
|  | self.outputDriver, | 
|  | ): | 
|  | if f: | 
|  | print(info, file=f) | 
|  |  | 
|  | if self.writeBody: | 
|  | print("#include <stdio.h>\n", file=self.output) | 
|  | if self.outputTests: | 
|  | print("#include <stdio.h>", file=self.outputTests) | 
|  | print("#include <string.h>", file=self.outputTests) | 
|  | print("#include <assert.h>\n", file=self.outputTests) | 
|  |  | 
|  | if headerName: | 
|  | for f in (self.output, self.outputTests, self.outputDriver): | 
|  | if f is not None: | 
|  | print('#include "%s"\n' % (headerName,), file=f) | 
|  |  | 
|  | if self.outputDriver: | 
|  | print("#include <stdio.h>", file=self.outputDriver) | 
|  | print("#include <stdlib.h>\n", file=self.outputDriver) | 
|  | print("int main(int argc, char **argv) {", file=self.outputDriver) | 
|  | print("  int index = -1;", file=self.outputDriver) | 
|  | print("  if (argc > 1) index = atoi(argv[1]);", file=self.outputDriver) | 
|  |  | 
|  | def finish(self): | 
|  | if self.layoutTests: | 
|  | print("int main(int argc, char **argv) {", file=self.output) | 
|  | print("  int index = -1;", file=self.output) | 
|  | print("  if (argc > 1) index = atoi(argv[1]);", file=self.output) | 
|  | for i, f in self.layoutTests: | 
|  | print("  if (index == -1 || index == %d)" % i, file=self.output) | 
|  | print("    %s();" % f, file=self.output) | 
|  | print("  return 0;", file=self.output) | 
|  | print("}", file=self.output) | 
|  |  | 
|  | if self.outputDriver: | 
|  | print('  printf("DONE\\n");', file=self.outputDriver) | 
|  | print("  return 0;", file=self.outputDriver) | 
|  | print("}", file=self.outputDriver) | 
|  |  | 
|  | def addDeclaration(self, decl): | 
|  | if decl in self.declarations: | 
|  | return False | 
|  |  | 
|  | self.declarations.add(decl) | 
|  | if self.outputHeader: | 
|  | print(decl, file=self.outputHeader) | 
|  | else: | 
|  | print(decl, file=self.output) | 
|  | if self.outputTests: | 
|  | print(decl, file=self.outputTests) | 
|  | return True | 
|  |  | 
|  | def getTypeName(self, T): | 
|  | name = self.types.get(T) | 
|  | if name is None: | 
|  | # Reserve slot | 
|  | self.types[T] = None | 
|  | self.types[T] = name = T.getTypeName(self) | 
|  | return name | 
|  |  | 
|  | def writeLayoutTest(self, i, ty): | 
|  | tyName = self.getTypeName(ty) | 
|  | tyNameClean = tyName.replace(" ", "_").replace("*", "star") | 
|  | fnName = "test_%s" % tyNameClean | 
|  |  | 
|  | print("void %s(void) {" % fnName, file=self.output) | 
|  | self.printSizeOfType("    %s" % fnName, tyName, ty, self.output) | 
|  | self.printAlignOfType("    %s" % fnName, tyName, ty, self.output) | 
|  | self.printOffsetsOfType("    %s" % fnName, tyName, ty, self.output) | 
|  | print("}", file=self.output) | 
|  | print(file=self.output) | 
|  |  | 
|  | self.layoutTests.append((i, fnName)) | 
|  |  | 
|  | def writeFunction(self, i, FT): | 
|  | args = ", ".join( | 
|  | ["%s arg%d" % (self.getTypeName(t), i) for i, t in enumerate(FT.argTypes)] | 
|  | ) | 
|  | if not args: | 
|  | args = "void" | 
|  |  | 
|  | if FT.returnType is None: | 
|  | retvalName = None | 
|  | retvalTypeName = "void" | 
|  | else: | 
|  | retvalTypeName = self.getTypeName(FT.returnType) | 
|  | if self.writeBody or self.outputTests: | 
|  | retvalName = self.getTestReturnValue(FT.returnType) | 
|  |  | 
|  | fnName = "fn%d" % (FT.index,) | 
|  | if self.outputHeader: | 
|  | print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputHeader) | 
|  | elif self.outputTests: | 
|  | print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputTests) | 
|  |  | 
|  | print("%s %s(%s)" % (retvalTypeName, fnName, args), end=" ", file=self.output) | 
|  | if self.writeBody: | 
|  | print("{", file=self.output) | 
|  |  | 
|  | for i, t in enumerate(FT.argTypes): | 
|  | self.printValueOfType("    %s" % fnName, "arg%d" % i, t) | 
|  |  | 
|  | if retvalName is not None: | 
|  | print("  return %s;" % (retvalName,), file=self.output) | 
|  | print("}", file=self.output) | 
|  | else: | 
|  | print("{}", file=self.output) | 
|  | print(file=self.output) | 
|  |  | 
|  | if self.outputDriver: | 
|  | print("  if (index == -1 || index == %d) {" % i, file=self.outputDriver) | 
|  | print("    extern void test_%s(void);" % fnName, file=self.outputDriver) | 
|  | print("    test_%s();" % fnName, file=self.outputDriver) | 
|  | print("   }", file=self.outputDriver) | 
|  |  | 
|  | if self.outputTests: | 
|  | if self.outputHeader: | 
|  | print("void test_%s(void);" % (fnName,), file=self.outputHeader) | 
|  |  | 
|  | if retvalName is None: | 
|  | retvalTests = None | 
|  | else: | 
|  | retvalTests = self.getTestValuesArray(FT.returnType) | 
|  | tests = [self.getTestValuesArray(ty) for ty in FT.argTypes] | 
|  | print("void test_%s(void) {" % (fnName,), file=self.outputTests) | 
|  |  | 
|  | if retvalTests is not None: | 
|  | print( | 
|  | '  printf("%s: testing return.\\n");' % (fnName,), | 
|  | file=self.outputTests, | 
|  | ) | 
|  | print( | 
|  | "  for (int i=0; i<%d; ++i) {" % (retvalTests[1],), | 
|  | file=self.outputTests, | 
|  | ) | 
|  | args = ", ".join(["%s[%d]" % (t, randrange(l)) for t, l in tests]) | 
|  | print("    %s RV;" % (retvalTypeName,), file=self.outputTests) | 
|  | print( | 
|  | "    %s = %s[i];" % (retvalName, retvalTests[0]), | 
|  | file=self.outputTests, | 
|  | ) | 
|  | print("    RV = %s(%s);" % (fnName, args), file=self.outputTests) | 
|  | self.printValueOfType( | 
|  | "  %s_RV" % fnName, | 
|  | "RV", | 
|  | FT.returnType, | 
|  | output=self.outputTests, | 
|  | indent=4, | 
|  | ) | 
|  | self.checkTypeValues( | 
|  | "RV", | 
|  | "%s[i]" % retvalTests[0], | 
|  | FT.returnType, | 
|  | output=self.outputTests, | 
|  | indent=4, | 
|  | ) | 
|  | print("  }", file=self.outputTests) | 
|  |  | 
|  | if tests: | 
|  | print( | 
|  | '  printf("%s: testing arguments.\\n");' % (fnName,), | 
|  | file=self.outputTests, | 
|  | ) | 
|  | for i, (array, length) in enumerate(tests): | 
|  | for j in range(length): | 
|  | args = ["%s[%d]" % (t, randrange(l)) for t, l in tests] | 
|  | args[i] = "%s[%d]" % (array, j) | 
|  | print( | 
|  | "  %s(%s);" | 
|  | % ( | 
|  | fnName, | 
|  | ", ".join(args), | 
|  | ), | 
|  | file=self.outputTests, | 
|  | ) | 
|  | print("}", file=self.outputTests) | 
|  |  | 
|  | def getTestReturnValue(self, type): | 
|  | typeName = self.getTypeName(type) | 
|  | info = self.testReturnValues.get(typeName) | 
|  | if info is None: | 
|  | name = "%s_retval" % (typeName.replace(" ", "_").replace("*", "star"),) | 
|  | print("%s %s;" % (typeName, name), file=self.output) | 
|  | if self.outputHeader: | 
|  | print("extern %s %s;" % (typeName, name), file=self.outputHeader) | 
|  | elif self.outputTests: | 
|  | print("extern %s %s;" % (typeName, name), file=self.outputTests) | 
|  | info = self.testReturnValues[typeName] = name | 
|  | return info | 
|  |  | 
|  | def getTestValuesArray(self, type): | 
|  | typeName = self.getTypeName(type) | 
|  | info = self.testValues.get(typeName) | 
|  | if info is None: | 
|  | name = "%s_values" % (typeName.replace(" ", "_").replace("*", "star"),) | 
|  | print("static %s %s[] = {" % (typeName, name), file=self.outputTests) | 
|  | length = 0 | 
|  | for item in self.getTestValues(type): | 
|  | print("\t%s," % (item,), file=self.outputTests) | 
|  | length += 1 | 
|  | print("};", file=self.outputTests) | 
|  | info = self.testValues[typeName] = (name, length) | 
|  | return info | 
|  |  | 
|  | def getTestValues(self, t): | 
|  | if isinstance(t, BuiltinType): | 
|  | if t.name == "float": | 
|  | for i in ["0.0", "-1.0", "1.0"]: | 
|  | yield i + "f" | 
|  | elif t.name == "double": | 
|  | for i in ["0.0", "-1.0", "1.0"]: | 
|  | yield i | 
|  | elif t.name in ("void *"): | 
|  | yield "(void*) 0" | 
|  | yield "(void*) -1" | 
|  | else: | 
|  | yield "(%s) 0" % (t.name,) | 
|  | yield "(%s) -1" % (t.name,) | 
|  | yield "(%s) 1" % (t.name,) | 
|  | elif isinstance(t, EnumType): | 
|  | for i in range(0, len(t.enumerators)): | 
|  | yield "enum%dval%d_%d" % (t.index, i, t.unique_id) | 
|  | elif isinstance(t, RecordType): | 
|  | nonPadding = [f for f in t.fields if not f.isPaddingBitField()] | 
|  |  | 
|  | if not nonPadding: | 
|  | yield "{ }" | 
|  | return | 
|  |  | 
|  | # FIXME: Use designated initializers to access non-first | 
|  | # fields of unions. | 
|  | if t.isUnion: | 
|  | for v in self.getTestValues(nonPadding[0]): | 
|  | yield "{ %s }" % v | 
|  | return | 
|  |  | 
|  | fieldValues = [list(v) for v in map(self.getTestValues, nonPadding)] | 
|  | for i, values in enumerate(fieldValues): | 
|  | for v in values: | 
|  | elements = [random.choice(fv) for fv in fieldValues] | 
|  | elements[i] = v | 
|  | yield "{ %s }" % (", ".join(elements)) | 
|  |  | 
|  | elif isinstance(t, ComplexType): | 
|  | for t in self.getTestValues(t.elementType): | 
|  | yield "%s + %s * 1i" % (t, t) | 
|  | elif isinstance(t, ArrayType): | 
|  | values = list(self.getTestValues(t.elementType)) | 
|  | if not values: | 
|  | yield "{ }" | 
|  | for i in range(t.numElements): | 
|  | for v in values: | 
|  | elements = [random.choice(values) for i in range(t.numElements)] | 
|  | elements[i] = v | 
|  | yield "{ %s }" % (", ".join(elements)) | 
|  | else: | 
|  | raise NotImplementedError('Cannot make tests values of type: "%s"' % (t,)) | 
|  |  | 
|  | def printSizeOfType(self, prefix, name, t, output=None, indent=2): | 
|  | print( | 
|  | '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));' | 
|  | % (indent, "", prefix, name, name), | 
|  | file=output, | 
|  | ) | 
|  |  | 
|  | def printAlignOfType(self, prefix, name, t, output=None, indent=2): | 
|  | print( | 
|  | '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));' | 
|  | % (indent, "", prefix, name, name), | 
|  | file=output, | 
|  | ) | 
|  |  | 
|  | def printOffsetsOfType(self, prefix, name, t, output=None, indent=2): | 
|  | if isinstance(t, RecordType): | 
|  | for i, f in enumerate(t.fields): | 
|  | if f.isBitField(): | 
|  | continue | 
|  | fname = "field%d" % i | 
|  | print( | 
|  | '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));' | 
|  | % (indent, "", prefix, name, fname, name, fname), | 
|  | file=output, | 
|  | ) | 
|  |  | 
|  | def printValueOfType(self, prefix, name, t, output=None, indent=2): | 
|  | if output is None: | 
|  | output = self.output | 
|  | if isinstance(t, BuiltinType): | 
|  | value_expr = name | 
|  | if t.name.split(" ")[-1] == "_Bool": | 
|  | # Hack to work around PR5579. | 
|  | value_expr = "%s ? 2 : 0" % name | 
|  |  | 
|  | if t.name.endswith("long long"): | 
|  | code = "lld" | 
|  | elif t.name.endswith("long"): | 
|  | code = "ld" | 
|  | elif t.name.split(" ")[-1] in ("_Bool", "char", "short", "int", "unsigned"): | 
|  | code = "d" | 
|  | elif t.name in ("float", "double"): | 
|  | code = "f" | 
|  | elif t.name == "long double": | 
|  | code = "Lf" | 
|  | else: | 
|  | code = "p" | 
|  | print( | 
|  | '%*sprintf("%s: %s = %%%s\\n", %s);' | 
|  | % (indent, "", prefix, name, code, value_expr), | 
|  | file=output, | 
|  | ) | 
|  | elif isinstance(t, EnumType): | 
|  | print( | 
|  | '%*sprintf("%s: %s = %%d\\n", %s);' % (indent, "", prefix, name, name), | 
|  | file=output, | 
|  | ) | 
|  | elif isinstance(t, RecordType): | 
|  | if not t.fields: | 
|  | print( | 
|  | '%*sprintf("%s: %s (empty)\\n");' % (indent, "", prefix, name), | 
|  | file=output, | 
|  | ) | 
|  | for i, f in enumerate(t.fields): | 
|  | if f.isPaddingBitField(): | 
|  | continue | 
|  | fname = "%s.field%d" % (name, i) | 
|  | self.printValueOfType(prefix, fname, f, output=output, indent=indent) | 
|  | elif isinstance(t, ComplexType): | 
|  | self.printValueOfType( | 
|  | prefix, | 
|  | "(__real %s)" % name, | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | self.printValueOfType( | 
|  | prefix, | 
|  | "(__imag %s)" % name, | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | elif isinstance(t, ArrayType): | 
|  | for i in range(t.numElements): | 
|  | # Access in this fashion as a hackish way to portably | 
|  | # access vectors. | 
|  | if t.isVector: | 
|  | self.printValueOfType( | 
|  | prefix, | 
|  | "((%s*) &%s)[%d]" % (t.elementType, name, i), | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | else: | 
|  | self.printValueOfType( | 
|  | prefix, | 
|  | "%s[%d]" % (name, i), | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | else: | 
|  | raise NotImplementedError('Cannot print value of type: "%s"' % (t,)) | 
|  |  | 
|  | def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2): | 
|  | prefix = "foo" | 
|  | if output is None: | 
|  | output = self.output | 
|  | if isinstance(t, BuiltinType): | 
|  | print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output) | 
|  | elif isinstance(t, EnumType): | 
|  | print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output) | 
|  | elif isinstance(t, RecordType): | 
|  | for i, f in enumerate(t.fields): | 
|  | if f.isPaddingBitField(): | 
|  | continue | 
|  | self.checkTypeValues( | 
|  | "%s.field%d" % (nameLHS, i), | 
|  | "%s.field%d" % (nameRHS, i), | 
|  | f, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | if t.isUnion: | 
|  | break | 
|  | elif isinstance(t, ComplexType): | 
|  | self.checkTypeValues( | 
|  | "(__real %s)" % nameLHS, | 
|  | "(__real %s)" % nameRHS, | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | self.checkTypeValues( | 
|  | "(__imag %s)" % nameLHS, | 
|  | "(__imag %s)" % nameRHS, | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | elif isinstance(t, ArrayType): | 
|  | for i in range(t.numElements): | 
|  | # Access in this fashion as a hackish way to portably | 
|  | # access vectors. | 
|  | if t.isVector: | 
|  | self.checkTypeValues( | 
|  | "((%s*) &%s)[%d]" % (t.elementType, nameLHS, i), | 
|  | "((%s*) &%s)[%d]" % (t.elementType, nameRHS, i), | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | else: | 
|  | self.checkTypeValues( | 
|  | "%s[%d]" % (nameLHS, i), | 
|  | "%s[%d]" % (nameRHS, i), | 
|  | t.elementType, | 
|  | output=output, | 
|  | indent=indent, | 
|  | ) | 
|  | else: | 
|  | raise NotImplementedError('Cannot print value of type: "%s"' % (t,)) | 
|  |  | 
|  |  | 
|  | import sys | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | from optparse import OptionParser, OptionGroup | 
|  |  | 
|  | parser = OptionParser("%prog [options] {indices}") | 
|  | parser.add_option( | 
|  | "", | 
|  | "--mode", | 
|  | dest="mode", | 
|  | help="autogeneration mode (random or linear) [default %default]", | 
|  | type="choice", | 
|  | choices=("random", "linear"), | 
|  | default="linear", | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--count", | 
|  | dest="count", | 
|  | help="autogenerate COUNT functions according to MODE", | 
|  | type=int, | 
|  | default=0, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--min", | 
|  | dest="minIndex", | 
|  | metavar="N", | 
|  | help="start autogeneration with the Nth function type  [default %default]", | 
|  | type=int, | 
|  | default=0, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--max", | 
|  | dest="maxIndex", | 
|  | metavar="N", | 
|  | help="maximum index for random autogeneration  [default %default]", | 
|  | type=int, | 
|  | default=10000000, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--seed", | 
|  | dest="seed", | 
|  | help="random number generator seed [default %default]", | 
|  | type=int, | 
|  | default=1, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--use-random-seed", | 
|  | dest="useRandomSeed", | 
|  | help="use random value for initial random number generator seed", | 
|  | action="store_true", | 
|  | default=False, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--skip", | 
|  | dest="skipTests", | 
|  | help="add a test index to skip", | 
|  | type=int, | 
|  | action="append", | 
|  | default=[], | 
|  | ) | 
|  | parser.add_option( | 
|  | "-o", | 
|  | "--output", | 
|  | dest="output", | 
|  | metavar="FILE", | 
|  | help="write output to FILE  [default %default]", | 
|  | type=str, | 
|  | default="-", | 
|  | ) | 
|  | parser.add_option( | 
|  | "-O", | 
|  | "--output-header", | 
|  | dest="outputHeader", | 
|  | metavar="FILE", | 
|  | help="write header file for output to FILE  [default %default]", | 
|  | type=str, | 
|  | default=None, | 
|  | ) | 
|  | parser.add_option( | 
|  | "-T", | 
|  | "--output-tests", | 
|  | dest="outputTests", | 
|  | metavar="FILE", | 
|  | help="write function tests to FILE  [default %default]", | 
|  | type=str, | 
|  | default=None, | 
|  | ) | 
|  | parser.add_option( | 
|  | "-D", | 
|  | "--output-driver", | 
|  | dest="outputDriver", | 
|  | metavar="FILE", | 
|  | help="write test driver to FILE  [default %default]", | 
|  | type=str, | 
|  | default=None, | 
|  | ) | 
|  | parser.add_option( | 
|  | "", | 
|  | "--test-layout", | 
|  | dest="testLayout", | 
|  | metavar="FILE", | 
|  | help="test structure layout", | 
|  | action="store_true", | 
|  | default=False, | 
|  | ) | 
|  |  | 
|  | group = OptionGroup(parser, "Type Enumeration Options") | 
|  | # Builtins - Ints | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-char", | 
|  | dest="useChar", | 
|  | help="do not generate char types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-short", | 
|  | dest="useShort", | 
|  | help="do not generate short types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-int", | 
|  | dest="useInt", | 
|  | help="do not generate int types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-long", | 
|  | dest="useLong", | 
|  | help="do not generate long types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-long-long", | 
|  | dest="useLongLong", | 
|  | help="do not generate long long types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-unsigned", | 
|  | dest="useUnsigned", | 
|  | help="do not generate unsigned integer types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  |  | 
|  | # Other builtins | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-bool", | 
|  | dest="useBool", | 
|  | help="do not generate bool types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-float", | 
|  | dest="useFloat", | 
|  | help="do not generate float types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-double", | 
|  | dest="useDouble", | 
|  | help="do not generate double types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-long-double", | 
|  | dest="useLongDouble", | 
|  | help="do not generate long double types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-void-pointer", | 
|  | dest="useVoidPointer", | 
|  | help="do not generate void* types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  |  | 
|  | # Enumerations | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-enums", | 
|  | dest="useEnum", | 
|  | help="do not generate enum types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  |  | 
|  | # Derived types | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-array", | 
|  | dest="useArray", | 
|  | help="do not generate record types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-complex", | 
|  | dest="useComplex", | 
|  | help="do not generate complex types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-record", | 
|  | dest="useRecord", | 
|  | help="do not generate record types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-union", | 
|  | dest="recordUseUnion", | 
|  | help="do not generate union types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-vector", | 
|  | dest="useVector", | 
|  | help="do not generate vector types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-bit-field", | 
|  | dest="useBitField", | 
|  | help="do not generate bit-field record members", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-builtins", | 
|  | dest="useBuiltins", | 
|  | help="do not use any types", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  |  | 
|  | # Tuning | 
|  | group.add_option( | 
|  | "", | 
|  | "--no-function-return", | 
|  | dest="functionUseReturn", | 
|  | help="do not generate return types for functions", | 
|  | action="store_false", | 
|  | default=True, | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--vector-types", | 
|  | dest="vectorTypes", | 
|  | help="comma separated list of vector types (e.g., v2i32) [default %default]", | 
|  | action="store", | 
|  | type=str, | 
|  | default="v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32", | 
|  | metavar="N", | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--bit-fields", | 
|  | dest="bitFields", | 
|  | help="comma separated list 'type:width' bit-field specifiers [default %default]", | 
|  | action="store", | 
|  | type=str, | 
|  | default=("char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24"), | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--max-args", | 
|  | dest="functionMaxArgs", | 
|  | help="maximum number of arguments per function [default %default]", | 
|  | action="store", | 
|  | type=int, | 
|  | default=4, | 
|  | metavar="N", | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--max-array", | 
|  | dest="arrayMaxSize", | 
|  | help="maximum array size [default %default]", | 
|  | action="store", | 
|  | type=int, | 
|  | default=4, | 
|  | metavar="N", | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--max-record", | 
|  | dest="recordMaxSize", | 
|  | help="maximum number of fields per record [default %default]", | 
|  | action="store", | 
|  | type=int, | 
|  | default=4, | 
|  | metavar="N", | 
|  | ) | 
|  | group.add_option( | 
|  | "", | 
|  | "--max-record-depth", | 
|  | dest="recordMaxDepth", | 
|  | help="maximum nested structure depth [default %default]", | 
|  | action="store", | 
|  | type=int, | 
|  | default=None, | 
|  | metavar="N", | 
|  | ) | 
|  | parser.add_option_group(group) | 
|  | (opts, args) = parser.parse_args() | 
|  |  | 
|  | if not opts.useRandomSeed: | 
|  | random.seed(opts.seed) | 
|  |  | 
|  | # Construct type generator | 
|  | builtins = [] | 
|  | if opts.useBuiltins: | 
|  | ints = [] | 
|  | if opts.useChar: | 
|  | ints.append(("char", 1)) | 
|  | if opts.useShort: | 
|  | ints.append(("short", 2)) | 
|  | if opts.useInt: | 
|  | ints.append(("int", 4)) | 
|  | # FIXME: Wrong size. | 
|  | if opts.useLong: | 
|  | ints.append(("long", 4)) | 
|  | if opts.useLongLong: | 
|  | ints.append(("long long", 8)) | 
|  | if opts.useUnsigned: | 
|  | ints = [("unsigned %s" % i, s) for i, s in ints] + [ | 
|  | ("signed %s" % i, s) for i, s in ints | 
|  | ] | 
|  | builtins.extend(ints) | 
|  |  | 
|  | if opts.useBool: | 
|  | builtins.append(("_Bool", 1)) | 
|  | if opts.useFloat: | 
|  | builtins.append(("float", 4)) | 
|  | if opts.useDouble: | 
|  | builtins.append(("double", 8)) | 
|  | if opts.useLongDouble: | 
|  | builtins.append(("long double", 16)) | 
|  | # FIXME: Wrong size. | 
|  | if opts.useVoidPointer: | 
|  | builtins.append(("void*", 4)) | 
|  |  | 
|  | btg = FixedTypeGenerator([BuiltinType(n, s) for n, s in builtins]) | 
|  |  | 
|  | bitfields = [] | 
|  | for specifier in opts.bitFields.split(","): | 
|  | if not specifier.strip(): | 
|  | continue | 
|  | name, width = specifier.strip().split(":", 1) | 
|  | bitfields.append(BuiltinType(name, None, int(width))) | 
|  | bftg = FixedTypeGenerator(bitfields) | 
|  |  | 
|  | charType = BuiltinType("char", 1) | 
|  | shortType = BuiltinType("short", 2) | 
|  | intType = BuiltinType("int", 4) | 
|  | longlongType = BuiltinType("long long", 8) | 
|  | floatType = BuiltinType("float", 4) | 
|  | doubleType = BuiltinType("double", 8) | 
|  | sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType]) | 
|  |  | 
|  | atg = AnyTypeGenerator() | 
|  | artg = AnyTypeGenerator() | 
|  |  | 
|  | def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField): | 
|  | atg.addGenerator(btg) | 
|  | if useBitField and opts.useBitField: | 
|  | atg.addGenerator(bftg) | 
|  | if useRecord and opts.useRecord: | 
|  | assert subgen | 
|  | atg.addGenerator( | 
|  | RecordTypeGenerator( | 
|  | subfieldgen, opts.recordUseUnion, opts.recordMaxSize | 
|  | ) | 
|  | ) | 
|  | if opts.useComplex: | 
|  | # FIXME: Allow overriding builtins here | 
|  | atg.addGenerator(ComplexTypeGenerator(sbtg)) | 
|  | if useArray and opts.useArray: | 
|  | assert subgen | 
|  | atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize)) | 
|  | if opts.useVector: | 
|  | vTypes = [] | 
|  | for i, t in enumerate(opts.vectorTypes.split(",")): | 
|  | m = re.match("v([1-9][0-9]*)([if][1-9][0-9]*)", t.strip()) | 
|  | if not m: | 
|  | parser.error("Invalid vector type: %r" % t) | 
|  | count, kind = m.groups() | 
|  | count = int(count) | 
|  | type = { | 
|  | "i8": charType, | 
|  | "i16": shortType, | 
|  | "i32": intType, | 
|  | "i64": longlongType, | 
|  | "f32": floatType, | 
|  | "f64": doubleType, | 
|  | }.get(kind) | 
|  | if not type: | 
|  | parser.error("Invalid vector type: %r" % t) | 
|  | vTypes.append(ArrayType(i, True, type, count * type.size)) | 
|  |  | 
|  | atg.addGenerator(FixedTypeGenerator(vTypes)) | 
|  | if opts.useEnum: | 
|  | atg.addGenerator(EnumTypeGenerator([None, "-1", "1", "1u"], 1, 4)) | 
|  |  | 
|  | if opts.recordMaxDepth is None: | 
|  | # Fully recursive, just avoid top-level arrays. | 
|  | subFTG = AnyTypeGenerator() | 
|  | subTG = AnyTypeGenerator() | 
|  | atg = AnyTypeGenerator() | 
|  | makeGenerator(subFTG, atg, atg, True, True, True) | 
|  | makeGenerator(subTG, atg, subFTG, True, True, False) | 
|  | makeGenerator(atg, subTG, subFTG, True, False, False) | 
|  | else: | 
|  | # Make a chain of type generators, each builds smaller | 
|  | # structures. | 
|  | base = AnyTypeGenerator() | 
|  | fbase = AnyTypeGenerator() | 
|  | makeGenerator(base, None, None, False, False, False) | 
|  | makeGenerator(fbase, None, None, False, False, True) | 
|  | for i in range(opts.recordMaxDepth): | 
|  | n = AnyTypeGenerator() | 
|  | fn = AnyTypeGenerator() | 
|  | makeGenerator(n, base, fbase, True, True, False) | 
|  | makeGenerator(fn, base, fbase, True, True, True) | 
|  | base = n | 
|  | fbase = fn | 
|  | atg = AnyTypeGenerator() | 
|  | makeGenerator(atg, base, fbase, True, False, False) | 
|  |  | 
|  | if opts.testLayout: | 
|  | ftg = atg | 
|  | else: | 
|  | ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs) | 
|  |  | 
|  | # Override max,min,count if finite | 
|  | if opts.maxIndex is None: | 
|  | if ftg.cardinality is aleph0: | 
|  | opts.maxIndex = 10000000 | 
|  | else: | 
|  | opts.maxIndex = ftg.cardinality | 
|  | opts.maxIndex = min(opts.maxIndex, ftg.cardinality) | 
|  | opts.minIndex = max(0, min(opts.maxIndex - 1, opts.minIndex)) | 
|  | if not opts.mode == "random": | 
|  | opts.count = min(opts.count, opts.maxIndex - opts.minIndex) | 
|  |  | 
|  | if opts.output == "-": | 
|  | output = sys.stdout | 
|  | else: | 
|  | output = open(opts.output, "w") | 
|  | atexit.register(lambda: output.close()) | 
|  |  | 
|  | outputHeader = None | 
|  | if opts.outputHeader: | 
|  | outputHeader = open(opts.outputHeader, "w") | 
|  | atexit.register(lambda: outputHeader.close()) | 
|  |  | 
|  | outputTests = None | 
|  | if opts.outputTests: | 
|  | outputTests = open(opts.outputTests, "w") | 
|  | atexit.register(lambda: outputTests.close()) | 
|  |  | 
|  | outputDriver = None | 
|  | if opts.outputDriver: | 
|  | outputDriver = open(opts.outputDriver, "w") | 
|  | atexit.register(lambda: outputDriver.close()) | 
|  |  | 
|  | info = "" | 
|  | info += "// %s\n" % (" ".join(sys.argv),) | 
|  | info += "// Generated: %s\n" % (time.strftime("%Y-%m-%d %H:%M"),) | 
|  | info += "// Cardinality of function generator: %s\n" % (ftg.cardinality,) | 
|  | info += "// Cardinality of type generator: %s\n" % (atg.cardinality,) | 
|  |  | 
|  | if opts.testLayout: | 
|  | info += "\n#include <stdio.h>" | 
|  |  | 
|  | P = TypePrinter( | 
|  | output, | 
|  | outputHeader=outputHeader, | 
|  | outputTests=outputTests, | 
|  | outputDriver=outputDriver, | 
|  | headerName=opts.outputHeader, | 
|  | info=info, | 
|  | ) | 
|  |  | 
|  | def write(N): | 
|  | try: | 
|  | FT = ftg.get(N) | 
|  | except RuntimeError as e: | 
|  | if e.args[0] == "maximum recursion depth exceeded": | 
|  | print( | 
|  | "WARNING: Skipped %d, recursion limit exceeded (bad arguments?)" | 
|  | % (N,), | 
|  | file=sys.stderr, | 
|  | ) | 
|  | return | 
|  | raise | 
|  | if opts.testLayout: | 
|  | P.writeLayoutTest(N, FT) | 
|  | else: | 
|  | P.writeFunction(N, FT) | 
|  |  | 
|  | if args: | 
|  | [write(int(a)) for a in args] | 
|  |  | 
|  | skipTests = set(opts.skipTests) | 
|  | for i in range(opts.count): | 
|  | if opts.mode == "linear": | 
|  | index = opts.minIndex + i | 
|  | else: | 
|  | index = opts.minIndex + int( | 
|  | (opts.maxIndex - opts.minIndex) * random.random() | 
|  | ) | 
|  | if index in skipTests: | 
|  | continue | 
|  | write(index) | 
|  |  | 
|  | P.finish() | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |