Merge branch '1.0.x'
[cvc5.git] / contrib / update-copyright.pl
1 #!/usr/bin/perl -w
2 #
3 # update-copyright.pl
4 # Morgan Deters <mdeters@cs.nyu.edu> for CVC4
5 # Copyright (c) 2009-2013 The CVC4 Project
6 #
7 # usage: update-copyright [-m] [files/directories...]
8 # update-copyright [-h | --help]
9 #
10 # This script goes through a source directory rewriting the top bits of
11 # source files to match a template (inline, below). For files with no
12 # top comment, it adds a fresh one.
13 #
14 # if no files/directories are unspecified, the script scans its own
15 # parent directory's "src" directory. Since it lives in contrib/ in
16 # the CVC4 source tree, that means src/ in the CVC4 source tree.
17 #
18 # If -m is specified as the first argument, all files and directories
19 # are scanned, but only ones modified in the index or working tree
20 # are modified (i.e., those that have at least one status M in
21 # "git status -s").
22 #
23 # It ignores any file/directory not starting with [a-zA-Z]
24 # (so, this includes . and .., vi swaps, .git meta-info,
25 # .deps, etc.)
26 #
27 # It ignores any file not ending with one of:
28 # .c .cc .cpp .C .h .hh .hpp .H .y .yy .ypp .Y .l .ll .lpp .L .g
29 # [ or those with ".in" also suffixed, e.g., .cpp.in ]
30 # (so, this includes emacs ~-backups, CVS detritus, etc.)
31 #
32 # It ignores any directory matching $excluded_directories
33 # (so, you should add here any sources imported but not covered under
34 # the license.)
35 #
36
37 my $excluded_directories = '^(minisat|bvminisat|cryptominisat|CVS|generated)$';
38 my $excluded_paths = '^(src/parser/antlr_input_imports.cpp|src/bindings/compat/.*)$';
39
40 # Years of copyright for the template. E.g., the string
41 # "1985, 1987, 1992, 1997, 2008" or "2006-2009" or whatever.
42 my $years = '2009-2013';
43
44 my $standard_template = <<EOF;
45 ** This file is part of the CVC4 project.
46 ** Copyright (c) $years New York University and The University of Iowa
47 ** See the file COPYING in the top-level source directory for licensing
48 ** information.\\endverbatim
49 EOF
50
51 my $public_template = <<EOF;
52 ** This file is part of the CVC4 project.
53 ** Copyright (c) $years New York University and The University of Iowa
54 ** See the file COPYING in the top-level source directory for licensing
55 ** information.\\endverbatim
56 EOF
57
58 ## end config ##
59
60 use strict;
61 use Fcntl ':mode';
62
63 my $dir = $0;
64 $dir =~ s,/[^/]+/*$,,;
65
66 if($#ARGV >= 0 && $ARGV[0] eq '-h' || $ARGV[0] eq '--help') {
67 open(my $SELF, $0) || die "error opening $0 for reading";
68 while($_ = <$SELF>) {
69 last if !/^#/;
70 print;
71 }
72 close $SELF;
73 exit;
74 }
75
76 # whether we ONLY process files with git status "M"
77 my $modonly = 0;
78
79 if($#ARGV >= 0 && $ARGV[0] eq '-m') {
80 $modonly = 1;
81 shift;
82 }
83
84 my @searchdirs = ();
85 if($#ARGV == -1) {
86 (chdir($dir."/..") && -f "src/include/cvc4_public.h") || die "can't find top-level source directory for CVC4";
87 my $pwd = `pwd`; chomp $pwd;
88
89 print <<EOF;
90 Warning: this script is dangerous. It will overwrite the header comments in your
91 source files to match the template in the script, attempting to retain file-specific
92 comments, but this isn't guaranteed. You should run this in a git working tree
93 and run "git diff" after to ensure everything was correctly rewritten.
94
95 The directories in which to search for and change sources is:
96 $pwd/src
97 $pwd/examples
98 $pwd/test
99
100 Continue? y or n:
101 EOF
102
103 $_ = <STDIN>; chomp;
104 die 'aborting operation' if !( $_ eq 'y' || $_ eq 'yes' || $_ eq 'Y' || $_ eq 'YES' );
105
106 $searchdirs[0] = 'src';
107 $searchdirs[1] = 'examples';
108 $searchdirs[2] = 'test';
109 } else {
110 @searchdirs = @ARGV;
111 }
112
113 print "Updating sources...\n";
114
115 while($#searchdirs >= 0) {
116 my $dir = shift @searchdirs;
117 my $mode = (stat($dir))[2] || warn "file or directory \`$dir' does not exist!";
118 my $is_directory = S_ISDIR($mode);
119 if($is_directory) {
120 recurse($dir);
121 } else {
122 if($dir =~ m,^(.*)\/([^/]*)$,) {
123 my($dir, $file) = ($1, $2);
124 if($dir eq "") {
125 $dir = "/";
126 }
127 handleFile($dir, $file);
128 } else {
129 handleFile(".", $dir);
130 }
131 }
132 }
133
134 sub handleFile {
135 my ($srcdir, $file) = @_;
136 return if !($file =~ /\.(c|cc|cpp|C|h|hh|hpp|H|y|yy|ypp|Y|l|ll|lpp|L|g|java)(\.in)?$/);
137 return if ($srcdir.'/'.$file) =~ /$excluded_paths/;
138 return if $modonly && `git status -s "$srcdir/$file" 2>/dev/null` !~ /^(M|.M)/;
139 print "$srcdir/$file...";
140 my $infile = $srcdir.'/'.$file;
141 my $outfile = $srcdir.'/#'.$file.'.tmp';
142 open(my $IN, $infile) || die "error opening $infile for reading";
143 open(my $OUT, '>', $outfile) || die "error opening $outfile for writing";
144 open(my $AUTHOR, "$dir/get-authors " . $infile . '|');
145 my $author = <$AUTHOR>; chomp $author;
146 my $major_contributors = <$AUTHOR>; chomp $major_contributors;
147 my $minor_contributors = <$AUTHOR>; chomp $minor_contributors;
148 close $AUTHOR;
149 $_ = <$IN>;
150 if(m,^(%{)?/\*(\*| )\*\*\*,) {
151 print "updating\n";
152 if($file =~ /\.(y|yy|ypp|Y)$/) {
153 print $OUT "%{/******************* */\n";
154 print $OUT "/** $file\n";
155 } elsif($file =~ /\.g$/) {
156 # avoid javadoc-style comment here; antlr complains
157 print $OUT "/* ******************* */\n";
158 print $OUT "/*! \\file $file\n";
159 } else {
160 print $OUT "/********************* */\n";
161 print $OUT "/*! \\file $file\n";
162 }
163 print $OUT " ** \\verbatim\n";
164 print $OUT " ** Original author: $author\n";
165 print $OUT " ** Major contributors: $major_contributors\n";
166 print $OUT " ** Minor contributors (to current version): $minor_contributors\n";
167 print $OUT $standard_template;
168 print $OUT " **\n";
169 while(my $line = <$IN>) {
170 last if $line =~ /^ \*\*\s*$/;
171 if($line =~ /\*\//) {
172 print $OUT " ** [[ Add lengthier description here ]]\n";
173 print $OUT " ** \\todo document this file\n";
174 print $OUT $line;
175 last;
176 }
177 }
178 } else {
179 my $line = $_;
180 print "adding\n";
181 if($file =~ /\.(y|yy|ypp|Y)$/) {
182 print $OUT "%{/******************* */\n";
183 print $OUT "/*! \\file $file\n";
184 } elsif($file =~ /\.g$/) {
185 # avoid javadoc-style comment here; antlr complains
186 print $OUT "/* ******************* */\n";
187 print $OUT "/*! \\file $file\n";
188 } else {
189 print $OUT "/********************* */\n";
190 print $OUT "/*! \\file $file\n";
191 }
192 print $OUT " ** \\verbatim\n";
193 print $OUT " ** Original author: $author\n";
194 print $OUT " ** Major contributors: $major_contributors\n";
195 print $OUT " ** Minor contributors (to current version): $minor_contributors\n";
196 print $OUT $standard_template;
197 print $OUT " **\n";
198 print $OUT " ** \\brief [[ Add one-line brief description here ]]\n";
199 print $OUT " **\n";
200 print $OUT " ** [[ Add lengthier description here ]]\n";
201 print $OUT " ** \\todo document this file\n";
202 print $OUT " **/\n\n";
203 print $OUT $line;
204 if($file =~ /\.(y|yy|ypp|Y)$/) {
205 while(my $line = <$IN>) {
206 chomp $line;
207 if($line =~ '\s*%{(.*)') {
208 print $OUT "$1\n";
209 last;
210 }
211 # just in case something's weird with the file ?
212 if(!($line =~ '\s*')) {
213 print $OUT "$line\n";
214 last;
215 }
216 }
217 }
218 }
219 while(my $line = <$IN>) {
220 print $OUT $line;
221 }
222 close $IN;
223 close $OUT;
224 rename($outfile, $infile) || die "can't rename working file \`$outfile' to \`$infile'";
225 }
226
227 sub recurse {
228 my ($srcdir) = @_;
229 print "in dir $srcdir\n";
230 opendir(my $DIR, $srcdir);
231 while(my $file = readdir $DIR) {
232 next if !($file =~ /^[a-zA-Z]/);
233
234 my $mode = (stat($srcdir.'/'.$file))[2];
235 my $is_directory = S_ISDIR($mode);
236 if($is_directory) {
237 next if $file =~ /$excluded_directories/;
238 recurse($srcdir.'/'.$file);
239 } else {
240 handleFile($srcdir, $file);
241 }
242 }
243 closedir $DIR;
244 }
245
246 ### Local Variables:
247 ### perl-indent-level: 2
248 ### End: