ABITestGen.py revision e8c55b407d8fc494d814d5fda256a47f27ace3a5
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom pprint import pprint 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport random, atexit, time 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom random import randrange 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom Enumeration import * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from TypeGen import * 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#### 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TypePrinter: 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, output, outputHeader=None, 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outputTests=None, outputDriver=None, 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headerName=None, info=None): 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.output = output 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.outputHeader = outputHeader 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.outputTests = outputTests 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.outputDriver = outputDriver 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.writeBody = outputHeader or outputTests or outputDriver 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.types = {} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.testValues = {} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.testReturnValues = {} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.layoutTests = [] 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if info: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for f in (self.output,self.outputHeader,self.outputTests,self.outputDriver): 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if f: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>f,info 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.writeBody: 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, '#include <stdio.h>\n' 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.outputTests: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.outputTests, '#include <stdio.h>\n' 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if headerName: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for f in (self.output,self.outputTests,self.outputDriver): 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if f is not None: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>f, '#include "%s"\n'%(headerName,) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.outputDriver: 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.outputDriver, 'int main(int argc, char **argv) {' 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def finish(self): 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if self.layoutTests: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, 'int main(int argc, char **argv) {' 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for f in self.layoutTests: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, ' %s();' % f 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, ' return 0;' 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, '}' 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.outputDriver: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.outputDriver, ' return 0;' 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.outputDriver, '}' 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def getTypeName(self, T): 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if isinstance(T,BuiltinType): 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return T.name 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = self.types.get(T) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if name is None: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = 'T%d'%(len(self.types),) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Reserve slot 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.types[T] = None 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.outputHeader: 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.outputHeader,T.getTypedefDef(name, self) 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else: 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.output,T.getTypedefDef(name, self) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.outputTests: 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.outputTests,T.getTypedefDef(name, self) 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch self.types[T] = name 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return name 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def writeLayoutTest(self, i, ty): 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tyName = self.getTypeName(ty) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tyNameClean = tyName.replace(' ','_').replace('*','star') 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fnName = 'test_%s' % tyNameClean 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.output,'void %s(void) {' % fnName 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.printSizeOfType(' %s'%fnName, tyName, ty, self.output) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.printAlignOfType(' %s'%fnName, tyName, ty, self.output) 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output,'}' 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.layoutTests.append(fnName) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def writeFunction(self, i, FT): 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)]) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not args: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args = 'void' 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if FT.returnType is None: 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch retvalName = None 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retvalTypeName = 'void' 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retvalTypeName = self.getTypeName(FT.returnType) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.writeBody or self.outputTests: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retvalName = self.getTestReturnValue(FT.returnType) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fnName = 'fn%d'%(FT.index,) 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if self.outputHeader: 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args) 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch elif self.outputTests: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args), 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.writeBody: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, '{' 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for i,t in enumerate(FT.argTypes): 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.printValueOfType(' %s'%fnName, 'arg%d'%i, t) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if retvalName is not None: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, ' return %s;'%(retvalName,) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print >>self.output, '}' 116 else: 117 print >>self.output, '{}' 118 print >>self.output 119 120 if self.outputDriver: 121 print >>self.outputDriver, ' { extern void test_%s(void); test_%s(); }\n'%(fnName,fnName,) 122 123 if self.outputTests: 124 if self.outputHeader: 125 print >>self.outputHeader, 'void test_%s(void);'%(fnName,) 126 127 if retvalName is None: 128 retvalTests = None 129 else: 130 retvalTests = self.getTestValuesArray(FT.returnType) 131 tests = map(self.getTestValuesArray, FT.argTypes) 132 print >>self.outputTests, 'void test_%s(void) {'%(fnName,) 133 134 if retvalTests is not None: 135 print >>self.outputTests, ' printf("%s: testing return.\\n");'%(fnName,) 136 print >>self.outputTests, ' for (int i=0; i<%d; ++i) {'%(retvalTests[1],) 137 args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests]) 138 print >>self.outputTests, ' %s RV;'%(retvalTypeName,) 139 print >>self.outputTests, ' %s = %s[i];'%(retvalName, retvalTests[0]) 140 print >>self.outputTests, ' RV = %s(%s);'%(fnName, args) 141 self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4) 142 print >>self.outputTests, ' }' 143 144 if tests: 145 print >>self.outputTests, ' printf("%s: testing arguments.\\n");'%(fnName,) 146 for i,(array,length) in enumerate(tests): 147 for j in range(length): 148 args = ['%s[%d]'%(t,randrange(l)) for t,l in tests] 149 args[i] = '%s[%d]'%(array,j) 150 print >>self.outputTests, ' %s(%s);'%(fnName, ', '.join(args),) 151 print >>self.outputTests, '}' 152 153 def getTestReturnValue(self, type): 154 typeName = self.getTypeName(type) 155 info = self.testReturnValues.get(typeName) 156 if info is None: 157 name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),) 158 print >>self.output, '%s %s;'%(typeName,name) 159 if self.outputHeader: 160 print >>self.outputHeader, 'extern %s %s;'%(typeName,name) 161 elif self.outputTests: 162 print >>self.outputTests, 'extern %s %s;'%(typeName,name) 163 info = self.testReturnValues[typeName] = name 164 return info 165 166 def getTestValuesArray(self, type): 167 typeName = self.getTypeName(type) 168 info = self.testValues.get(typeName) 169 if info is None: 170 name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),) 171 print >>self.outputTests, 'static %s %s[] = {'%(typeName,name) 172 length = 0 173 for item in self.getTestValues(type): 174 print >>self.outputTests, '\t%s,'%(item,) 175 length += 1 176 print >>self.outputTests,'};' 177 info = self.testValues[typeName] = (name,length) 178 return info 179 180 def getTestValues(self, t): 181 if isinstance(t, BuiltinType): 182 if t.name=='float': 183 for i in ['0.0','-1.0','1.0']: 184 yield i+'f' 185 elif t.name=='double': 186 for i in ['0.0','-1.0','1.0']: 187 yield i 188 elif t.name in ('void *'): 189 yield '(void*) 0' 190 yield '(void*) -1' 191 else: 192 yield '(%s) 0'%(t.name,) 193 yield '(%s) -1'%(t.name,) 194 yield '(%s) 1'%(t.name,) 195 elif isinstance(t, RecordType): 196 if not t.fields: 197 yield '{ }' 198 return 199 # FIXME: Use designated initializers to access non-first 200 # fields of unions. 201 if t.isUnion: 202 for v in self.getTestValues(t.fields[0]): 203 yield '{ %s }' % v 204 return 205 fieldValues = [list(self.getTestValues(f)) for f in t.fields] 206 for i,values in enumerate(fieldValues): 207 for v in values: 208 elements = map(random.choice,fieldValues) 209 elements[i] = v 210 yield '{ %s }'%(', '.join(elements)) 211 elif isinstance(t, ComplexType): 212 for t in self.getTestValues(t.elementType): 213 yield '%s + %s * 1i'%(t,t) 214 elif isinstance(t, ArrayType): 215 values = list(self.getTestValues(t.elementType)) 216 if not values: 217 yield '{ }' 218 for i in range(t.numElements): 219 for v in values: 220 elements = [random.choice(values) for i in range(t.numElements)] 221 elements[i] = v 222 yield '{ %s }'%(', '.join(elements)) 223 else: 224 raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,) 225 226 def printSizeOfType(self, prefix, name, t, output=None, indent=2): 227 print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", sizeof(%s));'%(indent, '', prefix, name, name) 228 def printAlignOfType(self, prefix, name, t, output=None, indent=2): 229 print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", __alignof__(%s));'%(indent, '', prefix, name, name) 230 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2): 231 if isinstance(t, RecordType): 232 for i,f in enumerate(t.fields): 233 fname = 'field%d' % i 234 print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", __builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname) 235 236 def printValueOfType(self, prefix, name, t, output=None, indent=2): 237 if output is None: 238 output = self.output 239 if isinstance(t, BuiltinType): 240 if t.name.endswith('long long'): 241 code = 'lld' 242 elif t.name.endswith('long'): 243 code = 'ld' 244 elif t.name.split(' ')[-1] in ('_Bool','char','short','int'): 245 code = 'd' 246 elif t.name in ('float','double'): 247 code = 'f' 248 elif t.name == 'long double': 249 code = 'Lf' 250 else: 251 code = 'p' 252 print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(indent, '', prefix, name, code, name) 253 elif isinstance(t, RecordType): 254 if not t.fields: 255 print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name) 256 for i,f in enumerate(t.fields): 257 fname = '%s.field%d'%(name,i) 258 self.printValueOfType(prefix, fname, f, output=output, indent=indent) 259 elif isinstance(t, ComplexType): 260 self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent) 261 self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent) 262 elif isinstance(t, ArrayType): 263 for i in range(t.numElements): 264 # Access in this fashion as a hackish way to portably 265 # access vectors. 266 if t.isVector: 267 self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent) 268 else: 269 self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent) 270 else: 271 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,) 272 273import sys 274 275def main(): 276 from optparse import OptionParser, OptionGroup 277 parser = OptionParser("%prog [options] {indices}") 278 parser.add_option("", "--mode", dest="mode", 279 help="autogeneration mode (random or linear) [default %default]", 280 type='choice', choices=('random','linear'), default='linear') 281 parser.add_option("", "--count", dest="count", 282 help="autogenerate COUNT functions according to MODE", 283 type=int, default=0) 284 parser.add_option("", "--min", dest="minIndex", metavar="N", 285 help="start autogeneration with the Nth function type [default %default]", 286 type=int, default=0) 287 parser.add_option("", "--max", dest="maxIndex", metavar="N", 288 help="maximum index for random autogeneration [default %default]", 289 type=int, default=10000000) 290 parser.add_option("", "--seed", dest="seed", 291 help="random number generator seed [default %default]", 292 type=int, default=1) 293 parser.add_option("", "--use-random-seed", dest="useRandomSeed", 294 help="use random value for initial random number generator seed", 295 action='store_true', default=False) 296 parser.add_option("-o", "--output", dest="output", metavar="FILE", 297 help="write output to FILE [default %default]", 298 type=str, default='-') 299 parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE", 300 help="write header file for output to FILE [default %default]", 301 type=str, default=None) 302 parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE", 303 help="write function tests to FILE [default %default]", 304 type=str, default=None) 305 parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE", 306 help="write test driver to FILE [default %default]", 307 type=str, default=None) 308 parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE", 309 help="test structure layout", 310 action='store_true', default=False) 311 312 group = OptionGroup(parser, "Type Enumeration Options") 313 # Builtins - Ints 314 group.add_option("", "--no-char", dest="useChar", 315 help="do not generate char types", 316 action="store_false", default=True) 317 group.add_option("", "--no-short", dest="useShort", 318 help="do not generate short types", 319 action="store_false", default=True) 320 group.add_option("", "--no-int", dest="useInt", 321 help="do not generate int types", 322 action="store_false", default=True) 323 group.add_option("", "--no-long", dest="useLong", 324 help="do not generate long types", 325 action="store_false", default=True) 326 group.add_option("", "--no-long-long", dest="useLongLong", 327 help="do not generate long long types", 328 action="store_false", default=True) 329 group.add_option("", "--no-unsigned", dest="useUnsigned", 330 help="do not generate unsigned integer types", 331 action="store_false", default=True) 332 333 # Other builtins 334 group.add_option("", "--no-bool", dest="useBool", 335 help="do not generate bool types", 336 action="store_false", default=True) 337 group.add_option("", "--no-float", dest="useFloat", 338 help="do not generate float types", 339 action="store_false", default=True) 340 group.add_option("", "--no-double", dest="useDouble", 341 help="do not generate double types", 342 action="store_false", default=True) 343 group.add_option("", "--no-long-double", dest="useLongDouble", 344 help="do not generate long double types", 345 action="store_false", default=True) 346 group.add_option("", "--no-void-pointer", dest="useVoidPointer", 347 help="do not generate void* types", 348 action="store_false", default=True) 349 350 # Derived types 351 group.add_option("", "--no-array", dest="useArray", 352 help="do not generate record types", 353 action="store_false", default=True) 354 group.add_option("", "--no-complex", dest="useComplex", 355 help="do not generate complex types", 356 action="store_false", default=True) 357 group.add_option("", "--no-record", dest="useRecord", 358 help="do not generate record types", 359 action="store_false", default=True) 360 group.add_option("", "--no-union", dest="recordUseUnion", 361 help="do not generate union types", 362 action="store_false", default=True) 363 group.add_option("", "--no-vector", dest="useVector", 364 help="do not generate vector types", 365 action="store_false", default=True) 366 367 # Tuning 368 group.add_option("", "--no-function-return", dest="functionUseReturn", 369 help="do not generate return types for functions", 370 action="store_false", default=True) 371 group.add_option("", "--vector-sizes", dest="vectorSizes", 372 help="comma separated list of sizes for vectors [default %default]", 373 action="store", type=str, default='8,16', metavar="N") 374 375 group.add_option("", "--max-args", dest="functionMaxArgs", 376 help="maximum number of arguments per function [default %default]", 377 action="store", type=int, default=4, metavar="N") 378 group.add_option("", "--max-array", dest="arrayMaxSize", 379 help="maximum array size [default %default]", 380 action="store", type=int, default=4, metavar="N") 381 group.add_option("", "--max-record", dest="recordMaxSize", 382 help="maximum number of fields per record [default %default]", 383 action="store", type=int, default=4, metavar="N") 384 group.add_option("", "--max-record-depth", dest="recordMaxDepth", 385 help="maximum nested structure depth [default %default]", 386 action="store", type=int, default=None, metavar="N") 387 parser.add_option_group(group) 388 (opts, args) = parser.parse_args() 389 390 if not opts.useRandomSeed: 391 random.seed(opts.seed) 392 393 # Contruct type generator 394 builtins = [] 395 ints = [] 396 if opts.useChar: ints.append(('char',1)) 397 if opts.useShort: ints.append(('short',2)) 398 if opts.useInt: ints.append(('int',4)) 399 # FIXME: Wrong size. 400 if opts.useLong: ints.append(('long',4)) 401 if opts.useLongLong: ints.append(('long long',8)) 402 if opts.useUnsigned: 403 ints = ([('unsigned %s'%i,s) for i,s in ints] + 404 [('signed %s'%i,s) for i,s in ints]) 405 builtins.extend(ints) 406 407 if opts.useBool: builtins.append(('_Bool',1)) 408 if opts.useFloat: builtins.append(('float',4)) 409 if opts.useDouble: builtins.append(('double',8)) 410 if opts.useLongDouble: builtins.append(('long double',16)) 411 # FIXME: Wrong size. 412 if opts.useVoidPointer: builtins.append(('void*',4)) 413 414 btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins]) 415 sbtg = FixedTypeGenerator([BuiltinType('char',1), 416 BuiltinType('int',4), 417 BuiltinType('float',4), 418 BuiltinType('double',8)]) 419 420 atg = AnyTypeGenerator() 421 artg = AnyTypeGenerator() 422 def makeGenerator(atg, subgen, useRecord, useArray): 423 atg.addGenerator(btg) 424 if useRecord and opts.useRecord: 425 assert subgen 426 atg.addGenerator(RecordTypeGenerator(subgen, opts.recordUseUnion, 427 opts.recordMaxSize)) 428 if opts.useComplex: 429 # FIXME: Allow overriding builtins here 430 atg.addGenerator(ComplexTypeGenerator(sbtg)) 431 if useArray and opts.useArray: 432 assert subgen 433 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize)) 434 if opts.useVector: 435 atg.addGenerator(VectorTypeGenerator(sbtg, 436 map(int, opts.vectorSizes.split(',')))) 437 438 439 if opts.recordMaxDepth is None: 440 # Fully recursive, just avoid top-level arrays. 441 subTG = AnyTypeGenerator() 442 atg = AnyTypeGenerator() 443 makeGenerator(subTG, atg, True, True) 444 makeGenerator(atg, subTG, True, False) 445 else: 446 # Make a chain of type generators, each builds smaller 447 # structures. 448 base = AnyTypeGenerator() 449 makeGenerator(base, None, False, False) 450 for i in range(opts.recordMaxDepth): 451 n = AnyTypeGenerator() 452 makeGenerator(n, base, True, True) 453 base = n 454 atg = AnyTypeGenerator() 455 makeGenerator(atg, base, True, False) 456 457 if opts.testLayout: 458 ftg = atg 459 else: 460 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs) 461 462 # Override max,min,count if finite 463 if opts.maxIndex is None: 464 if ftg.cardinality is aleph0: 465 opts.maxIndex = 10000000 466 else: 467 opts.maxIndex = ftg.cardinality 468 opts.maxIndex = min(opts.maxIndex, ftg.cardinality) 469 opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex)) 470 if not opts.mode=='random': 471 opts.count = min(opts.count, opts.maxIndex-opts.minIndex) 472 473 if opts.output=='-': 474 output = sys.stdout 475 else: 476 output = open(opts.output,'w') 477 atexit.register(lambda: output.close()) 478 479 outputHeader = None 480 if opts.outputHeader: 481 outputHeader = open(opts.outputHeader,'w') 482 atexit.register(lambda: outputHeader.close()) 483 484 outputTests = None 485 if opts.outputTests: 486 outputTests = open(opts.outputTests,'w') 487 atexit.register(lambda: outputTests.close()) 488 489 outputDriver = None 490 if opts.outputDriver: 491 outputDriver = open(opts.outputDriver,'w') 492 atexit.register(lambda: outputDriver.close()) 493 494 info = '' 495 info += '// %s\n'%(' '.join(sys.argv),) 496 info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),) 497 info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,) 498 info += '// Cardinality of type generator: %s\n'%(atg.cardinality,) 499 500 if opts.testLayout: 501 info += '\n#include <stdio.h>' 502 503 P = TypePrinter(output, 504 outputHeader=outputHeader, 505 outputTests=outputTests, 506 outputDriver=outputDriver, 507 headerName=opts.outputHeader, 508 info=info) 509 510 def write(N): 511 try: 512 FT = ftg.get(N) 513 except RuntimeError,e: 514 if e.args[0]=='maximum recursion depth exceeded': 515 print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,) 516 return 517 raise 518 if opts.testLayout: 519 P.writeLayoutTest(N, FT) 520 else: 521 P.writeFunction(N, FT) 522 523 if args: 524 [write(int(a)) for a in args] 525 526 for i in range(opts.count): 527 if opts.mode=='linear': 528 index = opts.minIndex + i 529 else: 530 index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random()) 531 write(index) 532 533 P.finish() 534 535if __name__=='__main__': 536 main() 537 538