Suggest including <stdint.h> or <cstdint> for [u]int[8|16|32|64]_t
[gcc.git] / contrib / update-copyright.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2013-2020 Free Software Foundation, Inc.
4 #
5 # This script is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3, or (at your option)
8 # any later version.
9
10 # This script adjusts the copyright notices at the top of source files
11 # so that they have the form:
12 #
13 # Copyright XXXX-YYYY Free Software Foundation, Inc.
14 #
15 # It doesn't change code that is known to be maintained elsewhere or
16 # that carries a non-FSF copyright.
17 #
18 # The script also doesn't change testsuite files, except those in
19 # libstdc++-v3. This is because libstdc++-v3 has a conformance testsuite,
20 # while most tests in other directories are just things that failed at some
21 # point in the past.
22 #
23 # Pass --this-year to the script if you want it to add the current year
24 # to all applicable notices. Pass --quilt if you are using quilt and
25 # want files to be added to the quilt before being changed.
26 #
27 # By default the script will update all directories for which the
28 # output has been vetted. You can instead pass the names of individual
29 # directories, including those that haven't been approved. So:
30 #
31 # update-copyright.py --this-year
32 #
33 # is the command that would be used at the beginning of a year to update
34 # all copyright notices (and possibly at other times to check whether
35 # new files have been added with old years). On the other hand:
36 #
37 # update-copyright.py --this-year libitm
38 #
39 # would run the script on just libitm/.
40 #
41 # Note that things like --version output strings must be updated before
42 # this script is run. There's already a separate procedure for that.
43
44 import os
45 import re
46 import sys
47 import time
48 import subprocess
49
50 class Errors:
51 def __init__ (self):
52 self.num_errors = 0
53
54 def report (self, filename, string):
55 if filename:
56 string = filename + ': ' + string
57 sys.stderr.write (string + '\n')
58 self.num_errors += 1
59
60 def ok (self):
61 return self.num_errors == 0
62
63 class GenericFilter:
64 def __init__ (self):
65 self.skip_files = set()
66 self.skip_dirs = set()
67 self.skip_extensions = set()
68 self.fossilised_files = set()
69 self.own_files = set()
70
71 self.skip_files |= set ([
72 # Skip licence files.
73 'COPYING',
74 'COPYING.LIB',
75 'COPYING3',
76 'COPYING3.LIB',
77 'LICENSE',
78 'LICENSE.txt',
79 'fdl.texi',
80 'gpl_v3.texi',
81 'fdl-1.3.xml',
82 'gpl-3.0.xml',
83
84 # Skip auto- and libtool-related files
85 'aclocal.m4',
86 'compile',
87 'config.guess',
88 'config.sub',
89 'depcomp',
90 'install-sh',
91 'libtool.m4',
92 'ltmain.sh',
93 'ltoptions.m4',
94 'ltsugar.m4',
95 'ltversion.m4',
96 'lt~obsolete.m4',
97 'missing',
98 'mkdep',
99 'mkinstalldirs',
100 'move-if-change',
101 'shlibpath.m4',
102 'symlink-tree',
103 'ylwrap',
104
105 # Skip FSF mission statement, etc.
106 'gnu.texi',
107 'funding.texi',
108 'appendix_free.xml',
109
110 # Skip imported texinfo files.
111 'texinfo.tex',
112 ])
113
114
115 def get_line_filter (self, dir, filename):
116 if filename.startswith ('ChangeLog'):
117 # Ignore references to copyright in changelog entries.
118 return re.compile ('\t')
119
120 return None
121
122 def skip_file (self, dir, filename):
123 if filename in self.skip_files:
124 return True
125
126 (base, extension) = os.path.splitext (os.path.join (dir, filename))
127 if extension in self.skip_extensions:
128 return True
129
130 if extension == '.in':
131 # Skip .in files produced by automake.
132 if os.path.exists (base + '.am'):
133 return True
134
135 # Skip files produced by autogen
136 if (os.path.exists (base + '.def')
137 and os.path.exists (base + '.tpl')):
138 return True
139
140 # Skip configure files produced by autoconf
141 if filename == 'configure':
142 if os.path.exists (base + '.ac'):
143 return True
144 if os.path.exists (base + '.in'):
145 return True
146
147 return False
148
149 def skip_dir (self, dir, subdir):
150 return subdir in self.skip_dirs
151
152 def is_fossilised_file (self, dir, filename):
153 if filename in self.fossilised_files:
154 return True
155 # Only touch current current ChangeLogs.
156 if filename != 'ChangeLog' and filename.find ('ChangeLog') >= 0:
157 return True
158 return False
159
160 def by_package_author (self, dir, filename):
161 return filename in self.own_files
162
163 class Copyright:
164 def __init__ (self, errors):
165 self.errors = errors
166
167 # Characters in a range of years. Include '.' for typos.
168 ranges = '[0-9](?:[-0-9.,\s]|\s+and\s+)*[0-9]'
169
170 # Non-whitespace characters in a copyright holder's name.
171 name = '[\w.,-]'
172
173 # Matches one year.
174 self.year_re = re.compile ('[0-9]+')
175
176 # Matches part of a year or copyright holder.
177 self.continuation_re = re.compile (ranges + '|' + name)
178
179 # Matches a full copyright notice:
180 self.copyright_re = re.compile (
181 # 1: 'Copyright (C)', etc.
182 '([Cc]opyright'
183 '|[Cc]opyright\s+\([Cc]\)'
184 '|[Cc]opyright\s+%s'
185 '|[Cc]opyright\s+&copy;'
186 '|[Cc]opyright\s+@copyright{}'
187 '|copyright = u\''
188 '|@set\s+copyright[\w-]+)'
189
190 # 2: the years. Include the whitespace in the year, so that
191 # we can remove any excess.
192 '(\s*(?:' + ranges + ',?'
193 '|@value\{[^{}]*\})\s*)'
194
195 # 3: 'by ', if used
196 '(by\s+)?'
197
198 # 4: the copyright holder. Don't allow multiple consecutive
199 # spaces, so that right-margin gloss doesn't get caught
200 # (e.g. gnat_ugn.texi).
201 '(' + name + '(?:\s?' + name + ')*)?')
202
203 # A regexp for notices that might have slipped by. Just matching
204 # 'copyright' is too noisy, and 'copyright.*[0-9]' falls foul of
205 # HTML header markers, so check for 'copyright' and two digits.
206 self.other_copyright_re = re.compile ('copyright.*[0-9][0-9]',
207 re.IGNORECASE)
208 self.comment_re = re.compile('#+|[*]+|;+|%+|//+|@c |dnl ')
209 self.holders = { '@copying': '@copying' }
210 self.holder_prefixes = set()
211
212 # True to 'quilt add' files before changing them.
213 self.use_quilt = False
214
215 # If set, force all notices to include this year.
216 self.max_year = None
217
218 # Goes after the year(s). Could be ', '.
219 self.separator = ' '
220
221 def add_package_author (self, holder, canon_form = None):
222 if not canon_form:
223 canon_form = holder
224 self.holders[holder] = canon_form
225 index = holder.find (' ')
226 while index >= 0:
227 self.holder_prefixes.add (holder[:index])
228 index = holder.find (' ', index + 1)
229
230 def add_external_author (self, holder):
231 self.holders[holder] = None
232
233 class BadYear():
234 def __init__ (self, year):
235 self.year = year
236
237 def __str__ (self):
238 return 'unrecognised year: ' + self.year
239
240 def parse_year (self, string):
241 year = int (string)
242 if len (string) == 2:
243 if year > 70:
244 return year + 1900
245 elif len (string) == 4:
246 return year
247 raise self.BadYear (string)
248
249 def year_range (self, years):
250 year_list = [self.parse_year (year)
251 for year in self.year_re.findall (years)]
252 assert len (year_list) > 0
253 return (min (year_list), max (year_list))
254
255 def set_use_quilt (self, use_quilt):
256 self.use_quilt = use_quilt
257
258 def include_year (self, year):
259 assert not self.max_year
260 self.max_year = year
261
262 def canonicalise_years (self, dir, filename, filter, years):
263 # Leave texinfo variables alone.
264 if years.startswith ('@value'):
265 return years
266
267 (min_year, max_year) = self.year_range (years)
268
269 # Update the upper bound, if enabled.
270 if self.max_year and not filter.is_fossilised_file (dir, filename):
271 max_year = max (max_year, self.max_year)
272
273 # Use a range.
274 if min_year == max_year:
275 return '%d' % min_year
276 else:
277 return '%d-%d' % (min_year, max_year)
278
279 def strip_continuation (self, line):
280 line = line.lstrip()
281 match = self.comment_re.match (line)
282 if match:
283 line = line[match.end():].lstrip()
284 return line
285
286 def is_complete (self, match):
287 holder = match.group (4)
288 return (holder
289 and (holder not in self.holder_prefixes
290 or holder in self.holders))
291
292 def update_copyright (self, dir, filename, filter, file, line, match):
293 orig_line = line
294 next_line = None
295 pathname = os.path.join (dir, filename)
296
297 intro = match.group (1)
298 if intro.startswith ('@set'):
299 # Texinfo year variables should always be on one line
300 after_years = line[match.end (2):].strip()
301 if after_years != '':
302 self.errors.report (pathname,
303 'trailing characters in @set: '
304 + after_years)
305 return (False, orig_line, next_line)
306 else:
307 # If it looks like the copyright is incomplete, add the next line.
308 while not self.is_complete (match):
309 try:
310 next_line = file.next()
311 except StopIteration:
312 break
313
314 # If the next line doesn't look like a proper continuation,
315 # assume that what we've got is complete.
316 continuation = self.strip_continuation (next_line)
317 if not self.continuation_re.match (continuation):
318 break
319
320 # Merge the lines for matching purposes.
321 orig_line += next_line
322 line = line.rstrip() + ' ' + continuation
323 next_line = None
324
325 # Rematch with the longer line, at the original position.
326 match = self.copyright_re.match (line, match.start())
327 assert match
328
329 holder = match.group (4)
330
331 # Use the filter to test cases where markup is getting in the way.
332 if filter.by_package_author (dir, filename):
333 assert holder not in self.holders
334
335 elif not holder:
336 self.errors.report (pathname, 'missing copyright holder')
337 return (False, orig_line, next_line)
338
339 elif holder not in self.holders:
340 self.errors.report (pathname,
341 'unrecognised copyright holder: ' + holder)
342 return (False, orig_line, next_line)
343
344 else:
345 # See whether the copyright is associated with the package
346 # author.
347 canon_form = self.holders[holder]
348 if not canon_form:
349 return (False, orig_line, next_line)
350
351 # Make sure the author is given in a consistent way.
352 line = (line[:match.start (4)]
353 + canon_form
354 + line[match.end (4):])
355
356 # Remove any 'by'
357 line = line[:match.start (3)] + line[match.end (3):]
358
359 # Update the copyright years.
360 years = match.group (2).strip()
361 try:
362 canon_form = self.canonicalise_years (dir, filename, filter, years)
363 except self.BadYear as e:
364 self.errors.report (pathname, str (e))
365 return (False, orig_line, next_line)
366
367 line = (line[:match.start (2)]
368 + ('' if intro.startswith ('copyright = ') else ' ')
369 + canon_form + self.separator
370 + line[match.end (2):])
371
372 # Use the standard (C) form.
373 if intro.endswith ('right'):
374 intro += ' (C)'
375 elif intro.endswith ('(c)'):
376 intro = intro[:-3] + '(C)'
377 line = line[:match.start (1)] + intro + line[match.end (1):]
378
379 # Strip trailing whitespace
380 line = line.rstrip() + '\n'
381
382 return (line != orig_line, line, next_line)
383
384 def process_file (self, dir, filename, filter):
385 pathname = os.path.join (dir, filename)
386 if filename.endswith ('.tmp'):
387 # Looks like something we tried to create before.
388 try:
389 os.remove (pathname)
390 except OSError:
391 pass
392 return
393
394 lines = []
395 changed = False
396 line_filter = filter.get_line_filter (dir, filename)
397 mode = None
398 with open (pathname, 'r') as file:
399 prev = None
400 mode = os.fstat (file.fileno()).st_mode
401 for line in file:
402 while line:
403 next_line = None
404 # Leave filtered-out lines alone.
405 if not (line_filter and line_filter.match (line)):
406 match = self.copyright_re.search (line)
407 if match:
408 res = self.update_copyright (dir, filename, filter,
409 file, line, match)
410 (this_changed, line, next_line) = res
411 changed = changed or this_changed
412
413 # Check for copyright lines that might have slipped by.
414 elif self.other_copyright_re.search (line):
415 self.errors.report (pathname,
416 'unrecognised copyright: %s'
417 % line.strip())
418 lines.append (line)
419 line = next_line
420
421 # If something changed, write the new file out.
422 if changed and self.errors.ok():
423 tmp_pathname = pathname + '.tmp'
424 with open (tmp_pathname, 'w') as file:
425 for line in lines:
426 file.write (line)
427 os.fchmod (file.fileno(), mode)
428 if self.use_quilt:
429 subprocess.call (['quilt', 'add', pathname])
430 os.rename (tmp_pathname, pathname)
431
432 def process_tree (self, tree, filter):
433 for (dir, subdirs, filenames) in os.walk (tree):
434 # Don't recurse through directories that should be skipped.
435 for i in xrange (len (subdirs) - 1, -1, -1):
436 if filter.skip_dir (dir, subdirs[i]):
437 del subdirs[i]
438
439 # Handle the files in this directory.
440 for filename in filenames:
441 if filter.skip_file (dir, filename):
442 sys.stdout.write ('Skipping %s\n'
443 % os.path.join (dir, filename))
444 else:
445 self.process_file (dir, filename, filter)
446
447 class CmdLine:
448 def __init__ (self, copyright = Copyright):
449 self.errors = Errors()
450 self.copyright = copyright (self.errors)
451 self.dirs = []
452 self.default_dirs = []
453 self.chosen_dirs = []
454 self.option_handlers = dict()
455 self.option_help = []
456
457 self.add_option ('--help', 'Print this help', self.o_help)
458 self.add_option ('--quilt', '"quilt add" files before changing them',
459 self.o_quilt)
460 self.add_option ('--this-year', 'Add the current year to every notice',
461 self.o_this_year)
462
463 def add_option (self, name, help, handler):
464 self.option_help.append ((name, help))
465 self.option_handlers[name] = handler
466
467 def add_dir (self, dir, filter = GenericFilter()):
468 self.dirs.append ((dir, filter))
469
470 def o_help (self, option = None):
471 sys.stdout.write ('Usage: %s [options] dir1 dir2...\n\n'
472 'Options:\n' % sys.argv[0])
473 format = '%-15s %s\n'
474 for (what, help) in self.option_help:
475 sys.stdout.write (format % (what, help))
476 sys.stdout.write ('\nDirectories:\n')
477
478 format = '%-25s'
479 i = 0
480 for (dir, filter) in self.dirs:
481 i += 1
482 if i % 3 == 0 or i == len (self.dirs):
483 sys.stdout.write (dir + '\n')
484 else:
485 sys.stdout.write (format % dir)
486 sys.exit (0)
487
488 def o_quilt (self, option):
489 self.copyright.set_use_quilt (True)
490
491 def o_this_year (self, option):
492 self.copyright.include_year (time.localtime().tm_year)
493
494 def main (self):
495 for arg in sys.argv[1:]:
496 if arg[:1] != '-':
497 self.chosen_dirs.append (arg)
498 elif arg in self.option_handlers:
499 self.option_handlers[arg] (arg)
500 else:
501 self.errors.report (None, 'unrecognised option: ' + arg)
502 if self.errors.ok():
503 if len (self.chosen_dirs) == 0:
504 self.chosen_dirs = self.default_dirs
505 if len (self.chosen_dirs) == 0:
506 self.o_help()
507 else:
508 for chosen_dir in self.chosen_dirs:
509 canon_dir = os.path.join (chosen_dir, '')
510 count = 0
511 for (dir, filter) in self.dirs:
512 if (dir + os.sep).startswith (canon_dir):
513 count += 1
514 self.copyright.process_tree (dir, filter)
515 if count == 0:
516 self.errors.report (None, 'unrecognised directory: '
517 + chosen_dir)
518 sys.exit (0 if self.errors.ok() else 1)
519
520 #----------------------------------------------------------------------------
521
522 class TopLevelFilter (GenericFilter):
523 def skip_dir (self, dir, subdir):
524 return True
525
526 class ConfigFilter (GenericFilter):
527 def __init__ (self):
528 GenericFilter.__init__ (self)
529
530 def skip_file (self, dir, filename):
531 if filename.endswith ('.m4'):
532 pathname = os.path.join (dir, filename)
533 with open (pathname) as file:
534 # Skip files imported from gettext.
535 if file.readline().find ('gettext-') >= 0:
536 return True
537 return GenericFilter.skip_file (self, dir, filename)
538
539 class GCCFilter (GenericFilter):
540 def __init__ (self):
541 GenericFilter.__init__ (self)
542
543 self.skip_files |= set ([
544 # Not part of GCC
545 'math-68881.h',
546 ])
547
548 self.skip_dirs |= set ([
549 # Better not create a merge nightmare for the GNAT folks.
550 'ada',
551
552 # Handled separately.
553 'testsuite',
554 ])
555
556 self.skip_extensions |= set ([
557 # Maintained by the translation project.
558 '.po',
559
560 # Automatically-generated.
561 '.pot',
562 ])
563
564 self.fossilised_files |= set ([
565 # Old news won't be updated.
566 'ONEWS',
567 ])
568
569 class TestsuiteFilter (GenericFilter):
570 def __init__ (self):
571 GenericFilter.__init__ (self)
572
573 self.skip_extensions |= set ([
574 # Don't change the tests, which could be woend by anyone.
575 '.c',
576 '.C',
577 '.cc',
578 '.d',
579 '.h',
580 '.hs',
581 '.f',
582 '.f90',
583 '.go',
584 '.inc',
585 '.java',
586 ])
587
588 def skip_file (self, dir, filename):
589 # g++.niklas/README contains historical copyright information
590 # and isn't updated.
591 if filename == 'README' and os.path.basename (dir) == 'g++.niklas':
592 return True
593 # Similarly params/README.
594 if filename == 'README' and os.path.basename (dir) == 'params':
595 return True
596 if filename == 'pdt_5.f03' and os.path.basename (dir) == 'gfortran.dg':
597 return True
598 return GenericFilter.skip_file (self, dir, filename)
599
600 class LibCppFilter (GenericFilter):
601 def __init__ (self):
602 GenericFilter.__init__ (self)
603
604 self.skip_extensions |= set ([
605 # Maintained by the translation project.
606 '.po',
607
608 # Automatically-generated.
609 '.pot',
610 ])
611
612 class LibGCCFilter (GenericFilter):
613 def __init__ (self):
614 GenericFilter.__init__ (self)
615
616 self.skip_dirs |= set ([
617 # Imported from GLIBC.
618 'soft-fp',
619 ])
620
621 class LibPhobosFilter (GenericFilter):
622 def __init__ (self):
623 GenericFilter.__init__ (self)
624
625 self.skip_files |= set ([
626 # Source module imported from upstream.
627 'object.d',
628 ])
629
630 self.skip_dirs |= set ([
631 # Contains sources imported from upstream.
632 'core',
633 'etc',
634 'gc',
635 'gcstub',
636 'rt',
637 'std',
638 ])
639
640 class LibStdCxxFilter (GenericFilter):
641 def __init__ (self):
642 GenericFilter.__init__ (self)
643
644 self.skip_files |= set ([
645 # Contains no copyright of its own, but quotes the GPL.
646 'intro.xml',
647 ])
648
649 self.skip_dirs |= set ([
650 # Contains automatically-generated sources.
651 'html',
652
653 # The testsuite data files shouldn't be changed.
654 'data',
655
656 # Contains imported images
657 'images',
658 ])
659
660 self.own_files |= set ([
661 # Contains markup around the copyright owner.
662 'spine.xml',
663 ])
664
665 def get_line_filter (self, dir, filename):
666 if filename == 'boost_concept_check.h':
667 return re.compile ('// \(C\) Copyright Jeremy Siek')
668 return GenericFilter.get_line_filter (self, dir, filename)
669
670 class GCCCopyright (Copyright):
671 def __init__ (self, errors):
672 Copyright.__init__ (self, errors)
673
674 canon_fsf = 'Free Software Foundation, Inc.'
675 self.add_package_author ('Free Software Foundation', canon_fsf)
676 self.add_package_author ('Free Software Foundation.', canon_fsf)
677 self.add_package_author ('Free Software Foundation Inc.', canon_fsf)
678 self.add_package_author ('Free Software Foundation, Inc', canon_fsf)
679 self.add_package_author ('Free Software Foundation, Inc.', canon_fsf)
680 self.add_package_author ('The Free Software Foundation', canon_fsf)
681 self.add_package_author ('The Free Software Foundation, Inc.', canon_fsf)
682 self.add_package_author ('Software Foundation, Inc.', canon_fsf)
683
684 self.add_external_author ('ARM')
685 self.add_external_author ('AdaCore')
686 self.add_external_author ('Ami Tavory and Vladimir Dreizin, IBM-HRL.')
687 self.add_external_author ('Cavium Networks.')
688 self.add_external_author ('Faraday Technology Corp.')
689 self.add_external_author ('Florida State University')
690 self.add_external_author ('Gerard Jungman')
691 self.add_external_author ('Greg Colvin and Beman Dawes.')
692 self.add_external_author ('Hewlett-Packard Company')
693 self.add_external_author ('Intel Corporation')
694 self.add_external_author ('Information Technology Industry Council.')
695 self.add_external_author ('James Theiler, Brian Gough')
696 self.add_external_author ('Makoto Matsumoto and Takuji Nishimura,')
697 self.add_external_author ('Mentor Graphics Corporation')
698 self.add_external_author ('National Research Council of Canada.')
699 self.add_external_author ('NVIDIA Corporation')
700 self.add_external_author ('Peter Dimov and Multi Media Ltd.')
701 self.add_external_author ('Peter Dimov')
702 self.add_external_author ('Pipeline Associates, Inc.')
703 self.add_external_author ('Regents of the University of California.')
704 self.add_external_author ('Silicon Graphics Computer Systems, Inc.')
705 self.add_external_author ('Silicon Graphics')
706 self.add_external_author ('Stephen L. Moshier')
707 self.add_external_author ('Sun Microsystems, Inc. All rights reserved.')
708 self.add_external_author ('The D Language Foundation, All Rights Reserved')
709 self.add_external_author ('The Go Authors. All rights reserved.')
710 self.add_external_author ('The Go Authors. All rights reserved.')
711 self.add_external_author ('The Go Authors.')
712 self.add_external_author ('The Regents of the University of California.')
713 self.add_external_author ('Unicode, Inc.')
714 self.add_external_author ('University of Toronto.')
715 self.add_external_author ('Yoshinori Sato')
716
717 class GCCCmdLine (CmdLine):
718 def __init__ (self):
719 CmdLine.__init__ (self, GCCCopyright)
720
721 self.add_dir ('.', TopLevelFilter())
722 # boehm-gc is imported from upstream.
723 self.add_dir ('config', ConfigFilter())
724 # contrib isn't really part of GCC.
725 self.add_dir ('fixincludes')
726 self.add_dir ('gcc', GCCFilter())
727 self.add_dir (os.path.join ('gcc', 'testsuite'), TestsuiteFilter())
728 self.add_dir ('gnattools')
729 self.add_dir ('gotools')
730 self.add_dir ('include')
731 # intl is imported from upstream.
732 self.add_dir ('libada')
733 self.add_dir ('libatomic')
734 self.add_dir ('libbacktrace')
735 self.add_dir ('libcc1')
736 self.add_dir ('libcpp', LibCppFilter())
737 self.add_dir ('libdecnumber')
738 # libffi is imported from upstream.
739 self.add_dir ('libgcc', LibGCCFilter())
740 self.add_dir ('libgfortran')
741 # libgo is imported from upstream.
742 self.add_dir ('libgomp')
743 self.add_dir ('libhsail-rt')
744 self.add_dir ('libiberty')
745 self.add_dir ('libitm')
746 self.add_dir ('libobjc')
747 # liboffloadmic is imported from upstream.
748 self.add_dir ('libphobos', LibPhobosFilter())
749 self.add_dir ('libquadmath')
750 # libsanitizer is imported from upstream.
751 self.add_dir ('libssp')
752 self.add_dir ('libstdc++-v3', LibStdCxxFilter())
753 self.add_dir ('libvtv')
754 self.add_dir ('lto-plugin')
755 # maintainer-scripts maintainer-scripts
756 # zlib is imported from upstream.
757
758 self.default_dirs = [
759 'gcc',
760 'include',
761 'libada',
762 'libatomic',
763 'libbacktrace',
764 'libcc1',
765 'libcpp',
766 'libdecnumber',
767 'libgcc',
768 'libgfortran',
769 'libgomp',
770 'libhsail-rt',
771 'libiberty',
772 'libitm',
773 'libobjc',
774 'libphobos',
775 'libssp',
776 'libstdc++-v3',
777 'libvtv',
778 'lto-plugin',
779 ]
780
781 GCCCmdLine().main()