15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/perl -w
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This script was originally based on the script of the same name from
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the KDE SDK (by dfaure@kde.org)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This version is
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   Copyright (C) 2007, 2008 Adam D. Barratt
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   Copyright (C) 2012 Francesco Poli
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This program is free software; you can redistribute it and/or modify
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# it under the terms of the GNU General Public License as published by
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the Free Software Foundation; either version 2 of the License, or
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# (at your option) any later version.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This program is distributed in the hope that it will be useful,
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# but WITHOUT ANY WARRANTY; without even the implied warranty of
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# GNU General Public License for more details.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# You should have received a copy of the GNU General Public License along
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# with this program. If not, see <http://www.gnu.org/licenses/>.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 NAME
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)licensecheck - simple license checker for source files
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 SYNOPSIS
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)B<licensecheck> B<--help>|B<--version>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)B<licensecheck> [B<--no-conf>] [B<--verbose>] [B<--copyright>]
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)[B<-l>|B<--lines=>I<N>] [B<-i>|B<--ignore=>I<regex>] [B<-c>|B<--check=>I<regex>]
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)[B<-m>|B<--machine>] [B<-r>|B<--recursive>]
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)I<list of files and directories to check>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 DESCRIPTION
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)B<licensecheck> attempts to determine the license that applies to each file
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)passed to it, by searching the start of the file for text belonging to
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)various licenses.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If any of the arguments passed are directories, B<licensecheck> will add
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the files contained within to the list of files to process.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 OPTIONS
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=over 4
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<--verbose>, B<--no-verbose>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Specify whether to output the text being processed from each file before
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the corresponding license information.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Default is to be quiet.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<-l=>I<N>, B<--lines=>I<N>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Specify the number of lines of each file's header which should be parsed
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)for license information. (Default is 60).
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<-i=>I<regex>, B<--ignore=>I<regex>
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)When processing the list of files and directories, the regular
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)expression specified by this option will be used to indicate those which
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)should not be considered (e.g. backup files, VCS metadata).
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<-r>, B<--recursive>
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Specify that the contents of directories should be added
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)recursively.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<-c=>I<regex>, B<--check=>I<regex>
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Specify a pattern against which filenames will be matched in order to
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)decide which files to check the license of.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The default includes common source files.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<--copyright>
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Also display copyright text found within the file
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<-m>, B<--machine>
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Display the information in a machine readable way, i.e. in the form
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)<file><tab><license>[<tab><copyright>] so that it can be easily sorted
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)and/or filtered, e.g. with the B<awk> and B<sort> commands.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Note that using the B<--verbose> option will kill the readability.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<--no-conf>, B<--noconf>
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Do not read any configuration files. This can only be used as the first
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)option given on the command-line.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=back
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 CONFIGURATION VARIABLES
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)The two configuration files F</etc/devscripts.conf> and
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)F<~/.devscripts> are sourced by a shell in that order to set
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)configuration variables.  Command line options can be used to override
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)configuration file settings.  Environment variable settings are
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ignored for this purpose.  The currently recognised variables are:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=over 4
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<LICENSECHECK_VERBOSE>
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If this is set to I<yes>, then it is the same as the B<--verbose> command
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)line parameter being used. The default is I<no>.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=item B<LICENSECHECK_PARSELINES>
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If this is set to a positive number then the specified number of lines
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)at the start of each file will be read whilst attempting to determine
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)the license(s) in use.  This is equivalent to the B<--lines> command line
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)option.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=back
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 LICENSE
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This code is copyright by Adam D. Barratt <I<adam@adam-barratt.org.uk>>,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)all rights reserved; based on a script of the same name from the KDE
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SDK, which is copyright by <I<dfaure@kde.org>>.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This program comes with ABSOLUTELY NO WARRANTY.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)You are free to redistribute this code under the terms of the GNU
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)General Public License, version 2 or later.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=head1 AUTHOR
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Adam D. Barratt <adam@adam-barratt.org.uk>
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)=cut
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)use strict;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)use warnings;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)use Getopt::Long qw(:config gnu_getopt);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)use File::Basename;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub fatal($);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub parse_copyright($);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub parselicense($);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $progname = basename($0);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# From dpkg-source
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $default_ignore_regex = '
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Ignore general backup files
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/).*~$|
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Ignore emacs recovery files
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/)\.#.*$|
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Ignore vi swap files
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/)\..*\.swp$|
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Ignore baz-style junk files or directories
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/),,.*(?:$|/.*$)|
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# File-names that should be ignored (never directories)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/)(?:DEADJOE|\.cvsignore|\.arch-inventory|\.bzrignore|\.gitignore)$|
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# File or directory names that should be ignored
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(?:^|/)(?:CVS|RCS|\.deps|\{arch\}|\.arch-ids|\.svn|\.hg|_darcs|\.git|
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)\.shelf|_MTN|\.bzr(?:\.backup|tags)?)(?:$|/.*$)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)';
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Take out comments and newlines
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$default_ignore_regex =~ s/^#.*$//mg;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$default_ignore_regex =~ s/\n//sg;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $default_check_regex = '\.(c(c|pp|xx)?|h(h|pp|xx)?|f(77|90)?|p(l|m)|xs|sh|php|py(|x)|rb|java|vala|el|sc(i|e)|cs|pas|inc|dtd|xsl|mod|m|tex|mli?)$';
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $modified_conf_msg;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my ($opt_verbose, $opt_lines, $opt_noconf, $opt_ignore_regex, $opt_check_regex)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  = ('', '', '', '', '');
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $opt_recursive = 0;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $opt_copyright = 0;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $opt_machine = 0;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my ($opt_help, $opt_version);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $def_lines = 60;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Read configuration files and then command line
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This is boilerplate
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $modified_conf_msg = "  (no configuration files read)";
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shift;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} else {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my @config_files = ('/etc/devscripts.conf', '~/.devscripts');
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my %config_vars = (
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       'LICENSECHECK_VERBOSE' => 'no',
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		       'LICENSECHECK_PARSELINES' => $def_lines,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      );
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my %config_default = %config_vars;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $shell_cmd;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Set defaults
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    foreach my $var (keys %config_vars) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$shell_cmd .= qq[$var="$config_vars{$var}";\n];
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n";
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n";
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Read back values
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $shell_out = `/bin/bash -c '$shell_cmd'`;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @config_vars{keys %config_vars} = split /\n/, $shell_out, -1;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check validity
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $config_vars{'LICENSECHECK_VERBOSE'} =~ /^(yes|no)$/
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	or $config_vars{'LICENSECHECK_VERBOSE'} = 'no';
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $config_vars{'LICENSECHECK_PARSELINES'} =~ /^[1-9][0-9]*$/
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	or $config_vars{'LICENSECHECK_PARSELINES'} = $def_lines;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    foreach my $var (sort keys %config_vars) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ($config_vars{$var} ne $config_default{$var}) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $modified_conf_msg .= "  $var=$config_vars{$var}\n";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $modified_conf_msg ||= "  (none)\n";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chomp $modified_conf_msg;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $opt_verbose = $config_vars{'LICENSECHECK_VERBOSE'} eq 'yes' ? 1 : 0;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $opt_lines = $config_vars{'LICENSECHECK_PARSELINES'};
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetOptions("help|h" => \$opt_help,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "version|v" => \$opt_version,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "verbose!" => \$opt_verbose,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "lines|l=i" => \$opt_lines,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "ignore|i=s" => \$opt_ignore_regex,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "recursive|r" => \$opt_recursive,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "check|c=s" => \$opt_check_regex,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "copyright" => \$opt_copyright,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "machine|m" => \$opt_machine,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "noconf" => \$opt_noconf,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   "no-conf" => \$opt_noconf,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   )
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    or die "Usage: $progname [options] filelist\nRun $progname --help for more details\n";
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$opt_lines = $def_lines if $opt_lines !~ /^[1-9][0-9]*$/;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$opt_ignore_regex = $default_ignore_regex if ! length $opt_ignore_regex;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$opt_check_regex = $default_check_regex if ! length $opt_check_regex;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if ($opt_noconf) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fatal "--no-conf is only acceptable as the first command-line option!";
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if ($opt_help) { help(); exit 0; }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if ($opt_version) { version(); exit 0; }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)die "Usage: $progname [options] filelist\nRun $progname --help for more details\n" unless @ARGV;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$opt_lines = $def_lines if not defined $opt_lines;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my @files = ();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my @find_args = ();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)my $files_count = @ARGV;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)push @find_args, qw(-maxdepth 1) unless $opt_recursive;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)push @find_args, qw(-follow -type f -print);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)while (@ARGV) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $file = shift @ARGV;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (-d $file) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	open FIND, '-|', 'find', $file, @find_args
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    or die "$progname: couldn't exec find: $!\n";
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	while (<FIND>) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    chomp;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    next unless m%$opt_check_regex%;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    # Skip empty files
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    next if (-z $_);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    push @files, $_ unless m%$opt_ignore_regex%;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	close FIND;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	next unless ($files_count == 1) or $file =~ m%$opt_check_regex%;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	push @files, $file unless $file =~ m%$opt_ignore_regex%;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)while (@files) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $file = shift @files;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $content = '';
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $copyright_match;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $copyright = '';
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $license = '';
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my %copyrights;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    open (F, "<$file") or die "Unable to access $file\n";
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (<F>) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last if ($. > $opt_lines);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $content .= $_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$copyright_match = parse_copyright($_);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ($copyright_match) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $copyrights{lc("$copyright_match")} = "$copyright_match";
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    close(F);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $copyright = join(" / ", values %copyrights);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print qq(----- $file header -----\n$content----- end header -----\n\n)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if $opt_verbose;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Remove Fortran comments
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $content =~ s/^[cC] //gm;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $content =~ tr/\t\r\n/ /;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Remove C / C++ comments
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $content =~ s#(\*/|/[/*])##g;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $content =~ tr% A-Za-z.,@;0-9\(\)/-%%cd;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $content =~ tr/ //s;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $license = parselicense($content);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($opt_machine) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "$file\t$license";
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "\t" . ($copyright or "*No copyright*") if $opt_copyright;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "\n";
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "$file: ";
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "*No copyright* " unless $copyright;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print $license . "\n";
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "  [Copyright: " . $copyright . "]\n"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  if $copyright and $opt_copyright;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	print "\n" if $opt_copyright;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub parse_copyright($) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $copyright = '';
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $match;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $copyright_indicator_regex = '
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(?:copyright	# The full word
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|copr\.		# Legally-valid abbreviation
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|\x{00a9}	# Unicode character COPYRIGHT SIGN
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|\xc2\xa9	# Unicode copyright sign encoded in iso8859
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|\(c\)		# Legally-null representation of sign
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	)';
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $copyright_disindicator_regex = '
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	\b(?:info(?:rmation)?	# Discussing copyright information
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|notice			# Discussing the notice
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	|and|or                 # Part of a sentence
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	)\b';
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (m%$copyright_indicator_regex(?::\s*|\s+)(\S.*)$%ix) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$match = $1;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	# Ignore lines matching "see foo for copyright information" etc.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ($match !~ m%^\s*$copyright_disindicator_regex%ix) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    # De-cruft
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $match =~ s/([,.])?\s*$//;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $match =~ s/$copyright_indicator_regex//igx;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $match =~ s/^\s+//;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $match =~ s/\s{2,}/ /g;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $match =~ s/\\@/@/g;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $copyright = $match;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return $copyright;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub help {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   print <<"EOF";
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Usage: $progname [options] filename [filename ...]
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Valid options are:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --help, -h             Display this message
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --version, -v          Display version and copyright info
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --no-conf, --noconf    Don't read devscripts config files; must be
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          the first option given
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --verbose              Display the header of each file before its
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            license information
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --lines, -l            Specify how many lines of the file header
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            should be parsed for license information
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            (Default: $def_lines)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --check, -c            Specify a pattern indicating which files should
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             be checked
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             (Default: '$default_check_regex')
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --machine, -m          Display in a machine readable way (good for awk)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --recursive, -r        Add the contents of directories recursively
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --copyright            Also display the file's copyright
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   --ignore, -i           Specify that files / directories matching the
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            regular expression should be ignored when
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            checking files
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            (Default: '$default_ignore_regex')
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Default settings modified by devscripts configuration files:
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$modified_conf_msg
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EOF
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub version {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print <<"EOF";
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This is $progname, from the Debian devscripts package, version ###VERSION###
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Copyright (C) 2007, 2008 by Adam D. Barratt <adam\@adam-barratt.org.uk>; based
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)on a script of the same name from the KDE SDK by <dfaure\@kde.org>.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This program comes with ABSOLUTELY NO WARRANTY.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)You are free to redistribute this code under the terms of the
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GNU General Public License, version 2, or (at your option) any
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)later version.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EOF
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub parselicense($) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my ($licensetext) = @_;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $gplver = "";
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $extrainfo = "";
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my $license = "";
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /version ([^, ]+?)[.,]? (?:\(?only\)?.? )?(?:of the GNU (Affero )?(Lesser |Library )?General Public License )?(as )?published by the Free Software Foundation/i or
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License (?:as )?published by the Free Software Foundation; version ([^, ]+?)[.,]? /i) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$gplver = " (v$1)";
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /GNU (?:Affero )?(?:Lesser |Library )?General Public License, version (\d+(?:\.\d+)?)[ \.]/) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$gplver = " (v$1)";
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /either version ([^ ]+)(?: of the License)?, or \(at your option\) any later version/) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$gplver = " (v$1 or later)";
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /(?:675 Mass Ave|59 Temple Place|51 Franklin Steet|02139|02111-1307)/i) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$extrainfo = " (with incorrect FSF address)$extrainfo";
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /permission (?:is (also granted|given))? to link (the code of )?this program with (any edition of )?(Qt|the Qt library)/i) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$extrainfo = " (with Qt exception)$extrainfo"
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /(All changes made in this file will be lost|DO NOT (EDIT|delete this file)|Generated (automatically|by|from)|generated.*file)/i) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "GENERATED FILE";
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is (free software.? you can redistribute it and\/or modify it|licensed) under the terms of (version [^ ]+ of )?the (GNU (Library |Lesser )General Public License|LGPL)/i) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "LGPL$gplver$extrainfo $license";
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is free software.? you can redistribute it and\/or modify it under the terms of the (GNU Affero General Public License|AGPL)/i) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "AGPL$gplver$extrainfo $license";
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is free software.? you (can|may) redistribute it and\/or modify it under the terms of (?:version [^ ]+ (?:\(?only\)? )?of )?the GNU General Public License/i) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "GPL$gplver$extrainfo $license";
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is distributed under the terms of the GNU General Public License,/
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	and length $gplver) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "GPL$gplver$extrainfo $license";
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is distributed.*terms.*GPL/) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "GPL (unversioned/unknown version) $license";
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /This file is part of the .*Qt GUI Toolkit. This file may be distributed under the terms of the Q Public License as defined/) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "QPL (part of Qt) $license";
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /may be distributed under the terms of the Q Public License as defined/) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "QPL $license";
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /opensource\.org\/licenses\/mit-license\.php/) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "MIT/X11 (BSD like) $license";
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /Permission is hereby granted, free of charge, to any person obtaining a copy of this software and(\/or)? associated documentation files \(the (Software|Materials)\), to deal in the (Software|Materials)/) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "MIT/X11 (BSD like) $license";
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose/) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "MIT/X11 (BSD like) $license";
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext  =~ /Permission to use, copy, modify, and(\/or)? distribute this software for any purpose with or without fee is hereby granted, provided.*copyright notice.*permission notice.*all copies/) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "ISC $license";
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /THIS SOFTWARE IS PROVIDED .*AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY/) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ($licensetext =~ /All advertising materials mentioning features or use of this software must display the following acknowledge?ment.*This product includes software developed by/i) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $license = "BSD (4 clause) $license";
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} elsif ($licensetext =~ /(The name .*? may not|Neither the names? .*? nor the names of (its|their) contributors may) be used to endorse or promote products derived from this software/i) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $license = "BSD (3 clause) $license";
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} elsif ($licensetext =~ /Redistributions of source code must retain the above copyright notice/i) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $license = "BSD (2 clause) $license";
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    $license = "BSD $license";
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Mozilla Public License Version ([^ ]+)/) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "MPL (v$1) $license";
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Released under the terms of the Artistic License ([^ ]+)/) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Artistic (v$1) $license";
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is free software under the Artistic [Ll]icense/) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Artistic $license";
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /This program is free software; you can redistribute it and\/or modify it under the same terms as Perl itself/) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Perl $license";
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /under the Apache License, Version ([^ ]+)/) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Apache (v$1) $license";
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /(THE BEER-WARE LICENSE)/i) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Beerware $license";
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /This source file is subject to version ([^ ]+) of the PHP license/) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "PHP (v$1) $license";
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /under the terms of the CeCILL /) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "CeCILL $license";
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /under the terms of the CeCILL-([^ ]+) /) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "CeCILL-$1 $license";
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /under the SGI Free Software License B/) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "SGI Free Software License B $license";
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /is in the public domain/i) {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "Public domain $license";
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /terms of the Common Development and Distribution License(, Version ([^(]+))? \(the License\)/) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "CDDL " . ($1 ? "(v$2) " : '') . $license;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Microsoft Permissive License \(Ms-PL\)/) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $license = "Ms-PL $license";
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license \(the \"Software\"\)/ or
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$licensetext =~ /Boost Software License([ ,-]+Version ([^ ]+)?(\.))/i) {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "BSL " . ($1 ? "(v$2) " : '') . $license;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /PYTHON SOFTWARE FOUNDATION LICENSE (VERSION ([^ ]+))/i) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "PSF " . ($1 ? "(v$2) " : '') . $license;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /The origin of this software must not be misrepresented.*Altered source versions must be plainly marked as such.*This notice may not be removed or altered from any source distribution/ or
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $licensetext =~ /see copyright notice in zlib\.h/) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	$license = "zlib/libpng $license";
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } elsif ($licensetext =~ /This code is released under the libpng license/) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $license = "libpng $license";
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Do What The Fuck You Want To Public License, Version ([^, ]+)/i) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $license = "WTFPL (v$1) $license";
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /Do what The Fuck You Want To Public License/i) {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $license = "WTFPL $license";
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ($licensetext =~ /(License WTFPL|Under (the|a) WTFPL)/i) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        $license = "WTFPL $license";
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $license = "UNKNOWN" if (!length($license));
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Remove trailing spaces.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $license =~ s/\s+$//;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return $license;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sub fatal($) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    my ($pack,$file,$line);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ($pack,$file,$line) = caller();
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (my $msg = "$progname: fatal error at line $line:\n@_\n") =~ tr/\0//d;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    $msg =~ s/\n\n$/\n/;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    die $msg;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
578