Simplify XML parsing a bit.
[platform/upstream/binutils.git] / gdb / copyright.py
1 #! /usr/bin/env python
2
3 """copyright.py
4
5 This script updates most of the files that are not already handled
6 by copyright.sh.  It must be run from the gdb/ subdirectory of the
7 GDB source tree.
8
9 """
10
11 import datetime
12 import re
13 import os
14 import os.path
15
16 class 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).
37 ADA_COMMENT = Comment(start="--")
38
39 THIS_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).
44 EXCLUSION_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.
51 BY_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).
56 NO_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.
353 COMMENT_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
376 class NotFound(Exception):
377     pass
378
379 class AlreadyDone(Exception):
380     pass
381
382 def 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
531 def 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
548 def 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
589 if __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