Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] New script copyright.py
@ 2011-01-05  5:56 Joel Brobecker
  2011-01-05 11:37 ` Eli Zaretskii
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Joel Brobecker @ 2011-01-05  5:56 UTC (permalink / raw)
  To: gdb-patches; +Cc: Joel Brobecker

We currently have one script called copyright.sh which uses
the "copyright" script in emacs.  The issue is that script
does not handle a certain number of files, and expects us
to update them by hand.  Unfortunately, that list is fairly long:

        byhand="
        *.s
        *.f
        *.f90
        *.igen
        *.ac
        *.texi
        *.texinfo
        *.tex
        *.defs
        *.1
        "

The purpose of this new script is, first, to automate the update
of these unhandled files. All of them could be handled automatically,
except one (sim/ppc/psim.texinfo).  I have also included the handling
of all Ada files (*.ads, *.adb, and *.gpr) in this script, since
the emacs script seemed to do fail at line wrapping with at least
the .gpr file.

This script also prints a warning if it was expecting a given file
to have a copyright header, and yet did not find one.

And finally, it prints a reminder at the end of all files that
still need to be updated manually (currently only one).

The end-of-year procedure still remains more or less the same, since
the new script is called from the old one.  Eventually, I think it would
be nice to see if we could transition progressively to the new script,
until it handles all files for us.  The reason for it is that I believe
this script can be made solid enough to handle all situations, and avoid
a dependency on a script that we do not control.  But that's for another
day...

gdb/ChangeLog:

        * copyright.py: New script.
        * copyright.sh (byhand): Add *.ads, *.adb and *.gpr.
        Launch emacs without exec'ing. Call copyright.py afterwards.

OK to commit?

---
 gdb/copyright.py |  557 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/copyright.sh |   10 +-
 2 files changed, 565 insertions(+), 2 deletions(-)
 create mode 100644 gdb/copyright.py

diff --git a/gdb/copyright.py b/gdb/copyright.py
new file mode 100644
index 0000000..394029d
--- /dev/null
+++ b/gdb/copyright.py
@@ -0,0 +1,557 @@
+#! /usr/bin/env python
+
+"""copyright.py
+
+This script updates most of the files that are not already handled
+by copyright.sh.  It must be run from the gdb/ subdirectory of the
+GDB source tree.
+
+"""
+
+import datetime
+import re
+import os
+import os.path
+
+class Comment(object):
+    """A class describing comment.
+
+    ATTRIBUTES
+      start:  A string describing how comments are started.
+      stop:   A string describing how comments end.  If None, then
+              a comment ends at the end of the line.
+      start2: Some files accept more than 1 kind of comment.
+              For those that do, this is the alternative form.
+              For now, it is assumed that if start2 is not None,
+              then stop is None (thus no stop2 attribute).
+    """
+    def __init__(self, start, stop=None, start2=None, max_lines=30):
+        """The "Copyright" keyword should be within MAX_LINES lines
+        from the start of the file."""
+        self.start = start
+        self.stop = stop
+        self.start2 = start2
+        self.max_lines = max_lines
+
+THIS_YEAR = str(datetime.date.today().year)
+
+# Files which should not be modified, either because they are
+# generated, non-FSF, or otherwise special (e.g. license text,
+# or test cases which must be sensitive to line numbering).
+EXCLUSION_LIST = (
+  "COPYING", "COPYING.LIB", "CVS", "configure", "copying.c", "gdbarch.c",
+  "gdbarch.h", "fdl.texi", "gpl.texi", "gdbtk", "gdb.gdbtk", "osf-share",
+  "aclocal.m4", "step-line.inp", "step-line.c",
+  )
+
+# Files that are too different from the rest to be processed automatically.
+BY_HAND = ['../sim/ppc/psim.texinfo']
+
+# Files for which we know that they do not have a copyright header.
+# Ideally, this list should be empty (but it may not be possible to
+# add a copyright header in some of them).
+NO_COPYRIGHT = (
+   # Configure files.  We should fix those, one day.
+   "testsuite/gdb.cell/configure.ac", "testsuite/gdb.hp/configure.ac",
+   "testsuite/gdb.hp/gdb.aCC/configure.ac",
+   "testsuite/gdb.hp/gdb.base-hp/configure.ac",
+   "testsuite/gdb.hp/gdb.compat/configure.ac",
+   "testsuite/gdb.hp/gdb.defects/configure.ac",
+   "testsuite/gdb.hp/gdb.objdbg/configure.ac",
+   "testsuite/gdb.stabs/configure.ac",
+   "../sim/arm/configure.ac", "../sim/avr/configure.ac",
+   "../sim/common/configure.ac", "../sim/configure.ac",
+   "../sim/cr16/configure.ac", "../sim/cris/configure.ac",
+   "../sim/d10v/configure.ac", "../sim/erc32/configure.ac",
+   "../sim/frv/configure.ac", "../sim/h8300/configure.ac",
+   "../sim/igen/configure.ac", "../sim/iq2000/configure.ac",
+   "../sim/lm32/configure.ac", "../sim/m32r/configure.ac",
+   "../sim/m68hc11/configure.ac", "../sim/mcore/configure.ac",
+   "../sim/microblaze/configure.ac", "../sim/mips/configure.ac",
+   "../sim/mn10300/configure.ac", "../sim/moxie/configure.ac",
+   "../sim/ppc/configure.ac", "../sim/sh/configure.ac",
+   "../sim/sh64/configure.ac", "../sim/testsuite/configure.ac",
+   "../sim/testsuite/d10v-elf/configure.ac",
+   "../sim/testsuite/frv-elf/configure.ac",
+   "../sim/testsuite/m32r-elf/configure.ac",
+   "../sim/testsuite/mips64el-elf/configure.ac", "../sim/v850/configure.ac",
+   # Assembly files.  It's not certain that we can add a copyright
+   # header in a way that works for all platforms supported by the
+   # testcase...
+   "testsuite/gdb.arch/pa-nullify.s", "testsuite/gdb.arch/pa64-nullify.s",
+   "testsuite/gdb.asm/asmsrc1.s", "testsuite/gdb.asm/asmsrc2.s",
+   "testsuite/gdb.disasm/am33.s", "testsuite/gdb.disasm/h8300s.s",
+   "testsuite/gdb.disasm/hppa.s", "testsuite/gdb.disasm/mn10200.s",
+   "testsuite/gdb.disasm/mn10300.s", "testsuite/gdb.disasm/sh3.s",
+   "testsuite/gdb.disasm/t01_mov.s", "testsuite/gdb.disasm/t02_mova.s",
+   "testsuite/gdb.disasm/t03_add.s", "testsuite/gdb.disasm/t04_sub.s",
+   "testsuite/gdb.disasm/t05_cmp.s", "testsuite/gdb.disasm/t06_ari2.s",
+   "testsuite/gdb.disasm/t07_ari3.s", "testsuite/gdb.disasm/t08_or.s",
+   "testsuite/gdb.disasm/t09_xor.s", "testsuite/gdb.disasm/t10_and.s",
+   "testsuite/gdb.disasm/t11_logs.s", "testsuite/gdb.disasm/t12_bit.s",
+   "testsuite/gdb.disasm/t13_otr.s", "testsuite/gdb.hp/gdb.base-hp/reg-pa64.s",
+   "testsuite/gdb.hp/gdb.base-hp/reg.s",
+   "../sim/testsuite/d10v-elf/exit47.s",
+   "../sim/testsuite/d10v-elf/hello.s",
+   "../sim/testsuite/d10v-elf/loop.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-is.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-is.s",
+   "../sim/testsuite/d10v-elf/t-dbt.s",
+   "../sim/testsuite/d10v-elf/t-ld-st.s",
+   "../sim/testsuite/d10v-elf/t-mac.s",
+   "../sim/testsuite/d10v-elf/t-mod-ld-pre.s",
+   "../sim/testsuite/d10v-elf/t-msbu.s",
+   "../sim/testsuite/d10v-elf/t-mulxu.s",
+   "../sim/testsuite/d10v-elf/t-mvtac.s",
+   "../sim/testsuite/d10v-elf/t-mvtc.s",
+   "../sim/testsuite/d10v-elf/t-rac.s",
+   "../sim/testsuite/d10v-elf/t-rachi.s",
+   "../sim/testsuite/d10v-elf/t-rdt.s",
+   "../sim/testsuite/d10v-elf/t-rep.s",
+   "../sim/testsuite/d10v-elf/t-rie-xx.s",
+   "../sim/testsuite/d10v-elf/t-rte.s",
+   "../sim/testsuite/d10v-elf/t-sac.s",
+   "../sim/testsuite/d10v-elf/t-sachi.s",
+   "../sim/testsuite/d10v-elf/t-sadd.s",
+   "../sim/testsuite/d10v-elf/t-slae.s",
+   "../sim/testsuite/d10v-elf/t-sp.s",
+   "../sim/testsuite/d10v-elf/t-sub.s",
+   "../sim/testsuite/d10v-elf/t-sub2w.s",
+   "../sim/testsuite/d10v-elf/t-subi.s",
+   "../sim/testsuite/d10v-elf/t-trap.s",
+   "../sim/testsuite/frv-elf/cache.s",
+   "../sim/testsuite/frv-elf/exit47.s",
+   "../sim/testsuite/frv-elf/grloop.s",
+   "../sim/testsuite/frv-elf/hello.s",
+   "../sim/testsuite/frv-elf/loop.s",
+   "../sim/testsuite/m32r-elf/exit47.s",
+   "../sim/testsuite/m32r-elf/hello.s",
+   "../sim/testsuite/m32r-elf/loop.s",
+   "../sim/testsuite/sim/cris/hw/rv-n-cris/quit.s",
+   "../sim/testsuite/sim/h8300/addb.s",
+   "../sim/testsuite/sim/h8300/addl.s",
+   "../sim/testsuite/sim/h8300/adds.s",
+   "../sim/testsuite/sim/h8300/addw.s",
+   "../sim/testsuite/sim/h8300/addx.s",
+   "../sim/testsuite/sim/h8300/andb.s",
+   "../sim/testsuite/sim/h8300/andl.s",
+   "../sim/testsuite/sim/h8300/andw.s",
+   "../sim/testsuite/sim/h8300/band.s",
+   "../sim/testsuite/sim/h8300/bfld.s",
+   "../sim/testsuite/sim/h8300/biand.s",
+   "../sim/testsuite/sim/h8300/bra.s",
+   "../sim/testsuite/sim/h8300/brabc.s",
+   "../sim/testsuite/sim/h8300/bset.s",
+   "../sim/testsuite/sim/h8300/cmpb.s",
+   "../sim/testsuite/sim/h8300/cmpl.s",
+   "../sim/testsuite/sim/h8300/cmpw.s",
+   "../sim/testsuite/sim/h8300/daa.s",
+   "../sim/testsuite/sim/h8300/das.s",
+   "../sim/testsuite/sim/h8300/dec.s",
+   "../sim/testsuite/sim/h8300/div.s",
+   "../sim/testsuite/sim/h8300/extl.s",
+   "../sim/testsuite/sim/h8300/extw.s",
+   "../sim/testsuite/sim/h8300/inc.s",
+   "../sim/testsuite/sim/h8300/jmp.s",
+   "../sim/testsuite/sim/h8300/ldc.s",
+   "../sim/testsuite/sim/h8300/ldm.s",
+   "../sim/testsuite/sim/h8300/mac.s",
+   "../sim/testsuite/sim/h8300/mova.s",
+   "../sim/testsuite/sim/h8300/movb.s",
+   "../sim/testsuite/sim/h8300/movl.s",
+   "../sim/testsuite/sim/h8300/movmd.s",
+   "../sim/testsuite/sim/h8300/movsd.s",
+   "../sim/testsuite/sim/h8300/movw.s",
+   "../sim/testsuite/sim/h8300/mul.s",
+   "../sim/testsuite/sim/h8300/neg.s",
+   "../sim/testsuite/sim/h8300/nop.s",
+   "../sim/testsuite/sim/h8300/not.s",
+   "../sim/testsuite/sim/h8300/orb.s",
+   "../sim/testsuite/sim/h8300/orl.s",
+   "../sim/testsuite/sim/h8300/orw.s",
+   "../sim/testsuite/sim/h8300/rotl.s",
+   "../sim/testsuite/sim/h8300/rotr.s",
+   "../sim/testsuite/sim/h8300/rotxl.s",
+   "../sim/testsuite/sim/h8300/rotxr.s",
+   "../sim/testsuite/sim/h8300/shal.s",
+   "../sim/testsuite/sim/h8300/shar.s",
+   "../sim/testsuite/sim/h8300/shll.s",
+   "../sim/testsuite/sim/h8300/shlr.s",
+   "../sim/testsuite/sim/h8300/stack.s",
+   "../sim/testsuite/sim/h8300/stc.s",
+   "../sim/testsuite/sim/h8300/subb.s",
+   "../sim/testsuite/sim/h8300/subl.s",
+   "../sim/testsuite/sim/h8300/subs.s",
+   "../sim/testsuite/sim/h8300/subw.s",
+   "../sim/testsuite/sim/h8300/subx.s",
+   "../sim/testsuite/sim/h8300/tas.s",
+   "../sim/testsuite/sim/h8300/xorb.s",
+   "../sim/testsuite/sim/h8300/xorl.s",
+   "../sim/testsuite/sim/h8300/xorw.s",
+   "../sim/testsuite/sim/mips/fpu64-ps-sb1.s",
+   "../sim/testsuite/sim/mips/fpu64-ps.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-1.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-2.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-3.s",
+   "../sim/testsuite/sim/mips/mdmx-ob-sb1.s",
+   "../sim/testsuite/sim/mips/mdmx-ob.s",
+   "../sim/testsuite/sim/mips/mips32-dsp.s",
+   "../sim/testsuite/sim/mips/mips32-dsp2.s",
+   "../sim/testsuite/sim/mips/sanity.s",
+   "../sim/testsuite/sim/sh/add.s",
+   "../sim/testsuite/sim/sh/and.s",
+   "../sim/testsuite/sim/sh/bandor.s",
+   "../sim/testsuite/sim/sh/bandornot.s",
+   "../sim/testsuite/sim/sh/bclr.s",
+   "../sim/testsuite/sim/sh/bld.s",
+   "../sim/testsuite/sim/sh/bldnot.s",
+   "../sim/testsuite/sim/sh/bset.s",
+   "../sim/testsuite/sim/sh/bst.s",
+   "../sim/testsuite/sim/sh/bxor.s",
+   "../sim/testsuite/sim/sh/clip.s",
+   "../sim/testsuite/sim/sh/div.s",
+   "../sim/testsuite/sim/sh/dmxy.s",
+   "../sim/testsuite/sim/sh/fabs.s",
+   "../sim/testsuite/sim/sh/fadd.s",
+   "../sim/testsuite/sim/sh/fail.s",
+   "../sim/testsuite/sim/sh/fcmpeq.s",
+   "../sim/testsuite/sim/sh/fcmpgt.s",
+   "../sim/testsuite/sim/sh/fcnvds.s",
+   "../sim/testsuite/sim/sh/fcnvsd.s",
+   "../sim/testsuite/sim/sh/fdiv.s",
+   "../sim/testsuite/sim/sh/fipr.s",
+   "../sim/testsuite/sim/sh/fldi0.s",
+   "../sim/testsuite/sim/sh/fldi1.s",
+   "../sim/testsuite/sim/sh/flds.s",
+   "../sim/testsuite/sim/sh/float.s",
+   "../sim/testsuite/sim/sh/fmac.s",
+   "../sim/testsuite/sim/sh/fmov.s",
+   "../sim/testsuite/sim/sh/fmul.s",
+   "../sim/testsuite/sim/sh/fneg.s",
+   "../sim/testsuite/sim/sh/fpchg.s",
+   "../sim/testsuite/sim/sh/frchg.s",
+   "../sim/testsuite/sim/sh/fsca.s",
+   "../sim/testsuite/sim/sh/fschg.s",
+   "../sim/testsuite/sim/sh/fsqrt.s",
+   "../sim/testsuite/sim/sh/fsrra.s",
+   "../sim/testsuite/sim/sh/fsub.s",
+   "../sim/testsuite/sim/sh/ftrc.s",
+   "../sim/testsuite/sim/sh/ldrc.s",
+   "../sim/testsuite/sim/sh/loop.s",
+   "../sim/testsuite/sim/sh/macl.s",
+   "../sim/testsuite/sim/sh/macw.s",
+   "../sim/testsuite/sim/sh/mov.s",
+   "../sim/testsuite/sim/sh/movi.s",
+   "../sim/testsuite/sim/sh/movli.s",
+   "../sim/testsuite/sim/sh/movua.s",
+   "../sim/testsuite/sim/sh/movxy.s",
+   "../sim/testsuite/sim/sh/mulr.s",
+   "../sim/testsuite/sim/sh/pabs.s",
+   "../sim/testsuite/sim/sh/padd.s",
+   "../sim/testsuite/sim/sh/paddc.s",
+   "../sim/testsuite/sim/sh/pand.s",
+   "../sim/testsuite/sim/sh/pass.s",
+   "../sim/testsuite/sim/sh/pclr.s",
+   "../sim/testsuite/sim/sh/pdec.s",
+   "../sim/testsuite/sim/sh/pdmsb.s",
+   "../sim/testsuite/sim/sh/pinc.s",
+   "../sim/testsuite/sim/sh/pmuls.s",
+   "../sim/testsuite/sim/sh/prnd.s",
+   "../sim/testsuite/sim/sh/pshai.s",
+   "../sim/testsuite/sim/sh/pshar.s",
+   "../sim/testsuite/sim/sh/pshli.s",
+   "../sim/testsuite/sim/sh/pshlr.s",
+   "../sim/testsuite/sim/sh/psub.s",
+   "../sim/testsuite/sim/sh/pswap.s",
+   "../sim/testsuite/sim/sh/pushpop.s",
+   "../sim/testsuite/sim/sh/resbank.s",
+   "../sim/testsuite/sim/sh/sett.s",
+   "../sim/testsuite/sim/sh/shll.s",
+   "../sim/testsuite/sim/sh/shll16.s",
+   "../sim/testsuite/sim/sh/shll2.s",
+   "../sim/testsuite/sim/sh/shll8.s",
+   "../sim/testsuite/sim/sh/shlr.s",
+   "../sim/testsuite/sim/sh/shlr16.s",
+   "../sim/testsuite/sim/sh/shlr2.s",
+   "../sim/testsuite/sim/sh/shlr8.s",
+   "../sim/testsuite/sim/sh/swap.s",
+   "../sim/testsuite/sim/sh64/misc/fr-dr.s",
+   )
+
+# A mapping between file extensions to their associated Comment object.
+# This dictionary also contains a number of exceptions, based on
+# filename.
+COMMENT_MAP = \
+  {".1" : Comment(start=r'.\"'),
+   ".ac" : Comment(start="dnl", start2="#"),
+   ".ads" : Comment(start="--"),
+   ".adb" : Comment(start="--"),
+   ".gpr" : Comment(start="--"),
+   ".f" : Comment(start="c"),
+   ".f90" : Comment(start="!"),
+   ".s" : Comment(start="!"),
+   ".tex" : Comment(start="%"),
+   ".texi" : Comment(start="@c"),
+   ".texinfo" : Comment(start="@c"),
+
+   # Files that use a different way of including the copyright
+   # header...
+   "gdbint.texinfo" : Comment(start='@copying', stop="@end copying"),
+   "annotate.texinfo" : Comment(start='@copying', stop="@end copying",
+                                max_lines=50),
+   "stabs.texinfo" : Comment(start='@copying', stop="@end copying"),
+  }
+
+class NotFound(Exception):
+    pass
+
+class AlreadyDone(Exception):
+    pass
+
+def process_header(src, dst, cdescr):
+    """Read from SRC for up to CDESCR.MAX_LINES until we find a copyright
+    notice.  If found, then write the entire file, with the copyright
+    noticed updated with the current year added.
+
+    Raises NotFound if the copyright notice could not be found or has
+    some inconsistencies.
+
+    Raises AlreadyDone if the copyright notice already includes the current
+    year.
+    """
+    line_count = 0
+    # The start-of-comment marker used for this file.  Only really useful
+    # in the case where comments ends at the end of the line, as this
+    # allows us to know which comment marker to use when breaking long
+    # lines (in the cases where there are more than one.
+    cdescr_start = ""
+
+    while True:
+        # If we still haven't found a copyright line within a certain
+        # number of lines, then give up.
+        if line_count > cdescr.max_lines:
+            raise NotFound("start of Copyright not found")
+
+        line = src.readline()
+        line_count += 1
+        if not line:
+            raise NotFound("start of Copyright not found (EOF)")
+
+        # Is this a copyright line?  If not, then no transformation is
+        # needed.  Write it as is, and continue.
+        if not re.search(r"Copyright\b.*\b(199\d|20\d\d)\b", line):
+            dst.write(line)
+            continue
+
+        # If a start-of-comment marker is needed for every line, try to
+        # figure out which one it is that is being used in this file (most
+        # files only accept one, in which case it's easy - but some accept
+        # two or more...).
+        if cdescr.stop is None:
+            stripped_line = line.lstrip()
+            if stripped_line.startswith(cdescr.start):
+                cdescr_start = cdescr.start
+            elif (cdescr.start2 is not None
+                  and stripped_line.startswith(cdescr.start2)):
+                cdescr_start = cdescr.start2
+            elif cdescr.start in stripped_line:
+                cdescr_start = cdescr.start
+            elif (cdescr.start2 is not None
+                  and cdescr.start2 in stripped_line):
+                cdescr_start = cdescr.start2
+            else:
+                # This can't be a line with a comment, so not the copyright
+                # line we were looking for.  Ignore.
+                continue
+
+        comment = line
+        break
+
+    while not re.search(r"Free\s+Software\s+Foundation", comment):
+        line = src.readline()
+        line_count += 1
+        if not line:
+            raise NotFound("Copyright owner not found (EOF)")
+
+        if cdescr.stop is None:
+            # Expect a new comment marker at the start of each line
+            line = line.lstrip()
+            if not line.startswith(cdescr_start):
+                raise NotFound("Copyright owner not found "
+                               "(end of comment)")
+            comment += " " + line[len(cdescr_start):]
+        else:
+            if cdescr.stop in comment:
+                raise NotFound("Copyright owner not found "
+                               "(end of comment)")
+            comment += line
+
+    # Normalize a bit the copyright string (we preserve the string
+    # up until "Copyright", in order to help preserve any original
+    # alignment.
+    (before, after) = comment.split("Copyright", 1)
+    after = after.replace("\n", " ")
+    after = re.sub("\s+", " ", after)
+    after = after.rstrip()
+
+    # If the copyright year has already been added, the nothing else
+    # to do.
+    if THIS_YEAR in after:
+        raise AlreadyDone
+
+    m = re.match("(.*[0-9]+)(.*)", after)
+    if m is None:
+        raise NotFound("Internal error - cannot split copyright line: "
+                       "`%s'" % comment)
+
+    # Reconstruct the comment line
+    comment = before + "Copyright" + m.group(1) + ', %s' % THIS_YEAR
+    owner_part = m.group(2).lstrip()
+
+    # Max comment len...
+    max_len = 76
+
+    # If we have to break the copyright line into multiple lines,
+    # we want to align all the lines on the "Copyright" keyword.
+    # Create a small "indent" string that we can use for that.
+    if cdescr.stop is None:
+        # The comment marker is needed on every line, so put it at the
+        # start of our "indent" string.
+        indent = cdescr_start + ' ' * (len(before) - len(cdescr_start))
+    else:
+        indent = ' ' * len(before)
+
+    # If the line is too long...
+    while len(comment) > max_len:
+        # Split the line at the first space before max_len.
+        space_index = comment[0:max_len].rfind(' ')
+        if space_index < 0:  # No space in the first max_len characters???
+            # Split at the first space, then...
+            space_index = comment.find(' ')
+        if space_index < 0:
+            # Still no space found.  This is extremely unlikely, but
+            # just pretend there is one at the end of the string.
+            space_index = len(comment)
+
+        # Write the first part of the string up until the space
+        # we selected to break our line.
+        dst.write(comment[:space_index] + '\n')
+
+        # Strip the part of comment that we have finished printing.
+        if space_index < len(comment):
+            comment = comment[space_index + 1:]
+        else:
+            comment = ""
+
+        # Prepend the "indent" string to make sure that we remain
+        # aligned on the "Copyright" word.
+        comment = indent + comment
+
+    # And finally, write the rest of the last line...  We want to write
+    # "Free Software Foundation, Inc" on the same line, so handle this
+    # with extra care.
+    dst.write(comment)
+    if len(comment) + 1 + len (owner_part) > max_len:
+        dst.write('\n' + indent)
+    else:
+        dst.write(' ')
+    dst.write(owner_part + '\n')
+
+def comment_for_filename(filename):
+    """Return the Comment object that best describes the given file.
+    This a smart lookup of the COMMENT_MAP dictionary where we check
+    for filename-based exceptions first, before looking up the comment
+    by filename extension.  """
+    # First, consult the COMMENT_MAP using the filename, in case this
+    # file needs special treatment.
+    basename = os.path.basename(filename)
+    if basename in COMMENT_MAP:
+        return COMMENT_MAP[basename]
+    # Not a special file.  Check the file extension.
+    ext = os.path.splitext(filename)[1]
+    if ext in COMMENT_MAP:
+        return COMMENT_MAP[ext]
+    # Not a know extension either, return None.
+    return None
+
+def process_file(filename):
+    """Processes the given file.
+    """
+    cdescr = comment_for_filename(filename)
+    if cdescr is None:
+        # Either no filename extension, or not an extension that we
+        # know how to handle.
+        return
+
+    dst_filename = filename + '.new'
+    src = open(filename)
+    dst = open(dst_filename, 'w')
+    try:
+        process_header(src, dst, cdescr)
+    except AlreadyDone:
+        print "+++ Already up to date: `%s'." % filename
+        dst.close()
+        os.unlink(dst_filename)
+        if filename in NO_COPYRIGHT:
+            # We expect the search for a copyright header to fail, and
+            # yet we found one...
+            print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
+        return
+    except NotFound as inst:
+        dst.close()
+        os.unlink(dst_filename)
+        if not filename in NO_COPYRIGHT:
+            print "*** \033[31m%s\033[0m: %s" % (filename, inst)
+        return
+
+    if filename in NO_COPYRIGHT:
+        # We expect the search for a copyright header to fail, and
+        # yet we found one...
+        print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
+
+    for line in src:
+        dst.write(line)
+    src.close()
+    dst.close()
+    os.rename(dst_filename, filename)
+
+if __name__ == "__main__":
+    if not os.path.isfile("doc/gdb.texinfo"):
+        print "Error: This script must be called from the gdb directory."
+    for gdb_dir in ('.', '../sim', '../include/gdb'):
+        for root, dirs, files in os.walk(gdb_dir):
+            for filename in files:
+                fullpath = os.path.join(root, filename)
+                if fullpath.startswith('./'):
+                    fullpath = fullpath[2:]
+                if filename not in EXCLUSION_LIST and fullpath not in BY_HAND:
+                    # Paths that start with './' are ugly, so strip that.
+                    # This also allows us to omit them in the NO_COPYRIGHT
+                    # list...
+                    process_file(fullpath)
+    print
+    print "\033[32mREMINDER: The following files must be updated by hand." \
+          "\033[0m"
+    for filename in BY_HAND:
+        print "  ", filename
+
diff --git a/gdb/copyright.sh b/gdb/copyright.sh
index 399ce3a..3b2d105 100644
--- a/gdb/copyright.sh
+++ b/gdb/copyright.sh
@@ -44,7 +44,8 @@
 #  tex (%)
 #  *.defs as C
 #   man
