% \iffalse meta-comment
%
% Written in 2010 by Manuel Pégourié-Gonnard.
%     <mpg@elzevir.fr>
%
% This work is under the CC0 license.
%
% This work consists of the main source file luatexbase-compat.dtx
% and the derived files
%   luatexbase-compat.pdf luatexbase-compat.sty
%   test-compat-plain.tex test-compat-latex.tex
%
% Unpacking:
%    tex luatexbase-compat.dtx
% Documentation:
%    pdflatex luatexbase-compat.dtx
%
%    The class ltxdoc loads the configuration file ltxdoc.cfg
%    if available. Here you can specify further options, e.g.
%    use A4 as paper format:
%       \PassOptionsToClass{a4paper}{article}
%
%<*ignore>
\begingroup
  \def\x{LaTeX2e}%
\expandafter\endgroup
\ifcase 0\ifx\install y1\fi\expandafter
         \ifx\csname processbatchFile\endcsname\relax\else1\fi
         \ifx\fmtname\x\else 1\fi\relax
\else\csname fi\endcsname
%</ignore>
%<*install>
\input docstrip.tex

\keepsilent
\askforoverwritefalse

\preamble

Written in 2010 by Manuel Pegourie-Gonnard.

This work is under the CC0 license.
See source file '\inFileName' for details.

\endpreamble

\generate{%
  \usedir{tex/luatex/luatexbase}%
  \file{luatexbase-compat.sty}{\from{luatexbase-compat.dtx}{texpackage}}%
}

\generate{%
  \usedir{doc/luatex/luatexbase}%
  \file{test-compat-plain.tex}{\from{luatexbase-compat.dtx}{testplain}}%
  \file{test-compat-latex.tex}{\from{luatexbase-compat.dtx}{testlatex}}%
}

\obeyspaces
\Msg{************************************************************************}
\Msg{*}
\Msg{* To finish the installation you have to move the following}
\Msg{* files into a directory searched by TeX:}
\Msg{*}
\Msg{*     luatexbase-compat.sty}
\Msg{*}
\Msg{* Happy TeXing!}
\Msg{*}
\Msg{************************************************************************}

