update-copyright.py 27 KB

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