blob: c45a0c343270b5866ef068f19cf6040315f79304 [file] [log] [blame]
Eli Friedman77a1fe92009-07-10 20:15:12 +00001#!/usr/bin/env python
Daniel Dunbara83fb862009-01-15 04:24:17 +00002
3from pprint import pprint
4import random, atexit, time
5from random import randrange
Daniel Dunbar0f1730d2009-02-22 04:17:53 +00006import re
Daniel Dunbara83fb862009-01-15 04:24:17 +00007
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 = {}
Daniel Dunbar5ce61572009-01-28 02:01:23 +000025 self.layoutTests = []
Daniel Dunbara83fb862009-01-15 04:24:17 +000026
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:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000035 print >>self.outputTests, '#include <stdio.h>'
36 print >>self.outputTests, '#include <string.h>'
37 print >>self.outputTests, '#include <assert.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000038
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:
Douglas Gregorc6277a02010-02-02 17:49:52 +000045 print >>self.outputDriver, '#include <stdio.h>'
46 print >>self.outputDriver, '#include <stdlib.h>\n'
Daniel Dunbara83fb862009-01-15 04:24:17 +000047 print >>self.outputDriver, 'int main(int argc, char **argv) {'
Daniel Dunbar484c7ca2009-05-08 23:40:45 +000048 print >>self.outputDriver, ' int index = -1;'
49 print >>self.outputDriver, ' if (argc > 1) index = atoi(argv[1]);'
Daniel Dunbara83fb862009-01-15 04:24:17 +000050
51 def finish(self):
Daniel Dunbar5ce61572009-01-28 02:01:23 +000052 if self.layoutTests:
53 print >>self.output, 'int main(int argc, char **argv) {'
Daniel Dunbar484c7ca2009-05-08 23:40:45 +000054 print >>self.output, ' int index = -1;'
55 print >>self.output, ' if (argc > 1) index = atoi(argv[1]);'
56 for i,f in self.layoutTests:
57 print >>self.output, ' if (index == -1 || index == %d)' % i
58 print >>self.output, ' %s();' % f
Daniel Dunbar5ce61572009-01-28 02:01:23 +000059 print >>self.output, ' return 0;'
60 print >>self.output, '}'
61
Daniel Dunbara83fb862009-01-15 04:24:17 +000062 if self.outputDriver:
Daniel Dunbar9dd60b42009-02-17 23:13:43 +000063 print >>self.outputDriver, ' printf("DONE\\n");'
Daniel Dunbara83fb862009-01-15 04:24:17 +000064 print >>self.outputDriver, ' return 0;'
Daniel Dunbar5ce61572009-01-28 02:01:23 +000065 print >>self.outputDriver, '}'
Daniel Dunbara83fb862009-01-15 04:24:17 +000066
67 def getTypeName(self, T):
68 if isinstance(T,BuiltinType):
69 return T.name
70 name = self.types.get(T)
71 if name is None:
72 name = 'T%d'%(len(self.types),)
73 # Reserve slot
74 self.types[T] = None
75 if self.outputHeader:
76 print >>self.outputHeader,T.getTypedefDef(name, self)
77 else:
78 print >>self.output,T.getTypedefDef(name, self)
79 if self.outputTests:
80 print >>self.outputTests,T.getTypedefDef(name, self)
81 self.types[T] = name
82 return name
83
Daniel Dunbar5ce61572009-01-28 02:01:23 +000084 def writeLayoutTest(self, i, ty):
85 tyName = self.getTypeName(ty)
86 tyNameClean = tyName.replace(' ','_').replace('*','star')
87 fnName = 'test_%s' % tyNameClean
88
89 print >>self.output,'void %s(void) {' % fnName
90 self.printSizeOfType(' %s'%fnName, tyName, ty, self.output)
91 self.printAlignOfType(' %s'%fnName, tyName, ty, self.output)
92 self.printOffsetsOfType(' %s'%fnName, tyName, ty, self.output)
93 print >>self.output,'}'
94 print >>self.output
95
Daniel Dunbar484c7ca2009-05-08 23:40:45 +000096 self.layoutTests.append((i,fnName))
Daniel Dunbar5ce61572009-01-28 02:01:23 +000097
Daniel Dunbara83fb862009-01-15 04:24:17 +000098 def writeFunction(self, i, FT):
99 args = ', '.join(['%s arg%d'%(self.getTypeName(t),i) for i,t in enumerate(FT.argTypes)])
100 if not args:
101 args = 'void'
102
103 if FT.returnType is None:
104 retvalName = None
105 retvalTypeName = 'void'
106 else:
107 retvalTypeName = self.getTypeName(FT.returnType)
108 if self.writeBody or self.outputTests:
109 retvalName = self.getTestReturnValue(FT.returnType)
110
111 fnName = 'fn%d'%(FT.index,)
112 if self.outputHeader:
113 print >>self.outputHeader,'%s %s(%s);'%(retvalTypeName, fnName, args)
114 elif self.outputTests:
115 print >>self.outputTests,'%s %s(%s);'%(retvalTypeName, fnName, args)
116
117 print >>self.output,'%s %s(%s)'%(retvalTypeName, fnName, args),
118 if self.writeBody:
119 print >>self.output, '{'
120
121 for i,t in enumerate(FT.argTypes):
122 self.printValueOfType(' %s'%fnName, 'arg%d'%i, t)
123
124 if retvalName is not None:
125 print >>self.output, ' return %s;'%(retvalName,)
126 print >>self.output, '}'
127 else:
128 print >>self.output, '{}'
129 print >>self.output
130
131 if self.outputDriver:
Daniel Dunbar484c7ca2009-05-08 23:40:45 +0000132 print >>self.outputDriver, ' if (index == -1 || index == %d) {' % i
133 print >>self.outputDriver, ' extern void test_%s(void);' % fnName
134 print >>self.outputDriver, ' test_%s();' % fnName
135 print >>self.outputDriver, ' }'
Daniel Dunbara83fb862009-01-15 04:24:17 +0000136
137 if self.outputTests:
138 if self.outputHeader:
139 print >>self.outputHeader, 'void test_%s(void);'%(fnName,)
140
141 if retvalName is None:
142 retvalTests = None
143 else:
144 retvalTests = self.getTestValuesArray(FT.returnType)
145 tests = map(self.getTestValuesArray, FT.argTypes)
146 print >>self.outputTests, 'void test_%s(void) {'%(fnName,)
147
148 if retvalTests is not None:
149 print >>self.outputTests, ' printf("%s: testing return.\\n");'%(fnName,)
150 print >>self.outputTests, ' for (int i=0; i<%d; ++i) {'%(retvalTests[1],)
151 args = ', '.join(['%s[%d]'%(t,randrange(l)) for t,l in tests])
152 print >>self.outputTests, ' %s RV;'%(retvalTypeName,)
153 print >>self.outputTests, ' %s = %s[i];'%(retvalName, retvalTests[0])
154 print >>self.outputTests, ' RV = %s(%s);'%(fnName, args)
155 self.printValueOfType(' %s_RV'%fnName, 'RV', FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000156 self.checkTypeValues('RV', '%s[i]' % retvalTests[0], FT.returnType, output=self.outputTests, indent=4)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000157 print >>self.outputTests, ' }'
158
159 if tests:
160 print >>self.outputTests, ' printf("%s: testing arguments.\\n");'%(fnName,)
161 for i,(array,length) in enumerate(tests):
162 for j in range(length):
163 args = ['%s[%d]'%(t,randrange(l)) for t,l in tests]
164 args[i] = '%s[%d]'%(array,j)
165 print >>self.outputTests, ' %s(%s);'%(fnName, ', '.join(args),)
166 print >>self.outputTests, '}'
167
168 def getTestReturnValue(self, type):
169 typeName = self.getTypeName(type)
170 info = self.testReturnValues.get(typeName)
171 if info is None:
172 name = '%s_retval'%(typeName.replace(' ','_').replace('*','star'),)
173 print >>self.output, '%s %s;'%(typeName,name)
174 if self.outputHeader:
175 print >>self.outputHeader, 'extern %s %s;'%(typeName,name)
176 elif self.outputTests:
177 print >>self.outputTests, 'extern %s %s;'%(typeName,name)
178 info = self.testReturnValues[typeName] = name
179 return info
180
181 def getTestValuesArray(self, type):
182 typeName = self.getTypeName(type)
183 info = self.testValues.get(typeName)
184 if info is None:
185 name = '%s_values'%(typeName.replace(' ','_').replace('*','star'),)
186 print >>self.outputTests, 'static %s %s[] = {'%(typeName,name)
187 length = 0
188 for item in self.getTestValues(type):
189 print >>self.outputTests, '\t%s,'%(item,)
190 length += 1
191 print >>self.outputTests,'};'
192 info = self.testValues[typeName] = (name,length)
193 return info
194
195 def getTestValues(self, t):
196 if isinstance(t, BuiltinType):
197 if t.name=='float':
198 for i in ['0.0','-1.0','1.0']:
199 yield i+'f'
200 elif t.name=='double':
201 for i in ['0.0','-1.0','1.0']:
202 yield i
203 elif t.name in ('void *'):
204 yield '(void*) 0'
205 yield '(void*) -1'
206 else:
207 yield '(%s) 0'%(t.name,)
208 yield '(%s) -1'%(t.name,)
209 yield '(%s) 1'%(t.name,)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000210 elif isinstance(t, EnumType):
211 for i in range(0, len(t.enumerators)):
212 yield 'enum%dval%d' % (t.index, i)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000213 elif isinstance(t, RecordType):
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000214 nonPadding = [f for f in t.fields
215 if not f.isPaddingBitField()]
216
217 if not nonPadding:
Daniel Dunbara83fb862009-01-15 04:24:17 +0000218 yield '{ }'
Daniel Dunbar900ed552009-01-29 07:36:46 +0000219 return
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000220
Daniel Dunbar900ed552009-01-29 07:36:46 +0000221 # FIXME: Use designated initializers to access non-first
222 # fields of unions.
223 if t.isUnion:
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000224 for v in self.getTestValues(nonPadding[0]):
225 yield '{ %s }' % v
Daniel Dunbar900ed552009-01-29 07:36:46 +0000226 return
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000227
228 fieldValues = map(list, map(self.getTestValues, nonPadding))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000229 for i,values in enumerate(fieldValues):
230 for v in values:
231 elements = map(random.choice,fieldValues)
232 elements[i] = v
233 yield '{ %s }'%(', '.join(elements))
Daniel Dunbar48df17b2009-05-08 22:48:39 +0000234
Daniel Dunbara83fb862009-01-15 04:24:17 +0000235 elif isinstance(t, ComplexType):
236 for t in self.getTestValues(t.elementType):
Daniel Dunbar550faa32009-01-26 19:05:20 +0000237 yield '%s + %s * 1i'%(t,t)
238 elif isinstance(t, ArrayType):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000239 values = list(self.getTestValues(t.elementType))
240 if not values:
241 yield '{ }'
Daniel Dunbar550faa32009-01-26 19:05:20 +0000242 for i in range(t.numElements):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000243 for v in values:
Daniel Dunbar550faa32009-01-26 19:05:20 +0000244 elements = [random.choice(values) for i in range(t.numElements)]
Daniel Dunbara83fb862009-01-15 04:24:17 +0000245 elements[i] = v
246 yield '{ %s }'%(', '.join(elements))
247 else:
248 raise NotImplementedError,'Cannot make tests values of type: "%s"'%(t,)
249
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000250 def printSizeOfType(self, prefix, name, t, output=None, indent=2):
Eli Friedman98a71702009-05-25 21:38:01 +0000251 print >>output, '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'%(indent, '', prefix, name, name)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000252 def printAlignOfType(self, prefix, name, t, output=None, indent=2):
Eli Friedman98a71702009-05-25 21:38:01 +0000253 print >>output, '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'%(indent, '', prefix, name, name)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000254 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
255 if isinstance(t, RecordType):
256 for i,f in enumerate(t.fields):
Eli Friedman98a71702009-05-25 21:38:01 +0000257 if f.isBitField():
Daniel Dunbar122ed242009-05-07 23:19:55 +0000258 continue
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000259 fname = 'field%d' % i
Eli Friedman98a71702009-05-25 21:38:01 +0000260 print >>output, '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'%(indent, '', prefix, name, fname, name, fname)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000261
Daniel Dunbara83fb862009-01-15 04:24:17 +0000262 def printValueOfType(self, prefix, name, t, output=None, indent=2):
263 if output is None:
264 output = self.output
265 if isinstance(t, BuiltinType):
266 if t.name.endswith('long long'):
267 code = 'lld'
268 elif t.name.endswith('long'):
269 code = 'ld'
270 elif t.name.split(' ')[-1] in ('_Bool','char','short','int'):
271 code = 'd'
272 elif t.name in ('float','double'):
273 code = 'f'
274 elif t.name == 'long double':
275 code = 'Lf'
276 else:
277 code = 'p'
278 print >>output, '%*sprintf("%s: %s = %%%s\\n", %s);'%(indent, '', prefix, name, code, name)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000279 elif isinstance(t, EnumType):
280 print >>output, '%*sprintf("%s: %s = %%d\\n", %s);'%(indent, '', prefix, name, name)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000281 elif isinstance(t, RecordType):
282 if not t.fields:
283 print >>output, '%*sprintf("%s: %s (empty)\\n");'%(indent, '', prefix, name)
284 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000285 if f.isPaddingBitField():
286 continue
Daniel Dunbara83fb862009-01-15 04:24:17 +0000287 fname = '%s.field%d'%(name,i)
288 self.printValueOfType(prefix, fname, f, output=output, indent=indent)
289 elif isinstance(t, ComplexType):
290 self.printValueOfType(prefix, '(__real %s)'%name, t.elementType, output=output,indent=indent)
291 self.printValueOfType(prefix, '(__imag %s)'%name, t.elementType, output=output,indent=indent)
Daniel Dunbar550faa32009-01-26 19:05:20 +0000292 elif isinstance(t, ArrayType):
293 for i in range(t.numElements):
294 # Access in this fashion as a hackish way to portably
295 # access vectors.
Daniel Dunbare61e95f2009-01-29 08:48:06 +0000296 if t.isVector:
297 self.printValueOfType(prefix, '((%s*) &%s)[%d]'%(t.elementType,name,i), t.elementType, output=output,indent=indent)
298 else:
299 self.printValueOfType(prefix, '%s[%d]'%(name,i), t.elementType, output=output,indent=indent)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000300 else:
301 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
302
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000303 def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
304 prefix = 'foo'
305 if output is None:
306 output = self.output
307 if isinstance(t, BuiltinType):
308 print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000309 elif isinstance(t, EnumType):
310 print >>output, '%*sassert(%s == %s);' % (indent, '', nameLHS, nameRHS)
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000311 elif isinstance(t, RecordType):
312 for i,f in enumerate(t.fields):
Daniel Dunbar122ed242009-05-07 23:19:55 +0000313 if f.isPaddingBitField():
314 continue
Daniel Dunbar9dd60b42009-02-17 23:13:43 +0000315 self.checkTypeValues('%s.field%d'%(nameLHS,i), '%s.field%d'%(nameRHS,i),
316 f, output=output, indent=indent)
317 if t.isUnion:
318 break
319 elif isinstance(t, ComplexType):
320 self.checkTypeValues('(__real %s)'%nameLHS, '(__real %s)'%nameRHS, t.elementType, output=output,indent=indent)
321 self.checkTypeValues('(__imag %s)'%nameLHS, '(__imag %s)'%nameRHS, t.elementType, output=output,indent=indent)
322 elif isinstance(t, ArrayType):
323 for i in range(t.numElements):
324 # Access in this fashion as a hackish way to portably
325 # access vectors.
326 if t.isVector:
327 self.checkTypeValues('((%s*) &%s)[%d]'%(t.elementType,nameLHS,i),
328 '((%s*) &%s)[%d]'%(t.elementType,nameRHS,i),
329 t.elementType, output=output,indent=indent)
330 else:
331 self.checkTypeValues('%s[%d]'%(nameLHS,i), '%s[%d]'%(nameRHS,i),
332 t.elementType, output=output,indent=indent)
333 else:
334 raise NotImplementedError,'Cannot print value of type: "%s"'%(t,)
335
Daniel Dunbara83fb862009-01-15 04:24:17 +0000336import sys
337
338def main():
339 from optparse import OptionParser, OptionGroup
340 parser = OptionParser("%prog [options] {indices}")
341 parser.add_option("", "--mode", dest="mode",
342 help="autogeneration mode (random or linear) [default %default]",
343 type='choice', choices=('random','linear'), default='linear')
344 parser.add_option("", "--count", dest="count",
345 help="autogenerate COUNT functions according to MODE",
346 type=int, default=0)
347 parser.add_option("", "--min", dest="minIndex", metavar="N",
348 help="start autogeneration with the Nth function type [default %default]",
349 type=int, default=0)
350 parser.add_option("", "--max", dest="maxIndex", metavar="N",
351 help="maximum index for random autogeneration [default %default]",
352 type=int, default=10000000)
353 parser.add_option("", "--seed", dest="seed",
354 help="random number generator seed [default %default]",
355 type=int, default=1)
356 parser.add_option("", "--use-random-seed", dest="useRandomSeed",
357 help="use random value for initial random number generator seed",
358 action='store_true', default=False)
359 parser.add_option("-o", "--output", dest="output", metavar="FILE",
360 help="write output to FILE [default %default]",
361 type=str, default='-')
362 parser.add_option("-O", "--output-header", dest="outputHeader", metavar="FILE",
363 help="write header file for output to FILE [default %default]",
364 type=str, default=None)
365 parser.add_option("-T", "--output-tests", dest="outputTests", metavar="FILE",
366 help="write function tests to FILE [default %default]",
367 type=str, default=None)
368 parser.add_option("-D", "--output-driver", dest="outputDriver", metavar="FILE",
369 help="write test driver to FILE [default %default]",
370 type=str, default=None)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000371 parser.add_option("", "--test-layout", dest="testLayout", metavar="FILE",
372 help="test structure layout",
373 action='store_true', default=False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000374
375 group = OptionGroup(parser, "Type Enumeration Options")
376 # Builtins - Ints
377 group.add_option("", "--no-char", dest="useChar",
378 help="do not generate char types",
379 action="store_false", default=True)
380 group.add_option("", "--no-short", dest="useShort",
381 help="do not generate short types",
382 action="store_false", default=True)
383 group.add_option("", "--no-int", dest="useInt",
384 help="do not generate int types",
385 action="store_false", default=True)
386 group.add_option("", "--no-long", dest="useLong",
387 help="do not generate long types",
388 action="store_false", default=True)
389 group.add_option("", "--no-long-long", dest="useLongLong",
390 help="do not generate long long types",
391 action="store_false", default=True)
392 group.add_option("", "--no-unsigned", dest="useUnsigned",
393 help="do not generate unsigned integer types",
394 action="store_false", default=True)
395
396 # Other builtins
397 group.add_option("", "--no-bool", dest="useBool",
398 help="do not generate bool types",
399 action="store_false", default=True)
400 group.add_option("", "--no-float", dest="useFloat",
401 help="do not generate float types",
402 action="store_false", default=True)
403 group.add_option("", "--no-double", dest="useDouble",
404 help="do not generate double types",
405 action="store_false", default=True)
406 group.add_option("", "--no-long-double", dest="useLongDouble",
407 help="do not generate long double types",
408 action="store_false", default=True)
409 group.add_option("", "--no-void-pointer", dest="useVoidPointer",
410 help="do not generate void* types",
411 action="store_false", default=True)
412
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000413 # Enumerations
414 group.add_option("", "--no-enums", dest="useEnum",
415 help="do not generate enum types",
416 action="store_false", default=True)
417
Daniel Dunbara83fb862009-01-15 04:24:17 +0000418 # Derived types
419 group.add_option("", "--no-array", dest="useArray",
420 help="do not generate record types",
421 action="store_false", default=True)
422 group.add_option("", "--no-complex", dest="useComplex",
423 help="do not generate complex types",
424 action="store_false", default=True)
425 group.add_option("", "--no-record", dest="useRecord",
426 help="do not generate record types",
427 action="store_false", default=True)
428 group.add_option("", "--no-union", dest="recordUseUnion",
429 help="do not generate union types",
430 action="store_false", default=True)
431 group.add_option("", "--no-vector", dest="useVector",
432 help="do not generate vector types",
433 action="store_false", default=True)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000434 group.add_option("", "--no-bit-field", dest="useBitField",
435 help="do not generate bit-field record members",
436 action="store_false", default=True)
437 group.add_option("", "--no-builtins", dest="useBuiltins",
438 help="do not use any types",
439 action="store_false", default=True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000440
441 # Tuning
442 group.add_option("", "--no-function-return", dest="functionUseReturn",
443 help="do not generate return types for functions",
444 action="store_false", default=True)
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000445 group.add_option("", "--vector-types", dest="vectorTypes",
446 help="comma separated list of vector types (e.g., v2i32) [default %default]",
Daniel Dunbarec1abb92009-03-02 06:14:33 +0000447 action="store", type=str, default='v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32', metavar="N")
Daniel Dunbar122ed242009-05-07 23:19:55 +0000448 group.add_option("", "--bit-fields", dest="bitFields",
449 help="comma separated list 'type:width' bit-field specifiers [default %default]",
Daniel Dunbar238a3182009-05-08 20:10:52 +0000450 action="store", type=str, default="char:0,char:4,unsigned:0,unsigned:4,unsigned:13,unsigned:24")
Daniel Dunbara83fb862009-01-15 04:24:17 +0000451 group.add_option("", "--max-args", dest="functionMaxArgs",
452 help="maximum number of arguments per function [default %default]",
453 action="store", type=int, default=4, metavar="N")
454 group.add_option("", "--max-array", dest="arrayMaxSize",
455 help="maximum array size [default %default]",
456 action="store", type=int, default=4, metavar="N")
457 group.add_option("", "--max-record", dest="recordMaxSize",
458 help="maximum number of fields per record [default %default]",
459 action="store", type=int, default=4, metavar="N")
460 group.add_option("", "--max-record-depth", dest="recordMaxDepth",
461 help="maximum nested structure depth [default %default]",
462 action="store", type=int, default=None, metavar="N")
463 parser.add_option_group(group)
464 (opts, args) = parser.parse_args()
465
466 if not opts.useRandomSeed:
467 random.seed(opts.seed)
468
469 # Contruct type generator
470 builtins = []
Daniel Dunbar122ed242009-05-07 23:19:55 +0000471 if opts.useBuiltins:
472 ints = []
473 if opts.useChar: ints.append(('char',1))
474 if opts.useShort: ints.append(('short',2))
475 if opts.useInt: ints.append(('int',4))
476 # FIXME: Wrong size.
477 if opts.useLong: ints.append(('long',4))
478 if opts.useLongLong: ints.append(('long long',8))
479 if opts.useUnsigned:
480 ints = ([('unsigned %s'%i,s) for i,s in ints] +
481 [('signed %s'%i,s) for i,s in ints])
482 builtins.extend(ints)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000483
Daniel Dunbar122ed242009-05-07 23:19:55 +0000484 if opts.useBool: builtins.append(('_Bool',1))
485 if opts.useFloat: builtins.append(('float',4))
486 if opts.useDouble: builtins.append(('double',8))
487 if opts.useLongDouble: builtins.append(('long double',16))
488 # FIXME: Wrong size.
489 if opts.useVoidPointer: builtins.append(('void*',4))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000490
Daniel Dunbar550faa32009-01-26 19:05:20 +0000491 btg = FixedTypeGenerator([BuiltinType(n,s) for n,s in builtins])
Daniel Dunbar122ed242009-05-07 23:19:55 +0000492
493 bitfields = []
494 for specifier in opts.bitFields.split(','):
495 if not specifier.strip():
496 continue
497 name,width = specifier.strip().split(':', 1)
498 bitfields.append(BuiltinType(name,None,int(width)))
499 bftg = FixedTypeGenerator(bitfields)
500
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000501 charType = BuiltinType('char',1)
502 shortType = BuiltinType('short',2)
503 intType = BuiltinType('int',4)
504 longlongType = BuiltinType('long long',8)
505 floatType = BuiltinType('float',4)
506 doubleType = BuiltinType('double',8)
507 sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])
Daniel Dunbara83fb862009-01-15 04:24:17 +0000508
509 atg = AnyTypeGenerator()
510 artg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000511 def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
Daniel Dunbara83fb862009-01-15 04:24:17 +0000512 atg.addGenerator(btg)
Daniel Dunbar122ed242009-05-07 23:19:55 +0000513 if useBitField and opts.useBitField:
514 atg.addGenerator(bftg)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000515 if useRecord and opts.useRecord:
516 assert subgen
Daniel Dunbar122ed242009-05-07 23:19:55 +0000517 atg.addGenerator(RecordTypeGenerator(subfieldgen, opts.recordUseUnion,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000518 opts.recordMaxSize))
519 if opts.useComplex:
520 # FIXME: Allow overriding builtins here
521 atg.addGenerator(ComplexTypeGenerator(sbtg))
522 if useArray and opts.useArray:
523 assert subgen
524 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))
525 if opts.useVector:
Daniel Dunbar0f1730d2009-02-22 04:17:53 +0000526 vTypes = []
527 for i,t in enumerate(opts.vectorTypes.split(',')):
528 m = re.match('v([1-9][0-9]*)([if][1-9][0-9]*)', t.strip())
529 if not m:
530 parser.error('Invalid vector type: %r' % t)
531 count,kind = m.groups()
532 count = int(count)
533 type = { 'i8' : charType,
534 'i16' : shortType,
535 'i32' : intType,
536 'i64' : longlongType,
537 'f32' : floatType,
538 'f64' : doubleType,
539 }.get(kind)
540 if not type:
541 parser.error('Invalid vector type: %r' % t)
542 vTypes.append(ArrayType(i, True, type, count * type.size))
543
544 atg.addGenerator(FixedTypeGenerator(vTypes))
Douglas Gregoraa74a1e2010-02-02 20:10:50 +0000545 if opts.useEnum:
546 atg.addGenerator(EnumTypeGenerator([None, '-1', '1', '1u'], 1, 4))
Daniel Dunbara83fb862009-01-15 04:24:17 +0000547
548 if opts.recordMaxDepth is None:
549 # Fully recursive, just avoid top-level arrays.
Daniel Dunbar122ed242009-05-07 23:19:55 +0000550 subFTG = AnyTypeGenerator()
Daniel Dunbara83fb862009-01-15 04:24:17 +0000551 subTG = AnyTypeGenerator()
552 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000553 makeGenerator(subFTG, atg, atg, True, True, True)
554 makeGenerator(subTG, atg, subFTG, True, True, False)
555 makeGenerator(atg, subTG, subFTG, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000556 else:
557 # Make a chain of type generators, each builds smaller
558 # structures.
559 base = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000560 fbase = AnyTypeGenerator()
561 makeGenerator(base, None, None, False, False, False)
562 makeGenerator(fbase, None, None, False, False, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000563 for i in range(opts.recordMaxDepth):
564 n = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000565 fn = AnyTypeGenerator()
566 makeGenerator(n, base, fbase, True, True, False)
567 makeGenerator(fn, base, fbase, True, True, True)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000568 base = n
Daniel Dunbar122ed242009-05-07 23:19:55 +0000569 fbase = fn
Daniel Dunbara83fb862009-01-15 04:24:17 +0000570 atg = AnyTypeGenerator()
Daniel Dunbar122ed242009-05-07 23:19:55 +0000571 makeGenerator(atg, base, fbase, True, False, False)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000572
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000573 if opts.testLayout:
574 ftg = atg
575 else:
576 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000577
578 # Override max,min,count if finite
579 if opts.maxIndex is None:
580 if ftg.cardinality is aleph0:
581 opts.maxIndex = 10000000
582 else:
583 opts.maxIndex = ftg.cardinality
584 opts.maxIndex = min(opts.maxIndex, ftg.cardinality)
585 opts.minIndex = max(0,min(opts.maxIndex-1, opts.minIndex))
586 if not opts.mode=='random':
587 opts.count = min(opts.count, opts.maxIndex-opts.minIndex)
588
589 if opts.output=='-':
590 output = sys.stdout
591 else:
592 output = open(opts.output,'w')
593 atexit.register(lambda: output.close())
594
595 outputHeader = None
596 if opts.outputHeader:
597 outputHeader = open(opts.outputHeader,'w')
598 atexit.register(lambda: outputHeader.close())
599
600 outputTests = None
601 if opts.outputTests:
602 outputTests = open(opts.outputTests,'w')
603 atexit.register(lambda: outputTests.close())
604
605 outputDriver = None
606 if opts.outputDriver:
607 outputDriver = open(opts.outputDriver,'w')
608 atexit.register(lambda: outputDriver.close())
609
610 info = ''
611 info += '// %s\n'%(' '.join(sys.argv),)
612 info += '// Generated: %s\n'%(time.strftime('%Y-%m-%d %H:%M'),)
613 info += '// Cardinality of function generator: %s\n'%(ftg.cardinality,)
614 info += '// Cardinality of type generator: %s\n'%(atg.cardinality,)
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000615
616 if opts.testLayout:
617 info += '\n#include <stdio.h>'
Daniel Dunbara83fb862009-01-15 04:24:17 +0000618
619 P = TypePrinter(output,
620 outputHeader=outputHeader,
621 outputTests=outputTests,
622 outputDriver=outputDriver,
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000623 headerName=opts.outputHeader,
Daniel Dunbara83fb862009-01-15 04:24:17 +0000624 info=info)
625
626 def write(N):
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000627 try:
Daniel Dunbara83fb862009-01-15 04:24:17 +0000628 FT = ftg.get(N)
629 except RuntimeError,e:
630 if e.args[0]=='maximum recursion depth exceeded':
631 print >>sys.stderr,'WARNING: Skipped %d, recursion limit exceeded (bad arguments?)'%(N,)
632 return
633 raise
Daniel Dunbar5ce61572009-01-28 02:01:23 +0000634 if opts.testLayout:
635 P.writeLayoutTest(N, FT)
636 else:
637 P.writeFunction(N, FT)
Daniel Dunbara83fb862009-01-15 04:24:17 +0000638
639 if args:
640 [write(int(a)) for a in args]
641
642 for i in range(opts.count):
643 if opts.mode=='linear':
644 index = opts.minIndex + i
645 else:
646 index = opts.minIndex + int((opts.maxIndex-opts.minIndex) * random.random())
647 write(index)
648
649 P.finish()
650
651if __name__=='__main__':
652 main()
653