"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "cloc" between
cloc-1.84.tar.gz and cloc-1.86.tar.gz

About: cloc ("Count Lines of Code") counts blank, comment and physical lines of source code in many programming languages.

cloc  (cloc-1.84):cloc  (cloc-1.86)
#!/usr/bin/env perl #!/usr/bin/env perl
# cloc -- Count Lines of Code {{{1 # cloc -- Count Lines of Code {{{1
# Copyright (C) 2006-2019 Al Danial <al.danial@gmail.com> # Copyright (C) 2006-2020 Al Danial <al.danial@gmail.com>
# First release August 2006 # First release August 2006
# #
# Includes code from: # Includes code from:
# - SLOCCount v2.26 # - SLOCCount v2.26
# http://www.dwheeler.com/sloccount/ # http://www.dwheeler.com/sloccount/
# by David Wheeler. # by David Wheeler.
# - Regexp::Common v2013031301 # - Regexp::Common v2013031301
# http://search.cpan.org/~abigail/Regexp-Common-2013031301/lib/Regexp/Common .pm # http://search.cpan.org/~abigail/Regexp-Common-2013031301/lib/Regexp/Common .pm
# by Damian Conway and Abigail. # by Damian Conway and Abigail.
# - Win32::Autoglob # - Win32::Autoglob
skipping to change at line 32 skipping to change at line 32
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details: # GNU General Public License for more details:
# <http://www.gnu.org/licenses/gpl.txt>. # <http://www.gnu.org/licenses/gpl.txt>.
# #
# 1}}} # 1}}}
my $VERSION = "1.84"; # odd number == beta; even number == stable my $VERSION = "1.86"; # odd number == beta; even number == stable
my $URL = "github.com/AlDanial/cloc"; # 'https://' pushes header too wide my $URL = "github.com/AlDanial/cloc"; # 'https://' pushes header too wide
require 5.006; require 5.006;
# use modules {{{1 # use modules {{{1
use warnings; use warnings;
use strict; use strict;
use Getopt::Long; use Getopt::Long;
use File::Basename; use File::Basename;
use File::Temp qw { tempfile tempdir }; use File::Temp qw { tempfile tempdir };
use File::Find; use File::Find;
skipping to change at line 150 skipping to change at line 150
$config_file = File::Spec->catfile( $ENV{'HOME'}, '.config', 'cloc', 'option s.txt'); $config_file = File::Spec->catfile( $ENV{'HOME'}, '.config', 'cloc', 'option s.txt');
} elsif ( $ENV{'APPDATA'} and $ON_WINDOWS ) { } elsif ( $ENV{'APPDATA'} and $ON_WINDOWS ) {
$config_file = File::Spec->catfile( $ENV{'APPDATA'}, 'cloc'); $config_file = File::Spec->catfile( $ENV{'APPDATA'}, 'cloc');
} }
my $NN = chr(27) . "[0m"; # normal my $NN = chr(27) . "[0m"; # normal
$NN = "" if $ON_WINDOWS or !(-t STDOUT); # -t STDOUT: is it a terminal? $NN = "" if $ON_WINDOWS or !(-t STDOUT); # -t STDOUT: is it a terminal?
my $BB = chr(27) . "[1m"; # bold my $BB = chr(27) . "[1m"; # bold
$BB = "" if $ON_WINDOWS or !(-t STDOUT); $BB = "" if $ON_WINDOWS or !(-t STDOUT);
my $script = basename $0; my $script = basename $0;
# Intended for v1.88:
# --git-diff-simindex Git diff strategy #3: use git's similarity index
# (git diff -M --name-status) to identify file pairs
# to compare. This is especially useful to compare
# files that were renamed between the commits.
my $brief_usage = " my $brief_usage = "
cloc -- Count Lines of Code cloc -- Count Lines of Code
Usage: Usage:
$script [options] <file(s)/dir(s)/git hash(es)> $script [options] <file(s)/dir(s)/git hash(es)>
Count physical lines of source code and comments in the given files Count physical lines of source code and comments in the given files
(may be archives such as compressed tarballs or zip files) and/or (may be archives such as compressed tarballs or zip files) and/or
recursively below the given directories or git commit hashes. recursively below the given directories or git commit hashes.
Example: cloc src/ include/ main.c Example: cloc src/ include/ main.c
skipping to change at line 198 skipping to change at line 205
--extract-with='gzip -dc >FILE< | tar xf -' --extract-with='gzip -dc >FILE< | tar xf -'
or, if you have GNU tar, or, if you have GNU tar,
--extract-with='tar zxf >FILE<' --extract-with='tar zxf >FILE<'
and on Windows use, for example: and on Windows use, for example:
--extract-with=\"\\\"c:\\Program Files\\WinZip\\W inZip32.exe\\\" -e -o >FILE< .\" --extract-with=\"\\\"c:\\Program Files\\WinZip\\W inZip32.exe\\\" -e -o >FILE< .\"
(if WinZip is installed there). (if WinZip is installed there).
--list-file=<file> Take the list of file and/or directory names to --list-file=<file> Take the list of file and/or directory names to
process from <file>, which has one file/directory process from <file>, which has one file/directory
name per line. Only exact matches are counted; name per line. Only exact matches are counted;
relative path names will be resolved starting from relative path names will be resolved starting from
the directory where cloc is invoked. the directory where cloc is invoked. Set <file>
to - to read file names from a STDIN pipe.
See also --exclude-list-file. See also --exclude-list-file.
--diff-list-file=<file> Take the pairs of file names to be diff'ed from
<file>, whose format matches the output of
--diff-alignment. (Run with that option to
see a sample.) The language identifier at the
end of each line is ignored. This enables --diff
mode and by-passes file pair alignment logic.
--vcs=<VCS> Invoke a system call to <VCS> to obtain a list of --vcs=<VCS> Invoke a system call to <VCS> to obtain a list of
files to work on. If <VCS> is 'git', then will files to work on. If <VCS> is 'git', then will
invoke 'git ls-files' to get a file list and invoke 'git ls-files' to get a file list and
'git submodule status' to get a list of submodules 'git submodule status' to get a list of submodules
whose contents will be ignored. See also --git whose contents will be ignored. See also --git
which accepts git commit hashes and branch names. which accepts git commit hashes and branch names.
If <VCS> is 'svn' then will invoke 'svn list -R'. If <VCS> is 'svn' then will invoke 'svn list -R'.
The primary benefit is that cloc will then skip The primary benefit is that cloc will then skip
files explicitly excluded by the versioning tool files explicitly excluded by the versioning tool
in question, ie, those in .gitignore or have the in question, ie, those in .gitignore or have the
svn:ignore property. svn:ignore property.
Alternatively <VCS> may be any system command Alternatively <VCS> may be any system command
that generates a list of files. that generates a list of files.
Note: cloc must be in a directory which can read Note: cloc must be in a directory which can read
the files as they are returned by <VCS>. cloc will the files as they are returned by <VCS>. cloc will
not download files from remote repositories. not download files from remote repositories.
'svn list -R' may refer to a remote repository 'svn list -R' may refer to a remote repository
to obtain file names (and therefore may require to obtain file names (and therefore may require
authentication to the remote repository), but authentication to the remote repository), but
the files themselves must be local. the files themselves must be local.
Setting <VCS> to 'auto' selects between 'git'
and 'svn' (or neither) depending on the presence
of a .git or .svn subdirectory below the directory
where cloc is invoked.
--unicode Check binary files to see if they contain Unicode --unicode Check binary files to see if they contain Unicode
expanded ASCII text. This causes performance to expanded ASCII text. This causes performance to
drop noticeably. drop noticeably.
${BB}Processing Options${NN} ${BB}Processing Options${NN}
--autoconf Count .in files (as processed by GNU autoconf) of --autoconf Count .in files (as processed by GNU autoconf) of
recognized languages. See also --no-autogen. recognized languages. See also --no-autogen.
--by-file Report results for every source file encountered. --by-file Report results for every source file encountered.
--by-file-by-lang Report results for every source file encountered --by-file-by-lang Report results for every source file encountered
in addition to reporting by language. in addition to reporting by language.
skipping to change at line 251 skipping to change at line 269
or archives. If --out or --report-file is given, or archives. If --out or --report-file is given,
three output files will be created, one for each three output files will be created, one for each
of the two counts and one for the diff. See also of the two counts and one for the diff. See also
--diff, --diff-alignment, --diff-timeout, --diff, --diff-alignment, --diff-timeout,
--ignore-case, --ignore-whitespace. --ignore-case, --ignore-whitespace.
--diff <set1> <set2> Compute differences in code and comments between --diff <set1> <set2> Compute differences in code and comments between
source file(s) of <set1> and <set2>. The inputs source file(s) of <set1> and <set2>. The inputs
may be any mix of files, directories, archives, may be any mix of files, directories, archives,
or git commit hashes. Use --diff-alignment to or git commit hashes. Use --diff-alignment to
generate a list showing which file pairs where generate a list showing which file pairs where
compared. See also --count-and-diff, --diff-alignm compared. When comparing git branches, only files
ent. which have changed in either commit are compared.
--diff-timeout, --ignore-case, --ignore-whitespace, See also --git, --count-and-diff, --diff-alignment,
--diff-list-file, --diff-timeout, --ignore-case,
--ignore-whitespace.
--diff-timeout <N> Ignore files which take more than <N> seconds --diff-timeout <N> Ignore files which take more than <N> seconds
to process. Default is 10 seconds. Setting <N> to process. Default is 10 seconds. Setting <N>
to 0 allows unlimited time. (Large files with many to 0 allows unlimited time. (Large files with many
repeated lines can cause Algorithm::Diff::sdiff() repeated lines can cause Algorithm::Diff::sdiff()
to take hours.) See also --timeout. to take hours.) See also --timeout.
--docstring-as-code cloc considers docstrings to be comments, but this is --docstring-as-code cloc considers docstrings to be comments, but this is
not always correct as docstrings represent regular not always correct as docstrings represent regular
strings when they appear on the right hand side of an strings when they appear on the right hand side of an
assignment or as function arguments. This switch assignment or as function arguments. This switch
forces docstrings to be counted as code. forces docstrings to be counted as code.
skipping to change at line 303 skipping to change at line 324
are not first identified as file or directory are not first identified as file or directory
names. This option overrides the --vcs=git logic names. This option overrides the --vcs=git logic
if this is given; in other words, --git gets its if this is given; in other words, --git gets its
list of files to work on directly from git using list of files to work on directly from git using
the hash or branch name rather than from the hash or branch name rather than from
'git ls-files'. This option can be used with 'git ls-files'. This option can be used with
--diff to perform line count diffs between git --diff to perform line count diffs between git
commits, or between a git commit and a file, commits, or between a git commit and a file,
directory, or archive. Use -v/--verbose to see directory, or archive. Use -v/--verbose to see
the git system commands cloc issues. the git system commands cloc issues.
--git-diff-rel Same as --git --diff, or just --diff if the inputs
are recognized as git targets. Only files which
have changed in either commit are compared.
--git-diff-all Git diff strategy #2: compare all files in the
repository between the two commits.
--ignore-whitespace Ignore horizontal white space when comparing files --ignore-whitespace Ignore horizontal white space when comparing files
with --diff. See also --ignore-case. with --diff. See also --ignore-case.
--ignore-case Ignore changes in case; consider upper- and lower- --ignore-case Ignore changes in case within file contents;
case letters equivalent when comparing files with consider upper- and lowercase letters equivalent
--diff. See also --ignore-whitespace. when comparing files with --diff. See also
--ignore-whitespace.
--ignore-case-ext Ignore case of file name extensions. This will
cause problems counting some languages
(specifically, .c and .C are associated with C and
C++; this switch would count .C files as C rather
than C++ on *nix operating systems). File name
case insensitivity is always true on Windows.
--lang-no-ext=<lang> Count files without extensions using the <lang> --lang-no-ext=<lang> Count files without extensions using the <lang>
counter. This option overrides internal logic counter. This option overrides internal logic
for files without extensions (where such files for files without extensions (where such files
are checked against known scripting languages are checked against known scripting languages
by examining the first line for #!). See also by examining the first line for #!). See also
--force-lang, --script-lang. --force-lang, --script-lang.
--max-file-size=<MB> Skip files larger than <MB> megabytes when --max-file-size=<MB> Skip files larger than <MB> megabytes when
traversing directories. By default, <MB>=100. traversing directories. By default, <MB>=100.
cloc's memory requirement is roughly twenty times cloc's memory requirement is roughly twenty times
larger than the largest file so running with larger than the largest file so running with
skipping to change at line 611 skipping to change at line 644
my $start_time = get_time(); my $start_time = get_time();
my ( my (
$opt_categorized , $opt_categorized ,
$opt_found , $opt_found ,
@opt_force_lang , @opt_force_lang ,
$opt_lang_no_ext , $opt_lang_no_ext ,
@opt_script_lang , @opt_script_lang ,
$opt_count_diff , $opt_count_diff ,
$opt_diff , $opt_diff ,
$opt_diff_alignment , $opt_diff_alignment ,
$opt_diff_list_file ,
$opt_diff_timeout , $opt_diff_timeout ,
$opt_timeout , $opt_timeout ,
$opt_html , $opt_html ,
$opt_ignored , $opt_ignored ,
$opt_counted , $opt_counted ,
$opt_show_ext , $opt_show_ext ,
$opt_show_lang , $opt_show_lang ,
$opt_progress_rate , $opt_progress_rate ,
$opt_print_filter_stages , $opt_print_filter_stages ,
$opt_v , $opt_v ,
skipping to change at line 674 skipping to change at line 708
$opt_skip_win_hidden , $opt_skip_win_hidden ,
$opt_read_binary_files , $opt_read_binary_files ,
$opt_sql , $opt_sql ,
$opt_sql_append , $opt_sql_append ,
$opt_sql_project , $opt_sql_project ,
$opt_sql_style , $opt_sql_style ,
$opt_inline , $opt_inline ,
$opt_exclude_ext , $opt_exclude_ext ,
$opt_ignore_whitespace , $opt_ignore_whitespace ,
$opt_ignore_case , $opt_ignore_case ,
$opt_ignore_case_ext ,
$opt_follow_links , $opt_follow_links ,
$opt_autoconf , $opt_autoconf ,
$opt_sum_one , $opt_sum_one ,
$opt_stdin_name , $opt_stdin_name ,
$opt_force_on_windows , $opt_force_on_windows ,
$opt_force_on_unix , # actually forces !$ON_WINDOWS $opt_force_on_unix , # actually forces !$ON_WINDOWS
$opt_show_os , $opt_show_os ,
$opt_skip_archive , $opt_skip_archive ,
$opt_max_file_size , # in MB $opt_max_file_size , # in MB
$opt_use_sloccount , $opt_use_sloccount ,
$opt_no_autogen , $opt_no_autogen ,
$opt_force_git , $opt_force_git ,
$opt_git_diff_rel ,
$opt_git_diff_all ,
$opt_git_diff_simindex ,
$opt_config_file , $opt_config_file ,
$opt_strip_str_comments , $opt_strip_str_comments ,
$opt_file_encoding , $opt_file_encoding ,
$opt_docstring_as_code , $opt_docstring_as_code ,
$opt_stat , $opt_stat ,
); );
my $getopt_success = GetOptions( # {{{1 my $getopt_success = GetOptions( # {{{1
"by_file|by-file" => \$opt_by_file , "by_file|by-file" => \$opt_by_file ,
"by_file_by_lang|by-file-by-lang" => \$opt_by_file_by_lang , "by_file_by_lang|by-file-by-lang" => \$opt_by_file_by_lang ,
skipping to change at line 711 skipping to change at line 749
"exclude_lang|exclude-lang=s" => \$opt_exclude_lang , "exclude_lang|exclude-lang=s" => \$opt_exclude_lang ,
"exclude_dir|exclude-dir=s" => \$opt_exclude_dir , "exclude_dir|exclude-dir=s" => \$opt_exclude_dir ,
"exclude_list_file|exclude-list-file=s" => \$opt_exclude_list_file , "exclude_list_file|exclude-list-file=s" => \$opt_exclude_list_file ,
"explain=s" => \$opt_explain , "explain=s" => \$opt_explain ,
"extract_with|extract-with=s" => \$opt_extract_with , "extract_with|extract-with=s" => \$opt_extract_with ,
"found=s" => \$opt_found , "found=s" => \$opt_found ,
"count_and_diff|count-and-diff" => \$opt_count_diff , "count_and_diff|count-and-diff" => \$opt_count_diff ,
"diff" => \$opt_diff , "diff" => \$opt_diff ,
"diff-alignment|diff_alignment=s" => \$opt_diff_alignment , "diff-alignment|diff_alignment=s" => \$opt_diff_alignment ,
"diff-timeout|diff_timeout=i" => \$opt_diff_timeout , "diff-timeout|diff_timeout=i" => \$opt_diff_timeout ,
"diff-list-file|diff_list_file=s" => \$opt_diff_list_file ,
"timeout=i" => \$opt_timeout , "timeout=i" => \$opt_timeout ,
"html" => \$opt_html , "html" => \$opt_html ,
"ignored=s" => \$opt_ignored , "ignored=s" => \$opt_ignored ,
"quiet" => \$opt_quiet , "quiet" => \$opt_quiet ,
"force_lang_def|force-lang-def=s" => \$opt_force_lang_def , "force_lang_def|force-lang-def=s" => \$opt_force_lang_def ,
"read_lang_def|read-lang-def=s" => \$opt_read_lang_def , "read_lang_def|read-lang-def=s" => \$opt_read_lang_def ,
"show_ext|show-ext:s" => \$opt_show_ext , "show_ext|show-ext:s" => \$opt_show_ext ,
"show_lang|show-lang:s" => \$opt_show_lang , "show_lang|show-lang:s" => \$opt_show_lang ,
"progress_rate|progress-rate=i" => \$opt_progress_rate , "progress_rate|progress-rate=i" => \$opt_progress_rate ,
"print_filter_stages|print-filter-stages" => \$opt_print_filter_stages , "print_filter_stages|print-filter-stages" => \$opt_print_filter_stages ,
skipping to change at line 765 skipping to change at line 804
"skip_win_hidden|skip-win-hidden" => \$opt_skip_win_hidden , "skip_win_hidden|skip-win-hidden" => \$opt_skip_win_hidden ,
"read_binary_files|read-binary-files" => \$opt_read_binary_files , "read_binary_files|read-binary-files" => \$opt_read_binary_files ,
"sql=s" => \$opt_sql , "sql=s" => \$opt_sql ,
"sql_project|sql-project=s" => \$opt_sql_project , "sql_project|sql-project=s" => \$opt_sql_project ,
"sql_append|sql-append" => \$opt_sql_append , "sql_append|sql-append" => \$opt_sql_append ,
"sql_style|sql-style=s" => \$opt_sql_style , "sql_style|sql-style=s" => \$opt_sql_style ,
"inline" => \$opt_inline , "inline" => \$opt_inline ,
"exclude_ext|exclude-ext=s" => \$opt_exclude_ext , "exclude_ext|exclude-ext=s" => \$opt_exclude_ext ,
"ignore_whitespace|ignore-whitespace" => \$opt_ignore_whitespace , "ignore_whitespace|ignore-whitespace" => \$opt_ignore_whitespace ,
"ignore_case|ignore-case" => \$opt_ignore_case , "ignore_case|ignore-case" => \$opt_ignore_case ,
"ignore_case_ext|ignore-case-ext" => \$opt_ignore_case_ext ,
"follow_links|follow-links" => \$opt_follow_links , "follow_links|follow-links" => \$opt_follow_links ,
"autoconf" => \$opt_autoconf , "autoconf" => \$opt_autoconf ,
"sum_one|sum-one" => \$opt_sum_one , "sum_one|sum-one" => \$opt_sum_one ,
"by_percent|by-percent=s" => \$opt_by_percent , "by_percent|by-percent=s" => \$opt_by_percent ,
"stdin_name|stdin-name=s" => \$opt_stdin_name , "stdin_name|stdin-name=s" => \$opt_stdin_name ,
"windows" => \$opt_force_on_windows , "windows" => \$opt_force_on_windows ,
"unix" => \$opt_force_on_unix , "unix" => \$opt_force_on_unix ,
"show_os|show-os" => \$opt_show_os , "show_os|show-os" => \$opt_show_os ,
"skip_archive|skip-archive=s" => \$opt_skip_archive , "skip_archive|skip-archive=s" => \$opt_skip_archive ,
"max_file_size|max-file-size=i" => \$opt_max_file_size , "max_file_size|max-file-size=i" => \$opt_max_file_size ,
"use_sloccount|use-sloccount" => \$opt_use_sloccount , "use_sloccount|use-sloccount" => \$opt_use_sloccount ,
"no_autogen|no-autogen" => \$opt_no_autogen , "no_autogen|no-autogen" => \$opt_no_autogen ,
"git" => \$opt_force_git , "git" => \$opt_force_git ,
"git_diff_rel|git-diff-rel" => \$opt_git_diff_rel ,
"git_diff_all|git-diff-all" => \$opt_git_diff_all ,
# "git_diff_simindex|git-diff-simindex" => \$opt_git_diff_simindex ,
"config=s" => \$opt_config_file , "config=s" => \$opt_config_file ,
"strip_str_comments|strip-str-comments" => \$opt_strip_str_comments , "strip_str_comments|strip-str-comments" => \$opt_strip_str_comments ,
"file_encoding|file-encoding=s" => \$opt_file_encoding , "file_encoding|file-encoding=s" => \$opt_file_encoding ,
"docstring_as_code|docstring-as-code" => \$opt_docstring_as_code , "docstring_as_code|docstring-as-code" => \$opt_docstring_as_code ,
"stat" => \$opt_stat , "stat" => \$opt_stat ,
); );
# 1}}} # 1}}}
$config_file = $opt_config_file if defined $opt_config_file; $config_file = $opt_config_file if defined $opt_config_file;
load_from_config_file($config_file, # {{{2 load_from_config_file($config_file, # {{{2
\$opt_by_file , \$opt_by_file ,
skipping to change at line 856 skipping to change at line 899
\$opt_skip_win_hidden , \$opt_skip_win_hidden ,
\$opt_read_binary_files , \$opt_read_binary_files ,
\$opt_sql , \$opt_sql ,
\$opt_sql_project , \$opt_sql_project ,
\$opt_sql_append , \$opt_sql_append ,
\$opt_sql_style , \$opt_sql_style ,
\$opt_inline , \$opt_inline ,
\$opt_exclude_ext , \$opt_exclude_ext ,
\$opt_ignore_whitespace , \$opt_ignore_whitespace ,
\$opt_ignore_case , \$opt_ignore_case ,
\$opt_ignore_case_ext ,
\$opt_follow_links , \$opt_follow_links ,
\$opt_autoconf , \$opt_autoconf ,
\$opt_sum_one , \$opt_sum_one ,
\$opt_by_percent , \$opt_by_percent ,
\$opt_stdin_name , \$opt_stdin_name ,
\$opt_force_on_windows , \$opt_force_on_windows ,
\$opt_force_on_unix , \$opt_force_on_unix ,
\$opt_show_os , \$opt_show_os ,
\$opt_skip_archive , \$opt_skip_archive ,
\$opt_max_file_size , \$opt_max_file_size ,
skipping to change at line 905 skipping to change at line 949
if $opt_include_lang; if $opt_include_lang;
# Forcibly exclude .svn, .cvs, .hg, .git, .bzr directories. The contents of the se # Forcibly exclude .svn, .cvs, .hg, .git, .bzr directories. The contents of the se
# directories often conflict with files of interest. # directories often conflict with files of interest.
$opt_exclude_dir = 1; $opt_exclude_dir = 1;
$Exclude_Dir{".svn"} = 1; $Exclude_Dir{".svn"} = 1;
$Exclude_Dir{".cvs"} = 1; $Exclude_Dir{".cvs"} = 1;
$Exclude_Dir{".hg"} = 1; $Exclude_Dir{".hg"} = 1;
$Exclude_Dir{".git"} = 1; $Exclude_Dir{".git"} = 1;
$Exclude_Dir{".bzr"} = 1; $Exclude_Dir{".bzr"} = 1;
$Exclude_Dir{".snapshot"} = 1; # NetApp backups $Exclude_Dir{".snapshot"} = 1; # NetApp backups
$Exclude_Dir{".config"} = 1;
$opt_count_diff = defined $opt_count_diff ? 1 : 0; $opt_count_diff = defined $opt_count_diff ? 1 : 0;
$opt_diff = 1 if $opt_diff_alignment; $opt_diff = 1 if $opt_diff_alignment or
$opt_diff_list_file or
$opt_git_diff_rel or
$opt_git_diff_all or
$opt_git_diff_simindex;
$opt_force_git = 1 if $opt_git_diff_rel or
$opt_git_diff_all or
$opt_git_diff_simindex;
$opt_diff_alignment = 0 if $opt_diff_list_file;
$opt_exclude_ext = "" unless $opt_exclude_ext; $opt_exclude_ext = "" unless $opt_exclude_ext;
$opt_ignore_whitespace = 0 unless $opt_ignore_whitespace; $opt_ignore_whitespace = 0 unless $opt_ignore_whitespace;
$opt_ignore_case = 0 unless $opt_ignore_case; $opt_ignore_case = 0 unless $opt_ignore_case;
$opt_ignore_case_ext = 0 unless $opt_ignore_case_ext;
$opt_lang_no_ext = 0 unless $opt_lang_no_ext; $opt_lang_no_ext = 0 unless $opt_lang_no_ext;
$opt_follow_links = 0 unless $opt_follow_links; $opt_follow_links = 0 unless $opt_follow_links;
if (defined $opt_diff_timeout) { if (defined $opt_diff_timeout) {
# if defined but with a value of <= 0, set to 2^31 seconds = 68 years # if defined but with a value of <= 0, set to 2^31 seconds = 68 years
$opt_diff_timeout = 2**31 unless $opt_diff_timeout > 0; $opt_diff_timeout = 2**31 unless $opt_diff_timeout > 0;
} else { } else {
$opt_diff_timeout =10; # seconds $opt_diff_timeout =10; # seconds
} }
if (defined $opt_timeout) { if (defined $opt_timeout) {
# if defined but with a value of <= 0, set to 2^31 seconds = 68 years # if defined but with a value of <= 0, set to 2^31 seconds = 68 years
skipping to change at line 955 skipping to change at line 1009
$opt_diff = 0; $opt_diff = 0;
$opt_count_diff = undef; $opt_count_diff = undef;
$opt_unicode = 0; $opt_unicode = 0;
$opt_strip_comments = 0; $opt_strip_comments = 0;
} }
} }
$opt_vcs = 0 if $opt_force_git; $opt_vcs = 0 if $opt_force_git;
my @COUNT_DIFF_ARGV = undef; my @COUNT_DIFF_ARGV = undef;
my $COUNT_DIFF_report_file = undef; my $COUNT_DIFF_report_file = undef;
if ($opt_count_diff) { if ($opt_count_diff and !$opt_diff_list_file) {
die "--count-and-diff requires two arguments; got ", scalar @ARGV, "\n" die "--count-and-diff requires two arguments; got ", scalar @ARGV, "\n"
if scalar @ARGV != 2; if scalar @ARGV != 2;
# prefix with a dummy term so that $opt_count_diff is the # prefix with a dummy term so that $opt_count_diff is the
# index into @COUNT_DIFF_ARGV to work on at each pass # index into @COUNT_DIFF_ARGV to work on at each pass
@COUNT_DIFF_ARGV = (undef, $ARGV[0], @COUNT_DIFF_ARGV = (undef, $ARGV[0],
$ARGV[1], $ARGV[1],
[$ARGV[0], $ARGV[1]]); # 3rd pass: diff them [$ARGV[0], $ARGV[1]]); # 3rd pass: diff them
$COUNT_DIFF_report_file = $opt_report_file if $opt_report_file; $COUNT_DIFF_report_file = $opt_report_file if $opt_report_file;
} }
skipping to change at line 1006 skipping to change at line 1060
die "'$opt_sql_style' is not a recognized SQL style.\n"; die "'$opt_sql_style' is not a recognized SQL style.\n";
} }
} }
$opt_by_percent = '' unless defined $opt_by_percent; $opt_by_percent = '' unless defined $opt_by_percent;
if ($opt_by_percent and $opt_by_percent !~ m/^(c|cm|cb|cmb)$/i) { if ($opt_by_percent and $opt_by_percent !~ m/^(c|cm|cb|cmb)$/i) {
die "--by-percent must be either 'c', 'cm', 'cb', or 'cmb'\n"; die "--by-percent must be either 'c', 'cm', 'cb', or 'cmb'\n";
} }
$opt_by_percent = lc $opt_by_percent; $opt_by_percent = lc $opt_by_percent;
if (defined $opt_vcs) { if (defined $opt_vcs) {
if ($opt_vcs eq "auto") {
if (-d ".git") {
$opt_vcs = "git";
} elsif (-d ".svn") {
$opt_vcs = "svn";
} else {
warn "--vcs auto: unable to determine versioning system\n";
}
}
if ($opt_vcs eq "git") { if ($opt_vcs eq "git") {
$opt_vcs = "git ls-files"; $opt_vcs = "git ls-files";
my @submodules = invoke_generator('git submodule status'); my @submodules = invoke_generator('git submodule status');
foreach my $SM (@submodules) { foreach my $SM (@submodules) {
$SM =~ s/^\s+//; # may have leading space $SM =~ s/^\s+//; # may have leading space
$SM =~ s/\(\S+\)\s*$//; # may end with something like (heads/master) $SM =~ s/\(\S+\)\s*$//; # may end with something like (heads/master)
my ($checksum, $dir) = split(' ', $SM, 2); my ($checksum, $dir) = split(' ', $SM, 2);
$dir =~ s/\s+$//; $dir =~ s/\s+$//;
$Exclude_Dir{$dir} = 1; $Exclude_Dir{$dir} = 1;
} }
} elsif ($opt_vcs eq "svn") { } elsif ($opt_vcs eq "svn") {
$opt_vcs = "svn list -R"; $opt_vcs = "svn list -R";
} }
} }
my $list_no_autogen = 0; my $list_no_autogen = 0;
if (defined $opt_no_autogen and scalar @ARGV == 1 and $ARGV[0] eq "list") { if (defined $opt_no_autogen and scalar @ARGV == 1 and $ARGV[0] eq "list") {
$list_no_autogen = 1; $list_no_autogen = 1;
} }
die $brief_usage unless defined $opt_version or die $brief_usage unless defined $opt_version or
defined $opt_show_lang or defined $opt_show_lang or
defined $opt_show_ext or defined $opt_show_ext or
defined $opt_show_os or defined $opt_show_os or
defined $opt_write_lang_def or defined $opt_write_lang_def or
defined $opt_write_lang_def_incl_dup or defined $opt_write_lang_def_incl_dup or
defined $opt_list_file or defined $opt_list_file or
defined $opt_diff_list_file or
defined $opt_vcs or defined $opt_vcs or
defined $opt_xsl or defined $opt_xsl or
defined $opt_explain or defined $opt_explain or
$list_no_autogen or $list_no_autogen or
scalar @ARGV >= 1; scalar @ARGV >= 1;
die "--diff requires two arguments; got ", scalar @ARGV, "\n" if (!$opt_diff_list_file) {
if $opt_diff and !$opt_sum_reports and scalar @ARGV != 2; die "--diff requires two arguments; got ", scalar @ARGV, "\n"
die "--diff arguments are identical; nothing done", "\n" if $opt_diff and !$opt_sum_reports and scalar @ARGV != 2;
if $opt_diff and !$opt_sum_reports and scalar @ARGV == 2 die "--diff arguments are identical; nothing done", "\n"
and $ARGV[0] eq $ARGV[1]; if $opt_diff and !$opt_sum_reports and scalar @ARGV == 2
and $ARGV[0] eq $ARGV[1];
}
trick_pp_packer_encode() if $ON_WINDOWS and $opt_file_encoding; trick_pp_packer_encode() if $ON_WINDOWS and $opt_file_encoding;
$File::Find::dont_use_nlink = 1 if $opt_stat or top_level_SMB_dir(\@ARGV); $File::Find::dont_use_nlink = 1 if $opt_stat or top_level_SMB_dir(\@ARGV);
replace_git_hash_with_tarfile(\@ARGV); my @git_similarity = (); # only populated with --git-diff-simindex
replace_git_hash_with_tarfile(\@ARGV, \@git_similarity);
# 1}}} # 1}}}
# Step 1: Initialize global constants. {{{1 # Step 1: Initialize global constants. {{{1
# #
my $nFiles_Found = 0; # updated in make_file_list my $nFiles_Found = 0; # updated in make_file_list
my (%Language_by_Extension, %Language_by_Script, my (%Language_by_Extension, %Language_by_Script,
%Filters_by_Language, %Not_Code_Extension, %Not_Code_Filename, %Filters_by_Language, %Not_Code_Extension, %Not_Code_Filename,
%Language_by_File, %Scale_Factor, %Known_Binary_Archives, %Language_by_File, %Scale_Factor, %Known_Binary_Archives,
%EOL_Continuation_re, %EOL_Continuation_re,
); );
my $ALREADY_SHOWED_HEADER = 0; my $ALREADY_SHOWED_HEADER = 0;
skipping to change at line 1076 skipping to change at line 1143
'D/dtrace' => [ 'd' ] , 'D/dtrace' => [ 'd' ] ,
'F#/Forth' => [ 'fs' ] , 'F#/Forth' => [ 'fs' ] ,
'Fortran 77/Forth' => [ 'f', 'for' ] , 'Fortran 77/Forth' => [ 'f', 'for' ] ,
'IDL/Qt Project/Prolog/ProGuard' => [ 'pro' ] , 'IDL/Qt Project/Prolog/ProGuard' => [ 'pro' ] ,
'Lisp/Julia' => [ 'jl' ] , 'Lisp/Julia' => [ 'jl' ] ,
'Lisp/OpenCL' => [ 'cl' ] , 'Lisp/OpenCL' => [ 'cl' ] ,
'MATLAB/Mathematica/Objective C/MUMPS/Mercury' => [ 'm' ] , 'MATLAB/Mathematica/Objective C/MUMPS/Mercury' => [ 'm' ] ,
'Pascal/Puppet' => [ 'pp' ] , 'Pascal/Puppet' => [ 'pp' ] ,
'Perl/Prolog' => [ 'pl', 'PL' ] , 'Perl/Prolog' => [ 'pl', 'PL' ] ,
'PHP/Pascal' => [ 'inc' ] , 'PHP/Pascal' => [ 'inc' ] ,
'Raku/Prolog' => [ 'p6', 'P6' ] ,
'Qt/Glade' => [ 'ui' ] , 'Qt/Glade' => [ 'ui' ] ,
'TypeScript/Qt Linguist' => [ 'ts' ] , 'TypeScript/Qt Linguist' => [ 'ts' ] ,
'Verilog-SystemVerilog/Coq' => [ 'v' ] , 'Verilog-SystemVerilog/Coq' => [ 'v' ] ,
'Visual Basic/TeX/Apex Class' => [ 'cls' ] , 'Visual Basic/TeX/Apex Class' => [ 'cls' ] ,
'Scheme/SaltStack' => [ 'sls' ] , 'Scheme/SaltStack' => [ 'sls' ] ,
); );
my @Autogen_to_ignore = no_autogen_files($list_no_autogen); my @Autogen_to_ignore = no_autogen_files($list_no_autogen);
if ($opt_force_lang_def) { if ($opt_force_lang_def) {
# replace cloc's definitions # replace cloc's definitions
read_lang_def( read_lang_def(
skipping to change at line 1179 skipping to change at line 1247
die_unknown_lang($lang, "--script-lang") die_unknown_lang($lang, "--script-lang")
unless $Recognized_Language_lc{$lang_lc}; unless $Recognized_Language_lc{$lang_lc};
$Language_by_Script{$script_name} = $Recognized_Language_lc{$lang_lc}; $Language_by_Script{$script_name} = $Recognized_Language_lc{$lang_lc};
} }
# If user provided file extensions to ignore, add these to # If user provided file extensions to ignore, add these to
# the exclusion list. # the exclusion list.
foreach my $ext (map { $_ => 1 } split(/,/, $opt_exclude_ext ) ) { foreach my $ext (map { $_ => 1 } split(/,/, $opt_exclude_ext ) ) {
$ext = lc $ext if $ON_WINDOWS; $ext = lc $ext if $ON_WINDOWS or $opt_ignore_case_ext;
$Not_Code_Extension{$ext} = 1; $Not_Code_Extension{$ext} = 1;
} }
# If SQL or --by-file output is requested, keep track of directory names # If SQL or --by-file output is requested, keep track of directory names
# generated by File::Temp::tempdir and used to temporarily hold the results # generated by File::Temp::tempdir and used to temporarily hold the results
# of compressed archives. Contents of the SQL table 't' will be much # of compressed archives. Contents of the SQL table 't' will be much
# cleaner if these meaningless directory names are stripped from the front # cleaner if these meaningless directory names are stripped from the front
# of files pulled from the archives. # of files pulled from the archives.
my %TEMP_DIR = (); my %TEMP_DIR = ();
my $TEMP_OFF = 0; # Needed for --sdir; keep track of the number of my $TEMP_OFF = 0; # Needed for --sdir; keep track of the number of
skipping to change at line 1444 skipping to change at line 1512
$binary_archives_exist = 0; $binary_archives_exist = 0;
} }
$previous_count = $count_binary_archives; $previous_count = $count_binary_archives;
} }
chdir $cwd; chdir $cwd;
@ARGV = @extract_location; @ARGV = @extract_location;
} else { } else {
# see if any of the inputs need to be auto-uncompressed &/or expanded # see if any of the inputs need to be auto-uncompressed &/or expanded
my @updated_ARGS = (); my @updated_ARGS = ();
replace_git_hash_with_tarfile(\@ARGV) if $opt_force_git; replace_git_hash_with_tarfile(\@ARGV, \@git_similarity) if $opt_force_git;
foreach my $Arg (@ARGV) { foreach my $Arg (@ARGV) {
if (is_dir($Arg)) { if (is_dir($Arg)) {
push @updated_ARGS, $Arg; push @updated_ARGS, $Arg;
next; next;
} }
my $full_path = ""; my $full_path = "";
if (File::Spec->file_name_is_absolute( $Arg )) { if (File::Spec->file_name_is_absolute( $Arg )) {
$full_path = $Arg; $full_path = $Arg;
} else { } else {
$full_path = File::Spec->catfile( $cwd, $Arg ); $full_path = File::Spec->catfile( $cwd, $Arg );
skipping to change at line 1513 skipping to change at line 1581
# 1}}} # 1}}}
my @Errors = (); my @Errors = ();
my @file_list = (); # global variable updated in files() my @file_list = (); # global variable updated in files()
my %Ignored = (); # files that are not counted (language not recognized or my %Ignored = (); # files that are not counted (language not recognized or
# problems reading the file) # problems reading the file)
my @Lines_Out = (); my @Lines_Out = ();
if ($opt_diff) { if ($opt_diff) {
# Step 4: Separate code from non-code files. {{{1 # Step 4: Separate code from non-code files. {{{1
my @fh = (); my @fh = ();
my @files_for_set = (); my @files_for_set = ();
my @files_added_tot = ();
my @files_removed_tot = ();
my @file_pairs_tot = ();
# make file lists for each separate argument # make file lists for each separate argument
if ($opt_diff_list_file) {
@files_for_set = ( (), () );
file_pairs_from_file($opt_diff_list_file, # in
\@files_added_tot , # out
\@files_removed_tot , # out
\@file_pairs_tot , # out
);
foreach my $F (@files_added_tot) {
push @{$files_for_set[1]}, $F;
}
foreach my $F (@files_removed_tot) {
push @{$files_for_set[0]}, $F;
}
foreach my $pair (@file_pairs_tot) {
push @{$files_for_set[0]}, $pair->[0];
push @{$files_for_set[1]}, $pair->[1];
}
@ARGV = (1, 2); # place holders
}
for (my $i = 0; $i < scalar @ARGV; $i++) { for (my $i = 0; $i < scalar @ARGV; $i++) {
push @fh, if ($opt_diff_list_file) {
make_file_list([ $ARGV[$i] ], \%Error_Codes, \@Errors, \%Ignored); push @fh, make_file_list($files_for_set[$i],
@{$files_for_set[$i]} = @file_list; \%Error_Codes, \@Errors, \%Ignored);
@{$files_for_set[$i]} = @file_list;
} else {
push @fh, make_file_list([ $ARGV[$i] ],
\%Error_Codes, \@Errors, \%Ignored);
@{$files_for_set[$i]} = @file_list;
}
if ($opt_exclude_list_file) { if ($opt_exclude_list_file) {
# note: process_exclude_list_file() references global @file_list # note: process_exclude_list_file() references global @file_list
process_exclude_list_file($opt_exclude_list_file, process_exclude_list_file($opt_exclude_list_file,
\%Exclude_Dir, \%Exclude_Dir,
\%Ignored); \%Ignored);
} }
if ($opt_no_autogen) { if ($opt_no_autogen) {
exclude_autogenerated_files(\@{$files_for_set[$i]}, # in/out exclude_autogenerated_files(\@{$files_for_set[$i]}, # in/out
\%Error_Codes, \@Errors, \%Ignored); \%Error_Codes, \@Errors, \%Ignored);
} }
skipping to change at line 1549 skipping to change at line 1645
\%{$Language{$FH}} , \%{$Language{$FH}} ,
\%{$unique_source_file{$FH}} , \%{$unique_source_file{$FH}} ,
\%Error_Codes , \%Error_Codes ,
\@Errors , \@Errors ,
\%Ignored ); \%Ignored );
if ($opt_exclude_content) { if ($opt_exclude_content) {
exclude_by_regex($opt_exclude_content, # in exclude_by_regex($opt_exclude_content, # in
\%{$unique_source_file{$FH}}, # in/out \%{$unique_source_file{$FH}}, # in/out
\%Ignored); # out \%Ignored); # out
} }
if ($opt_include_lang) {
# remove files associated with languages not
# specified by --include-lang
my @delete_file = ();
foreach my $file (keys %{$unique_source_file{$FH}}) {
my $keep_file = 0;
foreach my $keep_lang (keys %Include_Language) {
if ($Language{$FH}{$file} eq $keep_lang) {
$keep_file = 1;
last;
}
}
next if $keep_file;
push @delete_file, $file;
}
foreach my $file (@delete_file) {
delete $Language{$FH}{$file};
}
}
printf "%2d: %8d unique file%s. \r", printf "%2d: %8d unique file%s. \r",
$n_set, $n_set,
plural_form(scalar keys %unique_source_file) plural_form(scalar keys %unique_source_file)
unless $opt_quiet; unless $opt_quiet;
} }
# 1}}} # 1}}}
# Step 6: Count code, comments, blank lines. {{{1 # Step 6: Count code, comments, blank lines. {{{1
# #
my %Results_by_Language = (); my %Results_by_Language = ();
my %Results_by_File = (); my %Results_by_File = ();
my %Delta_by_Language = (); my %Delta_by_Language = ();
my %Delta_by_File = (); my %Delta_by_File = ();
my @files_added_tot = ();
my @files_removed_tot = ();
my @file_pairs_tot = ();
my %alignment = (); my %alignment = ();
my $fset_a = $fh[0]; my $fset_a = $fh[0];
my $fset_b = $fh[1]; my $fset_b = $fh[1];
my $n_filepairs_compared = 0; my $n_filepairs_compared = 0;
my $tot_counted = 0; my $tot_counted = 0;
if ( scalar @fh != 2 ) { if ( scalar @fh != 2 ) {
print "Error: in correct length fh array when preparing diff at step 6.\n"; print "Error: incorrect length fh array when preparing diff at step 6.\n"
exit 1; ;
exit 1;
}
if (!$opt_diff_list_file) {
align_by_pairs(\%{$unique_source_file{$fset_a}} , # in
\%{$unique_source_file{$fset_b}} , # in
\@files_added_tot , # out
\@files_removed_tot , # out
\@file_pairs_tot , # out
);
} }
align_by_pairs(\%{$unique_source_file{$fset_a}} , # in
\%{$unique_source_file{$fset_b}} , # in
\@files_added_tot , # out
\@files_removed_tot , # out
\@file_pairs_tot , # out
);
#use Data::Dumper; #use Data::Dumper;
#print "added : ", Dumper(\@files_added_tot); #print "added : ", Dumper(\@files_added_tot);
#print "removed : ", Dumper(\@files_removed_tot); #print "removed : ", Dumper(\@files_removed_tot);
#print "pairs : ", Dumper(\@file_pairs_tot); #print "pairs : ", Dumper(\@file_pairs_tot);
if ( $max_processes == 0) { if ( $max_processes == 0) {
# Multiprocessing is disabled # Multiprocessing is disabled
my $part = count_filesets ( $fset_a, $fset_b, \@files_added_tot, my $part = count_filesets ( $fset_a, $fset_b, \@files_added_tot,
\@files_removed_tot, \@file_pairs_tot , 0, \%Lang \@files_removed_tot, \@file_pairs_tot,
uage); 0, \%Language, \%Ignored);
%Results_by_File = %{$part->{'results_by_file'}}; %Results_by_File = %{$part->{'results_by_file'}};
%Results_by_Language= %{$part->{'results_by_language'}}; %Results_by_Language= %{$part->{'results_by_language'}};
%Delta_by_File = %{$part->{'delta_by_file'}}; %Delta_by_File = %{$part->{'delta_by_file'}};
%Delta_by_Language= %{$part->{'delta_by_language'}}; %Delta_by_Language= %{$part->{'delta_by_language'}};
%Ignored = ( %Ignored, %{$part->{'ignored'}}); %Ignored = ( %Ignored, %{$part->{'ignored'}});
%alignment = %{$part->{'alignment'}}; %alignment = %{$part->{'alignment'}};
$n_filepairs_compared = $part->{'n_filepairs_compared'}; $n_filepairs_compared = $part->{'n_filepairs_compared'};
push ( @Errors, @{$part->{'errors'}}); push ( @Errors, @{$part->{'errors'}});
} else { } else {
# Multiprocessing is enabled # Multiprocessing is enabled
skipping to change at line 1629 skipping to change at line 1746
my $part_result_by_language = $part->{'results_by_language'}; my $part_result_by_language = $part->{'results_by_language'};
my $part_delta_by_file = $part->{'delta_by_file'}; my $part_delta_by_file = $part->{'delta_by_file'};
my $part_delta_by_language = $part->{'delta_by_language'}; my $part_delta_by_language = $part->{'delta_by_language'};
my $part_alignment = $part->{'alignment'}; my $part_alignment = $part->{'alignment'};
my $part_errors = $part->{'errors'}; my $part_errors = $part->{'errors'};
$tot_counted += scalar keys %$part_result_by_file; $tot_counted += scalar keys %$part_result_by_file;
$n_filepairs_compared += $part->{'n_filepairs_compared'}; $n_filepairs_compared += $part->{'n_filepairs_compared'};
# Since files are processed by multiple processes, we can't measure # Since files are processed by multiple processes, we can't measure
# the number of processed files exactly. We approximate this by showing # the number of processed files exactly. We approximate this by showing
# the number of files counted by finished processes. # the number of files counted by finished processes.
printf "Counting: %d\r", $tot_counted printf "Counting: %d\r", $tot_counted
if $opt_progress_rate; if $opt_progress_rate;
foreach my $this_language ( keys %$part_result_by_language ) { foreach my $this_language ( keys %$part_result_by_language ) {
my $counts = $part_result_by_language->{$this_language}; my $counts = $part_result_by_language->{$this_language};
foreach my $inner_key ( keys %$counts ) { foreach my $inner_key ( keys %$counts ) {
$Results_by_Language{$this_language}{$inner_key} += $Results_by_Language{$this_language}{$inner_key} +=
$counts->{$inner_key}; $counts->{$inner_key};
} }
} }
skipping to change at line 1679 skipping to change at line 1796
my @files_added_part = splice @files_added_tot, 0, $num_filesadded_per_p art; my @files_added_part = splice @files_added_tot, 0, $num_filesadded_per_p art;
my @files_removed_part = splice @files_removed_tot, 0, $num_filesremoved _per_part; my @files_removed_part = splice @files_removed_tot, 0, $num_filesremoved _per_part;
my @filepairs_part = splice @file_pairs_tot, 0, $num_filepairs_per_part; my @filepairs_part = splice @file_pairs_tot, 0, $num_filepairs_per_part;
if ( scalar @files_added_part == 0 and scalar @files_removed_part == 0 a nd if ( scalar @files_added_part == 0 and scalar @files_removed_part == 0 a nd
scalar @filepairs_part == 0 ) { scalar @filepairs_part == 0 ) {
last; last;
} }
$pm->start() and next; $pm->start() and next;
my $count_result = count_filesets ( $fset_a, $fset_b, my $count_result = count_filesets ( $fset_a, $fset_b,
\@files_added_part, \@files_removed_part, \@filepairs_part, 1 , \%La \@files_added_part, \@files_removed_part,
nguage ); \@filepairs_part, 1, \%Language, \%Ignored );
$pm->finish(0 , $count_result); $pm->finish(0 , $count_result);
} }
# Wait for processes to finish # Wait for processes to finish
$pm->wait_all_children(); $pm->wait_all_children();
} }
# Write alignment data, if needed # Write alignment data, if needed
if ($opt_diff_alignment) { if ($opt_diff_alignment) {
write_alignment_data ( $opt_diff_alignment, $n_filepairs_compared, \%alignme nt ) ; write_alignment_data ( $opt_diff_alignment, $n_filepairs_compared, \%alignme nt ) ;
} }
skipping to change at line 1824 skipping to change at line 1942
$pm->run_on_finish ( sub { $pm->run_on_finish ( sub {
my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $part) = @_; my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $part) = @_;
my $part_ignored = $part->{'ignored'}; my $part_ignored = $part->{'ignored'};
my $part_result_by_file = $part->{'results_by_file'}; my $part_result_by_file = $part->{'results_by_file'};
my $part_result_by_language = $part->{'results_by_language'}; my $part_result_by_language = $part->{'results_by_language'};
my $part_errors = $part->{'errors'}; my $part_errors = $part->{'errors'};
my $nCounted+= scalar keys %$part_result_by_file; my $nCounted+= scalar keys %$part_result_by_file;
# Since files are processed by multiple processes, we can't measure # Since files are processed by multiple processes, we can't measure
# the number of processed files exactly. We approximate this by showing # the number of processed files exactly. We approximate this by showing
# the number of files counted by finished processes. # the number of files counted by finished processes.
printf "Counting: %d\r", $nCounted printf "Counting: %d\r", $nCounted
if $opt_progress_rate; if $opt_progress_rate;
foreach my $this_language ( keys %$part_result_by_language ) { foreach my $this_language ( keys %$part_result_by_language ) {
my $counts = $part_result_by_language->{$this_language}; my $counts = $part_result_by_language->{$this_language};
foreach my $inner_key ( keys %$counts ) { foreach my $inner_key ( keys %$counts ) {
$Results_by_Language{$this_language}{$inner_key} += $Results_by_Language{$this_language}{$inner_key} +=
$counts->{$inner_key}; $counts->{$inner_key};
} }
} }
%Results_by_File = ( %Results_by_File, %$part_result_by_file ); %Results_by_File = ( %Results_by_File, %$part_result_by_file );
skipping to change at line 1913 skipping to change at line 2031
$rh_ignored->{$file} = "line $line_num match for --exclude-conte nt=$regex"; $rh_ignored->{$file} = "line $line_num match for --exclude-conte nt=$regex";
push @exclude, $file; push @exclude, $file;
last; last;
} }
} }
} }
foreach my $file (@exclude) { foreach my $file (@exclude) {
delete $rh_unique_source_file->{$file}; delete $rh_unique_source_file->{$file};
} }
} # 1}}} } # 1}}}
sub get_max_processes { # {{{1 sub get_max_processes { # {{{1
# If user has specified valid number of processes, use that. # If user has specified valid number of processes, use that.
if (defined $opt_processes) { if (defined $opt_processes) {
eval "use Parallel::ForkManager 0.7.6;"; eval "use Parallel::ForkManager 0.7.6;";
if ( defined $Parallel::ForkManager::VERSION ) { if ( defined $Parallel::ForkManager::VERSION ) {
$HAVE_Parallel_ForkManager = 1; $HAVE_Parallel_ForkManager = 1;
} }
if ( $opt_processes !~ /^\d+$/ ) { if ( $opt_processes !~ /^\d+$/ ) {
print "Error: processes option argument must be numeric.\n"; print "Error: processes option argument must be numeric.\n";
exit 1; exit 1;
} }
elsif ( $opt_processes >0 and ! $HAVE_Parallel_ForkManager ) { elsif ( $opt_processes >0 and ! $HAVE_Parallel_ForkManager ) {
print "Error: cannot use multiple processes, because " . print "Error: cannot use multiple processes, because " .
"Parallel::ForkManager is not installed, or the version is too old.\n"; "Parallel::ForkManager is not installed, or the version is too old.\n";
exit 1; exit 1;
} }
elsif ( $opt_processes >0 and $ON_WINDOWS ) { elsif ( $opt_processes >0 and $ON_WINDOWS ) {
print "Error: cannot use multiple processes on Windows systems.\n"; print "Error: cannot use multiple processes on Windows systems.\n";
exit 1; exit 1;
} }
else { else {
return $opt_processes; return $opt_processes;
} }
} }
# Disable multiprocessing on Windows - does not work reliably # Disable multiprocessing on Windows - does not work reliably
if ($ON_WINDOWS) { if ($ON_WINDOWS) {
skipping to change at line 2102 skipping to change at line 2220
"results_by_language" => \%p_rbl, "results_by_language" => \%p_rbl,
} }
} # 1}}} } # 1}}}
sub count_filesets { # {{{1 sub count_filesets { # {{{1
my ($fset_a, my ($fset_a,
$fset_b, $fset_b,
$files_added, $files_added,
$files_removed, $files_removed,
$file_pairs, $file_pairs,
$counter_type, $counter_type,
$language_hash) = @_; $language_hash,
$rh_Ignored) = @_;
print "-> count_filesets()\n" if $opt_v > 2; print "-> count_filesets()\n" if $opt_v > 2;
my @p_errors = (); my @p_errors = ();
my %p_alignment = (); my %p_alignment = ();
my %p_ignored = (); my %p_ignored = ();
my %p_rbl = (); my %p_rbl = ();
my %p_rbf = (); my %p_rbf = ();
my %p_dbl = (); my %p_dbl = ();
my %p_dbf = (); my %p_dbf = ();
my %Language = %$language_hash; my %Language = %$language_hash;
skipping to change at line 2163 skipping to change at line 2282
foreach my $f (@$files_added) { foreach my $f (@$files_added) {
next if $already_counted{$f}; next if $already_counted{$f};
#printf "%10s -> %s\n", $f, $Language{$fh[$F+1]}{$f}; #printf "%10s -> %s\n", $f, $Language{$fh[$F+1]}{$f};
# Don't proceed unless the file (both L and R versions) # Don't proceed unless the file (both L and R versions)
# is in a known language. # is in a known language.
next if $opt_include_ext next if $opt_include_ext
and not $Include_Ext{ file_extension($f) }; and not $Include_Ext{ file_extension($f) };
next if $opt_include_lang next if $opt_include_lang
and not $Include_Language{$Language{$fset_b}{$f}}; and not $Include_Language{$Language{$fset_b}{$f}};
next if $Language{$fset_b}{$f} eq "(unknown)"; my $this_lang = $Language{$fset_b}{$f};
next if $Exclude_Language{$fset_b}{$f}; if ($this_lang eq "(unknown)") {
$p_alignment{"added"}{sprintf " + %s ; %s\n", $f, $Language{$fset_b}{$f $p_ignored{$f} = "uknown language";
}} = 1; next;
++$p_dbl{ $Language{$fset_b}{$f} }{'nFiles'}{'added'}; }
if ($Exclude_Language{$this_lang}) {
$p_ignored{$f} = "--exclude-lang=$this_lang";
next;
}
$p_alignment{"added"}{sprintf " + %s ; %s\n", $f, $this_lang} = 1;
++$p_dbl{ $this_lang }{'nFiles'}{'added'};
# Additionally, add contents of file $f to # Additionally, add contents of file $f to
# Delta_by_File{$f}{comment/blank/code}{'added'} # Delta_by_File{$f}{comment/blank/code}{'added'}
# Delta_by_Language{$lang}{comment/blank/code}{'added'} # Delta_by_Language{$lang}{comment/blank/code}{'added'}
# via the $p_dbl and $p_dbf variables. # via the $p_dbl and $p_dbf variables.
my ($all_line_count, my ($all_line_count,
$blank_count , $blank_count ,
$comment_count , $comment_count ,
) = call_counter($f, $Language{$fset_b}{$f}, \@p_errors); ) = call_counter($f, $this_lang, \@p_errors);
$p_dbl{ $Language{$fset_b}{$f} }{'comment'}{'added'} += $p_dbl{ $this_lang }{'comment'}{'added'} += $comment_count;
$comment_count; $p_dbl{ $this_lang }{'blank'}{'added'} += $blank_count;
$p_dbl{ $Language{$fset_b}{$f} }{'blank'}{'added'} += $p_dbl{ $this_lang }{'code'}{'added'} +=
$blank_count;
$p_dbl{ $Language{$fset_b}{$f} }{'code'}{'added'} +=
$all_line_count - $blank_count - $comment_count; $all_line_count - $blank_count - $comment_count;
$p_dbf{ $f }{'comment'}{'added'} = $comment_count; $p_dbf{ $f }{'comment'}{'added'} = $comment_count;
$p_dbf{ $f }{'blank'}{'added'} = $blank_count; $p_dbf{ $f }{'blank'}{'added'} = $blank_count;
$p_dbf{ $f }{'code'}{'added'} = $p_dbf{ $f }{'code'}{'added'} =
$all_line_count - $blank_count - $comment_count; $all_line_count - $blank_count - $comment_count;
} }
#print "removed:\n"; #print "removed:\n";
foreach my $f (@$files_removed) { foreach my $f (@$files_removed) {
next if $already_counted{$f}; next if $already_counted{$f};
# Don't proceed unless the file (both L and R versions) # Don't proceed unless the file (both L and R versions)
# is in a known language. # is in a known language.
next if $opt_include_ext next if $opt_include_ext
and not $Include_Ext{ file_extension($f) }; and not $Include_Ext{ file_extension($f) };
next if $opt_include_lang next if $opt_include_lang
and not $Include_Language{$Language{$fset_a}{$f}}; and (not defined $Language{$fset_a}{$f}
next if $Language{$fset_a}{$f} eq "(unknown)"; or not defined $Include_Language{$Language{$fset_a}{$f}});
next if $Exclude_Language{$fset_a}{$f}; my $this_lang = $Language{$fset_a}{$f};
++$p_dbl{ $Language{$fset_a}{$f} }{'nFiles'}{'removed'}; if ($this_lang eq "(unknown)") {
$p_alignment{"removed"}{sprintf " - %s ; %s\n", $f, $Language{$fset_a}{ $p_ignored{$f} = "uknown language";
$f}} = 1; next;
}
if ($Exclude_Language{$this_lang}) {
$p_ignored{$f} = "--exclude-lang=$this_lang";
next;
}
++$p_dbl{ $this_lang }{'nFiles'}{'removed'};
$p_alignment{"removed"}{sprintf " - %s ; %s\n", $f, $this_lang} = 1;
#printf "%10s -> %s\n", $f, $Language{$fh[$F ]}{$f}; #printf "%10s -> %s\n", $f, $Language{$fh[$F ]}{$f};
# Additionally, add contents of file $f to # Additionally, add contents of file $f to
# Delta_by_File{$f}{comment/blank/code}{'removed'} # Delta_by_File{$f}{comment/blank/code}{'removed'}
# Delta_by_Language{$lang}{comment/blank/code}{'removed'} # Delta_by_Language{$lang}{comment/blank/code}{'removed'}
# via the $p_dbl and $p_dbf variables. # via the $p_dbl and $p_dbf variables.
my ($all_line_count, my ($all_line_count,
$blank_count , $blank_count ,
$comment_count , $comment_count ,
) = call_counter($f, $Language{$fset_a}{$f}, \@p_errors); ) = call_counter($f, $this_lang, \@p_errors);
$p_dbl{ $Language{$fset_a}{$f}}{'comment'}{'removed'} += $p_dbl{ $this_lang}{'comment'}{'removed'} += $comment_count;
$comment_count; $p_dbl{ $this_lang}{'blank'}{'removed'} += $blank_count;
$p_dbl{ $Language{$fset_a}{$f}}{'blank'}{'removed'} += $p_dbl{ $this_lang}{'code'}{'removed'} +=
$blank_count;
$p_dbl{ $Language{$fset_a}{$f}}{'code'}{'removed'} +=
$all_line_count - $blank_count - $comment_count; $all_line_count - $blank_count - $comment_count;
$p_dbf{ $f }{'comment'}{'removed'} = $comment_count; $p_dbf{ $f }{'comment'}{'removed'} = $comment_count;
$p_dbf{ $f }{'blank'}{'removed'} = $blank_count; $p_dbf{ $f }{'blank'}{'removed'} = $blank_count;
$p_dbf{ $f }{'code'}{'removed'} = $p_dbf{ $f }{'code'}{'removed'} =
$all_line_count - $blank_count - $comment_count; $all_line_count - $blank_count - $comment_count;
} }
my $n_file_pairs_compared = 0; my $n_file_pairs_compared = 0;
# Don't know ahead of time how many file pairs will be compared # Don't know ahead of time how many file pairs will be compared
# since duplicates are weeded out below. The answer is # since duplicates are weeded out below. The answer is
skipping to change at line 2240 skipping to change at line 2370
my $Lang_R = $Language{$fset_b}{$file_R}; my $Lang_R = $Language{$fset_b}{$file_R};
if (!defined($Lang_L) or !defined($Lang_R)) { if (!defined($Lang_L) or !defined($Lang_R)) {
print " -> count_filesets skipping $file_L, $file_R ", print " -> count_filesets skipping $file_L, $file_R ",
"because language cannot be inferred\n" if $opt_v; "because language cannot be inferred\n" if $opt_v;
next; next;
} }
#print "main step 6 file_L=$file_L file_R=$file_R\n"; #print "main step 6 file_L=$file_L file_R=$file_R\n";
++$nCounted; ++$nCounted;
printf "Counting: %d\r", $nCounted printf "Counting: %d\r", $nCounted
unless ($counter_type or !$opt_progress_rate or ($nCounted % $opt_p rogress_rate)); unless ($counter_type or !$opt_progress_rate or ($nCounted % $opt_p rogress_rate));
next if $p_ignored{$file_L}; next if $p_ignored{$file_L} or $p_ignored{$file_R};
# filter out non-included extensions # filter out non-included extensions
if ($opt_include_ext and not $Include_Ext{ file_extension($file_L) } if ($opt_include_ext and not $Include_Ext{ file_extension($file_L) }
and not $Include_Ext{ file_extension($file_R) }) { and not $Include_Ext{ file_extension($file_R) }) {
$p_ignored{$file_L} = "not in --include-lang=$opt_include_ext"; $p_ignored{$file_L} = "not in --include-lang=$opt_include_ext";
$p_ignored{$file_R} = "not in --include-lang=$opt_include_ext"; $p_ignored{$file_R} = "not in --include-lang=$opt_include_ext";
next; next;
} }
# filter out non-included languages # filter out non-included languages
if ($opt_include_lang and not $Include_Language{$Lang_L} if ($opt_include_lang and not $Include_Language{$Lang_L}
and not $Include_Language{$Lang_R}) { and not $Include_Language{$Lang_R}) {
skipping to change at line 2282 skipping to change at line 2413
if (($Lang_L eq "(unknown)") or ($Lang_R eq "(unknown)")) { if (($Lang_L eq "(unknown)") or ($Lang_R eq "(unknown)")) {
$p_ignored{$fset_a}{$file_L} = "language unknown (#1)"; $p_ignored{$fset_a}{$file_L} = "language unknown (#1)";
$p_ignored{$fset_b}{$file_R} = "language unknown (#1)"; $p_ignored{$fset_b}{$file_R} = "language unknown (#1)";
} else { } else {
$p_ignored{$fset_a}{$file_L} = "missing Filters_by_Language{$Lan g_L}"; $p_ignored{$fset_a}{$file_L} = "missing Filters_by_Language{$Lan g_L}";
$p_ignored{$fset_b}{$file_R} = "missing Filters_by_Language{$Lan g_R}"; $p_ignored{$fset_b}{$file_R} = "missing Filters_by_Language{$Lan g_R}";
} }
next; next;
} }
# filter out explicitly excluded files
if ($opt_exclude_list_file and
($rh_Ignored->{$file_L} or $rh_Ignored->{$file_R})) {
my $msg_2;
if ($rh_Ignored->{$file_L}) {
$msg_2 = "$file_L (paired to $file_R)";
} else {
$msg_2 = "$file_R (paired to $file_L)";
}
my $msg_1 = "in --exclude-list-file=$opt_exclude_list_file";
$p_ignored{$file_L} = "$msg_1, $msg_2";
$p_ignored{$file_R} = "$msg_1, $msg_2";
next;
}
#print "DIFF($file_L, $file_R)\n"; #print "DIFF($file_L, $file_R)\n";
# step 0: compare the two files' contents # step 0: compare the two files' contents
chomp ( my @lines_L = read_file($file_L) ); chomp ( my @lines_L = read_file($file_L) );
chomp ( my @lines_R = read_file($file_R) ); chomp ( my @lines_R = read_file($file_R) );
my $language_file_L = ""; my $language_file_L = "";
if (defined $Language{$fset_a}{$file_L}) { if (defined $Language{$fset_a}{$file_L}) {
$language_file_L = $Language{$fset_a}{$file_L}; $language_file_L = $Language{$fset_a}{$file_L};
} else { } else {
# files $file_L and $file_R do not contain known language # files $file_L and $file_R do not contain known language
next; next;
skipping to change at line 2600 skipping to change at line 2746
my %normalized_reject = normalize_file_names(@file_reject_list); my %normalized_reject = normalize_file_names(@file_reject_list);
my %normalized_exclude = normalize_file_names(keys %{$rh_exclude_dir}); my %normalized_exclude = normalize_file_names(keys %{$rh_exclude_dir});
foreach my $F (keys %normalized_input) { foreach my $F (keys %normalized_input) {
if ($normalized_reject{$F} or is_excluded($F, \%normalized_exclude)) { if ($normalized_reject{$F} or is_excluded($F, \%normalized_exclude)) {
my $orig_F = $normalized_input{$F}; my $orig_F = $normalized_input{$F};
$rh_ignored->{$orig_F} = "listed in exclusion file $opt_exclude_list _file"; $rh_ignored->{$orig_F} = "listed in exclusion file $opt_exclude_list _file";
print "Ignoring $orig_F because it appears in $opt_exclude_list_file \n" print "Ignoring $orig_F because it appears in $opt_exclude_list_file \n"
if $opt_v > 1; if $opt_v > 1;
} }
} }
print "<- process_exclude_list_file\n" if $opt_v > 2; print "<- process_exclude_list_file\n" if $opt_v > 2;
} # 1}}} } # 1}}}
sub combine_results { # {{{1 sub combine_results { # {{{1
# returns 1 if the inputs are categorized by language # returns 1 if the inputs are categorized by language
# 0 if no identifiable language was found # 0 if no identifiable language was found
my ($ra_report_files, # in my ($ra_report_files, # in
$report_type , # in "by language" or "by report file" $report_type , # in "by language" or "by report file"
$rhh_count , # out count{TYPE}{nFiles|code|blank|comment|scaled} $rhh_count , # out count{TYPE}{nFiles|code|blank|comment|scaled}
$rhaa_Filters_by_Language , # in $rhaa_Filters_by_Language , # in
) = @_; ) = @_;
skipping to change at line 2781 skipping to change at line 2928
$column_1_offset = $max_len - 17 if $max_len > 17; $column_1_offset = $max_len - 17 if $max_len > 17;
$elapsed_sec = 0.5 unless $elapsed_sec; $elapsed_sec = 0.5 unless $elapsed_sec;
my $spacing_0 = 23; my $spacing_0 = 23;
my $spacing_1 = 13; my $spacing_1 = 13;
my $spacing_2 = 9; my $spacing_2 = 9;
my $spacing_3 = 17; my $spacing_3 = 17;
if (!$opt_3) { if (!$opt_3) {
$spacing_1 = 19; $spacing_1 = 19;
$spacing_2 = 14; $spacing_2 = 14;
$spacing_3 = 28; $spacing_3 = 27;
} }
$spacing_0 += $column_1_offset; $spacing_0 += $column_1_offset;
$spacing_1 += $column_1_offset; $spacing_1 += $column_1_offset;
$spacing_3 += $column_1_offset; $spacing_3 += $column_1_offset;
my %Format = ( my %Format = (
'1' => { 'xml' => 'name="%s" ', '1' => { 'xml' => 'name="%s" ',
'txt' => "\%-${spacing_0}s ", 'txt' => "\%-${spacing_0}s ",
}, },
'2' => { 'xml' => 'name="%s" ', '2' => { 'xml' => 'name="%s" ',
'txt' => "\%-${spacing_3}s ", 'txt' => "\%-${spacing_3}s ",
}, },
'3' => { 'xml' => 'files_count="%d" ', '3' => { 'xml' => 'files_count="%d" ',
'txt' => '%5d ', 'txt' => '%6d ',
}, },
'4' => { 'xml' => 'blank="%d" comment="%d" code="%d" ', '4' => { 'xml' => 'blank="%d" comment="%d" code="%d" ',
'txt' => "\%${spacing_2}d \%${spacing_2}d \%${spacing_2}d", 'txt' => "\%${spacing_2}d \%${spacing_2}d \%${spacing_2}d",
}, },
'5' => { 'xml' => 'blank="%.2f" comment="%.2f" code="%d" ', '5' => { 'xml' => 'blank="%.2f" comment="%.2f" code="%d" ',
'txt' => "\%3.2f \%3.2f \%${spacing_2}d", 'txt' => "\%3.2f \%3.2f \%${spacing_2}d",
}, },
'6' => { 'xml' => 'factor="%.2f" scaled="%.2f" ', '6' => { 'xml' => 'factor="%.2f" scaled="%.2f" ',
'txt' => ' x %6.2f = %14.2f', 'txt' => ' x %6.2f = %14.2f',
}, },
skipping to change at line 2862 skipping to change at line 3009
# sort diff output in descending order of cumulative entries # sort diff output in descending order of cumulative entries
foreach my $lang_or_file (sort { foreach my $lang_or_file (sort {
($rhhh_count->{$b}{'code'}{'added'} + ($rhhh_count->{$b}{'code'}{'added'} +
$rhhh_count->{$b}{'code'}{'same'} + $rhhh_count->{$b}{'code'}{'same'} +
$rhhh_count->{$b}{'code'}{'modified'} + $rhhh_count->{$b}{'code'}{'modified'} +
$rhhh_count->{$b}{'code'}{'removed'} ) <=> $rhhh_count->{$b}{'code'}{'removed'} ) <=>
($rhhh_count->{$a}{'code'}{'added'} + ($rhhh_count->{$a}{'code'}{'added'} +
$rhhh_count->{$a}{'code'}{'same'} + $rhhh_count->{$a}{'code'}{'same'} +
$rhhh_count->{$a}{'code'}{'modified'} + $rhhh_count->{$a}{'code'}{'modified'} +
$rhhh_count->{$a}{'code'}{'removed'})} $rhhh_count->{$a}{'code'}{'removed'})
keys %{$rhhh_count}) { or $a cmp $b }
keys %{$rhhh_count}) {
if ($BY_FILE) { if ($BY_FILE) {
push @results, rm_leading_tempdir($lang_or_file, \%TEMP_DIR); push @results, rm_leading_tempdir($lang_or_file, \%TEMP_DIR);
} else { } else {
push @results, $lang_or_file; push @results, $lang_or_file;
} }
foreach my $S (qw(same modified added removed)) { foreach my $S (qw(same modified added removed)) {
my $indent = $spacing_1 - 2; my $indent = $spacing_1 - 2;
my $line .= sprintf " %-${indent}s", $S; my $line .= sprintf " %-${indent}s", $S;
if ($BY_FILE) { if ($BY_FILE) {
skipping to change at line 3608 skipping to change at line 3756
my $sum_lines = $sum_blank + $sum_comment + $sum_code; my $sum_lines = $sum_blank + $sum_comment + $sum_code;
$elapsed_sec = 0.5 unless $elapsed_sec; $elapsed_sec = 0.5 unless $elapsed_sec;
my $spacing_0 = 23; my $spacing_0 = 23;
my $spacing_1 = 13; my $spacing_1 = 13;
my $spacing_2 = 9; my $spacing_2 = 9;
my $spacing_3 = 17; my $spacing_3 = 17;
if (!$opt_3) { if (!$opt_3) {
$spacing_1 = 19; $spacing_1 = 19;
$spacing_2 = 14; $spacing_2 = 14;
$spacing_3 = 28; $spacing_3 = 27;
} }
$spacing_0 += $column_1_offset; $spacing_0 += $column_1_offset;
$spacing_1 += $column_1_offset; $spacing_1 += $column_1_offset;
$spacing_3 += $column_1_offset; $spacing_3 += $column_1_offset;
my %Format = ( my %Format = (
'1' => { 'xml' => 'name="%s" ', '1' => { 'xml' => 'name="%s" ',
'txt' => "\%-${spacing_0}s ", 'txt' => "\%-${spacing_0}s ",
}, },
'2' => { 'xml' => 'name="%s" ', '2' => { 'xml' => 'name="%s" ',
'txt' => "\%-${spacing_3}s ", 'txt' => "\%-${spacing_3}s ",
}, },
'3' => { 'xml' => 'files_count="%d" ', '3' => { 'xml' => 'files_count="%d" ',
'txt' => '%5d ', 'txt' => '%6d ',
}, },
'4' => { 'xml' => 'blank="%d" comment="%d" code="%d" ', '4' => { 'xml' => 'blank="%d" comment="%d" code="%d" ',
'txt' => "\%${spacing_2}d \%${spacing_2}d \%${spacing_2}d", 'txt' => "\%${spacing_2}d \%${spacing_2}d \%${spacing_2}d",
}, },
'5' => { 'xml' => 'blank="%3.2f" comment="%3.2f" code="%d" ', '5' => { 'xml' => 'blank="%3.2f" comment="%3.2f" code="%d" ',
'txt' => "\%14.2f \%14.2f \%${spacing_2}d", 'txt' => "\%14.2f \%14.2f \%${spacing_2}d",
}, },
'6' => { 'xml' => 'factor="%.2f" scaled="%.2f" ', '6' => { 'xml' => 'factor="%.2f" scaled="%.2f" ',
'txt' => ' x %6.2f = %14.2f', 'txt' => ' x %6.2f = %14.2f',
}, },
skipping to change at line 3746 skipping to change at line 3894
$header2 .= "${DELIM}blank${DELIM}comment${DELIM}code"; $header2 .= "${DELIM}blank${DELIM}comment${DELIM}code";
$header2 .= "${DELIM}scale${DELIM}3rd gen. equiv" if $opt_3; $header2 .= "${DELIM}scale${DELIM}3rd gen. equiv" if $opt_3;
$header2 .= ${DELIM} . '"' . $header_line . '"'; $header2 .= ${DELIM} . '"' . $header_line . '"';
push @results, $header2; push @results, $header2;
} }
my $sum_scaled = 0; my $sum_scaled = 0;
foreach my $lang_or_file (sort { foreach my $lang_or_file (sort {
$rhh_count->{$b}{'code'} <=> $rhh_count->{$b}{'code'} <=>
$rhh_count->{$a}{'code'} $rhh_count->{$a}{'code'}
} or $a cmp $b
keys %{$rhh_count}) { }
keys %{$rhh_count}) {
next if $lang_or_file eq "by report file"; next if $lang_or_file eq "by report file";
my ($factor, $scaled); my ($factor, $scaled);
if ($BY_LANGUAGE or $BY_FILE) { if ($BY_LANGUAGE or $BY_FILE) {
$factor = 1; $factor = 1;
if ($BY_LANGUAGE) { if ($BY_LANGUAGE) {
if (defined $rh_scale->{$lang_or_file}) { if (defined $rh_scale->{$lang_or_file}) {
$factor = $rh_scale->{$lang_or_file}; $factor = $rh_scale->{$lang_or_file};
} else { } else {
warn "No scale factor for $lang_or_file; using 1.00"; warn "No scale factor for $lang_or_file; using 1.00";
} }
skipping to change at line 4088 skipping to change at line 4237
next if defined $Extension_Collision{$language}; next if defined $Extension_Collision{$language};
push @outlines, $language; push @outlines, $language;
foreach my $filter (@{$rhaa_Filters_by_Language->{$language}}) { foreach my $filter (@{$rhaa_Filters_by_Language->{$language}}) {
my $line = ""; my $line = "";
$line .= sprintf " filter %s", $filter->[0]; $line .= sprintf " filter %s", $filter->[0];
$line .= sprintf " %s", $filter->[1] if defined $filter->[1]; $line .= sprintf " %s", $filter->[1] if defined $filter->[1];
# $filter->[0] == 'remove_between_general', # $filter->[0] == 'remove_between_general',
# 'remove_between_regex', and # 'remove_between_regex', and
# 'remove_matches_2re' have two args # 'remove_matches_2re' have two args
$line .= sprintf " %s", $filter->[2] if defined $filter->[2]; $line .= sprintf " %s", $filter->[2] if defined $filter->[2];
# $filter->[0] == 'replace_between_regex' has three args # $filter->[0] == 'replace_between_regex' has three or four args
$line .= sprintf " %s", $filter->[3] if defined $filter->[3]; $line .= sprintf " %s", $filter->[3] if defined $filter->[3];
$line .= sprintf " %s", $filter->[4] if defined $filter->[4];
push @outlines, $line; push @outlines, $line;
} }
# file extension won't appear if the extension maps to # file extension won't appear if the extension maps to
# multiple languages; work around this # multiple languages; work around this
my $found = 0; my $found = 0;
foreach my $ext (sort keys %{$rh_Language_by_Extension}) { foreach my $ext (sort keys %{$rh_Language_by_Extension}) {
if ($language eq $rh_Language_by_Extension->{$ext}) { if ($language eq $rh_Language_by_Extension->{$ext}) {
push @outlines, sprintf " extension %s\n", $ext; push @outlines, sprintf " extension %s\n", $ext;
$found = 1; $found = 1;
} }
} }
if (!$found and $opt_write_lang_def_incl_dup) { if (!$found and $opt_write_lang_def_incl_dup) {
foreach my $multilang (sort keys %Extension_Collision) { foreach my $multilang (sort keys %Extension_Collision) {
my %Languages = map { $_ => 1 } split('/', $multilang); my %Languages = map { $_ => 1 } split('/', $multilang);
next unless $Languages{$language}; next unless $Languages{$language};
foreach my $ext (@{$Extension_Collision{$multilang}}) { foreach my $ext (@{$Extension_Collision{$multilang}}) {
push @outlines, sprintf " extension %s\n", $ext; push @outlines, sprintf " extension %s\n", $ext;
} }
} }
} }
foreach my $filename (sort keys %{$rh_Language_by_File}) { foreach my $filename (sort keys %{$rh_Language_by_File}) {
if ($language eq $rh_Language_by_File->{$filename}) { if ($language eq $rh_Language_by_File->{$filename}) {
push @outlines, sprintf " filename %s\n", $filename; push @outlines, sprintf " filename %s\n", $filename;
} }
} }
foreach my $script_exe (sort keys %{$rh_Language_by_Script}) { foreach my $script_exe (sort keys %{$rh_Language_by_Script}) {
if ($language eq $rh_Language_by_Script->{$script_exe}) { if ($language eq $rh_Language_by_Script->{$script_exe}) {
push @outlines, sprintf " script_exe %s\n", $script_exe; push @outlines, sprintf " script_exe %s\n", $script_exe;
} }
skipping to change at line 4166 skipping to change at line 4316
} }
die "Missing computer language name, line $. of $file\n" die "Missing computer language name, line $. of $file\n"
unless $language; unless $language;
if (/^\s{4}filter\s+(remove_between_(general|2re|regex)) if (/^\s{4}filter\s+(remove_between_(general|2re|regex))
\s+(\S+)\s+(\S+)\s*$/x) { \s+(\S+)\s+(\S+)\s*$/x) {
push @{$rhaa_Filters_by_Language->{$language}}, [ push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $3 , $4 ] $1 , $3 , $4 ]
} elsif (/^\s{4}filter\s+(replace_between_regex) } elsif (/^\s{4}filter\s+(replace_between_regex)
\s+(\S+)\s+(\S+)\s+(\S+|\".*\")\s+(\S+)\s*$/x) {
push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , $3 , $4 , $5]
} elsif (/^\s{4}filter\s+(replace_between_regex)
\s+(\S+)\s+(\S+)\s+(.*?)\s*$/x) { \s+(\S+)\s+(\S+)\s+(.*?)\s*$/x) {
push @{$rhaa_Filters_by_Language->{$language}}, [ push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , $3 , $4 ] $1 , $2 , $3 , $4 ]
} elsif (/^\s{4}filter\s+(replace_regex)\s+(\S+)\s*$/) {
push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , '' ]
} elsif (/^\s{4}filter\s+(replace_regex)
\s+(\S+)\s+(.+?)\s*$/x) {
push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , $3 ]
} elsif (/^\s{4}filter\s+(\w+)\s*$/) { } elsif (/^\s{4}filter\s+(\w+)\s*$/) {
push @{$rhaa_Filters_by_Language->{$language}}, [ $1 ] push @{$rhaa_Filters_by_Language->{$language}}, [ $1 ]
} elsif (/^\s{4}filter\s+(\w+)\s+(.*?)\s*$/) { } elsif (/^\s{4}filter\s+(\w+)\s+(.*?)\s*$/) {
push @{$rhaa_Filters_by_Language->{$language}}, [ $1 , $2 ] push @{$rhaa_Filters_by_Language->{$language}}, [ $1 , $2 ]
} elsif (/^\s{4}extension\s+(\S+)\s*$/) { } elsif (/^\s{4}extension\s+(\S+)\s*$/) {
if (defined $rh_Language_by_Extension->{$1}) { if (defined $rh_Language_by_Extension->{$1}) {
die "File extension collision: $1 ", die "File extension collision: $1 ",
"maps to languages '$rh_Language_by_Extension->{$1}' ", "maps to languages '$rh_Language_by_Extension->{$1}' ",
skipping to change at line 4236 skipping to change at line 4400
next if /^\s*#/ or /^\s*$/; next if /^\s*#/ or /^\s*$/;
if (/^(\w+.*?)\s*$/) { if (/^(\w+.*?)\s*$/) {
$language = $1; $language = $1;
$already_know_it = defined $rh_Scale_Factor->{$language}; $already_know_it = defined $rh_Scale_Factor->{$language};
next; next;
} }
die "Missing computer language name, line $. of $file\n" die "Missing computer language name, line $. of $file\n"
unless $language; unless $language;
if (/^ filter\s+(\w+)\s*$/) { if (/^\s{4}filter\s+(remove_between_(general|2re|regex))
\s+(\S+)\s+(\S+)\s*$/x) {
next if $already_know_it; next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, [ $1 ] push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $3 , $4 ]
} elsif (/^ filter\s+(remove_between_(general|regex))\s+(\S+)\s+(\S+) } elsif (/^\s{4}filter\s+(replace_between_regex)
\s*$/) { \s+(\S+)\s+(\S+)\s+(\S+|\".*\")\s+(\S+)\s*$/x) {
next if $already_know_it; next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, push @{$rhaa_Filters_by_Language->{$language}}, [
[ $1 , $3 , $4 ] $1 , $2 , $3 , $4 , $5]
} elsif (/^ filter\s+(\w+)\s+(.*?)\s*$/) {
} elsif (/^\s{4}filter\s+(replace_between_regex)
\s+(\S+)\s+(\S+)\s+(.*?)\s*$/x) {
next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , $3 , $4 ]
} elsif (/^\s{4}filter\s+(replace_regex)
\s+(\S+)\s+(.+?)\s*$/x) {
next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, [
$1 , $2 , $3 ]
} elsif (/^\s{4}filter\s+(\w+)\s*$/) {
next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, [ $1 ]
} elsif (/^\s{4}filter\s+(\w+)\s+(.*?)\s*$/) {
next if $already_know_it; next if $already_know_it;
push @{$rhaa_Filters_by_Language->{$language}}, [ $1 , $2 ] push @{$rhaa_Filters_by_Language->{$language}}, [ $1 , $2 ]
} elsif (/^ extension\s+(\S+)\s*$/) { } elsif (/^\s{4}extension\s+(\S+)\s*$/) {
next if $already_know_it; next if $already_know_it;
if (defined $rh_Language_by_Extension->{$1}) { if (defined $rh_Language_by_Extension->{$1}) {
die "File extension collision: $1 ", die "File extension collision: $1 ",
"maps to languages '$rh_Language_by_Extension->{$1}' ", "maps to languages '$rh_Language_by_Extension->{$1}' ",
"and '$language'\n" , "and '$language'\n" ,
"Edit $file and remove $1 from one of these two ", "Edit $file and remove $1 from one of these two ",
"language definitions.\n"; "language definitions.\n";
} }
$rh_Language_by_Extension->{$1} = $language; $rh_Language_by_Extension->{$1} = $language;
} elsif (/^ filename\s+(\S+)\s*$/) { } elsif (/^\s{4}filename\s+(\S+)\s*$/) {
next if $already_know_it; next if $already_know_it;
$rh_Language_by_File->{$1} = $language; $rh_Language_by_File->{$1} = $language;
} elsif (/^ script_exe\s+(\S+)\s*$/) { } elsif (/^\s{4}script_exe\s+(\S+)\s*$/) {
next if $already_know_it; next if $already_know_it;
$rh_Language_by_Script->{$1} = $language; $rh_Language_by_Script->{$1} = $language;
} elsif (/^ 3rd_gen_scale\s+(\S+)\s*$/) { } elsif (/^\s{4}3rd_gen_scale\s+(\S+)\s*$/) {
next if $already_know_it; next if $already_know_it;
$rh_Scale_Factor->{$language} = $1; $rh_Scale_Factor->{$language} = $1;
} elsif (/^ end_of_line_continuation\s+(\S+)\s*$/) { } elsif (/^\s{4}end_of_line_continuation\s+(\S+)\s*$/) {
next if $already_know_it; next if $already_know_it;
$rh_EOL_Continuation_re->{$language} = $1; $rh_EOL_Continuation_re->{$language} = $1;
} else { } else {
die "Unexpected data line $. of $file:\n$_\n"; die "Unexpected data line $. of $file:\n$_\n";
} }
} }
$IN->close; $IN->close;
print "<- merge_lang_def\n" if $opt_v > 2; print "<- merge_lang_def\n" if $opt_v > 2;
} # 1}}} } # 1}}}
sub print_extension_info { # {{{1 sub print_extension_info { # {{{1
my ($extension,) = @_; my ($extension,) = @_;
if ($extension) { # show information on this extension if ($extension) { # show information on this extension
foreach my $ext (sort {lc $a cmp lc $b } keys %Language_by_Extension) { foreach my $ext (sort {lc $a cmp lc $b or $a cmp $b } keys %Language_by_ Extension) {
# Language_by_Extension{f} = 'Fortran 77' # Language_by_Extension{f} = 'Fortran 77'
next if $Language_by_Extension{$ext} =~ /Brain/; next if $Language_by_Extension{$ext} =~ /Brain/;
printf "%-15s -> %s\n", $ext, $Language_by_Extension{$ext} printf "%-15s -> %s\n", $ext, $Language_by_Extension{$ext}
if $ext =~ m{$extension}i; if $ext =~ m{$extension}i;
} }
} else { # show information on all extensions } else { # show information on all extensions
foreach my $ext (sort {lc $a cmp lc $b } keys %Language_by_Extension) { foreach my $ext (sort {lc $a cmp lc $b or $a cmp $b } keys %Language_by_ Extension) {
next if $Language_by_Extension{$ext} =~ /Brain/; next if $Language_by_Extension{$ext} =~ /Brain/;
# Language_by_Extension{f} = 'Fortran 77' # Language_by_Extension{f} = 'Fortran 77'
printf "%-15s -> %s\n", $ext, $Language_by_Extension{$ext}; printf "%-15s -> %s\n", $ext, $Language_by_Extension{$ext};
} }
} }
} # 1}}} } # 1}}}
sub print_language_info { # {{{1 sub print_language_info { # {{{1
my ($language, my ($language,
$prefix ,) = @_; $prefix ,) = @_;
my %extensions = (); # the subset matched by the given $language value my %extensions = (); # the subset matched by the given $language value
if ($language) { # show information on this language if ($language) { # show information on this language
foreach my $ext (sort {lc $a cmp lc $b } keys %Language_by_Extension) { foreach my $ext (sort {lc $a cmp lc $b or $a cmp $b } keys %Language_by_ Extension) {
# Language_by_Extension{f} = 'Fortran 77' # Language_by_Extension{f} = 'Fortran 77'
push @{$extensions{$Language_by_Extension{$ext}} }, $ext push @{$extensions{$Language_by_Extension{$ext}} }, $ext
if lc $Language_by_Extension{$ext} eq lc $language; if lc $Language_by_Extension{$ext} eq lc $language;
# if $Language_by_Extension{$ext} =~ m{$language}i; # if $Language_by_Extension{$ext} =~ m{$language}i;
} }
} else { # show information on all languages } else { # show information on all languages
foreach my $ext (sort {lc $a cmp lc $b } keys %Language_by_Extension) { foreach my $ext (sort {lc $a cmp lc $b or $a cmp $b } keys %Language_by _Extension) {
# Language_by_Extension{f} = 'Fortran 77' # Language_by_Extension{f} = 'Fortran 77'
push @{$extensions{$Language_by_Extension{$ext}} }, $ext push @{$extensions{$Language_by_Extension{$ext}} }, $ext
} }
} }
# add exceptions (one file extension mapping to multiple languages) # add exceptions (one file extension mapping to multiple languages)
if (!$language or $language =~ /^(Objective C|MATLAB|Mathematica|MUMPS|Mercu ry)$/i) { if (!$language or $language =~ /^(Objective C|MATLAB|Mathematica|MUMPS|Mercu ry)$/i) {
push @{$extensions{'Objective C'}}, "m"; push @{$extensions{'Objective C'}}, "m";
push @{$extensions{'MATLAB'}} , "m"; push @{$extensions{'MATLAB'}} , "m";
push @{$extensions{'Mathematica'}}, "m"; push @{$extensions{'Mathematica'}}, "m";
skipping to change at line 4341 skipping to change at line 4525
if (!$language or $language =~ /^(Lisp|Julia)$/i) { if (!$language or $language =~ /^(Lisp|Julia)$/i) {
push @{$extensions{'Lisp'}} , "jl"; push @{$extensions{'Lisp'}} , "jl";
push @{$extensions{'Julia'}} , "jl"; push @{$extensions{'Julia'}} , "jl";
delete $extensions{'Lisp/Julia'}; delete $extensions{'Lisp/Julia'};
} }
if (!$language or $language =~ /^(Perl|Prolog)$/i) { if (!$language or $language =~ /^(Perl|Prolog)$/i) {
push @{$extensions{'Perl'}} , "pl"; push @{$extensions{'Perl'}} , "pl";
push @{$extensions{'Prolog'}}, "pl"; push @{$extensions{'Prolog'}}, "pl";
delete $extensions{'Perl/Prolog'}; delete $extensions{'Perl/Prolog'};
} }
if (!$language or $language =~ /^(Raku|Prolog)$/i) {
push @{$extensions{'Perl'}} , "p6";
push @{$extensions{'Prolog'}}, "p6";
delete $extensions{'Perl/Prolog'};
}
if (!$language or $language =~ /^(IDL|Qt Project|Prolog|ProGuard)$/i) { if (!$language or $language =~ /^(IDL|Qt Project|Prolog|ProGuard)$/i) {
push @{$extensions{'IDL'}} , "pro"; push @{$extensions{'IDL'}} , "pro";
push @{$extensions{'Qt Project'}}, "pro"; push @{$extensions{'Qt Project'}}, "pro";
push @{$extensions{'Prolog'}} , "pro"; push @{$extensions{'Prolog'}} , "pro";
push @{$extensions{'ProGuard'}} , "pro"; push @{$extensions{'ProGuard'}} , "pro";
delete $extensions{'IDL/Qt Project/Prolog/ProGuard'}; delete $extensions{'IDL/Qt Project/Prolog/ProGuard'};
} }
if (!$language or $language =~ /^(D|dtrace)$/i) { if (!$language or $language =~ /^(D|dtrace)$/i) {
push @{$extensions{'D'}} , "d"; push @{$extensions{'D'}} , "d";
push @{$extensions{'dtrace'}} , "d"; push @{$extensions{'dtrace'}} , "d";
skipping to change at line 4438 skipping to change at line 4627
!@{$Filters_by_Language{$language}}) { !@{$Filters_by_Language{$language}}) {
warn "Unknown language: $language\n"; warn "Unknown language: $language\n";
warn "Use --show-lang to list all defined languages.\n"; warn "Use --show-lang to list all defined languages.\n";
return; return;
} }
printf "%s\n", $language; printf "%s\n", $language;
foreach my $filter (@{$Filters_by_Language{$language}}) { foreach my $filter (@{$Filters_by_Language{$language}}) {
printf " filter %s", $filter->[0]; printf " filter %s", $filter->[0];
printf " %s", $filter->[1] if defined $filter->[1]; printf " %s", $filter->[1] if defined $filter->[1];
printf " %s", $filter->[2] if defined $filter->[2]; printf " %s", $filter->[2] if defined $filter->[2];
printf " %s", $filter->[3] if defined $filter->[3];
printf " %s", $filter->[4] if defined $filter->[4];
print "\n"; print "\n";
} }
print_language_info($language, " extensions:"); print_language_info($language, " extensions:");
} # 1}}} } # 1}}}
sub top_level_SMB_dir { # {{{1 sub top_level_SMB_dir { # {{{1
# Ref https://github.com/AlDanial/cloc/issues/392, if the # Ref https://github.com/AlDanial/cloc/issues/392, if the
# user supplies a directory name which is an SMB mount # user supplies a directory name which is an SMB mount
# point, this directory will appear to File::Find as # point, this directory will appear to File::Find as
# though it is empty unless $File::Find::dont_use_nlink # though it is empty unless $File::Find::dont_use_nlink
# is set to 1. This subroutine checks to see if any SMB # is set to 1. This subroutine checks to see if any SMB
skipping to change at line 4463 skipping to change at line 4654
next unless -d $entry; next unless -d $entry;
# gets here if $entry is a directory; now get its nlink value # gets here if $entry is a directory; now get its nlink value
my @stats = stat($entry); my @stats = stat($entry);
my $nlink = $stats[3]; my $nlink = $stats[3];
return 1 if $nlink == 2; # meaning it is an SMB mount return 1 if $nlink == 2; # meaning it is an SMB mount
} }
return 0; return 0;
} }
# 1}}} # 1}}}
sub replace_git_hash_with_tarfile { # {{{1 sub replace_git_hash_with_tarfile { # {{{1
my ($ra_arg_list,) = @_; # in file name, directory name and/or git commit my ($ra_arg_list, # in file name, directory name and/or
hash to examine # git commit hash to examine
$ra_git_similarity) = @_; # out only if --opt-git-diff-simindex
# replace git hashes in $ra_arg_list with tar files # replace git hashes in $ra_arg_list with tar files
# Diff mode and count mode behave differently: # Diff mode and count mode behave differently:
# Diff: # Diff:
# file git_hash # file git_hash
# Extract file from the git repo and only compare to it. # Extract file from the git repo and only compare to it.
# git_hash1 git_hash2 # git_hash1 git_hash2
# Get listings of all files in git_hash1 and git_hash2. # Get listings of all files in git_hash1 and git_hash2.
# git ls-tree --name-only -r *git_hash1* # git ls-tree --name-only -r *git_hash1*
# git ls-tree --name-only -r *git_hash2* # git ls-tree --name-only -r *git_hash2*
# Next, get listings of files that changed with git_hash1 # Next, get listings of files that changed with git_hash1
skipping to change at line 4537 skipping to change at line 4730
print "$git_list_cmd\n" if $opt_v; print "$git_list_cmd\n" if $opt_v;
foreach my $file (`$git_list_cmd`) { foreach my $file (`$git_list_cmd`) {
$file =~ s/\s+$//; $file =~ s/\s+$//;
$repo_listing{$hash}{$file} = 1; $repo_listing{$hash}{$file} = 1;
} }
} }
# logic for each of the modes # logic for each of the modes
if ($opt_diff) { if ($opt_diff) {
#print "A DIFF\n"; #print "A DIFF\n";
# set the default git diff algorithm
$opt_git_diff_rel = 1 unless $opt_git_diff_all or
$opt_git_diff_simindex;
# is it git to git, or git to file/dir ? # is it git to git, or git to file/dir ?
my ($Left, $Right) = @{$ra_arg_list}; my ($Left, $Right) = @{$ra_arg_list};
#use Data::Dumper; #use Data::Dumper;
#print "diff_listing= "; print Dumper(\%diff_listing); #print "diff_listing= "; print Dumper(\%diff_listing);
#print "git_hash= "; print Dumper(\%git_hash); #print "git_hash= "; print Dumper(\%git_hash);
if ($git_hash{$Left} and $git_hash{$Right}) { if ($git_hash{$Left} and $git_hash{$Right}) {
#print "A DIFF git-to-git\n"; #print "A DIFF git-to-git\n";
# git to git # git to git
# first make a union of all files that have changed in both commits # first make a union of all files that have changed in both commits
my %files_union = (); my %files_union = ();
# Strategy 1: Union files are what git consinders have changed my @left_files = ();
# between the two commits. my @right_files = ();
## my $git_list_cmd = "git diff-tree -r --no-commit-id --name-only $Lef if ($opt_git_diff_rel) {
t $Right"; # Strategy 1: Union files are what git consinders have changed
## print "$git_list_cmd\n" if $opt_v; # between the two commits.
## foreach my $file (`$git_list_cmd`) { my $git_list_cmd = "git diff-tree -r --no-commit-id --name-only
## chomp($file); $Left $Right";
## $files_union{$file} = 1; # print "$git_list_cmd\n" if $opt_v;
## } foreach my $file (`$git_list_cmd`) {
chomp($file);
# Strategy 2: Union files all files that have changed in both $files_union{$file} = 1;
# commits. }
foreach my $file (keys %{$repo_listing{$Left }}, } elsif ($opt_git_diff_all) {
keys %{$repo_listing{$Right}}) { # Strategy 2: Union files all files in both repos.
$files_union{$file} = 1; foreach my $file (keys %{$repo_listing{$Left }},
keys %{$repo_listing{$Right}}) {
$files_union{$file} = 1;
}
} elsif ($opt_git_diff_simindex) {
# Strategy 3: Use git's own similarity index to figure
# out which files to compare.
git_similarity_index($Left , # in
$Right , # in
\@left_files , # out
\@right_files , # out
$ra_git_similarity); # out
} }
#use Data::Dumper; #use Data::Dumper;
#print "files_union =\n", Dumper(\%files_union); #print "files_union =\n", Dumper(\%files_union);
#print "repo_listing=\n", Dumper(\%repo_listing); #print "repo_listing=\n", Dumper(\%repo_listing);
# then make trucated tar files of those union files which # then make trucated tar files of those union files which
# actually exist in each repo # actually exist in each repo
my @left_files = ();
my @right_files = ();
foreach my $file (sort keys %files_union) { foreach my $file (sort keys %files_union) {
push @left_files , $file if $repo_listing{$Left }{$file}; push @left_files , $file if $repo_listing{$Left }{$file};
push @right_files, $file if $repo_listing{$Right}{$file}; push @right_files, $file if $repo_listing{$Right}{$file};
} }
# backslash whitespace, weird chars within file names (#257, #284) # backslash whitespace, weird chars within file names (#257, #284)
# my @Lfiles= map {$_ =~ s/([\s\(\)\[\]{}';\^\$\?])/\\$1/g; $_} @lef t_files; # my @Lfiles= map {$_ =~ s/([\s\(\)\[\]{}';\^\$\?])/\\$1/g; $_} @lef t_files;
# my @Lfiles= @left_files; # my @Lfiles= @left_files;
$replacement_arg_list{$git_hash{$Left}} = git_archive($Left , \@lef if(scalar(@left_files) > 0) {
t_files); $replacement_arg_list{$git_hash{$Left}} = git_archive($Left , \
@left_files);
} else {
# In the right side commit ONLY file(s) was added, so no file(s)
will exist in the left side commit.
# Create empty TAR to detect added lines of code.
$replacement_arg_list{$git_hash{$Left}} = empty_tar();
}
# $replacement_arg_list{$git_hash{$Left}} = git_archive($Left , \@Lfi les); # $replacement_arg_list{$git_hash{$Left}} = git_archive($Left , \@Lfi les);
# my @Rfiles= map {$_ =~ s/([\s\(\)\[\]{}';\^\$\?])/\\$1/g; $_} @rig ht_files ; # my @Rfiles= map {$_ =~ s/([\s\(\)\[\]{}';\^\$\?])/\\$1/g; $_} @rig ht_files ;
# my @Rfiles= @right_files ; # my @Rfiles= @right_files ;
#use Data::Dumper; #use Data::Dumper;
#print Dumper('left' , \@left_files); #print Dumper('left' , \@left_files);
#print Dumper('right', \@right_files); #print Dumper('right', \@right_files);
#die; #die;
$replacement_arg_list{$git_hash{$Right}} = git_archive($Right, \@rig
ht_files); if(scalar(@right_files) > 0) {
$replacement_arg_list{$git_hash{$Right}} = git_archive($Right, \
@right_files);
} else {
# In the left side commit ONLY file(s) was deleted, so file(s)
will not exist in right side commit.
# Create empty TAR to detect removed lines of code.
$replacement_arg_list{$git_hash{$Right}} = empty_tar();
}
# $replacement_arg_list{$git_hash{$Right}} = git_archive($Right, \@Rfi les); # $replacement_arg_list{$git_hash{$Right}} = git_archive($Right, \@Rfi les);
#write_file("/tmp/Lfiles.txt", {}, sort @Lfiles); #write_file("/tmp/Lfiles.txt", {}, sort @Lfiles);
#write_file("/tmp/Rfiles.txt", {}, sort @Rfiles); #write_file("/tmp/Rfiles.txt", {}, sort @Rfiles);
#write_file("/tmp/files_union.txt", {}, sort keys %files_union); #write_file("/tmp/files_union.txt", {}, sort keys %files_union);
} else { } else {
#print "A DIFF git-to-file or file-to-git Left=$Left Right=$Right\n"; #print "A DIFF git-to-file or file-to-git Left=$Left Right=$Right\n";
# git to file/dir or file/dir to git # git to file/dir or file/dir to git
if ($git_hash{$Left} and $repo_listing{$Left}{$Right} ) { if ($git_hash{$Left} and $repo_listing{$Left}{$Right} ) {
#print "A DIFF 1\n"; #print "A DIFF 1\n";
skipping to change at line 4634 skipping to change at line 4853
# replace the input arg list with the new one # replace the input arg list with the new one
@{$ra_arg_list} = (); @{$ra_arg_list} = ();
foreach my $index (sort {$a <=> $b} keys %replacement_arg_list) { foreach my $index (sort {$a <=> $b} keys %replacement_arg_list) {
push @{$ra_arg_list}, $replacement_arg_list{$index}; push @{$ra_arg_list}, $replacement_arg_list{$index};
} }
#print "ra_arg_list 2: @{$ra_arg_list}\n"; #print "ra_arg_list 2: @{$ra_arg_list}\n";
print "<- replace_git_hash_with_tarfile()\n" if $opt_v > 2; print "<- replace_git_hash_with_tarfile()\n" if $opt_v > 2;
} # 1}}} } # 1}}}
sub git_similarity_index { # {{{
my ($git_hash_Left , # in
$git_hash_Right , # in
$ra_left_files , # out
$ra_right_files , # out
$ra_git_similarity) = @_; # out
die "this option is not yet implemented";
print "-> git_similarity_index($git_hash_Left, $git_hash_Right)\n" if $opt_v
> 2;
my $cmd = "git diff -M --name-status $git_hash_Left $git_hash_Right";
print $cmd, "\n" if $opt_v;
open(GSIM, "$cmd |") or die "Unable to run $cmd $!";
while (<GSIM>) {
print "git similarity> $_";
}
close(GSIM);
print "<- git_similarity_index\n" if $opt_v > 2;
} # 1}}}
sub empty_tar { # {{{1
my ($Tarfh, $Tarfile);
if ($opt_sdir) {
File::Path::mkpath($opt_sdir) unless is_dir($opt_sdir);
($Tarfh, $Tarfile) = tempfile(UNLINK => 1, DIR => $opt_sdir, SUFFIX => $ON
_WINDOWS ? '.zip' : '.tar'); # delete on exit
} else {
($Tarfh, $Tarfile) = tempfile(UNLINK => 1, SUFFIX => $ON_WINDOWS ? '.zip'
: '.tar'); # delete on exit
}
my $cmd = $ON_WINDOWS ? "type nul > $Tarfile" : "tar -cf $Tarfile -T /dev/nu
ll";
print $cmd, "\n" if $opt_v;
system $cmd;
if (!-r $Tarfile) {
# not readable
die "Failed to create empty tarfile.";
}
return $Tarfile;
} # 1}}}
sub git_archive { # {{{1 sub git_archive { # {{{1
# Invoke 'git archive' as a system command to create a tar file # Invoke 'git archive' as a system command to create a tar file
# using the given argument(s). # using the given argument(s).
my ($A1, $A2) = @_; my ($A1, $A2) = @_;
print "-> git_archive($A1)\n" if $opt_v > 2; print "-> git_archive($A1)\n" if $opt_v > 2;
my $args = undef; my $args = undef;
my @File_Set = ( ); my @File_Set = ( );
my $n_sets = 1; my $n_sets = 1;
if (ref $A2 eq 'ARRAY') { if (ref $A2 eq 'ARRAY') {
# Avoid "Argument list too long" for the git archive command # Avoid "Argument list too long" for the git archive command
# by splitting the inputs into sets of 10,000 files (issue 273). # by splitting the inputs into sets of 10,000 files (issue 273).
my $FILES_PER_ARCHIVE = 1_000; my $FILES_PER_ARCHIVE = 1_000;
$FILES_PER_ARCHIVE = 100 if $ON_WINDOWS; # github.com/AlDanial/cloc /issues/404 $FILES_PER_ARCHIVE = 100 if $ON_WINDOWS; # github.com/AlDanial/cloc /issues/404
my $n_files = scalar(@{$A2}); my $n_files = scalar(@{$A2});
$n_sets = $n_files/$FILES_PER_ARCHIVE; $n_sets = $n_files/$FILES_PER_ARCHIVE;
$n_sets = 1 + int($n_sets) if $n_sets > int($n_sets); $n_sets = 1 + int($n_sets) if $n_sets > int($n_sets);
$n_sets = 1 if !$n_sets; $n_sets = 1 if !$n_sets;
foreach my $i (0..$n_sets-1) { foreach my $i (0..$n_sets-1) {
@{$File_Set[$i]} = ( ); @{$File_Set[$i]} = ( );
my $start = $i*$FILES_PER_ARCHIVE; my $start = $i*$FILES_PER_ARCHIVE;
my $end = smaller(($i+1)*$FILES_PER_ARCHIVE, $n_files) - 1; my $end = smaller(($i+1)*$FILES_PER_ARCHIVE, $n_files) - 1;
# Wrap each file name in single quotes to protect spaces # Wrap each file name in single quotes to protect spaces
# and other odd characters. File names that themselves have # and other odd characters. File names that themselves have
# single quotes are instead wrapped in double quotes. File # single quotes are instead wrapped in double quotes. File
# names with both single and double quotes... jeez. # names with both single and double quotes... jeez.
foreach my $fname (@{$A2}[$start .. $end]) { foreach my $fname (@{$A2}[$start .. $end]) {
if ($fname =~ /^".*?\\".*?"$/) { if ($fname =~ /^".*?\\".*?"$/) {
# git pre-handles filenames with double quotes by backslashi ng # git pre-handles filenames with double quotes by backslashi ng
# each double quote then surrounding entire name in double # each double quote then surrounding entire name in double
skipping to change at line 4685 skipping to change at line 4939
##xx# # don't include \$ in the regex because git handles these correctly ##xx# # don't include \$ in the regex because git handles these correctly
# # to each word in @{$A2}[$start .. $end]: first backslash each # # to each word in @{$A2}[$start .. $end]: first backslash each
# # single quote, then wrap all entries in single quotes (#320) # # single quote, then wrap all entries in single quotes (#320)
# push @File_Set, # push @File_Set,
# "$A1 " . join(" ", map {$_ =~ s/'/\'/g; $_ =~ s/^(.*)$/'$1'/g; $_} # "$A1 " . join(" ", map {$_ =~ s/'/\'/g; $_ =~ s/^(.*)$/'$1'/g; $_}
## "$A1 " . join(" ", map {$_ =~ s/([\s\(\)\[\]{}';\^\?])/\\$1/g; $_} ## "$A1 " . join(" ", map {$_ =~ s/([\s\(\)\[\]{}';\^\?])/\\$1/g; $_}
# @{$A2}[$start .. $end]); # @{$A2}[$start .. $end]);
} }
} else { } else {
if (defined $A2) { if (defined $A2) {
push @{$File_Set[0]}, "$A1 $A2"; push @{$File_Set[0]}, "$A1 $A2";
} else { } else {
push @{$File_Set[0]}, "$A1"; push @{$File_Set[0]}, "$A1";
} }
} }
my $files_this_commit = join(" ", @{$File_Set[0]}); my $files_this_commit = join(" ", @{$File_Set[0]});
print " git_archive(file_set[0]=$files_this_commit)\n" if $opt_v > 2; print " git_archive(file_set[0]=$files_this_commit)\n" if $opt_v > 2;
my ($Tarfh, $Tarfile) = tempfile(UNLINK => 1, SUFFIX => $ON_WINDOWS ? '.zip' my ($Tarfh, $Tarfile);
: '.tar'); # delete on exit if ($opt_sdir) {
File::Path::mkpath($opt_sdir) unless is_dir($opt_sdir);
($Tarfh, $Tarfile) = tempfile(UNLINK => 1, DIR => $opt_sdir, SUFFIX => $ON
_WINDOWS ? '.zip' : '.tar'); # delete on exit
} else {
($Tarfh, $Tarfile) = tempfile(UNLINK => 1, SUFFIX => $ON_WINDOWS ? '.zip'
: '.tar'); # delete on exit
}
my $cmd = "git archive -o $Tarfile $files_this_commit"; my $cmd = "git archive -o $Tarfile $files_this_commit";
print $cmd, "\n" if $opt_v; print $cmd, "\n" if $opt_v;
system $cmd; system $cmd;
if (!-r $Tarfile or !-s $Tarfile) { if (!-r $Tarfile or !-s $Tarfile) {
# not readable, or zero sized # not readable, or zero sized
die "Failed to create tarfile of files from git."; die "Failed to create tarfile of files from git.";
} }
if ($n_sets > 1) { if ($n_sets > 1) {
foreach my $i (1..$n_sets-1) { foreach my $i (1..$n_sets-1) {
my $files_this_commit = join(" ", @{$File_Set[$i]}); my $files_this_commit = join(" ", @{$File_Set[$i]});
skipping to change at line 4719 skipping to change at line 4979
# TODO: on Windows switch to .tar instead of .zip # TODO: on Windows switch to .tar instead of .zip
$cmd = "tar -A -f ${Tarfile} ${Tarfile}_extra"; $cmd = "tar -A -f ${Tarfile} ${Tarfile}_extra";
print $cmd, "\n" if $opt_v; print $cmd, "\n" if $opt_v;
system $cmd; system $cmd;
} }
unlink "${Tarfile}_extra"; unlink "${Tarfile}_extra";
} }
print "<- git_archive()\n" if $opt_v > 2; print "<- git_archive()\n" if $opt_v > 2;
return $Tarfile return $Tarfile
} # 1}}} } # 1}}}
sub smaller { # {{{1 sub smaller { # {{{1
my( $a, $b ) = @_; my( $a, $b ) = @_;
return $a < $b ? $a : $b; return $a < $b ? $a : $b;
} # 1}}} } # 1}}}
sub make_file_list { # {{{1 sub make_file_list { # {{{1
my ($ra_arg_list, # in file and/or directory names to examine my ($ra_arg_list, # in file and/or directory names to examine
$rh_Err , # in hash of error codes $rh_Err , # in hash of error codes
$raa_errors , # out errors encountered $raa_errors , # out errors encountered
$rh_ignored , # out files not recognized as computer languages $rh_ignored , # out files not recognized as computer languages
) = @_; ) = @_;
print "-> make_file_list(@{$ra_arg_list})\n" if $opt_v > 2; print "-> make_file_list(@{$ra_arg_list})\n" if $opt_v > 2;
skipping to change at line 5219 skipping to change at line 5479
} else { } else {
return $Language_by_File{$file}; return $Language_by_File{$file};
} }
} }
if ($file =~ /\.([^\.]+)$/) { # has an extension if ($file =~ /\.([^\.]+)$/) { # has an extension
print "$full_file extension=[$1]\n" if $opt_v > 2; print "$full_file extension=[$1]\n" if $opt_v > 2;
my $extension = $1; my $extension = $1;
# Windows file names are case insensitive so map # Windows file names are case insensitive so map
# all extensions to lowercase there. # all extensions to lowercase there.
$extension = lc $extension if $ON_WINDOWS; $extension = lc $extension if $ON_WINDOWS or $opt_ignore_case_ext;
my @extension_list = ( $extension ); my @extension_list = ( $extension );
if ($file =~ /\.([^\.]+\.[^\.]+)$/) { # has a double extension if ($file =~ /\.([^\.]+\.[^\.]+)$/) { # has a double extension
my $extension = $1; my $extension = $1;
$extension = lc $extension if $ON_WINDOWS; $extension = lc $extension if $ON_WINDOWS or $opt_ignore_case_ext;
unshift @extension_list, $extension; # examine double ext first unshift @extension_list, $extension; # examine double ext first
} }
if ($file =~ /\.([^\.]+\.[^\.]+\.[^\.]+)$/) { # has a triple extension if ($file =~ /\.([^\.]+\.[^\.]+\.[^\.]+)$/) { # has a triple extension
my $extension = $1; my $extension = $1;
$extension = lc $extension if $ON_WINDOWS; $extension = lc $extension if $ON_WINDOWS or $opt_ignore_case_ext;
unshift @extension_list, $extension; # examine triple ext first unshift @extension_list, $extension; # examine triple ext first
} }
foreach my $extension (@extension_list) { foreach my $extension (@extension_list) {
if ($Not_Code_Extension{$extension} and if ($Not_Code_Extension{$extension} and
!$Forced_Extension{$extension}) { !$Forced_Extension{$extension}) {
# If .1 (for example) is an extension that would ordinarily be # If .1 (for example) is an extension that would ordinarily be
# ignored but the user has insisted this be counted with the # ignored but the user has insisted this be counted with the
# --force-lang option, then go ahead and count it. # --force-lang option, then go ahead and count it.
$rh_ignored->{$full_file} = $rh_ignored->{$full_file} =
'listed in $Not_Code_Extension{' . $extension . '}'; 'listed in $Not_Code_Extension{' . $extension . '}';
skipping to change at line 5283 skipping to change at line 5543
$rh_ignored->{$full_file} = $rh_ignored->{$full_file} =
'failure in pascal_or_puppet()'; 'failure in pascal_or_puppet()';
return $language; # (unknown) return $language; # (unknown)
} }
} elsif ($Language_by_Extension{$extension} eq 'Lisp/OpenCL') { } elsif ($Language_by_Extension{$extension} eq 'Lisp/OpenCL') {
return Lisp_or_OpenCL($full_file, $rh_Err, $raa_errors); return Lisp_or_OpenCL($full_file, $rh_Err, $raa_errors);
} elsif ($Language_by_Extension{$extension} eq 'Lisp/Julia') { } elsif ($Language_by_Extension{$extension} eq 'Lisp/Julia') {
return Lisp_or_Julia( $full_file, $rh_Err, $raa_errors); return Lisp_or_Julia( $full_file, $rh_Err, $raa_errors);
} elsif ($Language_by_Extension{$extension} eq 'Perl/Prolog') { } elsif ($Language_by_Extension{$extension} eq 'Perl/Prolog') {
return Perl_or_Prolog($full_file, $rh_Err, $raa_errors); return Perl_or_Prolog($full_file, $rh_Err, $raa_errors);
} elsif ($Language_by_Extension{$extension} eq 'Raku/Prolog') {
return Raku_or_Prolog($full_file, $rh_Err, $raa_errors);
} elsif ($Language_by_Extension{$extension} eq } elsif ($Language_by_Extension{$extension} eq
'IDL/Qt Project/Prolog/ProGuard') { 'IDL/Qt Project/Prolog/ProGuard') {
return IDL_or_QtProject($full_file, $rh_Err, $raa_errors); return IDL_or_QtProject($full_file, $rh_Err, $raa_errors);
} elsif ($Language_by_Extension{$extension} eq 'D/dtrace') { } elsif ($Language_by_Extension{$extension} eq 'D/dtrace') {
# is it D or an init.d shell script? # is it D or an init.d shell script?
my $a_script = really_is_D($full_file, $rh_Err, $raa_errors); my $a_script = really_is_D($full_file, $rh_Err, $raa_errors);
if ($a_script) { if ($a_script) {
# could be dtrace, sh, bash or anything one would # could be dtrace, sh, bash or anything one would
# write an init.d script in # write an init.d script in
if (defined $Language_by_Script{$a_script}) { if (defined $Language_by_Script{$a_script}) {
skipping to change at line 5375 skipping to change at line 5637
return $opt_lang_no_ext; return $opt_lang_no_ext;
} else { # no file extension } else { # no file extension
$look_at_first_line = 1; $look_at_first_line = 1;
} }
if ($look_at_first_line) { if ($look_at_first_line) {
# maybe it is a shell/Perl/Python/Ruby/etc script that # maybe it is a shell/Perl/Python/Ruby/etc script that
# starts with pound bang: # starts with pound bang:
# #!/usr/bin/perl # #!/usr/bin/perl
# #!/usr/bin/env perl # #!/usr/bin/env perl
my $script_language = peek_at_first_line($full_file , my ($script_language, $L) = peek_at_first_line($full_file ,
$rh_Err , $rh_Err ,
$raa_errors); $raa_errors);
if (!$script_language) { if (!$script_language) {
$rh_ignored->{$full_file} = "language unknown (#2)"; $rh_ignored->{$full_file} = "language unknown (#2)";
# returns (unknown) # returns (unknown)
} }
if (defined $Language_by_Script{$script_language}) { if (defined $Language_by_Script{$script_language}) {
if (defined $Filters_by_Language{ if (defined $Filters_by_Language{
$Language_by_Script{$script_language}}) { $Language_by_Script{$script_language}}) {
$language = $Language_by_Script{$script_language}; $language = $Language_by_Script{$script_language};
} else { } else {
$rh_ignored->{$full_file} = $rh_ignored->{$full_file} =
"undefined: Filters_by_Language{" . "undefined: Filters_by_Language{" .
$Language_by_Script{$script_language} . $Language_by_Script{$script_language} .
"} for scripting language $script_language"; "} for scripting language $script_language";
# returns (unknown) # returns (unknown)
} }
} else { } else {
$rh_ignored->{$full_file} = "language unknown (#3)"; # #456: XML files can have a variety of domain-specific file
# extensions. If the extension is unrecognized, examine
# the first line of the file to see if it is XML
if ($L =~ /<\?xml\s/) {
$language = "XML";
delete $rh_ignored->{$full_file};
} else {
$rh_ignored->{$full_file} = "language unknown (#3)";
}
# returns (unknown) # returns (unknown)
} }
} }
print "<- classify_file($full_file)=$language\n" if $opt_v > 2; print "<- classify_file($full_file)=$language\n" if $opt_v > 2;
return $language; return $language;
} # 1}}} } # 1}}}
sub first_line { # {{{1 sub first_line { # {{{1
# return back the first line of text in the file # return back the first line of text in the file
my ($file , # in my ($file , # in
$rh_Err , # in hash of error codes $rh_Err , # in hash of error codes
skipping to change at line 5452 skipping to change at line 5722
scalar @pound_bang > 1) { scalar @pound_bang > 1) {
$script_language = $pound_bang[1]; $script_language = $pound_bang[1];
#print "peek_at_first_line pound_bang A $pound_bang[1]\n"; #print "peek_at_first_line pound_bang A $pound_bang[1]\n";
} else { } else {
$script_language = basename $pound_bang[0]; $script_language = basename $pound_bang[0];
#print "peek_at_first_line pound_bang B $script_language\n"; #print "peek_at_first_line pound_bang B $script_language\n";
} }
} }
} }
print "<- peek_at_first_line($file)\n" if $opt_v > 2; print "<- peek_at_first_line($file)\n" if $opt_v > 2;
return $script_language; return ($script_language, $first_line);
} # 1}}} } # 1}}}
sub different_files { # {{{1 sub different_files { # {{{1
# See which of the given files are unique by computing each file's MD5 # See which of the given files are unique by computing each file's MD5
# sum. Return the subset of files which are unique. # sum. Return the subset of files which are unique.
my ($ra_files , # in my ($ra_files , # in
$rh_Err , # in $rh_Err , # in
$raa_errors , # out $raa_errors , # out
$rh_ignored , # out $rh_ignored , # out
) = @_; ) = @_;
skipping to change at line 5738 skipping to change at line 6008
$OUT->close; $OUT->close;
if (-r $file) { if (-r $file) {
print "Wrote $file" unless $opt_quiet; print "Wrote $file" unless $opt_quiet;
print ", $CLOC_XSL" if $opt_xsl and $opt_xsl eq $CLOC_XSL; print ", $CLOC_XSL" if $opt_xsl and $opt_xsl eq $CLOC_XSL;
print "\n" unless $opt_quiet; print "\n" unless $opt_quiet;
} }
print "<- write_file\n" if $opt_v > 2; print "<- write_file\n" if $opt_v > 2;
} # 1}}} } # 1}}}
sub file_pairs_from_file { # {{{1
my ($file , # in
$ra_added , # out
$ra_removed , # out
$ra_compare_list , # out
) = @_;
#
# Example valid input format for $file
# 1)
# A/d1/hello.f90 | B/d1/hello.f90
# A/hello.C | B/hello.C
# A/d2/hi.py | B/d2/hi.py
#
# 2)
# Files added: 1
# + B/extra_file.pl ; Perl
#
# Files removed: 1
# - A/d2/hello.java ; Java
#
# File pairs compared: 3
# != A/d1/hello.f90 | B/d1/hello.f90 ; Fortran 90
# != A/hello.C | B/hello.C ; C++
# == A/d2/hi.py | B/d2/hi.py ; Python
print "-> file_pairs_from_file($file)\n" if $opt_v and $opt_v > 2;
@{$ra_compare_list} = ();
my @lines = read_file($file);
my $mode = "compare";
foreach my $L (@lines) {
next if $L =~ /^\s*$/ or $L =~ /^\s*#/;
chomp($L);
if ($L =~ /^Files\s+(added|removed):/) {
$mode = $1;
} elsif ($L =~ /^File\s+pairs\s+compared:/) {
$mode = "compare";
} elsif ($mode eq "added" or $mode eq "removed") {
$L =~ m/^\s*[+-]\s+(.*?)\s+;/;
my $F = $1;
if (!defined $1) {
warn "file_pairs_from_file($file) parse failure\n",
"in $mode mode for '$L', ignoring\n";
next;
}
if ($mode eq "added") {
push @{$ra_added} , $F;
} else {
push @{$ra_removed}, $F;
}
} else {
$L =~ m/^\s*([!=]=\s*)?(.*?)\s*\|\s*(.*?)\s*(;.*?)?$/;
if (!defined $2 or !defined $3) {
warn "file_pairs_from_file($file) parse failure\n",
"in compare mode for '$L', ignoring\n";
next;
}
push @{$ra_compare_list}, ( [$2, $3] );
}
}
print "<- file_pairs_from_file\n" if $opt_v and $opt_v > 2;
}
sub read_file { # {{{1 sub read_file { # {{{1
my ($file, ) = @_; my ($file, ) = @_;
my %BoM = ( my %BoM = (
"fe ff" => 2 , "fe ff" => 2 ,
"ff fe" => 2 , "ff fe" => 2 ,
"ef bb bf" => 3 , "ef bb bf" => 3 ,
"f7 64 4c" => 3 , "f7 64 4c" => 3 ,
"0e fe ff" => 3 , "0e fe ff" => 3 ,
"fb ee 28" => 3 , "fb ee 28" => 3 ,
"00 00 fe ff" => 4 , "00 00 fe ff" => 4 ,
skipping to change at line 5906 skipping to change at line 6237
} }
print_lines($file, "post $subroutine(@args) blank cleanup:", \@lines) print_lines($file, "post $subroutine(@args) blank cleanup:", \@lines)
if $opt_print_filter_stages; if $opt_print_filter_stages;
} }
foreach (@lines) { chomp } # make sure no spurious newlines were added foreach (@lines) { chomp } # make sure no spurious newlines were added
# Exception for scripting languages: treat the first #! line as code. # Exception for scripting languages: treat the first #! line as code.
# Will need to add it back in if it was removed earlier. # Will need to add it back in if it was removed earlier.
chomp( $original_lines[0] ); chomp( $original_lines[0] );
if (defined $Script_Language{$language} and if (defined $Script_Language{$language} and
$original_lines[0] =~ /^#!/ and $original_lines[0] =~ /^#!/ and
(!scalar(@lines) or ($lines[0] ne $original_lines[0]))) { (!scalar(@lines) or ($lines[0] ne $original_lines[0]))) {
unshift @lines, $original_lines[0]; # add the first line back unshift @lines, $original_lines[0]; # add the first line back
} }
print "<- rm_comments\n" if $opt_v > 2; print "<- rm_comments\n" if $opt_v > 2;
return @lines; return @lines;
} # 1}}} } # 1}}}
sub remove_f77_comments { # {{{1 sub remove_f77_comments { # {{{1
skipping to change at line 6145 skipping to change at line 6476
# Global symbol "%RE" requires explicit package name at cloc line xx. # Global symbol "%RE" requires explicit package name at cloc line xx.
if ($all_lines =~ m/$RE{balanced}{-parens => $marker}/) { if ($all_lines =~ m/$RE{balanced}{-parens => $marker}/) {
no warnings; no warnings;
$all_lines =~ s/$1//g; $all_lines =~ s/$1//g;
} }
print "<- remove_between\n" if $opt_v > 2; print "<- remove_between\n" if $opt_v > 2;
return split("\n", $all_lines); return split("\n", $all_lines);
} # 1}}} } # 1}}}
sub rm_comments_in_strings { # {{{1 sub rm_comments_in_strings { # {{{1
my ($ra_lines, $string_marker, $start_comment, $end_comment, ) = @_; my ($ra_lines, $string_marker, $start_comment, $end_comment, $multiline_mode
) = @_;
$multiline_mode = 0 if not defined $multiline_mode;
# Replace comments within strings with 'xx'. # Replace comments within strings with 'xx'.
print "-> rm_comments_in_strings(string_marker=$string_marker, " . print "-> rm_comments_in_strings(string_marker=$string_marker, " .
"start_comment=$start_comment, end_comment=$end_comment)\n" "start_comment=$start_comment, end_comment=$end_comment)\n"
if $opt_v > 2; if $opt_v > 2;
my @save_lines = (); my @save_lines = ();
my $in_ml_string = 0;
foreach my $line (@{$ra_lines}) { foreach my $line (@{$ra_lines}) {
#print "line=[$line]\n"; #print "line=[$line]\n";
my $new_line = "";
if ($line !~ /${string_marker}/) { if ($line !~ /${string_marker}/) {
# short circuit; no strings on this line # short circuit; no strings on this line
if ( $in_ml_string ) {
$line =~ s/\Q${start_comment}\E/xx/g;
$line =~ s/\Q${end_comment}\E/xx/g if $end_comment;
}
push @save_lines, $line; push @save_lines, $line;
next; next;
} }
# replace backslashed string markers with 'Q' # replace backslashed string markers with 'Q'
$line =~ s/\\${string_marker}/Q/g; $line =~ s/\\${string_marker}/Q/g;
if ( $in_ml_string and $line =~ /^(.*?)(${string_marker})(.*)$/ ) {
# A multiline string ends on this line. Process the part
# until the end of the multiline string first.
my ($lastpart_ml_string, $firstpart_marker, $rest_of_line ) = ($1,
$2, $3);
$lastpart_ml_string =~ s/\Q${start_comment}\E/xx/g;
$lastpart_ml_string =~ s/\Q${end_comment}\E/xx/g if $end_comment;
$new_line = $lastpart_ml_string . $firstpart_marker;
$line = $rest_of_line;
$in_ml_string = 0;
}
my @tokens = split(/(${string_marker}.*?${string_marker})/, $line); my @tokens = split(/(${string_marker}.*?${string_marker})/, $line);
my $new_line = "";
foreach my $t (@tokens) { foreach my $t (@tokens) {
#printf " t0 = [$t]\n"; #printf " t0 = [$t]\n";
if ($t =~ /${string_marker}.*${string_marker}$/) { if ($t =~ /${string_marker}.*${string_marker}$/) {
# enclosed in quotes; process this token # enclosed in quotes; process this token
$t =~ s/\Q${start_comment}\E/xx/g; $t =~ s/\Q${start_comment}\E/xx/g;
$t =~ s/\Q${end_comment}\E/xx/g if $end_comment; $t =~ s/\Q${end_comment}\E/xx/g if $end_comment;
} }
#printf " t1 = [$t]\n"; elsif ( $multiline_mode and $t =~ /(${string_marker})/ ) {
# Unclosed quote present in line. If multiline_mode is enabled,
# consider it the start of a multiline string.
my $firstpart_marker = $1;
my @sub_token = split(/${string_marker}/, $t );
if ( scalar @sub_token == 1 ) {
# The line ends with a string marker that starts
# a multiline string.
$t = $sub_token[0] . $firstpart_marker;
$in_ml_string = 1;
}
elsif ( scalar @sub_token == 2 ) {
# The line has some more content after the string
# marker that starts a multiline string
$t = $sub_token[0] . $firstpart_marker;
$sub_token[1] =~ s/\Q${start_comment}\E/xx/g;
$sub_token[1] =~ s/\Q${end_comment}\E/xx/g if $end_comment;
$t .= $sub_token[1];
$in_ml_string = 1;
} else {
print "Warning: rm_comments_in_string length \@sub_token > 2
\n";
}
}
#printf " t1 = [$t]\n";
$new_line .= $t; $new_line .= $t;
} }
push @save_lines, $new_line; push @save_lines, $new_line;
} }
print "<- rm_comments_in_strings\n" if $opt_v > 2; print "<- rm_comments_in_strings\n" if $opt_v > 2;
return @save_lines; return @save_lines;
} # 1}}} } # 1}}}
sub remove_between_general { # {{{1 sub remove_between_general { # {{{1
my ($ra_lines, $start_marker, $end_marker, ) = @_; my ($ra_lines, $start_marker, $end_marker, ) = @_;
# Start and end markers may be any length strings. # Start and end markers may be any length strings.
skipping to change at line 6275 skipping to change at line 6650
next if /^\s*$/; next if /^\s*$/;
s/${regex}/${replace}/g; s/${regex}/${replace}/g;
next if /^\s*$/; next if /^\s*$/;
push @save_lines, $_; push @save_lines, $_;
} }
print "<- replace_regex\n" if $opt_v > 2; print "<- replace_regex\n" if $opt_v > 2;
return @save_lines; return @save_lines;
} # 1}}} } # 1}}}
sub replace_between_regex { # {{{1 sub replace_between_regex { # {{{1
my ($ra_lines, $start_RE, $end_RE, $replace_RE, ) = @_; my ($ra_lines, $start_RE, $end_RE, $replace_RE, $multiline_mode ) = @_;
# If multiline_mode is enabled, $replace_RE should not refer
# to any captured groups in $start_RE.
$multiline_mode = 1 if not defined $multiline_mode;
# Start and end regex's may be any length strings. # Start and end regex's may be any length strings.
print "-> replace_between_regex(start=$start_RE, end=$end_RE, replace=$repla ce_RE)\n" print "-> replace_between_regex(start=$start_RE, end=$end_RE, replace=$repla ce_RE)\n"
if $opt_v > 2; if $opt_v > 2;
my $all_lines = join("", @{$ra_lines}); my $all_lines = join("", @{$ra_lines});
my @save_lines = (); my @save_lines = ();
my $in_comment = 0; my $in_comment = 0;
foreach (@{$ra_lines}) { foreach (@{$ra_lines}) {
skipping to change at line 6298 skipping to change at line 6676
s/${start_RE}.*?${end_RE}/${replace_RE}/eeg; # strip one-line comments s/${start_RE}.*?${end_RE}/${replace_RE}/eeg; # strip one-line comments
next if /^\s*$/; next if /^\s*$/;
if ($in_comment) { if ($in_comment) {
if (/$end_RE/) { if (/$end_RE/) {
s/^.*?${end_RE}/${replace_RE}/ee; s/^.*?${end_RE}/${replace_RE}/ee;
$in_comment = 0; $in_comment = 0;
} }
next if $in_comment; next if $in_comment;
} }
next if /^\s*$/; next if /^\s*$/;
$in_comment = 1 if /^(.*?)${start_RE}/; # $1 may be blank or code $in_comment = 1 if $multiline_mode and /^(.*?)${start_RE}/ ; # $1 may be blank or code
next if defined $1 and $1 =~ /^\s*$/; # leading blank; all comment next if defined $1 and $1 =~ /^\s*$/; # leading blank; all comment
if ($in_comment) { if ($in_comment) {
# part code, part comment; strip the comment and keep the code # part code, part comment; strip the comment and keep the code
s/^(.*?)${start_RE}.*$/$1/; s/^(.*?)${start_RE}.*$/$1/;
} }
push @save_lines, $_; push @save_lines, $_;
} }
print "<- replace_between_regex\n" if $opt_v > 2; print "<- replace_between_regex\n" if $opt_v > 2;
return @save_lines; return @save_lines;
skipping to change at line 6827 skipping to change at line 7205
'adb' => 'Ada' , 'adb' => 'Ada' ,
'ads' => 'Ada' , 'ads' => 'Ada' ,
'adso' => 'ADSO/IDSM' , 'adso' => 'ADSO/IDSM' ,
'ahkl' => 'AutoHotkey' , 'ahkl' => 'AutoHotkey' ,
'ahk' => 'AutoHotkey' , 'ahk' => 'AutoHotkey' ,
'agda' => 'Agda' , 'agda' => 'Agda' ,
'lagda' => 'Agda' , 'lagda' => 'Agda' ,
'aj' => 'AspectJ' , 'aj' => 'AspectJ' ,
'am' => 'make' , 'am' => 'make' ,
'ample' => 'AMPLE' , 'ample' => 'AMPLE' ,
'apl' => 'APL' , 'apl' => 'APL' ,
'apla' => 'APL' , 'apla' => 'APL' ,
'aplf' => 'APL' , 'aplf' => 'APL' ,
'aplo' => 'APL' , 'aplo' => 'APL' ,
'apln' => 'APL' , 'apln' => 'APL' ,
'aplc' => 'APL' , 'aplc' => 'APL' ,
'apli' => 'APL' , 'apli' => 'APL' ,
'dyalog' => 'APL' , 'dyalog' => 'APL' ,
'dyapp' => 'APL' , 'dyapp' => 'APL' ,
'mipage' => 'APL' , 'mipage' => 'APL' ,
'as' => 'ActionScript' , 'as' => 'ActionScript' ,
'adoc' => 'AsciiDoc' , 'adoc' => 'AsciiDoc' ,
'asciidoc' => 'AsciiDoc' , 'asciidoc' => 'AsciiDoc' ,
'dofile' => 'AMPLE' , 'dofile' => 'AMPLE' ,
'startup' => 'AMPLE' , 'startup' => 'AMPLE' ,
'axd' => 'ASP' , 'axd' => 'ASP' ,
'ashx' => 'ASP' , 'ashx' => 'ASP' ,
'asa' => 'ASP' , 'asa' => 'ASP' ,
'asax' => 'ASP.NET' , 'asax' => 'ASP.NET' ,
'ascx' => 'ASP.NET' , 'ascx' => 'ASP.NET' ,
'asd' => 'Lisp' , # system definition file 'asd' => 'Lisp' , # system definition file
'nasm' => 'Assembly' , 'nasm' => 'Assembly' ,
'a51' => 'Assembly' , 'a51' => 'Assembly' ,
'asm' => 'Assembly' , 'asm' => 'Assembly' ,
'asmx' => 'ASP.NET' , 'asmx' => 'ASP.NET' ,
'asp' => 'ASP' , 'asp' => 'ASP' ,
'aspx' => 'ASP.NET' , 'aspx' => 'ASP.NET' ,
'master' => 'ASP.NET' , 'master' => 'ASP.NET' ,
'sitemap' => 'ASP.NET' , 'sitemap' => 'ASP.NET' ,
'cshtml' => 'Razor' , 'cshtml' => 'Razor' ,
'razor' => 'Razor' , # Client-side Blazor
'nawk' => 'awk' , 'nawk' => 'awk' ,
'mawk' => 'awk' , 'mawk' => 'awk' ,
'gawk' => 'awk' , 'gawk' => 'awk' ,
'auk' => 'awk' , 'auk' => 'awk' ,
'awk' => 'awk' , 'awk' => 'awk' ,
'bash' => 'Bourne Again Shell' , 'bash' => 'Bourne Again Shell' ,
'bzl' => 'Bazel' ,
'bazel' => 'Bazel' ,
'BUILD' => 'Bazel' ,
'vbhtml' => 'Visual Basic' , 'vbhtml' => 'Visual Basic' ,
'frx' => 'Visual Basic' , 'frx' => 'Visual Basic' ,
'bas' => 'Visual Basic' , 'bas' => 'Visual Basic' ,
'dxl' => 'DOORS Extension Language', 'dxl' => 'DOORS Extension Language',
'bat' => 'DOS Batch' , 'bat' => 'DOS Batch' ,
'BAT' => 'DOS Batch' , 'BAT' => 'DOS Batch' ,
'cmd' => 'DOS Batch' , 'cmd' => 'DOS Batch' ,
'CMD' => 'DOS Batch' , 'CMD' => 'DOS Batch' ,
'btm' => 'DOS Batch' , 'btm' => 'DOS Batch' ,
'BTM' => 'DOS Batch' , 'BTM' => 'DOS Batch' ,
skipping to change at line 6891 skipping to change at line 7273
'cobol' => 'COBOL' , 'cobol' => 'COBOL' ,
'ccp' => 'COBOL' , 'ccp' => 'COBOL' ,
'cbl' => 'COBOL' , 'cbl' => 'COBOL' ,
'CBL' => 'COBOL' , 'CBL' => 'COBOL' ,
'idc' => 'C' , 'idc' => 'C' ,
'cats' => 'C' , 'cats' => 'C' ,
'c' => 'C' , 'c' => 'C' ,
'tpp' => 'C++' , 'tpp' => 'C++' ,
'tcc' => 'C++' , 'tcc' => 'C++' ,
'ipp' => 'C++' , 'ipp' => 'C++' ,
'inl' => 'C++' ,
'h++' => 'C++' , 'h++' => 'C++' ,
'C' => 'C++' , 'C' => 'C++' ,
'cc' => 'C++' , 'cc' => 'C++' ,
'c++' => 'C++' , 'c++' => 'C++' ,
'ccs' => 'CCS' , 'ccs' => 'CCS' ,
'cfc' => 'ColdFusion CFScript' , 'cfc' => 'ColdFusion CFScript' ,
'cfml' => 'ColdFusion' , 'cfml' => 'ColdFusion' ,
'cfm' => 'ColdFusion' , 'cfm' => 'ColdFusion' ,
'chpl' => 'Chapel' , 'chpl' => 'Chapel' ,
'cl' => 'Lisp/OpenCL' , 'cl' => 'Lisp/OpenCL' ,
skipping to change at line 6940 skipping to change at line 7323
'ctl' => 'Visual Basic' , 'ctl' => 'Visual Basic' ,
'cu' => 'CUDA' , 'cu' => 'CUDA' ,
'cuh' => 'CUDA' , # CUDA header file 'cuh' => 'CUDA' , # CUDA header file
'cxx' => 'C++' , 'cxx' => 'C++' ,
'd' => 'D/dtrace' , 'd' => 'D/dtrace' ,
# in addition, .d can map to init.d files typically written as # in addition, .d can map to init.d files typically written as
# bash or sh scripts # bash or sh scripts
'da' => 'DAL' , 'da' => 'DAL' ,
'dart' => 'Dart' , 'dart' => 'Dart' ,
'def' => 'Windows Module Definition', 'def' => 'Windows Module Definition',
'dhall' => 'dhall' ,
'dt' => 'DIET' , 'dt' => 'DIET' ,
'patch' => 'diff' , 'patch' => 'diff' ,
'diff' => 'diff' , 'diff' => 'diff' ,
'dmap' => 'NASTRAN DMAP' , 'dmap' => 'NASTRAN DMAP' ,
'sthlp' => 'Stata' , 'sthlp' => 'Stata' ,
'matah' => 'Stata' , 'matah' => 'Stata' ,
'mata' => 'Stata' , 'mata' => 'Stata' ,
'ihlp' => 'Stata' , 'ihlp' => 'Stata' ,
'doh' => 'Stata' , 'doh' => 'Stata' ,
'ado' => 'Stata' , 'ado' => 'Stata' ,
skipping to change at line 7030 skipping to change at line 7414
'glslv' => 'GLSL' , 'glslv' => 'GLSL' ,
'geo' => 'GLSL' , 'geo' => 'GLSL' ,
'fshader' => 'GLSL' , 'fshader' => 'GLSL' ,
'fsh' => 'GLSL' , 'fsh' => 'GLSL' ,
'frg' => 'GLSL' , 'frg' => 'GLSL' ,
'fp' => 'GLSL' , 'fp' => 'GLSL' ,
'glsl' => 'GLSL' , 'glsl' => 'GLSL' ,
'graphqls' => 'GraphQL' , 'graphqls' => 'GraphQL' ,
'gql' => 'GraphQL' , 'gql' => 'GraphQL' ,
'graphql' => 'GraphQL' , 'graphql' => 'GraphQL' ,
'vert' => 'GLSL' , 'vert' => 'GLSL' ,
'tesc' => 'GLSL' , 'tesc' => 'GLSL' ,
'tese' => 'GLSL' , 'tese' => 'GLSL' ,
'geom' => 'GLSL' , 'geom' => 'GLSL' ,
'feature' => 'Cucumber' , 'feature' => 'Cucumber' ,
'frag' => 'GLSL' , 'frag' => 'GLSL' ,
'comp' => 'GLSL' , 'comp' => 'GLSL' ,
'g' => 'ANTLR Grammar' , 'g' => 'ANTLR Grammar' ,
'g4' => 'ANTLR Grammar' , 'g4' => 'ANTLR Grammar' ,
'go' => 'Go' , 'go' => 'Go' ,
'gsp' => 'Grails' , 'gsp' => 'Grails' ,
'jenkinsfile' => 'Groovy' , 'jenkinsfile' => 'Groovy' ,
'gvy' => 'Groovy' , 'gvy' => 'Groovy' ,
'gtpl' => 'Groovy' , 'gtpl' => 'Groovy' ,
'grt' => 'Groovy' , 'grt' => 'Groovy' ,
'groovy' => 'Groovy' , 'groovy' => 'Groovy' ,
'gant' => 'Groovy' , 'gant' => 'Groovy' ,
skipping to change at line 7231 skipping to change at line 7615
'vbproj' => 'MSBuild script' , 'vbproj' => 'MSBuild script' ,
'mps' => 'MUMPS' , 'mps' => 'MUMPS' ,
'mth' => 'Teamcenter mth' , 'mth' => 'Teamcenter mth' ,
'n' => 'Nemerle' , 'n' => 'Nemerle' ,
'nims' => 'Nim' , 'nims' => 'Nim' ,
'nimrod' => 'Nim' , 'nimrod' => 'Nim' ,
'nimble' => 'Nim' , 'nimble' => 'Nim' ,
'nim.cfg' => 'Nim' , 'nim.cfg' => 'Nim' ,
'nim' => 'Nim' , 'nim' => 'Nim' ,
'nix' => 'Nix' , 'nix' => 'Nix' ,
'nut' => 'Squirrel' ,
'oscript' => 'LiveLink OScript' , 'oscript' => 'LiveLink OScript' ,
'bod' => 'Oracle PL/SQL' , 'bod' => 'Oracle PL/SQL' ,
'spc' => 'Oracle PL/SQL' , 'spc' => 'Oracle PL/SQL' ,
'fnc' => 'Oracle PL/SQL' , 'fnc' => 'Oracle PL/SQL' ,
'prc' => 'Oracle PL/SQL' , 'prc' => 'Oracle PL/SQL' ,
'trg' => 'Oracle PL/SQL' , 'trg' => 'Oracle PL/SQL' ,
'pad' => 'Ada' , # Oracle Ada preprocessor 'pad' => 'Ada' , # Oracle Ada preprocessor
'page' => 'Visualforce Page' , 'page' => 'Visualforce Page' ,
'pas' => 'Pascal' , 'pas' => 'Pascal' ,
'pcc' => 'C++' , # Oracle C++ preprocessor 'pcc' => 'C++' , # Oracle C++ preprocessor
skipping to change at line 7266 skipping to change at line 7651
'php_cs.dist' => 'PHP' , 'php_cs.dist' => 'PHP' ,
'php_cs' => 'PHP' , 'php_cs' => 'PHP' ,
'php3' => 'PHP' , 'php3' => 'PHP' ,
'php4' => 'PHP' , 'php4' => 'PHP' ,
'php5' => 'PHP' , 'php5' => 'PHP' ,
'php' => 'PHP' , 'php' => 'PHP' ,
'phtml' => 'PHP' , 'phtml' => 'PHP' ,
'pig' => 'Pig Latin' , 'pig' => 'Pig Latin' ,
'plh' => 'Perl' , 'plh' => 'Perl' ,
'pl' => 'Perl/Prolog' , 'pl' => 'Perl/Prolog' ,
'p6' => 'Perl/Prolog' ,
'PL' => 'Perl/Prolog' , 'PL' => 'Perl/Prolog' ,
'p6' => 'Raku/Prolog' ,
'P6' => 'Raku/Prolog' ,
'plx' => 'Perl' , 'plx' => 'Perl' ,
'pm' => 'Perl' , 'pm' => 'Perl' ,
'pm6' => 'Perl' , 'pm6' => 'Raku' ,
'raku' => 'Raku' ,
'rakumod' => 'Raku' ,
'pom.xml' => 'Maven' , 'pom.xml' => 'Maven' ,
'pom' => 'Maven' , 'pom' => 'Maven' ,
'yap' => 'Prolog' , 'yap' => 'Prolog' ,
'prolog' => 'Prolog' , 'prolog' => 'Prolog' ,
'P' => 'Prolog' , 'P' => 'Prolog' ,
'p' => 'Pascal' , 'p' => 'Pascal' ,
'pp' => 'Pascal/Puppet' , 'pp' => 'Pascal/Puppet' ,
'viw' => 'SQL' , 'viw' => 'SQL' ,
'udf' => 'SQL' , 'udf' => 'SQL' ,
'tab' => 'SQL' , 'tab' => 'SQL' ,
skipping to change at line 7414 skipping to change at line 7802
're' => 'ReasonML' , 're' => 'ReasonML' ,
'rei' => 'ReasonML' , 'rei' => 'ReasonML' ,
'scrbl' => 'Racket' , 'scrbl' => 'Racket' ,
'sps' => 'Scheme' , 'sps' => 'Scheme' ,
'sc' => 'Scheme' , 'sc' => 'Scheme' ,
'ss' => 'Scheme' , 'ss' => 'Scheme' ,
'scm' => 'Scheme' , 'scm' => 'Scheme' ,
'sch' => 'Scheme' , 'sch' => 'Scheme' ,
'sls' => 'Scheme/SaltStack' , 'sls' => 'Scheme/SaltStack' ,
'sld' => 'Scheme' , 'sld' => 'Scheme' ,
'tsv' => 'RobotFramework' ,
'robot' => 'RobotFramework' , 'robot' => 'RobotFramework' ,
'rc' => 'Windows Resource File' , 'rc' => 'Windows Resource File' ,
'rc2' => 'Windows Resource File' , 'rc2' => 'Windows Resource File' ,
'sas' => 'SAS' , 'sas' => 'SAS' ,
'sass' => 'Sass' , 'sass' => 'Sass' ,
'scss' => 'Sass' , 'scss' => 'Sass' ,
'sh' => 'Bourne Shell' , 'sh' => 'Bourne Shell' ,
'smarty' => 'Smarty' , 'smarty' => 'Smarty' ,
'sml' => 'Standard ML' , 'sml' => 'Standard ML' ,
'sig' => 'Standard ML' , 'sig' => 'Standard ML' ,
'fun' => 'Standard ML' , 'fun' => 'Standard ML' ,
'slim' => 'Slim' , 'slim' => 'Slim' ,
'e' => 'Specman e' , 'e' => 'Specman e' ,
'sql' => 'SQL' , 'sql' => 'SQL' ,
'SQL' => 'SQL' , 'SQL' => 'SQL' ,
'sproc.sql' => 'SQL Stored Procedure' , 'sproc.sql' => 'SQL Stored Procedure' ,
'spoc.sql' => 'SQL Stored Procedure' , 'spoc.sql' => 'SQL Stored Procedure' ,
'spc.sql' => 'SQL Stored Procedure' , 'spc.sql' => 'SQL Stored Procedure' ,
'udf.sql' => 'SQL Stored Procedure' , 'udf.sql' => 'SQL Stored Procedure' ,
'data.sql' => 'SQL Data' , 'data.sql' => 'SQL Data' ,
'sss' => 'SugarSS' ,
'st' => 'Smalltalk' , 'st' => 'Smalltalk' ,
'styl' => 'Stylus' , 'styl' => 'Stylus' ,
'i' => 'SWIG' , 'i' => 'SWIG' ,
'svelte' => 'Svelte' ,
'sv' => 'Verilog-SystemVerilog' , 'sv' => 'Verilog-SystemVerilog' ,
'svh' => 'Verilog-SystemVerilog' , 'svh' => 'Verilog-SystemVerilog' ,
'svg' => 'SVG' , 'svg' => 'SVG' ,
'SVG' => 'SVG' , 'SVG' => 'SVG' ,
'v' => 'Verilog-SystemVerilog/Coq' , 'v' => 'Verilog-SystemVerilog/Coq' ,
'tcl' => 'Tcl/Tk' , 'tcl' => 'Tcl/Tk' ,
'tcsh' => 'C Shell' , 'tcsh' => 'C Shell' ,
'tk' => 'Tcl/Tk' , 'tk' => 'Tcl/Tk' ,
'mkvi' => 'TeX' , 'mkvi' => 'TeX' ,
'mkiv' => 'TeX' , 'mkiv' => 'TeX' ,
skipping to change at line 7469 skipping to change at line 7858
# 'cls' => 'TeX' , # 'cls' => 'TeX' ,
'dtx' => 'TeX' , 'dtx' => 'TeX' ,
'bst' => 'TeX' , 'bst' => 'TeX' ,
'thrift' => 'Thrift' , 'thrift' => 'Thrift' ,
'tpl' => 'Smarty' , 'tpl' => 'Smarty' ,
'trigger' => 'Apex Trigger' , 'trigger' => 'Apex Trigger' ,
'ttcn' => 'TTCN' , 'ttcn' => 'TTCN' ,
'ttcn2' => 'TTCN' , 'ttcn2' => 'TTCN' ,
'ttcn3' => 'TTCN' , 'ttcn3' => 'TTCN' ,
'ttcnpp' => 'TTCN' , 'ttcnpp' => 'TTCN' ,
'sdl' => 'TNSDL' ,
'ssc' => 'TNSDL' ,
'sdt' => 'TNSDL' ,
'spd' => 'TNSDL' ,
'sst' => 'TNSDL' ,
'rou' => 'TNSDL' ,
'cin' => 'TNSDL' ,
'cii' => 'TNSDL' ,
'interface' => 'TNSDL' ,
'in1' => 'TNSDL' ,
'in2' => 'TNSDL' ,
'in3' => 'TNSDL' ,
'in4' => 'TNSDL' ,
'inf' => 'TNSDL' ,
'tpd' => 'TITAN Project File Information', 'tpd' => 'TITAN Project File Information',
'ts' => 'TypeScript/Qt Linguist', 'ts' => 'TypeScript/Qt Linguist',
'tsx' => 'TypeScript' , 'tsx' => 'TypeScript' ,
'tss' => 'Titanium Style Sheet' , 'tss' => 'Titanium Style Sheet' ,
'twig' => 'Twig' , 'twig' => 'Twig' ,
'ui' => 'Qt/Glade' , 'ui' => 'Qt/Glade' ,
'glade' => 'Glade' , 'glade' => 'Glade' ,
'vala' => 'Vala' , 'vala' => 'Vala' ,
'vapi' => 'Vala Header' , 'vapi' => 'Vala Header' ,
'vhw' => 'VHDL' , 'vhw' => 'VHDL' ,
skipping to change at line 7650 skipping to change at line 8053
'dtrace' => 'dtrace' , 'dtrace' => 'dtrace' ,
'escript' => 'Erlang' , 'escript' => 'Erlang' ,
'groovy' => 'Groovy' , 'groovy' => 'Groovy' ,
'idl' => 'IDL' , 'idl' => 'IDL' ,
'kermit' => 'Kermit' , 'kermit' => 'Kermit' ,
'ksh' => 'Korn Shell' , 'ksh' => 'Korn Shell' ,
'lua' => 'Lua' , 'lua' => 'Lua' ,
'make' => 'make' , 'make' => 'make' ,
'octave' => 'Octave' , 'octave' => 'Octave' ,
'perl5' => 'Perl' , 'perl5' => 'Perl' ,
'perl6' => 'Perl' ,
'perl' => 'Perl' , 'perl' => 'Perl' ,
'miniperl' => 'Perl' , 'miniperl' => 'Perl' ,
'php' => 'PHP' , 'php' => 'PHP' ,
'php5' => 'PHP' , 'php5' => 'PHP' ,
'python' => 'Python' , 'python' => 'Python' ,
'python2.6'=> 'Python' , 'python2.6'=> 'Python' ,
'python2.7'=> 'Python' , 'python2.7'=> 'Python' ,
'python3' => 'Python' , 'python3' => 'Python' ,
'python3.3'=> 'Python' , 'python3.3'=> 'Python' ,
'python3.4'=> 'Python' , 'python3.4'=> 'Python' ,
'python3.5'=> 'Python' , 'python3.5'=> 'Python' ,
'python3.6'=> 'Python' , 'python3.6'=> 'Python' ,
'python3.7'=> 'Python' , 'python3.7'=> 'Python' ,
'python3.8'=> 'Python' , 'python3.8'=> 'Python' ,
'perl6' => 'Raku' ,
'raku' => 'Raku' ,
'rakudo' => 'Raku' ,
'rexx' => 'Rexx' , 'rexx' => 'Rexx' ,
'regina' => 'Rexx' , 'regina' => 'Rexx' ,
'ruby' => 'Ruby' , 'ruby' => 'Ruby' ,
'sed' => 'sed' , 'sed' => 'sed' ,
'sh' => 'Bourne Shell' , 'sh' => 'Bourne Shell' ,
'swipl' => 'Prolog' , 'swipl' => 'Prolog' ,
'tcl' => 'Tcl/Tk' , 'tcl' => 'Tcl/Tk' ,
'tclsh' => 'Tcl/Tk' , 'tclsh' => 'Tcl/Tk' ,
'tcsh' => 'C Shell' , 'tcsh' => 'C Shell' ,
'wish' => 'Tcl/Tk' , 'wish' => 'Tcl/Tk' ,
'zsh' => 'zsh' , 'zsh' => 'zsh' ,
); );
# 1}}} # 1}}}
%{$rh_Language_by_File} = ( # {{{1 %{$rh_Language_by_File} = ( # {{{1
'build.xml' => 'Ant/XML' , 'build.xml' => 'Ant/XML' ,
'BUILD' => 'Bazel' ,
'WORKSPACE' => 'Bazel' ,
'CMakeLists.txt' => 'CMake' , 'CMakeLists.txt' => 'CMake' ,
'Jamfile' => 'Jam' , 'Jamfile' => 'Jam' ,
'Jamrules' => 'Jam' , 'Jamrules' => 'Jam' ,
'Makefile' => 'make' , 'Makefile' => 'make' ,
'makefile' => 'make' , 'makefile' => 'make' ,
'gnumakefile' => 'make' , 'gnumakefile' => 'make' ,
'Gnumakefile' => 'make' , 'Gnumakefile' => 'make' ,
'pom.xml' => 'Maven/XML' , 'pom.xml' => 'Maven/XML' ,
'Rakefile' => 'Ruby' , 'Rakefile' => 'Ruby' ,
'rakefile' => 'Ruby' , 'rakefile' => 'Ruby' ,
skipping to change at line 7778 skipping to change at line 8185
[ 'remove_matches' , '^\*' ], # z/OS As sembly [ 'remove_matches' , '^\*' ], # z/OS As sembly
], ],
'AutoHotkey' => [ 'AutoHotkey' => [
[ 'remove_matches' , '^\s*;' ], [ 'remove_matches' , '^\s*;' ],
[ 'remove_inline' , ';.*$' ], [ 'remove_inline' , ';.*$' ],
], ],
'awk' => [ 'awk' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Bazel' => [
[ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ],
],
'bc' => [ 'bc' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Blade' => [ 'Blade' => [
[ 'remove_between_general', '{{--', '--}}' ], [ 'remove_between_general', '{{--', '--}}' ],
[ 'remove_html_comments', ], [ 'remove_html_comments', ],
], ],
'Bourne Again Shell' => [ 'Bourne Again Shell' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
skipping to change at line 7830 skipping to change at line 8241
'C/C++ Header' => [ 'C/C++ Header' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Clean' => [ 'Clean' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Clojure' => [ [ 'remove_matches' , '^\s*;' ], ], 'Clojure' => [
[ 'remove_matches' , '^\s*;' ],
[ 'remove_matches' , '^\s*#_' ],
],
'ClojureScript' => [ [ 'remove_matches' , '^\s*;' ], ], 'ClojureScript' => [ [ 'remove_matches' , '^\s*;' ], ],
'ClojureC' => [ [ 'remove_matches' , '^\s*;' ], ], 'ClojureC' => [ [ 'remove_matches' , '^\s*;' ], ],
'CMake' => [ 'CMake' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Crystal' => [ 'Crystal' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
skipping to change at line 7912 skipping to change at line 8326
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'DAL' => [ 'DAL' => [
[ 'remove_between_general', '[', ']', ], [ 'remove_between_general', '[', ']', ],
], ],
'Dart' => [ 'Dart' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'dhall' => [ [ 'remove_haskell_comments', '>filename<' ], ],
'DIET' => [ # same as Pug 'DIET' => [ # same as Pug
[ 'remove_pug_block' , ], [ 'remove_pug_block' , ],
[ 'remove_matches' , '^\s*//' ], [ 'remove_matches' , '^\s*//' ],
[ 'remove_inline' , '//.*$' ], [ 'remove_inline' , '//.*$' ],
], ],
# diff is kind of weird: anything but a space in the first column # diff is kind of weird: anything but a space in the first column
# will count as code, with the exception of #, ---, +++. Spaces # will count as code, with the exception of #, ---, +++. Spaces
# in the first column denote context lines which aren't part of the # in the first column denote context lines which aren't part of the
# difference. # difference.
'diff' => [ 'diff' => [
skipping to change at line 8066 skipping to change at line 8481
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
[ 'remove_inline' , '//.*$' ], [ 'remove_inline' , '//.*$' ],
], ],
'Gradle' => [ # same as Groovy 'Gradle' => [ # same as Groovy
[ 'remove_inline' , '//.*$' ], [ 'remove_inline' , '//.*$' ],
# separate /* inside quoted strings with two # separate /* inside quoted strings with two
# concatenated strings split between / and * # concatenated strings split between / and *
[ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1', [ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1',
'(.*?)' , '"$1$2$1 + $1$3$1$4"'], '(.*?)' , '"$1$2$1 + $1$3$1$4"', 0],
[ 'rm_comments_in_strings', '"""', '/*', '*/', 1
],
[ 'rm_comments_in_strings', '"""', '//', '', 1],
[ 'rm_comments_in_strings', "'''", '/*', '*/', 1
],
[ 'rm_comments_in_strings', "'''", '//', '', 1],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Grails' => [ 'Grails' => [
[ 'remove_html_comments', ], [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], [ 'call_regexp_common' , 'HTML' ],
[ 'remove_jsp_comments' , ], [ 'remove_jsp_comments' , ],
[ 'add_newlines' , ], [ 'add_newlines' , ],
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'GraphQL' => [ 'GraphQL' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Groovy' => [ 'Groovy' => [
[ 'remove_inline' , '//.*$' ], [ 'remove_inline' , '//.*$' ],
# separate /* inside quoted strings with two # separate /* inside quoted strings with two
# concatenated strings split between / and * # concatenated strings split between / and *
[ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1', [ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1',
'(.*?)' , '"$1$2$1 + $1$3$1$4"'], '(.*?)' , '"$1$2$1 + $1$3$1$4"', 0],
[ 'rm_comments_in_strings', '"""', '/*', '*/', 1
],
[ 'rm_comments_in_strings', '"""', '//', '', 1],
[ 'rm_comments_in_strings', "'''", '/*', '*/', 1
],
[ 'rm_comments_in_strings', "'''", '//', '', 1],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Handlebars' => [ 'Handlebars' => [
[ 'remove_between_general', '{{!--', '--}}' ], [ 'remove_between_general', '{{!--', '--}}' ],
[ 'remove_between_general', '{{!', '}}' ], [ 'remove_between_general', '{{!', '}}' ],
[ 'remove_html_comments', ], [ 'remove_html_comments', ],
], ],
'Harbour' => [ 'Harbour' => [
[ 'remove_matches' , '^\s*\&\&' ], [ 'remove_matches' , '^\s*\&\&' ],
[ 'remove_matches' , '^\s*\*' ], [ 'remove_matches' , '^\s*\*' ],
skipping to change at line 8206 skipping to change at line 8629
[ 'replace_between_regex', '(["\'])(.*?\*/)\g1', [ 'replace_between_regex', '(["\'])(.*?\*/)\g1',
'(.*?)' , '"xx"'], '(.*?)' , '"xx"'],
## separate /* inside quoted strings with two ## separate /* inside quoted strings with two
## concatenated strings split between / and * ## concatenated strings split between / and *
## -> defeated by "xx/**/*_xx" issue 365 ## -> defeated by "xx/**/*_xx" issue 365
#[ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1', #[ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1',
# '(.*?)' , '"$1$2$1 + $1$3$1$4"'], # '(.*?)' , '"$1$2$1 + $1$3$1$4"'],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'JavaScript' => [ 'JavaScript' => [
[ 'rm_comments_in_strings', "'", '/*', '*/' ],
[ 'rm_comments_in_strings', "'", '//', '' ],
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'JSX' => [ 'JSX' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'JCL' => [ [ 'remove_jcl_comments' , ], ], 'JCL' => [ [ 'remove_jcl_comments' , ], ],
skipping to change at line 8232 skipping to change at line 8657
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Julia' => [ 'Julia' => [
[ 'remove_between_general', '#=', '=#' ], [ 'remove_between_general', '#=', '=#' ],
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Kotlin' => [ 'Kotlin' => [
[ 'rm_comments_in_strings', '"""', '/*', '*/', 1
],
[ 'rm_comments_in_strings', '"""', '//', '', 1],
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Lean' => [ 'Lean' => [
[ 'remove_between_general', '/-', '-/' ], [ 'remove_between_general', '/-', '-/' ],
[ 'remove_matches' , '^\s*--' ], [ 'remove_matches' , '^\s*--' ],
[ 'remove_inline' , '--.*$' ], [ 'remove_inline' , '--.*$' ],
], ],
'LESS' => [ 'LESS' => [
skipping to change at line 8270 skipping to change at line 8697
'Lisp/OpenCL' => [ [ 'die' , ], ], # never called 'Lisp/OpenCL' => [ [ 'die' , ], ], # never called
'Lisp/Julia' => [ [ 'die' , ], ], # never called 'Lisp/Julia' => [ [ 'die' , ], ], # never called
'LiveLink OScript' => [ [ 'remove_matches' , '^\s*//' ], ], 'LiveLink OScript' => [ [ 'remove_matches' , '^\s*//' ], ],
'Logtalk' => [ # same filters as Prolog 'Logtalk' => [ # same filters as Prolog
[ 'remove_matches' , '^\s*\%' ], [ 'remove_matches' , '^\s*\%' ],
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_inline' , '(//|\%).*$' ], [ 'remove_inline' , '(//|\%).*$' ],
], ],
# 'Lua' => [ [ 'call_regexp_common' , 'lua' ], ], # 'Lua' => [ [ 'call_regexp_common' , 'lua' ], ],
'Lua' => [ 'Lua' => [
[ 'remove_between_general [ 'remove_between_general', '--[=====[', ']=====
', '--[=====[', ']=====]' ], ]' ],
[ 'remove_between_general [ 'remove_between_general', '--[====[', ']====]'
', '--[====[', ']====]' ], ],
[ 'remove_between_general [ 'remove_between_general', '--[===[', ']===]' ]
', '--[===[', ']===]' ], ,
[ 'remove_between_general [ 'remove_between_general', '--[==[', ']==]' ],
', '--[==[', ']==]' ], [ 'remove_between_general', '--[=[', ']=]' ],
[ 'remove_between_general
', '--[=[', ']=]' ],
[ 'remove_between_general', '--[[', ']]' ], [ 'remove_between_general', '--[[', ']]' ],
[ 'remove_matches' , '^\s*\-\-' ], [ 'remove_matches' , '^\s*\-\-' ],
], ],
'make' => [ 'make' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'MATLAB' => [ 'MATLAB' => [
[ 'remove_matches' , '^\s*%' ], [ 'remove_matches' , '^\s*%' ],
[ 'remove_inline' , '%.*$' ], [ 'remove_inline' , '%.*$' ],
skipping to change at line 8492 skipping to change at line 8919
], ],
'Rmd' => [ 'Rmd' => [
[ 'reduce_to_rmd_code_blocks' ], [ 'reduce_to_rmd_code_blocks' ],
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Racket' => [ 'Racket' => [
[ 'remove_matches' , '^\s*;' ], [ 'remove_matches' , '^\s*;' ],
[ 'remove_inline' , ';.*$' ], [ 'remove_inline' , ';.*$' ],
], ],
'Raku' => [ [ 'remove_matches' , '^\s*#' ],
[ 'remove_below_above' , '^=head1', '^=cut' ],
[ 'remove_below_above' , '^=begin', '^=end' ],
[ 'remove_inline' , '#.*$' ],
],
'Raku/Prolog' => [ [ 'die' , ], ], # never called
'RAML' => [ 'RAML' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'RapydScript' => [ 'RapydScript' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'docstring_to_C' ], [ 'docstring_to_C' ],
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
skipping to change at line 8557 skipping to change at line 8990
'Scala' => [ 'Scala' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Scheme/SaltStack' => [ [ 'die' , ], ], # never called 'Scheme/SaltStack' => [ [ 'die' , ], ], # never called
'Scheme' => [ 'Scheme' => [
[ 'remove_matches' , '^\s*;' ], [ 'remove_matches' , '^\s*;' ],
[ 'remove_inline' , ';.*$' ], [ 'remove_inline' , ';.*$' ],
], ],
'sed' => [
[ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ],
],
'Slice' => [ 'Slice' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Slim' => [ 'Slim' => [
[ 'remove_slim_block' , ], [ 'remove_slim_block' , ],
], ],
'SKILL' => [ 'SKILL' => [
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_matches' , '^\s*;' ], [ 'remove_matches' , '^\s*;' ],
], ],
'SKILL++' => [ 'SKILL++' => [
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_matches' , '^\s*;' ], [ 'remove_matches' , '^\s*;' ],
], ],
'Squirrel' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ],
[ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ],
],
'Starlark' => [ 'Starlark' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'docstring_to_C' ], [ 'docstring_to_C' ],
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Solidity' => [ 'Solidity' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
skipping to change at line 8613 skipping to change at line 9057
'SQL Stored Procedure'=> [ 'SQL Stored Procedure'=> [
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_matches' , '^\s*--' ], [ 'remove_matches' , '^\s*--' ],
[ 'remove_inline' , '--.*$' ], [ 'remove_inline' , '--.*$' ],
], ],
'SQL Data' => [ 'SQL Data' => [
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
[ 'remove_matches' , '^\s*--' ], [ 'remove_matches' , '^\s*--' ],
[ 'remove_inline' , '--.*$' ], [ 'remove_inline' , '--.*$' ],
], ],
'sed' => [
[ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ],
],
'Smalltalk' => [ 'Smalltalk' => [
[ 'call_regexp_common' , 'Smalltalk' ], [ 'call_regexp_common' , 'Smalltalk' ],
], ],
'Smarty' => [ 'Smarty' => [
[ 'smarty_to_C' ], [ 'smarty_to_C' ],
[ 'call_regexp_common' , 'C' ], [ 'call_regexp_common' , 'C' ],
], ],
'Standard ML' => [ 'Standard ML' => [
[ 'remove_between_general', '(*', '*)' ], [ 'remove_between_general', '(*', '*)' ],
], ],
'Stata' => [ 'Stata' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'Stylus' => [ 'Stylus' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'SugarSS' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ],
],
'Svelte' => [
[ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ],
],
'SVG' => [ 'SVG' => [
[ 'remove_html_comments', ], [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], [ 'call_regexp_common' , 'HTML' ],
], ],
'Swift' => [ 'Swift' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'SWIG' => [ 'SWIG' => [
skipping to change at line 8688 skipping to change at line 9137
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'Titanium Style Sheet' => [ 'Titanium Style Sheet' => [
[ 'remove_matches' , '^\s*//' ], [ 'remove_matches' , '^\s*//' ],
[ 'remove_inline' , '//.*$' ], [ 'remove_inline' , '//.*$' ],
[ 'remove_between_regex', '/[^/]', '[^/]/' ], [ 'remove_between_regex', '/[^/]', '[^/]/' ],
], ],
'TNSDL' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'call_regexp_common' , 'C++' ],
],
'TOML' => [ 'TOML' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
[ 'remove_inline' , '#.*$' ], [ 'remove_inline' , '#.*$' ],
], ],
'TTCN' => [ 'TTCN' => [
[ 'rm_comments_in_strings', '"', '/*', '*/' ], [ 'rm_comments_in_strings', '"', '/*', '*/' ],
[ 'rm_comments_in_strings', '"', '//', '' ], [ 'rm_comments_in_strings', '"', '//', '' ],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
], ],
'TITAN Project File Information' => [ 'TITAN Project File Information' => [
skipping to change at line 8871 skipping to change at line 9324
[ 'remove_between_general', '(:', ':)' ], [ 'remove_between_general', '(:', ':)' ],
], ],
'XSD' => [ [ 'remove_html_comments', ], 'XSD' => [ [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], ], [ 'call_regexp_common' , 'HTML' ], ],
'XSLT' => [ [ 'remove_html_comments', ], 'XSLT' => [ [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], ], [ 'call_regexp_common' , 'HTML' ], ],
'Xtend' => [ # copy of Java, plus triple << inline 'Xtend' => [ # copy of Java, plus triple << inline
# separate /* inside quoted strings with two # separate /* inside quoted strings with two
# concatenated strings split between / and * # concatenated strings split between / and *
[ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1', [ 'replace_between_regex', '(["\'])(.*?/)(\*.*?) \g1',
'(.*?)' , '"$1$2$1 + $1$3$1$4"'], '(.*?)' , '"$1$2$1 + $1$3$1$4"', 0],
[ 'call_regexp_common' , 'C++' ], [ 'call_regexp_common' , 'C++' ],
[ 'remove_matches' , '^\s*\x{c2ab}{3}' ], # doesn't work [ 'remove_matches' , '^\s*\x{c2ab}{3}' ], # doesn't work
# \xCA2B is unicode << character # \xCA2B is unicode << character
], ],
'NAnt script' => [ [ 'remove_html_comments', ], 'NAnt script' => [ [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], ], [ 'call_regexp_common' , 'HTML' ], ],
'MSBuild script' => [ [ 'remove_html_comments', ], 'MSBuild script' => [ [ 'remove_html_comments', ],
[ 'call_regexp_common' , 'HTML' ], ], [ 'call_regexp_common' , 'HTML' ], ],
'zsh' => [ 'zsh' => [
[ 'remove_matches' , '^\s*#' ], [ 'remove_matches' , '^\s*#' ],
skipping to change at line 9001 skipping to change at line 9454
'png' => 1, 'png' => 1,
'ps' => 1, # Postscript is _USUALLY_ generated automatically. 'ps' => 1, # Postscript is _USUALLY_ generated automatically.
'sgm' => 1, 'sgm' => 1,
'sgml' => 1, 'sgml' => 1,
'so' => 1, # Dynamically-loaded object code. 'so' => 1, # Dynamically-loaded object code.
'Tag' => 1, 'Tag' => 1,
'text' => 1, 'text' => 1,
'tfm' => 1, 'tfm' => 1,
'tgz' => 1, # gzipped tarball 'tgz' => 1, # gzipped tarball
'tiff' => 1, 'tiff' => 1,
'tsv' => 1, # tab separated values
'txt' => 1, 'txt' => 1,
'vf' => 1, 'vf' => 1,
'wav' => 1, 'wav' => 1,
'xbm' => 1, 'xbm' => 1,
'xpm' => 1, 'xpm' => 1,
'Y' => 1, # file compressed with "Yabba" 'Y' => 1, # file compressed with "Yabba"
'Z' => 1, # file compressed with "compress" 'Z' => 1, # file compressed with "compress"
'zip' => 1, # zip archive 'zip' => 1, # zip archive
'gitignore' => 1, 'gitignore' => 1,
); # 1}}} ); # 1}}}
skipping to change at line 9129 skipping to change at line 9583
'Assembly (macro)' => 0.51, 'Assembly (macro)' => 0.51,
'associative default' => 1.25, 'associative default' => 1.25,
'autocoder' => 0.25, 'autocoder' => 0.25,
'AutoHotkey' => 1.29, 'AutoHotkey' => 1.29,
'awk' => 3.81, 'awk' => 3.81,
'aztec c' => 0.63, 'aztec c' => 0.63,
'balm' => 0.75, 'balm' => 0.75,
'base sas' => 1.51, 'base sas' => 1.51,
'basic' => 0.75, 'basic' => 0.75,
'basic a' => 0.63, 'basic a' => 0.63,
'Bazel' => 1.00,
'bc' => 1.50, 'bc' => 1.50,
'berkeley pascal' => 0.88, 'berkeley pascal' => 0.88,
'better basic' => 0.88, 'better basic' => 0.88,
'Blade' => 2.00, 'Blade' => 2.00,
'bliss' => 0.75, 'bliss' => 0.75,
'bmsgen' => 2.22, 'bmsgen' => 2.22,
'boeingcalc' => 13.33, 'boeingcalc' => 13.33,
'bteq' => 6.15, 'bteq' => 6.15,
'Brainfuck' => 0.10, 'Brainfuck' => 0.10,
'BrightScript' => 2.00, 'BrightScript' => 2.00,
skipping to change at line 9153 skipping to change at line 9608
'C++' => 1.51, 'C++' => 1.51,
'c86plus' => 0.63, 'c86plus' => 0.63,
'cadbfast' => 2.00, 'cadbfast' => 2.00,
'caearl' => 2.86, 'caearl' => 2.86,
'cast' => 1.63, 'cast' => 1.63,
'cbasic' => 0.88, 'cbasic' => 0.88,
'cdadl' => 4.00, 'cdadl' => 4.00,
'cellsim' => 1.74, 'cellsim' => 1.74,
'ColdFusion' => 4.00, 'ColdFusion' => 4.00,
'ColdFusion CFScript' => 4.00, 'ColdFusion CFScript' => 4.00,
'Chapel' => 2.96, # estimate from some test code ba ses comparing to Python 'Chapel' => 2.96,
'chili' => 0.75, 'chili' => 0.75,
'chill' => 0.75, 'chill' => 0.75,
'cics' => 1.74, 'cics' => 1.74,
'clarion' => 1.38, 'clarion' => 1.38,
'clascal' => 1.00, 'clascal' => 1.00,
'Clean' => 2.50, 'Clean' => 2.50,
'cli' => 2.50, 'cli' => 2.50,
'clipper' => 2.05, 'clipper' => 2.05,
'clipper db' => 2.00, 'clipper db' => 2.00,
'clos' => 3.81, 'clos' => 3.81,
skipping to change at line 9217 skipping to change at line 9672
'data base default' => 2.00, 'data base default' => 2.00,
'dataflex' => 2.00, 'dataflex' => 2.00,
'datatrieve' => 4.00, 'datatrieve' => 4.00,
'dbase iii' => 2.00, 'dbase iii' => 2.00,
'dbase iv' => 1.54, 'dbase iv' => 1.54,
'DIET' => 2.00, 'DIET' => 2.00,
'diff' => 1.00, 'diff' => 1.00,
'decision support default' => 2.22, 'decision support default' => 2.22,
'decrally' => 2.00, 'decrally' => 2.00,
'delphi' => 2.76, 'delphi' => 2.76,
'dhall' => 2.11,
'DITA' => 1.90, 'DITA' => 1.90,
'dl/1' => 2.00, 'dl/1' => 2.00,
'dtrace' => 2.00, 'dtrace' => 2.00,
'NASTRAN DMAP' => 2.35, 'NASTRAN DMAP' => 2.35,
'dna4' => 4.21, 'dna4' => 4.21,
'DOORS Extension Language' => 1.50, 'DOORS Extension Language' => 1.50,
'Dockerfile' => 2.00, 'Dockerfile' => 2.00,
'DOS Batch' => 0.63, 'DOS Batch' => 0.63,
'Drools' => 2.00, 'Drools' => 2.00,
'dsp assembly' => 0.50, 'dsp assembly' => 0.50,
skipping to change at line 9553 skipping to change at line 10009
'query default' => 6.15, 'query default' => 6.15,
'quick basic 1' => 1.25, 'quick basic 1' => 1.25,
'quick basic 2' => 1.31, 'quick basic 2' => 1.31,
'quick basic 3' => 1.38, 'quick basic 3' => 1.38,
'quick c' => 0.63, 'quick c' => 0.63,
'quickbuild' => 2.86, 'quickbuild' => 2.86,
'quiz' => 5.33, 'quiz' => 5.33,
'R' => 3.00, 'R' => 3.00,
'Rmd' => 3.00, 'Rmd' => 3.00,
'Racket' => 1.50, 'Racket' => 1.50,
'Raku' => 4.00,
'rally' => 2.00, 'rally' => 2.00,
'ramis ii' => 2.00, 'ramis ii' => 2.00,
'RAML' => 0.90, 'RAML' => 0.90,
'rapidgen' => 2.86, 'rapidgen' => 2.86,
'ratfor' => 0.88, 'ratfor' => 0.88,
'rdb' => 2.00, 'rdb' => 2.00,
'realia' => 1.74, 'realia' => 1.74,
'realizer 1.0' => 2.00, 'realizer 1.0' => 2.00,
'realizer 2.0' => 2.22, 'realizer 2.0' => 2.22,
'ReasonML' => 2.50, 'ReasonML' => 2.50,
skipping to change at line 9629 skipping to change at line 10086
'SparForte' => 3.80, 'SparForte' => 3.80,
'speakeasy' => 2.22, 'speakeasy' => 2.22,
'spinnaker ppl' => 2.22, 'spinnaker ppl' => 2.22,
'splus' => 2.50, 'splus' => 2.50,
'spreadsheet default' => 13.33, 'spreadsheet default' => 13.33,
'sps' => 0.25, 'sps' => 0.25,
'spss' => 2.50, 'spss' => 2.50,
'Specman e' => 2.00, 'Specman e' => 2.00,
'SQL' => 2.29, 'SQL' => 2.29,
'sqlwindows' => 6.67, 'sqlwindows' => 6.67,
'Squirrel' => 2.50,
'statistical default' => 2.50, 'statistical default' => 2.50,
'Standard ML' => 3.00, 'Standard ML' => 3.00,
'Stata' => 3.00, 'Stata' => 3.00,
'strategem' => 2.22, 'strategem' => 2.22,
'stress' => 1.13, 'stress' => 1.13,
'strongly typed default' => 0.88, 'strongly typed default' => 0.88,
'style' => 1.74, 'style' => 1.74,
'Stylus' => 1.48, 'Stylus' => 1.48,
'SugarSS' => 2.50,
'superbase 1.3' => 2.22, 'superbase 1.3' => 2.22,
'surpass' => 13.33, 'surpass' => 13.33,
'Svelte' => 2.00,
'SVG' => 1.00, 'SVG' => 1.00,
'Swift' => 2.50, 'Swift' => 2.50,
'SWIG' => 2.50, 'SWIG' => 2.50,
'sybase' => 2.00, 'sybase' => 2.00,
'symantec c++' => 2.76, 'symantec c++' => 2.76,
'symbolang' => 1.25, 'symbolang' => 1.25,
'synchroworks' => 4.44, 'synchroworks' => 4.44,
'synon/2e' => 4.21, 'synon/2e' => 4.21,
'systemw' => 2.22, 'systemw' => 2.22,
'tandem access language' => 0.88, 'tandem access language' => 0.88,
skipping to change at line 9671 skipping to change at line 10131
'transform' => 5.33, 'transform' => 5.33,
'translisp plus' => 1.43, 'translisp plus' => 1.43,
'treet' => 1.25, 'treet' => 1.25,
'treetran' => 1.25, 'treetran' => 1.25,
'trs80 basic' => 0.63, 'trs80 basic' => 0.63,
'true basic' => 1.25, 'true basic' => 1.25,
'turing' => 1.00, 'turing' => 1.00,
'tutor' => 1.51, 'tutor' => 1.51,
'twaice' => 1.63, 'twaice' => 1.63,
'Twig' => 2.00, 'Twig' => 2.00,
'TNSDL' => 2.00,
'TTCN' => 2.00, 'TTCN' => 2.00,
'TITAN Project File Information' => 1.90, 'TITAN Project File Information' => 1.90,
'TypeScript' => 2.00, 'TypeScript' => 2.00,
'ucsd pascal' => 0.88, 'ucsd pascal' => 0.88,
'ufo/ims' => 2.22, 'ufo/ims' => 2.22,
'uhelp' => 2.50, 'uhelp' => 2.50,
'uniface' => 5.00, 'uniface' => 5.00,
'Unity-Prefab' => 2.50, 'Unity-Prefab' => 2.50,
'Vala' => 1.50, 'Vala' => 1.50,
'Vala Header' => 1.40, 'Vala Header' => 1.40,
skipping to change at line 9768 skipping to change at line 10229
'RapydScript' => 4.20, 'RapydScript' => 4.20,
'Starlark' => 4.20, 'Starlark' => 4.20,
'Cython' => 3.80, 'Cython' => 3.80,
'Ruby' => 4.20, 'Ruby' => 4.20,
'Ruby HTML' => 4.00, 'Ruby HTML' => 4.00,
'sed' => 4.00, 'sed' => 4.00,
'Lua' => 4.00, 'Lua' => 4.00,
'OpenCL' => 1.50, 'OpenCL' => 1.50,
'Xtend' => 2.00, 'Xtend' => 2.00,
# aggregates; value is meaningless # aggregates; value is meaningless
'C#/Smalltalk' => 1.00, 'C#/Smalltalk' => 1.00,
'D/dtrace' => 1.00, 'D/dtrace' => 1.00,
'F#/Forth' => 1.00, 'F#/Forth' => 1.00,
'Fortran 77/Forth' => 1.00, 'Fortran 77/Forth' => 1.00,
'Lisp/Julia' => 1.00, 'Lisp/Julia' => 1.00,
'Lisp/OpenCL' => 1.00, 'Lisp/OpenCL' => 1.00,
'PHP/Pascal' => 1.00, 'PHP/Pascal' => 1.00,
'Pascal/Puppet' => 1.00, 'Pascal/Puppet' => 1.00,
'Perl/Prolog' => 1.00, 'Perl/Prolog' => 1.00,
'Verilog-SystemVerilog/Coq' => 1.00, 'Raku/Prolog' => 1.00,
'MATLAB/Mathematica/Objective C/MUMPS/Mercury' => 1.00, 'Verilog-SystemVerilog/Coq' => 1.00,
'IDL/Qt Project/Prolog/ProGuard' => 1.00, 'MATLAB/Mathematica/Objective C/MUMPS/Mercury' => 1.00,
'IDL/Qt Project/Prolog/ProGuard' => 1.00,
); );
# 1}}} # 1}}}
%{$rh_Known_Binary_Archives} = ( # {{{1 %{$rh_Known_Binary_Archives} = ( # {{{1
'.tar' => 1 , '.tar' => 1 ,
'.tar.Z' => 1 , '.tar.Z' => 1 ,
'.tar.gz' => 1 , '.tar.gz' => 1 ,
'.tar.bz2' => 1 , '.tar.bz2' => 1 ,
'.zip' => 1 , '.zip' => 1 ,
'.Zip' => 1 , '.Zip' => 1 ,
'.ZIP' => 1 , '.ZIP' => 1 ,
skipping to change at line 12382 skipping to change at line 12844
my ($filename , # in my ($filename , # in
$rah_diff_L , # in see routine array_diff() for explanation $rah_diff_L , # in see routine array_diff() for explanation
$rah_diff_R , # in see routine array_diff() for explanation $rah_diff_R , # in see routine array_diff() for explanation
$rh_blank , # in location and counts of blank lines $rh_blank , # in location and counts of blank lines
) = @_; ) = @_;
print "-> write_comments_to_html($filename)\n" if $opt_v > 2; print "-> write_comments_to_html($filename)\n" if $opt_v > 2;
my $file = $filename . ".html"; my $file = $filename . ".html";
my $approx_line_count = scalar @{$rah_diff_L}; my $approx_line_count = scalar @{$rah_diff_L};
$approx_line_count = 1 unless $approx_line_count;
my $n_digits = 1 + int(log($approx_line_count)/2.30258509299405); # log_10 my $n_digits = 1 + int(log($approx_line_count)/2.30258509299405); # log_10
my $html_out = html_header($filename); my $html_out = html_header($filename);
my $comment_line_number = 0; my $comment_line_number = 0;
for (my $i = 0; $i < scalar @{$rah_diff_R}; $i++) { for (my $i = 0; $i < scalar @{$rah_diff_R}; $i++) {
if (defined $rh_blank->{$i}) { if (defined $rh_blank->{$i}) {
foreach (1..$rh_blank->{$i}) { foreach (1..$rh_blank->{$i}) {
$html_out .= "<!-- blank -->\n"; $html_out .= "<!-- blank -->\n";
} }
skipping to change at line 12556 skipping to change at line 13019
my @chars_R = split '', $line_R; my @chars_R = split '', $line_R;
$rah_diff_L->[$n_sdiff]{desc} = "modified"; $rah_diff_L->[$n_sdiff]{desc} = "modified";
$rah_diff_R->[$n_sdiff]{desc} = "modified"; $rah_diff_R->[$n_sdiff]{desc} = "modified";
$rah_diff_L->[$n_sdiff]{lnum} = $n_L; $rah_diff_L->[$n_sdiff]{lnum} = $n_L;
$rah_diff_R->[$n_sdiff]{lnum} = $n_R; $rah_diff_R->[$n_sdiff]{lnum} = $n_R;
} elsif ($flag eq '+') { # + = added } elsif ($flag eq '+') { # + = added
++$n_R; ++$n_R;
if ($COMMENT_MODE) { if ($COMMENT_MODE) {
# should never get here # should never get here, but may due to sdiff() bug,
@{$rah_diff_L} = (); # ref https://rt.cpan.org/Public/Bug/Display.html?id=131629
@{$rah_diff_R} = (); # Rather than failing, ignore and continue. A possible
push @{$raa_Errors}, # consequence is counts may be inconsistent.
[ $Error_Codes{'Diff error (quoted comments?)'}, $file ]; ##### @{$rah_diff_L} = ();
##### @{$rah_diff_R} = ();
##### push @{$raa_Errors},
##### [ $Error_Codes{'Diff error (quoted comments?)'}, $file ];
if ($opt_v) { if ($opt_v) {
warn "array_diff: diff failure (diff says the\n"; warn "array_diff: diff failure (diff says the\n";
warn "comment-free file has added lines).\n"; warn "comment-free file has added lines).\n";
warn "$n_sdiff $line_L\n"; warn "$n_sdiff $line_L\n";
} }
last;
} }
$rah_diff_L->[$n_sdiff]{type} = "nonexist"; #### $rah_diff_L->[$n_sdiff]{type} = "nonexist";
$rah_diff_L->[$n_sdiff]{type} = "comment";
$rah_diff_L->[$n_sdiff]{desc} = "removed"; $rah_diff_L->[$n_sdiff]{desc} = "removed";
$rah_diff_R->[$n_sdiff]{desc} = "added"; $rah_diff_R->[$n_sdiff]{desc} = "added";
$rah_diff_R->[$n_sdiff]{lnum} = $n_R; $rah_diff_R->[$n_sdiff]{lnum} = $n_R;
} elsif ($flag eq '-') { # - = removed } elsif ($flag eq '-') { # - = removed
++$n_L; ++$n_L;
if ($COMMENT_MODE) { if ($COMMENT_MODE) {
# line must be comment because blanks already gone # line must be comment because blanks already gone
$rah_diff_L->[$n_sdiff]{type} = "comment"; $rah_diff_L->[$n_sdiff]{type} = "comment";
} }
$rah_diff_R->[$n_sdiff]{type} = "nonexist"; $rah_diff_R->[$n_sdiff]{type} = "nonexist";
skipping to change at line 13194 skipping to change at line 13660
die "Unable to expand $archive_file because external\n", die "Unable to expand $archive_file because external\n",
"utility '$missing' is not available.\n", "utility '$missing' is not available.\n",
"Another possibility is to use the --extract-with option.\n"; "Another possibility is to use the --extract-with option.\n";
} else { } else {
return $extract_cmd; return $extract_cmd;
} }
} }
# 1}}} # 1}}}
sub read_list_file { # {{{1 sub read_list_file { # {{{1
my ($file, ) = @_; my ($file, ) = @_;
# reads filenames from a STDIN pipe if $file == "-"
print "-> read_list_file($file)\n" if $opt_v > 2; print "-> read_list_file($file)\n" if $opt_v > 2;
my $IN = new IO::File $file, "r"; my $IN;
if ($file eq "-") {
open($IN, $file);
} else {
$IN = new IO::File $file, "r";
}
if (!defined $IN) { if (!defined $IN) {
warn "Unable to read $file; ignoring.\n"; warn "Unable to read $file; ignoring.\n";
return (); return ();
} }
my @entry = (); my @entry = ();
while (<$IN>) { while (<$IN>) {
next if /^\s*$/ or /^\s*#/; # skip empty or commented lines next if /^\s*$/ or /^\s*#/; # skip empty or commented lines
s/\cM$//; # DOS to Unix s/\cM$//; # DOS to Unix
chomp; chomp;
push @entry, $_; push @entry, $_;
skipping to change at line 13658 skipping to change at line 14130
$F_norm =~ s{\\}{/}g; # Windows directory separators to Unix $F_norm =~ s{\\}{/}g; # Windows directory separators to Unix
$F_norm =~ s{^\./}{}g; # remove leading ./ $F_norm =~ s{^\./}{}g; # remove leading ./
if (($F_norm !~ m{^/}) and ($F_norm !~ m{^\w:/})) { if (($F_norm !~ m{^/}) and ($F_norm !~ m{^\w:/})) {
# looks like a relative path; prefix with cwd # looks like a relative path; prefix with cwd
$F_norm = lc "$cwd/$F_norm"; $F_norm = lc "$cwd/$F_norm";
} }
} else { } else {
$F_norm =~ s{^\./}{}g; # remove leading ./ $F_norm =~ s{^\./}{}g; # remove leading ./
if ($F_norm !~ m{^/}) { if ($F_norm !~ m{^/}) {
# looks like a relative path; prefix with cwd # looks like a relative path; prefix with cwd
$F_norm = lc "$cwd/$F_norm"; $F_norm = "$cwd/$F_norm";
} }
} }
# Remove trailing / so it does not interfere with further regex code # Remove trailing / so it does not interfere with further regex code
# that does not expect it # that does not expect it
$F_norm =~ s{/+$}{}; $F_norm =~ s{/+$}{};
$normalized{ $F_norm } = $F; $normalized{ $F_norm } = $F;
} }
return %normalized; return %normalized;
} # 1}}} } # 1}}}
sub combine_diffs { # {{{1 sub combine_diffs { # {{{1
skipping to change at line 13767 skipping to change at line 14239
} }
} # 1}}} } # 1}}}
sub really_is_D { # {{{1 sub really_is_D { # {{{1
# Ref bug 131, files ending with .d could be init.d scripts # Ref bug 131, files ending with .d could be init.d scripts
# instead of D language source files. # instead of D language source files.
my ($file , # in my ($file , # in
$rh_Err , # in hash of error codes $rh_Err , # in hash of error codes
$raa_errors , # out $raa_errors , # out
) = @_; ) = @_;
print "-> really_is_D($file)\n" if $opt_v > 2; print "-> really_is_D($file)\n" if $opt_v > 2;
my $possible_script = peek_at_first_line($file, $rh_Err, $raa_errors); my ($possible_script, $L) = peek_at_first_line($file, $rh_Err, $raa_errors);
print "<- really_is_D($file)\n" if $opt_v > 2; print "<- really_is_D($file)\n" if $opt_v > 2;
return $possible_script; # null string if D, otherwise a language return $possible_script; # null string if D, otherwise a language
} # 1}}} } # 1}}}
sub no_autogen_files { # {{{1 sub no_autogen_files { # {{{1
# ref https://github.com/AlDanial/cloc/issues/151 # ref https://github.com/AlDanial/cloc/issues/151
my ($print,) = @_; my ($print,) = @_;
print "-> no_autogen($print)\n" if $opt_v > 2; print "-> no_autogen($print)\n" if $opt_v > 2;
# These sometimes created manually? # These sometimes created manually?
# acinclude.m4 # acinclude.m4
# configure.ac # configure.ac
# Makefile.am # Makefile.am
my @files = qw ( my @files = qw (
aclocal.m4 aclocal.m4
announce-gen announce-gen
autogen.sh autogen.sh
bootstrap bootstrap
compile compile
skipping to change at line 13907 skipping to change at line 14379
$rs_skip_win_hidden , $rs_skip_win_hidden ,
$rs_read_binary_files , $rs_read_binary_files ,
$rs_sql , $rs_sql ,
$rs_sql_project , $rs_sql_project ,
$rs_sql_append , $rs_sql_append ,
$rs_sql_style , $rs_sql_style ,
$rs_inline , $rs_inline ,
$rs_exclude_ext , $rs_exclude_ext ,
$rs_ignore_whitespace , $rs_ignore_whitespace ,
$rs_ignore_case , $rs_ignore_case ,
$rs_ignore_case_ext ,
$rs_follow_links , $rs_follow_links ,
$rs_autoconf , $rs_autoconf ,
$rs_sum_one , $rs_sum_one ,
$rs_by_percent , $rs_by_percent ,
$rs_stdin_name , $rs_stdin_name ,
$rs_force_on_windows , $rs_force_on_windows ,
$rs_force_on_unix , $rs_force_on_unix ,
$rs_show_os , $rs_show_os ,
$rs_skip_archive , $rs_skip_archive ,
$rs_max_file_size , $rs_max_file_size ,
skipping to change at line 14006 skipping to change at line 14479
} elsif (!defined ${$rs_help} and /help/) { ${$rs_help} = 1; } elsif (!defined ${$rs_help} and /help/) { ${$rs_help} = 1;
} elsif (!defined ${$rs_skip_win_hidden} and /skip_win_hidden|skip-w in-hidden/) { ${$rs_skip_win_hidden} = 1; } elsif (!defined ${$rs_skip_win_hidden} and /skip_win_hidden|skip-w in-hidden/) { ${$rs_skip_win_hidden} = 1;
} elsif (!defined ${$rs_read_binary_files} and /read_binary_files|read -binary-files/) { ${$rs_read_binary_files} = 1; } elsif (!defined ${$rs_read_binary_files} and /read_binary_files|read -binary-files/) { ${$rs_read_binary_files} = 1;
} elsif (!defined ${$rs_sql} and /sql(=|\s+)(.*?)$/) { ${$rs_sql} = $2; } elsif (!defined ${$rs_sql} and /sql(=|\s+)(.*?)$/) { ${$rs_sql} = $2;
} elsif (!defined ${$rs_sql_project} and /sql_project|sql-projec t(=|\s+)(.*?)$/) { ${$rs_sql_project} = $2; } elsif (!defined ${$rs_sql_project} and /sql_project|sql-projec t(=|\s+)(.*?)$/) { ${$rs_sql_project} = $2;
} elsif (!defined ${$rs_sql_append} and /sql_append|sql-append/ ) { ${$rs_sql_append} = 1; } elsif (!defined ${$rs_sql_append} and /sql_append|sql-append/ ) { ${$rs_sql_append} = 1;
} elsif (!defined ${$rs_sql_style} and /sql_style|sql-style(=| \s+)(.*?)$/) { ${$rs_sql_style} = $2; } elsif (!defined ${$rs_sql_style} and /sql_style|sql-style(=| \s+)(.*?)$/) { ${$rs_sql_style} = $2;
} elsif (!defined ${$rs_inline} and /inline/) { ${$rs_inline} = 1; } elsif (!defined ${$rs_inline} and /inline/) { ${$rs_inline} = 1;
} elsif (!defined ${$rs_exclude_ext} and /exclude_ext|exclude-ex t(=|\s+)(.*?)$/) { ${$rs_exclude_ext} = $2; } elsif (!defined ${$rs_exclude_ext} and /exclude_ext|exclude-ex t(=|\s+)(.*?)$/) { ${$rs_exclude_ext} = $2;
} elsif (!defined ${$rs_ignore_whitespace} and /ignore_whitespace|igno re-whitespace/) { ${$rs_ignore_whitespace} = 1; } elsif (!defined ${$rs_ignore_whitespace} and /ignore_whitespace|igno re-whitespace/) { ${$rs_ignore_whitespace} = 1;
} elsif (!defined ${$rs_ignore_case_ext} and /ignore_case_ext|ignore -case-ext/) { ${$rs_ignore_case_ext} = 1;
} elsif (!defined ${$rs_ignore_case} and /ignore_case|ignore-cas e/) { ${$rs_ignore_case} = 1; } elsif (!defined ${$rs_ignore_case} and /ignore_case|ignore-cas e/) { ${$rs_ignore_case} = 1;
} elsif (!defined ${$rs_follow_links} and /follow_links|follow-li nks/) { ${$rs_follow_links} = 1; } elsif (!defined ${$rs_follow_links} and /follow_links|follow-li nks/) { ${$rs_follow_links} = 1;
} elsif (!defined ${$rs_autoconf} and /autoconf/) { ${$rs_autoconf} = 1; } elsif (!defined ${$rs_autoconf} and /autoconf/) { ${$rs_autoconf} = 1;
} elsif (!defined ${$rs_sum_one} and /sum_one|sum-one/) { ${$rs_sum_one} = 1; } elsif (!defined ${$rs_sum_one} and /sum_one|sum-one/) { ${$rs_sum_one} = 1;
} elsif (!defined ${$rs_by_percent} and /by_percent|by-percent( =|\s+)(.*?)$/) { ${$rs_by_percent} = $2; } elsif (!defined ${$rs_by_percent} and /by_percent|by-percent( =|\s+)(.*?)$/) { ${$rs_by_percent} = $2;
} elsif (!defined ${$rs_stdin_name} and /stdin_name|stdin-name( =|\s+)(.*?)$/) { ${$rs_stdin_name} = $2; } elsif (!defined ${$rs_stdin_name} and /stdin_name|stdin-name( =|\s+)(.*?)$/) { ${$rs_stdin_name} = $2;
} elsif (!defined ${$rs_force_on_windows} and /windows/) { ${$rs_force_on_windows} = 1; } elsif (!defined ${$rs_force_on_windows} and /windows/) { ${$rs_force_on_windows} = 1;
} elsif (!defined ${$rs_force_on_unix} and /unix/) { ${$rs_force_on_unix} = 1; } elsif (!defined ${$rs_force_on_unix} and /unix/) { ${$rs_force_on_unix} = 1;
} elsif (!defined ${$rs_show_os} and /show_os|show-os/) { ${$rs_show_os} = 1; } elsif (!defined ${$rs_show_os} and /show_os|show-os/) { ${$rs_show_os} = 1;
} elsif (!defined ${$rs_skip_archive} and /skip_archive|skip-arch ive(=|\s+)(.*?)$/) { ${$rs_skip_archive} = $2; } elsif (!defined ${$rs_skip_archive} and /skip_archive|skip-arch ive(=|\s+)(.*?)$/) { ${$rs_skip_archive} = $2;
 End of changes. 164 change blocks. 
211 lines changed or deleted 693 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)