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