GDB (API)
/home/stan/gdb/src/gdb/copyright.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 
00003 # Copyright (C) 2011-2013 Free Software Foundation, Inc.
00004 #
00005 # This file is part of GDB.
00006 #
00007 # This program is free software; you can redistribute it and/or modify
00008 # it under the terms of the GNU General Public License as published by
00009 # the Free Software Foundation; either version 3 of the License, or
00010 # (at your option) any later version.
00011 #
00012 # This program is distributed in the hope that it will be useful,
00013 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 # GNU General Public License for more details.
00016 #
00017 # You should have received a copy of the GNU General Public License
00018 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020 """copyright.py
00021 
00022 This script updates the list of years in the copyright notices in
00023 most files maintained by the GDB project.
00024 
00025 Usage: cd src/gdb && python copyright.py
00026 
00027 Always review the output of this script before committing it!
00028 A useful command to review the output is:
00029     % filterdiff -x \*.c -x \*.cc -x \*.h -x \*.exp updates.diff
00030 This removes the bulk of the changes which are most likely to be correct.
00031 """
00032 
00033 import datetime
00034 import os
00035 import os.path
00036 import subprocess
00037 
00038 
00039 def get_update_list():
00040     """Return the list of files to update.
00041 
00042     Assumes that the current working directory when called is the root
00043     of the GDB source tree (NOT the gdb/ subdirectory!).  The names of
00044     the files are relative to that root directory.
00045     """
00046     result = []
00047     for gdb_dir in ('gdb', 'sim', 'include/gdb'):
00048         for root, dirs, files in os.walk(gdb_dir, topdown=True):
00049             for dirname in dirs:
00050                 reldirname = "%s/%s" % (root, dirname)
00051                 if (dirname in EXCLUDE_ALL_LIST
00052                     or reldirname in EXCLUDE_LIST
00053                     or reldirname in NOT_FSF_LIST
00054                     or reldirname in BY_HAND):
00055                     # Prune this directory from our search list.
00056                     dirs.remove(dirname)
00057             for filename in files:
00058                 relpath = "%s/%s" % (root, filename)
00059                 if (filename in EXCLUDE_ALL_LIST
00060                     or relpath in EXCLUDE_LIST
00061                     or relpath in NOT_FSF_LIST
00062                     or relpath in BY_HAND):
00063                     # Ignore this file.
00064                     pass
00065                 else:
00066                     result.append(relpath)
00067     return result
00068 
00069 
00070 def update_files(update_list):
00071     """Update the copyright header of the files in the given list.
00072 
00073     We use gnulib's update-copyright script for that.
00074     """
00075     # We want to use year intervals in the copyright notices, and
00076     # all years should be collapsed to one single year interval,
00077     # even if there are "holes" in the list of years found in the
00078     # original copyright notice (OK'ed by the FSF, case [gnu.org #719834]).
00079     os.environ['UPDATE_COPYRIGHT_USE_INTERVALS'] = '2'
00080 
00081     # Perform the update, and save the output in a string.
00082     update_cmd = ['bash', 'gdb/gnulib/import/extra/update-copyright']
00083     update_cmd += update_list
00084 
00085     p = subprocess.Popen(update_cmd, stdout=subprocess.PIPE,
00086                          stderr=subprocess.STDOUT)
00087     update_out = p.communicate()[0]
00088 
00089     # Process the output.  Typically, a lot of files do not have
00090     # a copyright notice :-(.  The update-copyright script prints
00091     # a well defined warning when it did not find the copyright notice.
00092     # For each of those, do a sanity check and see if they may in fact
00093     # have one.  For the files that are found not to have one, we filter
00094     # the line out from the output, since there is nothing more to do,
00095     # short of looking at each file and seeing which notice is appropriate.
00096     # Too much work! (~4,000 files listed as of 2012-01-03).
00097     update_out = update_out.splitlines()
00098     warning_string = ': warning: copyright statement not found'
00099     warning_len = len(warning_string)
00100 
00101     for line in update_out:
00102         if line.endswith('\n'):
00103             line = line[:-1]
00104         if line.endswith(warning_string):
00105             filename = line[:-warning_len]
00106             if may_have_copyright_notice(filename):
00107                 print line
00108         else:
00109             # Unrecognized file format. !?!
00110             print "*** " + line
00111 
00112 
00113 def may_have_copyright_notice(filename):
00114     """Check that the given file does not seem to have a copyright notice.
00115 
00116     The filename is relative to the root directory.
00117     This function assumes that the current working directory is that root
00118     directory.
00119 
00120     The algorigthm is fairly crude, meaning that it might return
00121     some false positives.  I do not think it will return any false
00122     negatives...  We might improve this function to handle more
00123     complex cases later...
00124     """
00125     # For now, it may have a copyright notice if we find the word
00126     # "Copyright" at the (reasonable) start of the given file, say
00127     # 50 lines...
00128     MAX_LINES = 50
00129 
00130     fd = open(filename)
00131 
00132     lineno = 1
00133     for line in fd:
00134         if 'Copyright' in line:
00135             return True
00136         lineno += 1
00137         if lineno > 50:
00138             return False
00139     return False
00140 
00141 
00142 def main ():
00143     """The main subprogram."""
00144     if not os.path.isfile("gnulib/import/extra/update-copyright"):
00145         print "Error: This script must be called from the gdb directory."
00146     root_dir = os.path.dirname(os.getcwd())
00147     os.chdir(root_dir)
00148 
00149     update_list = get_update_list()
00150     update_files (update_list)
00151 
00152     # Remind the user that some files need to be updated by HAND...
00153     if BY_HAND:
00154         print
00155         print "\033[31mREMINDER: The following files must be updated by hand." \
00156               "\033[0m"
00157         for filename in BY_HAND + MULTIPLE_COPYRIGHT_HEADERS:
00158             print "  ", filename
00159 
00160 ############################################################################
00161 #
00162 # Some constants, placed at the end because they take up a lot of room.
00163 # The actual value of these constants is not significant to the understanding
00164 # of the script.
00165 #
00166 ############################################################################
00167 
00168 # Files which should not be modified, either because they are
00169 # generated, non-FSF, or otherwise special (e.g. license text,
00170 # or test cases which must be sensitive to line numbering).
00171 #
00172 # Filenames are relative to the root directory.
00173 EXCLUDE_LIST = (
00174     'gdb/common/glibc_thread_db.h',
00175     'gdb/CONTRIBUTE',
00176     'gdb/gnulib/import'
00177 )
00178 
00179 # Files which should not be modified, either because they are
00180 # generated, non-FSF, or otherwise special (e.g. license text,
00181 # or test cases which must be sensitive to line numbering).
00182 #
00183 # Matches any file or directory name anywhere.  Use with caution.
00184 # This is mostly for files that can be found in multiple directories.
00185 # Eg: We want all files named COPYING to be left untouched.
00186 
00187 EXCLUDE_ALL_LIST = (
00188     "COPYING", "COPYING.LIB", "CVS", "configure", "copying.c",
00189     "fdl.texi", "gpl.texi", "aclocal.m4",
00190 )
00191 
00192 # The list of files to update by hand.
00193 BY_HAND = (
00194     # These files are sensitive to line numbering.
00195     "gdb/testsuite/gdb.base/step-line.inp",
00196     "gdb/testsuite/gdb.base/step-line.c",
00197 )
00198 
00199 # Files containing multiple copyright headers.  This script is only
00200 # fixing the first one it finds, so we need to finish the update
00201 # by hand.
00202 MULTIPLE_COPYRIGHT_HEADERS = (
00203     "gdb/doc/gdb.texinfo",
00204     "gdb/doc/refcard.tex",
00205     "gdb/gdbarch.sh",
00206 )
00207 
00208 # The list of file which have a copyright, but not head by the FSF.
00209 # Filenames are relative to the root directory.
00210 NOT_FSF_LIST = (
00211     "gdb/exc_request.defs",
00212     "gdb/gdbtk",
00213     "gdb/testsuite/gdb.gdbtk/",
00214     "sim/arm/armemu.h", "sim/arm/armos.c", "sim/arm/gdbhost.c",
00215     "sim/arm/dbg_hif.h", "sim/arm/dbg_conf.h", "sim/arm/communicate.h",
00216     "sim/arm/armos.h", "sim/arm/armcopro.c", "sim/arm/armemu.c",
00217     "sim/arm/kid.c", "sim/arm/thumbemu.c", "sim/arm/armdefs.h",
00218     "sim/arm/armopts.h", "sim/arm/dbg_cp.h", "sim/arm/dbg_rdi.h",
00219     "sim/arm/parent.c", "sim/arm/armsupp.c", "sim/arm/armrdi.c",
00220     "sim/arm/bag.c", "sim/arm/armvirt.c", "sim/arm/main.c", "sim/arm/bag.h",
00221     "sim/arm/communicate.c", "sim/arm/gdbhost.h", "sim/arm/armfpe.h",
00222     "sim/arm/arminit.c",
00223     "sim/common/cgen-fpu.c", "sim/common/cgen-fpu.h",
00224     "sim/common/cgen-accfp.c",
00225     "sim/erc32/sis.h", "sim/erc32/erc32.c", "sim/erc32/func.c",
00226     "sim/erc32/float.c", "sim/erc32/interf.c", "sim/erc32/sis.c",
00227     "sim/erc32/exec.c",
00228     "sim/mips/m16run.c", "sim/mips/sim-main.c",
00229     "sim/moxie/moxie-gdb.dts",
00230     # Not a single file in sim/ppc/ appears to be copyright FSF :-(.
00231     "sim/ppc/filter.h", "sim/ppc/gen-support.h", "sim/ppc/ld-insn.h",
00232     "sim/ppc/hw_sem.c", "sim/ppc/hw_disk.c", "sim/ppc/idecode_branch.h",
00233     "sim/ppc/sim-endian.h", "sim/ppc/table.c", "sim/ppc/hw_core.c",
00234     "sim/ppc/gen-support.c", "sim/ppc/gen-semantics.h", "sim/ppc/cpu.h",
00235     "sim/ppc/sim_callbacks.h", "sim/ppc/RUN", "sim/ppc/Makefile.in",
00236     "sim/ppc/emul_chirp.c", "sim/ppc/hw_nvram.c", "sim/ppc/dc-test.01",
00237     "sim/ppc/hw_phb.c", "sim/ppc/hw_eeprom.c", "sim/ppc/bits.h",
00238     "sim/ppc/hw_vm.c", "sim/ppc/cap.h", "sim/ppc/os_emul.h",
00239     "sim/ppc/options.h", "sim/ppc/gen-idecode.c", "sim/ppc/filter.c",
00240     "sim/ppc/corefile-n.h", "sim/ppc/std-config.h", "sim/ppc/ld-decode.h",
00241     "sim/ppc/filter_filename.h", "sim/ppc/hw_shm.c",
00242     "sim/ppc/pk_disklabel.c", "sim/ppc/dc-simple", "sim/ppc/misc.h",
00243     "sim/ppc/device_table.h", "sim/ppc/ld-insn.c", "sim/ppc/inline.c",
00244     "sim/ppc/emul_bugapi.h", "sim/ppc/hw_cpu.h", "sim/ppc/debug.h",
00245     "sim/ppc/hw_ide.c", "sim/ppc/debug.c", "sim/ppc/gen-itable.h",
00246     "sim/ppc/interrupts.c", "sim/ppc/hw_glue.c", "sim/ppc/emul_unix.c",
00247     "sim/ppc/sim_calls.c", "sim/ppc/dc-complex", "sim/ppc/ld-cache.c",
00248     "sim/ppc/registers.h", "sim/ppc/dc-test.02", "sim/ppc/options.c",
00249     "sim/ppc/igen.h", "sim/ppc/registers.c", "sim/ppc/device.h",
00250     "sim/ppc/emul_chirp.h", "sim/ppc/hw_register.c", "sim/ppc/hw_init.c",
00251     "sim/ppc/sim-endian-n.h", "sim/ppc/filter_filename.c",
00252     "sim/ppc/bits.c", "sim/ppc/idecode_fields.h", "sim/ppc/hw_memory.c",
00253     "sim/ppc/misc.c", "sim/ppc/double.c", "sim/ppc/psim.h",
00254     "sim/ppc/hw_trace.c", "sim/ppc/emul_netbsd.h", "sim/ppc/psim.c",
00255     "sim/ppc/ppc-instructions", "sim/ppc/tree.h", "sim/ppc/README",
00256     "sim/ppc/gen-icache.h", "sim/ppc/gen-model.h", "sim/ppc/ld-cache.h",
00257     "sim/ppc/mon.c", "sim/ppc/corefile.h", "sim/ppc/vm.c",
00258     "sim/ppc/INSTALL", "sim/ppc/gen-model.c", "sim/ppc/hw_cpu.c",
00259     "sim/ppc/corefile.c", "sim/ppc/hw_opic.c", "sim/ppc/gen-icache.c",
00260     "sim/ppc/events.h", "sim/ppc/os_emul.c", "sim/ppc/emul_generic.c",
00261     "sim/ppc/main.c", "sim/ppc/hw_com.c", "sim/ppc/gen-semantics.c",
00262     "sim/ppc/emul_bugapi.c", "sim/ppc/device.c", "sim/ppc/emul_generic.h",
00263     "sim/ppc/tree.c", "sim/ppc/mon.h", "sim/ppc/interrupts.h",
00264     "sim/ppc/cap.c", "sim/ppc/cpu.c", "sim/ppc/hw_phb.h",
00265     "sim/ppc/device_table.c", "sim/ppc/lf.c", "sim/ppc/lf.c",
00266     "sim/ppc/dc-stupid", "sim/ppc/hw_pal.c", "sim/ppc/ppc-spr-table",
00267     "sim/ppc/emul_unix.h", "sim/ppc/words.h", "sim/ppc/basics.h",
00268     "sim/ppc/hw_htab.c", "sim/ppc/lf.h", "sim/ppc/ld-decode.c",
00269     "sim/ppc/sim-endian.c", "sim/ppc/gen-itable.c",
00270     "sim/ppc/idecode_expression.h", "sim/ppc/table.h", "sim/ppc/dgen.c",
00271     "sim/ppc/events.c", "sim/ppc/gen-idecode.h", "sim/ppc/emul_netbsd.c",
00272     "sim/ppc/igen.c", "sim/ppc/vm_n.h", "sim/ppc/vm.h",
00273     "sim/ppc/hw_iobus.c", "sim/ppc/inline.h",
00274     "sim/testsuite/sim/bfin/s21.s", "sim/testsuite/sim/mips/mips32-dsp2.s",
00275 )
00276 
00277 if __name__ == "__main__":
00278     main()
00279 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines