diff options
Diffstat (limited to 'utils')
| -rwxr-xr-x | utils/ABITest/ABITestGen.py | 17 | ||||
| -rw-r--r-- | utils/ABITest/TypeGen.py | 83 |
2 files changed, 98 insertions, 2 deletions
diff --git a/utils/ABITest/ABITestGen.py b/utils/ABITest/ABITestGen.py index 63da02bcda9d..c45a0c343270 100755 --- a/utils/ABITest/ABITestGen.py +++ b/utils/ABITest/ABITestGen.py @@ -42,7 +42,8 @@ class TypePrinter: print >>f, '#include "%s"\n'%(headerName,) if self.outputDriver: - print >>self.outputDriver, '#include <stdio.h>\n' + print >>self.outputDriver, '#include <stdio.h>' + print >>self.outputDriver, '#include <stdlib.h>\n' print >>self.outputDriver, 'int main(int argc, char **argv) {' print >>self.outputDriver, ' int index = -1;' print >>self.outputDriver, ' if (argc > 1) index = atoi(argv[1]);' @@ -206,6 +207,9 @@ class TypePrinter: 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' % (t.index, i) elif isinstance(t, RecordType): nonPadding = [f for f in t.fields if not f.isPaddingBitField()] @@ -272,6 +276,8 @@ class TypePrinter: else: code = 'p' print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(indent, '', prefix, name, code, name) + elif isinstance(t, EnumType): + print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name) elif isinstance(t, RecordType): if not t.fields: print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name) @@ -300,6 +306,8 @@ class TypePrinter: output = self.output if isinstance(t, BuiltinType): print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS) + elif isinstance(t, EnumType): + print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS) elif isinstance(t, RecordType): for i,f in enumerate(t.fields): if f.isPaddingBitField(): @@ -402,6 +410,11 @@ def main(): 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", @@ -529,6 +542,8 @@ def main(): 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. diff --git a/utils/ABITest/TypeGen.py b/utils/ABITest/TypeGen.py index d5678db6a0e8..40ea791eb515 100644 --- a/utils/ABITest/TypeGen.py +++ b/utils/ABITest/TypeGen.py @@ -46,6 +46,28 @@ class BuiltinType(Type): def __str__(self): return self.name +class EnumType(Type): + def __init__(self, index, enumerators): + self.index = index + self.enumerators = enumerators + + def getEnumerators(self): + result = '' + for i, init in enumerate(self.enumerators): + if i > 0: + result = result + ', ' + result = result + 'enum%dval%d' % (self.index, i) + if init: + result = result + ' = %s' % (init) + + return result + + def __str__(self): + return 'enum { %s }' % (self.getEnumerators()) + + def getTypedefDef(self, name, printer): + return 'typedef enum %s { %s } %s;'%(name, self.getEnumerators(), name) + class RecordType(Type): def __init__(self, index, isUnion, fields): self.index = index @@ -188,6 +210,63 @@ class FixedTypeGenerator(TypeGenerator): def generateType(self, N): return self.types[N] +# Factorial +def fact(n): + result = 1 + while n > 0: + result = result * n + n = n - 1 + return result + +# Compute the number of combinations (n choose k) +def num_combinations(n, k): + return fact(n) / (fact(k) * fact(n - k)) + +# Enumerate the combinations choosing k elements from the list of values +def combinations(values, k): + # From ActiveState Recipe 190465: Generator for permutations, + # combinations, selections of a sequence + if k==0: yield [] + else: + for i in xrange(len(values)-k+1): + for cc in combinations(values[i+1:],k-1): + yield [values[i]]+cc + +class EnumTypeGenerator(TypeGenerator): + def __init__(self, values, minEnumerators, maxEnumerators): + TypeGenerator.__init__(self) + self.values = values + self.minEnumerators = minEnumerators + self.maxEnumerators = maxEnumerators + self.setCardinality() + + def setCardinality(self): + self.cardinality = 0 + for num in range(self.minEnumerators, self.maxEnumerators + 1): + self.cardinality += num_combinations(len(self.values), num) + + def generateType(self, n): + # Figure out the number of enumerators in this type + numEnumerators = self.minEnumerators + valuesCovered = 0 + while numEnumerators < self.maxEnumerators: + comb = num_combinations(len(self.values), numEnumerators) + if valuesCovered + comb > n: + break + numEnumerators = numEnumerators + 1 + valuesCovered += comb + + # Find the requested combination of enumerators and build a + # type from it. + i = 0 + for enumerators in combinations(self.values, numEnumerators): + if i == n - valuesCovered: + return EnumType(n, enumerators) + + i = i + 1 + + assert False + class ComplexTypeGenerator(TypeGenerator): def __init__(self, typeGen): TypeGenerator.__init__(self) @@ -363,10 +442,12 @@ def test(): btg = FixedTypeGenerator([BuiltinType('char', 4), BuiltinType('int', 4)]) - + etg = EnumTypeGenerator([None, '-1', '1', '1u'], 0, 3) + atg = AnyTypeGenerator() atg.addGenerator( btg ) atg.addGenerator( RecordTypeGenerator(fields0, False, 4) ) + atg.addGenerator( etg ) print 'Cardinality:',atg.cardinality for i in range(100): if i == atg.cardinality: |