\endbatchfile
%</install>
%<*ignore>
\fi
%</ignore>
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\documentclass{ltxdoc}
\input lltxb-dtxstyle.tex
\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{luatexbase-compat.dtx}%
\end{document}
%</driver>
% \fi
%
% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \pkdate{luatexbase-compat}{2010/10/10 v0.3}
%
% \maketitle
%
% \begin{abstract}
% The \luatex manual is very clear: everything may change. This package
% provides tools to help package writers deal with the changes. It helps
% supporting \luatex versions down to 0.25.4, and is regularly tested with
% \luatex 0.40.6 (\texlive 2009) and from trunk.
% \end{abstract}
%
% \tableofcontents
%
% \section{Documentation}
%
% Three problems are currently addressed by this package: changes in the
% syntax of |\directlua|, version information, and variable policies for
% primitives activation and naming (in \luatex itself as well as in \texlive).
%
% \medskip
%
% Older versions of \luatex used to support multiple Lua states. A number was
% mandatory with |\directlua| in order to specify the Lua state to be used.
% Later, support for multiple Lua states was removed and the old syntax
% resulted in a warning. Now (\luatex 0.50), |\directlua| again accepts a
% number after |\directlua|, but with a different meaning (see the \luatex
% manual for details).
%
% This package provides a macro |\luatexbase@directlua| that expands to
% |\directlua0| on \luatex 0.35 and lower (where the number is mandatory), and
% to |\directlua| otherwise. It is a macro in both case so that the number of
% expansion steps remains constant.
%
% \medskip
%
% Current versions of \luatex make the version available directly from Lua as
% |tex.luatexversion| and |tex.luatexrevision|. However, older versions (such
% as 0.25.4) didn't, which makes it particularly uneasy to test the version
% from within Lua. The present package makes this information available as
% |luatexbase.luatexversion| and |luatexbase.luatexrevision|.
%
% \medskip
%
% Starting with \luatex 0.39.0, the only primitives available in Ini\tex mode
% are the basic primitives from \tex{}82 and |\directlua|. All other
% primitives are hidden by default and have to be activated using a Lua
% function. In \texlive 2009 (\luatex 0.40.6), the following arrangement has
% been made in order to try preserving usability while avoiding name clashes
% in the \latex world: in \latex-based formats, all pdf\tex primitives are
% enabled with their normal name, but the primitives specific to \luatex are
% enabled with the |luatex| prefix.\footnote{The prefix is dropped for
% primitives whose name already starts with \texttt{luatex}.} In Plain based
% formats however, all the primitives are enabled with their natural name, but
% are also provided with the same name as in \latex-based formats in order to
% help writing generic packages.
%
% So, starting with \texlive 2009, the situation is clear: the prefixed
% version of the \luatex primitives is always available. But in earlier
% versions (\texlive 2008, \luatex 0.25.4) those primitives were available
% only with their natural names. Also, it is theoretically possible, however
% unlikely, that the prefixed primitives are not available for some reason.
%
% \begin{quote}
% \cs{luatexbase@ensure@primitive}\marg{name}
% \end{quote}
% The tool provided to deal with that is \cs{luatexbase@ensure@primitive},
% whose argument is a primitive name (without a leading backslash nor any
% |luatex| prefix, eg just |{latelua}|). It makes sure that the primitive gets
% available as \cs{luatex\meta{name}}.
%
% \textbf{Warning.} In particular circumstances, this macro may fail silently
% for primitives whose natural name starts with |luatex|, hence such
% primitives shouldn't be used as arguments. This is actually not a problem,
% since the only three such primitives are |\luatexversion|, |\luatexrevision|
% and |\luatexdatestamp|. The first two are already activated by \pk{ifluatex}
% which is loaded by this package, so you don't need to activated them
% yourself. The third should never be used in production according to the
% \luatex manual.
%
% \textit{Remark.} If you only aim at compatibility down to \texlive 2009
% (\luatex 0.40.6), then you can simply use the primitives with their prefixed
% name (except for |\directlua| which never needs a prefix). If you want extra
% security and/or compatibility down to \texlive 2008 (\luatex 0.25.4) then
% you should use \cs{luatebase@ensure@primitive} for each primitive you intend
% to use (except |\directlua| again).
%
% This package doesn't try to activate every primitive, since it would require
% and extensive list of primitives for each version of \luatex, so it seems
% simpler to leave that burden on package writers.
%
%    \section{Implementation}
%
%    \begin{macrocode}
%<*texpackage>
%    \end{macrocode}
%
%    \subsection{Preliminaries}
%
%    Reload protection, especially for \plaintex.
%
%    \begin{macrocode}
                \csname lltxb@compat@loaded\endcsname
\expandafter\let\csname lltxb@compat@loaded\endcsname\endinput
%    \end{macrocode}
%
%    Catcode defenses.
%
%    \begin{macrocode}
\begingroup
  \catcode123 1 % {
  \catcode125 2 % }
  \catcode 35 6 % #
  \toks0{}%
  \def\x{}%
  \def\y#1 #2 {%
    \toks0\expandafter{\the\toks0 \catcode#1 \the\catcode#1}%
    \edef\x{\x \catcode#1 #2}}%
  \y 123 1  % {
  \y 125 2  % }
  \y  35 6  % #
  \y  10 12 % ^^J
  \y  34 12 % "
  \y  36 3  % $ $
  \y  39 12 % '
  \y  40 12 % (
  \y  41 12 % )
  \y  42 12 % *
  \y  43 12 % +
  \y  44 12 % ,
  \y  45 12 % -
  \y  46 12 % .
  \y  47 12 % /
  \y  60 12 % <
  \y  61 12 % =
  \y  64 11 % @ (letter)
  \y  62 12 % >
  \y  95 12 % _ (other)
  \y  96 12 % `
  \edef\y#1{\endgroup\edef#1{\the\toks0\relax}\x}%
\expandafter\y\csname lltxb@compat@AtEnd\endcsname
%    \end{macrocode}
%
%    Package declaration.
%
%    \begin{macrocode}
\begingroup
  \expandafter\ifx\csname ProvidesPackage\endcsname\relax
    \def\x#1[#2]{\immediate\write16{Package: #1 #2}}
  \else
    \let\x\ProvidesPackage
  \fi
\expandafter\endgroup
\x{luatexbase-compat}[2010/10/10 v0.3 Compatibility tools for LuaTeX]
%    \end{macrocode}
%
%    Make sure \luatex is used.
%
%    \begin{macrocode}
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname RequirePackage\endcsname\relax
  \input ifluatex.sty
\else
  \RequirePackage{ifluatex}
\fi
\ifluatex\else
  \begingroup
    \expandafter\ifx\csname PackageError\endcsname\relax
      \def\x#1#2#3{\begingroup \newlinechar10
        \errhelp{#3}\errmessage{Package #1 error: #2}\endgroup}
    \else
      \let\x\PackageError
    \fi
  \expandafter\endgroup
  \x{luatexbase-attr}{LuaTeX is required for this package. Aborting.}{%
    This package can only be used with the LuaTeX engine^^J%
    (command `lualatex' or `luatex').^^J%
    Package loading has been stopped to prevent additional errors.}
  \lltxb@compat@AtEnd
  \expandafter\endinput
