texlive[45131] trunk: checkcites (25aug17)

commits+karl at tug.org commits+karl at tug.org
Sat Aug 26 00:26:16 CEST 2017


Revision: 45131
          http://tug.org/svn/texlive?view=revision&revision=45131
Author:   karl
Date:     2017-08-26 00:26:15 +0200 (Sat, 26 Aug 2017)
Log Message:
-----------
checkcites (25aug17)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/checkcites/checkcites.lua
    trunk/Master/texmf-dist/doc/support/checkcites/README
    trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf
    trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex
    trunk/Master/texmf-dist/scripts/checkcites/checkcites.lua

Modified: trunk/Build/source/texk/texlive/linked_scripts/checkcites/checkcites.lua
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/checkcites/checkcites.lua	2017-08-25 22:25:59 UTC (rev 45130)
+++ trunk/Build/source/texk/texlive/linked_scripts/checkcites/checkcites.lua	2017-08-25 22:26:15 UTC (rev 45131)
@@ -1,684 +1,721 @@
 #!/usr/bin/env texlua
--- ******************************************************************
+-- -----------------------------------------------------------------
 -- checkcites.lua
--- Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+-- Copyright 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
 --
--- This work may be distributed and/or modified under the
--- conditions of the LaTeX Project Public License, either version 1.3
--- of this license or (at your option) any later version.
+-- This work may be distributed and/or modified under the conditions
+-- of the LaTeX  Project Public License, either version  1.3 of this
+-- license or (at your option) any later version.
 --
 -- The latest version of this license is in
---   http://www.latex-project.org/lppl.txt
--- and version 1.3 or later is part of all distributions of LaTeX
+--
+-- http://www.latex-project.org/lppl.txt
+--
+-- and version  1.3 or later is  part of all distributions  of LaTeX
 -- version 2005/12/01 or later.
 --
--- This work has the LPPL maintenance status `maintained'.
--- 
--- The Current Maintainers of this work are the original authors.
+-- This  work  has the  LPPL  maintenance  status `maintained'.  the
+-- current maintainers of  this work are the  original authors. This
+-- work consists of the file checkcites.lua.
 --
--- This work consists of the file checkcites.lua.
---
--- Project page: http://github.com/cereda/checkcites
--- ******************************************************************
+-- Project repository: http://github.com/cereda/checkcites
+-- -----------------------------------------------------------------
 
--- version and date, to be updated on each release/commit
-VERSION = "1.0i"
-DATE = "December 18, 2012"
-
--- globals
--- warning about \citation{*}
-globalAsteriskWarning = true
-
--- The following code adds a 'split' function to the string type,
--- thanks to the codebase available here:
--- http://lua-users.org/wiki/SplitJoin
-string.split = function(str, pattern)
-
-    pattern = pattern or "[^%s]+"
-    
-    if pattern:len() == 0 then
-    
-        pattern = "[^%s]+"
-    
+-- Checks if the table contains the element.
+-- @param a Table.
+-- @param hit Element.
+-- @return Boolean value if the table contains the element.
+local function exists(a, hit)
+  for _, v in ipairs(a) do
+    if v == hit then
+      return true
     end
-    
-    local parts = {__index = table.insert}
-    
-    setmetatable(parts, parts)
-    
-    str:gsub(pattern, parts)
-    
-    setmetatable(parts, nil)
-    
-    parts.__index = nil
-    
-    return parts
-
+  end
+  return false
 end
 
--- In order to make our lives easier, we borrowed the following
--- codes for implementing common set operations, available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setFind(a, tbl)
-
-	for _,a_ in ipairs(tbl) do
-        
-        if a_==a then
-            
-            return true
+-- Parses the list of arguments based on a configuration map.
+-- @param map Configuration map.
+-- @param args List of command line arguments.
+-- @return Table containing the valid keys and entries.
+-- @return Table containing the invalid keys.
+local function parse(map, args)
+  local keys, key, unknown = {}, 'unpaired', {}
+  local a, b
+  for _, v in ipairs(args) do
+    a, _, b = string.find(v, '^%-(%w)$')
+    if a then
+      for _, x in ipairs(map) do
+        key = 'unpaired'
+        if x['short'] == b then
+          key = x['long']
+          break
         end
-    
-    end
-
-end
-
--- This code returns a table containing the difference between
--- the two other tables, also available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setDifference(a, b)
-
-	local ret = {}
-
-	for _,a_ in ipairs(a) do
-
-		if not setFind(a_,b) then
-            
-            table.insert(ret, a_)
-        
+      end
+      if key == 'unpaired' then
+        table.insert(unknown, '-' .. b)
+      end
+      if not keys[key] then
+        keys[key] = {}
+      end
+    else
+      a, _, b = string.find(v, '^%-%-([%w-]+)$')
+      if a then
+        for _, x in ipairs(map) do
+          key = 'unpaired'
+          if x['long'] == b then
+            key = b
+            break
+          end
         end
-
-	end
-
-	return ret
-
-end
-
--- Code to remove duplicates from a table array.
-function removeDuplicates(tb)
-
-    -- new table
-    local ret = {}
-
-    -- flag to spot new insertions
-    local flag
-
-    -- set local variables
-    local i
-    local k
-    local j
-    local l
-
-    -- iterate through the original table
-    for i, k in pairs(tb) do
-
-        -- at first, insert element
-        flag = true
-
-        -- iterate through the new table
-        for j, l in pairs(ret) do
-
-            -- if the element already exists
-            if k == l then
-
-                -- set flag to false, so the
-                -- new element won't be inserted
-                flag = false
-
-            end
-
+        if key == 'unpaired' then
+          if not exists(unknown, '--' .. b) then
+            table.insert(unknown, '--' .. b)
+          end
         end
-
-        -- if it's ok to insert
-        if flag then
-
-            -- insert new element
-            table.insert(ret, k)
-
+        if not keys[key] then
+          keys[key] = {}
         end