-# So these need to be done by hand, as needed
+# So these need to be done either by hand, as needed, or by the copyright.py
+# script.
 byhand="
 *.s
 *.f
@@ -56,6 +57,9 @@ byhand="
 *.tex
 *.defs
 *.1
+*.ads
+*.adb
+*.gpr
 "
 
 # Files which should not be modified, either because they are
@@ -160,4 +164,6 @@ cat >> copytmp.el <<EOF
 (kill-emacs)
 EOF
 
-exec $EMACS --no-site-file -q -l ./copytmp.el
+$EMACS --no-site-file -q -l ./copytmp.el
+
+python $dir/copyright.py
-- 
1.7.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-05  5:56 [RFA] New script copyright.py Joel Brobecker
@ 2011-01-05 11:37 ` Eli Zaretskii
  2011-01-06  4:39   ` Joel Brobecker
  2011-01-05 16:12 ` Tom Tromey
  2011-01-06 18:25 ` Alfred M. Szmidt
  2 siblings, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2011-01-05 11:37 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

> From: Joel Brobecker <brobecker@adacore.com>
> Cc: Joel Brobecker <brobecker@adacore.com>
> Date: Wed,  5 Jan 2011 09:55:52 +0400
> 
> We currently have one script called copyright.sh which uses
> the "copyright" script in emacs.  The issue is that script
> does not handle a certain number of files, and expects us
> to update them by hand.  Unfortunately, that list is fairly long:
> 
>         byhand="
>         *.s
>         *.f
>         *.f90
>         *.igen
>         *.ac
>         *.texi
>         *.texinfo
>         *.tex
>         *.defs
>         *.1
>         "
> 
> The purpose of this new script is, first, to automate the update
> of these unhandled files. All of them could be handled automatically,
> except one (sim/ppc/psim.texinfo).  I have also included the handling
> of all Ada files (*.ads, *.adb, and *.gpr) in this script, since
> the emacs script seemed to do fail at line wrapping with at least
> the .gpr file.

