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