\fi
%    \end{macrocode}
%
%    \subsection{\cs{directlua} abstraction}
%
%    Define |\luatexbase@directlua| to be either |\directlua0| or
%    |\directlua|, depending on the version of \luatex.
%
%    \begin{macrocode}
\begingroup
\expandafter\ifx\csname newcommand\endcsname\relax
  \toks0{\long\def\luatexbase@directlua}%
\else
  \toks0{\newcommand\luatexbase@directlua}%
\fi
\ifnum\luatexversion<36
  \toks0\expandafter{\the\toks0{\directlua0}}%
\else
  \toks0\expandafter{\the\toks0{\directlua}}%
\fi
\expandafter\endgroup
\the\toks0
%    \end{macrocode}
%
%    \subsection{Version information}
%
%    Make |\luatexversion| and |\luatexrevision| available from Lua.
%
%    \begin{macrocode}
\luatexbase@directlua{%
  luatexbase = luatexbase or {}
  luatexbase.luatexversion = \number\luatexversion\space
  luatexbase.luatexrevision = \number\luatexrevision\space}
%    \end{macrocode}
%
%    \subsection{Primitives}
%
%    Try reasonably hard to activate a primitive. First, check if it is
%    already activated an do nothing in this case.
%
%    \begin{macrocode}
\begingroup
\expandafter\ifx\csname newcommand\endcsname\relax
  \toks0{\def\luatexbase@ensure@primitive#1}
\else
  \toks0{\newcommand*\luatexbase@ensure@primitive[1]}
\fi
\toks2{}\def\x#1{\toks2\expandafter{\the\toks2 #1}}
\x{%
  \ifcsname luatex#1\endcsname \else}
\ifnum\luatexversion<37\relax
%    \end{macrocode}
%
%    |tex.enableprimitives()| not available. If the unprefixed primitive is
%    undefined, issue an error.
%
%    \begin{macrocode}
  \x{%
    \begingroup\expandafter\expandafter\expandafter\endgroup
    \expandafter\ifx\csname #1\endcsname\relax}
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname PackageError\endcsname\relax
    \x{%
      \errmessage{%
        Package luatexbase-compat error: failed to enable `#1'.}}
  \else
    \x{%
      \PackageError{luatexbase-compat}{%
        Package luatexbase-compat error: failed to enable `#1'.}{}}
  \fi
  \x{%
    \else}
%    \end{macrocode}
%
%    Use the unprefixed primitive to define the prefixed version.
%
%    \begin{macrocode}
  \x{%
      \expandafter\let\csname luatex#1\expandafter\endcsname
      \csname#1\endcsname
    \fi}
\else
%    \end{macrocode}
%
%    |tex.enableprimitives()| available, use it.
%
%    \begin{macrocode}
  \x{%
    \luatexbase@directlua{tex.enableprimitives('luatex', {'#1'})}}
\fi
\x{%
  \fi}
\toks0\expandafter{\the\toks0\expandafter{\the\toks2}}
\expandafter\endgroup
\the\toks0
%    \end{macrocode}
%
%    That's all folks!
%
%    \begin{macrocode}
\lltxb@compat@AtEnd
%</texpackage>
%    \end{macrocode}
%
%    \section{Test files}
%
%    Test fils for Plain and LaTeX
%
%    \begin{macrocode}
%<testplain>\input luatexbase-compat.sty
%<testlatex>\RequirePackage{luatexbase-compat}
%<*testplain,testlatex>
\catcode64 11
\luatexbase@directlua{local answer = 42}
\luatexbase@ensure@primitive{primitive}
\luatexprimitive\relax
\luatexbase@directlua{assert(type(luatexbase.luatexversion) == 'number')}
\luatexbase@directlua{assert(type(luatexbase.luatexrevision) == 'number')}
%</testplain,testlatex>
%<testplain>\bye
%<testlatex>\stop
%    \end{macrocode}
%
%
% \Finale
\endinput