(Wearing my Emacs maintenance hat.)  It would be good to report these
problems to the Emacs bug tracker ("M-x report-emacs-bug RET"),
including all the details, like error messages etc.  At least some of
them should be fixable.

TIA


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-05  5:56 [RFA] New script copyright.py Joel Brobecker
  2011-01-05 11:37 ` Eli Zaretskii
@ 2011-01-05 16:12 ` Tom Tromey
  2011-01-06  6:33   ` Joel Brobecker
  2011-01-06 18:25 ` Alfred M. Szmidt
  2 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2011-01-05 16:12 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel>         * copyright.py: New script.
Joel>         * copyright.sh (byhand): Add *.ads, *.adb and *.gpr.
Joel>         Launch emacs without exec'ing. Call copyright.py afterwards.

Joel> OK to commit?

It seems like a good idea to me.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-05 11:37 ` Eli Zaretskii
@ 2011-01-06  4:39   ` Joel Brobecker
  0 siblings, 0 replies; 7+ messages in thread
From: Joel Brobecker @ 2011-01-06  4:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

> (Wearing my Emacs maintenance hat.)  It would be good to report these
> problems to the Emacs bug tracker ("M-x report-emacs-bug RET"),
> including all the details, like error messages etc.  At least some of
> them should be fixable.

