| # |
| # Copyright (C) 2017 and later: Unicode, Inc. and others. |
| # License & terms of use: http://www.unicode.org/copyright.html |
| # |
| # *********************************************************************** |
| # * COPYRIGHT: |
| # * Copyright (c) 2011, International Business Machines Corporation |
| # * and others. All Rights Reserved. |
| # *********************************************************************** |
| # |
| # Common functionality between cpysearch.pl and cpyscan.pl |
| # |
| |
| package Cpy; |
| use strict; |
| use warnings; |
| use base 'Exporter'; |
| |
| our @EXPORT = qw(any glob_to_regex should_ignore); |
| |
| # any(CODE, LIST) |
| # Evaluate CODE for each element of LIST till CODE($_) returns 1. Return 0 if |
| # not found. |
| sub any(&@) { |
| my $code = shift; |
| local $_; |
| &$code && return 1 for @_; |
| 0; |
| } |
| |
| # Perl doesn't have fnmatch. Closest thing is File::FnMatch but that's |
| # UNIX-only (see its caveats). So, as a workaround, convert globs to regular |
| # expressions. Translated from Python's fnmatch module. |
| sub glob_to_regex($) { |
| my ($glob, $i, $len, $regex); |
| $glob = shift; |
| $i = 0; |
| $len = length($glob); |
| $regex = ""; |
| |
| # charat(STR, IDX) |
| # Return the character in the argument at the given index. |
| my $charat = sub($$) { return substr(shift, shift, 1) }; |
| |
| while ($i < $len) { |
| my ($c, $out); |
| $c = &$charat($glob, $i++); |
| if ($c eq '*') { $out = '.*' } |
| elsif ($c eq '?') { $out = '.' } |
| elsif ($c eq '[') { # glob classes |
| my $j = $i; |
| |
| # Get the closing index of the class. ] appearing here is part |
| # of the class. |
| if ($j < $len && &$charat($glob, $j) eq '!') { $j++ } |
| if ($j < $len && &$charat($glob, $j) eq ']') { $j++ } |
| while ($j < $len && &$charat($glob, $j) ne ']') { $j++ } |
| |
| # Didn't find closing brace. Use literal [ |
| if ($j >= $len) { $out = "\\[" } |
| |
| else { |
| # The complete class contents (except the braces) |
| my $s = substr($regex, $i, $j - $i); |
| $s =~ s/\\/\\\\/g; |
| $i = $j + 1; # change position to outside class |
| |
| # Negation |
| if (&$charat($s, 0) eq '!') { $s = '^'.substr($s, 1); } |
| # Literal ^ |
| elsif (&$charat($s, 0) eq '^') { $s = '\\'.$s; } |
| |
| $out = "[$s]"; |
| } |
| } |
| else { $out = quotemeta($c) } |
| $regex .= $out; |
| } |
| return $regex; |
| } |
| |
| # Load cpyskip.txt contents. |
| # Try local .cpyskip.txt |
| # no support for HTTP fetch. |
| our $cpyskip_file = ".cpyskip.txt"; |
| our @cpyskip_lines; |
| if (open(our $cpyskip_fh, "<", $cpyskip_file)) { |
| @cpyskip_lines = <$cpyskip_fh>; |
| close $cpyskip_fh; |
| # print "Using local cpyskip.txt\n"; |
| } else { |
| die "Could not open $cpyskip_file"; |
| } |
| our @ignore_globs = map { chomp; glob_to_regex($_) } |
| grep { /^\s*[^#\s]+/ } |
| @cpyskip_lines; |
| |
| #for my $rgx (@ignore_globs) {print $rgx . "\n"} |
| #exit(0); |
| |
| # list of file extensions to ignore |
| our @ignore_extensions = qw(svn dll ilk idb pdb dsp dsw opt ncb vcproj sln suo |
| cvsignore cnv res icu exe obj bin exp lib out plg jar spp stub policy ttf |
| TTF otf); |
| our $ignore_exts = join '|', |
| map { "\\.$_" } |
| @ignore_extensions; |
| |
| # ignore regex |
| our $ignore_regex = "data/out/build|CVS|\\~|\\#|Debug|Release|positions|unidata|sources\.txt|$ignore_exts"; |
| |
| # Check if this file should be ignored. |
| sub should_ignore($) { |
| my $filename = shift; |
| return 1 if $filename eq $cpyskip_file; |
| return 1 if $filename =~ /$ignore_regex/; |
| for my $r (@ignore_globs) { return 1 if $filename =~ /$r/ } |
| 0; |
| } |
| |
| 1; |