[tex-eplain] Incorporating url.sty

geolsoft at mail.ru geolsoft at mail.ru
Sat Aug 27 23:19:22 CEST 2005

Phew, this was something!  About four times I was about to
submit the patch when I discovered something else was

So here is the patch for \usepackage.  The syntax is the
same as in LaTeX (including package version check).  It
currently supports the following packages "out of box", with
most of their options:  color, graphics, graphicx, picture
(LaTeX picture environment), psfrag, and url.  Some options
require a few more easy definitions, e.g., graphicx with the
option draft requires \let\ttfamily\relax and \strip at prefix
from LaTeX.

The patch is against the current CVS, as usual, see


or CVS repository at sarovar.org


If you do not want to patch / compile but want to see the
test output, you can download compiled test files from here:

  http://geolsoft.freeshell.org/usepackage.ps.gz  (dvips driver)
  http://geolsoft.freeshell.org/usepackage.pdf.gz (pdftex driver)

The second file does not contain the graphics from psfrag,
as it is a PDF file.

Most of the complications arise from the need to pass the
options around when loading packages recursively.  At first
I was hoping to avoid this.  Unfortunately, without this we
would not be able to pass options to graphicx:  graphicx
loads graphics recursively, passing the options down to it.
And graphicx has nice features not supported in graphics,
like specifying origin for text rotation.

Note for the test file:  it requires file example.eps from
the psfrag package (macros/latex/contrib/psfrag/example.eps
on CTAN hosts).

Note for the picture package:  right now you say
\usepackage{picture} to load LaTeX picture environment
support, however, all warnings and error messages will refer
to autopict package (this is due to the way that plain TeX
support was designed for it).  Would \usepackage{autopict} be
better?  This way, it will match the error messages, but the
name is less descriptive.

Note for the url package:  use the latest version (ver3.2,
27-Jun-2005, macros/latex/contrib/misc/url.sty on CTAN
hosts).  Some older versions have problems under plain TeX.

