Adding new platform:ppc32_bgp
[dyninst.git] / testsuite / src / specification / makemake.py
1 import os
2 import tuples
3
4 ######################################################################
5 # Utility functions
6 ######################################################################
7 #
8
9 def uniq(lst):
10    return reduce(lambda l, i: ((i not in l) and l.append(i)) or l, lst, [])
11
12 info = {}
13 def read_tuples(tuplefile):
14    f = open(tuplefile)
15    info['platforms'] = tuples.parse_platforms(f.readline())
16    info['languages'] = tuples.parse_languages(f.readline())
17    info['compilers'] = tuples.parse_compilers(f.readline())
18    info['mutators'] = tuples.parse_mutators(f.readline())
19    info['mutatees'] = tuples.parse_mutatees(f.readline())
20    info['tests'] = tuples.parse_tests(f.readline())
21    info['rungroups'] = tuples.parse_rungroups(f.readline())
22 #  info['exception_types'] = tuples.parse_exception_types(f.readline())
23    info['exception_types'] = None
24 #  info['exceptions'] = tuples.parse_exceptions(f.readline())
25    info['exceptions'] = None
26    info['objects'] = tuples.parse_object_files(f.readline())
27    f.close()
28
29
30 def extension(filename):
31    ext_ndx = filename.rfind('.')
32    return filename[ext_ndx:]
33
34 def replace_extension(name, ext):
35    dot_ndx = name.rfind('.')
36    return name[:dot_ndx] + ext
37
38 # Get the name of the language for the given file.  If more than one
39 # is possible, I don't really know what to do...  Return a list of all
40 # the possibilities with compilers on the current platform?
41 # We should not ever get more than one language for a given extension.  We're
42 # enforcing that in the tuple generator.
43 def get_file_lang(filename):
44    ext = extension(filename)
45    langs = filter(lambda x: ext in x['extensions'], info['languages'])
46    # We have a list of all languages which match the extension of the file
47    # Filter out all of those languages for which there is no compiler on this
48    # platform:
49    #  Find the compilers available on this platform
50    platform = os.environ.get('PLATFORM')
51    comps = filter(lambda x: platform in info['compilers'][x]['platforms'],
52                info['compilers'])
53    #  Get a list of all the languages supported by those compilers
54    supported_langs = map(lambda x: info['compilers'][x]['languages'],
55                     comps)
56    supported_langs = reduce(lambda x,y:x+y, supported_langs)
57    supported_langs = uniq(supported_langs)
58    #  Remove all languages from langs that aren't in supported_langs
59    langs = filter(lambda x: x['name'] in supported_langs, langs)
60    if len(langs) > 1:
61       return langs
62    else:
63       return langs[0]
64
65 def compiler_count(lang):
66    plat = os.environ.get('PLATFORM')
67    return len(filter(lambda x: lang in info['compilers'][x]['languages']
68                        and plat in info['compilers'][x]['platforms']
69                  , info['compilers']))
70
71 def find_platform(pname):
72    plist = filter(lambda p: p['name'] == pname, info['platforms'])
73    if len(plist) == 0:
74       return None
75    else:
76       return plist[0]
77
78 def find_language(lname):
79    llist = filter(lambda l: l['name'] == lname, info['languages'])
80    if len(llist) == 0:
81       return None
82    else:
83       return llist[0]
84
85 # Returns a string containing the mutatee's compile-time options filename
86 # component: a string of the form _<compiler>_<ABI>_<optimization>
87 def mutatee_cto_component(mutatee):
88    compiler = info['compilers'][mutatee['compiler']]
89    return fullspec_cto_component(compiler,
90                           mutatee['abi'],
91                           mutatee['optimization'], mutatee['pic'])
92
93 # Returns a string containing the mutatee's compile-time options filename
94 # component for mutatees compiled with an auxilliary compiler
95 def auxcomp_cto_component(compiler, mutatee):
96    return fullspec_cto_component(compiler,
97                           mutatee['abi'],
98                           mutatee['optimization'],
99                           mutatee['pic'])
100
101 # Returns a string containing the mutatee's compile-time options filename
102 # component for a fully specified set of build-time options
103 def fullspec_cto_component(compiler, abi, optimization, pic):
104    retval = "_%s_%s_%s_%s" % (compiler['executable'],
105                      abi,
106                      pic,
107                      optimization)
108    return retval
109
110 # Returns a string containing the link-time options component for a fully-
111 # specified set of link-time options
112 # NOTE: There are currently no link-time options specified
113 def fullspec_lto_component():
114    return ""
115
116 # Returns a string containing the link-time options component for a mutatee's
117 # filename
118 # NOTE: There are currently no link-time options specified
119 def mutatee_lto_component(mutatee):
120    return fullspec_lto_component()
121
122 # Returns a string containing the link-time options component for a mutatee's
123 # filename when the mutatee is compiled using an auxilliary compiler
124 # NOTE: I think this function is pointless
125 def auxcomp_lto_component(compiler, mutatee):
126    return fullspec_lto_component()
127
128 # Returns a string containing the build-time options component for a fully-
129 # specified set of build-time options
130 def fullspec_bto_component(compiler, abi, optimization, pic):
131    return "%s%s" % (fullspec_cto_component(compiler, abi, optimization, pic),
132                 fullspec_lto_component())
133
134 # Returns a string containing the build-time options component for a mutatee's
135 # filename
136 def mutatee_bto_component(mutatee):
137    return "%s%s" % (mutatee_cto_component(mutatee),
138                 mutatee_lto_component(mutatee))
139
140 # Returns a string containing the build-time options component for a mutatee's
141 # filename, when the mutatee is built using an auxilliary compiler
142 # NOTE: I don't think this ever happens.
143 def auxcomp_bto_component(compiler, mutatee):
144    return "%s%s" % (auxcomp_cto_component(compiler, mutatee),
145                 auxcomp_lto_component(compiler, mutatee))
146
147 def mutatee_binary(mutatee):
148    # Returns standard name for the solo mutatee binary for this mutatee
149    platform = find_platform(os.environ.get('PLATFORM'))
150    es = platform['filename_conventions']['executable_suffix']
151    format = mutatee_format(mutatee['format'])
152    return "%s.mutatee_solo%s%s%s" % (mutatee['name'], format,
153                            mutatee_bto_component(mutatee),
154                            es)
155
156 #
157 ######################################################################
158
159
160 ######################################################################
161 # make.mutators.gen
162 ######################################################################
163 #
164
165 def print_mutators_list(out, mutator_dict, test_dict):
166         platform = find_platform(os.environ.get('PLATFORM'))
167         LibSuffix = platform['filename_conventions']['library_suffix']
168         ObjSuffix = platform['filename_conventions']['object_suffix']
169
170         out.write("######################################################################\n")
171         out.write("# A list of all the mutators to be compiled\n")
172         out.write("######################################################################\n\n")
173
174         module_list = []
175         for t in test_dict:
176                 module_list.append(t['module'])
177         module_set = set(module_list)
178
179         for m in module_set:
180                 out.write("\n")
181                 out.write("%s_MUTATORS = " % (m))
182                 module_tests = filter(lambda t: m == t['module'], test_dict)
183                 module_mutators = map(lambda t: t['mutator'], module_tests)
184                 for t in uniq(module_mutators):
185                         out.write("%s " % (t))
186                 out.write("\n\n")
187                 out.write("%s_OBJS_ALL_MUTATORS = " % (m))
188                 for t in uniq(module_mutators):
189                         out.write("%s%s " % (t, ObjSuffix))
190                 out.write("\n\n")
191
192
193         # Now we'll print out a rule for each mutator..
194         for m in mutator_dict:
195                 tests = filter(lambda t: t['mutator'] == m['name'], test_dict)
196                 modules = map(lambda t: t['module'], tests)
197                 if(len(uniq(modules)) != 1):
198                          print "ERROR: multiple modules for test " + m['name']
199                          raise
200                 module = modules.pop()
201                 # FIXME Don't hardcode $(LIBTESTSUITE)
202                 out.write("%s%s: " % (m['name'], LibSuffix))
203                 # Loop through the files listed in this mutator's source list and
204                 # add object files corresponding to each to the list of dependencies
205                 try:
206                         for s in m['sources']:
207                                 # Print out the object file for this source file
208                                 out.write("%s%s " % (s[0:-len(extension(s))], ObjSuffix))
209                         out.write("$(OBJS_FORALL_MUTATORS) $(DEPENDDIR)/%s.dep $(LIBTESTSUITE) $(%s_COMPONENT_LIB)\n" % (m['name'], module))
210                 except KeyError:
211                         print "Couldn't find sources for mutator " + m['name']
212                         raise
213                 # FIXME Make this one better too.  Right now it's copied straight from
214                 # make.module.tmpl
215                 libstr = ""
216                 try:
217                         for l in m['libraries']:
218                                 libstr += ("-l%s " % l)
219                 except KeyError:
220                         print "Couldn't find libs for mutator " + m['name']
221                         raise
222                 out.write("\t$(CXX) -o $@ -shared $(filter %%%s,$^) $(%s_MUTATOR_FLAGS) $(MUTATOR_SO_LDFLAGS) $(LIBDIR) $(LIBS) $(LDFLAGS) %s\n" % (ObjSuffix, module, libstr))
223                 out.write("ifndef NO_OPT_FLAG\n")
224                 out.write("ifdef STRIP_SO\n")
225                 out.write("\t$(STRIP_SO) $@\n")
226                 out.write("endif\n")
227                 out.write("endif\n\n")
228
229         for m in module_set:
230                 rest = """
231
232 # Create shared library names from the mutator test names
233 %s_MUTATORS_SO += $(addsuffix %s,$(%s_MUTATORS))
234
235 """ % (m, LibSuffix, m)
236                 out.write(rest)
237
238        
239
240
241
242 def write_make_mutators_gen(filename, tuplefile):
243    read_tuples(tuplefile)
244    mutator_dict = info['mutators']
245    test_dict = info['tests']
246    platform = find_platform(os.environ.get('PLATFORM'))
247    LibSuffix = platform['filename_conventions']['library_suffix']
248    header = """
249 # This file is automatically generated by the Dyninst testing system.
250 # For more information, see core/testsuite/src/specification/makemake.py
251
252 """
253    out = open(filename, "w")
254    out.write(header)
255    print_mutators_list(out, mutator_dict, test_dict)
256    out.close()
257
258 #
259 ######################################################################
260
261 ######################################################################
262 # test_info_new.gen.C
263 ######################################################################
264 #
265
266 def write_test_info_new_gen(filename, tuplefile):
267    header = """/* This file automatically generated from test specifications.  See
268  * specification/spec.pl and specification/makemake.py
269  */
270
271 #include "test_info_new.h"
272
273
274 """
275    read_tuples(tuplefile)
276    compilers = info['compilers']
277    rungroups = info['rungroups']
278    out = open(filename, "w")
279    out.write(header)
280    print_initialize_mutatees(out, rungroups, compilers)
281    out.close()
282
283 # Return the name of the mutatee executable for this rungroup
284 def mutatee_filename(rungroup, compilers):
285    if rungroup['mutatee'] == 'none':
286       retval = ""
287    else:
288       compiler = compilers[rungroup['compiler']]
289       mutatee = rungroup['mutatee']
290       bto = fullspec_bto_component(compiler,
291                             rungroup['abi'],
292                             rungroup['optimization'],
293                             rungroup['pic'])
294       platform = find_platform(os.environ.get('PLATFORM'))
295       format = mutatee_format(rungroup['format'])
296       es = platform['filename_conventions']['executable_suffix']
297       retval = "%s.mutatee_solo%s%s%s" % (mutatee, format, bto, es)
298    return retval
299
300 def mutatee_format(formatSpec):
301     if formatSpec == 'staticMutatee':
302         format = '_static'
303     else:
304         format = '_dynamic'
305     return format
306
307 # Return the name of the mutator for this test
308 def test_mutator(testname):
309    testobj = filter(lambda t: t['name'] == testname, info['tests'])
310    if len(testobj) >= 1:
311       testobj = testobj[0]
312    else:
313       # TODO Handle this case better
314       testobj = None
315    if testobj != None:
316       mrname = testobj['mutator']
317    else:
318       mrname = None
319    return mrname
320
321 # Builds a text label for a test based on the run group's information
322 # FIXME This is hardcoded to set grouped to false.  It needs to be fixed to
323 # support the group mutatee optimization
324 def build_label(test, mutator, rungroup):
325    label = "{test: %s, mutator: %s, grouped: false" % (test, mutator)
326    for n in rungroup:
327       # We've already dealt with tests and we don't handle groupable yet
328       if n not in ['tests', 'groupable']:
329          label = label + ", " + n + ": " + rungroup[n]
330    label = label + "}"
331    return label
332
333
334 def print_initialize_mutatees(out, rungroups, compilers):
335         header = """
336 // Now we insert the test lists into the run groups
337 void initialize_mutatees(std::vector<RunGroup *> &tests) {
338         unsigned int group_count = 0;
339         // Keep track of which element each test is, for later use with the resumelog
340         unsigned int test_count;
341         RunGroup *rg;
342 """
343         out.write(header)
344
345         platform = find_platform(os.environ.get('PLATFORM'))
346         LibSuffix = platform['filename_conventions']['library_suffix']
347
348         # TODO Change these to get the string conversions from a tuple output
349         for group in rungroups:
350                 compiler = info['compilers'][group['compiler']]
351                 if compiler['presencevar'] != 'true':
352                         out.write("#ifdef %s\n" % (compiler['presencevar']))
353                 mutateename = mutatee_filename(group, compilers)
354                 out.write('  test_count = 0;\n')
355                 out.write('  rg = new RunGroup("%s", ' % (mutateename))
356                 if group['start_state'] == 'stopped':
357                         out.write('STOPPED, ')
358                 elif group['start_state'] == 'running':
359                         out.write('RUNNING, ')
360                 else: # Assuming 'selfstart'
361                         out.write('SELFSTART, ')
362                 if group['run_mode'] == 'createProcess':
363                         out.write('CREATE, ')
364                 elif group['run_mode'] == 'useAttach':
365                         out.write('USEATTACH, ')
366                 elif group['run_mode'] == 'deserialize':
367                         out.write('DESERIALIZE, ')
368                 else:
369                         out.write('DISK, ')
370                 if group['thread_mode'] == 'None':
371                         out.write('TNone, ')
372                 elif group['thread_mode'] == 'SingleThreaded':
373                         out.write('SingleThreaded, ')
374                 elif group['thread_mode'] == 'MultiThreaded':
375                         out.write('MultiThreaded, ')
376                 if group['process_mode'] == 'None':
377                         out.write('PNone, ')
378                 elif group['process_mode'] == 'SingleProcess':
379                         out.write('SingleProcess, ')
380                 elif group['process_mode'] == 'MultiProcess':
381                         out.write('MultiProcess, ')
382                 if group['format'] == 'staticMutatee':
383                         out.write('StaticLink, ')
384                 else:
385                         out.write('DynamicLink, ')
386                 if group['groupable'] == 'true':
387                         out.write('false, ') # !groupable
388                 else:
389                         out.write('true, ') # !groupable
390                 if group['pic'] == 'pic':
391                         out.write('PIC')
392                 else:
393                         out.write('nonPIC')
394                 try:
395                         testobj = filter(lambda t: t['name'] == group['tests'][0], info['tests'])
396                         if len(testobj) < 1:
397                                 raise TestNotFound, 'Test not found: ' + test
398                         else:
399                                 module = testobj[0]['module']
400                 except KeyError:
401                         print "No module found! Test object: " 
402                         print testobj[0]
403                         raise
404                 out.write(', "%s", "%s", "%s", "%s"' % (module, group['compiler'], group['optimization'], group['abi']))
405                 out.write(');\n')
406                 for test in group['tests']:
407                         # Set the tuple string for this test
408                         # (<test>, <mutatee compiler>, <mutatee optimization>, <create mode>)
409                         # I need to get the mutator that this test maps to..
410                         mutator = test_mutator(test)
411                         ts = build_label(test, mutator, group)
412                         if test in ['test_serializable']:
413                                 serialize_enable = 'true'
414                         else:
415                                 serialize_enable = 'false'
416                         out.write('  rg->tests.push_back(new TestInfo(test_count++, "%s", "%s", "%s%s", %s, "%s"));\n' % (test, mutator, mutator, LibSuffix, serialize_enable, ts))
417                 out.write('  rg->index = group_count++;\n')
418                 out.write('  tests.push_back(rg);\n')
419                 # Close compiler presence #ifdef
420                 if compiler['presencevar'] != 'true':
421                         out.write("#endif // defined(%s)\n" % (compiler['presencevar']))
422         out.write('}\n')
423
424 #
425 ##########
426
427 ######################################################################
428 # make.solo_mutatee.gen
429 ######################################################################
430 #
431
432 def collect_mutatee_comps(mutatees):
433    comps = []
434    for m in mutatees:
435       if m['compiler'] != '' and m['compiler'] not in comps:
436          comps.append(m['compiler'])
437    return comps
438
439 # Print makefile variable initializations for all the compilers used for
440 # makefiles on this platform
441 def print_mutatee_comp_defs(out):
442    out.write("# Define variables for our compilers, if they aren't already defined\n")
443    pname = os.environ.get('PLATFORM')
444    # TODO Check that we got a string
445    comps = filter(lambda c: c != ''
446                          and pname in info['compilers'][c]['platforms'],
447                info['compilers'])
448    for c in comps:
449       if info['compilers'][c]['presencevar'] != 'true':
450          out.write("ifdef %s\n" % (info['compilers'][c]['presencevar']))
451       out.write('M_%s ?= %s\n' % (info['compilers'][c]['defstring'], info['compilers'][c]['executable']))
452       if info['compilers'][c]['presencevar'] != 'true':
453          out.write("endif\n")
454    out.write('\n')
455
456 def get_module(mutatee):
457    return mutatee["module"]
458
459 def group_uses_module(group, module):
460    mutatee_name = group['mutatee']
461    mutatees = filter(lambda t: t['name'] == group['mutatee'], info['mutatees'])
462    return get_module(mutatees[0]) == module
463
464 def has_multiple_tests(testgroup):
465    try:
466       t = testgroup['tests']
467       return len(t) > 1
468    except TypeError:
469       print "Test group's test list was not a list"
470       print t
471       raise
472
473 def print_mutatee_rules(out, mutatees, compiler, module):
474         if(len(mutatees) == 0):
475                 return
476         mut_names = map(lambda x: mutatee_binary(x), mutatees)
477         out.write("######################################################################\n")
478         out.write("# Mutatees compiled with %s for %s\n" % (mutatees[0]['compiler'], module))
479         out.write("######################################################################\n\n")
480         if compiler['presencevar'] != 'true':
481                 out.write("ifdef %s\n" % (compiler['presencevar']))
482                 out.write("# We only want to build these targets if the compiler exists\n")
483         out.write("%s_SOLO_MUTATEES_%s = " % (module, compiler['defstring']))
484         for m in mut_names:
485                 out.write("%s " % (m))
486         out.write('\n')
487         if compiler['presencevar'] != 'true':
488                 out.write("endif\n")
489         out.write("\n")
490         out.write("# Now a list of rules for compiling the mutatees with %s\n\n"
491                           % (mutatees[0]['compiler']))
492
493         pname = os.environ.get('PLATFORM')
494         platform = find_platform(pname)
495         ObjSuffix = platform['filename_conventions']['object_suffix']
496         groups = info['rungroups']
497
498         # Write rules for building the mutatee executables from the object files
499         for (m, n) in zip(mutatees, mut_names):
500                 out.write("%s: " % (n))
501
502                 group_mutatee_list = filter(has_multiple_tests, groups)
503                 group_mutatee_list = filter(lambda g: g['mutatee'] == m['name'], group_mutatee_list)
504                 group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
505                 for bp in group_boilerplates:
506                         cto = mutatee_cto_component(m)
507                         out.write("%s " % (replace_extension(bp, "%s%s"
508                                                          % (cto, ObjSuffix))))
509
510                 for f in m['preprocessed_sources']:
511                         # List all the compiled transformed source files
512                         # I need to futz with the compiler here to make sure it's correct..
513                         # FIXME This next line may end up arbitrarily picking the first
514                         # language from a list of more than one for an extension
515                         lang = filter(lambda l: extension(f) in l['extensions'],
516                                                   info['languages'])[0]['name']
517                         if (lang in compiler['languages']):
518                                 cto = mutatee_cto_component(m)
519                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
520                                                                                                          % (cto, ObjSuffix))))
521                         else: # Preprocessed file compiled with auxilliary compiler
522                                 pname = os.environ.get('PLATFORM')
523                                 # TODO Check that we got a string..
524                                 platform = find_platform(pname)
525                                 # TODO Check that we retrieved a platform object
526                                 try:
527                                         aux_comp = platform['auxilliary_compilers'][lang]
528                                 except KeyError:
529                                         print "Working on mutatee: " + n + ", file: " + f + ", no language for " + lang + ", platform object:"
530                                         print platform
531                                         raise
532                                 # TODO Verify that we got a compiler
533                                 cto = auxcomp_cto_component(info['compilers'][aux_comp], m)
534                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
535                                                                                                          % (cto, ObjSuffix))))
536                 # TODO Let's grab the languages used in the preprocessed sources, and
537                 # save them for later.  We use this to determine which raw sources get
538                 # compiled with the same options as the preprocessed ones, in the case
539                 # of a compiler that is used for more than one language (e.g. GCC in
540                 # tests test1_35 or test_mem)
541
542                 # FIXME I'm doing this wrong: the compiler for preprocessed files might
543                 # not be the compiler that we're testing..
544                 # Get the compiler..
545                 maincomp_langs = uniq(info['compilers'][m['compiler']]['languages'])
546                 pp_langs = uniq(map(lambda x: get_file_lang(x)['name'], m['preprocessed_sources']))
547                 # So we want to print out a list of object files that go into this
548                 # mutatee.  For files that can be compiled with m['compiler'], we'll
549                 # use it, and compile at optimization level m['optimization'].  For
550                 # other files, we'll just use the appropriate compiler and not worry
551                 # about optimization levels?
552                 for f in m['raw_sources']:
553                         # Figure out whether or not this file can be compiled with
554                         # m['compiler']
555                         lang = get_file_lang(f)
556                         if type(lang) == type([]):
557                                 lang = lang[0] # BUG This may cause unexpected behavior if more
558                                                # than one language was returned, but more than
559                                                            # one language should never be returned
560                         if lang['name'] in maincomp_langs:
561                                 # This file is compiled with the main compiler for this mutatee
562                                 cto = mutatee_cto_component(m)
563                                 out.write("%s " % (replace_extension(f, "%s%s"
564                                                                                                          % (cto, ObjSuffix))))
565                         else:
566                                 # This file is compiled with an auxilliary compiler
567                                 # Find the auxilliary compiler for this language on this
568                                 # platform
569                                 # This assumes that there is only one possible auxilliary
570                                 # compiler for a language ending with the extension of interest
571                                 # on the platform.  This condition is enforced by sanity checks
572                                 # in the specification file.
573                                 aux_comp = platform['auxilliary_compilers'][lang['name']]
574                                 cto = fullspec_cto_component(info['compilers'][aux_comp],
575                                                                                          m['abi'], 'none', 'none')
576                                 out.write("%s " % (replace_extension(f, '%s%s'
577                                                                                                          % (cto, ObjSuffix))))
578                 # FIXME Check whether the current compiler compiles C files and if not
579                 # then use the aux compiler for this platform for the mutatee driver
580                 # object.
581                 if 'c' in info['compilers'][m['compiler']]['languages']:
582                         out.write("mutatee_driver_solo_%s_%s%s\n"
583                                           % (info['compilers'][m['compiler']]['executable'],
584                                                  m['abi'], ObjSuffix))
585                 else:
586                         # Get the aux compiler for C on this platform and use it
587                         aux_c = find_platform(os.environ.get('PLATFORM'))['auxilliary_compilers']['c']
588                         aux_c = info['compilers'][aux_c]['executable']
589                         out.write("mutatee_driver_solo_%s_%s%s\n"
590                                           % (aux_c, m['abi'], ObjSuffix))
591                 # Print the actions used to link the mutatee executable
592                 out.write("\t%s -o $@ $(filter %%%s,$^) %s %s"
593                                   % (platform['linker'] or "$(M_%s)" % compiler['defstring'],
594                                          ObjSuffix,
595                                          compiler['flags']['link'],
596                                          compiler['abiflags'][platform['name']][m['abi']]))
597                 if m['format'] == 'staticMutatee':
598                     linkage = compiler['staticlink']
599                 else:
600                     linkage = compiler['dynamiclink']
601                 out.write("%s " % linkage)
602                 for l in m['libraries']:
603                         # Need to include the required libraries on the command line
604                         # FIXME Use a compiler-specific command-line flag instead of '-l'
605                         out.write("-l%s" % (l))
606                         if os.environ.get('PLATFORM') == 'x86_64-unknown-linux2.4':
607                                 if m['abi'] == '32':
608                                         if l == 'testA':
609                                                 out.write('_m32')
610                         out.write(" ")
611                 out.write('\n')
612
613                 # ***ADD NEW BUILD-TIME ACTIONS HERE***
614
615
616 # Prints all the special object file compile rules for a given compiler
617 # FIXME This doesn't deal with preprocessed files!
618 def print_special_object_rules(compiler, out):
619         out.write("\n# Exceptional rules for mutatees compiled with %s\n\n"
620                           % (compiler))
621         objects = filter(lambda o: o['compiler'] == compiler, info['objects'])
622         for o in objects:
623                 # Print a rule to build this object file
624                 # TODO Convert the main source file name to an object name
625                 #  * Crap!  I don't know if this is a preprocessed file or not!
626                 #  * This should be okay soon; I'm removing the proprocessing stage..
627                 platform = os.environ.get("PLATFORM")
628                 ofileext = find_platform(platform)['filename_conventions']['object_suffix']
629                 ofilename = o['object'] + ofileext
630                 out.write("%s: " % (ofilename))
631                 for s in o['sources']:
632                         out.write("../src/%s " % (s))
633                 for i in o['intermediate_sources']:
634                         out.write("%s " % (i))
635                 for d in o['dependencies']:
636                         out.write("%s " % (d))
637                 out.write("\n")
638                 out.write("\t$(M_%s) $(SOLO_MUTATEE_DEFS) " % (info['compilers'][compiler]['defstring']))
639                 for f in o['flags']:
640                         out.write("%s " % (f))
641                 out.write("-o $@ %s " % info['compilers'][compiler]['parameters']['partial_compile'])
642                 for s in o['sources']:
643                         out.write("../src/%s " % (s))
644                 for i in o['intermediate_sources']:
645                         out.write("%s " % (i))
646                 out.write("\n")
647         out.write("\n")
648
649 # Produces a string of compiler flags for compiling mutatee object files with
650 # the specified build-time options
651 def object_flag_string(platform, compiler, abi, optimization, pic):
652    return "%s %s %s %s %s %s" % (compiler['flags']['std'],
653                         compiler['flags']['mutatee'],
654                         compiler['parameters']['partial_compile'],
655                         compiler['abiflags'][platform['name']][abi],
656                         compiler['optimization'][optimization],
657                         compiler['pic'][pic])
658
659
660 def print_patterns_wildcards(c, out, module):
661    compiler = info['compilers'][c]
662    platform = find_platform(os.environ.get('PLATFORM'))
663    ObjSuffix = platform['filename_conventions']['object_suffix']
664    
665    for abi in platform['abis']:
666       for o in compiler['optimization']:
667         for p in compiler['pic']:
668             cto = fullspec_cto_component(compiler, abi, o, p)
669             for l in compiler['languages']:
670                 lang = find_language(l) # Get language dictionary from name
671                 for e in lang['extensions']:
672                     if (module == None):
673                         out.write("%%%s%s: ../src/%%%s\n"
674                                     % (cto, ObjSuffix, e))
675                     else:
676                         out.write("%%%s%s: ../src/%s/%%%s\n"
677                                     % (cto, ObjSuffix, module, e))
678                     out.write("\t$(M_%s) $(SOLO_MUTATEE_DEFS) %s -o $@ $<\n"
679                                 % (compiler['defstring'],
680                                     object_flag_string(platform, compiler,
681                                                     abi, o, p)))
682 def is_valid_test(mutatee):
683          groups = info['rungroups']
684          mutatee_tests = filter(lambda g: g['mutatee'] == mutatee['name'], groups)
685          if not mutatee_tests:
686                   return 'false'
687          else:
688                   return 'true'
689
690 def is_groupable(mutatee):
691          if(mutatee['groupable'] == 'false'):
692                   return 'false'
693          groups = info['rungroups']
694          mutatee_tests = filter(lambda g: g['mutatee'] == mutatee['name'], groups)
695          if(max(map(lambda g: len(g['tests']), mutatee_tests)) > 1):
696                   return 'true'
697          else:
698                   return 'false'
699
700 def get_all_mutatee_sources(groupable, module):
701         return uniq(reduce(lambda a, b: set(a) | set(b),
702                 (map(lambda m: m['preprocessed_sources'],
703                 filter(lambda m: m['name'] != 'none'
704                         and is_valid_test(m) == 'true' and is_groupable(m) == groupable and get_module(m) == module,
705                         info['mutatees']))),
706                 []))
707          
708    
709 # Prints generic rules for compiling from mutatee boilerplate
710 def print_patterns(c, out, module):
711         out.write("\n# Generic rules for %s's mutatees and varying optimization levels for %s\n" % (c, module))
712
713         compiler = info['compilers'][c]
714         platform = find_platform(os.environ.get('PLATFORM'))
715         ObjSuffix = platform['filename_conventions']['object_suffix']
716
717         ng_sources = get_all_mutatee_sources('false', module)
718         g_sources = get_all_mutatee_sources('true', module)
719
720         for abi in platform['abis']:
721                 for o in compiler['optimization']:
722                     for p in compiler['pic']:
723                         # Rules for compiling source files to .o files
724                         cto = fullspec_cto_component(compiler, abi, o, p)
725
726                         #FIXME this prints out one rule for every mutatee preprocessed source for EVERY optimization
727                         #      I don't know whether the previous targets require every combination of source/opt
728                         #      i.e. printing ALL of them may be superfluous
729                         for sourcefile in ng_sources:
730                                 ext = extension(sourcefile)
731                                 boilerplate = "solo_mutatee_boilerplate" + ext
732                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
733
734                                 out.write("%s_mutatee_solo%s%s: ../src/%s ../src/%s/%s\n"
735                                                 % (basename, cto, ObjSuffix, boilerplate, module, sourcefile))
736                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -I../src/%s -DTEST_NAME=%s -DGROUPABLE=0 -DMUTATEE_SRC=../src/%s/%s -o $@ $<\n"
737                                                 % (compiler['defstring'], module,
738                                                    object_flag_string(platform, compiler, abi, o, p),
739                                                    module,
740                                                    basename, module, sourcefile))
741                         for sourcefile in g_sources:
742                                 ext = extension(sourcefile)
743                                 boilerplate = "solo_mutatee_boilerplate" + ext
744                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
745
746                                 out.write("%s_mutatee_solo%s%s: ../src/%s ../src/%s/%s\n"
747                                                 % (basename, cto, ObjSuffix, boilerplate, module, sourcefile))
748                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -I../src/%s -DTEST_NAME=%s -DGROUPABLE=1 -DMUTATEE_SRC=../src/%s/%s -o $@ $<\n"
749                                                 % (compiler['defstring'], module,
750                                                    object_flag_string(platform, compiler, abi, o, p),
751
752                                                    module,
753                                                    basename, module, sourcefile))
754         groups = info['rungroups']
755         group_mutatee_list = filter(has_multiple_tests, groups)
756         groups_for_module = filter(lambda g: group_ok_for_module(g, module) == 'true', group_mutatee_list)
757         group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', groups_for_module))
758         for abi in platform['abis']:
759                 for o in compiler['optimization']:
760                     for p in compiler['pic']:
761                         cto = fullspec_cto_component(compiler, abi, o, p)
762                         for sourcefile in group_boilerplates:
763                                     ext = extension(sourcefile)
764                                     basename = sourcefile[0:-len(ext)]
765                                     out.write("%s%s%s: %s\n" % (basename, cto, ObjSuffix, sourcefile))
766                                     out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -DGROUPABLE=1 -o $@ $<\n"
767                                                             % (compiler['defstring'], module,
768                                                                     object_flag_string(platform, compiler, abi, o, p)))
769
770         out.write("\n")
771
772
773
774 # Prints pattern rules for this platform's auxilliary compilers
775 def print_aux_patterns(out, platform, comps, module):
776         # Pattern rules for auxilliary compilers supported on this platform
777         out.write("\n# Generic rules for this platform's auxilliary compilers\n\n")
778         aux_comps = platform['auxilliary_compilers']
779         for ac_lang in aux_comps:
780                 compname = aux_comps[ac_lang]
781                 comp = info['compilers'][compname]
782                 # Print pattern rule(s) for this compiler
783                 # ac should be a map from a language to a compiler..
784                 lang = filter(lambda l: l['name'] == ac_lang, info['languages'])[0]
785                 for ext in lang['extensions']:
786                         for abi in platform['abis']:
787                                 for o in comp['optimization']:
788                                     for p in comp['pic']:
789                                         cto = fullspec_cto_component(comp, abi, o, p)
790                                         out.write("%%%s%s: ../src/%%%s\n"
791                                                           % (cto,
792                                                                  platform['filename_conventions']['object_suffix'],
793                                                                  ext))
794                                         # FIXME Make this read the parameter flags from the
795                                         # compiler tuple (output file parameter flag)
796                                         out.write("\t$(M_%s) %s -o $@ $<\n\n"
797                                                           % (comp['defstring'],
798                                                                  object_flag_string(platform, comp, abi, o, p)))
799
800                                         if (module != None):
801                                                  out.write("%%%s%s: ../src/%s/%%%s\n"
802                                                                           % (cto, platform['filename_conventions']['object_suffix'],
803                                                                                   module, ext))
804                                         else:
805                                                  out.write("%%%s%s: ../src/%%%s\n"
806                                                                           % (cto, platform['filename_conventions']['object_suffix'],
807                                                                                   ext))
808                                         # FIXME Make this read the parameter flags from the
809                                         # compiler tuple (output file parameter flag)
810                                         out.write("\t$(M_%s) %s -o $@ $<\n\n"
811                                                           % (comp['defstring'],
812                                                                  object_flag_string(platform, comp, abi, o, p)))
813
814
815 # Prints the footer for make.solo_mutatee.gen
816 def print_make_solo_mutatee_gen_footer(out, comps, platform, module):
817    compilers = info['compilers']
818    out.write("# And a rule to build all of the mutatees\n")
819    out.write(".PHONY: %s_solo_mutatees\n" % (module))
820    out.write("%s_solo_mutatees: " % (module))
821    for c in comps:
822       out.write("$(%sSOLO_MUTATEES_%s) " % (module, compilers[c]['defstring']))
823    out.write("\n\n")
824    out.write(".PHONY: clean_solo_mutatees\n")
825    out.write("%s_clean_solo_mutatees:\n" % (module))
826    for c in comps:
827       out.write("\t-$(RM) $(%s_SOLO_MUTATEES_%s)\n"
828               % (module, compilers[c]['defstring']))
829    # Get a list of optimization levels we're using and delete the mutatee
830    # objects for each of them individually
831    objExt = platform['filename_conventions']['object_suffix']
832    # FIXME Get the actual list of optimization levels we support
833    for o in ['none', 'low', 'high', 'max']:
834       out.write("\t-$(RM) *_%s%s\n" % (o, objExt))
835    out.write("\n\n")
836    out.write("%s_SOLO_MUTATEES =" % (module))
837    for c in comps:
838       out.write(" $(%s_SOLO_MUTATEES_%s)" % (module, compilers[c]['defstring']))
839    out.write("\n\n")
840
841    out.write("### COMPILER_CONTROL_DEFS is used to determine which compilers are present\n")
842    out.write("### when compiling the list of mutatees to test against\n")
843    out.write("COMPILER_CONTROL_DEFS =\n")
844    for c in comps:
845       if info['compilers'][c]['presencevar'] != 'true':
846          out.write("ifdef %s # Is %s present?\n" % (info['compilers'][c]['presencevar'], c))
847          out.write("COMPILER_CONTROL_DEFS += -D%s\n" % (info['compilers'][c]['presencevar']))
848          out.write("endif\n")
849    out.write('\n')
850
851 def format_test_info(test):
852    line = '  {"' + test + '", ' + test + '_mutatee, GROUPED, "' + test + '"}'
853    return line
854
855 def format_test_defines(test):
856    line = 'extern int ' + test + '_mutatee();\n'
857    return line
858
859 def write_group_mutatee_boilerplate_file(filename, tests):
860    out = open(filename, "w")
861    out.write("#ifdef __cplusplus\n")
862    out.write('extern "C" {\n')
863    out.write("#endif\n")
864    out.write('#include "../src/mutatee_call_info.h"\n\n')
865    map(lambda t: out.write(format_test_defines(t)), tests)
866    out.write("\n")
867    out.write("mutatee_call_info_t mutatee_funcs[] = {\n")
868    out.write(reduce(lambda s, t: s + ',\n' + t, map(format_test_info, tests)))
869    out.write("\n")
870    out.write("};\n")
871    out.write("\n")
872    out.write("int max_tests = %d;\n" % (len(tests)))
873    out.write("int runTest[%d];\n" % (len(tests)))
874    out.write("int passedTest[%d];\n" % (len(tests)))
875    out.write("#ifdef __cplusplus\n")
876    out.write("}\n")
877    out.write("#endif\n")
878    out.close()
879
880
881 def accumulate_tests_by_mutatee(acc, g):
882    if g['mutatee'] in acc:
883       acc[g['mutatee']] = acc[g['mutatee']] | set(g['tests']);
884    else:
885       acc.update([(g['mutatee'], set(g['tests']))])
886    return acc
887
888
889 def write_group_mutatee_boilerplate(filename_pre, filename_post, tuplefile):
890    read_tuples(tuplefile)
891    groups = filter(lambda g: len(g['tests']) > 25, info['rungroups'])
892    tests_by_group = reduce(accumulate_tests_by_mutatee, groups, {})
893    for mutatee, tests in tests_by_group.iteritems():
894       write_group_mutatee_boilerplate_file(filename_pre + mutatee + filename_post, tests)
895
896
897 # Main function for generating make.solo_mutatee.gen
898 def write_make_solo_mutatee_gen(filename, tuplefile):
899         read_tuples(tuplefile)
900         compilers = info['compilers']
901         mutatees = info['mutatees']
902         out = open(filename, "w")
903         print_mutatee_comp_defs(out)
904         comps = collect_mutatee_comps(mutatees)
905         pname = os.environ.get('PLATFORM')
906         platform = find_platform(pname)
907         ObjSuffix = platform['filename_conventions']['object_suffix']
908         modules = uniq(map(lambda t: t['module'], info['tests']))
909         for c in comps:
910                 # Generate a block of rules for mutatees produced by each compiler
911                 for m in modules:
912                         muts = filter(lambda x: x['compiler'] == c and is_valid_test(x) == 'true' and get_module(x) == m, mutatees)
913                         if(len(muts) != 0):
914                                 print_mutatee_rules(out, muts, compilers[c], m)
915                 # Print rules for exceptional object files
916                 print_special_object_rules(c, out)
917
918                 for m in modules:
919                         print_patterns(c, out, m)
920                         print_patterns_wildcards(c, out, m)
921                 print_patterns_wildcards(c, out, None)
922
923                 out.write("# Rules for building the driver and utility objects\n")
924                 # TODO Replace this code generation with language neutral code
925                 # generation
926                 if 'c' in info['compilers'][c]['languages']:
927                         for abi in platform['abis']:
928                                 out.write("mutatee_driver_solo_%s_%s%s: ../src/mutatee_driver.c\n" % (info['compilers'][c]['executable'], abi, ObjSuffix))
929                                 out.write("\t$(M_%s) %s %s %s -o $@ -c $<\n"
930                                                   % (compilers[c]['defstring'],
931                                                          compilers[c]['flags']['std'],
932                                                          compilers[c]['flags']['mutatee'],
933                                                          compilers[c]['abiflags'][platform['name']][abi]))
934                                 out.write("mutatee_util_%s_%s%s: ../src/mutatee_util.c\n"
935                                                   % (info['compilers'][c]['executable'],
936                                                          abi, ObjSuffix))
937                                 out.write("\t$(M_%s) %s %s %s -o $@ -c $<\n\n"
938                                                   % (compilers[c]['defstring'],
939                                                          compilers[c]['flags']['std'],
940                                                          compilers[c]['flags']['mutatee'],
941                                                          compilers[c]['abiflags'][platform['name']][abi]))
942                 else:
943                         out.write("# (Skipped: driver and utility objects cannot be compiled with this compiler\n")
944
945         # Print pattern rules for this platform's auxilliary compilers
946
947         for m in modules:
948                 print_aux_patterns(out, platform, comps, m)
949         print_aux_patterns(out, platform, comps, None)
950         # Print footer (list of targets, clean rules, compiler presence #defines)
951         for m in modules:
952                 print_make_solo_mutatee_gen_footer(out, comps, platform, m)
953
954
955         out.close()
956
957 #
958 ##########
959
960 # --------------------------------------------------------
961 # --------------------------------------------------------
962 # BEGIN NT SPECIFIC PROCEDURES
963 # --------------------------------------------------------
964 # --------------------------------------------------------
965
966 # Return the name of the mutatee executable for this rungroup
967 # (Based on compiler name, NOT compiler executable name
968 def mutatee_filename_nt(rungroup, compilers):
969         if rungroup['mutatee'] == 'none':
970                 retval = ""
971         else:
972                 compiler = compilers[rungroup['compiler']]
973                 mutatee = rungroup['mutatee']
974                 bto = fullspec_cto_component_nt(compiler,
975                                                                          rungroup['abi'],
976                                                                          rungroup['optimization'])
977                 platform = find_platform(os.environ.get('PLATFORM'))
978                 es = platform['filename_conventions']['executable_suffix']
979                 retval = "%s_mutatee_solo%s%s" % (mutatee, bto, es)
980         return retval
981
982
983
984 # These functions are duplicated because the compiler NAME, not executable name,
985 # needs to be used for windows, since the exec. name is the same for both c and c++
986 def mutatee_cto_component_nt(mutatee):
987    compiler = info['compilers'][mutatee['compiler']]
988    return fullspec_cto_component_nt(compiler,
989                           mutatee['abi'],
990                           mutatee['optimization'])
991
992 def auxcomp_cto_component_nt(compiler, mutatee):
993    return fullspec_cto_component_nt(compiler,
994                           mutatee['abi'],
995                           mutatee['optimization'])
996
997 def fullspec_cto_component_nt(compiler, abi, optimization):
998    def reverse_lookup(dict, value):
999       for key in dict:
1000          if dict[key] == value:
1001             return key
1002       raise ValueError
1003
1004    retval = "_%s_%s_%s" % (reverse_lookup(info['compilers'], compiler),
1005                      abi,
1006                      optimization)
1007    return retval
1008
1009 def mutatee_binary_nt(mutatee):
1010         # Returns standard name for the solo mutatee binary for this mutatee
1011         # (for windows)
1012         platform = find_platform(os.environ.get('PLATFORM'))
1013         es = platform['filename_conventions']['executable_suffix']
1014         return "%s_mutatee_solo%s%s" % (mutatee['name'],
1015                 mutatee_cto_component_nt(mutatee),
1016                 es)
1017
1018
1019 def group_ok_for_module(g, m):
1020         tests_in_group = filter(lambda t: t['mutatee'] == g['mutatee'], info['tests'])
1021         if(filter(lambda t: m == t['module'], tests_in_group) == []):
1022                 return 'false'
1023         else:
1024                 return 'true'
1025
1026 #TODO this function has literally one line differnet from the non _nt version.
1027 #     merge?
1028 def write_test_info_new_gen_nt(filename, tuplefile):
1029         header = """/* This file automatically generated from test specifications.  See
1030  * specification/spec.pl and specification/makemake.py
1031  */
1032
1033 #include "test_info_new.h"
1034 """
1035         read_tuples(tuplefile)
1036         compilers = info['compilers']
1037         rungroups = info['rungroups']
1038         out = open(filename, "w")
1039         out.write(header)
1040         modules = uniq(map(lambda t: t['module'], info['tests']))
1041         for m in modules:
1042                 out.write("void initialize_mutatees_%s(std::vector<RunGroup *> &tests);\n" % m)
1043         out.write("void initialize_mutatees(std::vector<RunGroup *> &tests) {")
1044         for m in modules:
1045                 out.write("  initialize_mutatees_%s(tests);" % m)
1046         out.write("}")
1047         for m in modules:
1048                 print_initialize_mutatees_nt(out, filter(lambda g: group_ok_for_module(g, m) == 'true', rungroups), compilers, m)
1049         out.close()
1050
1051 def test_ok_for_module(test, module):
1052         tests = info['tests']
1053         if(len(filter (lambda t: t['name'] == test and t['module'] == module, tests)) > 0):
1054                 return 'true'
1055         return 'false'
1056
1057 def print_initialize_mutatees_nt(out, rungroups, compilers, module):
1058 # in visual studio 2003, exceeding 1920 'exception states' causes the compiler to crash.
1059 # from what I can tell, each instantation of an object creates an 'exception case,' so
1060 # the workaround is to instantiate dynamically
1061         header = """
1062 // Now we insert the test lists into the run groups
1063 void initialize_mutatees_%s(std::vector<RunGroup *> &tests) {
1064         unsigned int group_count = 0;
1065         // Keep track of which element each test is, for later use with the resumelog
1066         unsigned int test_count;
1067         RunGroup *rg;
1068 """ % module
1069         out.write(header)
1070         platform = find_platform(os.environ.get('PLATFORM'))
1071         LibSuffix = platform['filename_conventions']['library_suffix']
1072
1073         rungroup_params = []
1074         test_params = []
1075         tests = info['tests']
1076         # TODO Change these to get the string conversions from a tuple output
1077         for group in rungroups:
1078                 compiler = info['compilers'][group['compiler']]
1079                 if compiler['presencevar'] == 'true':
1080                         presencevar = 'true'
1081                 else:
1082                         presencevar = 'false'
1083                 mutatee_name = mutatee_filename_nt(group, compilers)
1084                 if group['start_state'] == 'stopped':
1085                         state_init = 'STOPPED'
1086                 elif group['start_state'] == 'running':
1087                         state_init = 'RUNNING'
1088                 else: # Assuming 'selfstart'
1089                         state_init = 'SELFSTART'
1090                 if group['run_mode'] == 'createProcess':
1091                         attach_init = 'CREATE'
1092                 else: # Assuming 'useAttach'
1093                         attach_init = 'USEATTACH'
1094                 if group['groupable'] == 'true':
1095                         ex = 'false'
1096                 else:
1097                         ex = 'true'
1098                 if group['pic'] == 'pic':
1099                         pic = 'PIC'
1100                 else:
1101                         pic = 'nonPIC'
1102
1103                 group_empty = 'true'
1104                 for test in group['tests']:
1105                         if(test_ok_for_module(test, module) == 'false'):
1106                                 continue
1107                         group_empty = 'false'
1108                         # Set the tuple string for this test
1109                         # (<test>, <mutatee compiler>, <mutatee optimization>, <create mode>)
1110                         # I need to get the mutator that this test maps to..
1111                         mutator = test_mutator(test)
1112                         ts = build_label(test, mutator, group)
1113                         if test in ['test_serializable']:
1114                                 serialize_enable = 'true'
1115                         else:
1116                                 serialize_enable = 'false'
1117                         test_params.append({'test': test, 'mutator': mutator, 'LibSuffix': LibSuffix, 'serialize_enable' : serialize_enable, 'ts': ts, 'endrungroup': 'false'})
1118                 test_params[-1]['endrungroup'] = 'true'
1119                 if(group_empty == 'false'):
1120                         rungroup_params.append({'presencevar': presencevar, 'mutatee_name': mutatee_name, 'state_init': state_init, 
1121                                 'attach_init': attach_init, 'ex': ex, 'compiler': group['compiler'], 'optimization': group['optimization'],
1122                                 'abi': group['abi'], 'pic': pic})
1123
1124         body = """struct {
1125
1126     char * mutatee_name;
1127     start_state_t state_init;
1128     create_mode_t attach_init;
1129     bool ex;
1130     bool presencevar;
1131     char* module;
1132     char* compiler;
1133     char* optimization;
1134     char* abi;
1135     test_pictype_t pic;
1136   } rungroup_params[] = {"""
1137         out.write(body)
1138
1139         out.write(' {"%s", %s, %s, %s, %s, "%s", "%s", "%s", "%s", %s}' % (rungroup_params[0]['mutatee_name'], \
1140                 rungroup_params[0]['state_init'], rungroup_params[0]['attach_init'], rungroup_params[0]['ex'], \
1141                 rungroup_params[0]['presencevar'], module, rungroup_params[0]['compiler'], \
1142                 rungroup_params[0]['optimization'], rungroup_params[0]['abi'], rungroup_params[0]['pic']))
1143         for i in range(1, len(rungroup_params)):
1144                 out.write(',\n {"%s", %s, %s, %s, %s, "%s", "%s", "%s", "%s", %s}' % (rungroup_params[i]['mutatee_name'], \
1145                         rungroup_params[i]['state_init'], rungroup_params[i]['attach_init'], rungroup_params[i]['ex'], \
1146                         rungroup_params[i]['presencevar'], module, rungroup_params[i]['compiler'], \
1147                         rungroup_params[i]['optimization'], rungroup_params[i]['abi'], rungroup_params[i]['pic']))
1148         body = """ };
1149
1150   struct {
1151     bool endrungroup;
1152     const char * iname;
1153     const char * mrname;
1154     const char * isoname;
1155         bool serialize_enable;
1156     const char * ilabel;
1157   } test_params[] = {"""
1158
1159         out.write(body)
1160
1161         out.write(' {%s, "%s", "%s", "%s%s", %s, "%s"}' % (test_params[0]['endrungroup'], test_params[0]['test'], test_params[0]['mutator'], test_params[0]['mutator'], test_params[0]['LibSuffix'], test_params[i]['serialize_enable'], test_params[0]['ts']))
1162         for i in range(1, len(test_params)):
1163                 out.write(',\n {%s, "%s", "%s", "%s%s", %s, "%s"}' % (test_params[i]['endrungroup'], test_params[i]['test'], test_params[i]['mutator'], test_params[i]['mutator'], test_params[i]['LibSuffix'], test_params[i]['serialize_enable'], test_params[i]['ts']))
1164
1165 #TODO presencevar
1166         body = """ };
1167
1168   int tp_index = -1;
1169   for (int i = 0; i < %d; i++) {
1170     test_count = 0;
1171     rg = new RunGroup(rungroup_params[i].mutatee_name, rungroup_params[i].state_init, rungroup_params[i].attach_init, 
1172                         rungroup_params[i].ex, rungroup_params[i].pic, rungroup_params[i].module, rungroup_params[i].compiler,
1173                         rungroup_params[i].optimization, rungroup_params[i].abi);
1174     
1175     do {
1176       tp_index++;
1177       rg->tests.push_back(new TestInfo(test_count++, test_params[tp_index].iname, test_params[tp_index].mrname, test_params[tp_index].isoname, test_params[tp_index].serialize_enable, test_params[tp_index].ilabel));
1178     } while (tp_index < %d && test_params[tp_index].endrungroup == false);
1179
1180     rg->index = group_count++;
1181     tests.push_back(rg);
1182   }
1183 }
1184 """
1185
1186         out.write(body % (len(rungroup_params), len(test_params)))
1187
1188 # ----------------------------
1189 # nmake.mutators.gen (windows)
1190 # ----------------------------
1191 def print_mutators_list_nt(out, mutator_dict, test_dict):
1192         platform = find_platform(os.environ.get('PLATFORM'))
1193         LibSuffix = platform['filename_conventions']['library_suffix']
1194         ObjSuffix = platform['filename_conventions']['object_suffix']
1195         module_list = []
1196         for t in test_dict:
1197                 module_list.append(t['module'])
1198         module_set = set(module_list)
1199
1200         out.write("######################################################################\n")
1201         out.write("# A list of all the mutators to be compiled\n")
1202         out.write("######################################################################\n\n")
1203         mutator_string = "mutators:"
1204         for mod in module_set:  
1205                 module_tests = filter(lambda t: mod == t['module'], test_dict)
1206                 out.write("%s_MUTATORS = " % (mod))
1207                 mutator_string = "%s $(%s_MUTATORS_SO)" % (mutator_string, mod)
1208                 for t in module_tests:
1209                         out.write("%s " % (t['mutator']))
1210                 out.write("\n\n")
1211                 out.write("%s_MUTATORS_SO = " % (mod))
1212                 for t in module_tests:
1213                         out.write("%s%s " % (t['mutator'], LibSuffix))
1214                 out.write("\n\n")
1215                 out.write("%s_OBJS_ALL_MUTATORS = " % (mod))
1216                 for t in module_tests:
1217                         out.write("%s%s " % (t['mutator'], ObjSuffix))
1218                 out.write("\n\n")
1219         out.write("%s\n\n" % mutator_string)
1220
1221         # Now we'll print out a rule for each mutator..
1222         for mod in module_set:
1223                 module_tests = filter(lambda t: t['module'] == mod, test_dict)
1224                 module_mutators = map(lambda t: t['mutator'], module_tests)
1225                 mutators_for_module = filter(lambda m: m['name'] in module_mutators, mutator_dict)
1226                 for m in mutators_for_module:
1227                         # FIXME Don't hardcode $(LIBTESTSUITE)
1228                         out.write("%s%s: " % (m['name'], LibSuffix))
1229                         # Loop through the files listed in this mutator's source list and
1230                         # add object files corresponding to each to the list of dependencies
1231                         objs = []
1232                         sourcefiles = []
1233                         for s in m['sources']:
1234                                 # Print out the object file for this source file
1235                                 objs.append('%s%s' % (s[0:-len(extension(s))], ObjSuffix))
1236                                 sourcefiles.append('../src/%s/%s' % (mod, s))
1237                                 # TODO proper dependencies
1238                                 out.write("%s $(LIBTESTSUITE)\n" % (reduce(lambda x, y: x + " " + y, objs)))
1239                                 # FIXME Make this one better too.  Right now it's copied straight from
1240                                 # make.module.tmpl
1241                                 out.write("\t$(LINK) $(LDFLAGS) -DLL -out:$@ %s $(MUTATOR_LIBS)\n\n" % (reduce(lambda x, y: x + " " + y, objs)))
1242                         for s, o in zip(sourcefiles, objs):
1243                                 out.write("%s: %s\n" % (o, s))
1244                                 out.write("\t$(CXX) $(CXXFLAGS_NORM) -DDLL_BUILD -c -Fo$@ $**\n\n")
1245
1246
1247
1248 def write_make_mutators_gen_nt(filename, tuplefile):
1249         read_tuples(tuplefile)
1250         mutator_dict = info['mutators']
1251         test_dict = info['tests']
1252         platform = find_platform(os.environ.get('PLATFORM'))
1253         LibSuffix = platform['filename_conventions']['library_suffix']
1254         header = """
1255 # This file is automatically generated by the Dyninst testing system.
1256 # For more information, see core/testsuite/src/specification/makemake.py
1257
1258 """
1259
1260         out = open(filename, "w")
1261         out.write(header)
1262         print_mutators_list_nt(out, mutator_dict, test_dict)
1263         out.close()
1264
1265 # --------------------------------
1266 # --------------------------------
1267 # nmake.solo_mutatee.gen (windows)
1268 # --------------------------------
1269 # --------------------------------
1270
1271 # Print makefile variable initializations for all the compilers used for
1272 # makefiles on this platform
1273 def print_mutatee_comp_defs_nt(out):
1274    out.write("# Define variables for our compilers\n")
1275    pname = os.environ.get('PLATFORM')
1276    # TODO Check that we got a string
1277    comps = filter(lambda c: c != ''
1278                          and pname in info['compilers'][c]['platforms'],
1279                info['compilers'])
1280    for c in comps:
1281       if info['compilers'][c]['presencevar'] != 'true':
1282          out.write("!ifdef %s\n" % (info['compilers'][c]['presencevar']))
1283       out.write('M_%s = %s\n' % (info['compilers'][c]['defstring'], info['compilers'][c]['executable']))
1284       if info['compilers'][c]['presencevar'] != 'true':
1285          out.write("!endif\n")
1286    out.write('\n')
1287
1288 def print_mutatee_rules_nt(out, mutatees, compiler, unique_target_dict, module):
1289         mutatees_for_module = filter(lambda x: get_module(x) == module, mutatees)
1290         mut_names = map(lambda x: mutatee_binary_nt(x), mutatees_for_module)
1291
1292         out.write("######################################################################\n")
1293         out.write("# Mutatees compiled with %s for %s\n" % (mutatees[0]['compiler'], module))
1294         out.write("######################################################################\n\n")
1295         if compiler['presencevar'] != 'true':
1296                 out.write("!ifdef %s\n" % (compiler['presencevar']))
1297                 out.write("# We only want to build these targets if the compiler exists\n")
1298         out.write("%s_SOLO_MUTATEES_%s = " % (module, compiler['defstring']))
1299         for m in mut_names:
1300                 out.write("%s " % (m))
1301         out.write('\n')
1302         if compiler['presencevar'] != 'true':
1303                 out.write("!endif\n")
1304         out.write("\n")
1305         out.write("# Now a list of rules for compiling the mutatees with %s\n\n"
1306                           % (mutatees[0]['compiler']))
1307
1308         pname = os.environ.get('PLATFORM')
1309         platform = find_platform(pname)
1310         ObjSuffix = platform['filename_conventions']['object_suffix']
1311
1312         # this variable is used to keep track of dependency targets. this must
1313         # be done for windows because nmake doesn't have % wildcard support.
1314         # note: this excludes a mutattee's ['preprocessed_sources'][0], since
1315         # this is a special case accounted for in print_patterns_nt
1316         dependency_sources = {}
1317
1318         groups = info['rungroups']
1319
1320         # Write rules for building the mutatee executables from the object files
1321         for (m, n) in zip(mutatees_for_module, mut_names):
1322                 out.write("%s: " % (n))
1323
1324                 group_mutatee_list = filter(has_multiple_tests, groups)
1325                 group_mutatee_list = filter(lambda g: g['mutatee'] == m['name'], group_mutatee_list)
1326                 group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
1327                 for bp in group_boilerplates:
1328                         cto = mutatee_cto_component_nt(m)
1329                         out.write("%s " % (replace_extension(bp, "%s%s"
1330                                                          % (cto, ObjSuffix))))
1331
1332                 for f in m['preprocessed_sources']:
1333                         # List all the compiled transformed source files
1334                         # I need to futz with the compiler here to make sure it's correct..
1335                         # FIXME This next line may end up arbitrarily picking the first
1336                         # language from a list of more than one for an extension
1337                         lang = filter(lambda l: extension(f) in l['extensions'],
1338                                                   info['languages'])[0]['name']
1339                         if (lang in compiler['languages']):
1340                                 cto = mutatee_cto_component_nt(m)
1341                                 pps_name = replace_extension(f, "_solo%s%s"
1342                                                                                                         % (cto, ObjSuffix))
1343                                 out.write("%s " % (pps_name))
1344                                 # only add unique elements to the sources dictionary,
1345                                 # and don't add the first one, since it's rule is printed
1346                                 # in print_patterns_nt
1347 #                               if f != m['preprocessed_sources'][0]:
1348                                         # only insert this if it hasn't been accounted for in a
1349                                         # previous invocation of this procedure
1350 #                               try:
1351 #                                       unique_target_dict[pps_name]
1352 #                               except KeyError:
1353 #                                       # only insert it if it's not already in the list
1354 #                                       try:
1355 #                                               dependency_sources[pps_name]
1356 #                                       except KeyError:
1357 #                                               dependency_sources[pps_name] = {'src': f, 'abi': m['abi'],
1358 #                                                       'optimization': m['optimization'], 'suffix': ObjSuffix, 'compiler': compiler}
1359                         else: # Preprocessed file compiled with auxilliary compiler
1360                                 pname = os.environ.get('PLATFORM')
1361                                 # TODO Check that we got a string..
1362                                 platform = find_platform(pname)
1363                                 # TODO Check that we retrieved a platform object
1364                                 aux_comp = platform['auxilliary_compilers'][lang]
1365                                 # TODO Verify that we got a compiler
1366                                 cto = auxcomp_cto_component_nt(info['compilers'][aux_comp], m)
1367                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
1368                                                                                                          % (cto, ObjSuffix))))
1369                                 # TODO
1370                                 # the same try/except block can be duplicated as above, but
1371                                 # I don't think windows ever has preprocessed files compiled
1372                                 # with auxilliary compiler. if it does though, the script
1373                                 # will die here
1374                                 makeshift_die
1375                 # TODO Let's grab the languages used in the preprocessed sources, and
1376                 # save them for later.  We use this to determine which raw sources get
1377                 # compiled with the same options as the preprocessed ones, in the case
1378                 # of a compiler that is used for more than one language (e.g. GCC in
1379                 # tests test1_35 or test_mem)
1380
1381                 # FIXME I'm doing this wrong: the compiler for preprocessed files might
1382                 # not be the compiler that we're testing..
1383                 # Get the compiler..
1384                 maincomp_langs = uniq(info['compilers'][m['compiler']]['languages'])
1385                 pp_langs = uniq(map(lambda x: get_file_lang(x)['name'], m['preprocessed_sources']))
1386                 # So we want to print out a list of object files that go into this
1387                 # mutatee.  For files that can be compiled with m['compiler'], we'll
1388                 # use it, and compile at optimization level m['optimization'].  For
1389                 # other files, we'll just use the appropriate compiler and not worry
1390                 # about optimization levels?
1391                 for f in m['raw_sources']:
1392                         # Figure out whether or not this file can be compiled with
1393                         # m['compiler']
1394                         lang = get_file_lang(f)
1395                         if type(lang) == type([]):
1396                                 lang = lang[0] # BUG This may cause unexpected behavior if more
1397                                                # than one language was returned, but more than
1398                                                            # one language should never be returned
1399                         if lang['name'] in maincomp_langs:
1400                                 # This file is compiled with the main compiler for this mutatee
1401                                 cto = mutatee_cto_component_nt(m)
1402                                 comp = compiler
1403                                 opt = m['optimization']
1404                                 rs_name = replace_extension(f, "%s%s"
1405                                                                                                         % (cto, ObjSuffix))
1406                         else:
1407                                 # This file is compiled with an auxilliary compiler
1408                                 # Find the auxilliary compiler for this language on this
1409                                 # platform
1410                                 # This assumes that there is only one possible auxilliary
1411                                 # compiler for a language ending with the extension of interest
1412                                 # on the platform.  This condition is enforced by sanity checks
1413                                 # in the specification file.
1414                                 aux_comp = platform['auxilliary_compilers'][lang['name']]
1415                                 comp = info['compilers'][aux_comp]
1416                                 opt = 'none'
1417                                 cto = fullspec_cto_component_nt(info['compilers'][aux_comp],
1418                                                                                          m['abi'], 'none')
1419                                 rs_name = replace_extension(f, '%s%s'
1420                                                                                                         % (cto, ObjSuffix))
1421                         out.write("%s " % (rs_name))
1422
1423                         # only insert if it hasn't been accounted for in a previous
1424                         # invocation of this function
1425                         try:
1426                                 unique_target_dict[rs_name]
1427                         except KeyError:
1428                                 try:
1429                                         dependency_sources[rs_name]
1430                                 except KeyError:
1431                                         dependency_sources[rs_name] = {'src': f, 'abi': m['abi'],
1432                                                         'optimization': opt, 'suffix': ObjSuffix, 'compiler': comp,
1433                                                         'groupable': m['groupable'], 'pic': 'none'}
1434                 # FIXME Check whether the current compiler compiles C files and if not
1435                 # then use the aux compiler for this platform for the mutatee driver
1436                 # object.
1437                 if 'c' in info['compilers'][m['compiler']]['languages']:
1438                         out.write("mutatee_driver_solo_%s_%s_%s%s\n"
1439                                           % (m['compiler'],
1440                                                  m['abi'], m['optimization'], ObjSuffix))
1441                 else:
1442                         # Get the aux compiler for C on this platform and use it
1443                         aux_c = find_platform(os.environ.get('PLATFORM'))['auxilliary_compilers']['c']
1444                         aux_c = info['compilers'][aux_c]['executable']
1445                         out.write("mutatee_driver_solo_%s_%s_%s%s\n"
1446                                           % (aux_c, m['abi'], m['optimization'], ObjSuffix))
1447                 # Print the actions used to link the mutatee executable
1448                 out.write("\t%s %s -out:$@ $** %s "
1449                                   % (platform['linker'] or "$(M_%s)" % compiler['defstring'],
1450                                          compiler['flags']['link'],
1451                                          compiler['abiflags'][platform['name']][m['abi']]))
1452                 # TODO: libraries
1453                 #for l in m['libraries']:
1454                 # Need to include the required libraries on the command line
1455                 # FIXME Use a compiler-specific command-line flag instead of '-l'
1456                 #       out.write("-l%s " % (l))
1457                 out.write('\n')
1458
1459                 # ***ADD NEW BUILD-TIME ACTIONS HERE***
1460
1461         # now write the individual preprocessed source targets
1462         for object, options in dependency_sources.iteritems():
1463                 ObjSuffix = options['suffix']
1464                 src = options['src']
1465                 abi = options['abi']
1466                 o = options['optimization']
1467                 comp = options['compiler']
1468                 pic = options['pic']
1469
1470                 if src.startswith("mutatee_util"):
1471                         out.write("%s: ../src/%s\n" % (object, src))
1472                 else:
1473                         out.write("%s: ../src/%s/%s\n" % (object, module, src))
1474                 # FIXME -Dsnprintf=_snprintf is needed for c files that contain snprintf,
1475                 #       but not for .asm files. the masm compiler accepts the -D parameter,
1476                 #       but it's unnecessary
1477                 out.write("\t$(M_%s) %s -Dsnprintf=_snprintf -Fo$@ $**\n"
1478                                         % (comp['defstring'], object_flag_string(platform, comp, abi, o, pic)))
1479
1480                 # now add the object to the unique target list. this prevents the same
1481                 # target from being specified in a different invocation of this function
1482                 unique_target_dict[object] = 1
1483
1484
1485 # Prints generic rules for compiling from mutatee boilerplate
1486 def print_patterns_nt(c, out, module):
1487         out.write("\n# Generic rules for %s's mutatees and varying optimization levels\n" % (c))
1488
1489         compiler = info['compilers'][c]
1490         platform = find_platform(os.environ.get('PLATFORM'))
1491         ObjSuffix = platform['filename_conventions']['object_suffix']
1492
1493         
1494         ng_sources = get_all_mutatee_sources('false', module)
1495
1496         g_sources = get_all_mutatee_sources('true', module)
1497
1498         groups = filter(lambda g: group_ok_for_module(g, module) == 'true', info['rungroups'])
1499         group_mutatee_list = filter(has_multiple_tests, groups)
1500         group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
1501         for abi in platform['abis']:
1502                 for o in compiler['optimization']:
1503                         # Rules for compiling source files to .o files
1504                         cto = fullspec_cto_component_nt(compiler, abi, o)
1505
1506                         #FIXME this prints out one rule for every mutatee preprocessed source for EVERY optimization
1507                         #      I don't know whether the previous targets require every combination of source/opt
1508                         #      i.e. printing ALL of them may be superfluous
1509                         for sourcefile in ng_sources:
1510                                 ext = extension(sourcefile)
1511                                 boilerplate = "solo_mutatee_boilerplate" + ext
1512                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
1513
1514                                 out.write("%s_mutatee_solo%s%s: ../src/%s\n"
1515                                                 % (basename, cto, ObjSuffix, boilerplate))
1516                                 out.write("\t$(M_%s) %s -DTEST_NAME=%s -DGROUPABLE=0 -DMUTATEE_SRC=../src/%s/%s -Fo$@ $**\n"
1517                                                 % (compiler['defstring'],
1518                                                    object_flag_string(platform, compiler, abi, o, "none"),
1519                                                    basename, module, sourcefile))
1520
1521                         for sourcefile in g_sources:
1522                                 ext = extension(sourcefile)
1523                                 boilerplate = "solo_mutatee_boilerplate" + ext
1524                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
1525
1526                                 out.write("%s_mutatee_solo%s%s: ../src/%s\n"
1527                                                 % (basename, cto, ObjSuffix, boilerplate))
1528                                 out.write("\t$(M_%s) %s -DTEST_NAME=%s -DGROUPABLE=1 -DMUTATEE_SRC=../src/%s/%s -Fo$@ $**\n"
1529                                                 % (compiler['defstring'],
1530                                                    object_flag_string(platform, compiler, abi, o, "none"),
1531                                                    basename, module, sourcefile))
1532
1533
1534                         for sourcefile in group_boilerplates:
1535                                 ext = extension(sourcefile)
1536                                 basename = sourcefile[0:-len(ext)]
1537                                 out.write("%s%s%s: ../%s/%s\n" % (basename, cto, ObjSuffix, os.environ.get('PLATFORM'), sourcefile))
1538                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -DGROUPABLE=1 -Fo$@ $**\n" 
1539                                         % (compiler['defstring'], module, 
1540                                         object_flag_string(platform, compiler, abi, o, "none")))
1541                         for l in compiler['languages']: 
1542                                 lang = find_language(l) # Get language dictionary from name
1543                                 for e in lang['extensions']:
1544                                         # FIXME This generates spurious lines for compilers that
1545                                         # aren't used for this part of the mutatee build system
1546                                         # like .s and .S files for gcc and Fortran files.
1547                                         out.write("%%%s%s: {../src/%s/}%%%s\n"
1548                                                           % (cto, ObjSuffix, module, e))
1549                                         out.write("\t$(M_%s) %s -Fo$@ $**\n"
1550                                                 % (compiler['defstring'], object_flag_string(platform, compiler, abi, o, "none")))
1551         out.write("\n")
1552
1553 # Main function for generating nmake.solo_mutatee.gen
1554 def write_make_solo_mutatee_gen_nt(filename, tuplefile):
1555         read_tuples(tuplefile)
1556         compilers = info['compilers']
1557         mutatees = info['mutatees']
1558         out = open(filename, "w")
1559         print_mutatee_comp_defs_nt(out)
1560         # vvvvv This one isn't nt specific vvvvv
1561         comps = collect_mutatee_comps(mutatees)
1562         pname = os.environ.get('PLATFORM')
1563         platform = find_platform(pname)
1564         ObjSuffix = platform['filename_conventions']['object_suffix']
1565         unique_target_dict = {}
1566         modules = uniq(map(lambda t: t['module'], info['tests']))
1567         for c in comps:
1568                 # Generate a block of rules for mutatees produced by each compiler
1569                 muts = filter(lambda x: x['compiler'] == c, mutatees)
1570                 for m in modules:
1571                         print_mutatee_rules_nt(out, muts, compilers[c], unique_target_dict, m)
1572                 # Print rules for exceptional object files
1573                 # TODO: don't know if this needs to be done for windows
1574                 #print_special_object_rules(c, out)
1575 # TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
1576                 for m in modules:
1577                         print_patterns_nt(c, out, m)
1578                 out.write("# Rules for building the driver and utility objects\n")
1579                 # TODO Replace this code generation with language neutral code
1580                 # generation
1581                 if 'c' in info['compilers'][c]['languages']:
1582                         for abi in platform['abis']:
1583                                 for (opt_level, opt_flag) in compilers[c]['optimization'].items():
1584                                         out.write("mutatee_driver_solo_%s_%s_%s%s: ../src/mutatee_driver.c\n" % (c, abi, opt_level, ObjSuffix))
1585                                         out.write("\t$(M_%s) %s %s %s %s -Dsnprintf=_snprintf -Fo$@ -c $**\n"
1586                                                           % (compilers[c]['defstring'],
1587                                                                  compilers[c]['flags']['std'],
1588                                                                  compilers[c]['flags']['mutatee'],
1589                                                                  opt_flag,
1590                                                                  compilers[c]['abiflags'][platform['name']][abi]))
1591                                         # TODO: find where these files live in our data structures
1592                                         # and remove the hardcoding!
1593
1594                 else:
1595                         out.write("# (Skipped: driver and utility objects cannot be compiled with this compiler\n")
1596
1597         # Print pattern rules for this platform's auxilliary compilers
1598         #print_aux_patterns(out, platform, comps)
1599
1600         # Print footer (list of targets, clean rules, compiler presence #defines)
1601         for m in modules:
1602                 print_make_solo_mutatee_gen_footer(out, comps, platform, m)
1603         out.write("mutatees: ");
1604         for m in modules:
1605                 out.write("$(%s_SOLO_MUTATEES) " %(m));
1606         out.write("\n");
1607         out.close()