texlive[65257] trunk: bibcop (12dec22)

commits+karl at tug.org commits+karl at tug.org
Mon Dec 12 22:07:18 CET 2022


Revision: 65257
          http://tug.org/svn/texlive?view=revision&revision=65257
Author:   karl
Date:     2022-12-12 22:07:17 +0100 (Mon, 12 Dec 2022)
Log Message:
-----------
bibcop (12dec22)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/Makefile.am
    trunk/Build/source/texk/texlive/linked_scripts/Makefile.in
    trunk/Build/source/texk/texlive/linked_scripts/scripts.lst
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/libexec/ctan2tds
    trunk/Master/tlpkg/tlpsrc/collection-bibtexextra.tlpsrc

Added Paths:
-----------
    trunk/Build/source/texk/texlive/linked_scripts/bibcop/
    trunk/Build/source/texk/texlive/linked_scripts/bibcop/bibcop.pl
    trunk/Master/bin/aarch64-linux/bibcop
    trunk/Master/bin/amd64-freebsd/bibcop
    trunk/Master/bin/amd64-netbsd/bibcop
    trunk/Master/bin/armhf-linux/bibcop
    trunk/Master/bin/i386-cygwin/bibcop
    trunk/Master/bin/i386-freebsd/bibcop
    trunk/Master/bin/i386-linux/bibcop
    trunk/Master/bin/i386-netbsd/bibcop
    trunk/Master/bin/i386-solaris/bibcop
    trunk/Master/bin/universal-darwin/bibcop
    trunk/Master/bin/win32/bibcop.exe
    trunk/Master/bin/x86_64-cygwin/bibcop
    trunk/Master/bin/x86_64-darwinlegacy/bibcop
    trunk/Master/bin/x86_64-linux/bibcop
    trunk/Master/bin/x86_64-linuxmusl/bibcop
    trunk/Master/bin/x86_64-solaris/bibcop
    trunk/Master/texmf-dist/doc/latex/bibcop/
    trunk/Master/texmf-dist/doc/latex/bibcop/DEPENDS.txt
    trunk/Master/texmf-dist/doc/latex/bibcop/LICENSE.txt
    trunk/Master/texmf-dist/doc/latex/bibcop/README.md
    trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf
    trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf
    trunk/Master/texmf-dist/scripts/bibcop/
    trunk/Master/texmf-dist/scripts/bibcop/bibcop.pl
    trunk/Master/texmf-dist/source/latex/bibcop/
    trunk/Master/texmf-dist/source/latex/bibcop/bibcop.dtx
    trunk/Master/texmf-dist/source/latex/bibcop/bibcop.ins
    trunk/Master/texmf-dist/tex/latex/bibcop/
    trunk/Master/texmf-dist/tex/latex/bibcop/bibcop.sty
    trunk/Master/tlpkg/tlpsrc/bibcop.tlpsrc

Modified: trunk/Build/source/texk/texlive/linked_scripts/Makefile.am
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/Makefile.am	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Build/source/texk/texlive/linked_scripts/Makefile.am	2022-12-12 21:07:17 UTC (rev 65257)
@@ -111,6 +111,7 @@
 	authorindex/authorindex \
 	bib2gls/bib2gls.sh \
 	bib2gls/convertgls2bib.sh \
+	bibcop/bibcop.pl \
 	bundledoc/arlatex \
 	bundledoc/bundledoc \
 	cachepic/cachepic.tlu \

Modified: trunk/Build/source/texk/texlive/linked_scripts/Makefile.in
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/Makefile.in	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Build/source/texk/texlive/linked_scripts/Makefile.in	2022-12-12 21:07:17 UTC (rev 65257)
@@ -325,6 +325,7 @@
 	authorindex/authorindex \
 	bib2gls/bib2gls.sh \
 	bib2gls/convertgls2bib.sh \
+	bibcop/bibcop.pl \
 	bundledoc/arlatex \
 	bundledoc/bundledoc \
 	cachepic/cachepic.tlu \