Best regards,
Oleg Katsitadze
-------------- next part --------------
Index: xeplain.tex
RCS file: /cvsroot/eplain/eplain/xeplain.tex,v
retrieving revision 1.10
diff -u -p -r1.10 xeplain.tex
--- xeplain.tex	25 Aug 2005 06:27:38 -0000	1.10
+++ xeplain.tex	27 Aug 2005 20:47:29 -0000
@@ -4009,6 +4009,358 @@
+%  Support for LaTeX packages under plain TeX.
+% Much of the following was borrowed from LaTeX.
+% The internal variables are quite a mess, so here is a hint:
+%  - \usepkg at pkg, \usepkg at options, \usepkg at date are used by
+%    \usepackage to save its parameters.
+%  - When \RequirePackage is called within a package, the above
+%    variables are saved in \usepkg at save@VAR at RECURSIONLEVEL, where
+%    VAR={pkg,options,date}, and RECURSIONLEVEL is incremented for
+%    each nested package inclusion.  This way the variables can be
+%    restored after the (nested) package will have been loaded.
+%  - Options for package PACKAGE (no .sty extension) are accumulated
+%    in \usepkg at options@PACKAGE.
+%  - For each declared option OPTION in package PACKAGE, we save the
+%    code which enables OPTION in \usepkg at option@PACKAGE at OPTION.
+%    There may be a star (`*') option declaration, the code from which
+%    will be used to process options not declared by the package
+%    (without it, an undeclared option will cause an error).
+%  - For each loaded PACKAGE / FILE.EXT we declare \ver at PACKAGE.sty /
+%    \ver at FILE.EXT.  We use \ver at PACKAGE.sty to detect reloading
+%    of packages.  Some packages also use these macros.
+%  - Calls to \AtBeginDocument accumulate the code in
+%    \usepkg at at@begin at document.  We will expand it at the end of the
+%    \beginpackages...\endpackages `environment'.
+%  - Calls to \AtEndOfPackage accumulate the code in
+%    \usepkg at at@end at of@package.  We will expand it after the package
+%    is loaded.
+\newif\ifusepkg at miniltx@loaded
+\newcount\usepkg at recursion@level
+\def\usepkg at rcrs{\the\usepkg at recursion@level}%
+\let\usepkg at at@begin at document\empty
+\let\usepkg at at@end at of@package\empty
+\def\usepkg at word@picture{picture}%
+\def\usepkg at word@psfrag{psfrag}%
+% \beginpackages...\endpackages
+% All packages must be loaded within this `environment'.  This is so
+% to give us a chance to expand the accumulated \AtBeginDocument
+% commands.  There can be only one such construction in a document.
+  \let\usepackage\real at usepackage
+  #1%
+  \usepkg at at@begin at document
+  \global\let\usepkg at at@begin at document\empty
+  \global\let\usepackage\fake at usepackage
+  \gdef\beginpackages{\errmessage{You should have only one
+    \string\beginpackages...\string\endpackages\space environment}}%
+% \fake at usepackage
+% This is what \usepackage is defined to outside of
+% \beginpackages...\endpackages `environment'.
+\def\fake at usepackage{\errmessage{You should not use \string\usepackage\space outside of^^J
+  \@spaces\string\beginpackages...\string\endpackages\space environment}%
+% Save parameters for the package being loaded and call \usepackage to
+% load PACKAGES.  We depend on \usepackage to restore the saved
+% parameters.  We allow for nested calls to \RequirePackage.
+\def\eplain at RequirePackage{%
+  \global\ece\let{usepkg at save@pkg\usepkg at rcrs}\usepkg at pkg
+  \global\ece\let{usepkg at save@options\usepkg at rcrs}\usepkg at options
+  \global\ece\let{usepkg at save@date\usepkg at rcrs}\usepkg at date
+  \global\advance\usepkg at recursion@level by\@ne
+  \real at usepackage
+% Load each of the PACKAGES with OPTIONS, checking that the package
+% date is at least YYYY/MM/DD; if it is not, issue a warning.
+\let\usepackage\fake at usepackage
+\def\real at usepackage{\@getoptionalarg\@finusepackage}%
+  \let\usepkg at options\@optionalarg
+  \ifempty{#1}%
+    \errmessage{No packages specified}%
+  \fi
+  % Load miniltx.tex, if it is not loaded.
+  \ifusepkg at miniltx@loaded \else
+    \testfileexistence[miniltx]{tex}%
+    \if at fileexists
+      \input miniltx.tex
+      \global\usepkg at miniltx@loadedtrue
+      % Redefine some macros from miniltx.tex
+      \global\let\RequirePackage\eplain at RequirePackage
+      \global\let\DeclareOption\eplain at DeclareOption
+      \global\let\PassOptionsToPackage\eplain at PassOptionsToPackage
+      \global\let\ExecuteOptions\eplain at ExecuteOptions
+      \global\let\ProcessOptions\eplain at ProcessOptions
+      \global\let\AtBeginDocument\eplain at AtBeginDocument
+      \global\let\AtEndOfPackage\eplain at AtEndOfPackage
+      \global\let\ProvidesFile\eplain at ProvidesFile
+      \global\let\ProvidesPackage\eplain at ProvidesPackage
+    \else
+      \errmessage{miniltx.tex not found, cannot load LaTeX packages}%
+    \fi
+  \fi
+  % Read the trailing optional arg (YYYY/MM/DD).
+  \@ifnextchar[%]
+    {\@finfinusepackage{#1}}%
+    {\@finfinusepackage{#1}[]}%
+  \edef\usepkg at date{#2}%
+  % Load each package from the list.  Do it outside the \for loop to
+  % avoid clashes with any \for loops executed by the package.
+  \let\usepkg at load@list\empty
+  \for\usepkg at pkg:=#1\do{%
+    \toks@=\expandafter{\usepkg at load@list}%
+    \edef\usepkg at load@list{%
+      \the\toks@
+      \noexpand\usepkg at load@pkg{\usepkg at pkg}%
+    }%
+  }%
+  \usepkg at load@list
+  % Restore parameters in case we were called from \RequirePackage.
+  \ifnum\usepkg at recursion@level>0
+    \global\advance\usepkg at recursion@level by\m at ne
+    \expandafter\let\expandafter\usepkg at pkg\csname usepkg at save@pkg\usepkg at rcrs\endcsname
+    \expandafter\let\expandafter\usepkg at options\csname usepkg at save@options\usepkg at rcrs\endcsname
+    \expandafter\let\expandafter\usepkg at date\csname usepkg at save@date\usepkg at rcrs\endcsname
+    \global\ece\let{usepkg at save@pkg\usepkg at rcrs}\undefined
+    \global\ece\let{usepkg at save@options\usepkg at rcrs}\undefined
+    \global\ece\let{usepkg at save@date\usepkg at rcrs}\undefined
+  \fi
+% Load one package.  We assume packages have `sty' extension.
+\def\usepkg at load@pkg#1{%
+  % Special cases for `picture' and `psfrag' packages:
+  %   - `psfrag' is loaded by psfrag.tex.
+  %   - `picture' is loaded by picture.tex, but the package file is
+  %      autopict.sty.  This hack makes all warnings and errors
+  %      display `autopict' for the package name instead of `picture'.
+  \def\temp{#1}%
+  \ifx\temp\usepkg at word@picture
+    \def\usepkg at pkg{autopict}%
+    \testfileexistence[picture]{tex}%
+    \if at fileexists \else
+      \errmessage{Loader `picture.tex' for package `\usepkg at pkg' not found}%
+    \fi
+  \else
+    \def\usepkg at pkg{#1}%
+    \ifx\temp\usepkg at word@psfrag
+      \testfileexistence[psfrag]{tex}%
+      \if at fileexists \else
+        \errmessage{Loader `psfrag.tex' for package `\usepkg at pkg' not found}%
+      \fi
+    \fi
+  \fi
+  % See if the package was loaded.  If it was, we just bail out.
+  % (Maybe we should skip reloading it/warn?  We don't want to go into
+  % checking that the package was first loaded with a subset of
+  % options which are requested now.)  \ProvidePackage and
+  % \ProvideFile define the macro \ver at PACKAGE.sty (see
+  % \eplain at pr@videpackage below).
+  \ifundefined{ver@\usepkg at pkg.sty}\else
+    \errmessage{Package `\usepkg at pkg' already loaded}%
+  \fi
+  \testfileexistence[\usepkg at pkg]{sty}%
+  \if at fileexists \else
+    \errmessage{Package `\usepkg at pkg' not found}%
+  \fi
+  % Construct option list for the package.  Include any options
+  % passed to us by \PassOptionsToPackage and \RequirePackage.
+  \expandafter\let\expandafter\temp\csname usepkg at options@\usepkg at pkg\endcsname
+  \ifx\temp\relax
+    \let\temp\empty
+  \fi
+  \ifx\temp\empty
+    \let\temp\usepkg at options
+  \else
+    \ifx\usepkg at options\empty \else
+      \edef\temp{\temp,\usepkg at options}%
+    \fi
+  \fi
+  \global\ece\let{usepkg at options@\usepkg at pkg}\temp
+  % For the duration of the package, we want any calls to \usepackage
+  % to be mapped to \RequirePackage, to allow nested package loads
+  % without clobbering up anything.  (Maybe packages never use
+  % \usepackage instead of \RequirePackage, but this won't hurt.)
+  \let\usepackage\eplain at RequirePackage
+  % Load the package.  If the package asks to load other package,
+  % \RequirePackage will save our \usepkg@{pkg,options,date}, and
+  % \usepackage will restore them after recursively loading that
+  % package, so we don't worry about our setup being clobbered.
+  \def\temp{#1}%
+  \ifx\temp\usepkg at word@picture
+    \input picture.tex
+  \else
+    \ifx\temp\usepkg at word@psfrag
+      \input \usepkg at pkg.tex
+    \else
+      \input \usepkg at pkg.sty
+    \fi
+  \fi
+  % Execute the accumulated \AtEndOfPackage commands and reset them.
+  \usepkg at at@end at of@package
+  \global\let\usepkg at at@end at of@package\empty
+  % Restore the `real' \usepackage definition.
+  \let\usepackage\real at usepackage
+  % Clear the option list for the loaded package (we won't load a
+  % second copy anyway).
+  \global\ece\let{usepkg at options@\usepkg at pkg}\undefined
+  % We check package version in \ProvidePackage, before reading the
+  % rest of the package, so that in case of errors (which can be
+  % numerous) the warning hopefully comes before the errors.
+%  \@ifl at ter{sty}\usepkg at pkg\usepkg at date{}%
+%    {\message{Warning: you have requested package `\usepkg at pkg', version \usepkg at date,^^J
+%       \@spaces but only version `\csname ver@\usepkg at pkg.sty\endcsname' is available.}}%
+% \DeclareOption{OPTION}{CODE}
+% Save CODE in `usepkg at option@PACKAGE at OPTION'.  Starred version is not
+% treated any different here, but when defined it will be used by
+% \ProcessOptions and \ExecuteOptions to process undeclared options.
+\def\eplain at DeclareOption#1#2{%
+  \toks@{#2}%
+  \expandafter\xdef\csname usepkg at option@\usepkg at pkg @#1\endcsname{\the\toks@}%
+% \PassOptionsToPackage{OPTIONS}{PACKAGES}
+% Add OPTIONS to the option list for each of the PACKAGES.
+\def\eplain at PassOptionsToPackage#1#2{%
+  \ifempty{#1}\else
+    \for\usepkg at temp:=#2\do{%
+      \expandafter\let\expandafter\temp\csname usepkg at options@\usepkg at temp\endcsname
+      \ifx\temp\relax
+        \let\temp\empty
+      \fi
+      \ifx\temp\empty
+        \edef\temp{#1}%
+      \else
+        \edef\temp{\temp,#1}%
+      \fi
+      \global\ece\let{usepkg at options@\usepkg at temp}\temp
+    }%
+  \fi
+% \ExecuteOptions{OPTIONS}
+% \ProcessOptions
+% \ExecuteOptions executes each option from OPTIONS, \ProcessOptions
+% executes each option from the option list for the current package.
+% If the star (`*') option is declared, it will be used to process
+% undeclared options; otherwise, undeclared option will cause an
+% error.
+\def\usepkg at exec@options#1{%
+  \for\CurrentOption:=#1\do{%
+    \expandafter\let\expandafter\usepkg at temp
+      \csname usepkg at option@\usepkg at pkg @\CurrentOption\endcsname
+    \ifx\usepkg at temp\relax
+      % Option is not declared.  If a `default' option handler is
+      % declared, use it.
+      \expandafter\let\expandafter\temp\csname usepkg at option@\usepkg at pkg @*\endcsname
+      \ifx\temp\relax
+        \errmessage{Unknown option `\CurrentOption' to package `\usepkg at pkg'}%
+      \else
+        \temp
+      \fi
+    \else
+      % Option is declared.
+      \usepkg at temp
+    \fi
+  }%
+\let\eplain at ExecuteOptions\usepkg at exec@options
+\def\eplain at ProcessOptions{%
+  \expandafter\usepkg at exec@options\csname usepkg at options@\usepkg at pkg\endcsname
+% \AtBeginDocument{CODE}
+% \AtEndOfPackage{CODE}
+% miniltx.tex defines \AtBeginDocument to execute its parameter right
+% away, but some packages depend on \AtBeginDocument to be executed
+% after packages are processed.  So we redefine \AtBeginDocument to
+% accumulate its argument, to be executed by us at the end of
+% \beginpackages...\endpackages.  \AtEndOfPackage is not defined by
+% miniltx.tex at all; we define it similar to \AtBeginDocument.
+\def\usepkg at accumulate@cmds#1#2{%
+  \toks@=\expandafter{#1}%
+  \toks at ii={#2}%
+  \xdef#1{\the\toks@\the\toks at ii}%
+\def\eplain at AtBeginDocument{\usepkg at accumulate@cmds\usepkg at at@begin at document}%
+\def\eplain at AtEndOfPackage{\usepkg at accumulate@cmds\usepkg at at@end at of@package}%
+% \ProvidesPackage{PACKAGENAME}[VERSION]
+% miniltx.tex defines \ProvidesFile and \ProvidesPackage to only log a
+% message.  We want to define \ver at PACKAGE.sty / \ver at FILENAME.EXT, as
+% we depend on these to know when a package/file has been loaded, and
+% some packages depend on them, too.
+\def\eplain at ProvidesPackage#1{%
+  \@ifnextchar[%]
+    {\eplain at pr@videpackage{#1.sty}}{\eplain at pr@videpackage#1[]}%
+\def\eplain at pr@videpackage#1[#2]{%
+  \wlog{#1: #2}%
+  % This will flag the package as loaded.
+  \expandafter\xdef\csname ver@#1\endcsname{#2}%
+%  \expandafter\edef\expandafter\temp{\csname usepkg at options@\usepkg at pkg\endcsname}%
+%  \message{^^JPackage:\usepkg at pkg^^JOptions:\usepkg at options^^J+ passed options:\temp^^J}%
+  % Check package version.
+  \@ifl at t@r{#2}\usepkg at date{}%
+    {\message{Warning: you have requested package `\usepkg at pkg', version \usepkg at date,^^J
+       \@spaces but only version `\csname ver@#1\endcsname' is available.}}%
+\def\eplain at ProvidesFile#1{%
+  \@ifnextchar[%]
+    {\eplain at pr@videfile{#1}}{\eplain at pr@videfile#1[]}%
+\def\eplain at pr@videfile#1[#2]{%
+  \wlog{#1: #2}%
+  % This will flag the file as loaded.
+  \expandafter\xdef\csname ver@#1\endcsname{#2}%
+  % We don't check file version.  graphics calls \ProvideFile to
+  % \includegraphics, and it does not give any date at the beginning
+  % of #2, so checking the date will cause an error.
+% Check package version.  From LaTeX.
+\def\@ifl at ter#1#2{%
+  \expandafter\@ifl at t@r
+    \csname ver@#2.#1\endcsname
+\def\@ifl at t@r#1#2{%
+  \ifnum\expandafter\@parse at version#1//00\@nil<%
+        \expandafter\@parse at version#2//00\@nil
+    \expandafter\@secondoftwo
+  \else
+    \expandafter\@firstoftwo
+  \fi
+\def\@parse at version#1/#2/#3#4#5\@nil{#1#2#3#4 }%
+% Needed by some packages (psfrag), we use it, too.
 \let\wlog = \@plainwlog
 \catcode`@ = \@eplainoldatcode
-------------- next part --------------
A non-text attachment was scrubbed...
Name: usepackage.tex
Type: text/x-tex
Size: 3407 bytes
Desc: not available
Url : http://tug.org/pipermail/tex-eplain/attachments/20050828/fef225d4/usepackage.bin

More information about the tex-eplain mailing list