xref: /dragonfly/contrib/gdb-7/gdb/copyright.py (revision fb151170)
1#! /usr/bin/env python
2
3"""copyright.py
4
5This script updates most of the files that are not already handled
6by copyright.sh.  It must be run from the gdb/ subdirectory of the
7GDB source tree.
8
9"""
10
11import datetime
12import re
13import os
14import os.path
15
16class Comment(object):
17    """A class describing comment.
18
19    ATTRIBUTES
20      start:  A string describing how comments are started.
21      stop:   A string describing how comments end.  If None, then
22              a comment ends at the end of the line.
23      start2: Some files accept more than 1 kind of comment.
24              For those that do, this is the alternative form.
25              For now, it is assumed that if start2 is not None,
26              then stop is None (thus no stop2 attribute).
27    """
28    def __init__(self, start, stop=None, start2=None, max_lines=30):
29        """The "Copyright" keyword should be within MAX_LINES lines
30        from the start of the file."""
31        self.start = start
32        self.stop = stop
33        self.start2 = start2
34        self.max_lines = max_lines
35
36# The Comment object for Ada code (and GPR files).
37ADA_COMMENT = Comment(start="--")
38
39THIS_YEAR = str(datetime.date.today().year)
40
41# Files which should not be modified, either because they are
42# generated, non-FSF, or otherwise special (e.g. license text,
43# or test cases which must be sensitive to line numbering).
44EXCLUSION_LIST = (
45  "COPYING", "COPYING.LIB", "CVS", "configure", "copying.c", "gdbarch.c",
46  "gdbarch.h", "fdl.texi", "gpl.texi", "gdbtk", "gdb.gdbtk", "osf-share",
47  "aclocal.m4", "step-line.inp", "step-line.c",
48  )
49
50# Files that are too different from the rest to be processed automatically.
51BY_HAND = ['../sim/ppc/psim.texinfo']
52
53# Files for which we know that they do not have a copyright header.
54# Ideally, this list should be empty (but it may not be possible to
55# add a copyright header in some of them).
56NO_COPYRIGHT = (
57   # Configure files.  We should fix those, one day.
58   "testsuite/gdb.cell/configure.ac", "testsuite/gdb.hp/configure.ac",
59   "testsuite/gdb.hp/gdb.aCC/configure.ac",
60   "testsuite/gdb.hp/gdb.base-hp/configure.ac",
61   "testsuite/gdb.hp/gdb.compat/configure.ac",
62   "testsuite/gdb.hp/gdb.defects/configure.ac",
63   "testsuite/gdb.hp/gdb.objdbg/configure.ac",
64   "testsuite/gdb.stabs/configure.ac",
65   "../sim/arm/configure.ac", "../sim/avr/configure.ac",
66   "../sim/common/configure.ac", "../sim/configure.ac",
67   "../sim/cr16/configure.ac", "../sim/cris/configure.ac",
68   "../sim/d10v/configure.ac", "../sim/erc32/configure.ac",
69   "../sim/frv/configure.ac", "../sim/h8300/configure.ac",
70   "../sim/igen/configure.ac", "../sim/iq2000/configure.ac",
71   "../sim/lm32/configure.ac", "../sim/m32r/configure.ac",
72   "../sim/m68hc11/configure.ac", "../sim/mcore/configure.ac",
73   "../sim/microblaze/configure.ac", "../sim/mips/configure.ac",
74   "../sim/mn10300/configure.ac", "../sim/moxie/configure.ac",
75   "../sim/ppc/configure.ac", "../sim/sh/configure.ac",
76   "../sim/sh64/configure.ac", "../sim/testsuite/configure.ac",
77   "../sim/testsuite/d10v-elf/configure.ac",
78   "../sim/testsuite/frv-elf/configure.ac",
79   "../sim/testsuite/m32r-elf/configure.ac",
80   "../sim/testsuite/mips64el-elf/configure.ac", "../sim/v850/configure.ac",
81   # Assembly files.  It's not certain that we can add a copyright
82   # header in a way that works for all platforms supported by the
83   # testcase...
84   "testsuite/gdb.arch/pa-nullify.s", "testsuite/gdb.arch/pa64-nullify.s",
85   "testsuite/gdb.asm/asmsrc1.s", "testsuite/gdb.asm/asmsrc2.s",
86   "testsuite/gdb.disasm/am33.s", "testsuite/gdb.disasm/h8300s.s",
87   "testsuite/gdb.disasm/hppa.s", "testsuite/gdb.disasm/mn10200.s",
88   "testsuite/gdb.disasm/mn10300.s", "testsuite/gdb.disasm/sh3.s",
89   "testsuite/gdb.disasm/t01_mov.s", "testsuite/gdb.disasm/t02_mova.s",
90   "testsuite/gdb.disasm/t03_add.s", "testsuite/gdb.disasm/t04_sub.s",
91   "testsuite/gdb.disasm/t05_cmp.s", "testsuite/gdb.disasm/t06_ari2.s",
92   "testsuite/gdb.disasm/t07_ari3.s", "testsuite/gdb.disasm/t08_or.s",
93   "testsuite/gdb.disasm/t09_xor.s", "testsuite/gdb.disasm/t10_and.s",
94   "testsuite/gdb.disasm/t11_logs.s", "testsuite/gdb.disasm/t12_bit.s",
95   "testsuite/gdb.disasm/t13_otr.s", "testsuite/gdb.hp/gdb.base-hp/reg-pa64.s",
96   "testsuite/gdb.hp/gdb.base-hp/reg.s",
97   "../sim/testsuite/d10v-elf/exit47.s",
98   "../sim/testsuite/d10v-elf/hello.s",
99   "../sim/testsuite/d10v-elf/loop.s",
100   "../sim/testsuite/d10v-elf/t-ae-ld-d.s",
101   "../sim/testsuite/d10v-elf/t-ae-ld-i.s",
102   "../sim/testsuite/d10v-elf/t-ae-ld-id.s",
103   "../sim/testsuite/d10v-elf/t-ae-ld-im.s",
104   "../sim/testsuite/d10v-elf/t-ae-ld-ip.s",
105   "../sim/testsuite/d10v-elf/t-ae-ld2w-d.s",
106   "../sim/testsuite/d10v-elf/t-ae-ld2w-i.s",
107   "../sim/testsuite/d10v-elf/t-ae-ld2w-id.s",
108   "../sim/testsuite/d10v-elf/t-ae-ld2w-im.s",
109   "../sim/testsuite/d10v-elf/t-ae-ld2w-ip.s",
110   "../sim/testsuite/d10v-elf/t-ae-st-d.s",
111   "../sim/testsuite/d10v-elf/t-ae-st-i.s",
112   "../sim/testsuite/d10v-elf/t-ae-st-id.s",
113   "../sim/testsuite/d10v-elf/t-ae-st-im.s",
114   "../sim/testsuite/d10v-elf/t-ae-st-ip.s",
115   "../sim/testsuite/d10v-elf/t-ae-st-is.s",
116   "../sim/testsuite/d10v-elf/t-ae-st2w-d.s",
117   "../sim/testsuite/d10v-elf/t-ae-st2w-i.s",
118   "../sim/testsuite/d10v-elf/t-ae-st2w-id.s",
119   "../sim/testsuite/d10v-elf/t-ae-st2w-im.s",
120   "../sim/testsuite/d10v-elf/t-ae-st2w-ip.s",
121   "../sim/testsuite/d10v-elf/t-ae-st2w-is.s",
122   "../sim/testsuite/d10v-elf/t-dbt.s",
123   "../sim/testsuite/d10v-elf/t-ld-st.s",
124   "../sim/testsuite/d10v-elf/t-mac.s",
125   "../sim/testsuite/d10v-elf/t-mod-ld-pre.s",
126   "../sim/testsuite/d10v-elf/t-msbu.s",
127   "../sim/testsuite/d10v-elf/t-mulxu.s",
128   "../sim/testsuite/d10v-elf/t-mvtac.s",
129   "../sim/testsuite/d10v-elf/t-mvtc.s",
130   "../sim/testsuite/d10v-elf/t-rac.s",
131   "../sim/testsuite/d10v-elf/t-rachi.s",
132   "../sim/testsuite/d10v-elf/t-rdt.s",
133   "../sim/testsuite/d10v-elf/t-rep.s",
134   "../sim/testsuite/d10v-elf/t-rie-xx.s",
135   "../sim/testsuite/d10v-elf/t-rte.s",
136   "../sim/testsuite/d10v-elf/t-sac.s",
137   "../sim/testsuite/d10v-elf/t-sachi.s",
138   "../sim/testsuite/d10v-elf/t-sadd.s",
139   "../sim/testsuite/d10v-elf/t-slae.s",
140   "../sim/testsuite/d10v-elf/t-sp.s",
141   "../sim/testsuite/d10v-elf/t-sub.s",
142   "../sim/testsuite/d10v-elf/t-sub2w.s",
143   "../sim/testsuite/d10v-elf/t-subi.s",
144   "../sim/testsuite/d10v-elf/t-trap.s",
145   "../sim/testsuite/frv-elf/cache.s",
146   "../sim/testsuite/frv-elf/exit47.s",
147   "../sim/testsuite/frv-elf/grloop.s",
148   "../sim/testsuite/frv-elf/hello.s",
149   "../sim/testsuite/frv-elf/loop.s",
150   "../sim/testsuite/m32r-elf/exit47.s",
151   "../sim/testsuite/m32r-elf/hello.s",
152   "../sim/testsuite/m32r-elf/loop.s",
153   "../sim/testsuite/sim/cris/hw/rv-n-cris/quit.s",
154   "../sim/testsuite/sim/h8300/addb.s",
155   "../sim/testsuite/sim/h8300/addl.s",
156   "../sim/testsuite/sim/h8300/adds.s",
157   "../sim/testsuite/sim/h8300/addw.s",
158   "../sim/testsuite/sim/h8300/addx.s",
159   "../sim/testsuite/sim/h8300/andb.s",
160   "../sim/testsuite/sim/h8300/andl.s",
161   "../sim/testsuite/sim/h8300/andw.s",
162   "../sim/testsuite/sim/h8300/band.s",
163   "../sim/testsuite/sim/h8300/bfld.s",
164   "../sim/testsuite/sim/h8300/biand.s",
165   "../sim/testsuite/sim/h8300/bra.s",
166   "../sim/testsuite/sim/h8300/brabc.s",
167   "../sim/testsuite/sim/h8300/bset.s",
168   "../sim/testsuite/sim/h8300/cmpb.s",
169   "../sim/testsuite/sim/h8300/cmpl.s",
170   "../sim/testsuite/sim/h8300/cmpw.s",
171   "../sim/testsuite/sim/h8300/daa.s",
172   "../sim/testsuite/sim/h8300/das.s",
173   "../sim/testsuite/sim/h8300/dec.s",
174   "../sim/testsuite/sim/h8300/div.s",
175   "../sim/testsuite/sim/h8300/extl.s",
176   "../sim/testsuite/sim/h8300/extw.s",
177   "../sim/testsuite/sim/h8300/inc.s",
178   "../sim/testsuite/sim/h8300/jmp.s",
179   "../sim/testsuite/sim/h8300/ldc.s",
180   "../sim/testsuite/sim/h8300/ldm.s",
181   "../sim/testsuite/sim/h8300/mac.s",
182   "../sim/testsuite/sim/h8300/mova.s",
183   "../sim/testsuite/sim/h8300/movb.s",
184   "../sim/testsuite/sim/h8300/movl.s",
185   "../sim/testsuite/sim/h8300/movmd.s",
186   "../sim/testsuite/sim/h8300/movsd.s",
187   "../sim/testsuite/sim/h8300/movw.s",
188   "../sim/testsuite/sim/h8300/mul.s",
189   "../sim/testsuite/sim/h8300/neg.s",
190   "../sim/testsuite/sim/h8300/nop.s",
191   "../sim/testsuite/sim/h8300/not.s",
192   "../sim/testsuite/sim/h8300/orb.s",
193   "../sim/testsuite/sim/h8300/orl.s",
194   "../sim/testsuite/sim/h8300/orw.s",
195   "../sim/testsuite/sim/h8300/rotl.s",
196   "../sim/testsuite/sim/h8300/rotr.s",
197   "../sim/testsuite/sim/h8300/rotxl.s",
198   "../sim/testsuite/sim/h8300/rotxr.s",
199   "../sim/testsuite/sim/h8300/shal.s",
200   "../sim/testsuite/sim/h8300/shar.s",
201   "../sim/testsuite/sim/h8300/shll.s",
202   "../sim/testsuite/sim/h8300/shlr.s",
203   "../sim/testsuite/sim/h8300/stack.s",
204   "../sim/testsuite/sim/h8300/stc.s",
205   "../sim/testsuite/sim/h8300/subb.s",
206   "../sim/testsuite/sim/h8300/subl.s",
207   "../sim/testsuite/sim/h8300/subs.s",
208   "../sim/testsuite/sim/h8300/subw.s",
209   "../sim/testsuite/sim/h8300/subx.s",
210   "../sim/testsuite/sim/h8300/tas.s",
211   "../sim/testsuite/sim/h8300/xorb.s",
212   "../sim/testsuite/sim/h8300/xorl.s",
213   "../sim/testsuite/sim/h8300/xorw.s",
214   "../sim/testsuite/sim/mips/fpu64-ps-sb1.s",
215   "../sim/testsuite/sim/mips/fpu64-ps.s",
216   "../sim/testsuite/sim/mips/hilo-hazard-1.s",
217   "../sim/testsuite/sim/mips/hilo-hazard-2.s",
218   "../sim/testsuite/sim/mips/hilo-hazard-3.s",
219   "../sim/testsuite/sim/mips/mdmx-ob-sb1.s",
220   "../sim/testsuite/sim/mips/mdmx-ob.s",
221   "../sim/testsuite/sim/mips/mips32-dsp.s",
222   "../sim/testsuite/sim/mips/mips32-dsp2.s",
223   "../sim/testsuite/sim/mips/sanity.s",
224   "../sim/testsuite/sim/sh/add.s",
225   "../sim/testsuite/sim/sh/and.s",
226   "../sim/testsuite/sim/sh/bandor.s",
227   "../sim/testsuite/sim/sh/bandornot.s",
228   "../sim/testsuite/sim/sh/bclr.s",
229   "../sim/testsuite/sim/sh/bld.s",
230   "../sim/testsuite/sim/sh/bldnot.s",
231   "../sim/testsuite/sim/sh/bset.s",
232   "../sim/testsuite/sim/sh/bst.s",
233   "../sim/testsuite/sim/sh/bxor.s",
234   "../sim/testsuite/sim/sh/clip.s",
235   "../sim/testsuite/sim/sh/div.s",
236   "../sim/testsuite/sim/sh/dmxy.s",
237   "../sim/testsuite/sim/sh/fabs.s",
238   "../sim/testsuite/sim/sh/fadd.s",
239   "../sim/testsuite/sim/sh/fail.s",
240   "../sim/testsuite/sim/sh/fcmpeq.s",
241   "../sim/testsuite/sim/sh/fcmpgt.s",
242   "../sim/testsuite/sim/sh/fcnvds.s",
243   "../sim/testsuite/sim/sh/fcnvsd.s",
244   "../sim/testsuite/sim/sh/fdiv.s",
245   "../sim/testsuite/sim/sh/fipr.s",
246   "../sim/testsuite/sim/sh/fldi0.s",
247   "../sim/testsuite/sim/sh/fldi1.s",
248   "../sim/testsuite/sim/sh/flds.s",
249   "../sim/testsuite/sim/sh/float.s",
250   "../sim/testsuite/sim/sh/fmac.s",
251   "../sim/testsuite/sim/sh/fmov.s",
252   "../sim/testsuite/sim/sh/fmul.s",
253   "../sim/testsuite/sim/sh/fneg.s",
254   "../sim/testsuite/sim/sh/fpchg.s",
255   "../sim/testsuite/sim/sh/frchg.s",
256   "../sim/testsuite/sim/sh/fsca.s",
257   "../sim/testsuite/sim/sh/fschg.s",
258   "../sim/testsuite/sim/sh/fsqrt.s",
259   "../sim/testsuite/sim/sh/fsrra.s",
260   "../sim/testsuite/sim/sh/fsub.s",
261   "../sim/testsuite/sim/sh/ftrc.s",
262   "../sim/testsuite/sim/sh/ldrc.s",
263   "../sim/testsuite/sim/sh/loop.s",
264   "../sim/testsuite/sim/sh/macl.s",
265   "../sim/testsuite/sim/sh/macw.s",
266   "../sim/testsuite/sim/sh/mov.s",
267   "../sim/testsuite/sim/sh/movi.s",
268   "../sim/testsuite/sim/sh/movli.s",
269   "../sim/testsuite/sim/sh/movua.s",
270   "../sim/testsuite/sim/sh/movxy.s",
271   "../sim/testsuite/sim/sh/mulr.s",
272   "../sim/testsuite/sim/sh/pabs.s",
273   "../sim/testsuite/sim/sh/padd.s",
274   "../sim/testsuite/sim/sh/paddc.s",
275   "../sim/testsuite/sim/sh/pand.s",
276   "../sim/testsuite/sim/sh/pass.s",
277   "../sim/testsuite/sim/sh/pclr.s",
278   "../sim/testsuite/sim/sh/pdec.s",
279   "../sim/testsuite/sim/sh/pdmsb.s",
280   "../sim/testsuite/sim/sh/pinc.s",
281   "../sim/testsuite/sim/sh/pmuls.s",
282   "../sim/testsuite/sim/sh/prnd.s",
283   "../sim/testsuite/sim/sh/pshai.s",
284   "../sim/testsuite/sim/sh/pshar.s",
285   "../sim/testsuite/sim/sh/pshli.s",
286   "../sim/testsuite/sim/sh/pshlr.s",
287   "../sim/testsuite/sim/sh/psub.s",
288   "../sim/testsuite/sim/sh/pswap.s",
289   "../sim/testsuite/sim/sh/pushpop.s",
290   "../sim/testsuite/sim/sh/resbank.s",
291   "../sim/testsuite/sim/sh/sett.s",
292   "../sim/testsuite/sim/sh/shll.s",
293   "../sim/testsuite/sim/sh/shll16.s",
294   "../sim/testsuite/sim/sh/shll2.s",
295   "../sim/testsuite/sim/sh/shll8.s",
296   "../sim/testsuite/sim/sh/shlr.s",
297   "../sim/testsuite/sim/sh/shlr16.s",
298   "../sim/testsuite/sim/sh/shlr2.s",
299   "../sim/testsuite/sim/sh/shlr8.s",
300   "../sim/testsuite/sim/sh/swap.s",
301   "../sim/testsuite/sim/sh64/misc/fr-dr.s",
302   # .inc files.  These are usually assembly or C files...
303   "testsuite/gdb.asm/alpha.inc",
304   "testsuite/gdb.asm/arm.inc",
305   "testsuite/gdb.asm/common.inc",
306   "testsuite/gdb.asm/empty.inc",
307   "testsuite/gdb.asm/frv.inc",
308   "testsuite/gdb.asm/h8300.inc",
309   "testsuite/gdb.asm/i386.inc",
310   "testsuite/gdb.asm/ia64.inc",
311   "testsuite/gdb.asm/iq2000.inc",
312   "testsuite/gdb.asm/m32c.inc",
313   "testsuite/gdb.asm/m32r-linux.inc",
314   "testsuite/gdb.asm/m32r.inc",
315   "testsuite/gdb.asm/m68hc11.inc",
316   "testsuite/gdb.asm/m68k.inc",
317   "testsuite/gdb.asm/mips.inc",
318   "testsuite/gdb.asm/netbsd.inc",
319   "testsuite/gdb.asm/openbsd.inc",
320   "testsuite/gdb.asm/pa.inc",
321   "testsuite/gdb.asm/pa64.inc",
322   "testsuite/gdb.asm/powerpc.inc",
323   "testsuite/gdb.asm/powerpc64.inc",
324   "testsuite/gdb.asm/s390.inc",
325   "testsuite/gdb.asm/s390x.inc",
326   "testsuite/gdb.asm/sh.inc",
327   "testsuite/gdb.asm/sparc.inc",
328   "testsuite/gdb.asm/sparc64.inc",
329   "testsuite/gdb.asm/spu.inc",
330   "testsuite/gdb.asm/v850.inc",
331   "testsuite/gdb.asm/x86_64.inc",
332   "testsuite/gdb.asm/xstormy16.inc",
333   "../sim/testsuite/sim/arm/iwmmxt/testutils.inc",
334   "../sim/testsuite/sim/arm/testutils.inc",
335   "../sim/testsuite/sim/arm/thumb/testutils.inc",
336   "../sim/testsuite/sim/arm/xscale/testutils.inc",
337   "../sim/testsuite/sim/cr16/testutils.inc",
338   "../sim/testsuite/sim/cris/asm/testutils.inc",
339   "../sim/testsuite/sim/cris/hw/rv-n-cris/testutils.inc",
340   "../sim/testsuite/sim/fr30/testutils.inc",
341   "../sim/testsuite/sim/frv/testutils.inc",
342   "../sim/testsuite/sim/h8300/testutils.inc",
343   "../sim/testsuite/sim/m32r/testutils.inc",
344   "../sim/testsuite/sim/sh/testutils.inc",
345   "../sim/testsuite/sim/sh64/compact/testutils.inc",
346   "../sim/testsuite/sim/sh64/media/testutils.inc",
347   "../sim/testsuite/sim/v850/testutils.inc",
348   )
349
350# A mapping between file extensions to their associated Comment object.
351# This dictionary also contains a number of exceptions, based on
352# filename.
353COMMENT_MAP = \
354  {".1" : Comment(start=r'.\"'),
355   ".ac" : Comment(start="dnl", start2="#"),
356   ".ads" : ADA_COMMENT,
357   ".adb" : ADA_COMMENT,
358   ".f" : Comment(start="c"),
359   ".f90" : Comment(start="!"),
360   ".gpr" : ADA_COMMENT,
361   ".inc" : Comment(start="#", start2=";"),
362   ".s" : Comment(start="!"),
363   ".tex" : Comment(start="%"),
364   ".texi" : Comment(start="@c"),
365   ".texinfo" : Comment(start="@c"),
366
367   # Files that use a different way of including the copyright
368   # header...
369   "ada-operator.inc" : Comment(start="/*", stop="*/"),
370   "gdbint.texinfo" : Comment(start='@copying', stop="@end copying"),
371   "annotate.texinfo" : Comment(start='@copying', stop="@end copying",
372                                max_lines=50),
373   "stabs.texinfo" : Comment(start='@copying', stop="@end copying"),
374  }
375
376class NotFound(Exception):
377    pass
378
379class AlreadyDone(Exception):
380    pass
381
382def process_header(src, dst, cdescr):
383    """Read from SRC for up to CDESCR.MAX_LINES until we find a copyright
384    notice.  If found, then write the entire file, with the copyright
385    noticed updated with the current year added.
386
387    Raises NotFound if the copyright notice could not be found or has
388    some inconsistencies.
389
390    Raises AlreadyDone if the copyright notice already includes the current
391    year.
392    """
393    line_count = 0
394    # The start-of-comment marker used for this file.  Only really useful
395    # in the case where comments ends at the end of the line, as this
396    # allows us to know which comment marker to use when breaking long
397    # lines (in the cases where there are more than one.
398    cdescr_start = ""
399
400    while True:
401        # If we still haven't found a copyright line within a certain
402        # number of lines, then give up.
403        if line_count > cdescr.max_lines:
404            raise NotFound("start of Copyright not found")
405
406        line = src.readline()
407        line_count += 1
408        if not line:
409            raise NotFound("start of Copyright not found (EOF)")
410
411        # Is this a copyright line?  If not, then no transformation is
412        # needed.  Write it as is, and continue.
413        if not re.search(r"Copyright\b.*\b(199\d|20\d\d)\b", line):
414            dst.write(line)
415            continue
416
417        # If a start-of-comment marker is needed for every line, try to
418        # figure out which one it is that is being used in this file (most
419        # files only accept one, in which case it's easy - but some accept
420        # two or more...).
421        if cdescr.stop is None:
422            stripped_line = line.lstrip()
423            if stripped_line.startswith(cdescr.start):
424                cdescr_start = cdescr.start
425            elif (cdescr.start2 is not None
426                  and stripped_line.startswith(cdescr.start2)):
427                cdescr_start = cdescr.start2
428            elif cdescr.start in stripped_line:
429                cdescr_start = cdescr.start
430            elif (cdescr.start2 is not None
431                  and cdescr.start2 in stripped_line):
432                cdescr_start = cdescr.start2
433            else:
434                # This can't be a line with a comment, so not the copyright
435                # line we were looking for.  Ignore.
436                continue
437
438        comment = line
439        break
440
441    while not re.search(r"Free\s+Software\s+Foundation", comment):
442        line = src.readline()
443        line_count += 1
444        if not line:
445            raise NotFound("Copyright owner not found (EOF)")
446
447        if cdescr.stop is None:
448            # Expect a new comment marker at the start of each line
449            line = line.lstrip()
450            if not line.startswith(cdescr_start):
451                raise NotFound("Copyright owner not found "
452                               "(end of comment)")
453            comment += " " + line[len(cdescr_start):]
454        else:
455            if cdescr.stop in comment:
456                raise NotFound("Copyright owner not found "
457                               "(end of comment)")
458            comment += line
459
460    # Normalize a bit the copyright string (we preserve the string
461    # up until "Copyright", in order to help preserve any original
462    # alignment.
463    (before, after) = comment.split("Copyright", 1)
464    after = after.replace("\n", " ")
465    after = re.sub("\s+", " ", after)
466    after = after.rstrip()
467
468    # If the copyright year has already been added, the nothing else
469    # to do.
470    if THIS_YEAR in after:
471        raise AlreadyDone
472
473    m = re.match("(.*[0-9]+)(.*)", after)
474    if m is None:
475        raise NotFound("Internal error - cannot split copyright line: "
476                       "`%s'" % comment)
477
478    # Reconstruct the comment line
479    comment = before + "Copyright" + m.group(1) + ', %s' % THIS_YEAR
480    owner_part = m.group(2).lstrip()
481
482    # Max comment len...
483    max_len = 76
484
485    # If we have to break the copyright line into multiple lines,
486    # we want to align all the lines on the "Copyright" keyword.
487    # Create a small "indent" string that we can use for that.
488    if cdescr.stop is None:
489        # The comment marker is needed on every line, so put it at the
490        # start of our "indent" string.
491        indent = cdescr_start + ' ' * (len(before) - len(cdescr_start))
492    else:
493        indent = ' ' * len(before)
494
495    # If the line is too long...
496    while len(comment) > max_len:
497        # Split the line at the first space before max_len.
498        space_index = comment[0:max_len].rfind(' ')
499        if space_index < 0:  # No space in the first max_len characters???
500            # Split at the first space, then...
501            space_index = comment.find(' ')
502        if space_index < 0:
503            # Still no space found.  This is extremely unlikely, but
504            # just pretend there is one at the end of the string.
505            space_index = len(comment)
506
507        # Write the first part of the string up until the space
508        # we selected to break our line.
509        dst.write(comment[:space_index] + '\n')
510
511        # Strip the part of comment that we have finished printing.
512        if space_index < len(comment):
513            comment = comment[space_index + 1:]
514        else:
515            comment = ""
516
517        # Prepend the "indent" string to make sure that we remain
518        # aligned on the "Copyright" word.
519        comment = indent + comment
520
521    # And finally, write the rest of the last line...  We want to write
522    # "Free Software Foundation, Inc" on the same line, so handle this
523    # with extra care.
524    dst.write(comment)
525    if len(comment) + 1 + len (owner_part) > max_len:
526        dst.write('\n' + indent)
527    else:
528        dst.write(' ')
529    dst.write(owner_part + '\n')
530
531def comment_for_filename(filename):
532    """Return the Comment object that best describes the given file.
533    This a smart lookup of the COMMENT_MAP dictionary where we check
534    for filename-based exceptions first, before looking up the comment
535    by filename extension.  """
536    # First, consult the COMMENT_MAP using the filename, in case this
537    # file needs special treatment.
538    basename = os.path.basename(filename)
539    if basename in COMMENT_MAP:
540        return COMMENT_MAP[basename]
541    # Not a special file.  Check the file extension.
542    ext = os.path.splitext(filename)[1]
543    if ext in COMMENT_MAP:
544        return COMMENT_MAP[ext]
545    # Not a know extension either, return None.
546    return None
547
548def process_file(filename):
549    """Processes the given file.
550    """
551    cdescr = comment_for_filename(filename)
552    if cdescr is None:
553        # Either no filename extension, or not an extension that we
554        # know how to handle.
555        return
556
557    dst_filename = filename + '.new'
558    src = open(filename)
559    dst = open(dst_filename, 'w')
560    try:
561        process_header(src, dst, cdescr)
562    except AlreadyDone:
563        print "+++ Already up to date: `%s'." % filename
564        dst.close()
565        os.unlink(dst_filename)
566        if filename in NO_COPYRIGHT:
567            # We expect the search for a copyright header to fail, and
568            # yet we found one...
569            print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
570        return
571    except NotFound as inst:
572        dst.close()
573        os.unlink(dst_filename)
574        if not filename in NO_COPYRIGHT:
575            print "*** \033[31m%s\033[0m: %s" % (filename, inst)
576        return
577
578    if filename in NO_COPYRIGHT:
579        # We expect the search for a copyright header to fail, and
580        # yet we found one...
581        print "Warning: `%s' should not be in NO_COPYRIGHT" % filename
582
583    for line in src:
584        dst.write(line)
585    src.close()
586    dst.close()
587    os.rename(dst_filename, filename)
588
589if __name__ == "__main__":
590    if not os.path.isfile("doc/gdb.texinfo"):
591        print "Error: This script must be called from the gdb directory."
592    for gdb_dir in ('.', '../sim', '../include/gdb'):
593        for root, dirs, files in os.walk(gdb_dir):
594            for filename in files:
595                fullpath = os.path.join(root, filename)
596                if fullpath.startswith('./'):
597                    fullpath = fullpath[2:]
598                if filename not in EXCLUSION_LIST and fullpath not in BY_HAND:
599                    # Paths that start with './' are ugly, so strip that.
600                    # This also allows us to omit them in the NO_COPYRIGHT
601                    # list...
602                    process_file(fullpath)
603    print
604    print "\033[32mREMINDER: The following files must be updated by hand." \
605          "\033[0m"
606    for filename in BY_HAND:
607        print "  ", filename
608
609