summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/support/texosquery/TeXOSQuery.java681
-rw-r--r--Master/texmf-dist/source/support/texosquery/texosquery.dtx725
-rw-r--r--Master/texmf-dist/source/support/texosquery/texosquery.ins45
3 files changed, 1451 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/support/texosquery/TeXOSQuery.java b/Master/texmf-dist/source/support/texosquery/TeXOSQuery.java
new file mode 100644
index 00000000000..6b4f2a5c715
--- /dev/null
+++ b/Master/texmf-dist/source/support/texosquery/TeXOSQuery.java
@@ -0,0 +1,681 @@
+package com.dickimawbooks.texosquery;
+
+import java.util.Locale;
+import java.util.Calendar;
+import java.io.*;
+
+public class TeXOSQuery
+{
+ public static String escapeHash(String str)
+ {
+ return str.replaceAll("#", "\\\\#");
+ }
+
+ public static String getLocale(Locale locale)
+ {
+ return getLocale(locale, false);
+ }
+
+ public static String getLocale(Locale locale, boolean convertCodeset)
+ {
+ String id = "";
+
+ if (locale != null)
+ {
+ String lang = locale.getLanguage();
+
+ if (lang != null)
+ {
+ id = lang;
+ }
+
+ String country = locale.getCountry();
+
+ if (country != null && !country.isEmpty())
+ {
+ if (id.isEmpty())
+ {
+ id = country;
+ }
+ else
+ {
+ id = id+"-"+country;
+ }
+ }
+
+ String codeset = System.getProperty("file.encoding");
+
+ if (codeset != null && !codeset.isEmpty())
+ {
+ if (convertCodeset)
+ {
+ codeset = codeset.toLowerCase().replaceAll("-", "");
+ }
+
+ id = id+"."+codeset;
+ }
+
+ String script = locale.getScript();
+
+ if (script != null && !script.isEmpty())
+ {
+ id = id+"@"+escapeHash(script);
+ }
+
+ }
+
+ return id;
+ }
+
+ public static String getOSname()
+ {
+ try
+ {
+ return escapeHash(System.getProperty("os.name", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ public static String getOSarch()
+ {
+ try
+ {
+ return escapeHash(System.getProperty("os.arch", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ public static String getOSversion()
+ {
+ try
+ {
+ return escapeHash(System.getProperty("os.version", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ public static String getUserHome()
+ {
+ try
+ {
+ return toTeXPath(System.getProperty("user.home", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ /*
+ * Since this is designed to work within TeX, backslashes in paths
+ * need to be replaced with forward slashes.
+ */
+
+ public static String toTeXPath(String filename)
+ {
+ if (filename == null)
+ {
+ return "";
+ }
+
+ if (File.separatorChar == '\\')
+ {
+ filename = filename.replaceAll("\\\\", "/");
+ }
+
+ return escapeHash(filename);
+ }
+
+ public static String fromTeXPath(String filename)
+ {
+ if (File.separatorChar != '/')
+ {
+ return filename.replaceAll("/", File.separator);
+ }
+
+ return filename;
+ }
+
+ public static File fileFromTeXPath(String filename)
+ {
+ filename = fromTeXPath(filename);
+
+ File file = new File(filename);
+
+ if (!file.exists() && file.getParent() == null)
+ {
+ // use kpsewhich to find it
+
+ try
+ {
+ Process p = new ProcessBuilder("kpsewhich", filename).start();
+
+ if (p.waitFor() == 0)
+ {
+ InputStream is = p.getInputStream();
+
+ if (is != null)
+ {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(is));
+
+ String line = in.readLine();
+
+ in.close();
+
+ if (line != null && !line.isEmpty())
+ {
+ file = new File(fromTeXPath(line));
+ }
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+
+ return file;
+ }
+
+ public static String getCwd()
+ {
+ try
+ {
+ return toTeXPath(System.getProperty("user.dir", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ public static String getTmpDir()
+ {
+ try
+ {
+ return toTeXPath(System.getProperty("java.io.tmpdir", ""));
+ }
+ catch (SecurityException e)
+ {
+ return "";
+ }
+ }
+
+ public static String pdfnow()
+ {
+ Calendar cal = Calendar.getInstance();
+
+ return pdfDate(cal);
+ }
+
+ public static String pdfDate(Calendar cal)
+ {
+ String tz = String.format("%1$tz", cal);
+
+ return String.format("D:%1$tY%1$tm%1td%1$tH%1$tM%1$tS%2$s'%3$s'", cal,
+ tz.substring(0,3), tz.substring(3));
+ }
+
+ public static String pdfDate(File file)
+ {
+ try
+ {
+ long millisecs = file.lastModified();
+
+ if (millisecs > 0L)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(millisecs);
+
+ return pdfDate(cal);
+ }
+ }
+ catch (SecurityException e)
+ {
+ }
+
+ return "";
+ }
+
+ public static String getFileLength(File file)
+ {
+ try
+ {
+ long len = file.length();
+
+ if (len > 0L)
+ {
+ return String.format("%d", len);
+ }
+ }
+ catch (SecurityException e)
+ {
+ }
+
+ return "";
+ }
+
+ public static String getFileList(String sep, File dir)
+ {
+ if (!dir.isDirectory())
+ {
+ return "";
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ try
+ {
+ String[] list = dir.list();
+
+ if (list == null)
+ {
+ return "";
+ }
+
+ for (int i = 0; i < list.length; i++)
+ {
+ if (i > 0)
+ {
+ builder.append(sep);
+ }
+
+ // no need to worry about directory divider
+ // File.list() just returns the name not the path
+ builder.append(escapeHash(list[i]));
+ }
+ }
+ catch (SecurityException e)
+ {
+ }
+
+ return builder.toString();
+ }
+
+ public static String getFilterFileList(String sep,
+ final String regex, File dir)
+ {
+ if (!dir.isDirectory())
+ {
+ return "";
+ }
+
+ if (regex == null || regex.isEmpty())
+ {
+ return getFileList(sep, dir);
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ try
+ {
+ String[] list = dir.list(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name)
+ {
+ return name.matches(regex);
+ }
+ });
+
+ if (list == null)
+ {
+ return "";
+ }
+
+ for (int i = 0; i < list.length; i++)
+ {
+ if (i > 0)
+ {
+ builder.append(sep);
+ }
+
+ // no need to worry about directory divider
+ // File.list() just returns the name not the path
+ builder.append(escapeHash(list[i]));
+ }
+ }
+ catch (SecurityException e)
+ {
+ }
+
+ return builder.toString();
+ }
+
+ public static String fileURI(File file)
+ {
+ if (!file.exists())
+ {
+ return "";
+ }
+
+ try
+ {
+ // don't worry about '#' as it would've been converted to
+ // %23 (\TeXOSQuery changes the catcode of %)
+ return file.toURI().toString();
+ }
+ catch (SecurityException e)
+ {
+ }
+
+ return "";
+ }
+
+ public static String filePath(File file)
+ {
+ if (!file.exists())
+ {
+ return "";
+ }
+
+ try
+ {
+ return toTeXPath(file.getCanonicalPath());
+ }
+ catch (SecurityException e)
+ {
+ }
+ catch (IOException e)
+ {
+ }
+
+ return "";
+ }
+
+ public static void syntax()
+ {
+ System.out.println("Usage: texosquery <option>...");
+
+ System.out.println();
+ System.out.println("Cross-platform OS query application");
+ System.out.println("for use with TeX's shell escape.");
+ System.out.println();
+ System.out.println("Each query displays the result in a single line.");
+ System.out.println("A blank line is printed if the requested");
+ System.out.println("information is unavailable.");
+
+ System.out.println();
+ System.out.println("-h or --help\tDisplay this help message and exit");
+ System.out.println("-v or --version\tDisplay version information and exit");
+ System.out.println();
+ System.out.println("General:");
+ System.out.println();
+ System.out.println("-L or --locale\t\tDisplay locale information");
+ System.out.println("-l or --locale-lcs\tAs --locale but codeset ");
+ System.out.println("\t\t\tin lowercase with hyphens stripped");
+ System.out.println("-c or --cwd\t\tDisplay current working directory");
+ System.out.println("-m or --userhome\tDisplay user's home directory");
+ System.out.println("-t or --tmpdir\t\tDisplay temporary directory");
+ System.out.println("-o or --osname\t\tDisplay OS name");
+ System.out.println("-r or --osversion\tDisplay OS version");
+ System.out.println("-a or --osarch\t\tDisplay OS architecture");
+ System.out.println("-n or --pdfnow\t\tDisplay current date-time in PDF format");
+
+ System.out.println();
+ System.out.println("File Queries:");
+ System.out.println();
+ System.out.println("Paths should use / for the directory divider.");
+ System.out.println();
+ System.out.println("-d <file> or --pdfdate <file>");
+ System.out.println(" Display date stamp of <file> in PDF format");
+ System.out.println();
+ System.out.println("-s <file> or --filesize <file>");
+ System.out.println(" Display size of <file> in bytes");
+ System.out.println();
+ System.out.println("-i <sep> <dir> or --list <sep> <dir>");
+ System.out.println(" Display list of all files in <dir> separated by <sep>");
+ System.out.println();
+ System.out.println("-f <sep> <regex> <dir> or --filterlist <sep> <regex> <dir>");
+ System.out.println(" Display list of files in <dir> that match <regex> separated by <sep>");
+ System.out.println();
+ System.out.println("-u <file> or --uri <file>");
+ System.out.println(" Display the URI of <file>");
+ System.out.println();
+ System.out.println("-p <file> or --path <file>");
+ System.out.println(" Display the canonical path of <file>");
+
+ }
+
+ public static void version()
+ {
+ System.out.println(String.format("texosquery %s %s", versionNum,
+ versionDate));
+ System.out.println("Copyright 2016 Nicola Talbot");
+ System.out.println("License LPPL 1.3+ (http://ctan.org/license/lppl1.3)");
+ }
+
+ public static void main(String[] args)
+ {
+ if (args.length == 0)
+ {
+ System.err.println("Missing argument. Try texosquery --help");
+ System.exit(1);
+ }
+
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].equals("-L") || args[i].equals("--locale"))
+ {
+ System.out.println(getLocale(Locale.getDefault()));
+ }
+ else if (args[i].equals("-l") || args[i].equals("--locale-lcs"))
+ {
+ System.out.println(getLocale(Locale.getDefault(), true));
+ }
+ else if (args[i].equals("-c") || args[i].equals("--cwd"))
+ {
+ System.out.println(getCwd());
+ }
+ else if (args[i].equals("-m") || args[i].equals("--userhome"))
+ {
+ System.out.println(getUserHome());
+ }
+ else if (args[i].equals("-t") || args[i].equals("--tmpdir"))
+ {
+ System.out.println(getTmpDir());
+ }
+ else if (args[i].equals("-r") || args[i].equals("--osversion"))
+ {
+ System.out.println(getOSversion());
+ }
+ else if (args[i].equals("-a") || args[i].equals("--osarch"))
+ {
+ System.out.println(getOSarch());
+ }
+ else if (args[i].equals("-o") || args[i].equals("--osname"))
+ {
+ System.out.println(getOSname());
+ }
+ else if (args[i].equals("-n") || args[i].equals("--pdfnow"))
+ {
+ System.out.println(pdfnow());
+ }
+ else if (args[i].equals("-d") || args[i].equals("--pdfdate"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("filename expected after %s", args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(pdfDate(fileFromTeXPath(args[i])));
+ }
+ }
+ else if (args[i].equals("-s") || args[i].equals("--filesize"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("filename expected after %s", args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(getFileLength(fileFromTeXPath(args[i])));
+ }
+ }
+ else if (args[i].equals("-i") || args[i].equals("--list"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("separator and directory name expected after %s",
+ args[i-1]));
+ System.exit(1);
+ }
+
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("directory name expected after %s %s",
+ args[i-2], args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(getFileList(args[i-1],
+ new File(fromTeXPath(args[i]))));
+ }
+ }
+ else if (args[i].equals("-f") || args[i].equals("--filterlist"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format(
+ "separator, regex and directory name expected after %s",
+ args[i-1]));
+ System.exit(1);
+ }
+
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("regex and directory name expected after %s %s",
+ args[i-2], args[i-1]));
+ System.exit(1);
+ }
+
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("directory name expected after %s %s",
+ args[i-3], args[i-2], args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(getFilterFileList(
+ args[i-2], args[i-1], new File(fromTeXPath(args[i]))));
+ }
+ }
+ else if (args[i].equals("-u") || args[i].equals("--uri"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("filename expected after %s", args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(fileURI(fileFromTeXPath(args[i])));
+ }
+ }
+ else if (args[i].equals("-p") || args[i].equals("--path"))
+ {
+ i++;
+
+ if (i >= args.length)
+ {
+ System.err.println(
+ String.format("filename expected after %s", args[i-1]));
+ System.exit(1);
+ }
+
+ if (args[i].isEmpty())
+ {
+ System.out.println();
+ }
+ else
+ {
+ System.out.println(filePath(fileFromTeXPath(args[i])));
+ }
+ }
+ else if (args[i].equals("-h") || args[i].equals("--help"))
+ {
+ syntax();
+ System.exit(0);
+ }
+ else if (args[i].equals("-v") || args[i].equals("--version"))
+ {
+ version();
+ System.exit(0);
+ }
+ else
+ {
+ System.err.println(String.format("unknown option '%s'", args[i]));
+ System.exit(1);
+ }
+ }
+ }
+
+ public static final String versionNum = "1.0";
+ public static final String versionDate = "2016-07-08";
+}
diff --git a/Master/texmf-dist/source/support/texosquery/texosquery.dtx b/Master/texmf-dist/source/support/texosquery/texosquery.dtx
new file mode 100644
index 00000000000..35d3afc97cb
--- /dev/null
+++ b/Master/texmf-dist/source/support/texosquery/texosquery.dtx
@@ -0,0 +1,725 @@
+%\iffalse
+%<*package>
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%</package>
+%\fi
+% \iffalse
+% Doc-Source file
+% Copyright (C) 2016 Nicola Talbot, all rights reserved.
+% \fi
+% \iffalse
+%<*driver>
+\documentclass{ltxdoc}
+
+\usepackage[T1]{fontenc}
+\usepackage{tgtermes}
+\usepackage{metalogo}
+\usepackage[colorlinks,hyperindex=false]{hyperref}
+
+\CheckSum{234}
+
+\RecordChanges
+\PageIndex
+\CodelineNumbered
+\IndexPrologue{}
+
+\renewcommand*{\usage}[1]{\hyperpage{#1}}
+\renewcommand*{\main}[1]{\hyperpage{#1}}
+
+\newcommand*{\shortargfmt}[1]{\texttt{-#1}}
+\newcommand*{\longargfmt}[1]{\texttt{-{}-#1}}
+
+\newcommand*{\shortarg}[1]{\shortargfmt{#1}%
+ \index{texosquery options=\texttt{texosquery} options>#1=\protect\shortargfmt{-#1}|hyperpage}}
+\newcommand*{\longarg}[1]{\longargfmt{#1}%
+ \index{texosquery options=\texttt{texosquery} options>#1=\protect\longargfmt{#1}|hyperpage}}
+
+\newenvironment{important}
+ {\begin{quote}\textbf{Important Note:}}
+ {\end{quote}}
+
+\begin{document}
+\DocInput{texosquery.dtx}
+\end{document}
+%</driver>
+%\fi
+%
+%\DeleteShortVerb{|}
+%
+%\title{texosquery: query OS information from \TeX}
+%\author{Nicola L. C. Talbot\\\url{http://www.dickimaw-books.com/}}
+%\date{2016-07-08 (v1.0)}
+%\maketitle
+%
+%\begin{abstract}
+%\texttt{texosquery.jar} is a cross-platform Java application
+%to query certain OS information designed for use in \TeX's
+%shell escape mechanism.
+%The accompanying \TeX\ code provides a simple interface to the
+%\texttt{texosquery} Java application, which may be skipped
+%if you want to explicitly use \cs{input} (but take
+%care of any special characters appearing in the result).
+%\end{abstract}
+%
+%\begin{important}
+%You will need \TeX's shell escape enabled,
+%and you will also need the Java Runtime Environment (JRE)
+%installed to use \texttt{texosquery}.
+%\end{important}
+%
+%\tableofcontents
+%
+%\section{texosquery.jar: the Java application}
+%The \texttt{texosquery} Java command line application looks up
+%certain system information that may be of use in \TeX\
+%documents. All this information can easily be obtained using
+%native commands, but the Java application allows an
+%OS-independent approach with results that can easily be
+%captured by \TeX's shell-escape without having to strip
+%formatting information.
+%
+%\begin{important}
+%\texttt{texosquery} provides read-only actions, and I don't
+%intend adding any actions that modify system settings or files.
+%\end{important}
+%
+%Since the application is designed to work with \TeX, each
+%function will display the result on a single line without
+%formatting. A blank line will be displayed if the information
+%isn't available. A forward slash is always used as a
+%directory divider, regardless of the operating system, so
+%the result can be used, for example, in \cs{input} or
+%\cs{includegraphics}.
+%
+%If an input file name is required (for example, with the
+%\longargfmt{pdfdate} argument described below) then the file may be in
+%the current working directory, relative to the current directory
+%(with forward slash \texttt{/} as the directory divider), an absolute path
+%(again with forward slash) or on \TeX's path (in
+%which case, \texttt{kpsewhich} is used to locate it).
+%
+%Command line invocation:
+%\begin{flushleft}\ttfamily
+%texosquery \meta{action} ...
+%\end{flushleft}
+%Available actions (at least one required):
+%\begin{description}
+%\item[\shortarg{L} or \longarg{locale}] Display the locale
+%information in the form
+%\begin{flushleft}\ttfamily
+%\meta{lang}-\meta{region}.\meta{codeset}@\meta{modifier}
+%\end{flushleft}
+%where \meta{lang} is the ISO code for the language (e.g.\
+%\texttt{en}),
+%\meta{region} is the ISO code for the region (e.g.\ \texttt{GB}),
+%\meta{codeset} is the default code set (e.g.\ \texttt{UTF-8})
+% and \meta{modifier} is the modifier. Elements may be omitted
+% if unavailable. For example, \texttt{en-GB.UTF-8} has the
+% \meta{modifier} omitted, and \texttt{en} has all but the language
+% omitted.
+%\item[\shortarg{l} or \longarg{locale-lcs}] As the above but the
+%codeset (if present) is converted to lower case and any hyphens are
+%stripped. For example, if \longargfmt{locale} returns
+%\texttt{en-GB.UTF-8}, then \longargfmt{locale-lcs} would return
+%\texttt{en-GB.utf8}.
+%\item[\shortarg{c} or \longarg{cwd}] Displays the current working
+%directory.
+%\item[\shortarg{m} or \longarg{userhome}] Displays the user's home
+%directory.
+%\item[\shortarg{t} or \longarg{tmpdir}] Displays the temporary
+%directory.
+%\item[\shortarg{o} or \longarg{osname}] Displays the operating
+%system name.
+%\item[\shortarg{r} or \longarg{osversion}] Displays the operating
+%system version.
+%\item[\shortarg{a} or \longarg{osarch}] Displays the operating
+%system architecture.
+%\item[\shortarg{n} or \longarg{pdfnow}] Displays the current
+% date and time in PDF format. For example
+%\begin{verbatim}
+%D:20160704131006+01'00'
+%\end{verbatim}
+%Note that some, but not all, \TeX\ formats provide
+%\cs{pdfcreationdate}, which is more efficient than using the shell
+%escape, but this can be used
+%as a fallback method for those that don't (for example, \XeTeX).
+%\item[\shortarg{d} \meta{file} or \longarg{pdfdate} \meta{file}]
+% Displays the last modified time stamp of the given file in PDF format or a blank line
+% if the file doesn't exist or the file permissions prohibit this
+% action.
+%Again some, but not all, \TeX\ formats provide
+%\cs{pdffilemoddate}\marg{file}, which is more efficient than using
+%the shell escape.
+%\item[\shortarg{s} \meta{file} or \longarg{filesize} \meta{file}]
+% Displays the size in bytes of the given file or a blank line
+% if the file doesn't exist or the file permissions prohibit this
+% action.
+%Some, but not all, \TeX\ formats provide
+%\cs{pdffilesize}\marg{file}, which is more efficient than using
+%the shell escape.
+%\item[\shortarg{i} \meta{sep} \meta{dir} or \longarg{list}
+%\meta{sep} \meta{dir}]
+%List all files in the given directory with the output on a single
+%line using \meta{sep} as the separator between entries. Note that
+%the list doesn't include the full path, just the file names.
+%\item[\shortarg{f} \meta{sep} \meta{regex} \meta{dir} or
+%\longarg{filterlist} \meta{sep} \meta{regex} \meta{dir}]
+%Like the above but only lists those files whose name matches the
+%regular expression given in \meta{regex}. Note that this tests for a
+%complete match on the file name (not including path). For example,
+%if \meta{regexp} is \texttt{foo.*}, it will only match files whose
+%name starts with \texttt{foo} (for example, \texttt{foobar} will
+%match but \texttt{barfoo} won't).
+%\item[\shortarg{u} \meta{file} or \longarg{uri} \meta{file}]
+%Displays the URI of the given file or a blank line if the file
+%doesn't exist or the file permissions prohibit this action.
+%Note that this may include in a percent character in the result. The \TeX\
+%command \cs{TeXOSQuery} protects against this by changing the
+%category code, but if you explicitly call \texttt{texosquery}
+%using the shell escape, you'll need to be careful of this.
+%\item[\shortarg{p} \meta{file} or \longarg{path} \meta{file}]
+%Displays the canonical path of the given file or a blank line if
+%the file doesn't exists or the file permissions prohibit this
+%action.
+%\item[\shortarg{h} or \longarg{help}] Displays help message and
+%exits.
+%\item[\shortarg{v} or \longarg{version}] Displays version
+%information and exits.
+%\end{description}
+%
+%If multiple options are given, they will be processed in the
+%order specified in the command line invocation. Each result will
+%be displayed on a separate line.
+%
+%\section{texosquery.tex: generic \TeX\ code}
+%You can run \texttt{texosquery} directly from \TeX's shell escape.
+%For example:
+%\begin{verbatim}
+%\input|"texosquery --locale"
+%\end{verbatim}
+%However, \texttt{texosquery.tex} provides generic \TeX\ code to do
+%this for you and store the result in a control sequence.
+%
+%Plain \TeX\ users can input this file through the usual \cs{input}
+%method:
+%\begin{verbatim}
+%\input texosquery
+%\end{verbatim}
+%\LaTeX\ users may also simply input this file:
+%\begin{verbatim}
+%\input{texosquery}
+%\end{verbatim}
+%but may prefer the standard package approach:
+%\begin{verbatim}
+%\usepackage{texosquery}
+%\end{verbatim}
+%
+%\begin{important}
+%The commands described below are all fragile.
+%\end{important}
+%
+%The basic command to run \texttt{texosquery} and capture its output
+%in a control sequence is:
+%\DescribeMacro\TeXOSQuery
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQuery}\marg{cs}\marg{args}
+%\end{flushleft}
+%where \meta{cs} is the control sequence in which to store the
+%result and \meta{args} are the command line arguments to pass to
+%\texttt{texosquery}. This first locally changes the category code
+%of some problematic characters that may appear in the result.
+%The only special characters that aren't changed are the backslash
+%\verb|\|, curly braces \verb|{| and \verb|}|, and hash \verb|#|.
+%(\texttt{texosquery.jar} will replace \verb|#| with \verb|\#| in places
+%where it might possibly occur in the result, but in general it's
+%best to avoid these characters in file names.)
+%There are some short cut commands for convenience, described below.
+%
+%If any of these commands cause an error message in the form:
+%\begin{verbatim}
+%I can't find file `|texosquery'.
+%\end{verbatim}
+%then check that you have the shell escape on. If the error
+%persists with the shell escape enabled
+%(and not restricted), check that \texttt{texosquery} is on
+%your system's path. To do this, open a command prompt or terminal and
+%type \texttt{texosquery}. If it isn't installed correctly, there will be a
+%message like:
+%\begin{verbatim}
+%`texosquery' is not recognised
+%\end{verbatim}
+%or
+%\begin{verbatim}
+%texosquery: command not found
+%\end{verbatim}
+%If this happens, check the installation. (Instructions are
+%in the accompanying \texttt{README.md} file.)
+%
+%Dry run mode is determined by the conditional
+%\DescribeMacro\ifTeXOSQueryDryRun
+%\begin{verbatim}
+%\ifTeXOSQueryDryRun
+%\end{verbatim}
+%If true, the shell escape won't be used and the requested command
+%invocation will be printed in the transcript file prefixed with
+%\begin{verbatim}
+%TeXOSQuery:
+%\end{verbatim}
+%(the control sequence \meta{cs} will be set to empty).
+%This conditional will automatically be switched on if
+%\cs{shellescape} or \cs{pdfshellescape} is 0.
+%
+%The locale (\shortarg{l} or \longarg{locale-lcs}) information can be
+%obtained using:
+%\DescribeMacro\TeXOSQueryLocale
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryLocale}\marg{cs}
+%\end{flushleft}
+%Note that this uses the lower case codeset form, which has a better
+%chance of matching the encoding names used by the \texttt{inputenc}
+%package. If you want the unprocessed codeset name, you can do:
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQuery}\marg{cs}\{\shortarg{L}\}
+%\end{flushleft}
+%
+%The current working directory (\shortarg{c} or \longarg{cwd}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryCwd
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryCwd}\marg{cs}
+%\end{flushleft}
+%
+%The home directory (\shortarg{m} or \longarg{userhome}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryHome
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryHome}\marg{cs}
+%\end{flushleft}
+%
+%The temporary directory (\shortarg{t} or \longarg{tmpdir}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryTmpDir
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryTmpDir}\marg{cs}
+%\end{flushleft}
+%
+%The OS name (\shortarg{o} or \longarg{osname}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryName
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryName}\marg{cs}
+%\end{flushleft}
+%
+%The OS version (\shortarg{r} or \longarg{osversion}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryVersion
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryVersion}\marg{cs}
+%\end{flushleft}
+%
+%The OS architecture (\shortarg{a} or \longarg{osarch}) can
+%be obtained using:
+%\DescribeMacro\TeXOSQueryArch
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryArch}\marg{cs}
+%\end{flushleft}
+%
+%The current date-time stamp in PDF format (\shortarg{n} or
+%\longarg{pdfnow}) can be obtained using:
+%\DescribeMacro\TeXOSQueryNow
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryNow}\marg{cs}
+%\end{flushleft}
+%This is provided for the benefit of users who don't have
+%\cs{pdfcreationdate} defined by their \TeX\ format (for example,
+%\XeTeX).
+%
+%\begin{important}
+%The remaining commands all require extra arguments after the
+%relevant switch. These are automatically enclosed in single-quotes
+%to protect any spaces. If the argument actually contains any single-quote
+%characters, make sure you use \verb|\string\'| to prevent
+%interference. \emph{However, in general it's a very bad idea to use
+%quotes as part of a file name (rather than using them as
+%delimiters).}
+%Since the file name may need to be obtained from \cs{jobname},
+%which sometimes includes double-quotes, the first double-quote pair
+%found is stripped in file name arguments. Any other double-quotes
+%will need to be protected in the same manner as single-quotes
+%(but, again, this shouldn't be an issue if you use a safe
+%file naming scheme). Any paths should use a
+%forward slash for the directory divider.
+%\end{important}
+%
+%The modification date-time stamp in PDF format for a file
+%(\shortarg{d} or \longarg{pdfdate}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFileDate
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFileDate}\marg{cs}\marg{filename}
+%\end{flushleft}
+%where \meta{filename} is the name of the file.
+%This is provided for the benefit of users who don't have
+%\cs{pdffilemoddate} defined by their \TeX\ format.
+%
+%The size in bytes of a file
+%(\shortarg{s} or \longarg{filesize}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFileSize
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFileSize}\marg{cs}\marg{filename}
+%\end{flushleft}
+%where \meta{filename} is the name of the file.
+%This is provided for the benefit of users who don't have
+%\cs{pdffilesize} defined by their \TeX\ format.
+%
+%The list of files in a given directory
+%(\shortarg{i} or \longarg{list}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFileList
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFileList}\marg{cs}\marg{sep}\marg{dir}
+%\end{flushleft}
+%where \meta{sep} is the separator and \meta{dir} is the directory name.
+%For example:
+%\begin{verbatim}
+%\TeXOSQueryFileList{\result}{,}{.}
+%\end{verbatim}
+%will store a comma-separated list of all the files contained in the
+%current directory in the control sequence \cs{result}.
+%
+%A filtered list of files in a given directory
+%(\shortarg{f} or \longarg{filterlist}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFilterFileList
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFilterFileList}\marg{cs}\marg{sep}\marg{regex}\marg{dir}
+%\end{flushleft}
+%where \meta{regex} is a regular expression. \emph{Take care of any backslashes
+%in the regular expression!}
+%For example, to list only those files that have an extension:
+%\begin{verbatim}
+%\TeXOSQueryFilterFileList{\result}{,}{.+\string\..*}{.}
+%\end{verbatim}
+%Note the use of \verb|\string\.| to ensure that \cs{.} isn't
+%interpreted as a command. Another example, list only \texttt{.png}
+%and \texttt{.jpg} files in the directory called \texttt{images}:
+%\begin{verbatim}
+%\TeXOSQueryFilterFileList{\result}{,}{.+\string\.(jpg|png)}{images}
+%\end{verbatim}
+%
+%The URI of a file
+%(\shortarg{u} or \longarg{uri}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFileURI
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFileURI}\marg{cs}\marg{filename}
+%\end{flushleft}
+%where \meta{filename} is the name of the file.
+%(Any percent symbols \verb|%| contained in the URI will have
+%their category code set to 12.)
+%
+%The canonical path of a file
+%(\shortarg{p} or \longarg{path}) can be obtained using:
+%\DescribeMacro\TeXOSQueryFilePath
+%\begin{flushleft}\ttfamily
+%\cs{TeXOSQueryFilePath}\marg{cs}\marg{filename}
+%\end{flushleft}
+%where \meta{filename} is the name of the file.
+%
+%\StopEventually{\phantomsection
+%\addcontentsline{toc}{section}{Change History}%
+%\PrintChanges
+%\addcontentsline{toc}{section}{\indexname}%
+%\PrintIndex
+%}
+%
+%\section{The Code}
+%\changes{1.0}{2016-07-08}{Initial release}
+%\subsection{Generic \TeX\ Code}
+%\iffalse
+% \begin{macrocode}
+%<*texosquery.tex>
+% \end{macrocode}
+%\fi
+%Change category code of \texttt{@} if necessary.
+% \begin{macrocode}
+\ifnum\catcode`\@=11\relax
+ \def\@texosquery@restore@at{}%
+\else
+ \expandafter\edef\csname @texosquery@restore@at\endcsname{%
+ \noexpand\catcode`\noexpand\@=\number\catcode`\@\relax
+ }%
+ \catcode`\@=11\relax
+\fi
+% \end{macrocode}
+% Check if already loaded.
+% \begin{macrocode}
+\ifx\TeXOSQuery\undefined
+\else
+ \@texosquery@restore@at
+ \expandafter\endinput
+\fi
+% \end{macrocode}
+%\begin{macro}{\TeXOSInvokerName}
+%The name of the \texttt{texosquery} application.
+% \begin{macrocode}
+\def\TeXOSInvokerName{texosquery}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryInvoker}
+%If we're using \LaTeX, we'll need to use \cs{@@input} rather
+%than \cs{input}.
+% \begin{macrocode}
+\ifx\@@input\undefined
+ \def\TeXOSQueryInvoker#1{\input|"\TeXOSInvokerName\space#1" }
+\else
+ \def\TeXOSQueryInvoker#1{\@@input|"\TeXOSInvokerName\space#1" }
+\fi
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\ifTeXOSQueryDryRun}
+%Provide a dry-run mode.
+% \begin{macrocode}
+\newif\ifTeXOSQueryDryRun
+\TeXOSQueryDryRunfalse
+% \end{macrocode}
+%\end{macro}
+%
+%If shell escape is disabled, automatically switch on dry-run mode.
+% \begin{macrocode}
+\ifx\shellescape\undefined
+ \ifx\pdfshellescape\undefined
+ \else
+ \ifnum\pdfshellescape=0\relax
+ \TeXOSQueryDryRuntrue
+ \fi
+ \fi
+\else
+ \ifnum\shellescape=0\relax
+ \TeXOSQueryDryRuntrue
+ \fi
+\fi
+% \end{macrocode}
+%
+%\begin{macro}{\TeXOSQuery}
+%Use \texttt{texosquery} with the option given in the second
+%argument and store the result in control sequence given in the
+%first argument.
+% \begin{macrocode}
+\def\TeXOSQuery#1#2{%
+ \ifTeXOSQueryDryRun
+ \begingroup
+ \newlinechar=`\^^J
+ \message{^^JTeXOSQuery: \TeXOSInvokerName\space#2^^J}%
+ \endgroup
+ \def#1{}%
+ \else
+ \begingroup
+ \endlinechar=-1\relax
+% \end{macrocode}
+%Just in case the result contains any awkward characters that have
+%some special meaning to \TeX. (Can't really protect against hash,
+%backslash or curly braces, but they're unlikely to occur unless
+%the user has a very wacky and inappropriate file naming scheme.)
+% \begin{macrocode}
+ \catcode`\-=12\relax
+ \catcode`\_=12\relax
+ \catcode`\^=12\relax
+ \catcode`\~=12\relax
+ \catcode`\$=12\relax
+ \catcode`\&=12\relax
+ \catcode`\"=12\relax
+ \catcode`\'=12\relax
+ \catcode`\.=12\relax
+ \catcode`\/=12\relax
+ \catcode`\:=12\relax
+ \catcode`\;=12\relax
+ \catcode`\%=12\relax
+ \everyeof{\noexpand}\relax
+ \edef\x{\endgroup\def\noexpand#1{\TeXOSQueryInvoker{#2}}}\x
+ \fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%Now for some convenient shortcuts so the user doesn't have to
+%remember the command line options. \cs{string} is used in
+%case the hyphen character has been made active.
+%\begin{macro}{\TeXOSQueryLocale}
+%Query the locale and store the result in the control sequence
+%provided in the argument.
+% \begin{macrocode}
+\def\TeXOSQueryLocale#1{\TeXOSQuery{#1}{\string-l}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryCwd}
+%Query the current working directory.
+% \begin{macrocode}
+\def\TeXOSQueryCwd#1{\TeXOSQuery{#1}{\string-c}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryHome}
+%Query the user's home directory.
+% \begin{macrocode}
+\def\TeXOSQueryHome#1{\TeXOSQuery{#1}{\string-m}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryTmpDir}
+%Query the temporary directory.
+% \begin{macrocode}
+\def\TeXOSQueryTmpDir#1{\TeXOSQuery{#1}{\string-t}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryVersion}
+%Query the operating system version.
+% \begin{macrocode}
+\def\TeXOSQueryVersion#1{\TeXOSQuery{#1}{\string-r}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryArch}
+%Query the operating system architecture.
+% \begin{macrocode}
+\def\TeXOSQueryArch#1{\TeXOSQuery{#1}{\string-a}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryName}
+%Query the operating system name.
+% \begin{macrocode}
+\def\TeXOSQueryName#1{\TeXOSQuery{#1}{\string-o}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryNow}
+%Query the current time stamp.
+% \begin{macrocode}
+\def\TeXOSQueryNow#1{\TeXOSQuery{#1}{\string-n}}
+% \end{macrocode}
+%\end{macro}
+%
+%If the file name is supplied using \cs{jobname} it may have
+%double-quotes which will interfere with things.
+%\begin{macro}{\texosquerystripquotes}
+% \begin{macrocode}
+\def\texosquerystripquotes#1{%
+ \@texosquery@stripquotes#1\@mid@texosquery@stripquotes
+ "\relax"\relax\@end@texosquery@stripquotes
+}
+\def\@texosquery@stripquotes#1"#2"{%
+ \@@texosquery@stripquotes#1#2%
+}
+\def\@@texosquery@stripquotes#1\@mid@texosquery@stripquotes#2\@end@texosquery@stripquotes{%
+ #1%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFileDate}
+%Query the time stamp of the file given in the second argument.
+% \begin{macrocode}
+\def\TeXOSQueryFileDate#1#2{\TeXOSQuery{#1}{\string-d
+ \string'\texosquerystripquotes{#2}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFileSize}
+%Query the size of the file given in the second argument.
+% \begin{macrocode}
+\def\TeXOSQueryFileSize#1#2{\TeXOSQuery{#1}{\string-s
+ \string'\texosquerystripquotes{#2}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFileList}
+%List all files in the directory given in the third argument,
+%separated by the second argument.
+% \begin{macrocode}
+\def\TeXOSQueryFileList#1#2#3{\TeXOSQuery{#1}{%
+ \string-i \string'#2\string'
+ \string'\texosquerystripquotes{#3}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFilterFileList}
+%Filtered list files in the directory given in the fourth argument,
+%separated by the second argument. The third argument is the regular
+%expression used to filter the list. \emph{Take care of backslashes
+%in the regular expression!}
+% \begin{macrocode}
+\def\TeXOSQueryFilterFileList#1#2#3#4{\TeXOSQuery{#1}{%
+ \string-f \string'#2\string' \string'#3\string'
+ \string'\texosquerystripquotes{#4}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFileURI}
+%Get the URI of the file given in the second argument.
+% \begin{macrocode}
+\def\TeXOSQueryFileURI#1#2{\TeXOSQuery{#1}{\string-u
+ \string'\texosquerystripquotes{#2}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\TeXOSQueryFilePath}
+%Get the canonical path of the file given in the second argument.
+% \begin{macrocode}
+\def\TeXOSQueryFilePath#1#2{\TeXOSQuery{#1}{\string-p
+ \string'\texosquerystripquotes{#2}\string'}}
+% \end{macrocode}
+%\end{macro}
+%
+%All done.
+%Restore the category code of \texttt{@}:
+% \begin{macrocode}
+\@texosquery@restore@at
+% \end{macrocode}
+%\iffalse
+% \begin{macrocode}
+%</texosquery.tex>
+% \end{macrocode}
+%\fi
+%
+%\subsection{\LaTeX\ Code}
+%This is just a simple wrapper for \texttt{texosquery.tex}
+%so that it can be loaded using \LaTeX's standard \cs{usepackage}
+%method.
+%\iffalse
+% \begin{macrocode}
+%<*texosquery.sty>
+% \end{macrocode}
+%\fi
+%Identify package:
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{texosquery}[2016/07/08 v1.0 (NLCT)]
+% \end{macrocode}
+%Load \texttt{texosquery.tex}:
+% \begin{macrocode}
+\input{texosquery}
+% \end{macrocode}
+%That's it!
+%\iffalse
+% \begin{macrocode}
+%</texosquery.sty>
+% \end{macrocode}
+%\fi
+%
+%\Finale
+\endinput
diff --git a/Master/texmf-dist/source/support/texosquery/texosquery.ins b/Master/texmf-dist/source/support/texosquery/texosquery.ins
new file mode 100644
index 00000000000..b86ef27d4fa
--- /dev/null
+++ b/Master/texmf-dist/source/support/texosquery/texosquery.ins
@@ -0,0 +1,45 @@
+\input docstrip
+
+\preamble
+
+ texosquery
+ Copyright 2016 Nicola Talbot
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either version 1.3
+ of this license of (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
+ version 2005/12/01 or later.
+
+ This work has the LPPL maintenance status `maintained'.
+
+ The Current Maintainer of this work is Nicola Talbot.
+
+ This work consists of the files texosquery.dtx and texosquery.ins
+ and the derived files texosquery.sty, texosquery.tex.
+ Additionally, the Java application texosquery.jar and bash script
+ texosquery
+\endpreamble
+
+\askforoverwritefalse
+
+\generate
+{%
+ \file{texosquery.sty}%
+ {%
+ \usepreamble\defaultpreamble
+ \usepostamble\defaultpostamble
+ \from{texosquery.dtx}{texosquery.sty,package}%
+ }
+ \file{texosquery.tex}%
+ {%
+ \usepreamble\defaultpreamble
+ \usepostamble\defaultpostamble
+ \from{texosquery.dtx}{texosquery.tex,package}%
+ }
+}
+
+\endbatchfile
+