4 # Copyright (c) 2009-2020 The CVC4 Project
6 # usage: update-copyright [-m] [files/directories...]
7 # update-copyright [-h | --help]
9 # This script goes through a source directory rewriting the top bits of
10 # source files to match a template (inline, below). For files with no
11 # top comment, it adds a fresh one.
13 # if no files/directories are unspecified, the script scans its own
14 # parent directory's "src" directory. Since it lives in contrib/ in
15 # the CVC4 source tree, that means src/ in the CVC4 source tree.
17 # If -m is specified as the first argument, all files and directories
18 # are scanned, but only ones modified in the index or working tree
19 # are modified (i.e., those that have at least one status M in
22 # It ignores any file/directory not starting with [a-zA-Z]
23 # (so, this includes . and .., vi swaps, .git meta-info,
26 # It ignores any file not ending with one of:
27 # .c .cc .cpp .h .hh .hpp .g .py .cmake .cmake.in CMakeLists.txt
28 # [ or those with ".in" also suffixed, e.g., .cpp.in ]
29 # (so, this includes emacs ~-backups, CVS detritus, etc.)
31 # It ignores any directory matching $excluded_directories
32 # (so, you should add here any sources imported but not covered under
36 my $excluded_directories = '^(CVS|generated)$';
37 my $excluded_paths = '^(';
38 # note: first excluded path regexp must not start with a '|'
40 $excluded_paths .= 'cmake/CodeCoverage.cmake';
41 $excluded_paths .= '|cmake/FindCython.cmake';
42 $excluded_paths .= '|cmake/FindPythonExtensions.cmake';
43 $excluded_paths .= '|cmake/UseCython.cmake';
44 $excluded_paths .= '|cmake/targetLinkLibrariesWithDynamicLookup.cmake';
46 $excluded_paths .= '|src/prop/(bv)?minisat/core/.*';
47 $excluded_paths .= '|src/prop/(bv)?minisat/mtl/.*';
48 $excluded_paths .= '|src/prop/(bv)?minisat/simp/.*';
49 $excluded_paths .= '|src/prop/(bv)?minisat/utils/.*';
50 $excluded_paths .= ')$';
52 # Years of copyright for the template. E.g., the string
53 # "1985, 1987, 1992, 1997, 2008" or "2006-2009" or whatever.
54 my $years = '2009-2020';
56 my $standard_template = <<EOF;
57 ** This file is part of the CVC4 project.
58 ** Copyright (c) $years by the authors listed in the file AUTHORS
59 ** in the top-level source directory and their institutional affiliations.
60 ** All rights reserved. See the file COPYING in the top-level source
61 ** directory for licensing information.\\endverbatim
65 my $doc_template = <<EOF;
66 ** \\brief [[ Add one-line brief description here ]]
68 ** [[ Add lengthier description here ]]
69 ** \\todo document this file
72 my $standard_template_end = " **/\n";
74 my $standard_template_hash = $standard_template;
75 $standard_template_hash =~ s/ \*\*/\#\#/g;
76 $standard_template_hash =~ s/\\endverbatim//;
85 $dir =~ s
,/[^/]+/*$,,;
87 if($#ARGV >= 0 && ($ARGV[0] eq '-h' || $ARGV[0] eq '--help')) {
88 open(my $SELF, $0) || die "error opening $0 for reading";
97 # whether we ONLY process files with git status "M"
100 if($#ARGV >= 0 && $ARGV[0] eq '-m') {
107 (chdir($dir."/..") && -f
"src/include/cvc4_public.h") || die "can't find top-level source directory for CVC4";
108 my $pwd = `pwd`; chomp $pwd;
111 Warning: this script is dangerous. It will overwrite the header comments in your
112 source files to match the template in the script, attempting to retain file-specific
113 comments, but this isn't guaranteed. You should run this in a git working tree
114 and run "git diff" after to ensure everything was correctly rewritten.
116 The directories in which to search for and change sources is:
127 die 'aborting operation' if !( $_ eq 'y' || $_ eq 'yes' || $_ eq 'Y' || $_ eq 'YES' );
129 $searchdirs[0] = 'CMakeLists.txt';
130 $searchdirs[1] = 'cmake';
131 $searchdirs[2] = 'src';
132 $searchdirs[3] = 'examples';
133 $searchdirs[4] = 'test';
138 print "Updating sources...\n";
140 while($#searchdirs >= 0) {
141 my $dir = shift @searchdirs;
142 $dir =~ s
,\
/$,,; # remove trailing slash from directory
143 my $mode = (stat($dir))[2] || warn "file or directory \`$dir' does not exist!";
144 my $is_directory = S_ISDIR
($mode);
148 if ($dir =~ m
,^(.*)\
/([^/]*)$,) {
149 my ($dir, $file) = ($1, $2);
153 handleFile
($dir, $file);
155 handleFile
(".", $dir);
162 return ($file =~ /\.(cmake|py)(\.in)?$/ or $file =~ /CMakeLists\.txt/);
166 my ($OUT, $file) = @_;
167 if (reqHashPrefix
($file)) {
168 print $OUT "#####################\n";
169 print $OUT "## $file\n";
170 } elsif ($file =~ /\.g$/) {
171 # avoid javadoc-style comment here; antlr complains
172 print $OUT "/* ******************* */\n";
173 print $OUT "/*! \\file $file\n";
175 print $OUT "/********************* */\n";
176 print $OUT "/*! \\file $file\n";
180 sub printTopContrib
{
181 my ($OUT, $file, $authors) = @_;
182 my $comment_style = " **";
183 if (reqHashPrefix
($file)) {
184 $comment_style = "##";
186 print $OUT "$comment_style \\verbatim\n";
188 print $OUT "$comment_style Top contributors (to current version):\n";
189 print $OUT "$comment_style $authors\n";
193 my ($srcdir, $file) = @_;
194 return if !($file =~ /\.(c|cc|cpp|h|hh|hpp|g|java)(\.in)?$/ or reqHashPrefix
($file));
195 return if ($srcdir.'/'.$file) =~ /$excluded_paths/;
196 return if $modonly && `git status -s "$srcdir/$file" 2>/dev/null` !~ /^(M
|.M
)/;
197 print "$srcdir/$file... ";
198 my $infile = $srcdir.'/'.$file;
199 my $outfile = $srcdir.'/#'.$file.'.tmp';
200 open(my $IN, $infile) || die "error opening $infile for reading";
201 open(my $OUT, '>', $outfile) || die "error opening $outfile for writing";
202 open(my $AUTHOR, "$dir/get-authors " . $infile . '|');
203 my $authors = <$AUTHOR>; chomp $authors;
206 # Read file into array
210 # Check if file contains a shebang and print it as first line.
211 if ($lines[0] =~ /^\#!/) {
212 print $OUT $lines[0];
216 printHeader
($OUT, $file);
217 printTopContrib
($OUT, $file, $authors);
220 # Copyright header already exists
221 if ($lines[0] =~ /^(%\{)?\/\
*(\
*| )\
*{19}/ or $lines[0] =~ /^\#
{21}$/) {
224 # Skip lines until copyright header end and preserve copyright of non CVC4
226 my $found_header_end = 0;
227 while (my $line = shift @lines) {
228 # Check if someone else holds this copyright and keep it.
229 if($line =~ /\b[Cc]opyright\b/ && $line !~ /\bby the authors listed in the file AUTHORS\b/) {
232 # Reached end of copyright header section
233 if ($line =~ /^ \*\*\s*$/ or $line =~ /^\#\#$/) {
234 $found_header_end = 1;
238 if (!$found_header_end) {
239 die "error: did not find end of copyright header secion (** or #)";
246 if (reqHashPrefix
($file)) {
247 print $OUT $standard_template_hash;
249 print $OUT $standard_template;
251 print $OUT $doc_template;
252 print $OUT $standard_template_end;
255 # Print remaining file
261 # Preserve file permissions of $infile
262 my $perm = (stat($infile))[2] & 0777;
263 chmod $perm, $outfile;
265 rename($outfile, $infile) || die "can't rename working file \`$outfile' to \`$infile'";
270 opendir(my $DIR, $srcdir);
271 while(my $file = readdir $DIR) {
272 next if !($file =~ /^[a-zA-Z]/);
274 my $mode = (stat($srcdir.'/'.$file))[2];
275 my $is_directory = S_ISDIR
($mode);
277 next if $file =~ /$excluded_directories/;
278 recurse
($srcdir.'/'.$file);
280 handleFile
($srcdir, $file);
287 ### perl-indent-level: 2