I have to pass on that, really sorry. I don't use emacs at all, and
I even had to install it just so that I could run the copyright update
script. Plenty of people seem to know emacs really well, whereas my
emacs hackers ended over 10 years ago, and I don't remember anymore.
If you are looking for files that the script mis-handled, you can
have a look at:

   * testsuite/gdb.ada/gnat_ada.gpr
   * sim/testsuite/sim/mips/testutils.inc
     http://www.sourceware.org/ml/gdb-patches/2011-01/msg00097.html

In both instances, the problem came from the fact that the copyright
line became too long and had to be wrapped, but the wrapping forgot
to add the comment marker (a "--" for .gpr files, and a "#" in the
.inc file).

-- 
Joel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-05 16:12 ` Tom Tromey
@ 2011-01-06  6:33   ` Joel Brobecker
  0 siblings, 0 replies; 7+ messages in thread
From: Joel Brobecker @ 2011-01-06  6:33 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 748 bytes --]

> >>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
> 
> Joel>         * copyright.py: New script.
> Joel>         * copyright.sh (byhand): Add *.ads, *.adb and *.gpr.
> Joel>         Launch emacs without exec'ing. Call copyright.py afterwards.
> 
> Joel> OK to commit?
> 
> It seems like a good idea to me.

Cool! Given the issues with .inc files that HP discovered, I also
transfered, after some testing that it does the right thing, the
responsibility of updating these files to the new script.

Attached is what I just checked in.

gdb/ChangeLog:

        * copyright.py: New script.
        * copyright.sh (byhand): Add *.ads, *.adb, *.gpr and *.inc.
        Launch emacs without exec'ing. Call copyright.py afterwards.

-- 
Joel

