summaryrefslogtreecommitdiff
path: root/support/bibtexperllibs/BibTeX-Parser
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/bibtexperllibs/BibTeX-Parser
Initial commit
Diffstat (limited to 'support/bibtexperllibs/BibTeX-Parser')
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/Changes80
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/LICENSE379
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/MANIFEST44
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/META.yml23
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/Makefile.PL71
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/Makefile.TDS25
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/README10
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/dist.ini28
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser.pm364
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Author.pm412
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Entry.pm433
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser.3pm213
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Author.3pm216
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Entry.3pm263
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/notes26
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/00-load.t11
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/01-parse.t36
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/02-parse_string.t39
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/03-parse_entry.t102
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/04-entry.t42
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/05-author.t68
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/06-parse_complex.t46
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/07-parse_englishbib.t42
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/08-parse_large.t24
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/09-complex.t42
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/10-funnyname.t61
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/11-split_braced.t28
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/12-von_token.t12
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/13_output.t39
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/14-extratext.t65
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/15-capitalization.t72
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/01.bib7
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/06.bib27
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/09-complex.bib11
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/10-funnyname.bib10
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/14-extratext.bib22
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/braces.bib21
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/endnote.txt6
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/engineering_village.txt24
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/english.bib55
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bibs/mathscinet.txt40
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bug66325.t71
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/bug67419.t29
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/cleaned_field.t142
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/pod-coverage.t18
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/pod.t12
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/release-pod-coverage.t21
-rw-r--r--support/bibtexperllibs/BibTeX-Parser/t/release-pod-syntax.t15
48 files changed, 3847 insertions, 0 deletions
diff --git a/support/bibtexperllibs/BibTeX-Parser/Changes b/support/bibtexperllibs/BibTeX-Parser/Changes
new file mode 100644
index 0000000000..addfd59900
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/Changes
@@ -0,0 +1,80 @@
+Revision history for BibTeX-Parser
+
+1.02 2018-04-29 03:19:56 +0000
+ Corrected the bug when Jr is not accompanied by von.
+
+1.01 2017-11-19 03:12:34 +0000
+ New options for to_string:
+ - print_pre - whether to print text preceding the entry
+ - type_capitalization ('Uppercase', 'Lowercase',
+ 'Titlecase')
+ - field_capitalization ('Uppercase', 'Lowercase',
+ 'Titlecase')
+
+1.00 2017-03-18 21:53:15+00:00
+ Typo corrected: editors -> editor
+
+0.70 2016-11-23 02:28:35+00:00
+ Compatibility with perl 5.25 (Alexandr Ciornii)
+
+0.69 2016-03-24 15:13:50-04:00
+ Added option canonize_names to Entry::to_string
+
+0.68 2016-03-10 13:45:31-05:00
+ Now we preserve the order of entries
+
+0.67 2015-12-28 22:36:42+00:00
+ Corrected test t/13_output.t
+
+0.66 2015-12-23 19:52:55-05:00
+ Corrected bug 67419.
+ Added $entry->to_string function
+ No Do not remove braces from the authors' names
+
+0.65 2013-09-03 21:04:43
+ Add links in documentation.
+
+0.64 2012-03-10 22:23:50
+ Remove a warning about undefined value.
+
+0.63 2011-03-15 23:08:18
+ Parse files with errors (no keys, spaces in wrong positions). Bug #66325
+
+0.62 2010-10-15 08:52:53
+ Declare Test::More minimum version with done_testing
+
+0.61 2010-07-19 16:37:49
+ Add methods $entry->cleaned_author / cleaned_editor
+
+0.6 2010-07-19 14:43:15
+ Add method $entry->cleaned_field( 'name' )
+ Add prerequisite LaTeX::ToUnicode >= 0.02
+
+0.5 2010-07-06 13:17:45 Europe/Berlin
+ Do not attempt to clean up returned values
+ Author names with braces are split correctly
+
+0.4 2010-02-09
+ Parsing of quoted author names (e.g. "{Foo and Bar, Inc.}")
+
+0.3.2 2009-07-26
+ Removed dependency on Text::Balanced
+
+0.3.1 2009-07-19
+ No changes, removed huge test file from dist
+
+0.3 2009-07-18
+ Better parsing of author names,
+ new Method B::P::Entry->raw_bibtex
+ Removed Module::Install from package
+
+0.21 2009-01-23
+ Fixed errors in synopsis.
+
+0.2 2008-12-30
+ First public release.
+
+0.1 2008-03-14
+ First version, internal
+
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/LICENSE b/support/bibtexperllibs/BibTeX-Parser/LICENSE
new file mode 100644
index 0000000000..3f09c94f5c
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/LICENSE
@@ -0,0 +1,379 @@
+This software is copyright (c) 2013-2016 by Gerhard Gossen and Boris Veytsman
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+Terms of the Perl programming language system itself
+
+a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+b) the "Artistic License"
+
+--- The GNU General Public License, Version 1, February 1989 ---
+
+This software is copyright (c) 2013-2016 by Gerhard Gossen and Boris Veytsman
+
+This is free software, licensed under:
+
+ The GNU General Public License, Version 1, February 1989
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+--- The Artistic License 1.0 ---
+
+This software is Copyright (c) 2013 by Gerhard Gossen.
+
+This is free software, licensed under:
+
+ The Artistic License 1.0
+
+The Artistic License
+
+Preamble
+
+The intent of this document is to state the conditions under which a Package
+may be copied, such that the Copyright Holder maintains some semblance of
+artistic control over the development of the package, while giving the users of
+the package the right to use and distribute the Package in a more-or-less
+customary fashion, plus the right to make reasonable modifications.
+
+Definitions:
+
+ - "Package" refers to the collection of files distributed by the Copyright
+ Holder, and derivatives of that collection of files created through
+ textual modification.
+ - "Standard Version" refers to such a Package if it has not been modified,
+ or has been modified in accordance with the wishes of the Copyright
+ Holder.
+ - "Copyright Holder" is whoever is named in the copyright or copyrights for
+ the package.
+ - "You" is you, if you're thinking about copying or distributing this Package.
+ - "Reasonable copying fee" is whatever you can justify on the basis of media
+ cost, duplication charges, time of people involved, and so on. (You will
+ not be required to justify it to the Copyright Holder, but only to the
+ computing community at large as a market that must bear the fee.)
+ - "Freely Available" means that no fee is charged for the item itself, though
+ there may be fees involved in handling the item. It also means that
+ recipients of the item may redistribute it under the same conditions they
+ received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications derived
+from the Public Domain or from the Copyright Holder. A Package modified in such
+a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided that
+you insert a prominent notice in each changed file stating how and when you
+changed that file, and provided that you do at least ONE of the following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or an
+ equivalent medium, or placing the modifications on a major archive site
+ such as ftp.uu.net, or by allowing the Copyright Holder to include your
+ modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict with
+ standard executables, which must also be provided, and provide a separate
+ manual page for each non-standard executable that clearly documents how it
+ differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or executable
+form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where to
+ get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of the Package
+ with your modifications.
+
+ c) accompany any non-standard executables with their corresponding Standard
+ Version executables, giving the non-standard executables non-standard
+ names, and clearly documenting the differences in manual pages (or
+ equivalent), together with instructions on where to get the Standard
+ Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package. You
+may not charge a fee for this Package itself. However, you may distribute this
+Package in aggregate with other (possibly commercial) programs as part of a
+larger (possibly commercial) software distribution provided that you do not
+advertise this Package as a product of your own.
+
+6. The scripts and library files supplied as input to or produced as output
+from the programs of this Package do not automatically fall under the copyright
+of this Package, but belong to whomever generated them, and may be sold
+commercially, and may be aggregated with this Package.
+
+7. C or perl subroutines supplied by you and linked into this Package shall not
+be considered part of this Package.
+
+8. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+The End
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/MANIFEST b/support/bibtexperllibs/BibTeX-Parser/MANIFEST
new file mode 100644
index 0000000000..ec2f7719ea
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/MANIFEST
@@ -0,0 +1,44 @@
+Changes
+LICENSE
+MANIFEST
+META.yml
+Makefile.PL
+README
+dist.ini
+lib/BibTeX/Parser.pm
+lib/BibTeX/Parser/Author.pm
+lib/BibTeX/Parser/Entry.pm
+notes
+t/00-load.t
+t/01-parse.t
+t/02-parse_string.t
+t/03-parse_entry.t
+t/04-entry.t
+t/05-author.t
+t/06-parse_complex.t
+t/07-parse_englishbib.t
+t/08-parse_large.t
+t/09-complex.t
+t/10-funnyname.t
+t/11-split_braced.t
+t/12-von_token.t
+t/13_output.t
+t/14-extratext.t
+t/15-capitalization.t
+t/bibs/01.bib
+t/bibs/06.bib
+t/bibs/09-complex.bib
+t/bibs/10-funnyname.bib
+t/bibs/14-extratext.bib
+t/bibs/braces.bib
+t/bibs/endnote.txt
+t/bibs/engineering_village.txt
+t/bibs/english.bib
+t/bibs/mathscinet.txt
+t/bug66325.t
+t/bug67419.t
+t/cleaned_field.t
+t/pod-coverage.t
+t/pod.t
+t/release-pod-coverage.t
+t/release-pod-syntax.t
diff --git a/support/bibtexperllibs/BibTeX-Parser/META.yml b/support/bibtexperllibs/BibTeX-Parser/META.yml
new file mode 100644
index 0000000000..ea5508c50b
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/META.yml
@@ -0,0 +1,23 @@
+---
+abstract: 'A pure perl BibTeX parser'
+author:
+ - 'Gerhard Gossen <gerhard.gossen@googlemail.com>'
+ - 'Boris Veytsman <borisv@lk.net>'
+build_requires:
+ Test::More: 0.88
+configure_requires:
+ ExtUtils::MakeMaker: 6.30
+dynamic_config: 0
+generated_by: 'Dist::Zilla version 4.300037, CPAN::Meta::Converter version 2.120921'
+license: perl
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: 1.4
+name: BibTeX-Parser
+requires:
+ File::Spec: 0
+ IO::File: 0
+ IO::String: 0
+ LaTeX::ToUnicode: 0.02
+ Test::More: 0
+version: 1.02
diff --git a/support/bibtexperllibs/BibTeX-Parser/Makefile.PL b/support/bibtexperllibs/BibTeX-Parser/Makefile.PL
new file mode 100644
index 0000000000..1deb311e4b
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/Makefile.PL
@@ -0,0 +1,71 @@
+
+use strict;
+use warnings;
+
+
+
+use ExtUtils::MakeMaker 6.30;
+
+
+
+my %WriteMakefileArgs = (
+ "ABSTRACT" => "A pure perl BibTeX parser",
+ "AUTHOR" => "Gerhard Gossen <gerhard.gossen\@googlemail.com> and Boris Veytsman <boris\@varphi.com>",
+ "BUILD_REQUIRES" => {},
+ "CONFIGURE_REQUIRES" => {
+ "ExtUtils::MakeMaker" => "6.30"
+ },
+ "DISTNAME" => "BibTeX-Parser",
+ "EXE_FILES" => [],
+ "LICENSE" => "perl",
+ "NAME" => "BibTeX::Parser",
+ "PREREQ_PM" => {
+ "File::Spec" => 0,
+ "IO::File" => 0,
+ "IO::String" => 0,
+ "LaTeX::ToUnicode" => "0.02",
+ "Test::More" => 0
+ },
+ "TEST_REQUIRES" => {
+ "Test::More" => "0.88"
+ },
+ "VERSION" => "1.02",
+ "test" => {
+ "TESTS" => "t/*.t"
+ }
+);
+
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+ my $tr = delete $WriteMakefileArgs{TEST_REQUIRES};
+ my $br = $WriteMakefileArgs{BUILD_REQUIRES};
+ for my $mod ( keys %$tr ) {
+ if ( exists $br->{$mod} ) {
+ $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
+ }
+ else {
+ $br->{$mod} = $tr->{$mod};
+ }
+ }
+}
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
+ my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
+ my $pp = $WriteMakefileArgs{PREREQ_PM};
+ for my $mod ( keys %$br ) {
+ if ( exists $pp->{$mod} ) {
+ $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
+ }
+ else {
+ $pp->{$mod} = $br->{$mod};
+ }
+ }
+}
+
+delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
+ unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
+
+WriteMakefile(%WriteMakefileArgs);
+
+
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/Makefile.TDS b/support/bibtexperllibs/BibTeX-Parser/Makefile.TDS
new file mode 100644
index 0000000000..7072d1f20d
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/Makefile.TDS
@@ -0,0 +1,25 @@
+#
+# This is Makefile for TDS-compliant TeX distributions
+# Written by Boris Veytsman, boris@varphi.com
+#
+# This file is in public domain
+#
+PREFIX = /usr/local
+
+LIBDIR = $(PREFIX)/scripts/bibtexperllibs
+
+DOCDIR = $(PREFIX)/doc/bibtex/bibtexperllibs
+
+all:
+
+
+
+install:
+ mkdir -p $(LIBDIR)
+ cp -r lib/* $(LIBDIR)
+ mkdir -p $(DOCDIR)
+ cp -r man/man3/* $(DOCDIR)
+
+clean:
+
+distclean: clean
diff --git a/support/bibtexperllibs/BibTeX-Parser/README b/support/bibtexperllibs/BibTeX-Parser/README
new file mode 100644
index 0000000000..bbaac1e9db
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/README
@@ -0,0 +1,10 @@
+This archive contains the distribution BibTeX-Parser,
+version 1.02:
+
+ A pure perl BibTeX parser
+
+This software is copyright (c) 2013--2017 by Gerhard Gossen and Boris Veytsman
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/dist.ini b/support/bibtexperllibs/BibTeX-Parser/dist.ini
new file mode 100644
index 0000000000..b615101f91
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/dist.ini
@@ -0,0 +1,28 @@
+name = BibTeX-Parser
+version = 1.02
+author = Gerhard Gossen <gerhard.gossen@googlemail.com> and Boris Veytsman <boris@varphi.com>
+license = Perl_5
+copyright_holder = Gerhard Gossen and Boris Veytsman
+
+[@Classic]
+
+[NextRelease]
+format = %-7v %{yyyy-MM-dd HH:mm:ss}d
+
+[PodWeaver]
+
+[Prereqs]
+Test::More = 0
+IO::String = 0
+IO::File = 0
+File::Spec = 0
+LaTeX::ToUnicode = 0.02
+
+[Prereqs / TestRequires]
+Test::More = 0.88 ; for done_testing
+
+[PruneFiles]
+filenames = t/bibs/java.bib
+
+[Repository]
+[@Git]
diff --git a/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser.pm b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser.pm
new file mode 100644
index 0000000000..2eac696a04
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser.pm
@@ -0,0 +1,364 @@
+package BibTeX::Parser;
+{
+ $BibTeX::Parser::VERSION = '1.02';
+}
+# ABSTRACT: A pure perl BibTeX parser
+use warnings;
+use strict;
+
+use BibTeX::Parser::Entry;
+
+
+my $re_namechar = qr/[a-zA-Z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]/o;
+my $re_name = qr/$re_namechar+/o;
+
+
+sub new {
+ my ( $class, $fh ) = @_;
+
+ return bless {
+ fh => $fh,
+ strings => {
+ jan => "January",
+ feb => "February",
+ mar => "March",
+ apr => "April",
+ may => "May",
+ jun => "June",
+ jul => "July",
+ aug => "August",
+ sep => "September",
+ oct => "October",
+ nov => "November",
+ dec => "December",
+
+ },
+ line => -1,
+ buffer => "",
+ }, $class;
+}
+
+sub _slurp_close_bracket;
+
+sub _parse_next {
+ my $self = shift;
+
+ while (1) { # loop until regular entry is finished
+ return 0 if $self->{fh}->eof;
+ local $_ = $self->{buffer};
+
+ until (/@/m) {
+ my $line = $self->{fh}->getline;
+ return 0 unless defined $line;
+ $_ .= $line;
+ }
+
+ my $current_entry = new BibTeX::Parser::Entry;
+ if (/@($re_name)/cgo) {
+ my $type = uc $1;
+ $current_entry->type( $type );
+ my $start_pos = pos($_) - length($type) - 1;
+
+ # read rest of entry (matches braces)
+ my $bracelevel = 0;
+ $bracelevel += tr/\{/\{/; #count braces
+ $bracelevel -= tr/\}/\}/;
+ while ( $bracelevel != 0 ) {
+ my $position = pos($_);
+ my $line = $self->{fh}->getline;
+ last unless defined $line;
+ $bracelevel =
+ $bracelevel + ( $line =~ tr/\{/\{/ ) - ( $line =~ tr/\}/\}/ );
+ $_ .= $line;
+ pos($_) = $position;
+ }
+
+ # Remember text before the entry
+ my $pre = substr($_, 0, $start_pos-1);
+ if ($start_pos == 0) {
+ $pre = '';
+ }
+ $current_entry->pre($pre);
+
+
+ # Remember raw bibtex code
+ my $raw = substr($_, $start_pos);
+ $raw =~ s/^\s+//;
+ $raw =~ s/\s+$//;
+ $current_entry->raw_bibtex($raw);
+
+ my $pos = pos $_;
+ tr/\n/ /;
+ pos($_) = $pos;
+
+ if ( $type eq "STRING" ) {
+ if (/\G\{\s*($re_name)\s*=\s*/cgo) {
+ my $key = $1;
+ my $value = _parse_string( $self->{strings} );
+ if ( defined $self->{strings}->{$key} ) {
+ warn("Redefining string $key!");
+ }
+ $self->{strings}->{$key} = $value;
+ /\G[\s\n]*\}/cg;
+ } else {
+ $current_entry->error("Malformed string!");
+ return $current_entry;
+ }
+ } elsif ( $type eq "COMMENT" or $type eq "PREAMBLE" ) {
+ /\G\{./cgo;
+ _slurp_close_bracket;
+ } else { # normal entry
+ $current_entry->parse_ok(1);
+
+ # parse key
+ if (/\G\s*\{(?:\s*($re_name)\s*,[\s\n]*|\s+\r?\s*)/cgo) {
+ $current_entry->key($1);
+
+ # fields
+ while (/\G[\s\n]*($re_name)[\s\n]*=[\s\n]*/cgo) {
+ $current_entry->field(
+ $1 => _parse_string( $self->{strings} ) );
+ my $idx = index( $_, ',', pos($_) );
+ pos($_) = $idx + 1 if $idx > 0;
+ }
+
+ return $current_entry;
+
+ } else {
+
+ $current_entry->error("Malformed entry (key contains illegal characters) at " . substr($_, pos($_) || 0, 20) . ", ignoring");
+ _slurp_close_bracket;
+ return $current_entry;
+ }
+ }
+
+ $self->{buffer} = substr $_, pos($_);
+
+ } else {
+ $current_entry->error("Did not find type at " . substr($_, pos($_) || 0, 20));
+ return $current_entry;
+ }
+
+ }
+}
+
+
+sub next {
+ my $self = shift;
+
+ return $self->_parse_next;
+}
+
+# slurp everything till the next closing brace. Handles
+# nested brackets
+sub _slurp_close_bracket {
+ my $bracelevel = 0;
+ BRACE: {
+ /\G[^\}]*\{/cg && do { $bracelevel++; redo BRACE };
+ /\G[^\{]*\}/cg
+ && do {
+ if ( $bracelevel > 0 ) {
+ $bracelevel--;
+ redo BRACE;
+ } else {
+ return;
+ }
+ }
+ }
+}
+
+# parse bibtex string in $_ and return. A BibTeX string is either enclosed
+# in double quotes '"' or matching braces '{}'. The braced form may contain
+# nested braces.
+sub _parse_string {
+ my $strings_ref = shift;
+
+ my $value = "";
+
+ PART: {
+ if (/\G(\d+)/cg) {
+ $value .= $1;
+ } elsif (/\G($re_name)/cgo) {
+ warn("Using undefined string $1") unless defined $strings_ref->{$1};
+ $value .= $strings_ref->{$1} || "";
+ } elsif (/\G"(([^"\\]*(\\.)*[^\\"]*)*)"/cgs)
+ { # quoted string with embeded escapes
+ $value .= $1;
+ } else {
+ my $part = _extract_bracketed( $_ );
+ $value .= substr $part, 1, length($part) - 2; # strip quotes
+ }
+
+ if (/\G\s*#\s*/cg) { # string concatenation by #
+ redo PART;
+ }
+ }
+ $value =~ s/[\s\n]+/ /g;
+ return $value;
+}
+
+sub _extract_bracketed
+{
+ for($_[0]) # alias to $_
+ {
+ /\G\s+/cg;
+ my $start = pos($_);
+ my $depth = 0;
+ while(1)
+ {
+ /\G\\./cg && next;
+ /\G\{/cg && (++$depth, next);
+ /\G\}/cg && (--$depth > 0 ? next : last);
+ /\G([^\\\{\}]+)/cg && next;
+ last; # end of string
+ }
+ return substr($_, $start, pos($_)-$start);
+ }
+}
+
+# Split the $string using $pattern as a delimiter with
+# each part having balanced braces (so "{$pattern}"
+# does NOT split).
+# Return empty list if unmatched braces
+
+sub _split_braced_string {
+ my $string = shift;
+ my $pattern = shift;
+ my @tokens;
+ return () if $string eq '';
+ my $buffer;
+ while (!defined pos $string || pos $string < length $string) {
+ if ( $string =~ /\G(.*?)(\{|$pattern)/cgi ) {
+ my $match = $1;
+ if ( $2 =~ /$pattern/i ) {
+ $buffer .= $match;
+ push @tokens, $buffer;
+ $buffer = "";
+ } elsif ( $2 =~ /\{/ ) {
+ $buffer .= $match . "{";
+ my $numbraces=1;
+ while ($numbraces !=0 && pos $string < length $string) {
+ my $symbol = substr($string, pos $string, 1);
+ $buffer .= $symbol;
+ if ($symbol eq '{') {
+ $numbraces ++;
+ } elsif ($symbol eq '}') {
+ $numbraces --;
+ }
+ pos($string) ++;
+ }
+ if ($numbraces != 0) {
+ return ();
+ }
+ } else {
+ $buffer .= $match;
+ }
+ } else {
+ $buffer .= substr $string, (pos $string || 0);
+ last;
+ }
+ }
+ push @tokens, $buffer if $buffer;
+ return @tokens;
+}
+
+
+1; # End of BibTeX::Parser
+
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Parser - A pure perl BibTeX parser
+
+
+=head1 SYNOPSIS
+
+Parses BibTeX files.
+
+ use BibTeX::Parser;
+ use IO::File;
+
+ my $fh = IO::File->new("filename");
+
+ # Create parser object ...
+ my $parser = BibTeX::Parser->new($fh);
+
+ # ... and iterate over entries
+ while (my $entry = $parser->next ) {
+ if ($entry->parse_ok) {
+ my $type = $entry->type;
+ my $title = $entry->field("title");
+
+ my @authors = $entry->author;
+ # or:
+ my @editors = $entry->editor;
+
+ foreach my $author (@authors) {
+ print $author->first . " "
+ . $author->von . " "
+ . $author->last . ", "
+ . $author->jr;
+ }
+ } else {
+ warn "Error parsing file: " . $entry->error;
+ }
+ }
+
+
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Creates new parser object.
+
+Parameters:
+
+ * fh: A filehandle
+
+=head2 next
+
+Returns the next parsed entry or undef.
+
+=head1 NOTES
+
+The fields C<author> and C<editor> are canonized, see
+L<BibTeX::Parser::Author>
+
+
+=head1 SEE ALSO
+
+=over 4
+
+=item
+
+L<BibTeX::Parser::Entry>
+
+=item
+
+L<BibTeX::Parser::Author>
+
+=back
+
+=head1 VERSION
+
+version 1.02
+
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013-2016 by Gerhard Gossen and Boris Veytsman
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Author.pm b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Author.pm
new file mode 100644
index 0000000000..7d5274d1d7
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Author.pm
@@ -0,0 +1,412 @@
+package BibTeX::Parser::Author;
+{
+ $BibTeX::Parser::Author::VERSION = '1.02';
+}
+
+use warnings;
+use strict;
+
+use BibTeX::Parser;
+
+
+use overload
+ '""' => \&to_string;
+
+
+
+sub new {
+ my $class = shift;
+
+ if (@_) {
+ my $self = [ $class->split(@_) ];
+ return bless $self, $class;
+ } else {
+ return bless [], $class;
+ }
+}
+
+sub _get_or_set_field {
+ my ($self, $field, $value) = @_;
+ if (defined $value) {
+ $self->[$field] = $value;
+ } else {
+ return $self->[$field];
+ }
+}
+
+
+sub first {
+ shift->_get_or_set_field(0, @_);
+}
+
+
+sub von {
+ shift->_get_or_set_field(1, @_);
+}
+
+
+sub last {
+ shift->_get_or_set_field(2, @_);
+}
+
+
+sub jr {
+ shift->_get_or_set_field(3, @_);
+}
+
+
+# Take a string and create an array [first, von, last, jr]
+sub split {
+ my ($self_or_class, $name) = @_;
+
+ # remove whitespace at start and end of string
+ $name =~ s/^\s*(.*)\s*$/$1/s;
+
+
+
+ if (!length($name)) {
+ return (undef, undef, undef, undef);
+ }
+
+ my @comma_separated =
+ BibTeX::Parser::_split_braced_string($name,
+ '\s*,\s*');
+ if (scalar(@comma_separated) == 0) {
+ # Error?
+ return (undef, undef, undef, undef);
+ }
+
+ my $first=undef;
+ my $von=undef;
+ my $last=undef;
+ my $jr=undef;
+
+ if (scalar(@comma_separated) == 1) {
+ # First von Last form
+ my @tokens =
+ BibTeX::Parser::_split_braced_string($name, '\s+');
+ if (!scalar (@tokens)) {
+ return (undef, undef, undef, undef);
+ }
+ my ($start_von, $start_last) = _getStartVonLast (@tokens);
+ if ($start_von >0) {
+ $first = join(' ', splice(@tokens,0,$start_von));
+ }
+ if (($start_last-$start_von) >0) {
+ $von = join(' ', splice(@tokens,0,$start_last-$start_von));
+ }
+ $last = join(' ',@tokens);
+ return ($first, $von, $last, $jr);
+ }
+ # Now we work with von Last, [Jr,] First form
+ if (scalar @comma_separated == 2) { # no jr
+ my @tokens=
+ BibTeX::Parser::_split_braced_string($comma_separated[1], '\s+');
+ $first = join(' ', @tokens);
+ } else { # jr is present
+ my @tokens=
+ BibTeX::Parser::_split_braced_string($comma_separated[1], '\s+');
+ $jr = join(' ', @tokens);
+ @tokens=
+ BibTeX::Parser::_split_braced_string($comma_separated[2], '\s+');
+ $first = join(' ', @tokens);
+ }
+ my @tokens =
+ BibTeX::Parser::_split_braced_string($comma_separated[0], '\s+');
+ my $start_last = _getStartLast(@tokens);
+ if ($start_last > 0) {
+ $von=join(' ', splice(@tokens,0,$start_last));
+ }
+ $last = join(' ',@tokens);
+ return ($first, $von, $last, $jr);
+
+}
+
+# Return the index of the first von element and the first lastname
+# element. If no von element, von=last
+
+sub _getStartVonLast {
+ my $length=scalar(@_);
+ if ($length==1) {
+ return (0,0);
+ }
+ my $start_von=-1;
+ my $start_last=$length-1;
+ for (my $i=0; $i<$length; $i++) {
+ if (_is_von_token($_[$i])) {
+ $start_von=$i;
+ last;
+ }
+ }
+ if ($start_von== -1) { # no von part
+ return($length-1, $length-1);
+ }
+ if ($start_von== $length-1) { # all parts but last are upper case?
+ return($length-1, $length-1);
+ }
+ for (my $i=$start_von+1; $i<$length; $i++) {
+ if (!_is_von_token($_[$i])) {
+ $start_last=$i;
+ last;
+ }
+ }
+ return($start_von, $start_last);
+}
+
+
+# Return the index of the first lastname
+# element provided no first name elements are present
+
+sub _getStartLast {
+ my $length=scalar(@_);
+ if ($length==1) {
+ return 0;
+ }
+ my $start_last=$length-1;
+ for (my $i=0; $i<$length; $i++) {
+ if (!_is_von_token($_[$i])) {
+ $start_last=$i;
+ last;
+ }
+ }
+ return $start_last;
+}
+
+
+sub _split_name_parts {
+ my $name = shift;
+
+ if ( $name !~ /\{/ ) {
+ return split /\s+/, $name;
+ } else {
+ my @parts;
+ my $cur_token = '';
+ while ( scalar( $name =~ /\G ( [^\s\{]* ) ( \s+ | \{ | \s* $ ) /xgc ) ) {
+ $cur_token .= $1;
+ if ( $2 =~ /\{/ ) {
+ if ( scalar( $name =~ /\G([^\}]*)\}/gc ) ) {
+ $cur_token .= "{$1}";
+ } else {
+ die "Unmatched brace in name '$name'";
+ }
+ } else {
+ if ( $cur_token =~ /^{(.*)}$/ ) {
+ $cur_token = $1;
+ }
+ push @parts, $cur_token;
+ $cur_token = '';
+ }
+ }
+ return @parts;
+ }
+
+}
+
+
+sub _get_single_author_from_tokens {
+ my (@tokens) = @_;
+ if (@tokens == 0) {
+ return (undef, undef, undef, undef);
+ } elsif (@tokens == 1) { # name without comma
+ if ( $tokens[0] =~ /(^|\s)[[:lower:]]/) { # name has von part or has only lowercase names
+ my @name_parts = _split_name_parts $tokens[0];
+
+ my $first;
+ while (@name_parts && ucfirst($name_parts[0]) eq $name_parts[0] ) {
+ $first .= $first ? ' ' . shift @name_parts : shift @name_parts;
+ }
+
+ my $von;
+ # von part are lowercase words
+ while ( @name_parts && lc($name_parts[0]) eq $name_parts[0] ) {
+ $von .= $von ? ' ' . shift @name_parts : shift @name_parts;
+ }
+
+ if (@name_parts) {
+ return ($first, $von, join(" ", @name_parts), undef);
+ } else {
+ return (undef, undef, $tokens[0], undef);
+ }
+ } else {
+ if ( $tokens[0] !~ /\{/ && $tokens[0] =~ /^((.*)\s+)?\b(\S+)$/) {
+ return ($2, undef, $3, undef);
+ } else {
+ my @name_parts = _split_name_parts $tokens[0];
+ return ($name_parts[0], undef, $name_parts[1], undef);
+ }
+ }
+
+ } elsif (@tokens == 2) {
+ my @von_last_parts = _split_name_parts $tokens[0];
+ my $von;
+ # von part are lowercase words
+ while ( @von_last_parts && lc($von_last_parts[0]) eq $von_last_parts[0] ) {
+ $von .= $von ? ' ' . shift @von_last_parts : shift @von_last_parts;
+ }
+ return ($tokens[1], $von, join(" ", @von_last_parts), undef);
+ } else {
+ my @von_last_parts = _split_name_parts $tokens[0];
+ my $von;
+ # von part are lowercase words
+ while ( @von_last_parts && lc($von_last_parts[0]) eq $von_last_parts[0] ) {
+ $von .= $von ? ' ' . shift @von_last_parts : shift @von_last_parts;
+ }
+ return ($tokens[2], $von, join(" ", @von_last_parts), $tokens[1]);
+ }
+
+}
+
+
+
+
+sub to_string {
+ my $self = shift;
+
+ if ($self->jr) {
+ return ($self->von ? $self->von . " " : '') . " " . $self->last . ", " . $self->jr . ", " . $self->first;
+ } else {
+ return ($self->von ? $self->von . " " : '') . $self->last . ($self->first ? ", " . $self->first : '');
+ }
+}
+
+
+# Return 1 if the first letter on brace level 0 is lowercase
+sub _is_von_token {
+ my $string = shift;
+ while ($string =~
+ s/^(\\[[:alpha:]]+\{|\{|\\[[:^alpha:]]?|[[:^alpha:]])//) {
+ if ($1 eq '{' ) {
+ my $numbraces=1;
+ while ($numbraces !=0 && length($string)) {
+ my $symbol = substr($string, 0, 1);
+ if ($symbol eq '{') {
+ $numbraces ++;
+ } elsif ($symbol eq '}') {
+ $numbraces --;
+ }
+ $string = substr($string,1);
+ }
+ }
+ }
+
+ if (length $string ) {
+ my $symbol = substr($string, 0, 1);
+ if (lc($symbol) eq $symbol) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ return 1;
+ }
+
+}
+
+1; # End of BibTeX::Entry
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Author - Contains a single author for a BibTeX document.
+
+=head1 SYNOPSIS
+
+This class ist a wrapper for a single BibTeX author. It is usually created
+by a BibTeX::Parser.
+
+ use BibTeX::Parser::Author;
+
+ my $entry = BibTeX::Parser::Author->new($full_name);
+
+ my $firstname = $author->first;
+ my $von = $author->von;
+ my $last = $author->last;
+ my $jr = $author->jr;
+
+ # or ...
+
+ my ($first, $von, $last, $jr) = BibTeX::Author->split($fullname);
+
+
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Create new author object. Expects full name as parameter.
+
+=head2 first
+
+Set or get first name(s).
+
+=head2 von
+
+Set or get 'von' part of name.
+
+=head2 last
+
+Set or get last name(s).
+
+=head2 jr
+
+Set or get 'jr' part of name.
+
+=head2 split
+
+Split name into (firstname, von part, last name, jr part). Returns array
+with four strings, some of them possibly empty.
+
+=head2 to_string
+
+Return string representation of the name.
+
+=head1 NOTES
+
+BibTeX allows three representations of a person's name:
+
+=over 4
+
+=item 1.
+
+First von Last
+
+=item 2.
+
+von Last, First
+
+=item 3.
+
+von Last, Jr, First
+
+=back
+
+The module always converts the first form to the second of third one
+to allow simple string comparisons.
+
+The algorithm to determine the von part is the following: von part
+consists of tokens where the first letter at brace level 0 is in lower case.
+Anything in a "special characters" is on brace level 0. Thus the following
+tokens are considered von parts: C<von>, C<\NOOP{von}Von>, and
+the following token is not: C<{von}>
+
+=head1 VERSION
+
+version 1.02
+
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013--2016 by Gerhard Gossen and Boris Veytsman.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Entry.pm b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Entry.pm
new file mode 100644
index 0000000000..2b8fe76220
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/lib/BibTeX/Parser/Entry.pm
@@ -0,0 +1,433 @@
+package BibTeX::Parser::Entry;
+{
+ $BibTeX::Parser::Entry::VERSION = '1.02';
+}
+
+use warnings;
+use strict;
+
+use BibTeX::Parser;
+use BibTeX::Parser::Author;
+
+
+
+sub new {
+ my ($class, $type, $key, $parse_ok, $fieldsref) = @_;
+
+ my %fields = defined $fieldsref ? %$fieldsref : ();
+ my $i=0;
+ foreach my $field (keys %fields) {
+ if ($field !~ /^_/) {
+ $fields{_fieldnums}->{$field}=$i;
+ $i++;
+ }
+ }
+ if (defined $type) {
+ $fields{_type} = uc($type);
+ }
+ $fields{_key} = $key;
+ $fields{_parse_ok} = $parse_ok;
+ $fields{_raw} = '';
+ return bless \%fields, $class;
+}
+
+
+
+sub parse_ok {
+ my $self = shift;
+ if (@_) {
+ $self->{_parse_ok} = shift;
+ }
+ $self->{_parse_ok};
+}
+
+
+sub error {
+ my $self = shift;
+ if (@_) {
+ $self->{_error} = shift;
+ $self->parse_ok(0);
+ }
+ return $self->parse_ok ? undef : $self->{_error};
+}
+
+
+sub type {
+ if (scalar @_ == 1) {
+ # get
+ my $self = shift;
+ return $self->{_type};
+ } else {
+ # set
+ my ($self, $newval) = @_;
+ $self->{_type} = uc($newval);
+ }
+}
+
+
+sub key {
+ if (scalar @_ == 1) {
+ # get
+ my $self = shift;
+ return $self->{_key};
+ } else {
+ # set
+ my ($self, $newval) = @_;
+ $self->{_key} = $newval;
+ }
+
+}
+
+
+sub field {
+ if (scalar @_ == 2) {
+ # get
+ my ($self, $field) = @_;
+ return $self->{ lc( $field ) };
+ } else {
+ my ($self, $key, $value) = @_;
+ my $field = lc ($key);
+ $self->{$field} = $value; #_sanitize_field($value);
+ if (!exists($self->{_fieldnums}->{$field})) {
+ my $num = scalar keys %{$self->{_fieldnums}};
+ $self->{_fieldnums}->{$field} = $num;
+ }
+ }
+
+}
+
+use LaTeX::ToUnicode qw( convert );
+
+
+sub cleaned_field {
+ my ( $self, $field, @options ) = @_;
+ if ( $field =~ /author|editor/i ) {
+ return $self->field( $field );
+ } else {
+ return convert( $self->field( lc $field ), @options );
+ }
+}
+
+
+sub cleaned_author {
+ my $self = shift;
+ $self->_handle_cleaned_author_editor( [ $self->author ], @_ );
+}
+
+
+sub cleaned_editor {
+ my $self = shift;
+ $self->_handle_cleaned_author_editor( [ $self->editor ], @_ );
+}
+
+sub _handle_cleaned_author_editor {
+ my ( $self, $authors, @options ) = @_;
+ map {
+ my $author = $_;
+ my $new_author = BibTeX::Parser::Author->new;
+ map {
+ $new_author->$_( convert( $author->$_, @options ) )
+ } grep { defined $author->$_ } qw( first von last jr );
+ $new_author;
+ } @$authors;
+}
+
+no LaTeX::ToUnicode;
+
+sub _handle_author_editor {
+ my $type = shift;
+ my $self = shift;
+ if (@_) {
+ if (@_ == 1) { #single string
+ # my @names = split /\s+and\s+/i, $_[0];
+ $_[0] =~ s/^\s*//;
+ $_[0] =~ s/\s*$//;
+ my @names = BibTeX::Parser::_split_braced_string($_[0],
+ '\s+and\s+');
+ if (!scalar @names) {
+ $self->error('Bad names in author/editor field');
+ return;
+ }
+ $self->{"_$type"} = [map {new BibTeX::Parser::Author $_} @names];
+ $self->field($type, join " and ", @{$self->{"_$type"}});
+ } else {
+ $self->{"_$type"} = [];
+ foreach my $param (@_) {
+ if (ref $param eq "BibTeX::Author") {
+ push @{$self->{"_$type"}}, $param;
+ } else {
+ push @{$self->{"_$type"}}, new BibTeX::Parser::Author $param;
+ }
+
+ $self->field($type, join " and ", @{$self->{"_$type"}});
+ }
+ }
+ } else {
+ unless ( defined $self->{"_$type"}) {
+ my @names = BibTeX::Parser::_split_braced_string($self->{$type} || "", '\s+and\s+' );
+ $self->{"_$type"} = [map {new BibTeX::Parser::Author $_} @names];
+ }
+ return @{$self->{"_$type"}};
+ }
+}
+
+
+
+sub author {
+ _handle_author_editor('author', @_);
+}
+
+
+sub editor {
+ _handle_author_editor('editor', @_);
+}
+
+
+sub fieldlist {
+ my $self = shift;
+
+ return grep {!/^_/} keys %$self;
+}
+
+
+sub has {
+ my ($self, $field) = @_;
+
+ return defined $self->{$field};
+}
+
+sub _sanitize_field {
+ my $value = shift;
+ for ($value) {
+ tr/\{\}//d;
+ s/\\(?!=[ \\])//g;
+ s/\\\\/\\/g;
+ }
+ return $value;
+}
+
+
+
+sub raw_bibtex {
+ my $self = shift;
+ if (@_) {
+ $self->{_raw} = shift;
+ }
+ return $self->{_raw};
+}
+
+sub pre {
+ my $self = shift;
+ if (@_) {
+ $self->{_pre} = shift;
+ }
+ return $self->{_pre};
+}
+
+
+sub to_string {
+ my $self = shift;
+ my %options=@_;
+ if (!exists($options{canonize_names})) {
+ $options{canonize_names}=1;
+ }
+ my @fields = grep {!/^_/} keys %$self;
+ @fields = sort {
+ $self->{_fieldnums}->{$a} <=>
+ $self->{_fieldnums}->{$b}} @fields;
+ my $result = '';
+ if ($options{print_pre}) {
+ $result .= $self->pre()."\n";
+ }
+ my $type = $self->type;
+ if (exists($options{type_capitalization})) {
+ if ($options{type_capitalization} eq 'Lowercase') {
+ $type = lc $type;
+ }
+ if ($options{type_capitalization} eq 'Titlecase') {
+ $type = ucfirst lc $type;
+ }
+ }
+ $result .= '@'.$type."{".$self->key.",\n";
+ foreach my $field (@fields) {
+ my $value = $self->field($field);
+ if ($field eq 'author' && $options{canonize_names}) {
+ my @names = ($self->author);
+ $value = join(' and ', @names);
+ }
+ if ($field eq 'editor' && $options{canonize_names}) {
+ my @names = ($self->editor);
+ $value = join(' and ', @names);
+ }
+ if (exists($options{field_capitalization})) {
+ if ($options{field_capitalization} eq 'Uppercase') {
+ $field = uc $field;
+ }
+ if ($options{field_capitalization} eq 'Titlecase') {
+ $field = ucfirst $field;
+ }
+ }
+ $result .= " $field = {"."$value"."},\n";
+ }
+ $result .= "}";
+ return $result;
+}
+
+1; # End of BibTeX::Entry
+
+__END__
+=pod
+
+=head1 NAME
+
+BibTeX::Parser::Entry - Contains a single entry of a BibTeX document.
+
+=head1 SYNOPSIS
+
+This class ist a wrapper for a single BibTeX entry. It is usually created
+by a BibTeX::Parser.
+
+ use BibTeX::Parser::Entry;
+
+ my $entry = BibTeX::Parser::Entry->new($type, $key, $parse_ok, \%fields);
+
+ if ($entry->parse_ok) {
+ my $type = $entry->type;
+ my $key = $enty->key;
+ print $entry->field("title");
+ my @authors = $entry->author;
+ my @editors = $entry->editor;
+
+ ...
+
+ print $entry->to_string;
+ }
+
+
+
+
+
+=head1 FUNCTIONS
+
+=head2 new
+
+Create new entry.
+
+=head2 parse_ok
+
+If the entry was correctly parsed, this method returns a true value, false otherwise.
+
+=head2 error
+
+Return the error message, if the entry could not be parsed or undef otherwise.
+
+=head2 type
+
+Get or set the type of the entry, eg. 'ARTICLE' or 'BOOK'. Return value is
+always uppercase.
+
+=head2 key
+
+Get or set the reference key of the entry.
+
+=head2 field($name [, $value])
+
+Get or set the contents of a field. The first parameter is the name of the
+field, the second (optional) value is the new value.
+
+=head2 cleaned_field($name)
+
+Retrieve the contents of a field in a format that is cleaned of TeX markup.
+
+=head2 cleaned_author
+
+Get an array of L<BibTeX::Parser::Author> objects for the authors of this
+entry. Each name has been cleaned of accents and braces.
+
+=head2 cleaned_editor
+
+Get an array of L<BibTeX::Parser::Author> objects for the editors of this
+entry. Each name has been cleaned of accents and braces.
+
+=head2 author([@authors])
+
+Get or set the authors. Returns an array of L<BibTeX::Author|BibTeX::Author>
+objects. The parameters can either be L<BibTeX::Author|BibTeX::Author> objects
+or strings.
+
+Note: You can also change the authors with $entry->field('author', $authors_string)
+
+=head2 editor([@editors])
+
+Get or set the editors. Returns an array of L<BibTeX::Author|BibTeX::Author>
+objects. The parameters can either be L<BibTeX::Author|BibTeX::Author> objects
+or strings.
+
+Note: You can also change the authors with $entry->field('editor', $editors_string)
+
+=head2 fieldlist ()
+
+Returns a list of all the fields used in this entry.
+
+=head2 has($fieldname)
+
+Returns a true value if this entry has a value for $fieldname.
+
+=head2 pre ()
+
+Return the text in BibTeX file before the entry
+
+=head2 raw_bibtex ()
+
+Return raw BibTeX entry (if available).
+
+=head2 to_string ([options])
+
+Returns a text of the BibTeX entry in BibTeX format. Options are
+a hash.
+
+=over 4
+
+=item C<canonize_names>
+
+If true (the default), authors' and editors'
+names are translated into canonical bibtex form. The command
+C<$entry-E<gt>to_string(canonize_names=E<gt>0)> overrides this behavior.
+
+=item C<field_capitalization>
+
+Capitalization of the field names.
+Can take values 'Uppercase', 'Lowercase' (the default) or 'Titlecase'
+
+=item C<print_pre>
+
+False by default. If true, the text in the Bib file before the
+entry is printed. Note that at present we assume the text
+before the entry NEVER has the @ symbol inside
+
+=item C<type_capitalization>
+
+Capitalization of the type names.
+Can take values 'Uppercase' (the default), 'Lowercase' or 'Titlecase'
+
+
+=back
+
+=head1 VERSION
+
+version 1.02
+
+=head1 AUTHOR
+
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2013-2016 by Gerhard Gossen and Boris Veytsman
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser.3pm b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser.3pm
new file mode 100644
index 0000000000..d6fe7d17b4
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser.3pm
@@ -0,0 +1,213 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "BibTeX::Parser 3"
+.TH BibTeX::Parser 3 "2017-12-09" "perl v5.18.2" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+BibTeX::Parser \- A pure perl BibTeX parser
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+Parses BibTeX files.
+.PP
+.Vb 2
+\& use BibTeX::Parser;
+\& use IO::File;
+\&
+\& my $fh = IO::File\->new("filename");
+\&
+\& # Create parser object ...
+\& my $parser = BibTeX::Parser\->new($fh);
+\&
+\& # ... and iterate over entries
+\& while (my $entry = $parser\->next ) {
+\& if ($entry\->parse_ok) {
+\& my $type = $entry\->type;
+\& my $title = $entry\->field("title");
+\&
+\& my @authors = $entry\->author;
+\& # or:
+\& my @editors = $entry\->editor;
+\&
+\& foreach my $author (@authors) {
+\& print $author\->first . " "
+\& . $author\->von . " "
+\& . $author\->last . ", "
+\& . $author\->jr;
+\& }
+\& } else {
+\& warn "Error parsing file: " . $entry\->error;
+\& }
+\& }
+.Ve
+.SH "FUNCTIONS"
+.IX Header "FUNCTIONS"
+.SS "new"
+.IX Subsection "new"
+Creates new parser object.
+.PP
+Parameters:
+.PP
+.Vb 1
+\& * fh: A filehandle
+.Ve
+.SS "next"
+.IX Subsection "next"
+Returns the next parsed entry or undef.
+.SH "NOTES"
+.IX Header "NOTES"
+The fields \f(CW\*(C`author\*(C'\fR and \f(CW\*(C`editor\*(C'\fR are canonized, see
+BibTeX::Parser::Author
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+.IP "\(bu" 4
+BibTeX::Parser::Entry
+.IP "\(bu" 4
+BibTeX::Parser::Author
+.SH "VERSION"
+.IX Header "VERSION"
+version 1.01
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+.SH "COPYRIGHT AND LICENSE"
+.IX Header "COPYRIGHT AND LICENSE"
+This software is copyright (c) 2013\-2016 by Gerhard Gossen and Boris Veytsman
+.PP
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
diff --git a/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Author.3pm b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Author.3pm
new file mode 100644
index 0000000000..33d0126d32
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Author.3pm
@@ -0,0 +1,216 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "BibTeX::Parser::Author 3"
+.TH BibTeX::Parser::Author 3 "2017-12-09" "perl v5.18.2" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+BibTeX::Author \- Contains a single author for a BibTeX document.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+This class ist a wrapper for a single BibTeX author. It is usually created
+by a BibTeX::Parser.
+.PP
+.Vb 1
+\& use BibTeX::Parser::Author;
+\&
+\& my $entry = BibTeX::Parser::Author\->new($full_name);
+\&
+\& my $firstname = $author\->first;
+\& my $von = $author\->von;
+\& my $last = $author\->last;
+\& my $jr = $author\->jr;
+\&
+\& # or ...
+\&
+\& my ($first, $von, $last, $jr) = BibTeX::Author\->split($fullname);
+.Ve
+.SH "FUNCTIONS"
+.IX Header "FUNCTIONS"
+.SS "new"
+.IX Subsection "new"
+Create new author object. Expects full name as parameter.
+.SS "first"
+.IX Subsection "first"
+Set or get first name(s).
+.SS "von"
+.IX Subsection "von"
+Set or get 'von' part of name.
+.SS "last"
+.IX Subsection "last"
+Set or get last name(s).
+.SS "jr"
+.IX Subsection "jr"
+Set or get 'jr' part of name.
+.SS "split"
+.IX Subsection "split"
+Split name into (firstname, von part, last name, jr part). Returns array
+with four strings, some of them possibly empty.
+.SS "to_string"
+.IX Subsection "to_string"
+Return string representation of the name.
+.SH "NOTES"
+.IX Header "NOTES"
+BibTeX allows three representations of a person's name:
+.IP "1." 4
+First von Last
+.IP "2." 4
+von Last, First
+.IP "3." 4
+von Last, Jr, First
+.PP
+The module always converts the first form to the second of third one
+to allow simple string comparisons.
+.PP
+The algorithm to determine the von part is the following: von part
+consists of tokens where the first letter at brace level 0 is in lower case.
+Anything in a \*(L"special characters\*(R" is on brace level 0. Thus the following
+tokens are considered von parts: \f(CW\*(C`von\*(C'\fR, \f(CW\*(C`\eNOOP{von}Von\*(C'\fR, and
+the following token is not: \f(CW\*(C`{von}\*(C'\fR
+.SH "VERSION"
+.IX Header "VERSION"
+version 1.01
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+.SH "COPYRIGHT AND LICENSE"
+.IX Header "COPYRIGHT AND LICENSE"
+This software is copyright (c) 2013\-\-2016 by Gerhard Gossen and Boris Veytsman.
+.PP
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
diff --git a/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Entry.3pm b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Entry.3pm
new file mode 100644
index 0000000000..c91647d554
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/man/man3/BibTeX::Parser::Entry.3pm
@@ -0,0 +1,263 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+. if \nF \{
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "BibTeX::Parser::Entry 3"
+.TH BibTeX::Parser::Entry 3 "2017-12-09" "perl v5.18.2" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+BibTeX::Parser::Entry \- Contains a single entry of a BibTeX document.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+This class ist a wrapper for a single BibTeX entry. It is usually created
+by a BibTeX::Parser.
+.PP
+.Vb 1
+\& use BibTeX::Parser::Entry;
+\&
+\& my $entry = BibTeX::Parser::Entry\->new($type, $key, $parse_ok, \e%fields);
+\&
+\& if ($entry\->parse_ok) {
+\& my $type = $entry\->type;
+\& my $key = $enty\->key;
+\& print $entry\->field("title");
+\& my @authors = $entry\->author;
+\& my @editors = $entry\->editor;
+\&
+\& ...
+\&
+\& print $entry\->to_string;
+\& }
+.Ve
+.SH "FUNCTIONS"
+.IX Header "FUNCTIONS"
+.SS "new"
+.IX Subsection "new"
+Create new entry.
+.SS "parse_ok"
+.IX Subsection "parse_ok"
+If the entry was correctly parsed, this method returns a true value, false otherwise.
+.SS "error"
+.IX Subsection "error"
+Return the error message, if the entry could not be parsed or undef otherwise.
+.SS "type"
+.IX Subsection "type"
+Get or set the type of the entry, eg. '\s-1ARTICLE\s0' or '\s-1BOOK\s0'. Return value is
+always uppercase.
+.SS "key"
+.IX Subsection "key"
+Get or set the reference key of the entry.
+.ie n .SS "field($name [, $value])"
+.el .SS "field($name [, \f(CW$value\fP])"
+.IX Subsection "field($name [, $value])"
+Get or set the contents of a field. The first parameter is the name of the
+field, the second (optional) value is the new value.
+.SS "cleaned_field($name)"
+.IX Subsection "cleaned_field($name)"
+Retrieve the contents of a field in a format that is cleaned of TeX markup.
+.SS "cleaned_author"
+.IX Subsection "cleaned_author"
+Get an array of BibTeX::Parser::Author objects for the authors of this
+entry. Each name has been cleaned of accents and braces.
+.SS "cleaned_editor"
+.IX Subsection "cleaned_editor"
+Get an array of BibTeX::Parser::Author objects for the editors of this
+entry. Each name has been cleaned of accents and braces.
+.SS "author([@authors])"
+.IX Subsection "author([@authors])"
+Get or set the authors. Returns an array of BibTeX::Author
+objects. The parameters can either be BibTeX::Author objects
+or strings.
+.PP
+Note: You can also change the authors with \f(CW$entry\fR\->field('author', \f(CW$authors_string\fR)
+.SS "editor([@editors])"
+.IX Subsection "editor([@editors])"
+Get or set the editors. Returns an array of BibTeX::Author
+objects. The parameters can either be BibTeX::Author objects
+or strings.
+.PP
+Note: You can also change the authors with \f(CW$entry\fR\->field('editor', \f(CW$editors_string\fR)
+.SS "fieldlist ()"
+.IX Subsection "fieldlist ()"
+Returns a list of all the fields used in this entry.
+.SS "has($fieldname)"
+.IX Subsection "has($fieldname)"
+Returns a true value if this entry has a value for \f(CW$fieldname\fR.
+.SS "pre ()"
+.IX Subsection "pre ()"
+Return the text in BibTeX file before the entry
+.SS "raw_bibtex ()"
+.IX Subsection "raw_bibtex ()"
+Return raw BibTeX entry (if available).
+.SS "to_string ([options])"
+.IX Subsection "to_string ([options])"
+Returns a text of the BibTeX entry in BibTeX format. Options are
+a hash.
+.ie n .IP """canonize_names""" 4
+.el .IP "\f(CWcanonize_names\fR" 4
+.IX Item "canonize_names"
+If true (the default), authors' and editors'
+names are translated into canonical bibtex form. The command
+\&\f(CW\*(C`$entry\->to_string(canonize_names=>0)\*(C'\fR overrides this behavior.
+.ie n .IP """field_capitalization""" 4
+.el .IP "\f(CWfield_capitalization\fR" 4
+.IX Item "field_capitalization"
+Capitalization of the field names.
+Can take values 'Uppercase', 'Lowercase' (the default) or 'Titlecase'
+.ie n .IP """print_pre""" 4
+.el .IP "\f(CWprint_pre\fR" 4
+.IX Item "print_pre"
+False by default. If true, the text in the Bib file before the
+entry is printed. Note that at present we assume the text
+before the entry \s-1NEVER\s0 has the @ symbol inside
+.ie n .IP """type_capitalization""" 4
+.el .IP "\f(CWtype_capitalization\fR" 4
+.IX Item "type_capitalization"
+Capitalization of the type names.
+Can take values 'Uppercase' (the default), 'Lowercase' or 'Titlecase'
+.SH "VERSION"
+.IX Header "VERSION"
+version 1.01
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Gerhard Gossen <gerhard.gossen@googlemail.com> and
+Boris Veytsman <boris@varphi.com>
+.SH "COPYRIGHT AND LICENSE"
+.IX Header "COPYRIGHT AND LICENSE"
+This software is copyright (c) 2013\-2016 by Gerhard Gossen and Boris Veytsman
+.PP
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
diff --git a/support/bibtexperllibs/BibTeX-Parser/notes b/support/bibtexperllibs/BibTeX-Parser/notes
new file mode 100644
index 0000000000..5e41df4090
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/notes
@@ -0,0 +1,26 @@
+from Biblio::Catalog::BibTeX :
+
+sub tex2html {
+ my $latex = shift;
+ return "" unless defined($latex);
+
+ for ($latex) {
+ s/\\textit\{([^{]+)\}/<i>$1<\/i>/g;
+ s/\\textbf\{([^{]+)\}/<b>$1<\/b>/g;
+ s/\\texttt\{([^{]+)\}/<tt>$1<\/tt>/g;
+ s/\\emph{([^{]+)}/<i>$1<\/i>/g;
+ s/\\item\b/<li>/g;
+ s/\\_/_/g;
+ s/\\mbox{([^}]+)}/$1/g;
+ s/{\\it\s([^}]+)}/<i>$1<\/i>/g;
+ s/\\LaTeX/LaTeX/g;
+ s/\\begin{itemize}/<ul>/g;
+ s/\\begin{quote}/<blockquote><i>/g;
+ s/\\end{quote}/<\/i><\/blockquote>/g;
+ s/\\end{itemize}/<\/ul>/g;
+ s/[}{]//g;
+ }
+
+ return $latex;
+}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/00-load.t b/support/bibtexperllibs/BibTeX-Parser/t/00-load.t
new file mode 100644
index 0000000000..9862dc7986
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/00-load.t
@@ -0,0 +1,11 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 3;
+
+BEGIN {
+ use_ok( 'BibTeX::Parser' );
+ use_ok( 'BibTeX::Parser::Author' );
+ use_ok( 'BibTeX::Parser::Entry' );
+}
+
+diag( "Testing BibTeX::Parser $BibTeX::Parser::VERSION, Perl $], $^X" );
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/01-parse.t b/support/bibtexperllibs/BibTeX-Parser/t/01-parse.t
new file mode 100644
index 0000000000..70e298d4be
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/01-parse.t
@@ -0,0 +1,36 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 11;
+
+use BibTeX::Parser;
+use IO::File;
+
+use constant ENTRIES => 1;
+
+my $fh = new IO::File "t/bibs/01.bib", "r" ;
+
+if (defined $fh) {
+ my $parser = new BibTeX::Parser $fh;
+
+ isa_ok($parser, "BibTeX::Parser");
+
+ my $count = 0;
+
+ while (my $entry = $parser->next) {
+ $count++;
+ isa_ok($entry, "BibTeX::Parser::Entry");
+ is($entry->key, "key01", "key");
+ is($entry->type, "ARTICLE", "type");
+ ok($entry->parse_ok, "parse_ok");
+ is($entry->field("year"), 1950, "field");
+ is($entry->field("month"), "January~1", "field");
+
+ my @authors = $entry->author;
+ is(scalar @authors, 2, "#authors");
+ isa_ok($authors[0], "BibTeX::Parser::Author");
+ is("$authors[0]", "Duck, Donald", "correct author");
+ }
+
+ is($count, ENTRIES, "number of entries");
+}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/02-parse_string.t b/support/bibtexperllibs/BibTeX-Parser/t/02-parse_string.t
new file mode 100644
index 0000000000..90b87eba14
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/02-parse_string.t
@@ -0,0 +1,39 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 7;
+
+use BibTeX::Parser;
+
+my %strings = ();
+
+$_ = 1234;
+parse_ok("parse digit string");
+
+$_ = '"simple double quoted string"';
+parse_is("simple double quoted string", "- double quoted string");
+
+$_ = '"double quotes { with embeded } brackets"';
+parse_is("double quotes { with embeded } brackets", "- with embeded brackets");
+
+$_ = '"string 1 " # "string 2"';
+parse_is("string 1 string 2", "- concatenation");
+
+$strings{test} = "string";
+$strings{other} = "text";
+
+$_ = "test";
+parse_is("string", "- string variable");
+
+$_ = "test # other";
+parse_is("stringtext", "- concatenation of string variables");
+
+$_ = '"M{\"{u}}nchen"';
+parse_is('M{\"{u}}nchen', "- escaped quote");
+
+sub parse_ok {
+ is(BibTeX::Parser::_parse_string(\%strings), $_, shift);
+}
+
+sub parse_is {
+ is(BibTeX::Parser::_parse_string(\%strings), shift, shift);
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/03-parse_entry.t b/support/bibtexperllibs/BibTeX-Parser/t/03-parse_entry.t
new file mode 100644
index 0000000000..6b4e4632bc
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/03-parse_entry.t
@@ -0,0 +1,102 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 3;
+
+use IO::String;
+use BibTeX::Parser;
+
+{
+ my $string = q|@article{lin1973,
+ author = "Shen Lin and Brian W. Kernighan",
+ title = "An Effective Heuristic Algorithm for the Travelling-Salesman Problem",
+ journal = "Operations Research",
+ volume = 21,
+ year = 1973,
+ pages = "498--516"
+ }|;
+ my $fh = IO::String->new($string);
+
+ my $parser = BibTeX::Parser->new( $fh );
+
+#my @result = BibTeX::Parser->_parse($fh);
+
+ my $entry = $parser->next;
+
+ is_deeply($entry, {_type => 'ARTICLE', _key => 'lin1973', author => "Shen Lin and Brian W. Kernighan",
+ title => "An Effective Heuristic Algorithm for the Travelling-Salesman Problem",
+ journal => "Operations Research",
+ volume => 21,
+ year => 1973,
+ pages => "498--516", _parse_ok => 1,
+ _fieldnums => {'author' => 0, 'title' => 1,
+ 'journal' => 2, 'volume' => 3,
+ 'year' => 4, 'pages' => 5},
+ _pre => '',
+ _raw => $string}, "parse \@ARTICLE");
+
+}
+{
+ my $string1 = q|@article{lin1973,
+ author = "Shen Lin and Brian W. Kernighan",
+ title = "An Effective Heuristic Algorithm for the Travelling-Salesman Problem",
+ journal = "Operations Research",
+ volume = 21,
+ year = 1973,
+ pages = "498--516"
+ }|;
+ my $string = "some
+text
+$string1";
+ my $fh = IO::String->new($string);
+
+ my $parser = BibTeX::Parser->new( $fh );
+
+#my @result = BibTeX::Parser->_parse($fh);
+
+ my $entry = $parser->next;
+
+ is_deeply($entry, {_type => 'ARTICLE', _key => 'lin1973', author => "Shen Lin and Brian W. Kernighan",
+ title => "An Effective Heuristic Algorithm for the Travelling-Salesman Problem",
+ journal => "Operations Research",
+ volume => 21,
+ year => 1973,
+ pages => "498--516", _parse_ok => 1,
+ _fieldnums => {'author' => 0, 'title' => 1,
+ 'journal' => 2, 'volume' => 3,
+ 'year' => 4, 'pages' => 5},
+ _pre => "some\ntext",
+ _raw => $string1}, "parse \@ARTICLE");
+
+}
+{
+ my $string = q|@InProceedings{Herper:2001:MVS,
+ author = {Henry Herper},
+ title = {{M}odellierung von {S}ystemen: ein
+ {A}pplikationsgebiet im {I}nformatikunterricht},
+ booktitle = {Informatikunterricht und Medienbildung, INFOS 2001
+ (9. Fachtagung Informatik und Schule, Paderborn
+ 17.-20- September 2001) -- Tagungsband},
+ editor = {Reinhard Keil-Slavik and Johannes Magenheim},
+ year = {2001},
+}|;
+ my $fh = IO::String->new($string);
+
+ my $parser = BibTeX::Parser->new( $fh );
+
+ my $entry = $parser->next;
+
+ is_deeply($entry, {
+ _type => 'INPROCEEDINGS',
+ _key => 'Herper:2001:MVS',
+ _fieldnums => {'author' => 0, 'title' => 1,
+ 'booktitle' => 2, 'editor' => 3,
+ 'year' => 4},
+ author => "Henry Herper",
+ title => "{M}odellierung von {S}ystemen: ein {A}pplikationsgebiet im {I}nformatikunterricht",
+ booktitle => "Informatikunterricht und Medienbildung, INFOS 2001 (9. Fachtagung Informatik und Schule, Paderborn 17.-20- September 2001) -- Tagungsband",
+ editor => "Reinhard Keil-Slavik and Johannes Magenheim",
+ year => 2001,
+ _parse_ok => 1,
+ _pre => '',
+ _raw => $string}, "parse \@ARTICLE");
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/04-entry.t b/support/bibtexperllibs/BibTeX-Parser/t/04-entry.t
new file mode 100644
index 0000000000..3ca9797011
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/04-entry.t
@@ -0,0 +1,42 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 13;
+
+use BibTeX::Parser::Entry;
+
+
+my $entry = new BibTeX::Parser::Entry("type", "key", 1, {title => "title"});
+
+isa_ok($entry, "BibTeX::Parser::Entry");
+
+is($entry->type, "TYPE", "Entry::type get");
+
+$entry->type("newtype");
+
+is($entry->type, "NEWTYPE", "Entry::type set");
+
+is($entry->key, "key", "Entry::key get");
+
+$entry->key("newkey");
+
+is($entry->key, "newkey", "Entry::key set");
+
+is($entry->field("title"), "title", "Entry::field with new");
+
+$entry->field("title" => "newtitle");
+
+is($entry->field("title"), "newtitle", "Entry::field overwrite");
+
+$entry->field("year" => 2008);
+
+is($entry->field("year"), 2008, "Entry::field set");
+
+is($entry->field("pages"), undef, "Entry::field undef on unknown value");
+
+is($entry->fieldlist, 2, "size of fieldlist");
+
+ok($entry->has("title"), "Entry::has true on known value");
+
+ok($entry->has("year"), "Entry::has true on known value");
+
+ok( ! $entry->has("pages"), "Entry::has false on unknown value");
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/05-author.t b/support/bibtexperllibs/BibTeX-Parser/t/05-author.t
new file mode 100644
index 0000000000..45bc5413df
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/05-author.t
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+
+use Test::More;
+
+use BibTeX::Parser::Author;
+
+# Names from Mittelbach, Goossens: The LaTeX Companion, Second Edition.
+my %names = (
+ "Donald E. Knuth" => ["Donald E.", undef, "Knuth", undef],
+ "John Chris Smith" => ["John Chris", undef, "Smith", undef],
+ "Smith, John Chris" => ["John Chris", undef, "Smith", undef],
+ "Thomas von Neumann" => ["Thomas", "von", "Neumann", undef],
+ "von Neumann, Thomas" => ["Thomas", "von", "Neumann", undef],
+ "Lopez Fernandez, Miguel" => ["Miguel", undef, "Lopez Fernandez", undef],
+ "Pierre de la Porte" => ["Pierre", "de la", "Porte", undef],
+ "Smith, Jr., Robert" => ["Robert", undef, "Smith", "Jr."],
+ "von Smith, Jr., Robert" => ["Robert", "von", "Smith", "Jr."],
+ "Johannes Martinus Albertus van de Groene Heide" => ["Johannes Martinus Albertus", "van de", "Groene Heide", undef],
+ "Maria-Victoria Delgrande" => ["Maria-Victoria", undef, "Delgrande", undef],
+ "Anonymous" => [undef, undef, "Anonymous", undef],
+ "von Neumann" => [undef, "von", "Neumann", undef],
+ "N. Tetteh-Lartey" => ["N.", undef, "Tetteh-Lartey", undef],
+ "von Tetteh-Lartey, N." => ["N.", "von", "Tetteh-Lartey", undef],
+ "von Tetteh-Lartey, Jr., N." => ["N.", "von", "Tetteh-Lartey", "Jr."],
+ "" => [undef, undef, undef, undef],
+ " " => [undef, undef, undef, undef],
+ "\n" => [undef, undef, undef, undef],
+ "al." => [undef, undef, "al.", undef],
+ "et.~al." => [undef, undef, "et.~al.", undef],
+ "O'Malley, A." => ["A.", undef, "O'Malley", undef],
+ "A. O'Malley" => ["A.", undef, "O'Malley", undef],
+ "Arthur O'Malley" => ["Arthur", undef, "O'Malley", undef],
+ "O'Malley, Arthur" => ["Arthur", undef, "O'Malley", undef],
+ 'L.M. M\"uller' => ["L.M.", undef, 'M\"uller', undef],
+ 'M\"uller, L.M.' => ["L.M.", undef, 'M\"uller', undef],
+ 'L.M. M"uller' => ["L.M.", undef, 'M"uller', undef],
+ 'M"uller, L.M.' => ["L.M.", undef, 'M"uller', undef],
+ 'van Beethoven, Ludwig' => ["Ludwig", "van", "Beethoven", undef ],
+ '{Barnes and Noble, Inc.}' => [undef, undef, '{Barnes and Noble, Inc.}', undef],
+ "Ludwigg {van Beethoven}" => ["Ludwigg", undef, "{van Beethoven}", undef],
+ '{van Beethoven}, Ludwig' => ["Ludwig", undef, "{van Beethoven}", undef ],
+);
+
+plan tests => (keys(%names) * 6 + 5);
+
+my $author = new BibTeX::Parser::Author;
+
+isa_ok($author, "BibTeX::Parser::Author", "Correct type");
+
+is($author->first, undef, "Initial state 'first'");
+is($author->von, undef, "Initial state 'von'");
+is($author->last, undef, "Initial state 'last'");
+is($author->jr, undef, "Initial state 'jr'");
+
+
+foreach my $name (keys %names) {
+
+ is_deeply([BibTeX::Parser::Author->split($name)], $names{$name}, $name =~ /\w/ ? $name : "whitespace name: '$name'" );
+
+ $author = new BibTeX::Parser::Author $name;
+
+ isa_ok($author, "BibTeX::Parser::Author");
+
+ is($author->first, $names{$name}->[0] );
+ is($author->von, $names{$name}->[1]);
+ is($author->last, $names{$name}->[2]);
+ is($author->jr, $names{$name}->[3]);
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/06-parse_complex.t b/support/bibtexperllibs/BibTeX-Parser/t/06-parse_complex.t
new file mode 100644
index 0000000000..95a5848a71
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/06-parse_complex.t
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+
+use Test::More tests => 19;
+
+use strict;
+use IO::File;
+use BibTeX::Parser;
+
+my $fh = IO::File->new("t/bibs/06.bib");
+
+my $parser = new BibTeX::Parser $fh;
+
+
+my $entry = $parser->next;
+
+isa_ok($entry, 'BibTeX::Parser::Entry', "Correct type");
+ok($entry->parse_ok, "Entry parsed correctly");
+is($entry->type, "ARTICLE", "BibTeX type is correct");
+is($entry->field("title"), "Paper title", "Title attribute");
+is($entry->field("year"), 2008);
+is($entry->field("month"), "August", "Month expansion");
+is($entry->key, 'key1', "key");
+
+my @authors = $entry->author;
+is(scalar @authors, 2, "number of authors correct");
+my $author = shift @authors;
+is_deeply(
+ [$author->first, $author->von, $author->last, $author->jr],
+ ['Gerhard', undef, 'Gossen', undef], "author correct");
+
+$author = shift @authors;
+is_deeply(
+ [$author->first, $author->von, $author->last, $author->jr],
+ ['Ludwig', 'van', 'Beethoven', undef], "author correct");
+
+$entry = $parser->next;
+isa_ok($entry, 'BibTeX::Parser::Entry', "Correct type");
+ok($entry->parse_ok, "Entry parsed correctly");
+is($entry->type, "BOOK", "BibTeX type is correct");
+is($entry->field("title"), "Book title", "Title attribute");
+is($entry->field("year"), 2008);
+is($entry->field("month"), "August", "Month expansion");
+is($entry->key, 'key2', "key");
+@authors = $entry->author;
+is(scalar @authors, 1, "number of authors");
+is(scalar $entry->editor, 0, "number of editors");
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/07-parse_englishbib.t b/support/bibtexperllibs/BibTeX-Parser/t/07-parse_englishbib.t
new file mode 100644
index 0000000000..3348a55248
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/07-parse_englishbib.t
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+
+use Test::More tests => 8;
+
+use strict;
+use IO::File;
+use BibTeX::Parser;
+
+
+my $fh = IO::File->new("t/bibs/english.bib");
+
+my $parser = new BibTeX::Parser $fh;
+
+my $count = 0;
+
+my $entry = $parser->next;
+
+is($entry->parse_ok, 0, "Ignore spurious @ before parenthesis");
+
+$entry = $parser->next;
+
+is($entry->parse_ok, 0, "Ignore spurious @ in email address");
+
+$entry = $parser->next;
+
+is(scalar $entry->author, 1, "# authors");
+#@BOOK{Carey,
+# AUTHOR="G. V. Carey",
+is($entry->field("title"), "Mind the Stop: A Brief Guide to Punctuation", "title");
+is($entry->field("publisher"), "Penguin", "publisher");
+is($entry->field("year"), 1958, "year");
+$count++;
+
+while ($entry = $parser->next) {
+ $count++;
+ if ($count == 8) {
+ is( scalar $entry->author, 4, 'Last entry has 4 authors');
+ }
+}
+
+
+is($count, 8, "number of entries");
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/08-parse_large.t b/support/bibtexperllibs/BibTeX-Parser/t/08-parse_large.t
new file mode 100644
index 0000000000..5375d9a062
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/08-parse_large.t
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+use Test::More skip_all => "Performance test", tests => 1;
+
+use IO::File;
+use BibTeX::Parser;
+
+my $starttime = time;
+
+my $fh = IO::File->new('t/bibs/java.bib'); #cl-nlp8x.bib');
+
+my $parser = new BibTeX::Parser $fh;
+my $entries = 0;
+
+#my @result = BibTeX::Parser->_parse($fh);
+
+while(my $entry = $parser->next) {
+ $entries++;
+}
+
+my $parsetime = time - $starttime;
+
+warn "Parsed $entries entries in $parsetime seconds";
+ok(1, "Parsed $entries entries in $parsetime seconds");
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/09-complex.t b/support/bibtexperllibs/BibTeX-Parser/t/09-complex.t
new file mode 100644
index 0000000000..56ce75cceb
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/09-complex.t
@@ -0,0 +1,42 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 1;
+
+use IO::File;
+use BibTeX::Parser;
+
+
+my $fh = IO::File->new('t/bibs/09-complex.bib');
+
+my $parser = new BibTeX::Parser $fh;
+
+#my @result = BibTeX::Parser->_parse($fh);
+
+my $entry = $parser->next;
+
+is_deeply($entry, {_type => 'ARTICLE', _key => 'Ahrenberg88',
+ author => "L. Ahrenberg and A. Jonsson",
+ title => "An interactive system for tagging dialogues",
+ journal => 'Literary \& Linguistic Computing',
+ volume => 3,
+ number => "2",
+ pages => "66--70",
+ year => "1988",
+ keywords => "conver",
+ _fieldnums => {'author' => 0, 'title' => 1,
+ 'journal' => 2, 'volume' => 3,
+ 'number' => 4, 'pages'=> 5,
+ 'year' => 6, 'keywords' => 7},
+ _parse_ok => 1,
+ _raw => '@Article{Ahrenberg88,
+ author = "L. Ahrenberg and A. Jonsson",
+ title = "An interactive system for tagging dialogues",
+ journal = "Literary \& Linguistic Computing",
+ volume = "3",
+ number = "2",
+ pages = "66--70",
+ year = "1988",
+ keywords = "conver",
+}',
+ _pre => ''
+ }, "parse \@ARTICLE");
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/10-funnyname.t b/support/bibtexperllibs/BibTeX-Parser/t/10-funnyname.t
new file mode 100644
index 0000000000..8ab48396e9
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/10-funnyname.t
@@ -0,0 +1,61 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 11;
+
+use IO::File;
+use BibTeX::Parser;
+
+my $fh = IO::File->new('t/bibs/10-funnyname.bib');
+
+my $parser = BibTeX::Parser->new($fh);
+
+#my @result = BibTeX::Parser->_parse($fh);
+
+my $entry = $parser->next;
+
+is_deeply(
+ $entry,
+ {
+ _type => 'ARTICLE',
+ _key => 'testkey',
+ author => 'A. Bar and L.M. M\"uller',
+ title => 'foo',
+ journal => 'journal',
+ volume => 1,
+ number => 1,
+ pages => 1,
+ year => 2008,
+ _parse_ok => 1,
+ _fieldnums => {'year' => 0, 'title' => 1,
+ 'author' => 2, 'journal' => 3,
+ 'volume' => 4, 'number'=> 5,
+ 'pages' => 6},
+ _raw => '@article{testkey,
+ year = {2008},
+ title = "foo",
+ author = {A. Bar and L.M. M\"uller},
+ journal = {journal},
+ volume = {1},
+ number = {1},
+ pages = {1},
+}',
+ _pre => ''
+ },
+ "parse \@ARTICLE"
+);
+
+my @authors = $entry->author;
+
+pass("->author didn't loop forever");
+ok(@authors == 2, "Two authors");
+
+is($authors[0]->first, 'A.', "A1 first name");
+is($authors[0]->last, 'Bar', "A1 last name");
+ok(!$authors[0]->von, "A1 no 'von'");
+ok(!$authors[0]->jr, "A1 no 'jr'");
+
+is($authors[1]->first, 'L.M.', "A2 first name");
+is($authors[1]->last, 'M\"uller', "A2 last name");
+ok(!$authors[1]->von, "A2 no 'von'");
+ok(!$authors[1]->jr, "A2 no 'jr'");
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/11-split_braced.t b/support/bibtexperllibs/BibTeX-Parser/t/11-split_braced.t
new file mode 100644
index 0000000000..85a29be86f
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/11-split_braced.t
@@ -0,0 +1,28 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 12;
+
+use BibTeX::Parser;
+use IO::File;
+
+my @tokens = BibTeX::Parser::_split_braced_string("a and b", '\s+and\s+');
+is(scalar @tokens,2);
+is($tokens[0],'a');
+is($tokens[1],'b');
+
+@tokens = BibTeX::Parser::_split_braced_string("a {and} b", '\s+and\s+');
+is(scalar @tokens,1);
+is($tokens[0],'a {and} b');
+
+@tokens = BibTeX::Parser::_split_braced_string("a {and b", '\s+and\s+');
+is(scalar @tokens,0);
+
+@tokens = BibTeX::Parser::_split_braced_string("} a {", '\s+');
+is(scalar @tokens,0);
+
+@tokens = BibTeX::Parser::_split_braced_string("{a b} c {d}e u", '\s+');
+is(scalar @tokens,4);
+is($tokens[0],'{a b}');
+is($tokens[1],'c');
+is($tokens[2],'{d}e');
+is($tokens[3],'u');
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/12-von_token.t b/support/bibtexperllibs/BibTeX-Parser/t/12-von_token.t
new file mode 100644
index 0000000000..6daceafa96
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/12-von_token.t
@@ -0,0 +1,12 @@
+#!/usr/bin/perl -w
+
+use Test::More tests => 5;
+
+use BibTeX::Parser::Author;
+use IO::File;
+
+is(BibTeX::Parser::Author::_is_von_token('von'),1);
+is(BibTeX::Parser::Author::_is_von_token('Von'),0);
+is(BibTeX::Parser::Author::_is_von_token('\noop{von}Von'),1);
+is(BibTeX::Parser::Author::_is_von_token('\noop{Von}von'),0);
+is(BibTeX::Parser::Author::_is_von_token('\noop{AE}{\AE}schylus'),0);
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/13_output.t b/support/bibtexperllibs/BibTeX-Parser/t/13_output.t
new file mode 100644
index 0000000000..02fb1cd26f
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/13_output.t
@@ -0,0 +1,39 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+
+use BibTeX::Parser;
+use IO::File;
+
+
+my $fh = new IO::File "t/bibs/01.bib", "r" ;
+
+my $parser = new BibTeX::Parser $fh;
+
+
+
+
+while (my $entry = $parser->next) {
+ if($entry->key eq 'key01') {
+ my $result1='@ARTICLE{key01,
+ year = {1950},
+ author = {Duck, Donald and Else, Someone},
+ editor = {Itor, E. D. and Other, A. N.},
+ title = {Title text},
+ month = {January~1},
+}';
+ my $result2='@ARTICLE{key01,
+ year = {1950},
+ author = {Donald Duck and Someone Else},
+ editor = {E. D. Itor and A. N. Other},
+ title = {Title text},
+ month = {January~1},
+}';
+ is($entry->to_string,$result1);
+ is($entry->to_string(canonize_names=>0),$result2);
+ }
+
+}
+
+done_testing();
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/14-extratext.t b/support/bibtexperllibs/BibTeX-Parser/t/14-extratext.t
new file mode 100644
index 0000000000..0a663b043a
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/14-extratext.t
@@ -0,0 +1,65 @@
+#!/usr/bin/perl -w
+
+
+use Test::More tests => 6;
+
+use BibTeX::Parser;
+use IO::File;
+
+
+my $fh = new IO::File "t/bibs/14-extratext.bib", "r" ;
+
+my $parser = new BibTeX::Parser $fh;
+
+
+
+
+while (my $entry = $parser->next) {
+
+ if($entry->key eq 'Partridge') {
+ my $result1= '@BOOK{Partridge,
+ author = {Partridge, Eric},
+ title = {Use and Abuse: a Guide to Good {E}nglish},
+ publisher = {Hamish Hamilton},
+ edition = {4},
+ year = {1970},
+}';
+ my $result2 = "First published in 1947\n$result1";
+ is($entry->to_string,$result1);
+ is($entry->to_string(print_pre=>1),$result2);
+ }
+
+ if ($entry->key eq 'Cooper') {
+ my $result1 = '@BOOK{Cooper,
+ author = {Cooper, Bruce M.},
+ title = {Writing Technical Reports},
+ publisher = {Penguin},
+ year = {1964},
+}';
+ my $result2 = "\n\n$result1";
+ is($entry->to_string,$result1);
+ is($entry->to_string(print_pre=>1),$result2);
+ }
+
+
+ if ($entry->key eq 'Fowler-ModernEnglish') {
+
+ my $result1 = '@BOOK{Fowler-ModernEnglish,
+ author = {Fowler, H. W.},
+ title = {[A Dictionary of] Modern {E}nglish Usage},
+ publisher = {Oxford University Press},
+ edition = {2},
+ year = {1965},
+}';
+ my $result2 = '
+
+
+First published in 1926
+'. $result1;
+ is($entry->to_string,$result1);
+ is($entry->to_string(print_pre=>1),$result2);
+ }
+}
+
+done_testing();
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/15-capitalization.t b/support/bibtexperllibs/BibTeX-Parser/t/15-capitalization.t
new file mode 100644
index 0000000000..4254f5c12f
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/15-capitalization.t
@@ -0,0 +1,72 @@
+#!/usr/bin/perl -w
+
+use Test::More tests=>7;
+
+use BibTeX::Parser;
+use IO::File;
+
+
+my $fh = new IO::File "t/bibs/01.bib", "r" ;
+
+my $parser = new BibTeX::Parser $fh;
+
+
+
+
+while (my $entry = $parser->next) {
+ if($entry->key eq 'key01') {
+ my $result1='@ARTICLE{key01,
+ year = {1950},
+ author = {Duck, Donald and Else, Someone},
+ editor = {Itor, E. D. and Other, A. N.},
+ title = {Title text},
+ month = {January~1},
+}';
+ my $result2='@ARTICLE{key01,
+ YEAR = {1950},
+ AUTHOR = {Duck, Donald and Else, Someone},
+ EDITOR = {Itor, E. D. and Other, A. N.},
+ TITLE = {Title text},
+ MONTH = {January~1},
+}';
+ my $result3='@ARTICLE{key01,
+ Year = {1950},
+ Author = {Duck, Donald and Else, Someone},
+ Editor = {Itor, E. D. and Other, A. N.},
+ Title = {Title text},
+ Month = {January~1},
+}';
+ my $result4='@article{key01,
+ year = {1950},
+ author = {Duck, Donald and Else, Someone},
+ editor = {Itor, E. D. and Other, A. N.},
+ title = {Title text},
+ month = {January~1},
+}';
+ my $result5='@Article{key01,
+ year = {1950},
+ author = {Duck, Donald and Else, Someone},
+ editor = {Itor, E. D. and Other, A. N.},
+ title = {Title text},
+ month = {January~1},
+}';
+ is($entry->to_string,$result1);
+ is($entry->to_string(field_capitalization=>'Lowercase'),
+ $result1);
+ is($entry->to_string(field_capitalization=>'Uppercase'),
+ $result2);
+ is($entry->to_string(field_capitalization=>'Titlecase'),
+ $result3);
+
+ is($entry->to_string(type_capitalization=>'Lowercase'),
+ $result4);
+ is($entry->to_string(type_capitalization=>'Uppercase'),
+ $result1);
+ is($entry->to_string(type_capitalization=>'Titlecase'),
+ $result5);
+ }
+
+}
+
+done_testing();
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/01.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/01.bib
new file mode 100644
index 0000000000..7f6233d177
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/01.bib
@@ -0,0 +1,7 @@
+@ARTICLE{key01,
+ year = 1950,
+ author = {Donald Duck and Someone Else},
+ editor = {E. D. Itor and A. N. Other},
+ title = {Title text},
+ month = jan # "~1"
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/06.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/06.bib
new file mode 100644
index 0000000000..242ae662cc
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/06.bib
@@ -0,0 +1,27 @@
+this is text, which is ignored by bibtex.
+
+@PREAMBLE{
+ This is only used for BibTeX files used in LaTeX documents
+}
+
+@Comment{
+ Comments are ignored too.
+}
+
+@ARTICLE{key1,
+ author = {Gerhard Gossen and Ludwig van Beethoven},
+ title = "Paper title",
+ year = 2008,
+ month = aug,
+}
+
+@STRING{ gerhard = "Gerhard" }
+
+@STRING{ gossen = "Gossen" }
+
+@BOOK{ key2,
+ author = gerhard # " " # gossen,
+ title = "Book title",
+ year = "2008",
+ month = aug,
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/09-complex.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/09-complex.bib
new file mode 100644
index 0000000000..cacf322723
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/09-complex.bib
@@ -0,0 +1,11 @@
+@Article{Ahrenberg88,
+ author = "L. Ahrenberg and A. Jonsson",
+ title = "An interactive system for tagging dialogues",
+ journal = "Literary \& Linguistic Computing",
+ volume = "3",
+ number = "2",
+ pages = "66--70",
+ year = "1988",
+ keywords = "conver",
+}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/10-funnyname.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/10-funnyname.bib
new file mode 100644
index 0000000000..050fbc0534
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/10-funnyname.bib
@@ -0,0 +1,10 @@
+@article{testkey,
+ year = {2008},
+ title = "foo",
+ author = {A. Bar and L.M. M\"uller},
+ journal = {journal},
+ volume = {1},
+ number = {1},
+ pages = {1},
+}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/14-extratext.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/14-extratext.bib
new file mode 100644
index 0000000000..56f96aa01b
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/14-extratext.bib
@@ -0,0 +1,22 @@
+First published in 1947
+@BOOK{Partridge,
+ AUTHOR="Eric Partridge",
+ TITLE="Use and Abuse: a Guide to Good {E}nglish",
+ PUBLISHER="Hamish Hamilton",
+ EDITION="4", YEAR="1970"}
+
+
+@BOOK{Cooper,
+ AUTHOR="Bruce M. Cooper",
+ TITLE="Writing Technical Reports",
+ PUBLISHER="Penguin", YEAR="1964"}
+
+
+
+First published in 1926
+@BOOK{Fowler-ModernEnglish,
+ AUTHOR="H. W. Fowler",
+ TITLE="[A Dictionary of] Modern {E}nglish Usage",
+ PUBLISHER="Oxford University Press",
+ EDITION="2", YEAR="1965"}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/braces.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/braces.bib
new file mode 100644
index 0000000000..3791fb5760
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/braces.bib
@@ -0,0 +1,21 @@
+@Article{scholkopf98kpca,
+ author = {Bernhard {Sch\"olkopf} and Alex Smola and K.R. Muller},
+ title = {Nonlinear component analysis as a kernel eigenvalue
+problem},
+ journal = {Neural Computation},
+ year = {1998},
+ volume = {10},
+ pages = {1299--1319}
+}
+
+@article{brownetal93,
+ author = {Peter F. Brown and Stephen A. {Della Pietra} and
+ Vincent J. {Della Pietra} and Robert~L. Mercer},
+ title = {The Mathematics of Statistical Machine Translation:
+ Parameter Estimation},
+ journal = {Computational Linguistics},
+ year = 1993,
+ volume = 19,
+ number = 2,
+ pages = {263-311}
+}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/endnote.txt b/support/bibtexperllibs/BibTeX-Parser/t/bibs/endnote.txt
new file mode 100644
index 0000000000..b74621354e
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/endnote.txt
@@ -0,0 +1,6 @@
+@article{
+ volume = {59},
+ number = {6},
+ year = {1999}
+}
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/engineering_village.txt b/support/bibtexperllibs/BibTeX-Parser/t/bibs/engineering_village.txt
new file mode 100644
index 0000000000..09763e928c
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/engineering_village.txt
@@ -0,0 +1,24 @@
+@inproceedings{1997493856789 ,
+language = {English},
+year = {1997},
+}
+
+
+@inproceedings{1998043944915 ,
+language = {English},
+year = {1997},
+}
+
+
+@article{2003137419501 ,
+language = {English},
+year = {2002},
+}
+
+
+@inproceedings{2002367072517 ,
+language = {English},
+year = {2002},
+}
+
+
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/english.bib b/support/bibtexperllibs/BibTeX-Parser/t/bibs/english.bib
new file mode 100644
index 0000000000..be62f92104
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/english.bib
@@ -0,0 +1,55 @@
+$Id: english.bib,v 1.7 2018/04/29 19:39:51 boris Exp $
+
+Please notify Adrian F Clark <alien@uk.ac.essex.ese> of any additions
+or corrections to this list.
+
+@BOOK{Carey,
+ AUTHOR="G. V. Carey",
+ TITLE="Mind the Stop: A Brief Guide to Punctuation",
+ PUBLISHER="Penguin", YEAR="1958"}
+
+@BOOK{Cooper,
+ AUTHOR="Bruce M. Cooper",
+ TITLE="Writing Technical Reports",
+ PUBLISHER="Penguin", YEAR="1964"}
+
+@BOOK{Fowler-ModernEnglish,
+ AUTHOR="H. W. Fowler",
+ TITLE="[A Dictionary of] Modern {E}nglish Usage",
+ PUBLISHER="Oxford University Press",
+ EDITION="2", YEAR="1965"}
+ (but first published in 1926)
+
+@BOOK{Fowler-KingsEnglish,
+ AUTHOR="H. W. Fowler and F. G. Fowler",
+ TITLE="The {K}ing's {E}nglish",
+ PUBLISHER="Oxford University Press",
+ EDITION="3", YEAR="1931"}
+ (but first published in 1906)
+
+@BOOK{Gowers,
+ AUTHOR="Sir Ernest Gowers",
+ TITLE="The Complete Plain Words",
+ PUBLISHER="Penguin", YEAR="1954"}
+ (but first published by HMSO)
+
+@BOOK{Hart,
+ AUTHOR="Horace Hart",
+ TITLE="[Hart's] Rules for Compositors and Readers
+ [at the Oxford University Press]",
+ PUBLISHER="Oxford University Press",
+ EDITION="39", YEAR="1983"}
+ (but first published in 1893)
+
+@BOOK{Partridge,
+ AUTHOR="Eric Partridge",
+ TITLE="Use and Abuse: a Guide to Good {E}nglish",
+ PUBLISHER="Hamish Hamilton",
+ EDITION="4", YEAR="1970"}
+ (but first published in 1947)
+
+@BOOK{Quirk-CompGram,
+ AUTHOR="Randolph Quirk and Sydney Greenbaum and Geoffrey Leach and
+ Jan Svartnik",
+ TITLE="A Comprehensive Grammar of the {E}nglish Language",
+ PUBLISHER="Longman", YEAR="1985"}
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bibs/mathscinet.txt b/support/bibtexperllibs/BibTeX-Parser/t/bibs/mathscinet.txt
new file mode 100644
index 0000000000..acf4457b95
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bibs/mathscinet.txt
@@ -0,0 +1,40 @@
+MathSciNet </mathscinet/index.html>
+
+ *
+ Clipboard </mathscinet/clipboard.html>
+ * Home </mathscinet/index.html>
+ * Preferences </mathscinet/preferences.html>
+ * Help </mathscinet/help/headline_review_help_full.html>
+ * Support Mail </mathscinet/support_mail.html>
+ * Terms of Use </mathscinet/help/mathscinet_terms_of_use.html>
+ * University of Southampton
+
+@article {MR2254280,
+ VOLUME = {23},
+ YEAR = {2006},
+}
+
+
+@article {MR2254274,
+ VOLUME = {23},
+ YEAR = {2006},
+}
+
+
+@article {MR2248052,
+ VOLUME = {23},
+ YEAR = {2006},
+}
+
+
+*Matches:* 3
+Mirror Sites
+
+
+© Copyright 2011, American Mathematical Society
+<http://www.ams.org/ams/copyright.html>
+Privacy Statement <http://www.ams.org/ams/privacy.html>
+American Mathematical Society <http://www.ams.org>
+American Mathematical Society
+201 Charles Street
+Providence, RI 02904-2294
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bug66325.t b/support/bibtexperllibs/BibTeX-Parser/t/bug66325.t
new file mode 100644
index 0000000000..ac83b43aa9
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bug66325.t
@@ -0,0 +1,71 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+
+use BibTeX::Parser;
+use IO::File;
+
+{
+ my $fh = new IO::File "t/bibs/endnote.txt", "r" ;
+
+ if (defined $fh) {
+ my $parser = new BibTeX::Parser $fh;
+
+ while (my $entry = $parser->next) {
+ isa_ok($entry, "BibTeX::Parser::Entry");
+ ok($entry->parse_ok, "parse_ok");
+ is($entry->key, undef, "key");
+ is($entry->type, "ARTICLE", "type");
+ is($entry->field("year"), 1999, "field");
+ is($entry->field("volume"), 59, "first field");
+ }
+ }
+}
+
+{
+ my $fh = new IO::File "t/bibs/mathscinet.txt", "r" ;
+ my @keys = qw(MR2254280 MR2254274 MR2248052);
+
+ if (defined $fh) {
+ my $parser = new BibTeX::Parser $fh;
+ my $count = 0;
+
+ while (my $entry = $parser->next) {
+ isa_ok($entry, "BibTeX::Parser::Entry");
+ ok($entry->parse_ok, "parse_ok");
+ is($entry->key, $keys[$count], "key");
+ is($entry->type, "ARTICLE", "type");
+ is($entry->field("volume"), 23, "first field");
+ is($entry->field("year"), 2006, "field");
+ $count++;
+ }
+
+ is($count, 3, "number of entries");
+ }
+}
+
+{
+ my $fh = new IO::File "t/bibs/engineering_village.txt", "r" ;
+
+ my @types = qw( inproceedings inproceedings article inproceedings );
+ my @keys = qw( 1997493856789 1998043944915 2003137419501 2002367072517 );
+ my @years = qw( 1997 1997 2002 2002 );
+
+ if (defined $fh) {
+ my $parser = new BibTeX::Parser $fh;
+ my $count = 0;
+
+ while (my $entry = $parser->next) {
+ isa_ok($entry, "BibTeX::Parser::Entry");
+ ok($entry->parse_ok, "parse_ok");
+ is($entry->key, $keys[$count], "key");
+ is($entry->type, uc $types[$count], "type");
+ is($entry->field("language"), "English", "first field");
+ is($entry->field("year"), $years[$count], "field");
+ $count++;
+ }
+
+ is($count, 4, "number of entries");
+ }
+}
+done_testing;
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/bug67419.t b/support/bibtexperllibs/BibTeX-Parser/t/bug67419.t
new file mode 100644
index 0000000000..0f944f373a
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/bug67419.t
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use Test::More;
+
+use BibTeX::Parser;
+use IO::File;
+
+my $fh = new IO::File "t/bibs/braces.bib", "r" ;
+my $parser = new BibTeX::Parser $fh;
+while (my $entry=$parser->next) {
+ is($entry->parse_ok,1);
+ if ($entry->key eq 'scholkopf98kpca') {
+ @authors=$entry->author;
+ is(scalar @authors,3);
+ is("$authors[0]", '{Sch\"olkopf}, Bernhard');
+ is("$authors[1]", 'Smola, Alex');
+ is("$authors[2]", 'Muller, K.R.');
+ }
+ if ($entry->key eq 'brownetal93') {
+ @authors=$entry->author;
+ is(scalar @authors,4);
+ is("$authors[0]", 'Brown, Peter F.');
+ is("$authors[1]", '{Della Pietra}, Stephen A.');
+ is("$authors[2]", '{Della Pietra}, Vincent J.');
+ is("$authors[3]", 'Mercer, Robert~L.');
+ }
+}
+
+done_testing();
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/cleaned_field.t b/support/bibtexperllibs/BibTeX-Parser/t/cleaned_field.t
new file mode 100644
index 0000000000..33a38784cd
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/cleaned_field.t
@@ -0,0 +1,142 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use utf8;
+
+use Test::More;
+use BibTeX::Parser::Entry;
+
+sub new_entry {
+ BibTeX::Parser::Entry->new( 'ARTICLE', 'Foo2010', 1, { @_ } );
+}
+{
+ my @german_tests = (
+ [ '"a' => 'ä' ],
+ ['"`' => '„' ],
+ ["\"'" => '“' ],
+ );
+
+ foreach my $test ( @german_tests ) {
+ my $entry = new_entry( foo => $test->[0] );
+ is( $entry->cleaned_field( 'foo', german => 1 ), $test->[1], "Convert $test->[0], german => 1" );
+ }
+}
+
+{
+ binmode( DATA, ':utf8' );
+ while (<DATA>) {
+ chomp;
+ my ( $tex, $result ) = split /\t/;
+ is( new_entry( foo => $tex )->cleaned_field( 'foo' ), $result, "Convert $tex" );
+ }
+ close DATA;
+}
+
+{
+ my $entry_with_authors = new_entry( author => 'F{\"o}o Bar and B"ar, F.' );
+ my @authors = $entry_with_authors->author;
+ is( scalar @authors, 2, "Number of authors is correct");
+ is( $authors[0]->first, 'F{\"o}o', "non-cleaned version of first" );
+ is( $authors[0]->last, 'Bar', "non-cleaned version of last" );
+
+ is( $authors[1]->first, 'F.', "non-cleaned version of first" );
+ is( $authors[1]->last, 'B"ar', "non-cleaned version of last" );
+
+ my @clean_authors = $entry_with_authors->cleaned_author;
+ is( $clean_authors[0]->first, 'Föo', "cleaned version of first" );
+ is( $clean_authors[0]->last, 'Bar', "cleaned version of last" );
+
+ is( $clean_authors[1]->first, 'F.', "cleaned version of first" );
+ is( $clean_authors[1]->last, 'B"ar', "cleaned version of last" );
+}
+done_testing;
+
+__DATA__
+\& &
+{\`a} à
+{\^a} â
+{\~a} ã
+{\'a} á
+{\'{a}} á
+{\"a} ä
+{\`A} À
+{\'A} Á
+{\"A} Ä
+{\aa} å
+{\AA} Å
+{\ae} æ
+{\bf 12} 12
+{\'c} ć
+{\cal P} P
+{\c{c}} ç
+{\c{C}} Ç
+{\c{e}} ȩ
+{\c{s}} ş
+{\c{S}} Ş
+{\c{t}} ţ
+{\-d} d
+{\`e} è
+{\^e} ê
+{\'e} é
+{\"e} ë
+{\'E} É
+{\em bits} bits
+{\H{o}} ő
+{\`i} ì
+{\^i} î
+{\i} ı
+{\`i} ì
+{\'i} í
+{\"i} ï
+{\`\i} ì
+{\'\i} í
+{\"\i} ï
+{\`{\i}} ì
+{\'{\i}} í
+{\"{\i}} ï
+{\it Note} Note
+{\k{e}} ę
+{\l} ł
+{\-l} l
+{\log} log
+{\~n} ñ
+{\'n} ń
+{\^o} ô
+{\o} ø
+{\'o} ó
+{\"o} ö
+{\"{o}} ö
+{\'O} Ó
+{\"O} Ö
+{\"{O}} Ö
+{\rm always} always
+{\-s} s
+{\'s} ś
+{\sc JoiN} JoiN
+{\sl bit\/ \bf 7} bit 7
+{\sl L'Informatique Nouvelle} L’Informatique Nouvelle
+{\small and} and
+{\ss} ß
+{\TeX} TEX
+{\TM} ™
+{\tt awk} awk
+{\^u} û
+{\'u} ú
+{\"u} ü
+{\"{u}} ü
+{\'U} Ú
+{\"U} Ü
+{\u{a}} ă
+{\u{g}} ğ
+{\v{c}} č
+{\v{C}} Č
+{\v{e}} ě
+{\v{n}} ň
+{\v{r}} ř
+{\v{s}} š
+{\v{S}} Š
+{\v{z}} ž
+{\v{Z}} Ž
+{\'y} ý
+{\.{z}} ż
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/pod-coverage.t b/support/bibtexperllibs/BibTeX-Parser/t/pod-coverage.t
new file mode 100644
index 0000000000..fc40a57c2a
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/pod-coverage.t
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Ensure a recent version of Test::Pod::Coverage
+my $min_tpc = 1.08;
+eval "use Test::Pod::Coverage $min_tpc";
+plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
+ if $@;
+
+# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
+# but older versions don't recognize some common documentation styles
+my $min_pc = 0.18;
+eval "use Pod::Coverage $min_pc";
+plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
+ if $@;
+
+all_pod_coverage_ok();
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/pod.t b/support/bibtexperllibs/BibTeX-Parser/t/pod.t
new file mode 100644
index 0000000000..e22a39b524
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/pod.t
@@ -0,0 +1,12 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+use Test::More;
+
+# Ensure a recent version of Test::Pod
+my $min_tp = 1.22;
+eval "use Test::Pod $min_tp";
+plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
+
+all_pod_files_ok();
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/release-pod-coverage.t b/support/bibtexperllibs/BibTeX-Parser/t/release-pod-coverage.t
new file mode 100644
index 0000000000..3a818499f0
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/release-pod-coverage.t
@@ -0,0 +1,21 @@
+#!perl
+
+BEGIN {
+ unless ($ENV{RELEASE_TESTING}) {
+ require Test::More;
+ Test::More::plan(skip_all => 'these tests are for release candidate testing');
+ }
+}
+
+
+use Test::More;
+
+eval "use Test::Pod::Coverage 1.08";
+plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage"
+ if $@;
+
+eval "use Pod::Coverage::TrustPod";
+plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage"
+ if $@;
+
+all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });
diff --git a/support/bibtexperllibs/BibTeX-Parser/t/release-pod-syntax.t b/support/bibtexperllibs/BibTeX-Parser/t/release-pod-syntax.t
new file mode 100644
index 0000000000..d46a955694
--- /dev/null
+++ b/support/bibtexperllibs/BibTeX-Parser/t/release-pod-syntax.t
@@ -0,0 +1,15 @@
+#!perl
+
+BEGIN {
+ unless ($ENV{RELEASE_TESTING}) {
+ require Test::More;
+ Test::More::plan(skip_all => 'these tests are for release candidate testing');
+ }
+}
+
+use Test::More;
+
+eval "use Test::Pod 1.41";
+plan skip_all => "Test::Pod 1.41 required for testing POD" if $@;
+
+all_pod_files_ok();