Added: trunk/Build/source/texk/texlive/linked_scripts/bibcop/bibcop.pl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/bibcop/bibcop.pl	                        (rev 0)
+++ trunk/Build/source/texk/texlive/linked_scripts/bibcop/bibcop.pl	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,492 @@
+#!/usr/bin/perl
+# (The MIT License)
+#
+# Copyright (c) 2022 Yegor Bugayenko
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the 'Software'), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+package bibcop;
+
+use warnings;
+use strict;
+
+# If you want to add an extra check, just create a new procedure
+# named as "check_*".
+
+# Only these keys are allowed and only these types of items.
+my %blessed = (
+  'article' => ['doi', 'year', 'title', 'author', 'journal', 'volume', 'number', 'publisher?'],
+  'inproceedings' => ['doi', 'booktitle', 'title', 'author', 'year', 'pages?', 'organization?', 'volume?'],
+  'book' => ['doi', 'title', 'author', 'year', 'publisher'],
+  'misc' => ['title', 'author', 'year', 'eprint?', 'archiveprefix?', 'primaryclass?', 'publisher?', 'organization?', 'doi?'],
+);
+
+# Check the presence of mandatory keys.
+sub check_mandatory_keys {
+  my (%item) = @_;
+  my $type = $item{':type'};
+  my $mandatory = $blessed{$type};
+  foreach my $key (@$mandatory) {
+    if ($key =~ /^.*\?$/) {
+      next;
+    }
+    if (not(exists $item{$key})) {
+      my $listed = listed_keys(%item);
+      return "A mandatory '$key' key for '\@$type' is missing among $listed"
+    }
+  }
+  if (exists $blessed{$type}) {
+    my %required = map { $_ => 1 } @$mandatory;
+    foreach my $key (keys %item) {
+      if ($key =~ /^:/) {
+        next;
+      }
+      if (not(exists $required{$key}) && not(exists $required{$key . '?'})) {
+        return "The '$key' key is not suitable for '$type', use only these: (@$mandatory)"
+      }
+    }
+  }
+}
+
+# Check that all major words are capitalized.
+sub check_capitalization {
+  my (%item) = @_;
+  my %keys = map { $_ => 1 } qw/title booktitle journal/;
+  my %minors = map { $_ => 1 } qw/in of at to by the a an and or as if up via yet nor but off on for into/;
+  foreach my $key (keys %item) {
+    if (not exists $keys{$key}) {
+      next;
+    }
+    my $value = $item{$key};
+    my @words = only_words($value);
+    my $pos = 0;
+    foreach my $word (@words) {
+      if (not $word =~ /^[A-Za-z]/) {
+        next;
+      }
+      $pos = $pos + 1;
+      if (exists $minors{$word}) {
+        next;
+      }
+      if (exists $minors{lc($word)} and $pos gt 1) {
+        return "All minor words in the '$key' must be lower-cased, while '$word' (no.$pos) is not"
+      }
+      if ($word =~ /^[a-z].*/) {
+        return "All major words in the '$key' must be capitalized, while '$word' (no.$pos) is not"
+      }
+    }
+  }
+}
+
+# Check that the 'author' is formatted correctly.
+sub check_author {
+  my (%item) = @_;
+  if (exists $item{'author'} and not $item{'author'} =~ /^\{.+\}$/) {
+    my $author = clean_tex($item{'author'});
+    if (not $author =~ /^[A-Z][^ ]+(,( [A-Z][^ ]+)+)?( and [A-Z][^ ]+(,( [A-Z][^ ]+)+)?)*( and others)?$/) {
+      return "The format of the 'author' is wrong, use something like 'Knuth, Donald E. and Duane, Bibby'"
+    }
+    if ($author =~ /.*[A-Z]([ ,]|$).*/) {
+      return "A shortened name must have a tailing dot, as in 'Knuth, Donald E.'"
+    }
+  }
+}
+
+# Check that titles don't have shortened words with a tailing dot.
+sub check_shortenings {
+  my (%item) = @_;
+  my %keys = map { $_ => 1 } qw/title booktitle journal/;
+  foreach my $key (keys %item) {
+    if (not exists $keys{$key}) {
+      next;
+    }
+    my $value = $item{$key};
+    my @words = only_words($value);
+    foreach my $word (@words) {
+      if (not $word =~ /^[A-Za-z]/) {
+        next;
+      }
+      if ($word =~ /^.*\.$/) {
+        return "Do not shorten the words in the '$key', such as '$word'"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'title' and 'booktitle.'
+sub check_titles {
+  my (%item) = @_;
+  my @keys = qw/title booktitle/;
+  foreach my $key (@keys) {
+    if (not exists($item{$key})) {
+      next;
+    }
+    my $title = $item{$key};
+    if (not $title =~ /^\{.+\}$/) {
+      return "The '$key' must be wrapped in double curled brackets"
+    }
+  }
+}
+
+# Check that no values have tailing dots.
+# Check that there are no spaces before commans.
+sub check_typography {
+  my (%item) = @_;
+  foreach my $key (keys %item) {
+    if ($key =~ /^:.*/) {
+      next;
+    }
+    my $value = $item{$key};
+    if ($value =~ /.*\.$/ and $key ne 'author') {
+      return "The '$key' must not end with a dot"
+    }
+    if ($value =~ /.* ,.*/) {
+      return "In the '$key', do not put a space before the comma"
+    }
+  }
+}
+
+# Check the year is not mentioned in titles.
+sub check_year_in_titles {
+  my (%item) = @_;
+  my @keys = qw/title booktitle journal/;
+  foreach my $key (@keys) {
+    if (not exists($item{$key})) {
+      next;
+    }
+    my @words = only_words($item{$key});
+    foreach my $word (@words) {
+      if ($word =~ /^[1-9][0-9]{3}$/) {
+        return "The '$key' must not contain the year $word, it is enough to have the 'year' key"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'booktitle' in the 'inproceedings' item.
+sub check_booktile_of_inproceedings {
+  my (%item) = @_;
+  my $key = 'inproceedings';
+  if ($item{':type'} eq $key) {
+    if (exists $item{'booktitle'}) {
+      my @words = only_words($item{'booktitle'});
+      if (lc($words[0]) ne 'proceedings' or lc($words[1]) ne 'of' or lc($words[2]) ne 'the') {
+        return "The '$key' must start with 'Proceedings of the ...'"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'doi.'
+sub check_doi {
+  my (%item) = @_;
+  if (exists $item{'doi'}) {
+    my $doi = $item{'doi'};
+    if (not $item{'doi'} =~ /^[0-9a-zA-Z.]+\/[0-9a-zA-Z._\-]+$/) {
+      return "The format of the 'doi' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'year.'
+sub check_year {
+  my (%item) = @_;
+  if (exists $item{'year'}) {
+    my $year = $item{'year'};
+    if (not $item{'year'} =~ /^[0-9]{3,4}$/) {
+      return "The format of the 'year' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'month.'
+sub check_month {
+  my (%item) = @_;
+  if (exists $item{'month'}) {
+    my $month = $item{'month'};
+    if (not $item{'month'} =~ /^[1-9]|10|11|12$/) {
+      return "The format of the 'month' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'volume.'
+sub check_volume {
+  my (%item) = @_;
+  if (exists $item{'volume'}) {
+    my $volume = $item{'volume'};
+    if (not $item{'volume'} =~ /^[1-9][0-9]*$/) {
+      return "The format of the 'volume' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'pages.'
+sub check_pages {
+  my (%item) = @_;
+  if (exists $item{'pages'}) {
+    my $pages = $item{'pages'};
+    if (not $item{'pages'} =~ /^[1-9][0-9]*--[1-9][0-9]*|[1-9][0-9]*$/) {
+      return "The format of the 'pages' is wrong"
+    }
+    my @parts = split(/--/, $pages);
+    if (@parts+0 eq 2) {
+      if ($parts[0] gt $parts[1]) {
+        return "The 'pages' are in the wrong order"
+      }
+    }
+  }
+}
+
+# Check one item.
+sub process_item {
+  my (%item) = @_;
+  my @checks;
+  foreach my $entry (keys %bibcop::) {
+    if ($entry =~ /^check_/) {
+      push(@checks, $entry);
+    }
+  }
+  my @sorted = sort @checks;
+  my @errors;
+  foreach my $check (@sorted) {
+    no strict 'refs';
+    my $err = $check->(%item);
+    if ($err ne '') {
+      push(@errors, $err);
+    }
+  }
+  return @errors;
+}
+
+# Parse the incoming .bib file and return an array
+# of hash-maps, where each one is a bibitem.
+sub bibitems {
+  my ($bib) = @_;
+  my @items;
+  my $s = 'top';
+  my %item;
+  my $acc = '';
+  my $key = '';
+  my $lineno = 0;
+  my $nest = 0;
+  my $escape = 0;
+  for my $pos (0..length($bib)-1) {
+    my $char = substr($bib, $pos, 1);
+    if ($char eq ' ') {
+      # ignore the white space
+    } elsif ($char eq "\n") {
+      # ignore the EOL
+      $lineno = $lineno + 1;
+    } elsif ($char eq '@' and $s eq 'top') {
+      %item = ();
+      $s = 'start';
+      $acc = '';
+    } elsif ($char =~ /[a-z]/ and $s eq 'start') {
+      # @article
+    } elsif ($char eq '{' and $s eq 'start') {
+      $item{':type'} = substr($acc, 1);
+      $acc = '';
+      $s = 'body';
+    } elsif ($char =~ /[a-zA-Z]/ and $s eq 'body') {
+      $acc = '';
+      $s = 'key';
+    } elsif ($char =~ /[a-zA-Z0-9_]/ and $s eq 'key') {
+      # reading the key
+    } elsif ($char =~ /[a-zA-Z0-9]/ and $s eq 'value') {
+      # reading the value without quotes or brackets
+    } elsif ($char eq ',' and $s eq 'key') {
+      $item{':name'} = $acc;
+      $s = 'body';
+    } elsif ($char eq '=' and $s eq 'key') {
+      $key = $acc;
+      $s = 'value';
+      $acc = '';
+    } elsif ($char eq ',' and $s eq 'value') {
+      if (not exists $item{lc($key)}) {
+        my $tex = substr($acc, 1);
+        $tex =~ s/\s//g;
+        $item{lc($key)} = $tex;
+      }
+      $s = 'body';
+    } elsif ($char eq '}' and $s eq 'body') {
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '}' and $s eq 'value') {
+      if (not exists $item{lc($key)}) {
+        my $tex = substr($acc, 1);
+        $tex =~ s/\s//g;
+        $item{lc($key)} = $tex;
+      }
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '}' and $s eq 'key') {
+      $item{':name'} = $acc;
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '"' and $s eq 'value') {
+      $s = 'quote';
+      $acc = '';
+    } elsif ($char eq '"' and $s eq 'quote') {
+      $item{lc($key)} = substr($acc, 1);
+      $s = 'value';
+    } elsif ($s eq 'quote') {
+      # nothing
+    } elsif ($char eq '{' and $s eq 'value') {
+      $nest = 1;
+      $s = 'brackets';
+      $acc = '';
+    } elsif ($s eq 'brackets') {
+      if ($char eq '\\') {
+        $escape = 1;
+      } elsif ($char eq '{' and $escape ne 1) {
+        $nest = $nest + 1;
+      } elsif ($char eq '}' and $escape ne 1) {
+        $nest = $nest - 1;
+        if ($nest eq 0) {
+          $item{lc($key)} = substr($acc, 1);
+          $s = 'value';
+        }
+      }
+      $escape = 0;
+    } else {
+      print "\\PackageWarningNoLine{bibcop}{It is impossible to parse the .bib file, because I do not know what to do with '$char' at line #$lineno (s=$s)}\n";
+      last;
+    }
+    if ($char eq ' ' and not($s =~ /quote|brackets/)) {
+      next;
+    }
+    $acc = $acc . $char;
+  }
+  return @items;
+}
+
+# Takes the text and returns only list of words seen there.
+sub only_words {
+  my ($tex) = @_;
+  return split(/[ \-]/, clean_tex($tex));
+}
+
+# Take a TeX string and return a cleaner one, without redundant spaces, brackets, etc.
+sub clean_tex {
+  my ($tex) = @_;
+  $tex =~ s/\s+/ /g;
+  $tex =~ s/^\{+//g;
+  $tex =~ s/\}+$//g;
+  return $tex;
+}
+
+# Take a bibitem and print all its keys as a comma-separated string.
+sub listed_keys {
+  my (%item) = @_;
+  my @list;
+  foreach my $key (keys %item) {
+    if ($key =~ /^:.*/) {
+      next;
+    }
+    push(@list, $key);
+  }
+  my @sorted = sort @list;
+  return '(' . join(', ', @sorted) . ')';
+}
+
+my %args = map { $_ => 1 } @ARGV;
+if (@ARGV+0 eq 0 or exists $args{'--help'}) {
+  debug("Bibcop is a Style Checker of .bib Files\n" .
+    "Usage: bibcop [<options>] <.bib file path>\n" .
+    "  --version Print the current version of the tool and exit\n" .
+    "  --help    Print this help screen\n" .
+    "  --fix     Fix the errors and print a new version of the .bib file to the console\n" .
+    "  --latex   Report errors in LaTeX format using \\PackageWarningNoLine command");
+} elsif (exists $args{'--version'}) {
+  debug('0.0.2');
+} else {
+  my ($file) = grep { not($_ =~ /^--.*$/) } @ARGV;
+  open(my $fh, '<', $file);
+  my $bib; { local $/; $bib = <$fh>; }
+  my @items = bibitems($bib);
+  if (exists $args{'--fix'}) {
+    for my $i (0..(@items+0 - 1)) {
+      my %item = %{ $items[$i] };
+      my $type = $item{':type'};
+      if (not exists $blessed{$type}) {
+        error("I don't know what to do with \@$type type of bibitem");
+      }
+      my $keys = $blessed{$item{':type'}};
+      my %allowed = map { $_ => 1 } @$keys;
+      my @lines;
+      foreach my $key (keys %item) {
+        if ($key =~ /^:/) {
+          next;
+        }
+        if (not exists $allowed{$key} and not exists $allowed{$key . '?'}) {
+          next;
+        }
+        my $value = clean_tex($item{$key});
+        if ($key =~ /title|booktitle|journal/) {
+          $value = '{' . $value . '}';
+        }
+        push(@lines, "  $key = {$value},");
+      }
+      debug("\@$type\{$item{':name'},");
+      my @sorted = sort @lines;
+      foreach my $line (@sorted) {
+        debug($line);
+      }
+      debug("}\n");
+    }
+  } else {
+    debug((@items+0) . ' bibitems found in ' . $file);
+    for my $i (0..(@items+0 - 1)) {
+      my %item = %{ $items[$i] };
+      debug("Checking $item{':name'} (#$i)...");
+      foreach my $err (process_item(%item)) {
+        warning("$err, in the '$item{':name'}' bibitem");
+      }
+    }
+  }
+}
+
+# Print ERROR message to the console and die.
+sub error {
+  my ($txt) = @_;
+  print $txt . "\n";
+  exit 1;
+}
+
+# Print DEBUG message to the console.
+sub debug {
+  my ($txt) = @_;
+  if (exists $args{'--latex'}) {
+    print '% ';
+  }
+  print $txt . "\n";
+}
+
+# Print INFO message to the console.
+sub warning {
+  my ($txt) = @_;
+  if (exists $args{'--latex'}) {
+    print "\\PackageWarningNoLine{bibcop}{$txt}\n";
+  } else {
+    print $txt . "\n";
+  }
+}
+
+1;


Property changes on: trunk/Build/source/texk/texlive/linked_scripts/bibcop/bibcop.pl
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Build/source/texk/texlive/linked_scripts/scripts.lst
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/scripts.lst	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Build/source/texk/texlive/linked_scripts/scripts.lst	2022-12-12 21:07:17 UTC (rev 65257)
@@ -50,6 +50,7 @@
 authorindex/authorindex
 bib2gls/bib2gls.sh
 bib2gls/convertgls2bib.sh
+bibcop/bibcop.pl
 bundledoc/arlatex
 bundledoc/bundledoc
 cachepic/cachepic.tlu

Added: trunk/Master/bin/aarch64-linux/bibcop
===================================================================
--- trunk/Master/bin/aarch64-linux/bibcop	                        (rev 0)
+++ trunk/Master/bin/aarch64-linux/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/aarch64-linux/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/amd64-freebsd/bibcop
===================================================================
--- trunk/Master/bin/amd64-freebsd/bibcop	                        (rev 0)
+++ trunk/Master/bin/amd64-freebsd/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/amd64-freebsd/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/amd64-netbsd/bibcop
===================================================================
--- trunk/Master/bin/amd64-netbsd/bibcop	                        (rev 0)
+++ trunk/Master/bin/amd64-netbsd/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/amd64-netbsd/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/armhf-linux/bibcop
===================================================================
--- trunk/Master/bin/armhf-linux/bibcop	                        (rev 0)
+++ trunk/Master/bin/armhf-linux/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/armhf-linux/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/i386-cygwin/bibcop
===================================================================
--- trunk/Master/bin/i386-cygwin/bibcop	                        (rev 0)
+++ trunk/Master/bin/i386-cygwin/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/i386-cygwin/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/i386-freebsd/bibcop
===================================================================
--- trunk/Master/bin/i386-freebsd/bibcop	                        (rev 0)
+++ trunk/Master/bin/i386-freebsd/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/i386-freebsd/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/i386-linux/bibcop
===================================================================
--- trunk/Master/bin/i386-linux/bibcop	                        (rev 0)
+++ trunk/Master/bin/i386-linux/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/i386-linux/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/i386-netbsd/bibcop
===================================================================
--- trunk/Master/bin/i386-netbsd/bibcop	                        (rev 0)
+++ trunk/Master/bin/i386-netbsd/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/i386-netbsd/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/i386-solaris/bibcop
===================================================================
--- trunk/Master/bin/i386-solaris/bibcop	                        (rev 0)
+++ trunk/Master/bin/i386-solaris/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/i386-solaris/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/universal-darwin/bibcop
===================================================================
--- trunk/Master/bin/universal-darwin/bibcop	                        (rev 0)
+++ trunk/Master/bin/universal-darwin/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/universal-darwin/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/win32/bibcop.exe
===================================================================
(Binary files differ)

Index: trunk/Master/bin/win32/bibcop.exe
===================================================================
--- trunk/Master/bin/win32/bibcop.exe	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/bin/win32/bibcop.exe	2022-12-12 21:07:17 UTC (rev 65257)

Property changes on: trunk/Master/bin/win32/bibcop.exe
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Added: trunk/Master/bin/x86_64-cygwin/bibcop
===================================================================
--- trunk/Master/bin/x86_64-cygwin/bibcop	                        (rev 0)
+++ trunk/Master/bin/x86_64-cygwin/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/x86_64-cygwin/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/x86_64-darwinlegacy/bibcop
===================================================================
--- trunk/Master/bin/x86_64-darwinlegacy/bibcop	                        (rev 0)
+++ trunk/Master/bin/x86_64-darwinlegacy/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/x86_64-darwinlegacy/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/x86_64-linux/bibcop
===================================================================
--- trunk/Master/bin/x86_64-linux/bibcop	                        (rev 0)
+++ trunk/Master/bin/x86_64-linux/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/x86_64-linux/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/x86_64-linuxmusl/bibcop
===================================================================
--- trunk/Master/bin/x86_64-linuxmusl/bibcop	                        (rev 0)
+++ trunk/Master/bin/x86_64-linuxmusl/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/x86_64-linuxmusl/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/bin/x86_64-solaris/bibcop
===================================================================
--- trunk/Master/bin/x86_64-solaris/bibcop	                        (rev 0)
+++ trunk/Master/bin/x86_64-solaris/bibcop	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1 @@
+link ../../texmf-dist/scripts/bibcop/bibcop.pl
\ No newline at end of file


Property changes on: trunk/Master/bin/x86_64-solaris/bibcop
___________________________________________________________________
Added: svn:special
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/bibcop/DEPENDS.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/bibcop/DEPENDS.txt	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/bibcop/DEPENDS.txt	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,3 @@
+hard iexec
+hard fancyvrb
+hard verbatimcopy
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/bibcop/DEPENDS.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/bibcop/LICENSE.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/bibcop/LICENSE.txt	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/bibcop/LICENSE.txt	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,21 @@
+(The MIT License)
+
+Copyright (c) 2022 Yegor Bugayenko
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the 'Software'), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.


Property changes on: trunk/Master/texmf-dist/doc/latex/bibcop/LICENSE.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/bibcop/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/bibcop/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/bibcop/README.md	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,54 @@
+<img src="https://raw.githubusercontent.com/yegor256/bibcop/master/logo.svg" height="92px"/>
+
+[![l3build](https://github.com/yegor256/bibcop/actions/workflows/l3build.yml/badge.svg)](https://github.com/yegor256/bibcop/actions/workflows/l3build.yml)
+[![CTAN](https://img.shields.io/ctan/v/bibcop)](https://ctan.org/pkg/bibcop)
+[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/bibcop/blob/master/LICENSE.txt)
+
+This LaTeX package checks the quality of your `.bib` file and
+emits warning message if any issues found. You may also like
+[biblint](https://github.com/Kingsford-Group/biblint) tool —
+it does almost the same but from the command line.
+
+First, [install it](https://en.wikibooks.org/wiki/LaTeX/Installing_Extra_Packages)
+from [CTAN](https://ctan.org/pkg/bibcop)
+and then use in the preamble (if you use BibTeX, for example):
+
+```tex
+\documentclass{article}
+\usepackage{bibcop}
+\begin{document}
+\bibliographystyle{plain}
+\bibliography{main}
+\end{document}
+```
+
+Otherwise, you can download [`bibcop.sty`](https://raw.githubusercontent.com/yegor256/bibcop/gh-pages/bibcop/bibcop.sty) and add to your project.
+
+You can also download [bibcop.pl](https://raw.githubusercontent.com/yegor256/bibcop/master/bibcop.pl)
+and use it as a command line tool
+to check your `.bib` files and to auto-fix them:
+
+```
+$ ./bibcop.pl --fix main.bib > fixed.bib
+```
+
+This command will read the `main.bib` file and create `fixed.bib`, which
+will have the fixed and properly formatted content (well, to some extent).
+
+## How to Contribute
+
+If you want to contribute yourself, make a fork, then create a branch, 
+then run `l3build ctan` in the root directory.
+It should compile everything without errors. If not, submit an issue and wait.
+Otherwise, make your changes and then run `l3build ctan` again. If the build is
+still clean, submit a pull request.
+
+If you want to add a new check, add it as a Perl subroutine to the `bibcop.pl` file.
+Don't forget to add a test to one of the test files that stay in the `perl-tests/` directory.
+When ready, run this, in order to check that all tests pass:
+
+```bash
+$ ./tests.pl
+```
+
+You should see the `GREAT!` message.
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/bibcop/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf	2022-12-12 21:07:17 UTC (rev 65257)

Property changes on: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop-logo.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf	2022-12-12 21:07:17 UTC (rev 65257)

Property changes on: trunk/Master/texmf-dist/doc/latex/bibcop/bibcop.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/scripts/bibcop/bibcop.pl
===================================================================
--- trunk/Master/texmf-dist/scripts/bibcop/bibcop.pl	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/bibcop/bibcop.pl	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,492 @@
+#!/usr/bin/perl
+# (The MIT License)
+#
+# Copyright (c) 2022 Yegor Bugayenko
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the 'Software'), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+package bibcop;
+
+use warnings;
+use strict;
+
+# If you want to add an extra check, just create a new procedure
+# named as "check_*".
+
+# Only these keys are allowed and only these types of items.
+my %blessed = (
+  'article' => ['doi', 'year', 'title', 'author', 'journal', 'volume', 'number', 'publisher?'],
+  'inproceedings' => ['doi', 'booktitle', 'title', 'author', 'year', 'pages?', 'organization?', 'volume?'],
+  'book' => ['doi', 'title', 'author', 'year', 'publisher'],
+  'misc' => ['title', 'author', 'year', 'eprint?', 'archiveprefix?', 'primaryclass?', 'publisher?', 'organization?', 'doi?'],
+);
+
+# Check the presence of mandatory keys.
+sub check_mandatory_keys {
+  my (%item) = @_;
+  my $type = $item{':type'};
+  my $mandatory = $blessed{$type};
+  foreach my $key (@$mandatory) {
+    if ($key =~ /^.*\?$/) {
+      next;
+    }
+    if (not(exists $item{$key})) {
+      my $listed = listed_keys(%item);
+      return "A mandatory '$key' key for '\@$type' is missing among $listed"
+    }
+  }
+  if (exists $blessed{$type}) {
+    my %required = map { $_ => 1 } @$mandatory;
+    foreach my $key (keys %item) {
+      if ($key =~ /^:/) {
+        next;
+      }
+      if (not(exists $required{$key}) && not(exists $required{$key . '?'})) {
+        return "The '$key' key is not suitable for '$type', use only these: (@$mandatory)"
+      }
+    }
+  }
+}
+
+# Check that all major words are capitalized.
+sub check_capitalization {
+  my (%item) = @_;
+  my %keys = map { $_ => 1 } qw/title booktitle journal/;
+  my %minors = map { $_ => 1 } qw/in of at to by the a an and or as if up via yet nor but off on for into/;
+  foreach my $key (keys %item) {
+    if (not exists $keys{$key}) {
+      next;
+    }
+    my $value = $item{$key};
+    my @words = only_words($value);
+    my $pos = 0;
+    foreach my $word (@words) {
+      if (not $word =~ /^[A-Za-z]/) {
+        next;
+      }
+      $pos = $pos + 1;
+      if (exists $minors{$word}) {
+        next;
+      }
+      if (exists $minors{lc($word)} and $pos gt 1) {
+        return "All minor words in the '$key' must be lower-cased, while '$word' (no.$pos) is not"
+      }
+      if ($word =~ /^[a-z].*/) {
+        return "All major words in the '$key' must be capitalized, while '$word' (no.$pos) is not"
+      }
+    }
+  }
+}
+
+# Check that the 'author' is formatted correctly.
+sub check_author {
+  my (%item) = @_;
+  if (exists $item{'author'} and not $item{'author'} =~ /^\{.+\}$/) {
+    my $author = clean_tex($item{'author'});
+    if (not $author =~ /^[A-Z][^ ]+(,( [A-Z][^ ]+)+)?( and [A-Z][^ ]+(,( [A-Z][^ ]+)+)?)*( and others)?$/) {
+      return "The format of the 'author' is wrong, use something like 'Knuth, Donald E. and Duane, Bibby'"
+    }
+    if ($author =~ /.*[A-Z]([ ,]|$).*/) {
+      return "A shortened name must have a tailing dot, as in 'Knuth, Donald E.'"
+    }
+  }
+}
+
+# Check that titles don't have shortened words with a tailing dot.
+sub check_shortenings {
+  my (%item) = @_;
+  my %keys = map { $_ => 1 } qw/title booktitle journal/;
+  foreach my $key (keys %item) {
+    if (not exists $keys{$key}) {
+      next;
+    }
+    my $value = $item{$key};
+    my @words = only_words($value);
+    foreach my $word (@words) {
+      if (not $word =~ /^[A-Za-z]/) {
+        next;
+      }
+      if ($word =~ /^.*\.$/) {
+        return "Do not shorten the words in the '$key', such as '$word'"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'title' and 'booktitle.'
+sub check_titles {
+  my (%item) = @_;
+  my @keys = qw/title booktitle/;
+  foreach my $key (@keys) {
+    if (not exists($item{$key})) {
+      next;
+    }
+    my $title = $item{$key};
+    if (not $title =~ /^\{.+\}$/) {
+      return "The '$key' must be wrapped in double curled brackets"
+    }
+  }
+}
+
+# Check that no values have tailing dots.
+# Check that there are no spaces before commans.
+sub check_typography {
+  my (%item) = @_;
+  foreach my $key (keys %item) {
+    if ($key =~ /^:.*/) {
+      next;
+    }
+    my $value = $item{$key};
+    if ($value =~ /.*\.$/ and $key ne 'author') {
+      return "The '$key' must not end with a dot"
+    }
+    if ($value =~ /.* ,.*/) {
+      return "In the '$key', do not put a space before the comma"
+    }
+  }
+}
+
+# Check the year is not mentioned in titles.
+sub check_year_in_titles {
+  my (%item) = @_;
+  my @keys = qw/title booktitle journal/;
+  foreach my $key (@keys) {
+    if (not exists($item{$key})) {
+      next;
+    }
+    my @words = only_words($item{$key});
+    foreach my $word (@words) {
+      if ($word =~ /^[1-9][0-9]{3}$/) {
+        return "The '$key' must not contain the year $word, it is enough to have the 'year' key"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'booktitle' in the 'inproceedings' item.
+sub check_booktile_of_inproceedings {
+  my (%item) = @_;
+  my $key = 'inproceedings';
+  if ($item{':type'} eq $key) {
+    if (exists $item{'booktitle'}) {
+      my @words = only_words($item{'booktitle'});
+      if (lc($words[0]) ne 'proceedings' or lc($words[1]) ne 'of' or lc($words[2]) ne 'the') {
+        return "The '$key' must start with 'Proceedings of the ...'"
+      }
+    }
+  }
+}
+
+# Check the right format of the 'doi.'
+sub check_doi {
+  my (%item) = @_;
+  if (exists $item{'doi'}) {
+    my $doi = $item{'doi'};
+    if (not $item{'doi'} =~ /^[0-9a-zA-Z.]+\/[0-9a-zA-Z._\-]+$/) {
+      return "The format of the 'doi' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'year.'
+sub check_year {
+  my (%item) = @_;
+  if (exists $item{'year'}) {
+    my $year = $item{'year'};
+    if (not $item{'year'} =~ /^[0-9]{3,4}$/) {
+      return "The format of the 'year' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'month.'
+sub check_month {
+  my (%item) = @_;
+  if (exists $item{'month'}) {
+    my $month = $item{'month'};
+    if (not $item{'month'} =~ /^[1-9]|10|11|12$/) {
+      return "The format of the 'month' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'volume.'
+sub check_volume {
+  my (%item) = @_;
+  if (exists $item{'volume'}) {
+    my $volume = $item{'volume'};
+    if (not $item{'volume'} =~ /^[1-9][0-9]*$/) {
+      return "The format of the 'volume' is wrong"
+    }
+  }
+}
+
+# Check the right format of the 'pages.'
+sub check_pages {
+  my (%item) = @_;
+  if (exists $item{'pages'}) {
+    my $pages = $item{'pages'};
+    if (not $item{'pages'} =~ /^[1-9][0-9]*--[1-9][0-9]*|[1-9][0-9]*$/) {
+      return "The format of the 'pages' is wrong"
+    }
+    my @parts = split(/--/, $pages);
+    if (@parts+0 eq 2) {
+      if ($parts[0] gt $parts[1]) {
+        return "The 'pages' are in the wrong order"
+      }
+    }
+  }
+}
+
+# Check one item.
+sub process_item {
+  my (%item) = @_;
+  my @checks;
+  foreach my $entry (keys %bibcop::) {
+    if ($entry =~ /^check_/) {
+      push(@checks, $entry);
+    }
+  }
+  my @sorted = sort @checks;
+  my @errors;
+  foreach my $check (@sorted) {
+    no strict 'refs';
+    my $err = $check->(%item);
+    if ($err ne '') {
+      push(@errors, $err);
+    }
+  }
+  return @errors;
+}
+
+# Parse the incoming .bib file and return an array
+# of hash-maps, where each one is a bibitem.
+sub bibitems {
+  my ($bib) = @_;
+  my @items;
+  my $s = 'top';
+  my %item;
+  my $acc = '';
+  my $key = '';
+  my $lineno = 0;
+  my $nest = 0;
+  my $escape = 0;
+  for my $pos (0..length($bib)-1) {
+    my $char = substr($bib, $pos, 1);
+    if ($char eq ' ') {
+      # ignore the white space
+    } elsif ($char eq "\n") {
+      # ignore the EOL
+      $lineno = $lineno + 1;
+    } elsif ($char eq '@' and $s eq 'top') {
+      %item = ();
+      $s = 'start';
+      $acc = '';
+    } elsif ($char =~ /[a-z]/ and $s eq 'start') {
+      # @article
+    } elsif ($char eq '{' and $s eq 'start') {
+      $item{':type'} = substr($acc, 1);
+      $acc = '';
+      $s = 'body';
+    } elsif ($char =~ /[a-zA-Z]/ and $s eq 'body') {
+      $acc = '';
+      $s = 'key';
+    } elsif ($char =~ /[a-zA-Z0-9_]/ and $s eq 'key') {
+      # reading the key
+    } elsif ($char =~ /[a-zA-Z0-9]/ and $s eq 'value') {
+      # reading the value without quotes or brackets
+    } elsif ($char eq ',' and $s eq 'key') {
+      $item{':name'} = $acc;
+      $s = 'body';
+    } elsif ($char eq '=' and $s eq 'key') {
+      $key = $acc;
+      $s = 'value';
+      $acc = '';
+    } elsif ($char eq ',' and $s eq 'value') {
+      if (not exists $item{lc($key)}) {
+        my $tex = substr($acc, 1);
+        $tex =~ s/\s//g;
+        $item{lc($key)} = $tex;
+      }
+      $s = 'body';
+    } elsif ($char eq '}' and $s eq 'body') {
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '}' and $s eq 'value') {
+      if (not exists $item{lc($key)}) {
+        my $tex = substr($acc, 1);
+        $tex =~ s/\s//g;
+        $item{lc($key)} = $tex;
+      }
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '}' and $s eq 'key') {
+      $item{':name'} = $acc;
+      push(@items, { %item });
+      $s = 'top';
+    } elsif ($char eq '"' and $s eq 'value') {
+      $s = 'quote';
+      $acc = '';
+    } elsif ($char eq '"' and $s eq 'quote') {
+      $item{lc($key)} = substr($acc, 1);
+      $s = 'value';
+    } elsif ($s eq 'quote') {
+      # nothing
+    } elsif ($char eq '{' and $s eq 'value') {
+      $nest = 1;
+      $s = 'brackets';
+      $acc = '';
+    } elsif ($s eq 'brackets') {
+      if ($char eq '\\') {
+        $escape = 1;
+      } elsif ($char eq '{' and $escape ne 1) {
+        $nest = $nest + 1;
+      } elsif ($char eq '}' and $escape ne 1) {
+        $nest = $nest - 1;
+        if ($nest eq 0) {
+          $item{lc($key)} = substr($acc, 1);
+          $s = 'value';
+        }
+      }
+      $escape = 0;
+    } else {
+      print "\\PackageWarningNoLine{bibcop}{It is impossible to parse the .bib file, because I do not know what to do with '$char' at line #$lineno (s=$s)}\n";
+      last;
+    }
+    if ($char eq ' ' and not($s =~ /quote|brackets/)) {
+      next;
+    }
+    $acc = $acc . $char;
+  }
+  return @items;
+}
+
+# Takes the text and returns only list of words seen there.
+sub only_words {
+  my ($tex) = @_;
+  return split(/[ \-]/, clean_tex($tex));
+}
+
+# Take a TeX string and return a cleaner one, without redundant spaces, brackets, etc.
+sub clean_tex {
+  my ($tex) = @_;
+  $tex =~ s/\s+/ /g;
+  $tex =~ s/^\{+//g;
+  $tex =~ s/\}+$//g;
+  return $tex;
+}
+
+# Take a bibitem and print all its keys as a comma-separated string.
+sub listed_keys {
+  my (%item) = @_;
+  my @list;
+  foreach my $key (keys %item) {
+    if ($key =~ /^:.*/) {
+      next;
+    }
+    push(@list, $key);
+  }
+  my @sorted = sort @list;
+  return '(' . join(', ', @sorted) . ')';
+}
+
+my %args = map { $_ => 1 } @ARGV;
+if (@ARGV+0 eq 0 or exists $args{'--help'}) {
+  debug("Bibcop is a Style Checker of .bib Files\n" .
+    "Usage: bibcop [<options>] <.bib file path>\n" .
+    "  --version Print the current version of the tool and exit\n" .
+    "  --help    Print this help screen\n" .
+    "  --fix     Fix the errors and print a new version of the .bib file to the console\n" .
+    "  --latex   Report errors in LaTeX format using \\PackageWarningNoLine command");
+} elsif (exists $args{'--version'}) {
+  debug('0.0.2');
+} else {
+  my ($file) = grep { not($_ =~ /^--.*$/) } @ARGV;
+  open(my $fh, '<', $file);
+  my $bib; { local $/; $bib = <$fh>; }
+  my @items = bibitems($bib);
+  if (exists $args{'--fix'}) {
+    for my $i (0..(@items+0 - 1)) {
+      my %item = %{ $items[$i] };
+      my $type = $item{':type'};
+      if (not exists $blessed{$type}) {
+        error("I don't know what to do with \@$type type of bibitem");
+      }
+      my $keys = $blessed{$item{':type'}};
+      my %allowed = map { $_ => 1 } @$keys;
+      my @lines;
+      foreach my $key (keys %item) {
+        if ($key =~ /^:/) {
+          next;
+        }
+        if (not exists $allowed{$key} and not exists $allowed{$key . '?'}) {
+          next;
+        }
+        my $value = clean_tex($item{$key});
+        if ($key =~ /title|booktitle|journal/) {
+          $value = '{' . $value . '}';
+        }
+        push(@lines, "  $key = {$value},");
+      }
+      debug("\@$type\{$item{':name'},");
+      my @sorted = sort @lines;
+      foreach my $line (@sorted) {
+        debug($line);
+      }
+      debug("}\n");
+    }
+  } else {
+    debug((@items+0) . ' bibitems found in ' . $file);
+    for my $i (0..(@items+0 - 1)) {
+      my %item = %{ $items[$i] };
+      debug("Checking $item{':name'} (#$i)...");
+      foreach my $err (process_item(%item)) {
+        warning("$err, in the '$item{':name'}' bibitem");
+      }
+    }
+  }
+}
+
+# Print ERROR message to the console and die.
+sub error {
+  my ($txt) = @_;
+  print $txt . "\n";
+  exit 1;
+}
+
+# Print DEBUG message to the console.
+sub debug {
+  my ($txt) = @_;
+  if (exists $args{'--latex'}) {
+    print '% ';
+  }
+  print $txt . "\n";
+}
+
+# Print INFO message to the console.
+sub warning {
+  my ($txt) = @_;
+  if (exists $args{'--latex'}) {
+    print "\\PackageWarningNoLine{bibcop}{$txt}\n";
+  } else {
+    print $txt . "\n";
+  }
+}
+
+1;


Property changes on: trunk/Master/texmf-dist/scripts/bibcop/bibcop.pl
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/bibcop/bibcop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/bibcop/bibcop.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/bibcop/bibcop.dtx	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,346 @@
+% \iffalse meta-comment
+% (The MIT License)
+%
+% Copyright (c) 2022 Yegor Bugayenko
+%
+% Permission is hereby granted, free of charge, to any person obtaining a copy
+% of this software and associated documentation files (the 'Software'), to deal
+% in the Software without restriction, including without limitation the rights
+% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+% copies of the Software, and to permit persons to whom the Software is
+% furnished to do so, subject to the following conditions:
+%
+% The above copyright notice and this permission notice shall be included in all
+% copies or substantial portions of the Software.
+%
+% THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+% SOFTWARE.
+% \fi
+
+% \CheckSum{0}
+%
+% \CharacterTable
+%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%   Digits        \0\1\2\3\4\5\6\7\8\9
+%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%   Dollar        \$     Percent       \%     Ampersand     \&
+%   Acute accent  \'     Left paren    \(     Right paren   \)
+%   Asterisk      \*     Plus          \+     Comma         \,
+%   Minus         \-     Point         \.     Solidus       \/
+%   Colon         \:     Semicolon     \;     Less than     \<
+%   Equals        \=     Greater than  \>     Question mark \?
+%   Commercial at \@     Left bracket  \[     Backslash     \\
+%   Right bracket \]     Circumflex    \^     Underscore    \_
+%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%   Right brace   \}     Tilde         \~}
+
+% \GetFileInfo{bibcop.dtx}
+% \DoNotIndex{\endgroup,\begingroup,\let,\else,\s,\n,\r,\\,\1,\fi}
+
+% \iffalse
+%<*driver>
+\ProvidesFile{bibcop.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}
+%<package>\ProvidesPackage{bibcop}
+%<*package>
+[2022-12-12 0.0.2 Style Checker of Bibliography Files]
+%</package>
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage[T1]{fontenc}
+\usepackage[maxnames=1,minnames=1,maxbibnames=1,natbib=true,citestyle=authoryear,bibstyle=authoryear,doi=false,url=false,isbn=false,isbn=false]{biblatex}
+\addbibresource{bibcop.bib}
+\usepackage[tt=false, type1=true]{libertine}
+\usepackage{microtype}
+\AddToHook{env/verbatim/begin}{\microtypesetup{protrusion=false}}
+\usepackage{href-ul}
+\usepackage{xcolor}
+\usepackage{graphicx}
+\PageIndex
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+	\DocInput{bibcop.dtx}
+	\PrintChanges
+	\PrintIndex
+\end{document}
+%</driver>
+% \fi
+
+% \title{\includegraphics[height=1in]{bibcop-logo.pdf} \\ |bibcop|: \LaTeX{} Package \\ for Style Checking of |.bib| Files\thanks{The sources are in GitHub at \href{https://github.com/yegor256/bibcop}{yegor256/bibcop}}}
+% \author{Yegor Bugayenko \\ \texttt{yegor256 at gmail.com}}
+% \date{\filedate, \fileversion}
+%
+% \maketitle
+%
+% \textbf{\color{red}NB!}
+% You must run \TeX{} processor with |--shell-escape| option
+% and you must have \href{https://www.perl.org}{Perl} installed.
+% This package doesn't work on Windows.
+
+% \section{Introduction}
+%
+% This package scans your |.bib| files for style errors and emits
+% warning messages if any issues are found (make sure you use it before
+% all other bibliography related packages):
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+\documentclass{article}
+\usepackage{bibcop}
+\begin{document}
+\bibliographystyle{plain}
+\bibliography{main}
+\end{document}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% You may see warnings in the \TeX log. Fix the issues in the |main.bib| file
+% and the warnings will disappear.
+
+% If you use the |.sty| file (without installing it into the \TeX{} tree), don't forget
+% to also copy the |bibcop.pl| file --- it is the Perl script that does all the work
+% of checking your |.bib| files. The |.sty| is just a simple wrapper around it.
+
+% Make sure |\usepackage{bibcop}| stays before all other |\usepackage| commands, otherwise
+% you won't see any warnings from |bibcop|.
+
+% \section{The Rules}
+
+% This is a more or less complete list of rules we enforce on a |.bib| file:
+
+% \DescribeMacro{types}
+% Only |@article|, |@book|, |@inproceedings|, and |@misc| types of bib items are allowed.
+% Everything else, like |@manual|, |@phdthesis|, and many others are simply prohibited.
+% The mentioned four should be enough for everything.
+
+% \DescribeMacro{keys}
+% There are pretty limited lists of allowed keys for each type of bib item. The keys
+% that are not in the list are prohibited to use.
+
+% \DescribeMacro{doi}
+% Every bib item must have the |doi| key, which is a unique
+% \href{https://www.doi.org}{Digital Object Identifier}
+% of the material that you reference. It seems to be a good practice, in order to avoid ambiguity,
+% to always mention the DOI.
+
+% \DescribeMacro{caps}
+% In |title|, |booktitle|, and |journal| keys, all major words must be capitalized,
+% as it is \href{https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case}{recommended by APA}:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+title = {A Preliminary Architecture for a Basic Data-Flow Processor}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% Here, the leading ``|A|'' is capital because it opens the title.
+% The word ``|for|'' and the article ``|a|'' are minor words, that's why they are in lower case.
+% Both parts of the composite word ``|Data-Flow|'' are capitalized.
+
+% \DescribeMacro{author}
+% The |author| must contain a list of authors separated by ``|and|''. Each author
+% must have two parts separated by a comma. The first part is the last name of the author,
+% the second part is a list of their first names separated by a space, for example:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+author = {Knuth, Donald E. and Duane, Bibby}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% When the list of authors is too long, it's possible to say ``|and others|'':
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+author = {Knuth, Donald E. and others}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% When first names are shortened to a single letter, it has to have a tailing dot.
+
+% \DescribeMacro{shorts}
+% It is not allowed to shorten any words, for example this is illegal:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+journal = {J. Log. Comput.}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% This must be replaced with the following:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+journal = {Journal of Logic and Computation}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \DescribeMacro{brackets}
+% The |title|, |booktitle|, and |journal| must be wrapped with double brackets, for example:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+title = {{A Survey of Symbolic Execution Techniques}}
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% This is necessary in order to prevent down-casing of capitalized words, which is done by some
+% bibliography styles.
+
+% \DescribeMacro{year}
+% It is not allowed to mention the year inside the title of a conference or a journal, for example,
+% this would be illegal:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+booktitle = {{1994 IEEE International Conference on Computer Languages}},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+% The year should only be mentioned in the |year| key, nowhere else.
+% In the |year| key only numbers are allowed:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+year = {1994},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \DescribeMacro{month}
+% The |month| may contain only a number:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+month = {12},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \DescribeMacro{volume}
+% The |volume| may contain only a number:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+volume = {32},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \DescribeMacro{pages}
+% The |pages| may contain either a number or two numbers separated by a double dash:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+pages = {145--163},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \DescribeMacro{proceedings}
+% The |booktitle| in the |@inproceedings| bib item must always start with ``|Proceedings| |of| |the|'',
+% as in this example:
+%\iffalse
+%<*verb>
+%\fi
+\begin{verbatim}
+booktitle = {{Proceedings of the International
+  Conference on Computer Languages}},
+\end{verbatim}
+%\iffalse
+%</verb>
+%\fi
+
+% \StopEventually{}
+
+% \section{Implementation}
+% \changes{0.0.1}{2022/12/11}{First draft.}
+% \changes{0.0.2}{2022/12/12}{Documentation extended, more rules added.}
+
+% First, we include a few packages.
+% We need \href{https://ctan.org/pkg/iexec}{iexec} for executing Perl scripts:
+%    \begin{macrocode}
+\RequirePackage{iexec}
+%    \end{macrocode}
+
+% \begin{macro}{bibcop.pl}
+% Then, we copy the Perl script using |\VerbatimCopy| from
+% \href{https://ctan.org/pkg/verbatimcopy}{verbatimcopy}:
+%    \begin{macrocode}
+\RequirePackage{verbatimcopy}
+\VerbatimCopy{bibcop.pl}{bibcop.tmp.pl}
+\message{bibcop: File with Perl script 'bibcop.pl' copied^^J}%
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\bibliography}
+% Then, we re-define the |\bibliography| command:
+%    \begin{macrocode}
+\makeatletter
+\ifdefined\bibliography\else\gdef\bibliography#1{}\fi
+\let\bibcop at oldbibliography\bibliography
+\renewcommand\bibliography[1]{%
+  \iexec{perl "./bibcop.tmp.pl" --latex '#1.bib'}%
+  \bibcop at oldbibliography{#1}%
+}
+\makeatother
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}{\addbibresource}
+% Then, we re-define the |\addbibresource| command:
+%    \begin{macrocode}
+\makeatletter
+\ifdefined\addbibresource\else\gdef\addbibresource#1{}\fi
+\let\bibcop at oldaddbibresource\addbibresource
+\renewcommand\addbibresource[1]{%
+  \iexec{perl "./bibcop.tmp.pl" --latex '#1'}%
+  \bibcop at oldaddbibresource{#1}%
+}
+\makeatother
+%    \end{macrocode}
+% \end{macro}
+
+% \Finale
+
+% \clearpage
+% \printbibliography
+% \clearpage
+
+% \PrintChanges
+% \clearpage
+% \PrintIndex


Property changes on: trunk/Master/texmf-dist/source/latex/bibcop/bibcop.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/bibcop/bibcop.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/bibcop/bibcop.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/bibcop/bibcop.ins	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,55 @@
+%% (The MIT License)
+%%
+%% Copyright (c) 2022 Yegor Bugayenko
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the 'Software'), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be included in all
+%% copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+%% SOFTWARE.
+
+\input docstrip.tex
+\keepsilent
+\usedir{macros/latex/contrib/bibcop}
+\preamble
+(The MIT License)
+
+Copyright (c) 2022 Yegor Bugayenko
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the 'Software'), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+\endpreamble
+\generate{\file{bibcop.sty}{\from{bibcop.dtx}{package}}}
+\obeyspaces
+\Msg{To finish the installation you have to move the ".sty"}
+\Msg{file into a directory searched by TeX. To produce the}
+\Msg{documentation run the file ".dtx" through LaTeX. If any}
+\Msg{questions, submit a new GitHub issue.}
+\endbatchfile

Added: trunk/Master/texmf-dist/tex/latex/bibcop/bibcop.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/bibcop/bibcop.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/bibcop/bibcop.sty	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,84 @@
+%%
+%% This is file `bibcop.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% bibcop.dtx  (with options: `package')
+%% (The MIT License)
+%% 
+%% Copyright (c) 2022 Yegor Bugayenko
+%% 
+%% Permission is hereby granted, free of charge, to any person obtaining a copy
+%% of this software and associated documentation files (the 'Software'), to deal
+%% in the Software without restriction, including without limitation the rights
+%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%% copies of the Software, and to permit persons to whom the Software is
+%% furnished to do so, subject to the following conditions:
+%% 
+%% The above copyright notice and this permission notice shall be included in all
+%% copies or substantial portions of the Software.
+%% 
+%% THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+%% SOFTWARE.
+
+
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{bibcop}
+[2022-12-12 0.0.2 Style Checker of Bibliography Files]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+\RequirePackage{iexec}
+
+\RequirePackage{verbatimcopy}
+\VerbatimCopy{bibcop.pl}{bibcop.tmp.pl}
+\message{bibcop: File with Perl script 'bibcop.pl' copied^^J}%
+
+\makeatletter
+\ifdefined\bibliography\else\gdef\bibliography#1{}\fi
+\let\bibcop at oldbibliography\bibliography
+\renewcommand\bibliography[1]{%
+  \iexec{perl "./bibcop.tmp.pl" --latex '#1.bib'}%
+  \bibcop at oldbibliography{#1}%
+}
+\makeatother
+
+\makeatletter
+\ifdefined\addbibresource\else\gdef\addbibresource#1{}\fi
+\let\bibcop at oldaddbibresource\addbibresource
+\renewcommand\addbibresource[1]{%
+  \iexec{perl "./bibcop.tmp.pl" --latex '#1'}%
+  \bibcop at oldaddbibresource{#1}%
+}
+\makeatother
+
+
+
+\endinput
+%%
+%% End of file `bibcop.sty'.


Property changes on: trunk/Master/texmf-dist/tex/latex/bibcop/bibcop.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2022-12-12 21:07:17 UTC (rev 65257)
@@ -105,7 +105,7 @@
     beebe begingreek begriff beilstein belleek bengali
     bera berenisadf besjournals bestpapers betababel beton beuron
     bewerbung bez123 bezierplot bfh-ci bgteubner bguq bhcexam
-    bib-fr bib2gls bibarts biber biber-ms bibhtml
+    bib-fr bib2gls bibarts bibcop biber biber-ms bibhtml
     biblatex biblatex-abnt biblatex-ajc2020unofficial
     biblatex-anonymous biblatex-apa biblatex-apa6
     biblatex-archaeology biblatex-arthistory-bonn

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2022-12-12 21:07:17 UTC (rev 65257)
@@ -3541,6 +3541,7 @@
  'attachfile2'		=> 'pdfatfi\.pl$',
  'authorindex'          => 'authorindex$',
  'bib2gls'		=> '\.sh$',
+ 'bibcop'		=> '\.pl$',
  'bibexport'            => 'bibexport\.sh$',
  'bundledoc'            => '(arlatex|bundledoc)$',
  'checkcites'           => '\.lua$',

Added: trunk/Master/tlpkg/tlpsrc/bibcop.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/bibcop.tlpsrc	                        (rev 0)
+++ trunk/Master/tlpkg/tlpsrc/bibcop.tlpsrc	2022-12-12 21:07:17 UTC (rev 65257)
@@ -0,0 +1,4 @@
+binpattern f bin/${ARCH}/${PKGNAME}
+hard iexec
+hard fancyvrb
+hard verbatimcopy

Modified: trunk/Master/tlpkg/tlpsrc/collection-bibtexextra.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-bibtexextra.tlpsrc	2022-12-12 21:02:56 UTC (rev 65256)
+++ trunk/Master/tlpkg/tlpsrc/collection-bibtexextra.tlpsrc	2022-12-12 21:07:17 UTC (rev 65257)
@@ -20,6 +20,7 @@
 depend bestpapers
 depend bib2gls
 depend bibarts
+depend bibcop
 depend biber
 depend biber-ms
 depend bibexport



More information about the tex-live-commits mailing list.