-
-    end
-
-    -- return new table
-    return ret
-end
-
--- This function opens and gets all data from the provided
--- aux file.
--- Return:
---   * list of citations
---   * list of bibfiles
-function getDataFromAuxFile(theAuxFile)
-
-    -- open a file handler
-	local fileHandler = io.open(theAuxFile,"r")
-
-    -- check if the handler is valid
-	if fileHandler then
-
-        -- create a local table for citations
-		local theCitations = {}
-
-        -- and a local reference to the bib file
-		local theBibFiles = {}
-
-        -- define local variables
-        local currentLine
-        local citation
-        local index
-        local theCitation
-        local theBibFile
-        local entry
-
-        -- now let's iterate through the lines
-		for currentLine in fileHandler:lines() do
-
-            -- if the citation matches, extract it
-			for citation in string.gmatch(currentLine, '\\citation{(.+)}') do
-
-                -- sanity check, in case it's an '*'
-				if citation ~= "*" then
-
-                    -- break the citations list, in case of multiple
-                    -- citations in the same \citation{}
-					local parts = string.split(citation, "[^,%s]+" )
-
-                    -- for every entry in the citations list
-					for index, theCitation in pairs(parts) do
-                        
-                        -- insert the reference
-						table.insert(theCitations, theCitation)
-
-					end
-
-                -- found a '*'
-                else
-
-                    -- check if warning is still valid, that is,
-                    -- if not displayed yet
-                    if globalAsteriskWarning then
-
-                        -- show message
-                        print("Warning: '\\nocite{*}' found, I'll do the check nonetheless.\n")
-
-                        -- warning already displayed, so
-                        -- set flag to false
-                        globalAsteriskWarning = false
-
-                    end
-
-                end
-
-            -- end of citation in current line
+      else
+        if not keys[key] then
+          keys[key] = {}
+        end
+        if key ~= 'unpaired' then
+          for _, x in ipairs(map) do
+            if x['long'] == key then
+              if not (x['argument'] and
+                 #keys[key] == 0) then
+                key = 'unpaired'
+              end
+              break
             end
-
-            -- in the same current line, check if there's the 
-            -- bibdata entry and extract it
-			for entry in string.gmatch(currentLine, '\\bibdata{(.+)}') do
-
-                -- break the bib files list, in case of multiple
-                -- files in the same \bibdata{}
-				local parts = string.split(entry, "[^,%s]+" )
-
-                -- for every entry in the bib files list
-				for index, theBibFile in pairs(parts) do
-
-                    -- insert the file
-        			table.insert(theBibFiles, theBibFile)
-
-				end
-
-            -- end of bib files in the current line
-            end
-
-        -- end of current line
-        end
-
-        -- close the file handler
-		fileHandler:close()
-
-        -- remove duplicated citations
-        theCitations = removeDuplicates(theCitations)
-
-        -- print a message about the citations
-		print("I found " .. #theCitations .. " citation(s).")
-
-        -- remove possible duplicated files
-        theBibFiles = removeDuplicates(theBibFiles)
-
-        -- if there are no bib files
-        if #theBibFiles == 0 then
-
-            -- show message
-            print("I couldn't find any bibliography files.\nI'm afraid I have nothing to do now.")
-
-            -- and abort the script
-    		os.exit()
-
-        -- if there is only one bib file
-        elseif #theBibFiles == 1 then
-
-            -- show message
-            print("Great, there's only one 'bib' file. Let me check it.")
-
-        -- there are more bib files
+          end
+          if not keys[key] then
+            keys[key] = {}
+          end
+          table.insert(keys[key], v)
         else
-
-            -- show message
-            print("Oh no, I have to check more than one 'bib' file. Please wait.")
-
+          if not keys[key] then
+            keys[key] = {}
+          end
+          table.insert(keys[key], v)
         end
+      end
+    end
+  end
+  return keys, unknown
+end
 
-        -- return both citations and bib files
-        return theCitations, theBibFiles
-
-    -- the file handler is invalid
-    else
-
-        -- print an error message
-		print("File '" .. theAuxFile .. "' does not exist or is unavailable. Aborting script.")
-
-        -- and abort the script
-		os.exit()
-
+-- Calculates the difference between two tables.
+-- @param a First table.
+-- @param b Second table.
+-- @return Table containing the difference between two tables.
+local function difference(a, b)
+  local result = {}
+  for _, v in ipairs(a) do
+    if not exists(b, v) then
+      table.insert(result, v)
     end
+  end
+  return result
+end
 
--- end of function
+-- Splits the string based on a pattern.
+-- @param str String.
+-- @param pattern Pattern.
+local function split(str, pattern)
+  local result = {}
+  string.gsub(str, pattern, function(a)
+              table.insert(result, a) end)
+  return result
 end
 
--- This function opens and gets all data from all the available
--- bib files.
-function getDataFromBibFiles(theBibFiles)
-
-    -- create a table to store the citations
-	local theReferences = {}
-
-    -- set local variables
-    local index
-    local theBibFile
-    local currentLine
-    local reference
-
-    -- iterate through all bib files
-    for index, theBibFile in pairs(theBibFiles) do
-
-        -- open the bib file
-		local fileHandler = io.open(theBibFile .. ".bib","r")
-
-        -- check if the handler is valid
-		if fileHandler then
-
-            -- iterate through every line of the bib file
-			for currentLine in fileHandler:lines() do
-
-                -- if a reference is found
-				for reference in string.gmatch(currentLine, '@%w+{%s*(.+),') do
-
-                    -- insert the reference
-					table.insert(theReferences, reference)
-
-                end
-
-            -- end current line
-            end
-
-            -- close the file handler
-			fileHandler:close()
-
-        -- bib file does not exist
-        else
-
-            -- error message
-			print("File '" .. theBibFile .. ".bib' does not exist. Aborting.")
-
-			-- abort script
-			os.exit()
-
-        end
-
-    -- end iteration through the bib files
+-- Reads lines from a file.
+-- @param file File.
+-- @returns Table representing the lines.
+local function read(file)
+  local handler = io.open(file, 'r')
+  local lines = {}
+  if handler then
+    for line in handler:lines() do
+      table.insert(lines, line)
     end
+    handler:close()
+  end
+  return lines
+end
 
-    -- remove duplicated references
-    theReferences = removeDuplicates(theReferences)
-
-    -- print message
-	print("I found " .. #theReferences .. " reference(s).")
-
-    -- return references
-	return theReferences
-
--- end of function
+-- Normalizes the string, removing leading and trailing spaces.
+-- @param str String.
+-- @return Normalized string without leading and trailing spaces.
+local function normalize(str)
+  local result, _ = string.gsub(str, '^%s', '')
+  result, _ = string.gsub(result, '%s$', '')
+  return result
 end
 
--- This function show all the undefined references. It's very
--- simple, it's a difference between two sets.
-function showUndefinedReferences(citations, references)
-
-    -- get all undefined references
-	local undefined = setDifference(citations, references)
-
-    -- print message
-    print("\nUndefined reference(s) in your TeX file: " .. #undefined)
-
-	-- if there are undefined references
-	if #undefined ~= 0 then
-
-        -- local variables
-        local index
-        local reference
-
-		-- iterate
-		for index, reference in pairs(undefined) do
-
-			-- and print
-			print("- " .. reference)
-
-		end
-
+-- Checks if the element is in a blacklist.
+-- @param a Element.
+-- @return Boolean value if the element is blacklisted.
+local function blacklist(a)
+  local list = {}
+  for _, v in ipairs(list) do
+    if v == a then
+      return true
     end
-
--- end of function
+  end
+  return false
 end
 
--- This function show all the unused references. It's very
--- simple, it's a difference between two sets.
-function showUnusedReferences(citations, references)
-
--- get all undefined references
-	local unused = setDifference(references, citations)
-
-    -- print message
-   	print("\nUnused reference(s) in your bibliography file(s): " .. #unused)
-
-	-- if there are unused references
-	if #unused ~= 0 then
-
-        -- local variables
-        local index
-        local reference
-
-		-- iterate
-		for index, reference in pairs(unused) do
-
-			-- and print
-			print("- " .. reference)
-
-		end
-        
+-- Extracts the biblographic key.
+-- @param lines Lines of a file.
+-- @return Table containing bibliographic keys.
+local function extract(lines)
+  local result = {}
+  for _, line in ipairs(lines) do
+    local hit = string.match(line,
+                '^%s*%@%w+%s*{%s*(.+),')
+    if hit then
+      if not exists(result, hit) then
+        hit = normalize(hit)
+        table.insert(result, hit)
+      end
     end
+  end
+  return result
+end
 
--- end of function
+-- Gets a pluralized word based on a counter.
+-- @param i Counter.
+-- @param a Word in singular.
+-- @param b Word in plural.
+-- @return Either the first or second word based on the counter.
+local function plural(i, a, b)
+  if i == 1 then
+    return a
+  else
+    return b
+  end
 end
 
--- This function parses the command line arguments and returns a
--- bunch of info for us to use.
--- Return:
---   * an argument code
---   * the filename
---   * an action code
-function parseArguments(theArgs)
+-- Backend namespace
+local backends = {}
 
-    -- check if there are no arguments
-    if #theArgs == 0 then
-
-        -- return usage code
-        return 0, nil, nil
-
-    -- there is one argument
-    elseif #theArgs == 1 then
-
-        -- check if it's help
-        if theArgs[1] == "--help" then
-
-            -- return help code
-            return 1, nil, nil
-
-            -- check if it's version
-        elseif theArgs[1] == "--version" then
-
-            -- return version code
-            return 2, nil, nil
-
-        -- check if it's invalid
-        elseif string.sub(theArgs[1], 1, 1) == "-" then
-
-            -- return invalid code
-            return 3, nil, nil
-
-        -- it seems a clean argument
-        else
-
-            -- return it as a valid argument
-            return 4, theArgs[1], nil
-
-        -- end for one parameter
+-- Gets data from auxiliary files (BibTeX).
+-- @param lines Lines of a file.
+-- @return Boolean indicating if an asterisk was found.
+-- @return Table containing the citations.
+-- @return Table containing the bibliography files.
+backends.bibtex = function(lines)
+  local citations, bibliography = {}, {}
+  local asterisk, parts, hit = false
+  for _, line in ipairs(lines) do
+    hit = string.match(line, '^%s*\\citation{(.+)}$')
+    if hit then
+      if hit ~= '*' then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(citations, v) then
+            table.insert(citations, v)
+          end
         end
+      else
+        asterisk = true
+      end
+    else
+      hit = string.match(line, '^%s*\\bibdata{(.+)}$')
+      if hit then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(bibliography, v) and
+             not blacklist(v) then
+            table.insert(bibliography, v)
+          end
+        end
+      end
+    end
+  end
+  return asterisk, citations, bibliography
+end
 
-    -- there are two arguments
-    elseif #theArgs == 2 then
-
-        -- check if both are valid
-        if ((theArgs[1] == "--all" or theArgs[1] == "--unused" or theArgs[1] == "--undefined") and string.sub(theArgs[2], 1, 1) ~= "-") or ((theArgs[2] == "--all" or theArgs[2] == "--unused" or theArgs[2] == "--undefined") and string.sub(theArgs[1], 1, 1) ~= "-") then
-
-            -- create an action code
-            local actionCode
-
-            -- check which one is the file name
-            if string.sub(theArgs[1], 1, 1) ~= "-" then
-
-                -- check for --all
-                if theArgs[2] == "--all" then
-
-                    -- set the action code
-                    actionCode = 0
-
-                -- check for --unused
-                elseif theArgs[2] == "--unused" then
-
-                    -- set the action code
-                    actionCode = 1
-
-                -- it's --undefined
-                else
-
-                    -- set the action code
-                    actionCode = 2
-
-                end
-
-                -- it's the first
-                return 4, theArgs[1], actionCode
-
-            else
-
-                -- check for --all
-                if theArgs[1] == "--all" then
-
-                    -- set the action code
-                    actionCode = 0
-
-                -- check for --unused
-                elseif theArgs[1] == "--unused" then
-
-                    -- set the action code
-                    actionCode = 1
-
-                else
-
-                    -- it's --undefined
-                    actionCode = 2
-
-                end
-
-                -- it's the second
-                return 4, theArgs[2], actionCode
-
-            end
-
-        else
-
-            -- return invalid code
-            return 3, nil, nil
-
+-- Gets data from auxiliary files (Biber).
+-- @param lines Lines of a file.
+-- @return Boolean indicating if an asterisk was found.
+-- @return Table containing the citations.
+-- @return Table containing the bibliography files.
+backends.biber = function(lines)
+  local citations, bibliography = {}, {}
+  local asterisk, parts, hit = false
+  for _, line in ipairs(lines) do
+    hit = string.match(line, '^%s*<bcf:citekey order="%d+">' ..
+          '(.+)</bcf:citekey>$')
+    if hit then
+      if hit ~= '*' then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(citations, v) then
+            table.insert(citations, v)
+          end
         end
-
+      else
+        asterisk = true
+      end
     else
-
-        -- more than two arguments, return usage code
-        return 0, nil, nil
-
+      hit = string.match(line, '^%s*<bcf:datasource type="file" ' ..
+            'datatype="%w+">(.+)</bcf:datasource>$')
+      if hit then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(bibliography, v) and
+             not blacklist(v) then
+            table.insert(bibliography, v)
+          end
+        end
+      end
     end
+  end
+  return asterisk, citations, bibliography
+end
 
--- end of function
+-- Counts the number of elements of a nominal table.
+-- @param t Table.
+-- @return Table size.
+local function count(t)
+  local counter = 0
+  for _, _ in pairs(t) do
+    counter = counter + 1
+  end
+  return counter
 end
 
--- This function prints the script header.
-function printHeader()
+-- Repeats the provided char a certain number of times.
+-- @param c Char.
+-- @param w Number of times.
+-- @return String with a char repeated a certain number of times.
+local function pad(c, w)
+  local r = c
+  while #r < w do
+    r = r .. c
+  end
+  return r
+end
 
-    -- print message
-	print("checkcites.lua -- a reference checker script (v" .. VERSION .. ")")
-	print("Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda\n")
+-- Adds the extension if the file does not have it.
+-- @param file File.
+-- @param extension Extension.
+-- @return File with proper extension.
+local function sanitize(file, extension)
+  extension = '.' .. extension
+  if string.sub(file, -#extension) ~= extension then
+    file = file .. extension
+  end
+  return file
+end
 
--- end of function
+-- Flattens a table of tables into only one table.
+-- @param t Table.
+-- @return Flattened table.
+local function flatten(t)
+  local result = {}
+  for _, v in ipairs(t) do
+    for _, k in ipairs(v) do
+      if not exists(result, k) then
+        table.insert(result, k)
+      end
+    end
+  end
+  return result
 end
 
--- This function prints the script usage
-function printUsage()
+-- Applies a function to elements of a table.
+-- @param c Table.
+-- @param f Function.
+-- @return A new table.
+local function apply(c, f)
+  local result = {}
+  for _, v in ipairs(c) do
+    table.insert(result, f(v))
+  end
+  return result
+end
 
-    -- show message
-	print("Usage: " .. arg[0] .. " [--all | --unused | --undefined] file.aux\n")
-    print("--all         Lists all unused and undefined references.")
-    print("--unused      Lists only unused references in your 'bib' file.")
-    print("--undefined   Lists only undefined references in your 'tex' file.\n")
-    print("If no flag is provided, '--all' is set by default.")
-	print("Be sure to have all your 'bib' files in the same directory.")
+-- Wraps a string based on a line width.
+-- @param str String.
+-- @param size Line width.
+-- @return Wrapped string.
+local function wrap(str, size)
+  local parts = split(str, '[^%s]+')
+  local r, l = '', ''
+  for _, v in ipairs(parts) do
+    if (#l + #v) > size then
+      r = r .. '\n' .. l
+      l = v
+    else
+      l = normalize(l .. ' ' .. v)
+    end
+  end
+  r = normalize(r .. '\n' .. l)
+  return r
+end
 
--- end of function
+-- Prints the script header.
+local function header()
+print("     _           _       _ _")
+print(" ___| |_ ___ ___| |_ ___|_| |_ ___ ___")
+print("|  _|   | -_|  _| '_|  _| |  _| -_|_ -|")
+print("|___|_|_|___|___|_,_|___|_|_| |___|___|")
+print()
+  print(wrap('checkcites.lua -- a reference ' ..
+             'checker script (v2.0)', 74))
+  print(wrap('Copyright (c) 2012, 2017, ' ..
+             'Enrico Gregorio, Paulo ' ..
+             'Roberto Massa Cereda', 74))
 end
 
-function printHelp()
+-- Operation namespace
+local operations = {}
 
-    -- show message
-    print("checkcites.lua is a Lua script written for the sole purpose of")
-    print("detecting undefined/unused references from LaTeX auxiliary or")
-    print("bibliography files. It's very easy to use!\n")
+-- Reports the unused references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer representing the status.
+operations.unused = function(citations, references)
+  print()
+  print(pad('-', 74))
+  print(wrap('Report of unused references in your TeX ' ..
+             'document (that is, references present in ' ..
+             'bibliography files, but not cited in ' ..
+             'the TeX source file)', 74))
+  print(pad('-', 74))
+  local r = difference(references, citations)
+  print()
+  print(wrap('Unused references in your TeX document: ' ..
+             tostring(#r), 74))
+  if #r == 0 then
+    return 0
+  else
+    for _, v in ipairs(r) do
+      print('=> ' .. v)
+    end
+    return 1
+  end
+end
 
-    -- print usage
-    printUsage()
+-- Reports the undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.undefined = function(citations, references)
+  print()
+  print(pad('-', 74))
+  print(wrap('Report of undefined references in your TeX ' ..
+             'document (that is, references cited in the ' ..
+             'TeX source file, but not present in the ' ..
+             'bibliography files)', 74))
+  print(pad('-', 74))
+  local r = difference(citations, references)
+  print()
+  print(wrap('Undefined references in your TeX document: ' ..
+        tostring(#r), 74))
+  if #r == 0 then
+    return 0
+  else
+    for _, v in ipairs(r) do
+      print('=> ' .. v)
+    end
+    return 1
+  end
+end
 
--- end of function
+-- Reports both unused and undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.all = function(citations, references)
+  local x, y
+  x = operations.unused(citations, references)
+  y = operations.undefined(citations, references)
+  if x + y > 0 then
+    return 1
+  else
+    return 0
+  end
 end
 
--- This function prints the script version.
-function printVersion()
+-- Checks if a file exists.
+-- @param file File.
+-- @return Boolean value indicating if the file exists.
+local function valid(file)
+  local handler = io.open(file, 'r')
+  if handler then
+    handler:close()
+    return true
+  else
+    return false
+  end
+end
 
-    -- print message
-    print("checkcites.lua version " .. VERSION .. " (dated " .. DATE .. ")")
-    print("You can find more information about this script in the official")
-    print("source code repository:\n")
-    print("http://github.com/cereda/checkcites\n")
-    print("checkcites.lua is licensed under the LaTeX Project Public License.")
-
--- end of function
+-- Filters a table of files, keeping the inexistent ones.
+-- @param files Table.
+-- @return Table of inexistent files.
+local function validate(files)
+  local result = {}
+  for _, v in ipairs(files) do
+    if not valid(v) then
+      table.insert(result, v)
+    end
+  end
+  return result
 end
 
--- This function prints a message for invalid parameters.
-function printInvalid()
+-- Main function.
+-- @param args Command line arguments.
+-- @return Integer value indicating the status
+local function checkcites(args)
+  header()
 
-    -- print message
-    print("Oh no, it seems you used an invalid argument.\n")
+  local parameters = {
+    { short = 'a', long = 'all', argument = false },
+    { short = 'u', long = 'unused', argument = false },
+    { short = 'U', long = 'undefined', argument = false },
+    { short = 'v', long = 'version', argument = false },
+    { short = 'h', long = 'help', argument = false },
+    { short = 'b', long = 'backend', argument = true }
+  }
 
-    -- print usage
-    printUsage()
+  local keys, err = parse(parameters, args)
+  local check, backend = 'all', 'bibtex'
 
--- end of function
-end
+  if #err ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I do not recognize ' ..
+               'the following ' .. plural(#err, 'option',
+               'options') .. ':', 74))
+    for _, v in ipairs(err) do
+      print('=> ' .. v)
+    end
 
--- This is our main function.
-function runMain(theArgs)
+    print()
+    print(wrap('Please make sure to use the correct ' ..
+               'options when running this script. You ' ..
+               'can also refer to the user documentation ' ..
+               'for a list of valid options. The script ' ..
+               'will end now.', 74))
+    return 1
+  end
 
-   	-- print the script header
-	printHeader()
+  if count(keys) == 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but you have not provided ' ..
+               'any command line argument, including ' ..
+               'files to check and options. Make ' ..
+               'sure to invoke the script with the actual ' ..
+               'arguments. Refer to the user documentation ' ..
+               'if you are unsure of how this tool ' ..
+               'works. The script will end now.', 74))
+    return 1
+  end
 
-    -- set local variables
-    local argCode
-    local fileName
-    local actionCode
+  if keys['version'] or keys['help'] then
+    if keys['version'] then
+      print()
+      print(wrap('checkcites.lua, version 2.0 (dated August ' ..
+                 '25, 2017)', 74))
 
-    -- parse arguments and get the result
-    argCode, fileName, actionCode = parseArguments(theArgs)
+      print(pad('-', 74))
+      print(wrap('You can find more details about this ' ..
+                 'script, as well as the user documentation, ' ..
+                 'in the official source code repository:', 74))
 
-    -- check for usage
-    if argCode == 0 then
+      print()
+      print('https://github.com/cereda/checkcites')
 
-        -- print usage
-        printUsage()
+      print()
+      print(wrap('The checkcites.lua script is licensed ' ..
+                 'under the LaTeX Project Public License, ' ..
+                 'version 1.3. The current maintainers ' ..
+                 'are the original authors.', 74))
+    else
+      print()
+      print(wrap('Usage: ' .. args[0] .. ' [ [ --all | --unused | ' ..
+                 '--undefined ] [ --backend <arg> ] <file> [ ' ..
+                 '<file 2> ... <file n> ] | --help | --version ' ..
+                 ']', 74))
 
-    -- it's help
-    elseif argCode == 1 then
+      print()
+      print('-a,--all           list all unused and undefined references')
+      print('-u,--unused        list only unused references in your bibliography files')
+      print('-U,--undefined     list only undefined references in your TeX source file')
+      print('-b,--backend <arg> set the backend-based file lookup policy')
+      print('-h,--help          print the help message')
+      print('-v,--version       print the script version')
 
-        -- print help
-        printHelp()
+      print()
+      print(wrap('Unless specified, the script lists all unused and ' ..
+                 'undefined references by default. Also, the default ' ..
+                 'backend is set to "bibtex". Please refer to the user ' ..
+                 'documentation for more details.', 74))
+    end
+    return 0
+  end
 
-    -- it's version
-    elseif argCode == 2 then
+  if not keys['unpaired'] then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but you have not provided ' ..
+               'files to process. The tool requires ' ..
+               'least one file in order to properly ' ..
+               'work. Make sure to invoke the script ' ..
+               'with an actual file (or files). Refer ' ..
+               'to the user documentation if you are ' ..
+               'unsure of how this tool works. The ' ..
+               'script will end now.', 74))
+    return 1
+  end
 
-        -- print version
-        printVersion()
+  if keys['backend'] then
+    if not exists({ 'bibtex', 'biber' }, keys['backend'][1]) then
+      print()
+      print(pad('-', 74))
+      print(wrap('I am sorry, but you provided an ' ..
+                 'invalid backend. I know two: ' ..
+                 '"bibtex" (which is the default ' ..
+                 'one) and "biber". Please make ' ..
+                 'sure to select one of the two. ' ..
+                 'Also refer to the user documentation ' ..
+                 'for more information on how these ' ..
+                 'backends work. The script will end ' ..
+                 'now.', 74))
+      return 1
+    else
+      backend = keys['backend'][1]
+    end
+  end
 
-    -- it's an invalid parameter
-    elseif argCode == 3 then
+  if not keys['all'] then
+    if keys['unused'] and keys['undefined'] then
+      check = 'all'
+    elseif keys['unused'] or keys['undefined'] then
+      check = (keys['unused'] and 'unused') or
+              (keys['undefined'] and 'undefined')
+    end
+  end
 
-        -- print invalid
-        printInvalid()
+  local auxiliary = apply(keys['unpaired'], function(a)
+                    return sanitize(a, (backend == 'bibtex'
+                    and 'aux') or 'bcf') end)
 
-    -- it's a valid operation
-    else
+  local vld = validate(auxiliary)
+  if #vld ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I was unable to ' ..
+               'locate ' .. plural(#vld, 'this file',
+               'these files')  .. ' (the extension ' ..
+               'is automatically set based on the ' ..
+               '"' .. backend .. '" backend):', 74))
+    for _, v in ipairs(vld) do
+      print('=> ' .. v)
+    end
 
-        -- get data from aux
-        a, b = getDataFromAuxFile(fileName)
+    print()
+    print(wrap('Selected backend: ' .. backend, 74))
+    print(wrap('File lookup policy: add ".' ..
+               ((backend == 'bibtex' and 'aux') or 'bcf') ..
+               '" to files if not provided.', 74))
 
-        -- get data from bib
-        c = getDataFromBibFiles(b)
+    print()
+    print(wrap('Please make sure the ' .. plural(#vld,
+               'path is', 'paths are') .. ' ' ..
+               'correct and the ' .. plural(#vld,
+               'file exists', 'files exist') ..  '. ' ..
+               'There is nothing I can do at the moment. ' ..
+               'Refer to the user documentation for ' ..
+               'details on the file lookup. If ' .. plural(#vld,
+               'this is not the file', 'these are not the ' ..
+               'files') .. ' you were expecting, ' ..
+               'double-check your source file or ' ..
+               'change the backend option when running ' ..
+               'this tool. The script will end now.', 74))
+    return 1
+  end
 
-        -- if there is an action code
-        if actionCode ~= nil then
+  local lines = flatten(apply(auxiliary, read))
+  local asterisk, citations, bibliography = backends[backend](lines)
 
-            -- it's --all
-            if actionCode == 0 then
+  print()
+  print(wrap('Great, I found ' .. tostring(#citations) .. ' ' ..
+             plural(#citations, 'citation', 'citations') .. ' in ' ..
+             tostring(#auxiliary) .. ' ' .. plural(#auxiliary, 'file',
+             'files') ..'. I also found ' .. tostring(#bibliography) ..
+             ' ' .. 'bibliography ' .. plural(#bibliography, 'file',
+             'files') .. '. Let me check ' .. plural(#bibliography,
+             'this file', 'these files') .. ' and extract the ' ..
+             'references. Please wait a moment.', 74))
 
-                -- do everything
-                showUnusedReferences(a,c)
-                showUndefinedReferences(a,c)
+  if asterisk then
+    print()
+    print(wrap('Also, it is worth noticing that I found a mention to ' ..
+               'a special "*" when retrieving citations. That means ' ..
+               'your TeX document contains "\\nocite{*}" somewhere in ' ..
+               'the source code. I will continue with the check ' ..
+               'nonetheless.', 74))
+  end
 
-            -- it's --unused
-            elseif actionCode == 1 then
+  bibliography = apply(bibliography, function(a)
+                 return sanitize(a, 'bib') end)
 
-                -- only show unused
-                showUnusedReferences(a,c)
+  vld = validate(bibliography)
+  if #vld ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I was unable to locate ' ..
+               plural(#vld, 'this file', 'these files') .. ' ' ..
+               '(the extension is automatically set to ' ..
+               '".bib", if not provided):', 74))
+    for _, v in ipairs(vld) do
+      print('=> ' .. v)
+    end
 
-            -- it's --undefined
-            else
+    print()
+    print(wrap('Please make sure the ' .. plural(#vld,
+               'path is', 'paths are') .. ' ' ..
+               'correct and the ' .. plural(#vld,
+               'file exists', 'files exist') ..  '. ' ..
+               'There is nothing I can do at the moment. ' ..
+               'Refer to to the user documentation ' ..
+               'for details on bibliography lookup. If ' ..
+               plural(#vld, 'this is not the file',
+               'these are not the files') .. ' you were ' ..
+               'expecting (wrong bibliography), double-check ' ..
+               'your source file. The script will end ' ..
+               'now.', 74))
+    return 1
+  end
 
-                -- only show undefined
-                showUndefinedReferences(a,c)
+  local references = flatten(apply(bibliography, function(a)
+                     return extract(read(a)) end))
 
-            end
+  print()
+  print(wrap('Fantastic, I found ' .. tostring(#references) ..
+             ' ' .. plural(#references, 'reference',
+             'references') .. ' in ' .. tostring(#bibliography) ..
+             ' bibliography ' .. plural(#bibliography, 'file',
+             'files') .. '. Please wait a moment while the ' ..
+             plural(((check == 'all' and 2) or 1), 'report is',
+             'reports are') .. ' generated.', 74))
 
-        -- there's only one parameter, the file name,
-        -- so we set --all
-        else
+  return operations[check](citations, references)
+end
 
-            -- show everything
-            showUnusedReferences(a,c)
-            showUndefinedReferences(a,c)
+-- Call and exit
+os.exit(checkcites(arg))
 
-        end
+-- EOF
 
-    end
-
--- end of function
-end
-
--- run the main function
-runMain(arg)

Modified: trunk/Master/texmf-dist/doc/support/checkcites/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/checkcites/README	2017-08-25 22:25:59 UTC (rev 45130)
+++ trunk/Master/texmf-dist/doc/support/checkcites/README	2017-08-25 22:26:15 UTC (rev 45131)
@@ -1,10 +1,10 @@
-checkcites.lua -- Version 1.0i from December 18, 2012.
-======================================================
+checkcites.lua -- Version 2.0 from August 25, 2017.
+===================================================
 
 License
 -------
 
-Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+Copyright (c) 2012, 2017 Enrico Gregorio, Paulo Roberto Massa Cereda
 
 - Enrico dot Gregorio at univr dot it
 - cereda at users dot sf dot net
@@ -17,18 +17,18 @@
 -----
 
 checkcites is a Lua script written for the sole purpose of detecting
-unused or undefined references from both LaTeX auxiliary or
-bibliography files. We use 'unused reference' to refer to the
-reference present the bibliography file -- with the '.bib'
-extension -- but not cited in the '.tex' file. The 'undefined
-reference' is exactly the opposite, that is, the items cited in the
-'.tex' file, but not present in the '.bib' file.
+unused or undefined references from both LaTeX auxiliary or bibliography
+files. We use the term *unused reference* to refer to the reference
+present the bibliography file -- with the '.bib' extension -- but not
+cited in the '.tex' file. The term *undefined reference* is exactly the
+opposite, i.e, the item cited in the '.tex' file, but not present in the
+'.bib' file.
 
-The original idea came from a question posted in the TeX.sx community
-about how to check which bibliography entries were not used. We
-decided to write a script to check references. We opted for Lua,
-since it's a very straightforward language and it has an interpreter
-available on every modern TeX distribution.
+The original idea came from a question posted in the TEX community at
+Stack Exchange about how to check which bibliography entries were not
+used. We decided to write a script to check references. We opted for
+Lua, since it's a very straightforward language and it has an
+interpreter available on every modern TEX distribution.
 
 Installation
 ------------
@@ -62,15 +62,51 @@
 -----
 
 The script is pretty simple to use. The only requirement is a recent
-TeX distribution, such as TeX Live. Then run checkcites:
+TeX distribution, such as TeX Live.
 
+checkcites uses the generated auxiliary files to start the analysis.
+From version 2.0 on, the scripts supports two backends:
+
+-> bibtex
+
+Default behavior, the script checks '.aux' files looking for citations,
+in the form of '\citation{a}'. For every \citation line found, checkcites
+will extract the citations and add them to a table, even for multiple
+citations separated by commas, like '\citation{a,b,c}'. The citation
+table contains no duplicate values. At the same time checkcites also
+looks for bibliography data, in the form of '\bibdata{a}'. Similarly,
+for every '\bibdata' line found, the script will extract the bibliography
+data and add them to a table, even if they are separated by commas, like
+'\bibdata{d,e,f}'. Again, no duplicate values are allowed. Stick with this
+backend if you are using BibTeX or BibLaTeX with the 'backend=bibtex'
+package option.
+
+-> biber
+
+With this backend, the script checks '.bcf files' (which are XML-based)
+looking for citations, in the form of 'bcf:citekey' tags. For every tag
+found, checkcites will extract the corresponding values and add them to
+a table. The citation table contains no duplicate values. At the same
+time checkcites also looks for bibliography data, in the form of
+'bcf:datasource' tags. Similarly, for every tag found, the script will
+extract the bibliography data and add them to a table. Again, no duplicate
+values are allowed. Stick with this backend if you are using BibLaTeX with
+the default options or with the 'backend=biber' option explicitly set.
+
+Open a terminal and run checkcites:
+
 $ checkcites
 
-It will print the script usage. The only required argument is the
-'.aux' file which is generated when you compile your '.tex' file.
-If your main document is named 'foo.tex', you will have a 'foo.aux'
-file too. To run the script on that file, go with:
+When you run checkcites without providing any argument to it, the a message
+error will appear. Do not panic! Try again with the --help flag:
 
+$ checkcites --help
+
+If you are using BibTeX, simply provide the auxiliary file -- the one with
+the '.aux' extension -- which is generated when you compile your main '.tex'
+file. For example, if your main document is named 'foo.tex', you probably
+have a 'foo.aux' file too. Then simply invoke
+
 $ checkcites foo.aux
 
 checkcites allows an additional argument that will tell it how to
@@ -95,6 +131,18 @@
 
 If no special argument is provided, --all is set as default.
 
+If you are using BibLaTeX, we need to inspect '.bcf' files instead. For
+example, if your main document is named 'foo.tex', you probably have a
+'foo.bcf' file too. Then invoke
+
+$ checkcites foo.aux --backend biber
+
+Note the --backend flag used for BibLaTeX support. We can even omit the
+file extension, the script will automatically assign one based on the
+current backend.
+
+That is it, folks!
+
 Official code repository
 ------------------------
 

Modified: trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex	2017-08-25 22:25:59 UTC (rev 45130)
+++ trunk/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex	2017-08-25 22:26:15 UTC (rev 45131)
@@ -4,6 +4,7 @@
 \usepackage[utf8]{inputenc}
 
 \usepackage[english]{babel}
+\usepackage{tgpagella}
 
 \usepackage[margin=1in]{geometry}
 
@@ -15,7 +16,7 @@
 
 \newcommand{\checkcites}{\texttt{checkcites}}
 \newcommand{\email}[1]{\small\texttt{#1}}
-\newcommand{\version}{Version 1.0i from December 18, 2012.}
+\newcommand{\version}{Version 2.0 from August 25, 2017.}
 
 \newenvironment{infoblock}[1]
   {\par\addvspace{\medskipamount}
@@ -43,25 +44,25 @@
 \section{Introduction}
 \label{sec:intro}
 
-\checkcites\ is a Lua script written for the sole purpose of detecting
-unused or undefined references from both \LaTeX{} auxiliary or
-bibliography files. We use \emph{unused reference} to refer to the
-reference present the bibliography file --~with the \verb|.bib|
-extension~-- but not cited in the \verb|.tex| file. The
-\emph{undefined reference} is exactly the opposite, that is, the items
-cited in the \texttt{.tex} file, but not present in the \verb|.bib|
-file.
+\checkcites\  is  a  Lua  script  written for  the  sole  purpose  of
+detecting unused or undefined  references from both \LaTeX\ auxiliary
+or bibliography  files. We  use the  term \emph{unused  reference} to
+refer  to the  reference  present the  bibliography file~--~with  the
+\verb|.bib|  extension~--~but  not  cited in  the  \verb|.tex|  file.
+The  term \emph{undefined  reference} is  exactly the  opposite, i.e,
+the  item cited  in  the \verb|.tex|  file, but  not  present in  the
+\verb|.bib| file.
 
-The original idea came from a question posted in the
-\href{http://tex.stackexchange.com}{TeX.sx community} about
-\href{http://tex.stackexchange.com/questions/43276}{how to check which
-bibliography entries were not used}. We decided to write a script to
-check references. We opted for Lua, since it's a very straightforward
-language and it has an interpreter available on every modern \TeX\
-distribution.
+The    original     idea    came     from    a     question    posted
+in    the     \TeX\    community    at    Stack     Exchange    about
+\href{http://tex.stackexchange.com/questions/43276}{how    to   check
+which  bibliography entries  were not  used}. We  decided to  write a
+script  to check  references. We  opted for  Lua, since it is a  very
+straightforward language and it has an interpreter available on every
+modern \TeX\ distribution.
 
 \begin{infoblock}{Attention!}
-\checkcites\ is known to run with the most recent \verb|texlua| and
+\checkcites\ is known  to run with the most  recent \verb|texlua| and
 \verb|lua| interpreters. Unfortunately, the code is incompatible with
 interpreters prior to the Lua 5.1 language specification.
 \end{infoblock}
@@ -69,68 +70,79 @@
 \section{How the script works}
 \label{sec:howto}
 
-\checkcites\ uses the generated \verb|.aux| file to start the
-analysis. The first step is to extract all citations found, in the
-form of \verb|\citation{a}|. For every \verb|\citation| line found,
-\checkcites\ will extract the citations and add them to a table, even
-for multiple citations separated by commas, like
-\verb|\citation{a,b,c}|. Then the citations table has all duplicate
-values removed --~in other words, the table becomes a set.  Let's call
-$A$ the set of citations.
+\checkcites\  uses  the  generated   auxiliary  files  to  start  the
+analysis. From version 2.0 on, the scripts supports two backends:
 
-\begin{infoblock}{Attention!}
-If \verb|\citation{*}| is found, \checkcites\ will issue a message
-telling that \verb|\nocite{*}| is in the \verb|.tex| document, but
-the script will do the check nonetheless.
-\end{infoblock}
+\begin{description}
+\item[\texttt{bibtex}]   Default   behavior,    the   script   checks
+\verb|.aux|   files   looking  for   citations,   in   the  form   of
+\verb|\citation{a}|.   For   every   \verb|\citation|   line   found,
+\checkcites\  will   extract  the  citations   and  add  them   to  a
+table,  even  for  multiple   citations  separated  by  commas,  like
+\verb|\citation{a,b,c}|.  The citation  table  contains no  duplicate
+values. At  the same  time \checkcites\  also looks  for bibliography
+data,  in  the  form  of  \verb|\bibdata{a}|.  Similarly,  for  every
+\verb|\bibdata| line found, the  script will extract the bibliography
+data and add them  to a table, even if they  are separated by commas,
+like \verb|\bibdata{d,e,f}|. Again, no  duplicate values are allowed.
+Stick with this backend if you  are using Bib\TeX\ or Bib\LaTeX\ with
+the \verb|backend=bibtex| package option.
 
-At the same time \checkcites\ also looks for bibliography data, in the
-form of \verb|\bibdata{a}|. Similarly, for every \verb|\bibdata| line
-found, the script will extract the bibliography data and add them to a
-table, even if they are separated by commas, like
-\verb|\bibdata{d,e,f}|. The table has all duplicate values removed.
+\item[\texttt{biber}]   With   this   backend,  the   script   checks
+\verb|.bcf| files (which are XML-based) looking for citations, in the
+form of  \verb|bcf:citekey| tags.  For every tag  found, \checkcites\
+will extract  the corresponding values and  add them to a  table. The
+citation  table  contains  no  duplicate values.  At  the  same  time
+\checkcites\  also  looks  for  bibliography data,  in  the  form  of
+\verb|bcf:datasource|  tags.  Similarly,  for every  tag  found,  the
+script will  extract the bibliography data  and add them to  a table.
+Again, no  duplicate values are  allowed. Stick with this  backend if
+you  are  using Bib\LaTeX\  with  the  default  options or  with  the
+\verb|backend=biber| option explicitly set.
+\end{description}
 
 \begin{infoblock}{Attention!}
-If no \verb|\bibdata| command is found, the script ends. There's
-nothing to do in this case.
+If  \verb|\citation{*}|  (Bib\TeX)  or  simply  \verb|*|  (Bib\LaTeX)
+is   found,  \checkcites\   will   issue  a   message  telling   that
+\verb|\nocite{*}| is in the \verb|.tex| document, but the script will
+do the check nonetheless.
 \end{infoblock}
 
-Now, \checkcites\ will extract all entries from the bibliography files
-found in the previous step. For every element in the bibliography data
-table, the script will look for entries like \verb|@BOOK|,
-\verb|@ARTICLE| and so forth --~we actually use pattern matching for
-this~-- and add their identifiers to a table. The script treats all
-\verb|.bib| files as if they were only one. After all files have been
-analyzed and all entries' identifiers extracted, the table has all
-duplicate values removed. Let's call $B$ the set of bibliography
-entries.
+Now,  \checkcites\ will  extract  all entries  from the  bibliography
+files found  in the previous  steps, regardless of which  backend was
+used. For  every element in  the bibliography data table,  the script
+will  look  for entries  like  \verb|@BOOK|,  \verb|@ARTICLE| and  so
+forth~--~we actually use  pattern matching for this~--  and add their
+identifiers to a table. No duplicate values are allowed.
 
 \begin{infoblock}{Attention!}
-If \checkcites\ cannot find a certain bibliography file --~that is, a
-\verb|.bib| file~-- the script ends. Make sure to put the correct
-name of the bibliography file in your \verb|.tex| file.
+If \checkcites\ cannot  find a certain bibliography  file, the script
+ends. Make sure  to put the correct name of  the bibliography file in
+your \verb|.tex| file.
 \end{infoblock}
 
-Now we have both sets $A$ and $B$. In order to get all unused
-references in the \verb|.bib| files, we compute the set difference
+Let  there be  $A$  and $B$  the sets  of  citations and  references,
+respectively.  In  order   to  get  all  unused   references  in  the
+\verb|.bib| files, we compute the set difference:
 \[
 B - A = \{ x : x \in B, x \notin A \}.
-\] 
-Similarly, in order to get all undefined references in the \verb|.tex|
-file, we compute the set difference
+\]
+Similarly,  in  order   to  get  all  undefined   references  in  the
+\verb|.tex| file, we compute the set difference:
 \[
 A - B = \{ x : x \in A, x \notin B \}.
 \]
 If there are either unused or undefined references, \checkcites\ will
-print them in a list format. In Section~\ref{sec:usage} there's a more
-complete explanation on how to use the script.
+print them  in a list  format. In Section~\ref{sec:usage} there  is a
+more complete explanation on how to use the script.
 
 \section{Usage}
 \label{sec:usage}
 
-\checkcites\ is very easy to use. First of all, let's define two files
-that will be used here to explain the script usage. Here's our sample
-bibliography file \verb|example.bib|, with five fictional entries.
+\checkcites\ is  very easy to  use. First of  all, let us  define two
+files that will be used here to explain the script usage. Here is our
+sample  bibliography  file  \verb|example.bib|, with  five  fictional
+entries.
 
 \begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
                    title=Bibliography file, fonttitle=\bfseries,
@@ -176,7 +188,9 @@
 }
 \end{tcblisting}
 
-The second file is our main \LaTeX{} document, \verb|document.tex|.
+The second  file is  our main \LaTeX{}  document, \verb|document.tex|.
+Observe that we will stick with  Bib\TeX\ for now and check Bib\LaTeX\
+later on.
 
 \begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
                    title=Main document, fonttitle=\bfseries,
@@ -185,7 +199,8 @@
 
 \begin{document}
 
-Hello world \cite{foo:2012a,foo:2012c}, how are you \cite{foo:2012f},
+Hello world \cite{foo:2012a,foo:2012c},
+how are you \cite{foo:2012f},
 and goodbye \cite{foo:2012d,foo:2012a}.
 
 \bibliographystyle{plain}
@@ -200,26 +215,29 @@
 \begin{verbatim}
 $ checkcites
 \end{verbatim}
-\tcblower
+\tcblower\small
 \begin{verbatim}
-checkcites.lua -- a reference checker script (v1.0i)
-Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+     _           _       _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+|  _|   | -_|  _| '_|  _| |  _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
 
-Usage: checkcites.lua [--all | --unused | --undefined] file.aux
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
 
---all         Lists all unused and undefined references.
---unused      Lists only unused references in your 'bib' file.
---undefined   Lists only undefined references in your 'tex' file.
-
-If no flag is provided, '--all' is set by default.
-Be sure to have all your 'bib' files in the same directory.
+--------------------------------------------------------------------------
+I am sorry, but you have not provided any command line argument, including
+files to check and options. Make sure to invoke the script with the actual
+arguments. Refer to the user documentation if you are unsure of how this
+tool works. The script will end now.
 \end{verbatim}
 \end{terminal}
 
-If you don't have \checkcites\ installed with your \TeX\ distribution,
-you can run the standalone script \verb|checkcites.lua| with either
-\verb|texlua| or \verb|lua|. We recommend to use \verb|texlua|, as
-it's shipped with all the modern \TeX\ distributions:
+If  you   do  not  have   \checkcites\  installed  with   your  \TeX\
+distribution, you can run the standalone script \verb|checkcites.lua|
+with  either  \verb|texlua|  or   \verb|lua|.  We  recommend  to  use
+\verb|texlua|,  as   it  is  shipped   with  all  the   modern  \TeX\
+distributions:
 \begin{terminal}
 \begin{verbatim}
 $ texlua checkcites.lua
@@ -226,20 +244,52 @@
 \end{verbatim}
 \end{terminal}
 
-When you run \checkcites\ without providing any argument to it, the
-script usage will be printed, as seen in the previous output. The only
-required argument is the auxiliary file --~with the \verb|.aux|
-extension~-- which is generated when you compile your main \verb|.tex|
-file. For example, if your main document is named \verb|foo.tex|, you
-probably have a \verb|foo.aux| file too. Let's compile our sample
-document \verb|document.tex|:
+When you run \checkcites\ without providing any argument to it, the a
+message  error  will  appear.  Do  not  panic!  Try  again  with  the
+\verb|--help| flag:
 \begin{terminal}
 \begin{verbatim}
+$ checkcites --help
+\end{verbatim}
+\tcblower\small
+\begin{verbatim}
+     _           _       _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+|  _|   | -_|  _| '_|  _| |  _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
+
+Usage: checkcites.lua [ [ --all | --unused | --undefined ] [ --backend
+<arg> ] <file> [ <file 2> ... <file n> ] | --help | --version ]
+
+-a,--all           list all unused and undefined references
+-u,--unused        list only unused references in your bibliography files
+-U,--undefined     list only undefined references in your TeX source file
+-b,--backend <arg> set the backend-based file lookup policy
+-h,--help          print the help message
+-v,--version       print the script version
+
+Unless specified, the script lists all unused and undefined references by
+default. Also, the default backend is set to "bibtex". Please refer to the
+user documentation for more details.
+\end{verbatim}
+\end{terminal}
+
+Since  we  are  using  Bib\TeX,  we   do  not  need  to  set  up  the
+backend!  Simply  provide  the  auxiliary file~--~the  one  with  the
+\verb|.aux|  extension~--~which is  generated when  you compile  your
+main \verb|.tex|  file. For example,  if your main document  is named
+\verb|foo.tex|, you probably  have a \verb|foo.aux| file  too. Let us
+compile our sample document \verb|document.tex|:
+\begin{terminal}
+\begin{verbatim}
 $ pdflatex document.tex
 \end{verbatim}
 \end{terminal}
 
-After running \verb|pdflatex| on our \verb|.tex| file, there's now a
+After running \verb|pdflatex| on our \verb|.tex| file, there is now a
 \verb|document.aux| file in our work directory.
 
 \begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
@@ -261,31 +311,49 @@
 \begin{verbatim}
 $ checkcites document.aux
 \end{verbatim}
-\tcblower
+\tcblower\small
 \begin{verbatim}
-checkcites.lua -- a reference checker script (v1.0i)
-Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+     _           _       _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+|  _|   | -_|  _| '_|  _| |  _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
 
-I found 4 citation(s).
-Great, there's only one 'bib' file. Let me check it.
-I found 5 reference(s).
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
 
-Unused reference(s) in your bibliography file(s): 2
-- foo:2012b
-- foo:2012e
+Great, I found 4 citations in 1 file. I also found 1 bibliography file. Let
+me check this file and extract the references. Please wait a moment.
 
-Undefined reference(s) in your TeX file: 1
-- foo:2012f
+Fantastic, I found 5 references in 1 bibliography file. Please wait a
+moment while the reports are generated.
+
+--------------------------------------------------------------------------
+Report of unused references in your TeX document (that is, references
+present in bibliography files, but not cited in the TeX source file)
+--------------------------------------------------------------------------
+
+Unused references in your TeX document: 2
+=> foo:2012b
+=> foo:2012e
+
+--------------------------------------------------------------------------
+Report of undefined references in your TeX document (that is, references
+cited in the TeX source file, but not present in the bibliography files)
+--------------------------------------------------------------------------
+
+Undefined references in your TeX document: 1
+=> foo:2012f
 \end{verbatim}
 \end{terminal}
 
-As we can see in the script output, \checkcites\ analyzed both
-\verb|.aux| and \verb|.bib| files and found two unused references in
-the bibliography file --~\verb|foo:2012b| and \verb|foo:2012e|~-- and
-one undefined reference in the document --~\verb|foo:2012f|.
+As  we   can  see  in   the  script  output,   \checkcites\  analyzed
+both  \verb|.aux|  and \verb|.bib|  files  and  managed to  find  two
+unused  references   in  the   bibliography  file~--~\verb|foo:2012b|
+and   \verb|foo:2012e|~--~and   one   undefined  reference   in   the
+document~--~\verb|foo:2012f|.
 
-\checkcites\ allows a command line switch that will tell it how to
-behave. For example,
+\checkcites\ allows a couple of command  line flags that will tell it
+how to behave. For example, check this command line:
 
 \begin{terminal}
 \begin{verbatim}
@@ -293,9 +361,9 @@
 \end{verbatim}
 \end{terminal}
 
-The \verb|--unused| flag will make the script only look for unused
-references in the \verb|.bib| file. The argument order doesn't matter,
-you can also run
+The \verb|--unused|  flag will make  the script only look  for unused
+references  in the  \verb|.bib|  file. The  argument  order does  not
+matter, you can also run:
 
 \begin{terminal}
 \begin{verbatim}
@@ -303,7 +371,7 @@
 \end{verbatim}
 \end{terminal}
 
-The script will behave the same. Similarly, you can use
+The script will behave the same. Similarly, you can use:
 
 \begin{terminal}
 \begin{verbatim}
@@ -311,9 +379,9 @@
 \end{verbatim}
 \end{terminal}
 
-The \verb|--undefined| flag will make the script only look for
-undefined references in the \verb|.tex| file. If you want \checkcites\
-to look for both unused and undefined references, run:
+The  \verb|--undefined|   flag  will   make  the  script   only  look
+for  undefined  references  in  the \verb|.tex|  file.  If  you  want
+\checkcites\ to look for both unused and undefined references, run:
 
 \begin{terminal}
 \begin{verbatim}
@@ -321,15 +389,113 @@
 \end{verbatim}
 \end{terminal}
 
-If no special argument is provided, the \verb|--all| flag is set as default.
+If no  special argument is provided,  the \verb|--all| flag is  set as
+default.
 
+Observe  that  our  example  relied  on  the  default  backend,  which
+uses  Bib\TeX.  Let   us  change  our  document  a  bit   to  make  it
+Bib\LaTeX-compliant:
+
+\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
+                   title=Main document, fonttitle=\bfseries,
+                   listing options={columns=fullflexible,basicstyle=\ttfamily}}
+\documentclass{article}
+
+\usepackage{biblatex}
+\addbibresource{example.bib}
+
+\begin{document}
+
+Hello world \cite{foo:2012a,foo:2012c},
+how are you \cite{foo:2012f},
+and goodbye \cite{foo:2012d,foo:2012a}.
+
+\printbibliography
+
+\end{document}
+\end{tcblisting}
+
+As usual, let's compile our sample document \verb|document.tex|:
+
+\begin{terminal}
+\begin{verbatim}
+$ pdflatex document.tex
+\end{verbatim}
+\end{terminal}
+
+After running \verb|pdflatex| on our \verb|.tex| file, there is now a
+\verb|document.aux| file in our work directory, as expected. However,
+since  we are  using Bib\LaTeX\  as well,  there is  another file  of
+interest  in  our  working  directory, one  that  has  a  \verb|.bcf|
+extension! In  order to  run \checkcites\ on  that specific  file, we
+need to provide the \verb|biber| backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document.bcf
+\end{verbatim}
+\end{terminal}
+
+We can  even omit  the file extension,  the script  will automatically
+assign one based on the current backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document
+\end{verbatim}
+\end{terminal}
+
+Now, let  us run \checkcites\  on the \verb|.bcf| file,  providing the
+\verb|biber| backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document.bcf
+\end{verbatim}
+\tcblower\small
+\begin{verbatim}
+     _           _       _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+|  _|   | -_|  _| '_|  _| |  _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
+
+Great, I found 4 citations in 1 file. I also found 1 bibliography file. Let
+me check this file and extract the references. Please wait a moment.
+
+Fantastic, I found 5 references in 1 bibliography file. Please wait a
+moment while the reports are generated.
+
+--------------------------------------------------------------------------
+Report of unused references in your TeX document (that is, references
+present in bibliography files, but not cited in the TeX source file)
+--------------------------------------------------------------------------
+
+Unused references in your TeX document: 2
+=> foo:2012b
+=> foo:2012e
+
+--------------------------------------------------------------------------
+Report of undefined references in your TeX document (that is, references
+cited in the TeX source file, but not present in the bibliography files)
+--------------------------------------------------------------------------
+
+Undefined references in your TeX document: 1
+=> foo:2012f
+\end{verbatim}
+\end{terminal}
+
+That is all, folks!
+
 \section{License}
 \label{sec:license}
 
-This script is licensed under the
-\href{http://www.latex-project.org/lppl/}{LaTeX Project Public
-License}. If you want to support \LaTeX{} development by a donation,
-the best way to do this is donating to the
+This        script        is         licensed        under        the
+\href{http://www.latex-project.org/lppl/}{\LaTeX\    Project   Public
+License}.  If  you   want  to  support  \LaTeX{}   development  by  a
+donation,   the  best   way   to   do  this   is   donating  to   the
 \href{http://www.tug.org/}{TeX Users Group}.
 
 \begin{infoblock}{Official code repository}

Modified: trunk/Master/texmf-dist/scripts/checkcites/checkcites.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/checkcites/checkcites.lua	2017-08-25 22:25:59 UTC (rev 45130)
+++ trunk/Master/texmf-dist/scripts/checkcites/checkcites.lua	2017-08-25 22:26:15 UTC (rev 45131)
@@ -1,684 +1,721 @@
 #!/usr/bin/env texlua
--- ******************************************************************
+-- -----------------------------------------------------------------
 -- checkcites.lua
--- Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+-- Copyright 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
 --
--- This work may be distributed and/or modified under the
--- conditions of the LaTeX Project Public License, either version 1.3
--- of this license or (at your option) any later version.
+-- This work may be distributed and/or modified under the conditions
+-- of the LaTeX  Project Public License, either version  1.3 of this
+-- license or (at your option) any later version.
 --
 -- The latest version of this license is in
---   http://www.latex-project.org/lppl.txt
--- and version 1.3 or later is part of all distributions of LaTeX
+--
+-- http://www.latex-project.org/lppl.txt
+--
+-- and version  1.3 or later is  part of all distributions  of LaTeX
 -- version 2005/12/01 or later.
 --
--- This work has the LPPL maintenance status `maintained'.
--- 
--- The Current Maintainers of this work are the original authors.
+-- This  work  has the  LPPL  maintenance  status `maintained'.  the
+-- current maintainers of  this work are the  original authors. This
+-- work consists of the file checkcites.lua.
 --
--- This work consists of the file checkcites.lua.
---
--- Project page: http://github.com/cereda/checkcites
--- ******************************************************************
+-- Project repository: http://github.com/cereda/checkcites
+-- -----------------------------------------------------------------
 
--- version and date, to be updated on each release/commit
-VERSION = "1.0i"
-DATE = "December 18, 2012"
-
--- globals
--- warning about \citation{*}
-globalAsteriskWarning = true
-
--- The following code adds a 'split' function to the string type,
--- thanks to the codebase available here:
--- http://lua-users.org/wiki/SplitJoin
-string.split = function(str, pattern)
-
-    pattern = pattern or "[^%s]+"
-    
-    if pattern:len() == 0 then
-    
-        pattern = "[^%s]+"
-    
+-- Checks if the table contains the element.
+-- @param a Table.
+-- @param hit Element.
+-- @return Boolean value if the table contains the element.
+local function exists(a, hit)
+  for _, v in ipairs(a) do
+    if v == hit then
+      return true
     end
-    
-    local parts = {__index = table.insert}
-    
-    setmetatable(parts, parts)
-    
-    str:gsub(pattern, parts)
-    
-    setmetatable(parts, nil)
-    
-    parts.__index = nil
-    
-    return parts
-
+  end
+  return false
 end
 
--- In order to make our lives easier, we borrowed the following
--- codes for implementing common set operations, available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setFind(a, tbl)
-
-	for _,a_ in ipairs(tbl) do
-        
-        if a_==a then
-            
-            return true
+-- Parses the list of arguments based on a configuration map.
+-- @param map Configuration map.
+-- @param args List of command line arguments.
+-- @return Table containing the valid keys and entries.
+-- @return Table containing the invalid keys.
+local function parse(map, args)
+  local keys, key, unknown = {}, 'unpaired', {}
+  local a, b
+  for _, v in ipairs(args) do
+    a, _, b = string.find(v, '^%-(%w)$')
+    if a then
+      for _, x in ipairs(map) do
+        key = 'unpaired'
+        if x['short'] == b then
+          key = x['long']
+          break
         end
-    
-    end
-
-end
-
--- This code returns a table containing the difference between
--- the two other tables, also available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setDifference(a, b)
-
-	local ret = {}
-
-	for _,a_ in ipairs(a) do
-
-		if not setFind(a_,b) then
-            
-            table.insert(ret, a_)
-        
+      end
+      if key == 'unpaired' then
+        table.insert(unknown, '-' .. b)
+      end
+      if not keys[key] then
+        keys[key] = {}
+      end
+    else
+      a, _, b = string.find(v, '^%-%-([%w-]+)$')
+      if a then
+        for _, x in ipairs(map) do
+          key = 'unpaired'
+          if x['long'] == b then
+            key = b
+            break
+          end
         end
-
-	end
-
-	return ret
-
-end
-
--- Code to remove duplicates from a table array.
-function removeDuplicates(tb)
-
-    -- new table
-    local ret = {}
-
-    -- flag to spot new insertions
-    local flag
-
-    -- set local variables
-    local i
-    local k
-    local j
-    local l
-
-    -- iterate through the original table
-    for i, k in pairs(tb) do
-
-        -- at first, insert element
-        flag = true
-
-        -- iterate through the new table
-        for j, l in pairs(ret) do
-
-            -- if the element already exists
-            if k == l then
-
-                -- set flag to false, so the
-                -- new element won't be inserted
-                flag = false
-
-            end
-
+        if key == 'unpaired' then
+          if not exists(unknown, '--' .. b) then
+            table.insert(unknown, '--' .. b)
+          end
         end
-
-        -- if it's ok to insert
-        if flag then
-
-            -- insert new element
-            table.insert(ret, k)
-
+        if not keys[key] then
+          keys[key] = {}
         end
-
-    end
-
-    -- return new table
-    return ret
-end
-
--- This function opens and gets all data from the provided
--- aux file.
--- Return:
---   * list of citations
---   * list of bibfiles
-function getDataFromAuxFile(theAuxFile)
-
-    -- open a file handler
-	local fileHandler = io.open(theAuxFile,"r")
-
-    -- check if the handler is valid
-	if fileHandler then
-
-        -- create a local table for citations
-		local theCitations = {}
-
-        -- and a local reference to the bib file
-		local theBibFiles = {}
-
-        -- define local variables
-        local currentLine
-        local citation
-        local index
-        local theCitation
-        local theBibFile
-        local entry
-
-        -- now let's iterate through the lines
-		for currentLine in fileHandler:lines() do
-
-            -- if the citation matches, extract it
-			for citation in string.gmatch(currentLine, '\\citation{(.+)}') do
-
-                -- sanity check, in case it's an '*'
-				if citation ~= "*" then
-
-                    -- break the citations list, in case of multiple
-                    -- citations in the same \citation{}
-					local parts = string.split(citation, "[^,%s]+" )
-
-                    -- for every entry in the citations list
-					for index, theCitation in pairs(parts) do
-                        
-                        -- insert the reference
-						table.insert(theCitations, theCitation)
-
-					end
-
-                -- found a '*'
-                else
-
-                    -- check if warning is still valid, that is,
-                    -- if not displayed yet
-                    if globalAsteriskWarning then
-
-                        -- show message
-                        print("Warning: '\\nocite{*}' found, I'll do the check nonetheless.\n")
-
-                        -- warning already displayed, so
-                        -- set flag to false
-                        globalAsteriskWarning = false
-
-                    end
-
-                end
-
-            -- end of citation in current line
+      else
+        if not keys[key] then
+          keys[key] = {}
+        end
+        if key ~= 'unpaired' then
+          for _, x in ipairs(map) do
+            if x['long'] == key then
+              if not (x['argument'] and
+                 #keys[key] == 0) then
+                key = 'unpaired'
+              end
+              break
             end
-
-            -- in the same current line, check if there's the 
-            -- bibdata entry and extract it
-			for entry in string.gmatch(currentLine, '\\bibdata{(.+)}') do
-
-                -- break the bib files list, in case of multiple
-                -- files in the same \bibdata{}
-				local parts = string.split(entry, "[^,%s]+" )
-
-                -- for every entry in the bib files list
-				for index, theBibFile in pairs(parts) do
-
-                    -- insert the file
-        			table.insert(theBibFiles, theBibFile)
-
-				end
-
-            -- end of bib files in the current line
-            end
-
-        -- end of current line
-        end
-
-        -- close the file handler
-		fileHandler:close()
-
-        -- remove duplicated citations
-        theCitations = removeDuplicates(theCitations)
-
-        -- print a message about the citations
-		print("I found " .. #theCitations .. " citation(s).")
-
-        -- remove possible duplicated files
-        theBibFiles = removeDuplicates(theBibFiles)
-
-        -- if there are no bib files
-        if #theBibFiles == 0 then
-
-            -- show message
-            print("I couldn't find any bibliography files.\nI'm afraid I have nothing to do now.")
-
-            -- and abort the script
-    		os.exit()
-
-        -- if there is only one bib file
-        elseif #theBibFiles == 1 then
-
-            -- show message
-            print("Great, there's only one 'bib' file. Let me check it.")
-
-        -- there are more bib files
+          end
+          if not keys[key] then
+            keys[key] = {}
+          end
+          table.insert(keys[key], v)
         else
-
-            -- show message
-            print("Oh no, I have to check more than one 'bib' file. Please wait.")
-
+          if not keys[key] then
+            keys[key] = {}
+          end
+          table.insert(keys[key], v)
         end
+      end
+    end
+  end
+  return keys, unknown
+end
 
-        -- return both citations and bib files
-        return theCitations, theBibFiles
-
-    -- the file handler is invalid
-    else
-
-        -- print an error message
-		print("File '" .. theAuxFile .. "' does not exist or is unavailable. Aborting script.")
-
-        -- and abort the script
-		os.exit()
-
+-- Calculates the difference between two tables.
+-- @param a First table.
+-- @param b Second table.
+-- @return Table containing the difference between two tables.
+local function difference(a, b)
+  local result = {}
+  for _, v in ipairs(a) do
+    if not exists(b, v) then
+      table.insert(result, v)
     end
+  end
+  return result
+end
 
--- end of function
+-- Splits the string based on a pattern.
+-- @param str String.
+-- @param pattern Pattern.
+local function split(str, pattern)
+  local result = {}
+  string.gsub(str, pattern, function(a)
+              table.insert(result, a) end)
+  return result
 end
 
--- This function opens and gets all data from all the available
--- bib files.
-function getDataFromBibFiles(theBibFiles)
-
-    -- create a table to store the citations
-	local theReferences = {}
-
-    -- set local variables
-    local index
-    local theBibFile
-    local currentLine
-    local reference
-
-    -- iterate through all bib files
-    for index, theBibFile in pairs(theBibFiles) do
-
-        -- open the bib file
-		local fileHandler = io.open(theBibFile .. ".bib","r")
-
-        -- check if the handler is valid
-		if fileHandler then
-
-            -- iterate through every line of the bib file
-			for currentLine in fileHandler:lines() do
-
-                -- if a reference is found
-				for reference in string.gmatch(currentLine, '@%w+{%s*(.+),') do
-
-                    -- insert the reference
-					table.insert(theReferences, reference)
-
-                end
-
-            -- end current line
-            end
-
-            -- close the file handler
-			fileHandler:close()
-
-        -- bib file does not exist
-        else
-
-            -- error message
-			print("File '" .. theBibFile .. ".bib' does not exist. Aborting.")
-
-			-- abort script
-			os.exit()
-
-        end
-
-    -- end iteration through the bib files
+-- Reads lines from a file.
+-- @param file File.
+-- @returns Table representing the lines.
+local function read(file)
+  local handler = io.open(file, 'r')
+  local lines = {}
+  if handler then
+    for line in handler:lines() do
+      table.insert(lines, line)
     end
+    handler:close()
+  end
+  return lines
+end
 
-    -- remove duplicated references
-    theReferences = removeDuplicates(theReferences)
-
-    -- print message
-	print("I found " .. #theReferences .. " reference(s).")
-
-    -- return references
-	return theReferences
-
--- end of function
+-- Normalizes the string, removing leading and trailing spaces.
+-- @param str String.
+-- @return Normalized string without leading and trailing spaces.
+local function normalize(str)
+  local result, _ = string.gsub(str, '^%s', '')
+  result, _ = string.gsub(result, '%s$', '')
+  return result
 end
 
--- This function show all the undefined references. It's very
--- simple, it's a difference between two sets.
-function showUndefinedReferences(citations, references)
-
-    -- get all undefined references
-	local undefined = setDifference(citations, references)
-
-    -- print message
-    print("\nUndefined reference(s) in your TeX file: " .. #undefined)
-
-	-- if there are undefined references
-	if #undefined ~= 0 then
-
-        -- local variables
-        local index
-        local reference
-
-		-- iterate
-		for index, reference in pairs(undefined) do
-
-			-- and print
-			print("- " .. reference)
-
-		end
-
+-- Checks if the element is in a blacklist.
+-- @param a Element.
+-- @return Boolean value if the element is blacklisted.
+local function blacklist(a)
+  local list = {}
+  for _, v in ipairs(list) do
+    if v == a then
+      return true
     end
-
--- end of function
+  end
+  return false
 end
 
--- This function show all the unused references. It's very
--- simple, it's a difference between two sets.
-function showUnusedReferences(citations, references)
-
--- get all undefined references
-	local unused = setDifference(references, citations)
-
-    -- print message
-   	print("\nUnused reference(s) in your bibliography file(s): " .. #unused)
-
-	-- if there are unused references
-	if #unused ~= 0 then
-
-        -- local variables
-        local index
-        local reference
-
-		-- iterate
-		for index, reference in pairs(unused) do
-
-			-- and print
-			print("- " .. reference)
-
-		end
-        
+-- Extracts the biblographic key.
+-- @param lines Lines of a file.
+-- @return Table containing bibliographic keys.
+local function extract(lines)
+  local result = {}
+  for _, line in ipairs(lines) do
+    local hit = string.match(line,
+                '^%s*%@%w+%s*{%s*(.+),')
+    if hit then
+      if not exists(result, hit) then
+        hit = normalize(hit)
+        table.insert(result, hit)
+      end
     end
+  end
+  return result
+end
 
--- end of function
+-- Gets a pluralized word based on a counter.
+-- @param i Counter.
+-- @param a Word in singular.
+-- @param b Word in plural.
+-- @return Either the first or second word based on the counter.
+local function plural(i, a, b)
+  if i == 1 then
+    return a
+  else
+    return b
+  end
 end
 
--- This function parses the command line arguments and returns a
--- bunch of info for us to use.
--- Return:
---   * an argument code
---   * the filename
---   * an action code
-function parseArguments(theArgs)
+-- Backend namespace
+local backends = {}
 
-    -- check if there are no arguments
-    if #theArgs == 0 then
-
-        -- return usage code
-        return 0, nil, nil
-
-    -- there is one argument
-    elseif #theArgs == 1 then
-
-        -- check if it's help
-        if theArgs[1] == "--help" then
-
-            -- return help code
-            return 1, nil, nil
-
-            -- check if it's version
-        elseif theArgs[1] == "--version" then
-
-            -- return version code
-            return 2, nil, nil
-
-        -- check if it's invalid
-        elseif string.sub(theArgs[1], 1, 1) == "-" then
-
-            -- return invalid code
-            return 3, nil, nil
-
-        -- it seems a clean argument
-        else
-
-            -- return it as a valid argument
-            return 4, theArgs[1], nil
-
-        -- end for one parameter
+-- Gets data from auxiliary files (BibTeX).
+-- @param lines Lines of a file.
+-- @return Boolean indicating if an asterisk was found.
+-- @return Table containing the citations.
+-- @return Table containing the bibliography files.
+backends.bibtex = function(lines)
+  local citations, bibliography = {}, {}
+  local asterisk, parts, hit = false
+  for _, line in ipairs(lines) do
+    hit = string.match(line, '^%s*\\citation{(.+)}$')
+    if hit then
+      if hit ~= '*' then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(citations, v) then
+            table.insert(citations, v)
+          end
         end
+      else
+        asterisk = true
+      end
+    else
+      hit = string.match(line, '^%s*\\bibdata{(.+)}$')
+      if hit then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(bibliography, v) and
+             not blacklist(v) then
+            table.insert(bibliography, v)
+          end
+        end
+      end
+    end
+  end
+  return asterisk, citations, bibliography
+end
 
-    -- there are two arguments
-    elseif #theArgs == 2 then
-
-        -- check if both are valid
-        if ((theArgs[1] == "--all" or theArgs[1] == "--unused" or theArgs[1] == "--undefined") and string.sub(theArgs[2], 1, 1) ~= "-") or ((theArgs[2] == "--all" or theArgs[2] == "--unused" or theArgs[2] == "--undefined") and string.sub(theArgs[1], 1, 1) ~= "-") then
-
-            -- create an action code
-            local actionCode
-
-            -- check which one is the file name
-            if string.sub(theArgs[1], 1, 1) ~= "-" then
-
-                -- check for --all
-                if theArgs[2] == "--all" then
-
-                    -- set the action code
-                    actionCode = 0
-
-                -- check for --unused
-                elseif theArgs[2] == "--unused" then
-
-                    -- set the action code
-                    actionCode = 1
-
-                -- it's --undefined
-                else
-
-                    -- set the action code
-                    actionCode = 2
-
-                end
-
-                -- it's the first
-                return 4, theArgs[1], actionCode
-
-            else
-
-                -- check for --all
-                if theArgs[1] == "--all" then
-
-                    -- set the action code
-                    actionCode = 0
-
-                -- check for --unused
-                elseif theArgs[1] == "--unused" then
-
-                    -- set the action code
-                    actionCode = 1
-
-                else
-
-                    -- it's --undefined
-                    actionCode = 2
-
-                end
-
-                -- it's the second
-                return 4, theArgs[2], actionCode
-
-            end
-
-        else
-
-            -- return invalid code
-            return 3, nil, nil
-
+-- Gets data from auxiliary files (Biber).
+-- @param lines Lines of a file.
+-- @return Boolean indicating if an asterisk was found.
+-- @return Table containing the citations.
+-- @return Table containing the bibliography files.
+backends.biber = function(lines)
+  local citations, bibliography = {}, {}
+  local asterisk, parts, hit = false
+  for _, line in ipairs(lines) do
+    hit = string.match(line, '^%s*<bcf:citekey order="%d+">' ..
+          '(.+)</bcf:citekey>$')
+    if hit then
+      if hit ~= '*' then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(citations, v) then
+            table.insert(citations, v)
+          end
         end
-
+      else
+        asterisk = true
+      end
     else
-
-        -- more than two arguments, return usage code
-        return 0, nil, nil
-
+      hit = string.match(line, '^%s*<bcf:datasource type="file" ' ..
+            'datatype="%w+">(.+)</bcf:datasource>$')
+      if hit then
+        parts = split(hit, '[^,%s]+')
+        for _, v in ipairs(parts) do
+          v = normalize(v)
+          if not exists(bibliography, v) and
+             not blacklist(v) then
+            table.insert(bibliography, v)
+          end
+        end
+      end
     end
+  end
+  return asterisk, citations, bibliography
+end
 
--- end of function
+-- Counts the number of elements of a nominal table.
+-- @param t Table.
+-- @return Table size.
+local function count(t)
+  local counter = 0
+  for _, _ in pairs(t) do
+    counter = counter + 1
+  end
+  return counter
 end
 
--- This function prints the script header.
-function printHeader()
+-- Repeats the provided char a certain number of times.
+-- @param c Char.
+-- @param w Number of times.
+-- @return String with a char repeated a certain number of times.
+local function pad(c, w)
+  local r = c
+  while #r < w do
+    r = r .. c
+  end
+  return r
+end
 
-    -- print message
-	print("checkcites.lua -- a reference checker script (v" .. VERSION .. ")")
-	print("Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda\n")
+-- Adds the extension if the file does not have it.
+-- @param file File.
+-- @param extension Extension.
+-- @return File with proper extension.
+local function sanitize(file, extension)
+  extension = '.' .. extension
+  if string.sub(file, -#extension) ~= extension then
+    file = file .. extension
+  end
+  return file
+end
 
--- end of function
+-- Flattens a table of tables into only one table.
+-- @param t Table.
+-- @return Flattened table.
+local function flatten(t)
+  local result = {}
+  for _, v in ipairs(t) do
+    for _, k in ipairs(v) do
+      if not exists(result, k) then
+        table.insert(result, k)
+      end
+    end
+  end
+  return result
 end
 
--- This function prints the script usage
-function printUsage()
+-- Applies a function to elements of a table.
+-- @param c Table.
+-- @param f Function.
+-- @return A new table.
+local function apply(c, f)
+  local result = {}
+  for _, v in ipairs(c) do
+    table.insert(result, f(v))
+  end
+  return result
+end
 
-    -- show message
-	print("Usage: " .. arg[0] .. " [--all | --unused | --undefined] file.aux\n")
-    print("--all         Lists all unused and undefined references.")
-    print("--unused      Lists only unused references in your 'bib' file.")
-    print("--undefined   Lists only undefined references in your 'tex' file.\n")
-    print("If no flag is provided, '--all' is set by default.")
-	print("Be sure to have all your 'bib' files in the same directory.")
+-- Wraps a string based on a line width.
+-- @param str String.
+-- @param size Line width.
+-- @return Wrapped string.
+local function wrap(str, size)
+  local parts = split(str, '[^%s]+')
+  local r, l = '', ''
+  for _, v in ipairs(parts) do
+    if (#l + #v) > size then
+      r = r .. '\n' .. l
+      l = v
+    else
+      l = normalize(l .. ' ' .. v)
+    end
+  end
+  r = normalize(r .. '\n' .. l)
+  return r
+end
 
--- end of function
+-- Prints the script header.
+local function header()
+print("     _           _       _ _")
+print(" ___| |_ ___ ___| |_ ___|_| |_ ___ ___")
+print("|  _|   | -_|  _| '_|  _| |  _| -_|_ -|")
+print("|___|_|_|___|___|_,_|___|_|_| |___|___|")
+print()
+  print(wrap('checkcites.lua -- a reference ' ..
+             'checker script (v2.0)', 74))
+  print(wrap('Copyright (c) 2012, 2017, ' ..
+             'Enrico Gregorio, Paulo ' ..
+             'Roberto Massa Cereda', 74))
 end
 
-function printHelp()
+-- Operation namespace
+local operations = {}
 
-    -- show message
-    print("checkcites.lua is a Lua script written for the sole purpose of")
-    print("detecting undefined/unused references from LaTeX auxiliary or")
-    print("bibliography files. It's very easy to use!\n")
+-- Reports the unused references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer representing the status.
+operations.unused = function(citations, references)
+  print()
+  print(pad('-', 74))
+  print(wrap('Report of unused references in your TeX ' ..
+             'document (that is, references present in ' ..
+             'bibliography files, but not cited in ' ..
+             'the TeX source file)', 74))
+  print(pad('-', 74))
+  local r = difference(references, citations)
+  print()
+  print(wrap('Unused references in your TeX document: ' ..
+             tostring(#r), 74))
+  if #r == 0 then
+    return 0
+  else
+    for _, v in ipairs(r) do
+      print('=> ' .. v)
+    end
+    return 1
+  end
+end
 
-    -- print usage
-    printUsage()
+-- Reports the undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.undefined = function(citations, references)
+  print()
+  print(pad('-', 74))
+  print(wrap('Report of undefined references in your TeX ' ..
+             'document (that is, references cited in the ' ..
+             'TeX source file, but not present in the ' ..
+             'bibliography files)', 74))
+  print(pad('-', 74))
+  local r = difference(citations, references)
+  print()
+  print(wrap('Undefined references in your TeX document: ' ..
+        tostring(#r), 74))
+  if #r == 0 then
+    return 0
+  else
+    for _, v in ipairs(r) do
+      print('=> ' .. v)
+    end
+    return 1
+  end
+end
 
--- end of function
+-- Reports both unused and undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.all = function(citations, references)
+  local x, y
+  x = operations.unused(citations, references)
+  y = operations.undefined(citations, references)
+  if x + y > 0 then
+    return 1
+  else
+    return 0
+  end
 end
 
--- This function prints the script version.
-function printVersion()
+-- Checks if a file exists.
+-- @param file File.
+-- @return Boolean value indicating if the file exists.
+local function valid(file)
+  local handler = io.open(file, 'r')
+  if handler then
+    handler:close()
+    return true
+  else
+    return false
+  end
+end
 
-    -- print message
-    print("checkcites.lua version " .. VERSION .. " (dated " .. DATE .. ")")
-    print("You can find more information about this script in the official")
-    print("source code repository:\n")
-    print("http://github.com/cereda/checkcites\n")
-    print("checkcites.lua is licensed under the LaTeX Project Public License.")
-
--- end of function
+-- Filters a table of files, keeping the inexistent ones.
+-- @param files Table.
+-- @return Table of inexistent files.
+local function validate(files)
+  local result = {}
+  for _, v in ipairs(files) do
+    if not valid(v) then
+      table.insert(result, v)
+    end
+  end
+  return result
 end
 
--- This function prints a message for invalid parameters.
-function printInvalid()
+-- Main function.
+-- @param args Command line arguments.
+-- @return Integer value indicating the status
+local function checkcites(args)
+  header()
 
-    -- print message
-    print("Oh no, it seems you used an invalid argument.\n")
+  local parameters = {
+    { short = 'a', long = 'all', argument = false },
+    { short = 'u', long = 'unused', argument = false },
+    { short = 'U', long = 'undefined', argument = false },
+    { short = 'v', long = 'version', argument = false },
+    { short = 'h', long = 'help', argument = false },
+    { short = 'b', long = 'backend', argument = true }
+  }
 
-    -- print usage
-    printUsage()
+  local keys, err = parse(parameters, args)
+  local check, backend = 'all', 'bibtex'
 
--- end of function
-end
+  if #err ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I do not recognize ' ..
+               'the following ' .. plural(#err, 'option',
+               'options') .. ':', 74))
+    for _, v in ipairs(err) do
+      print('=> ' .. v)
+    end
 
--- This is our main function.
-function runMain(theArgs)
+    print()
+    print(wrap('Please make sure to use the correct ' ..
+               'options when running this script. You ' ..
+               'can also refer to the user documentation ' ..
+               'for a list of valid options. The script ' ..
+               'will end now.', 74))
+    return 1
+  end
 
-   	-- print the script header
-	printHeader()
+  if count(keys) == 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but you have not provided ' ..
+               'any command line argument, including ' ..
+               'files to check and options. Make ' ..
+               'sure to invoke the script with the actual ' ..
+               'arguments. Refer to the user documentation ' ..
+               'if you are unsure of how this tool ' ..
+               'works. The script will end now.', 74))
+    return 1
+  end
 
-    -- set local variables
-    local argCode
-    local fileName
-    local actionCode
+  if keys['version'] or keys['help'] then
+    if keys['version'] then
+      print()
+      print(wrap('checkcites.lua, version 2.0 (dated August ' ..
+                 '25, 2017)', 74))
 
-    -- parse arguments and get the result
-    argCode, fileName, actionCode = parseArguments(theArgs)
+      print(pad('-', 74))
+      print(wrap('You can find more details about this ' ..
+                 'script, as well as the user documentation, ' ..
+                 'in the official source code repository:', 74))
 
-    -- check for usage
-    if argCode == 0 then
+      print()
+      print('https://github.com/cereda/checkcites')
 
-        -- print usage
-        printUsage()
+      print()
+      print(wrap('The checkcites.lua script is licensed ' ..
+                 'under the LaTeX Project Public License, ' ..
+                 'version 1.3. The current maintainers ' ..
+                 'are the original authors.', 74))
+    else
+      print()
+      print(wrap('Usage: ' .. args[0] .. ' [ [ --all | --unused | ' ..
+                 '--undefined ] [ --backend <arg> ] <file> [ ' ..
+                 '<file 2> ... <file n> ] | --help | --version ' ..
+                 ']', 74))
 
-    -- it's help
-    elseif argCode == 1 then
+      print()
+      print('-a,--all           list all unused and undefined references')
+      print('-u,--unused        list only unused references in your bibliography files')
+      print('-U,--undefined     list only undefined references in your TeX source file')
+      print('-b,--backend <arg> set the backend-based file lookup policy')
+      print('-h,--help          print the help message')
+      print('-v,--version       print the script version')
 
-        -- print help
-        printHelp()
+      print()
+      print(wrap('Unless specified, the script lists all unused and ' ..
+                 'undefined references by default. Also, the default ' ..
+                 'backend is set to "bibtex". Please refer to the user ' ..
+                 'documentation for more details.', 74))
+    end
+    return 0
+  end
 
-    -- it's version
-    elseif argCode == 2 then
+  if not keys['unpaired'] then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but you have not provided ' ..
+               'files to process. The tool requires ' ..
+               'least one file in order to properly ' ..
+               'work. Make sure to invoke the script ' ..
+               'with an actual file (or files). Refer ' ..
+               'to the user documentation if you are ' ..
+               'unsure of how this tool works. The ' ..
+               'script will end now.', 74))
+    return 1
+  end
 
-        -- print version
-        printVersion()
+  if keys['backend'] then
+    if not exists({ 'bibtex', 'biber' }, keys['backend'][1]) then
+      print()
+      print(pad('-', 74))
+      print(wrap('I am sorry, but you provided an ' ..
+                 'invalid backend. I know two: ' ..
+                 '"bibtex" (which is the default ' ..
+                 'one) and "biber". Please make ' ..
+                 'sure to select one of the two. ' ..
+                 'Also refer to the user documentation ' ..
+                 'for more information on how these ' ..
+                 'backends work. The script will end ' ..
+                 'now.', 74))
+      return 1
+    else
+      backend = keys['backend'][1]
+    end
+  end
 
-    -- it's an invalid parameter
-    elseif argCode == 3 then
+  if not keys['all'] then
+    if keys['unused'] and keys['undefined'] then
+      check = 'all'
+    elseif keys['unused'] or keys['undefined'] then
+      check = (keys['unused'] and 'unused') or
+              (keys['undefined'] and 'undefined')
+    end
+  end
 
-        -- print invalid
-        printInvalid()
+  local auxiliary = apply(keys['unpaired'], function(a)
+                    return sanitize(a, (backend == 'bibtex'
+                    and 'aux') or 'bcf') end)
 
-    -- it's a valid operation
-    else
+  local vld = validate(auxiliary)
+  if #vld ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I was unable to ' ..
+               'locate ' .. plural(#vld, 'this file',
+               'these files')  .. ' (the extension ' ..
+               'is automatically set based on the ' ..
+               '"' .. backend .. '" backend):', 74))
+    for _, v in ipairs(vld) do
+      print('=> ' .. v)
+    end
 
-        -- get data from aux
-        a, b = getDataFromAuxFile(fileName)
+    print()
+    print(wrap('Selected backend: ' .. backend, 74))
+    print(wrap('File lookup policy: add ".' ..
+               ((backend == 'bibtex' and 'aux') or 'bcf') ..
+               '" to files if not provided.', 74))
 
-        -- get data from bib
-        c = getDataFromBibFiles(b)
+    print()
+    print(wrap('Please make sure the ' .. plural(#vld,
+               'path is', 'paths are') .. ' ' ..
+               'correct and the ' .. plural(#vld,
+               'file exists', 'files exist') ..  '. ' ..
+               'There is nothing I can do at the moment. ' ..
+               'Refer to the user documentation for ' ..
+               'details on the file lookup. If ' .. plural(#vld,
+               'this is not the file', 'these are not the ' ..
+               'files') .. ' you were expecting, ' ..
+               'double-check your source file or ' ..
+               'change the backend option when running ' ..
+               'this tool. The script will end now.', 74))
+    return 1
+  end
 
-        -- if there is an action code
-        if actionCode ~= nil then
+  local lines = flatten(apply(auxiliary, read))
+  local asterisk, citations, bibliography = backends[backend](lines)
 
-            -- it's --all
-            if actionCode == 0 then
+  print()
+  print(wrap('Great, I found ' .. tostring(#citations) .. ' ' ..
+             plural(#citations, 'citation', 'citations') .. ' in ' ..
+             tostring(#auxiliary) .. ' ' .. plural(#auxiliary, 'file',
+             'files') ..'. I also found ' .. tostring(#bibliography) ..
+             ' ' .. 'bibliography ' .. plural(#bibliography, 'file',
+             'files') .. '. Let me check ' .. plural(#bibliography,
+             'this file', 'these files') .. ' and extract the ' ..
+             'references. Please wait a moment.', 74))
 
-                -- do everything
-                showUnusedReferences(a,c)
-                showUndefinedReferences(a,c)
+  if asterisk then
+    print()
+    print(wrap('Also, it is worth noticing that I found a mention to ' ..
+               'a special "*" when retrieving citations. That means ' ..
+               'your TeX document contains "\\nocite{*}" somewhere in ' ..
+               'the source code. I will continue with the check ' ..
+               'nonetheless.', 74))
+  end
 
-            -- it's --unused
-            elseif actionCode == 1 then
+  bibliography = apply(bibliography, function(a)
+                 return sanitize(a, 'bib') end)
 
-                -- only show unused
-                showUnusedReferences(a,c)
+  vld = validate(bibliography)
+  if #vld ~= 0 then
+    print()
+    print(pad('-', 74))
+    print(wrap('I am sorry, but I was unable to locate ' ..
+               plural(#vld, 'this file', 'these files') .. ' ' ..
+               '(the extension is automatically set to ' ..
+               '".bib", if not provided):', 74))
+    for _, v in ipairs(vld) do
+      print('=> ' .. v)
+    end
 
-            -- it's --undefined
-            else
+    print()
+    print(wrap('Please make sure the ' .. plural(#vld,
+               'path is', 'paths are') .. ' ' ..
+               'correct and the ' .. plural(#vld,
+               'file exists', 'files exist') ..  '. ' ..
+               'There is nothing I can do at the moment. ' ..
+               'Refer to to the user documentation ' ..
+               'for details on bibliography lookup. If ' ..
+               plural(#vld, 'this is not the file',
+               'these are not the files') .. ' you were ' ..
+               'expecting (wrong bibliography), double-check ' ..
+               'your source file. The script will end ' ..
+               'now.', 74))
+    return 1
+  end
 
-                -- only show undefined
-                showUndefinedReferences(a,c)
+  local references = flatten(apply(bibliography, function(a)
+                     return extract(read(a)) end))
 
-            end
+  print()
+  print(wrap('Fantastic, I found ' .. tostring(#references) ..
+             ' ' .. plural(#references, 'reference',
+             'references') .. ' in ' .. tostring(#bibliography) ..
+             ' bibliography ' .. plural(#bibliography, 'file',
+             'files') .. '. Please wait a moment while the ' ..
+             plural(((check == 'all' and 2) or 1), 'report is',
+             'reports are') .. ' generated.', 74))
 
-        -- there's only one parameter, the file name,
-        -- so we set --all
-        else
+  return operations[check](citations, references)
+end
 
-            -- show everything
-            showUnusedReferences(a,c)
-            showUndefinedReferences(a,c)
+-- Call and exit
+os.exit(checkcites(arg))
 
-        end
+-- EOF
 
-    end
-
--- end of function
-end
-
--- run the main function
-runMain(arg)



More information about the tex-live-commits mailing list