[-- Attachment #2: new-copyright-update-script.diff --]
[-- Type: text/x-diff, Size: 26226 bytes --]

commit 5612845d5bffe22638a420915d87efcb7d51b5ed
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Wed Jan 5 09:42:51 2011 +0400

    New script copyright.py
    
    gdb/ChangeLog:
    
            * copyright.py: New script.
            * copyright.sh (byhand): Add *.ads, *.adb, *.gpr and *.inc.
            Launch emacs without exec'ing. Call copyright.py afterwards.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5721016..60676a3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2011-01-06  Joel Brobecker  <brobecker@adacore.com>
+
+	* copyright.py: New script.
+	* copyright.sh (byhand): Add *.ads, *.adb, *.gpr and *.inc.
+	Launch emacs without exec'ing. Call copyright.py afterwards.
+
 2011-01-05  Michael Snyder  <msnyder@vmware.com>
 
 	* addrmap.c: Shorten lines of >= 80 columns.
diff --git a/gdb/copyright.py b/gdb/copyright.py
new file mode 100644
index 0000000..71f261d
--- /dev/null
+++ b/gdb/copyright.py
@@ -0,0 +1,608 @@
+#! /usr/bin/env python
+
+"""copyright.py
+
+This script updates most of the files that are not already handled
+by copyright.sh.  It must be run from the gdb/ subdirectory of the
+GDB source tree.
+
+"""
+
+import datetime
+import re
+import os
+import os.path
+
+class Comment(object):
+    """A class describing comment.
+
+    ATTRIBUTES
+      start:  A string describing how comments are started.
+      stop:   A string describing how comments end.  If None, then
+              a comment ends at the end of the line.
+      start2: Some files accept more than 1 kind of comment.
+              For those that do, this is the alternative form.
+              For now, it is assumed that if start2 is not None,
+              then stop is None (thus no stop2 attribute).
+    """
+    def __init__(self, start, stop=None, start2=None, max_lines=30):
+        """The "Copyright" keyword should be within MAX_LINES lines
+        from the start of the file."""
+        self.start = start
+        self.stop = stop
+        self.start2 = start2
+        self.max_lines = max_lines
+
+# The Comment object for Ada code (and GPR files).
+ADA_COMMENT = Comment(start="--")
+
+THIS_YEAR = str(datetime.date.today().year)
+
+# Files which should not be modified, either because they are
+# generated, non-FSF, or otherwise special (e.g. license text,
+# or test cases which must be sensitive to line numbering).
+EXCLUSION_LIST = (
+  "COPYING", "COPYING.LIB", "CVS", "configure", "copying.c", "gdbarch.c",
+  "gdbarch.h", "fdl.texi", "gpl.texi", "gdbtk", "gdb.gdbtk", "osf-share",
+  "aclocal.m4", "step-line.inp", "step-line.c",
+  )
+
+# Files that are too different from the rest to be processed automatically.
+BY_HAND = ['../sim/ppc/psim.texinfo']
+
+# Files for which we know that they do not have a copyright header.
+# Ideally, this list should be empty (but it may not be possible to
+# add a copyright header in some of them).
+NO_COPYRIGHT = (
+   # Configure files.  We should fix those, one day.
+   "testsuite/gdb.cell/configure.ac", "testsuite/gdb.hp/configure.ac",
+   "testsuite/gdb.hp/gdb.aCC/configure.ac",
+   "testsuite/gdb.hp/gdb.base-hp/configure.ac",
+   "testsuite/gdb.hp/gdb.compat/configure.ac",
+   "testsuite/gdb.hp/gdb.defects/configure.ac",
+   "testsuite/gdb.hp/gdb.objdbg/configure.ac",
+   "testsuite/gdb.stabs/configure.ac",
+   "../sim/arm/configure.ac", "../sim/avr/configure.ac",
+   "../sim/common/configure.ac", "../sim/configure.ac",
+   "../sim/cr16/configure.ac", "../sim/cris/configure.ac",
+   "../sim/d10v/configure.ac", "../sim/erc32/configure.ac",
+   "../sim/frv/configure.ac", "../sim/h8300/configure.ac",
+   "../sim/igen/configure.ac", "../sim/iq2000/configure.ac",
+   "../sim/lm32/configure.ac", "../sim/m32r/configure.ac",
+   "../sim/m68hc11/configure.ac", "../sim/mcore/configure.ac",
+   "../sim/microblaze/configure.ac", "../sim/mips/configure.ac",
+   "../sim/mn10300/configure.ac", "../sim/moxie/configure.ac",
+   "../sim/ppc/configure.ac", "../sim/sh/configure.ac",
+   "../sim/sh64/configure.ac", "../sim/testsuite/configure.ac",
+   "../sim/testsuite/d10v-elf/configure.ac",
+   "../sim/testsuite/frv-elf/configure.ac",
+   "../sim/testsuite/m32r-elf/configure.ac",
+   "../sim/testsuite/mips64el-elf/configure.ac", "../sim/v850/configure.ac",
+   # Assembly files.  It's not certain that we can add a copyright
+   # header in a way that works for all platforms supported by the
+   # testcase...
+   "testsuite/gdb.arch/pa-nullify.s", "testsuite/gdb.arch/pa64-nullify.s",
+   "testsuite/gdb.asm/asmsrc1.s", "testsuite/gdb.asm/asmsrc2.s",
+   "testsuite/gdb.disasm/am33.s", "testsuite/gdb.disasm/h8300s.s",
+   "testsuite/gdb.disasm/hppa.s", "testsuite/gdb.disasm/mn10200.s",
+   "testsuite/gdb.disasm/mn10300.s", "testsuite/gdb.disasm/sh3.s",
+   "testsuite/gdb.disasm/t01_mov.s", "testsuite/gdb.disasm/t02_mova.s",
+   "testsuite/gdb.disasm/t03_add.s", "testsuite/gdb.disasm/t04_sub.s",
+   "testsuite/gdb.disasm/t05_cmp.s", "testsuite/gdb.disasm/t06_ari2.s",
+   "testsuite/gdb.disasm/t07_ari3.s", "testsuite/gdb.disasm/t08_or.s",
+   "testsuite/gdb.disasm/t09_xor.s", "testsuite/gdb.disasm/t10_and.s",
+   "testsuite/gdb.disasm/t11_logs.s", "testsuite/gdb.disasm/t12_bit.s",
+   "testsuite/gdb.disasm/t13_otr.s", "testsuite/gdb.hp/gdb.base-hp/reg-pa64.s",
+   "testsuite/gdb.hp/gdb.base-hp/reg.s",
+   "../sim/testsuite/d10v-elf/exit47.s",
+   "../sim/testsuite/d10v-elf/hello.s",
+   "../sim/testsuite/d10v-elf/loop.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-ld2w-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st-is.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-d.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-i.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-id.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-im.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-ip.s",
+   "../sim/testsuite/d10v-elf/t-ae-st2w-is.s",
+   "../sim/testsuite/d10v-elf/t-dbt.s",
+   "../sim/testsuite/d10v-elf/t-ld-st.s",
+   "../sim/testsuite/d10v-elf/t-mac.s",
+   "../sim/testsuite/d10v-elf/t-mod-ld-pre.s",
+   "../sim/testsuite/d10v-elf/t-msbu.s",
+   "../sim/testsuite/d10v-elf/t-mulxu.s",
+   "../sim/testsuite/d10v-elf/t-mvtac.s",
+   "../sim/testsuite/d10v-elf/t-mvtc.s",
+   "../sim/testsuite/d10v-elf/t-rac.s",
+   "../sim/testsuite/d10v-elf/t-rachi.s",
+   "../sim/testsuite/d10v-elf/t-rdt.s",
+   "../sim/testsuite/d10v-elf/t-rep.s",
+   "../sim/testsuite/d10v-elf/t-rie-xx.s",
+   "../sim/testsuite/d10v-elf/t-rte.s",
+   "../sim/testsuite/d10v-elf/t-sac.s",
+   "../sim/testsuite/d10v-elf/t-sachi.s",
+   "../sim/testsuite/d10v-elf/t-sadd.s",
+   "../sim/testsuite/d10v-elf/t-slae.s",
+   "../sim/testsuite/d10v-elf/t-sp.s",
+   "../sim/testsuite/d10v-elf/t-sub.s",
+   "../sim/testsuite/d10v-elf/t-sub2w.s",
+   "../sim/testsuite/d10v-elf/t-subi.s",
+   "../sim/testsuite/d10v-elf/t-trap.s",
+   "../sim/testsuite/frv-elf/cache.s",
+   "../sim/testsuite/frv-elf/exit47.s",
+   "../sim/testsuite/frv-elf/grloop.s",
+   "../sim/testsuite/frv-elf/hello.s",
+   "../sim/testsuite/frv-elf/loop.s",
+   "../sim/testsuite/m32r-elf/exit47.s",
+   "../sim/testsuite/m32r-elf/hello.s",
+   "../sim/testsuite/m32r-elf/loop.s",
+   "../sim/testsuite/sim/cris/hw/rv-n-cris/quit.s",
+   "../sim/testsuite/sim/h8300/addb.s",
+   "../sim/testsuite/sim/h8300/addl.s",
+   "../sim/testsuite/sim/h8300/adds.s",
+   "../sim/testsuite/sim/h8300/addw.s",
+   "../sim/testsuite/sim/h8300/addx.s",
+   "../sim/testsuite/sim/h8300/andb.s",
+   "../sim/testsuite/sim/h8300/andl.s",
+   "../sim/testsuite/sim/h8300/andw.s",
+   "../sim/testsuite/sim/h8300/band.s",
+   "../sim/testsuite/sim/h8300/bfld.s",
+   "../sim/testsuite/sim/h8300/biand.s",
+   "../sim/testsuite/sim/h8300/bra.s",
+   "../sim/testsuite/sim/h8300/brabc.s",
+   "../sim/testsuite/sim/h8300/bset.s",
+   "../sim/testsuite/sim/h8300/cmpb.s",
+   "../sim/testsuite/sim/h8300/cmpl.s",
+   "../sim/testsuite/sim/h8300/cmpw.s",
+   "../sim/testsuite/sim/h8300/daa.s",
+   "../sim/testsuite/sim/h8300/das.s",
+   "../sim/testsuite/sim/h8300/dec.s",
+   "../sim/testsuite/sim/h8300/div.s",
+   "../sim/testsuite/sim/h8300/extl.s",
+   "../sim/testsuite/sim/h8300/extw.s",
+   "../sim/testsuite/sim/h8300/inc.s",
+   "../sim/testsuite/sim/h8300/jmp.s",
+   "../sim/testsuite/sim/h8300/ldc.s",
+   "../sim/testsuite/sim/h8300/ldm.s",
+   "../sim/testsuite/sim/h8300/mac.s",
+   "../sim/testsuite/sim/h8300/mova.s",
+   "../sim/testsuite/sim/h8300/movb.s",
+   "../sim/testsuite/sim/h8300/movl.s",
+   "../sim/testsuite/sim/h8300/movmd.s",
+   "../sim/testsuite/sim/h8300/movsd.s",
+   "../sim/testsuite/sim/h8300/movw.s",
+   "../sim/testsuite/sim/h8300/mul.s",
+   "../sim/testsuite/sim/h8300/neg.s",
+   "../sim/testsuite/sim/h8300/nop.s",
+   "../sim/testsuite/sim/h8300/not.s",
+   "../sim/testsuite/sim/h8300/orb.s",
+   "../sim/testsuite/sim/h8300/orl.s",
+   "../sim/testsuite/sim/h8300/orw.s",
+   "../sim/testsuite/sim/h8300/rotl.s",
+   "../sim/testsuite/sim/h8300/rotr.s",
+   "../sim/testsuite/sim/h8300/rotxl.s",
+   "../sim/testsuite/sim/h8300/rotxr.s",
+   "../sim/testsuite/sim/h8300/shal.s",
+   "../sim/testsuite/sim/h8300/shar.s",
+   "../sim/testsuite/sim/h8300/shll.s",
+   "../sim/testsuite/sim/h8300/shlr.s",
+   "../sim/testsuite/sim/h8300/stack.s",
+   "../sim/testsuite/sim/h8300/stc.s",
+   "../sim/testsuite/sim/h8300/subb.s",
+   "../sim/testsuite/sim/h8300/subl.s",
+   "../sim/testsuite/sim/h8300/subs.s",
+   "../sim/testsuite/sim/h8300/subw.s",
+   "../sim/testsuite/sim/h8300/subx.s",
+   "../sim/testsuite/sim/h8300/tas.s",
+   "../sim/testsuite/sim/h8300/xorb.s",
+   "../sim/testsuite/sim/h8300/xorl.s",
+   "../sim/testsuite/sim/h8300/xorw.s",
+   "../sim/testsuite/sim/mips/fpu64-ps-sb1.s",
+   "../sim/testsuite/sim/mips/fpu64-ps.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-1.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-2.s",
+   "../sim/testsuite/sim/mips/hilo-hazard-3.s",
+   "../sim/testsuite/sim/mips/mdmx-ob-sb1.s",
+   "../sim/testsuite/sim/mips/mdmx-ob.s",
+   "../sim/testsuite/sim/mips/mips32-dsp.s",
+   "../sim/testsuite/sim/mips/mips32-dsp2.s",
+   "../sim/testsuite/sim/mips/sanity.s",
+   "../sim/testsuite/sim/sh/add.s",
+   "../sim/testsuite/sim/sh/and.s",
+   "../sim/testsuite/sim/sh/bandor.s",
+   "../sim/testsuite/sim/sh/bandornot.s",
+   "../sim/testsuite/sim/sh/bclr.s",
+   "../sim/testsuite/sim/sh/bld.s",
+   "../sim/testsuite/sim/sh/bldnot.s",
+   "../sim/testsuite/sim/sh/bset.s",
+   "../sim/testsuite/sim/sh/bst.s",
+   "../sim/testsuite/sim/sh/bxor.s",
+   "../sim/testsuite/sim/sh/clip.s",
+   "../sim/testsuite/sim/sh/div.s",
+   "../sim/testsuite/sim/sh/dmxy.s",
+   "../sim/testsuite/sim/sh/fabs.s",
+   "../sim/testsuite/sim/sh/fadd.s",
+   "../sim/testsuite/sim/sh/fail.s",
+   "../sim/testsuite/sim/sh/fcmpeq.s",
+   "../sim/testsuite/sim/sh/fcmpgt.s",
+   "../sim/testsuite/sim/sh/fcnvds.s",
+   "../sim/testsuite/sim/sh/fcnvsd.s",
+   "../sim/testsuite/sim/sh/fdiv.s",
+   "../sim/testsuite/sim/sh/fipr.s",
+   "../sim/testsuite/sim/sh/fldi0.s",
+   "../sim/testsuite/sim/sh/fldi1.s",
+   "../sim/testsuite/sim/sh/flds.s",
+   "../sim/testsuite/sim/sh/float.s",
+   "../sim/testsuite/sim/sh/fmac.s",
+   "../sim/testsuite/sim/sh/fmov.s",
+   "../sim/testsuite/sim/sh/fmul.s",
+   "../sim/testsuite/sim/sh/fneg.s",
+   "../sim/testsuite/sim/sh/fpchg.s",
+   "../sim/testsuite/sim/sh/frchg.s",
+   "../sim/testsuite/sim/sh/fsca.s",
+   "../sim/testsuite/sim/sh/fschg.s",
+   "../sim/testsuite/sim/sh/fsqrt.s",
+   "../sim/testsuite/sim/sh/fsrra.s",
+   "../sim/testsuite/sim/sh/fsub.s",
+   "../sim/testsuite/sim/sh/ftrc.s",
+   "../sim/testsuite/sim/sh/ldrc.s",
+   "../sim/testsuite/sim/sh/loop.s",
+   "../sim/testsuite/sim/sh/macl.s",
+   "../sim/testsuite/sim/sh/macw.s",
+   "../sim/testsuite/sim/sh/mov.s",
+   "../sim/testsuite/sim/sh/movi.s",
+   "../sim/testsuite/sim/sh/movli.s",
+   "../sim/testsuite/sim/sh/movua.s",
+   "../sim/testsuite/sim/sh/movxy.s",
+   "../sim/testsuite/sim/sh/mulr.s",
+   "../sim/testsuite/sim/sh/pabs.s",
+   "../sim/testsuite/sim/sh/padd.s",
+   "../sim/testsuite/sim/sh/paddc.s",
+   "../sim/testsuite/sim/sh/pand.s",
+   "../sim/testsuite/sim/sh/pass.s",
+   "../sim/testsuite/sim/sh/pclr.s",
+   "../sim/testsuite/sim/sh/pdec.s",
+   "../sim/testsuite/sim/sh/pdmsb.s",
+   "../sim/testsuite/sim/sh/pinc.s",
+   "../sim/testsuite/sim/sh/pmuls.s",
+   "../sim/testsuite/sim/sh/prnd.s",
+   "../sim/testsuite/sim/sh/pshai.s",
+   "../sim/testsuite/sim/sh/pshar.s",
+   "../sim/testsuite/sim/sh/pshli.s",
+   "../sim/testsuite/sim/sh/pshlr.s",
+   "../sim/testsuite/sim/sh/psub.s",
+   "../sim/testsuite/sim/sh/pswap.s",
+   "../sim/testsuite/sim/sh/pushpop.s",
+   "../sim/testsuite/sim/sh/resbank.s",
+   "../sim/testsuite/sim/sh/sett.s",
+   "../sim/testsuite/sim/sh/shll.s",
+   "../sim/testsuite/sim/sh/shll16.s",
+   "../sim/testsuite/sim/sh/shll2.s",
+   "../sim/testsuite/sim/sh/shll8.s",
+   "../sim/testsuite/sim/sh/shlr.s",
+   "../sim/testsuite/sim/sh/shlr16.s",
+   "../sim/testsuite/sim/sh/shlr2.s",
+   "../sim/testsuite/sim/sh/shlr8.s",
+   "../sim/testsuite/sim/sh/swap.s",
+   "../sim/testsuite/sim/sh64/misc/fr-dr.s",
+   # .inc files.  These are usually assembly or C files...
+   "testsuite/gdb.asm/alpha.inc",
+   "testsuite/gdb.asm/arm.inc",
+   "testsuite/gdb.asm/common.inc",
+   "testsuite/gdb.asm/empty.inc",
+   "testsuite/gdb.asm/frv.inc",
+   "testsuite/gdb.asm/h8300.inc",
+   "testsuite/gdb.asm/i386.inc",
+   "testsuite/gdb.asm/ia64.inc",
+   "testsuite/gdb.asm/iq2000.inc",
+   "testsuite/gdb.asm/m32c.inc",
+   "testsuite/gdb.asm/m32r-linux.inc",
+   "testsuite/gdb.asm/m32r.inc",
+   "testsuite/gdb.asm/m68hc11.inc",
+   "testsuite/gdb.asm/m68k.inc",
+   "testsuite/gdb.asm/mips.inc",
+   "testsuite/gdb.asm/netbsd.inc",
+   "testsuite/gdb.asm/openbsd.inc",
+   "testsuite/gdb.asm/pa.inc",
+   "testsuite/gdb.asm/pa64.inc",
+   "testsuite/gdb.asm/powerpc.inc",
+   "testsuite/gdb.asm/powerpc64.inc",
+   "testsuite/gdb.asm/s390.inc",
+   "testsuite/gdb.asm/s390x.inc",
+   "testsuite/gdb.asm/sh.inc",
+   "testsuite/gdb.asm/sparc.inc",
+   "testsuite/gdb.asm/sparc64.inc",
+   "testsuite/gdb.asm/spu.inc",
+   "testsuite/gdb.asm/v850.inc",
+   "testsuite/gdb.asm/x86_64.inc",
+   "testsuite/gdb.asm/xstormy16.inc",
+   "../sim/testsuite/sim/arm/iwmmxt/testutils.inc",
+   "../sim/testsuite/sim/arm/testutils.inc",
+   "../sim/testsuite/sim/arm/thumb/testutils.inc",
+   "../sim/testsuite/sim/arm/xscale/testutils.inc",
+   "../sim/testsuite/sim/cr16/testutils.inc",
+   "../sim/testsuite/sim/cris/asm/testutils.inc",
+   "../sim/testsuite/sim/cris/hw/rv-n-cris/testutils.inc",
+   "../sim/testsuite/sim/fr30/testutils.inc",
+   "../sim/testsuite/sim/frv/testutils.inc",
+   "../sim/testsuite/sim/h8300/testutils.inc",
+   "../sim/testsuite/sim/m32r/testutils.inc",
+   "../sim/testsuite/sim/sh/testutils.inc",
+   "../sim/testsuite/sim/sh64/compact/testutils.inc",
+   "../sim/testsuite/sim/sh64/media/testutils.inc",
+   "../sim/testsuite/sim/v850/testutils.inc",
+   )
+
+# A mapping between file extensions to their associated Comment object.
+# This dictionary also contains a number of exceptions, based on
+# filename.
+COMMENT_MAP = \
+  {".1" : Comment(start=r'.\"'),
+   ".ac" : Comment(start="dnl", start2="#"),
+   ".ads" : ADA_COMMENT,
+   ".adb" : ADA_COMMENT,
+   ".f" : Comment(start="c"),
+   ".f90" : Comment(start="!"),
+   ".gpr" : ADA_COMMENT,
+   ".inc" : Comment(start="#", start2=";"),
+   ".s" : Comment(start="!"),
+   ".tex" : Comment(start="%"),
+   ".texi" : Comment(start="@c"),
+   ".texinfo" : Comment(start="@c"),
+
+   # Files that use a different way of including the copyright
+   # header...
+   "ada-operator.inc" : Comment(start="/*", stop="*/"),
+   "gdbint.texinfo" : Comment(start='@copying', stop="@end copying"),
+   "annotate.texinfo" : Comment(start='@copying', stop="@end copying",
+                                max_lines=50),
+   "stabs.texinfo" : Comment(start='@copying', stop="@end copying"),
+  }
+
+class NotFound(Exception):
+    pass
+
+class AlreadyDone(Exception):
+    pass
+
+def process_header(src, dst, cdescr):
+    """Read from SRC for up to CDESCR.MAX_LINES until we find a copyright
+    notice.  If found, then write the entire file, with the copyright
+    noticed updated with the current year added.
+
+    Raises NotFound if the copyright notice could not be found or has
+    some inconsistencies.
+
+    Raises AlreadyDone if the copyright notice already includes the current
+    year.
+    """
+    line_count = 0
+    # The start-of-comment marker used for this file.  Only really useful
+    # in the case where comments ends at the end of the line, as this
+    # allows us to know which comment marker to use when breaking long
+    # lines (in the cases where there are more than one.
+    cdescr_start = ""
+
+    while True:
+        # If we still haven't found a copyright line within a certain
+        # number of lines, then give up.
+        if line_count > cdescr.max_lines:
+            raise NotFound("start of Copyright not found")
+
+        line = src.readline()
+        line_count += 1
+        if not line:
+            raise NotFound("start of Copyright not found (EOF)")
+
+        # Is this a copyright line?  If not, then no transformation is
+        # needed.  Write it as is, and continue.
+        if not re.search(r"Copyright\b.*\b(199\d|20\d\d)\b", line):
+            dst.write(line)
+            continue
+
+        # If a start-of-comment marker is needed for every line, try to
+        # figure out which one it is that is being used in this file (most
+        # files only accept one, in which case it's easy - but some accept
+        # two or more...).
+        if cdescr.stop is None:
+            stripped_line = line.lstrip()
+            if stripped_line.startswith(cdescr.start):
+                cdescr_start = cdescr.start
+            elif (cdescr.start2 is not None
+                  and stripped_line.startswith(cdescr.start2)):
+                cdescr_start = cdescr.start2
+            elif cdescr.start in stripped_line:
+                cdescr_start = cdescr.start
+            elif (cdescr.start2 is not None
+                  and cdescr.start2 in stripped_line):
+                cdescr_start = cdescr.start2
+            else:
+                # This can't be a line with a comment, so not the copyright
+                # line we were looking for.  Ignore.
+                continue
+
+        comment = line
+        break
+
+    while not re.search(r"Free\s+Software\s+Foundation", comment):
+        line = src.readline()
+        line_count += 1
+        if not line:
+            raise NotFound("Copyright owner not found (EOF)")
+
+        if cdescr.stop is None:
+            # Expect a new comment marker at the start of each line
+            line = line.lstrip()
+            if not line.startswith(cdescr_start):
+                raise NotFound("Copyright owner not found "
+                               "(end of comment)")
+            comment += " " + line[len(cdescr_start):]
+        else:
+            if cdescr.stop in comment:
+                raise NotFound("Copyright owner not found "
+                               "(end of comment)")
+            comment += line
+
+    # Normalize a bit the copyright string (we preserve the string
+    # up until "Copyright", in order to help preserve any original
+    # alignment.
+    (before, after) = comment.split("Copyright", 1)
+    after = after.replace("\n", " ")
+    after = re.sub("\s+", " ", after)
+    after = after.rstrip()
+
+    # If the copyright year has already been added, the nothing else
+    # to do.
+    if THIS_YEAR in after:
+        raise AlreadyDone
+
+    m = re.match("(.*[0-9]+)(.*)", after)
+    if m is None:
+        raise NotFound("Internal error - cannot split copyright line: "
+                       "`%s'" % comment)
+
+    # Reconstruct the comment line
+    comment = before + "Copyright" + m.group(1) + ', %s' % THIS_YEAR
+    owner_part = m.group(2).lstrip()
+
+    # Max comment len...
+    max_len = 76
+
+    # If we have to break the copyright line into multiple lines,
+    # we want to align all the lines on the "Copyright" keyword.
+    # Create a small "indent" string that we can use for that.
+    if cdescr.stop is None:
+        # The comment marker is needed on every line, so put it at the
+        # start of our "indent" string.
+        indent = cdescr_start + ' ' * (len(before) - len(cdescr_start))
+    else:
+        indent = ' ' * len(before)
+
+    # If the line is too long...
+    while len(comment) > max_len:
+        # Split the line at the first space before max_len.
+        space_index = comment[0:max_len].rfind(' ')
+        if space_index < 0:  # No space in the first max_len characters???
+            # Split at the first space, then...
+            space_index = comment.find(' ')
+        if space_index < 0:
+            # Still no space found.  This is extremely unlikely, but
+            # just pretend there is one at the end of the string.
+            space_index = len(comment)
+
+        # Write the first part of the string up until the space
+        # we selected to break our line.
+        dst.write(comment[:space_index] + '\n')
+
+        # Strip the part of comment that we have finished printing.
+        if space_index < len(comment):
+            comment = comment[space_index + 1:]
+        else:
+            comment = ""
+
+        # Prepend the "indent" string to make sure that we remain
+        # aligned on the "Copyright" word.
+        comment = indent + comment
+
+    # And finally, write the rest of the last line...  We want to write
+    # "Free Software Foundation, Inc" on the same line, so handle this
+    # with extra care.
+    dst.write(comment)
+    if len(comment) + 1 + len (owner_part) > max_len:
+        dst.write('\n' + indent)
+    else:
+        dst.write(' ')
+    dst.write(owner_part + '\n')
+
+def comment_for_filename(filename):
+    """Return the Comment object that best describes the given file.
+    This a smart lookup of the COMMENT_MAP dictionary where we check
+    for filename-based exceptions first, before looking up the comment
+    by filename extension.  """
+    # First, consult the COMMENT_MAP using the filename, in case this
+    # file needs special treatment.
+    basename = os.path.basename(filename)
+    if basename in COMMENT_MAP:
+        return COMMENT_MAP[basename]
+    # Not a special file.  Check the file extension.
+    ext = os.path.splitext(filename)[1]
+    if ext in COMMENT_MAP:
+        return COMMENT_MAP[ext]
+    # Not a know extension either, return None.
+    return None
+
+def process_file(filename):
+    """Processes the given file.
+    """
+    cdescr = comment_for_filename(filename)
+    if cdescr is None:
+        # Either no filename extension, or not an extension that we
+        # know how to handle.
+        return
+
+    dst_filename = filename + '.new'
+    src = open(filename)
+    dst = open(dst_filename, 'w')
+    try:
+        process_header(src, dst, cdescr)
+    except AlreadyDone:
+        print "+++ Already up to date: `%s'." % filename
+        dst.close()
+        os.unlink(dst_filename)
+        if filename in NO_COPYRIGHT:
+            # We expect the search for a copyright header to fail, and
+            # yet we found one...
+            print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
+        return
+    except NotFound as inst:
+        dst.close()
+        os.unlink(dst_filename)
+        if not filename in NO_COPYRIGHT:
+            print "*** \033[31m%s\033[0m: %s" % (filename, inst)
+        return
+
+    if filename in NO_COPYRIGHT:
+        # We expect the search for a copyright header to fail, and
+        # yet we found one...
+        print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
+
+    for line in src:
+        dst.write(line)
+    src.close()
+    dst.close()
+    os.rename(dst_filename, filename)
+
+if __name__ == "__main__":
+    if not os.path.isfile("doc/gdb.texinfo"):
+        print "Error: This script must be called from the gdb directory."
+    for gdb_dir in ('.', '../sim', '../include/gdb'):
+        for root, dirs, files in os.walk(gdb_dir):
+            for filename in files:
+                fullpath = os.path.join(root, filename)
+                if fullpath.startswith('./'):
+                    fullpath = fullpath[2:]
+                if filename not in EXCLUSION_LIST and fullpath not in BY_HAND:
+                    # Paths that start with './' are ugly, so strip that.
+                    # This also allows us to omit them in the NO_COPYRIGHT
+                    # list...
+                    process_file(fullpath)
+    print
+    print "\033[32mREMINDER: The following files must be updated by hand." \
+          "\033[0m"
+    for filename in BY_HAND:
+        print "  ", filename
+
diff --git a/gdb/copyright.sh b/gdb/copyright.sh
index 399ce3a..13f860a 100644
--- a/gdb/copyright.sh
+++ b/gdb/copyright.sh
@@ -44,7 +44,8 @@
 #  tex (%)
 #  *.defs as C
 #   man
-# So these need to be done by hand, as needed
+# So these need to be done either by hand, as needed, or by the copyright.py
+# script.
 byhand="
 *.s
 *.f
@@ -56,6 +57,10 @@ byhand="
 *.tex
 *.defs
 *.1
+*.ads
+*.adb
+*.gpr
+*.inc
 "
 
 # Files which should not be modified, either because they are
@@ -160,4 +165,6 @@ cat >> copytmp.el <<EOF
 (kill-emacs)
 EOF
 
-exec $EMACS --no-site-file -q -l ./copytmp.el
+$EMACS --no-site-file -q -l ./copytmp.el
+
+python $dir/copyright.py

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-05  5:56 [RFA] New script copyright.py Joel Brobecker
  2011-01-05 11:37 ` Eli Zaretskii
  2011-01-05 16:12 ` Tom Tromey
@ 2011-01-06 18:25 ` Alfred M. Szmidt
  2011-01-07  4:07   ` Joel Brobecker
  2 siblings, 1 reply; 7+ messages in thread
From: Alfred M. Szmidt @ 2011-01-06 18:25 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches, brobecker

   The end-of-year procedure still remains more or less the same, since
   the new script is called from the old one.  Eventually, I think it would
   be nice to see if we could transition progressively to the new script,
   until it handles all files for us.  The reason for it is that I believe
   this script can be made solid enough to handle all situations, and avoid
   a dependency on a script that we do not control.  But that's for another
   day...

Is there a particular reason why one can't use the update-copyright
script in gnulib?  It already handles all of the corner cases, and
werido situations that can occur.

Attached update-copyright for reference.

===File ~/gnulib/build-aux/update-copyright=================
eval '(exit $?0)' && eval 'exec perl -wS -0777 -pi "$0" ${1+"$@"}'
  & eval 'exec perl -wS -0777 -pi "$0" $argv:q'
    if 0;
# Update an FSF copyright year list to include the current year.

my $VERSION = '2009-12-28.11:09'; # UTC

# Copyright (C) 2009-2011 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Written by Jim Meyering and Joel E. Denny

# The arguments to this script should be names of files that contain FSF
# copyright statements to be updated.  For example, you might wish to
# use the update-copyright target rule in maint.mk from gnulib's
# maintainer-makefile module.
#
# Iff an FSF copyright statement is recognized in a file and the final
# year is not the current year, then the statement is updated for the
# new year and it is reformatted to:
#
#   1. Fit within 72 columns.
#   2. Convert 2-digit years to 4-digit years by prepending "19".
#   3. Expand copyright year intervals.  (See "Environment variables"
#      below.)
#
# A warning is printed for every file for which no FSF copyright
# statement is recognized.
#
# Each file's FSF copyright statement must be formated correctly in
# order to be recognized.  For example, each of these is fine:
#
#   Copyright @copyright{} 1990-2005, 2007-2009 Free Software
#   Foundation, Inc.
#
#   # Copyright (C) 1990-2005, 2007-2009 Free Software
#   # Foundation, Inc.
#
#   /*
#    * Copyright &copy; 90,2005,2007-2009
#    * Free Software Foundation, Inc.
#    */
#
# However, the following format is not recognized because the line
# prefix changes after the first line:
#
#   ## Copyright (C) 1990-2005, 2007-2009 Free Software
#   #  Foundation, Inc.
#
# The following copyright statement is not recognized because the
# copyright holder is not the FSF:
#
#   Copyright (C) 1990-2005, 2007-2009 Acme, Inc.
#
# However, any correctly formatted FSF copyright statement following
# either of the previous two copyright statements would be recognized.
#
# The exact conditions that a file's FSF copyright statement must meet
# to be recognized are:
#
#   1. It is the first FSF copyright statement that meets all of the
#      following conditions.  Subsequent FSF copyright statements are
#      ignored.
#   2. Its format is "Copyright (C)", then a list of copyright years,
#      and then the name of the copyright holder, which is "Free
#      Software Foundation, Inc.".
#   3. The "(C)" takes one of the following forms or is omitted
#      entirely:
#
#        A. (C)
#        B. (c)
#        C. @copyright{}
#        D. &copy;
#
#   4. The "Copyright" appears at the beginning of a line except that it
#      may be prefixed by any sequence (e.g., a comment) of no more than
#      5 characters.
#   5. Iff such a prefix is present, the same prefix appears at the
#      beginning of each remaining line within the FSF copyright
#      statement.  There is one exception in order to support C-style
#      comments: if the first line's prefix contains nothing but
#      whitespace surrounding a "/*", then the prefix for all subsequent
#      lines is the same as the first line's prefix except with each of
#      "/" and possibly "*" replaced by a " ".  The replacement of "*"
#      by " " is consistent throughout all subsequent lines.
#   6. Blank lines, even if preceded by the prefix, do not appear
#      within the FSF copyright statement.
#   7. Each copyright year is 2 or 4 digits, and years are separated by
#      commas or dashes.  Whitespace may appear after commas.
#
# Environment variables:
#
#   1. If UPDATE_COPYRIGHT_FORCE=1, a recognized FSF copyright statement
#      is reformatted even if it does not need updating for the new
#      year.  If unset or set to 0, only updated FSF copyright
#      statements are reformatted.
#   2. If UPDATE_COPYRIGHT_USE_INTERVALS=1, every series of consecutive
#      copyright years (such as 90, 1991, 1992-2007, 2008) in a
#      reformatted FSF copyright statement is collapsed to a single
#      interval (such as 1990-2008).  If unset or set to 0, all existing
#      copyright year intervals in a reformatted FSF copyright statement
#      are expanded instead.
#   3. For testing purposes, you can set the assumed current year in
#      UPDATE_COPYRIGHT_YEAR.
#   4. The default maximum line length for a copyright line is 72.
#      Set UPDATE_COPYRIGHT_MAX_LINE_LENGTH to use a different length.

use strict;
use warnings;

my $copyright_re = 'Copyright';
my $circle_c_re = '(?:\([cC]\)|@copyright{}|&copy;)';
my $holder = 'Free Software Foundation, Inc.';
my $prefix_max = 5;
my $margin = $ENV{UPDATE_COPYRIGHT_MAX_LINE_LENGTH};
!$margin || $margin !~ m/^\d+$/
  and $margin = 72;

my $tab_width = 8;

my $this_year = $ENV{UPDATE_COPYRIGHT_YEAR};
if (!$this_year || $this_year !~ m/^\d{4}$/)
  {
    my ($sec, $min, $hour, $mday, $month, $year) = localtime (time ());
    $this_year = $year + 1900;
  }

# Unless the file consistently uses "\r\n" as the EOL, use "\n" instead.
my $eol = /(?:^|[^\r])\n/ ? "\n" : "\r\n";

my $leading;
my $prefix;
my $ws_re;
my $stmt_re;
while (/(^|\n)(.{0,$prefix_max})$copyright_re/g)
  {
    $leading = "$1$2";
    $prefix = $2;
    if ($prefix =~ /^(\s*\/)\*(\s*)$/)
      {
        $prefix =~ s,/, ,;
        my $prefix_ws = $prefix;
        $prefix_ws =~ s/\*/ /; # Only whitespace.
        if (/\G(?:[^*\n]|\*[^\/\n])*\*?\n$prefix_ws/)
          {
            $prefix = $prefix_ws;
          }
      }
    $ws_re = '[ \t\r\f]'; # \s without \n
    $ws_re =
      "(?:$ws_re*(?:$ws_re|\\n" . quotemeta($prefix) . ")$ws_re*)";
    my $holder_re = $holder;
    $holder_re =~ s/\s/$ws_re/g;
    my $stmt_remainder_re =
      "(?:$ws_re$circle_c_re)?"
      . "$ws_re(?:(?:\\d\\d)?\\d\\d(?:,$ws_re?|-))*"
      . "((?:\\d\\d)?\\d\\d)$ws_re$holder_re";
    if (/\G$stmt_remainder_re/)
      {
        $stmt_re =
          quotemeta($leading) . "($copyright_re$stmt_remainder_re)";
        last;
      }
  }
if (defined $stmt_re)
  {
    /$stmt_re/ or die; # Should never die.
    my $stmt = $1;
    my $final_year_orig = $2;

    # Handle two-digit year numbers like "98" and "99".
    my $final_year = $final_year_orig;
    $final_year <= 99
      and $final_year += 1900;

    if ($final_year != $this_year)
      {
        # Update the year.
        $stmt =~ s/$final_year_orig/$final_year, $this_year/;
      }
    if ($final_year != $this_year || $ENV{'UPDATE_COPYRIGHT_FORCE'})
      {
        # Normalize all whitespace including newline-prefix sequences.
        $stmt =~ s/$ws_re/ /g;

        # Put spaces after commas.
        $stmt =~ s/, ?/, /g;

        # Convert 2-digit to 4-digit years.
        $stmt =~ s/(\b\d\d\b)/19$1/g;

        # Make the use of intervals consistent.
        if (!$ENV{UPDATE_COPYRIGHT_USE_INTERVALS})
          {
            $stmt =~ s/(\d{4})-(\d{4})/join(', ', $1..$2)/eg;
          }
        else
          {
            $stmt =~
              s/
                (\d{4})
                (?:
                  (,\ |-)
                  ((??{
                    if    ($2 eq '-') { '\d{4}'; }
                    elsif (!$3)       { $1 + 1;  }
                    else              { $3 + 1;  }
                  }))
                )+
              /$1-$3/gx;
          }

        # Format within margin.
        my $stmt_wrapped;
        my $text_margin = $margin - length($prefix);
        if ($prefix =~ /^(\t+)/)
          {
            $text_margin -= length($1) * ($tab_width - 1);
          }
        while (length $stmt)
          {
            if (($stmt =~ s/^(.{1,$text_margin})(?: |$)//)
                || ($stmt =~ s/^([\S]+)(?: |$)//))
              {
                my $line = $1;
                $stmt_wrapped .= $stmt_wrapped ? "$eol$prefix" : $leading;
                $stmt_wrapped .= $line;
              }
            else
              {
                # Should be unreachable, but we don't want an infinite
                # loop if it can be reached.
                die;
              }
          }

        # Replace the old copyright statement.
        s/$stmt_re/$stmt_wrapped/;
      }
  }
else
  {
    print STDERR "$ARGV: warning: FSF copyright statement not found\n";
  }

# Local variables:
# mode: perl
# indent-tabs-mode: nil
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "my $VERSION = '"
# time-stamp-format: "%:y-%02m-%02d.%02H:%02M"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "'; # UTC"
# End:
============================================================


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] New script copyright.py
  2011-01-06 18:25 ` Alfred M. Szmidt
@ 2011-01-07  4:07   ` Joel Brobecker
  0 siblings, 0 replies; 7+ messages in thread
From: Joel Brobecker @ 2011-01-07  4:07 UTC (permalink / raw)
  To: Alfred M. Szmidt; +Cc: gdb-patches

> Is there a particular reason why one can't use the update-copyright
> script in gnulib?  It already handles all of the corner cases, and
> werido situations that can occur.

Thanks for pointing it out, it looks like an interesting script indeed.
I wish I had known about it then (google at the time did not help find
any such script). I will put that script on my TODO list to see if
we can integrate it.  Kudos to the authors for documenting the script
usage so nicely.

-- 
Joel


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-01-07  4:07 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-05  5:56 [RFA] New script copyright.py Joel Brobecker
2011-01-05 11:37 ` Eli Zaretskii
2011-01-06  4:39   ` Joel Brobecker
2011-01-05 16:12 ` Tom Tromey
2011-01-06  6:33   ` Joel Brobecker
2011-01-06 18:25 ` Alfred M. Szmidt
2011-01-07  4:07   ` Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox