diff options
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/README | 14 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf | bin | 452170 -> 448327 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex | 319 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg | 13 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/catoptions/catoptions.sty | 2217 |
5 files changed, 1378 insertions, 1185 deletions
diff --git a/Master/texmf-dist/doc/latex/catoptions/README b/Master/texmf-dist/doc/latex/catoptions/README index 277392c5dce..9003c0f039d 100644 --- a/Master/texmf-dist/doc/latex/catoptions/README +++ b/Master/texmf-dist/doc/latex/catoptions/README @@ -11,17 +11,17 @@ to many TeX programming tools. LICENSE -The 'catoptions' package may be distributed and/or modified under -the conditions of the LaTeX Project Public License, either -version 1.3 of this license or 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 +The 'catoptions' package may be distributed and/or modified under +the conditions of the LaTeX Project Public License, either +version 1.3 of this license or 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. The LPPL maintenance status of this software is 'author-maintained'. This software is provided 'as it is', without warranty of any kind, -either expressed or implied, including, but not limited to, the +either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. @@ -36,6 +36,6 @@ The catcode section of the 'catoptions' package is based on the VERSION -Version 0.2.5, July 2011 +Version 0.2.7, November 2011 diff --git a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf Binary files differindex cb85c28fa4b..e3f6e07ba75 100644 --- a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf +++ b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf diff --git a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex index 5037a01e1bb..a2277633ab6 100644 --- a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex +++ b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex @@ -13,8 +13,10 @@ \hfuzz1pt \makeatletter \WrapQuotes -\def\xdecs{\fx{\XDeclareOption}\RedStar\sspace} +\def\xdecs{\fx{\XDeclareOption}\Redstar\sspace} \makeindex +\useshortdoccmds +\let\footnote\ltsfootnote \begin{document} @@ -23,10 +25,10 @@ \titlenotes[t1,t2]{% The package is available at \url{\titleurltext}.\sep This manual doesn't, as yet, explain all the currently available features and commands of - the \pkg'{catoptions}. This manual continues to evolve, but many of the available functions will appear in the user guide of the forthcoming \pkg'{ltxtools}. + the \pkg'{catoptions}. This manual continues to evolve, but many of the available functions will appear in the forthcoming user guide of the \pkg'{ltxtools}. } -\version{0.2.6} -\titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/catoptions/} +\version{0.2.7} +\titleurl{http://mirror.ctan.org/macros/latex/contrib/catoptions/} \author{Ahmed Musa \Email{amusa22@gmail.com}\\Preston, Lancashire, UK} \def\abstractname{\textsf{Summary}} @@ -60,17 +62,17 @@ \docsection(sec:packageloading){Loading the package} -\deffnote{1}{% - The user interfaces of \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} are similar to those of \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} but they aren't the same. See \amref{sec:options-parse}. +\deffootnote{1}{% + The user interfaces of \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} are similar to those of \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} but they aren't the same. See \sref{sec:options-parse}. } -The \pkg'{catoptions} can be loaded in class and style files and in documents (before or after \hx{\documentclass}) with the options described in \amref{sec:pkg-options}. If the package is loaded before \hx{\documentclass}, it will, by default, use the options parser of the package in place of \latex's options parsing scheme (namely, the more robust commands \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} in place of \latex's native commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions})\usefnote{1}. In that case, the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} are aliased to \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions}, respectively. The latter set of commands do immediately recognize that they have to deal with option functions that are based on the kernel's syntax and semantics. This allows expandable options and option values (together with options with spaces in their names) to be passed via \hx{\documentclass}---if \pkg{catoptions} is loaded before \hx{\documentclass}. This also implies that existing packages can use the options parsing scheme of \pkg'{catoptions} without modifying the packages. +The \pkg'{catoptions} can be loaded in class and style files and in documents (before or after \hx{\documentclass}) with the options described in \sref{sec:pkg-options}. If the package is loaded before \hx{\documentclass}, it will, by default, use the options parser of the package in place of \latex's options parsing scheme (namely, the more robust commands \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} in place of \latex's native commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions})\usefootnote{1}. In that case, the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} are aliased to \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions}, respectively. The latter set of commands do immediately recognize that they have to deal with option functions that are based on the kernel's syntax and semantics. This allows expandable options and option values (together with options with spaces in their names) to be passed via \hx{\documentclass}---if \pkg{catoptions} is loaded before \hx{\documentclass}. This also implies that existing packages can use the options parsing scheme of \pkg'{catoptions} without modifying the packages. -However, if after loading \pkg'{catoptions} before \hx{\documentclass} the user still wants to use the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions}, the package option \fx{usepox} (see \amref{sec:pkg-options}) can be toggled to \texttt{false}. In this case, option values can't be passed via \hx{\documentclass}. More precisely, option values passed via \hx{\documentclass} are stripped off internally by \pkg{catoptions} so that they may be processed by \hx{\ProcessOptions}. +However, if after loading \pkg'{catoptions} before \hx{\documentclass} the user still wants to use the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions}, the package option \fx{usepox} (see \sref{sec:pkg-options}) can be toggled to \texttt{false}. In this case, option values can't be passed via \hx{\documentclass}. More precisely, option values passed via \hx{\documentclass} are stripped off internally by \pkg{catoptions} so that they may be processed by \hx{\ProcessOptions}. \docsection(sec:pkg-options)<Package options>{Package options} -\lletter{T}{he} \pkg'{catoptions} has the options shown in \amref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to enter information onto the log file when some events happen (\eg, when commands are redefined by means of, say, the command \fx{\robust@redef}, which has the same syntax with \tex's legacy \hx{\def}; and when an option from the same family is multiply submitted to, say, \fx{\XExecuteOptions}). This option may be used in the future to provide debugging features for the package. +\lletter{T}{he} \pkg'{catoptions} has the options shown in \sref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to enter information onto the log file when some events happen (\eg, when commands are redefined by means of, say, the command \fx{\robust@redef}, which has the same syntax with \tex's legacy \hx{\def}; and when an option from the same family is multiply submitted to, say, \fx{\XExecuteOptions}). This option may be used in the future to provide debugging features for the package. \extrarowheight=2pt \arrayrulecolor{yellow} @@ -91,7 +93,7 @@ However, if after loading \pkg'{catoptions} before \hx{\documentclass} the user \fx{usepox} & \hx{true} & The boolean switch that determines if the options parser of \pkgg{catoptions} should be used for all options processing of packages loaded after \hx{\documentclass} even if those packages are based on \usecsn{latex2e}'s native options processing scheme.\\\hline \end{tabularx} -As noted in \amref{sec:packageloading}, if the \pkg'{catoptions} is loaded before \hx{\documentclass} it will invariably use the options processing mechanism of the package. In that case (of the package being loaded before \hx{\documentclass}), the option \fxim{usepox} directs the package to use the \pkg{catoptions}'s options processing scheme for all the packages loaded after \hx{\documentclass}, instead of \latex's native options parsing procedures. This allows \pkg{catoptions}'s options parsing scheme to be used for existing packages loaded after \hx{\documentclass} without modifying the packages. +As noted in \sref{sec:packageloading}, if the \pkg'{catoptions} is loaded before \hx{\documentclass} it will invariably use the options processing mechanism of the package. In that case (of the package being loaded before \hx{\documentclass}), the option \fxim{usepox} directs the package to use the \pkg{catoptions}'s options processing scheme for all the packages loaded after \hx{\documentclass}, instead of \latex's native options parsing procedures. This allows \pkg{catoptions}'s options parsing scheme to be used for existing packages loaded after \hx{\documentclass} without modifying the packages. Assuming that the options \quotedtt{textstyle} and \quotedtt{name} belong to an existing package (say, \quotedtt{mypackage}) to be loaded later, then the following example demonstrates one feature of the \pkg'{catoptions}, in the case in which the package is loaded before \hx{\documentclass}: @@ -132,7 +134,7 @@ After issuing the command \fx{\GetCurrentCatcodeSubset}, you can do \finish{example} \fxim*{\currentcatcodesubset} -to see the current catcode setup. The command \fx{\cptfutureletsetup} is described in \amref{sec:future-letting}. +to see the current catcode setup. The command \fx{\cptfutureletsetup} is described in \sref{sec:future-letting}. \start{example}[\UseNormalCatcodes] \ProvidesPackage{mypackage}[2011/01/16 v0.01] @@ -145,7 +147,7 @@ to see the current catcode setup. The command \fx{\cptfutureletsetup} is describ \dummyfxi*{\UseNormalCatcodes} -\docsection(sec:future-letting){Future-letting of \headqtd{other} characters} +\docsection(sec:future-letting){Future-letting of \headquoted{other} characters} The command \fx{\cptfutureletsetup} defines canonical control sequences to represent the following characters: @@ -299,6 +301,9 @@ The commands \ffx'{\mypack@error,\mypack@info} can be used as follows: The interfaces of the options processing commands are as follows, which, apart from the optional family \ang{fam} and default value \ang{default}, are syntactically similar to the corresponding native \latex commands. The optional family name is useful for defining unique options that stand only a remote chance of being mixed up with options of other families. And the optional default value is handy when the user doesn't supply a value for an option: no errors are produced in this case. Existing packages can be processed with these commands without any modifications to those packages. In fact, we have run many existing packages on the bases of these commands (by letting \latex's \hhx'{\DeclareOption,\ExecuteOptions,\ProcessOptions} to these commands), without encountering difficulties. + +\docsubsection(sec:ord-options){Ordinary options} + \start{newmacro}[\XDeclareOption] \XDeclareOption<|nang(fam)>{|nang(opt)}[|nang(default)]{|nang(fn1)}|label(mac:xdec:a) \XDeclareOption|*<|nang(fam)>{|nang(fn2)}|label(mac:xdec:b) @@ -314,11 +319,11 @@ The \unstform of the macro \fx{\XDeclareOption} declares an option that can be u \XDeclareOption{leftmargin}[.5\hsize]{\setlength\leftmargin{#1}}|xwmlabel(mac:leftmargin) \finish{example} -\deffnote{2}{% +\deffootnote{2}{% The commands \ffx'{\XDeclareBooleanOption, \XDeclareBooleanOptions, \XDeclareBiBooleanOptions} allow the user to define new boolean options without the need to first initialize the booleans with \hx{\newif} or \fx{\cptnewbool} as seen here. } -The user would have noticed the use \fx{\cptnewbool} in the above example\usefnote{2}. The options \ffx'{mybool,leftmargin} could then be called via any of the following statements: +The user would have noticed the use \fx{\cptnewbool} in the above example\usefootnote{2}. The options \ffx'{mybool,leftmargin} could then be called via any of the following statements: \start{example}[\XDeclareOption] |com(Inside class or package files:) @@ -329,76 +334,12 @@ The user would have noticed the use \fx{\cptnewbool} in the above example\usefno \documentclass[mybool,leftmargin=20pt]{myclass} \finish{example} -The \stform of the macro \fx{\XDeclareOption} can be used to process unknown options. It is similar to \latex's \hx{\DeclareOption}\RedStar, but it has additional features. You can deploy \hx{\CurrentOption} within the \ang{fn} of this macro to access the option name and value for which the option is unknown. These values (possibly including an option) could, for example, be passed on to another class or package or could be used as an extra class or package option that, for instance, specifies a style that should be loaded. Moreover, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{fn} to refer to the current family, current option (without its value), and current value, respectively. +The \stform of the macro \fx{\XDeclareOption} can be used to process unknown options. It is similar to \latex's \hx{\DeclareOption}\Redstar, but it has additional features. You can deploy \hx{\CurrentOption} within the \ang{fn} of this macro to access the option name and value for which the option is unknown. These values (possibly including an option) could, for example, be passed on to another class or package or could be used as an extra class or package option that, for instance, specifies a style that should be loaded. Moreover, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{fn} to refer to the current family, current option (without its value), and current value, respectively. -\Note This note refers to macro lines \ref{mac:xdec:a} and \ref{mac:xdec:b}. In \fx{\XDeclareOption}, the current option value can be accessed by using \fx{#1} in \ang{fn1}. However, in \xdecs the current family name is accessed as \fx{#1}, the option name is available in \fx{#2}, and the current option value can be accessed with \fx{#3} (all in \ang{fn2}). These differences are important. - -\start{newmacro}[\XUnknownOptionHandler] -\XUnknownOptionHandler<|nang(fams)>[|nang(na)]{|nang(handler)} -\finish{newmacro} -\fxim*{\XUnknownOptionHandler} +\ltsnote This note refers to macro lines \ref{mac:xdec:a} and \ref{mac:xdec:b}. In \fx{\XDeclareOption}, the current option value can be accessed by using \fx{#1} in \ang{fn1}. However, in \xdecs the current family name is accessed as \fx{#1}, the option name is available in \fx{#2}, and the current option value can be accessed with \fx{#3} (all in \ang{fn2}). These differences are important. -\deffnote{3}{% - Declaring a default handler for each unknown option is, of course, inefficient. - We have, therefore, provided provisions for declaring such handers for only families of options. -} -The command \fx{\XUnknownOptionHandler} can be used in place of \xdecs to specify default action(s) for options undefined in any family in \ang{fams}\usefnote{3}. \ang{handler} refers to the default function that should be executed if undeclared options are called from families \ang{fams} by the user. \hx{\CurrentOption} can be deployed within \ang{handler} to access the option name (coupled with its current value) for which the option name is unknown. As mentioned above in the case of \xdecs, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{handler} to access the current family, current option (uncoupled from its current value), and current value, respectively. \ang{na} is the list of options for which \ang{handler} shouldn't apply; for these options, the kernel's unknown option handler (\ie, \hx{\default@ds}) would apply. -If the \ang{handler} contains the special literal form \fx{define/.code=} as in - -\start{example}[Unknown option handler] -|A(fn1) |R(define/.code=)|nang(callback)|R(/.end) |A(fn2)|label(mac:handler) -\finish{example} -\fxim*{define/.code} - -then each unknown option in families \ang{fams} will be momentarily defined and executed with the option function \ang{callback}. The family of the new option will be \fx{\cpt@currfam} (the prevailing family name); its default value will be \fx{\cpt@currval} (the value specified by the user for the unknown option); and its macro function will be the above-indicated \ang{callback}. Again, you can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{handler} to refer to the current option family, option name, and option value, respectively. - -\Note Functions \ang{fn1} and \ang{fn2} on \amref{mac:handler} will be executed for each unknown function in families \ang{fams}, but (unlike \ang{callback}) will not be used in defining unknown options of \ang{fams}. - -If the value given for the unknown option is \hx{true} or \hx{false}, the new (\ie, undeclared) option will be defined as a boolean option with macro prefix \quotedFx{\@currname @}; otherwise it will be defined as a command option with macro prefix \quotedfx{cmd\@currname @}. (See the descriptions of the commands \ffx'{\XDeclareCommandOption,\XDeclareBooleanOption} for the meaning of \quoted{macro prefix}.) It should be noted that the token \quoted{define} in the above syntax is not escaped, and that the token \fx{/.end} is mandatory. If \ang{callback} contains these literal forms, they have to be enclosed in curly braces. - -The following example, among other things, produces a warning when the user supplies an option that was not previously declared: - -\zapname -\start{example}[\XDeclareOption*] -\XDeclareOption|*<mypackage>{% - |com(Unknown options will not be defined automatically here:) - \PackageWarningNoLine{mypackage}{Unknown option `\CurrentOption' ignored}% - |com(Current option family:) - \def\currfamily{#1}% - |com(Current option without the given value:) - \def\curroption{#2}% - |com(User-supplied value of current option:) - \def\currvalue{#3}% - |com(User defined function:) - \def\mymacro##1{\do@a{#2=#3}\do@b{##1}% - |com(`\CurrentOption' isn't equivalent to `#2=#3' because non-active) - |com(spaces around `#3' would have been removed.) -} -\finish{example} - -And the following example passes undeclared options to \hx{article} class: - -\zapname -\start{example}[\XDeclareOption*] -\XDeclareOption|*{\PassOptionsToClass{#2=#3}{article}} -\finish{example} - -The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the callback shown. - -\start{example}[\XUnknownOptionHandler] -\XUnknownOptionHandler<mypackage>{% - |com(Unknown options will be defined automatically here with the) - |com(indicated code:) - |R(define/.code=) - \def\x##1{##1\relax `option #2 = value #3' in family `#1'}% - |R(/.end) - |com(The following will be executed for each unknown option of the) - |com(given family, but will not be a `callback' for unknown options:) - \PackageWarningNoLine{mypackage}{Unknown option `#2' of family - `#1' defined on the fly}% -} -\finish{example} +\docsubsection(sec:external-options){External options} If no default family handler has been provided by the user (through the macro \xdecs or \fx{\XUnknownOptionHandler}) for the family of an undeclared option, and the option doesn't appear in the list \fx{\XExternalOptions}, then that option will be logged (\ie, entered in the transcript file) as undefined at the end of the document. By default, \fx{\XExternalOptions} contains all \hhx'{article,report,memoir} class options. The user can update the \fx{\XExternalOptions} list by means of the following commands: @@ -410,7 +351,7 @@ If no default family handler has been provided by the user (through the macro \x where \ang{opts} are the comma-separated option names to be added to, or removed from, the list. -\Note Unknown options that appear in \fx{\XExternalOptions} list will not have their \ang{fn1}, \ang{fn2} and \ang{callback} of the default family handler (see \amref{mac:handler}) executed unless they contain one of the commands \hhx'{\PassOptionsToClass, \PassOptionsToPackage}. +\ltsnote Unknown options that appear in \fx{\XExternalOptions} list will not have their \ang{fn1}, \ang{fn2} and \ang{callback} of the default family handler (see \sref{mac:handler}) executed unless they contain one of the commands \hhx'{\PassOptionsToClass, \PassOptionsToPackage}. \start{newmacro}[\XDeclareOptions] \XDeclareOptions<|nang(fam)>{|nang(opts)}[|nang(default)]{|nang(fn)} @@ -419,37 +360,15 @@ where \ang{opts} are the comma-separated option names to be added to, or removed The command \fx{\XDeclareOptions} is similar to \fx{\XDeclareOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. The command \fx{\XDeclareOptions} can be used to save tokens when it is required to declare a set of options with identical attributes. -\start+{newmacro}[\XDeclareInvalidOption,\XDeclareInvalidOptions] -\XDeclareInvalidOption<|nang(fams)>{|nang(opt)} -\XDeclareInvalidOptions<|nang(fams)>{|nang(opts)} -\finish{newmacro} -\fxim*{\XDeclareInvalidOption,\XDeclareInvalidOptions} - -The commands \ffx'{\XDeclareInvalidOption,\XDeclareInvalidOptions} declare the given list \ang{opts} as invalid or inadmissible within the specified families \ang{fams}. A user submitting the invalid option will receive the message the option author has specified for the given family via the command \fx{\XInvalidOptionHandler}. Package and class authors don't necessarily have to provide invalid-option handler for each or any family (of their options) via the macro \fx{\XInvalidOptionHandler}: the package provides a default error message for invoked invalid options when the author of the option hasn't defined an invalid-option handler. - -\start{newmacro}[\XInvalidOptionHandler] -\XInvalidOptionHandler<|nang(fams)>{|nang(handler)} -\finish{newmacro} -\fxim*{\XInvalidOptionHandler} - -The command \fx{\XInvalidOptionHandler} defines, for each family \ang{fam} in \ang{fams}, a one-parameter function, which, when specified, is used to replace the macros of options in the family \ang{fam} when the options appear in \ang{opts} list of \fx{\XDeclareInvalidOptions}. - -\start{example}[\XInvalidOptionHandler] -\XInvalidOptionHandler<fama,famb>{% - \@latex@error{Invalid or null option `\CurrentOption'}% - {I have encountered an invalid option `\CurrentOption': - Your package author has set this option as inadmissible.}% -} -\XDeclareInvalidOptions<fama,famb>{opta,optb} -\finish{example} +\docsubsection(sec:cmd-options){Command options} \start{newmacro}[\XDeclareCommandOption] \XDeclareCommandOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)} \finish{newmacro} \fxim*{\XDeclareCommandOption} -The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl*'\bs{pref,opt} to hold the user-supplied value of the option. The macro so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedFx{\@currname @} prefixed with the letters \fx{cmd}. +The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl*'\bs{pref,opt} to hold the user-supplied value of the option. The macro so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} prefixed with the letters \fx{cmd}. \start{newmacro}[\XDeclareCommandOptions] \XDeclareCommandOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} @@ -459,12 +378,14 @@ The command \fx{\XDeclareCommandOption} will, apart from declaring the option \a The command \fx{\XDeclareCommandOptions} is similar to \fx{\XDeclareCommandOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. +\docsubsection(sec:bool-options){Boolean options} + \start{newmacro}[\XDeclareBooleanOption] \XDeclareBooleanOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)} \finish{newmacro} \fxim*{\XDeclareBooleanOption} -The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \ang{opt}, also create a boolean \fnl*'{\bs if}{pref,opt}. It will automatically toggle this boolean (to \hx{true} or \hx{false}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedFx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a boolean option. +The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \ang{opt}, also create a boolean \fnl*'{\bs if}{pref,opt}. It will automatically toggle this boolean (to \hx{true} or \hx{false}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a boolean option. \start{newmacro}[\XDeclareBooleanOptions] \XDeclareBooleanOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} @@ -474,6 +395,8 @@ The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \a The command \fx{\XDeclareBooleanOptions} is similar to \fx{\XDeclareBooleanOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Again, each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. +\docsubsubsection(sec:bibool-options){Biboolean options} + \start{newmacro}[\XDeclareBiBooleanOptions] \XDeclareBiBooleanOptions<|A(fam)>{|A(opt1),|A(opt2)}[|A(default)]|(|A(pref)|){|A(fn1)}{|A(fn2)} \finish{newmacro} @@ -482,6 +405,8 @@ The command \fx{\XDeclareBooleanOptions} is similar to \fx{\XDeclareBooleanOptio The command \fx{\XDeclareBiBooleanOptions} declares the two options \ang{opt1} and \ang{opt2} in the comma-separated list of options. Again, each of the two declared options is defined with the same family \ang{fam} and default value \ang{default}, but separate functions \ang{fn1} and \ang{fn2}. A distinguishing characteristic of bi-boolean options is that when one option is \hx{true}, the partner option is automatically turned \hx{false}, and vice versa. +\docsubsection(sec:switch-options){Switch options} + \start{newmacro}[\XDeclareSwitchOption] \XDeclareSwitchOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)} \finish{newmacro} @@ -495,10 +420,10 @@ In the parlance of the \pkg'{catoptions,ltxtools}, a switch can assume only one \finish{newmacro} \fxim*{\ifswitchTF,\ifswitchFT} -\deffnote{4}{% +\deffootnote{4}{% Because of the need to do, \eg, \fx{\let\swa\cpttrue} and \hx{\if}\unskip\fx{\swa} for any given switch \fx{\swa}, switches, unlike toggles, don't have their own separate namespace and it is all too easy to redefine an existing switch. } -Note that here \ang{switch} has no escape character, unless it evaluates to a switch name. So, after defining \fx{\def\swa{00}} we could then do \fx{\ifswitchTF{swa}{true}{false}}. It is somewhat risky to introduce new switches with \hx{\def} or \hx{\let}\usefnote{4}. It is advisable to always use \fx{\newswitch} instead. It has the syntax +Note that here \ang{switch} has no escape character, unless it evaluates to a switch name. So, after defining \fx{\def\swa{00}} we could then do \fx{\ifswitchTF{swa}{true}{false}}. It is somewhat risky to introduce new switches with \hx{\def} or \hx{\let}\usefootnote{4}. It is advisable to always use \fx{\newswitch} instead. It has the syntax \start{newmacro}[\newswitch] \newswitch{|nang(switch)}[|nang(state)] @@ -519,7 +444,7 @@ It is possible to toggle the state of a switch by simply using the commands: \finish{newmacro} \fxim*{\setswitchtrue,\setswitchfalse} -The command \fx{\XDeclareSwitchOption} will, apart from declaring the option \ang{opt}, also create a switch \fnl*'\bs{pref,opt}. It will automatically toggle this switch to \hx{true} (equivalent to \fx{00}) or \hx{false} (equivalent to \fx{01}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is again \quotedFx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a switch option. +The command \fx{\XDeclareSwitchOption} will, apart from declaring the option \ang{opt}, also create a switch \fnl*'\bs{pref,opt}. It will automatically toggle this switch to \hx{true} (equivalent to \fx{00}) or \hx{false} (equivalent to \fx{01}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is again \quotedfx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a switch option. \start{newmacro}[\XDeclareSwitchOptions] \XDeclareSwitchOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} @@ -529,6 +454,105 @@ The command \fx{\XDeclareSwitchOption} will, apart from declaring the option \an The command \fx{\XDeclareSwitchOptions} is similar to \fx{\XDeclareSwitchOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Again, each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. +\docsubsection(sec:unknown-options){Unknown option handler} + +\start{newmacro}[\XUnknownOptionHandler] +\XUnknownOptionHandler<|nang(fams)>[|nang(na)]{|nang(handler)} +\finish{newmacro} +\fxim*{\XUnknownOptionHandler} + +\deffootnote{3}{% + Declaring a default handler for each unknown option is, of course, inefficient. + We have, therefore, provided provisions for declaring such handers for only families of options. +} +The command \fx{\XUnknownOptionHandler} can be used in place of \xdecs to specify default action(s) for options undefined in any family in \ang{fams}\usefootnote{3}. \ang{handler} refers to the default function that should be executed if undeclared options are called from families \ang{fams} by the user. \hx{\CurrentOption} can be deployed within \ang{handler} to access the option name (coupled with its current value) for which the option name is unknown. As mentioned above in the case of \xdecs, you can use \fx{#1}, \fx{#2} and \fx{#3} within \ang{handler} to access the current family, current option (uncoupled from its current value), and current value, respectively. \ang{na} is the list of options for which \ang{handler} shouldn't apply; for these options, the kernel's unknown option handler (\ie, \hx{\default@ds}) would apply. + +If the \ang{handler} contains the special literal form \fx{define/.code=} as in + +\start{example}[Unknown option handler] +|A(fn1) |R(define/.code=)|nang(callback)|R(/.end) |A(fn2)|label(mac:handler) +\finish{example} +\fxim*{define/.code} + +then each unknown option in families \ang{fams} will be momentarily defined and executed with the option function \ang{callback}. The family of the new option will be \fx{\cpt@currfam} (the prevailing family name); its default value will be \fx{\cpt@currval} (the value specified by the user for the unknown option); and its macro function will be the above-indicated \ang{callback}. Again, you can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{handler} to refer to the current option family, option name, and option value, respectively. + +\ltsnote Functions \ang{fn1} and \ang{fn2} on \sref{mac:handler} will be executed for each unknown function in families \ang{fams}, but (unlike \ang{callback}) will not be used in defining unknown options of \ang{fams}. + +If the value given for the unknown option is \hx{true} or \hx{false}, the new (\ie, undeclared) option will be defined as a boolean option with macro prefix \quotedfx{\@currname @}; otherwise it will be defined as a command option with macro prefix \quotedfx{cmd\@currname @}. (See the descriptions of the commands \ffx'{\XDeclareCommandOption,\XDeclareBooleanOption} for the meaning of \quoted{macro prefix}.) It should be noted that the token \quoted{define} in the above syntax is not escaped, and that the token \fx{/.end} is mandatory. If \ang{callback} contains these literal forms, they have to be enclosed in curly braces. + +The following example, among other things, produces a warning when the user supplies an option that was not previously declared: + +\amvzapname +\start{example}[\XDeclareOption*] +\XDeclareOption|*<mypackage>{% + |com(Unknown options will not be defined automatically here:) + \PackageWarningNoLine{mypackage}{Unknown option `\CurrentOption' ignored}% + |com(Current option family:) + \def\currfamily{#1}% + |com(Current option without the given value:) + \def\curroption{#2}% + |com(User-supplied value of current option:) + \def\currvalue{#3}% + |com(User defined function:) + \def\mymacro##1{\do@a{#2=#3}\do@b{##1}% + |com(`\CurrentOption' isn't equivalent to `#2=#3' because non-active) + |com(spaces around `#3' would have been removed.) +} +\finish{example} + +And the following example passes undeclared options to \hx{article} class: + +\amvzapname +\start{example}[\XDeclareOption*] +\XDeclareOption|*{\PassOptionsToClass{#2=#3}{article}} +\finish{example} + +The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the callback shown. + +\start{example}[\XUnknownOptionHandler] +\XUnknownOptionHandler<mypackage>{% + |com(Unknown options will be defined automatically here with the) + |com(indicated code:) + |R(define/.code=) + \def\x##1{##1\relax `option #2 = value #3' in family `#1'}% + |R(/.end) + |com(The following will be executed for each unknown option of the) + |com(given family, but will not be a `callback' for unknown options:) + \PackageWarningNoLine{mypackage}{Unknown option `#2' of family + `#1' defined on the fly}% +} +\finish{example} + + +\docsubsection(sec:invalid-options){Invalid options} + +\start+{newmacro}[\XDeclareInvalidOption,\XDeclareInvalidOptions] +\XDeclareInvalidOption<|nang(fams)>{|nang(opt)} +\XDeclareInvalidOptions<|nang(fams)>{|nang(opts)} +\finish{newmacro} +\fxim*{\XDeclareInvalidOption,\XDeclareInvalidOptions} + +The commands \ffx'{\XDeclareInvalidOption,\XDeclareInvalidOptions} declare the given list \ang{opts} as invalid or inadmissible within the specified families \ang{fams}. A user submitting the invalid option will receive the message the option author has specified for the given family via the command \fx{\XInvalidOptionHandler}. Package and class authors don't necessarily have to provide invalid-option handler for each or any family (of their options) via the macro \fx{\XInvalidOptionHandler}: the package provides a default error message for invoked invalid options when the author of the option hasn't defined an invalid-option handler. + +\start{newmacro}[\XInvalidOptionHandler] +\XInvalidOptionHandler<|nang(fams)>{|nang(handler)} +\finish{newmacro} +\fxim*{\XInvalidOptionHandler} + +The command \fx{\XInvalidOptionHandler} defines, for each family \ang{fam} in \ang{fams}, a one-parameter function, which, when specified, is used to replace the macros of options in the family \ang{fam} when the options appear in \ang{opts} list of \fx{\XDeclareInvalidOptions}. + +\start{example}[\XInvalidOptionHandler] +\XInvalidOptionHandler<fama,famb>{% + \@latex@error{Invalid or null option `\CurrentOption'}% + {I have encountered an invalid option `\CurrentOption': + Your package author has set this option as inadmissible.}% +} +\XDeclareInvalidOptions<fama,famb>{opta,optb} +\finish{example} + + +\docsubsection(sec:exec-options){Executing options} + \start{newmacro}[\XExecuteOptions] \XExecuteOptions<|nang(fams)>{|nang(opts)}[|nang(na)] \finish{newmacro} @@ -543,7 +567,10 @@ This macro will not use the declaration done by \xdecs when undeclared options a \finish{example} \dummyfxi*{\XExecuteOptions} -This initializes the option \hx{\leftmargin} of \amref{mac:leftmargin} to 0pt. +This initializes the option \hx{\leftmargin} of \sref{mac:leftmargin} to 0pt. + + +\docsubsection(sec:process-options){Processing options} \start{newmacro}[\XProcessOptions] \XProcessOptions<|nang(fams)>[|nang(na)] @@ -553,9 +580,9 @@ This initializes the option \hx{\leftmargin} of \amref{mac:leftmargin} to 0pt. The re-entrant \fx{\XProcessOptions} macro processes the options and values passed by the user to the class or package. The optional argument \ang{fams} can be used to specify the \emph{families} that have been used to define the options. The optional argument \ang{na} can be used to specify options that should be ignored, \ie, not processed. When used in a class file, this macro will ignore unknown options. This allows the user to use global options in the \hx{\documentclass} command which could be claimed by packages loaded later. -The \stform of \fx{\XProcessOptions} works like the \unstform except that the former also copies user input from the \hx{\documentclass} command and processes the options in the order specified by the \hx{\documentclass}. When the user specifies an option in the \hx{\documentclass} which also exists in the local family (or families) of the package calling \fx{\XProcessOptions}\RedStar, the local option will be set as well. In this case, \fx{#1} in \fx{\XDeclareOption} macro will contain the user-value entered in the \hx{\documentclass} (or \fx{\usepackage} or \fx{\RequirePackage}) command for this option. First the global options from \hx{\documentclass} will set local options and afterwards the local options (specified via \hhx'{\usepackage, \RequirePackage, \LoadClass} or similar commands) will set local options, which could overwrite the global options set earlier, depending on how the options sections are organized. The macro \fx{\XProcessOptions}\RedStar reduces to \fx{\XProcessOptions} only when issued from the class which forms the document class for the file at hand (to avoid setting the same options twice), but not for classes loaded later using, for instance, \hx{\LoadClass}. Global options that do not exist in the local families of the package or class calling \fx{\XProcessOptions}\RedStar will be simply ignored or highlighted. +The \stform of \fx{\XProcessOptions} works like the \unstform except that the former also copies user input from the \hx{\documentclass} command and processes the options in the order specified by the \hx{\documentclass}. When the user specifies an option in the \hx{\documentclass} which also exists in the local family (or families) of the package calling \fx{\XProcessOptions}\Redstar, the local option will be set as well. In this case, \fx{#1} in \fx{\XDeclareOption} macro will contain the user-value entered in the \hx{\documentclass} (or \fx{\usepackage} or \fx{\RequirePackage}) command for this option. First the global options from \hx{\documentclass} will set local options and afterwards the local options (specified via \hhx'{\usepackage, \RequirePackage, \LoadClass} or similar commands) will set local options, which could overwrite the global options set earlier, depending on how the options sections are organized. The macro \fx{\XProcessOptions}\Redstar reduces to \fx{\XProcessOptions} only when issued from the class which forms the document class for the file at hand (to avoid setting the same options twice), but not for classes loaded later using, for instance, \hx{\LoadClass}. Global options that do not exist in the local families of the package or class calling \fx{\XProcessOptions}\Redstar will be simply ignored or highlighted. -The implementation here differs significantly from the \latex kernel's scheme of carrying out \hx{\ProcessOptions} and \hx{\ProcessOptions}\RedStar. It also deviates from the implementations by other options processing packages. The differences lie mainly in how the local and global options are distinguished and in the order of processing those options. Among other issues, the family structure introduced by the \pkg'{catoptions} (though lightweight) makes the independence between local and global options possible, even if the options from the two categories share the same namespace and are mixed in, say, \hx{\documentclass} command. Also, document classes loaded by \hx{\LoadClass} don't have the same primacy as the first document class. When using \latex kernel's \hx{\ProcessOptions} or \hx{\ProcessOptions}\RedStar, a class file can't copy document class options, even if the class file is loaded by \hx{\LoadClass}. This is not the case with the \pkg'{catoptions}. +The implementation here differs significantly from the \latex kernel's scheme of carrying out \hx{\ProcessOptions} and \hx{\ProcessOptions}\Redstar. It also deviates from the implementations by other options processing packages. The differences lie mainly in how the local and global options are distinguished and in the order of processing those options. Among other issues, the family structure introduced by the \pkg'{catoptions} (though lightweight) makes the independence between local and global options possible, even if the options from the two categories share the same namespace and are mixed in, say, \hx{\documentclass} command. Also, document classes loaded by \hx{\LoadClass} don't have the same primacy as the first document class. When using \latex kernel's \hx{\ProcessOptions} or \hx{\ProcessOptions}\Redstar, a class file can't copy document class options, even if the class file is loaded by \hx{\LoadClass}. This is not the case with the \pkg'{catoptions}. \start+{example}[\XDeclareOption,\XExecuteOptions,\XProcessOptions] |com(This is a sample class file. We specify a family for the options,) @@ -630,6 +657,35 @@ The implementation here differs significantly from the \latex kernel's scheme of \fxim*{\cptloadpackages} +\docsubsection(sec:before-proc-options){Hook for before and after processing options} + +\start{newmacro}[\BeforeProcessOptions,\AfterProcessOptions] +\BeforeProcessOptions{|nang(code)} +\AfterProcessOptions{|nang(code)} +\finish{newmacro} +\fxim*{\BeforeProcessOptions,\AfterProcessOptions} + +The macros \ffx'{\BeforeProcessOptions,\AfterProcessOptions} can be used to process \ang{code} before and after \fx{\XProcessOptions} has run its course. The command \fx{\AfterProcessOptions} is particularly useful when it is required to optionally load a package, depending on the state of an option in the current package. For obvious reasons, \latex doesn't allow the loading of packages in the options section. The command \fx{\AfterProcessOptions} can be used to load packages after the current package's options have been processed. Here is an example for optionally loading sub-packages at the end of the options section: + +\start{example}[\AfterProcessOptions] +\newif\ifloadsubpackages +\robust@def*\inputpackage{\cpt@testopt\inp@tpackage{}} +\robust@def*\inp@tpackage[#1]#2{% + \ifloadsubpackages + \AfterProcessOptions{\RequirePackage[#1]{#2}}% + \fi +} +\robust@def*\loadsub#1{% + \docommalist{#1}{% + \XDeclareOption{##1}{\inputpackage[####1]{##1}}% + }% +} +\loadsub{subpkg1,subpkg2,subpkg3} +\finish{example} + + +\docsubsection(sec:ifoptiondef){Testing if an option is defined} + \start{newmacro}[\ifoptdefTF] \ifoptdefTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)} \ifoptdefFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)} @@ -639,6 +695,8 @@ The implementation here differs significantly from the \latex kernel's scheme of The macro \fx{\ifoptdefTF} returns \ang{true} if option \ang{opt} is undefined in one or more members of \ang{fams}, and \ang{false} otherwise. The command \fx{\ifoptdefFT} reverses the logic of \fx{\ifoptdefTF}. +\docsubsection(sec:disable-options){Disabling options} + \start{newmacro}[\XDisableOptions] \XDisableOptions<|nang(fams)>{|nang(opts)} \XDisableOptions|*<|nang(fams)>{|nang(opts)} @@ -649,14 +707,8 @@ The command \fx{\XDisableOptions} disables all the options in the list \ang{opts The \stform of \fx{\XDisableOptions} delays the invalidation of the \ang{opts} until the invocation of \hx{\begin{document}}. This may be used to bar users of the options from committing the options after the start of document, but not before. -\start{newmacro}[\ifoptdisabled] -\ifoptdisabledTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)} -\ifoptdisabledFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)} -\finish{newmacro} -\fxim*{\ifoptdisabledTF} - -The macro \fx{\ifoptdisabledTF} returns \ang{true} if option \ang{opt} has been disabled from one or more members of \ang{fams}, and \ang{false} otherwise. The command \fx{\ifoptdisabledFT} reverses the logic of \fx{\ifoptdisabledTF}. +\docsubsubsection{Logging disabled options} \start{newmacro}[\XLogDisabledOptions] \XLogDisabledOptions<|nang(fams)> @@ -666,6 +718,17 @@ The macro \fx{\ifoptdisabledTF} returns \ang{true} if option \ang{opt} has been The command \fx{\XLogDisabledOptions}, which can be called before and after \hx{\begin{document}}, writes in the current transcript file the options of the families \ang{fams} that have been disabled so far. If no options have been disabled from any of the given families or if the given family does not exist, a message is logged to that effect. +\docsubsubsection{Testing if an option is disabled} + +\start{newmacro}[\ifoptdisabled] +\ifoptdisabledTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)} +\ifoptdisabledFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)} +\finish{newmacro} +\fxim*{\ifoptdisabledTF} + +The macro \fx{\ifoptdisabledTF} returns \ang{true} if option \ang{opt} has been disabled from one or more members of \ang{fams}, and \ang{false} otherwise. The command \fx{\ifoptdisabledFT} reverses the logic of \fx{\ifoptdisabledTF}. + + \docsection(sec:normalize)<Normalizing lists>{Normalizing csv and kv lists} Any arbitrary parser-separated-values (csv) list can be normalized by means of the package command \fx{\csv@@normalize} before processing the list. @@ -694,7 +757,7 @@ Here, \ang{list}, which is populated by parser-separated elements, is not expand \finish{newmacro} \fxim*{\kv@@normalize} -The command \fx{\kv@@normalize} normalizes a list of key-value pairs, returning the result in the macro \fx{\normalized@list} (in the \unstform case) or \ang{listcmd} (in the \stform case). Besides dealing with multiple commas and the spaces between entries, in this case the spaces between keys and the equality sign are removed and multiple equality signs are made only one. Moreover, the category codes of the arbitrary parser and the equality sign is made normal/other throughout the list. The command \fx{\kv@@normalize} is meant for options or key-value parsing; it is used in the options processing scheme of \pkg'{catoptions}. +The command \fx{\kv@@normalize} normalizes a list of key-value pairs, returning the result in the macro \fx{\normalized@list} (in the \unstform case) or \ang{listcmd} (in the \stform case). Besides dealing with multiple commas and the spaces between entries, in this case the spaces between keys and the equality sign are removed and multiple equality signs are made only one. Moreover, the category codes of the arbitrary parser and the equality sign are made normal/other throughout the list. The command \fx{\kv@@normalize} is meant for options or key-value parsing; it is used in the options processing scheme of \pkg'{catoptions}. \start{example}[\csv@@normalize] \begingroup @@ -730,7 +793,6 @@ Here are some points to note about these list processors: \item If an item contains \ang{parser}, it must be wrapped in curly braces when using \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, otherwise the elements may be mixed up during parsing. The braces will persist thereafter, but will of course be removed during printing (if the items are printed). \item White spaces before and after the list separator are always ignored by the normalizer called by \ffx'{\csv@@parse,\kv@@parse}. If an item contains \ang{parser} or starts with a space, it must, therefore, be wrapped in curly braces before commencing these loops. \item Since \ffx'{\csv@@loop,\kv@@loop} don't call the normalizer, they preserve outer/surrounding spaces in the entries. Empty entries in \ang{list} or \ang{listcmd} will be processed by \ffx'{\csv@@loop,\kv@@loop} if the boolean \fx{cpt@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry}, which are based on the boolean \fx{cpt@useempty}, before commencing the iteration. If empty entries are important to the task at hand, then issuing \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} prior to the commencement of the loop is recommended, because a previous call to either \fx{\csv@@loop} or \fx{\kv@@loop} (perhaps by another package) could have set \fx{cpt@useempty} to a state that is no longer valid or desired. -\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} will execute at least once for empty \ang{list} or \ang{listcmd}. \item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} can be nested to any level and can be mixed. \item In the commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, it is always possible to break out of the loop prematurely at any level of nesting, simply by issuing the command \fx{\loopbreak} (see the example below). Breaking an inner loop doesn't affect the continuation of the outer loop, and vice versa; that is, loop breaks are nest-level-dependent. \item The user can insert \fx{\csvbreak} as an element in \ang{list} for any of the commands \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse, \dofunclist} with the hope of automatically breaking out of the list processing prematurely (\ie, before the list is exhausted). The tokens \ffx'{\listbreak, \breaklist} are not defined or used by the \pkg'{catoptions}, to avoid name clashes with other packages. The \pkg'{catoptions} instead uses \fx{\csvbreak}, which is an unexpandable token; if it were to be expandable, then experience has shown that a chaotic infinite loop could arise in an expansion context. Breaking out of the loop prematurely on the current nest level doesn't affect the continuation of the loop on the other levels. @@ -822,7 +884,7 @@ Empty entries in \ang{list} will be ignored by the normalizer called by \fx{\dof |com(Let us load many packages compactly here. This is just an example of) |com(|fx(\dofunclist); you can instead use the more appropriate command) -|com(|fx(\cptloadpackages) to load packages (see |amref(mac:loadpkg)):) +|com(|fx(\cptloadpackages) to load packages (see |sref(mac:loadpkg)):) \def\do#1.#2[#3]{% \@ifpackageloaded{#1}{% \@ifpackagelater{#1}{#2}{}{% @@ -929,7 +991,7 @@ The following provides a simple application of \fx{\indrisloop}, which I posted \finish{example} %\bigskip -\docsection(sec:tsvparse)<Iterating tokenwise>{Parsing \headqtd{tsv} lists} +\docsection(sec:tsvparse)<Iterating tokenwise>{Parsing \headquoted{tsv} lists} \start+{newmacro}[\tsv@@parse,\tsv@@loop] \tsv@@loop{|nang(list)} @@ -969,6 +1031,9 @@ In the commands \ffx'{\tsv@loop,\tsv@@parse}, it is always possible to break out The following change history highlights significant changes that affect user utilities and interfaces; mutations of technical nature are not documented in this section. The numbers on the right-hand side of the following lists are section numbers; the \stsign means the subject features in the package but is not reflected anywhere in this user guide. \begin{versionhist} + \begin{version}{0.2.7}{2011/10/10} + \item Introduced the commands \ffx'{\BeforeProcessOptions,\AfterProcessOptions} \vsecref{sec:before-proc-options} + \end{version} \begin{version}{0.2.6}{2011/09/10} \item Bug fix in the command \fx{\UseNormalCatcodes} \vsecref{sec:saving-catcodes} \end{version} @@ -1006,9 +1071,9 @@ The following change history highlights significant changes that affect user uti \end{versionhist} \newpage -\indexpreambleformat{\centering} -\indexpreamble{Index numbers refer to page numbers.} -\indexcolumns\tw@ +\ltsindexpreambleformat{\centering} +\ltsindexpreamble{Index numbers refer to page numbers.} +\ltsindexcolumns\tw@ \printindex \end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg b/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg index 5a7153b4ca9..a0e96a49764 100644 --- a/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg +++ b/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg @@ -1,8 +1,9 @@ \ProvidesFile{catoptions-guide.cfg}% - [2011/09/10 v0.2.6 Configuration file for catoptions-guide.tex (AM)] + [2011/09/10 v0.2.7 Configuration file for catoptions-guide.tex (AM)] +% Change file name: ++++++++++++++++++++++++++++++++++++++++++ \cptloadpackages{% - xwatermark|printwatermark; + n-xwatermark|printwatermark; array; colortbl; ltablex; @@ -14,13 +15,13 @@ showpagenumbers = true, showheadrule = true, showfootrule = false, - yposition = -.45\paperheight, + yposition = -.42\paperheight, xposition = 0, scale = 1, angle = 0, left-header = The \textcolor{macrocolor}{catoptions} package, style = \textsc{Page~\thepage~of~\pageref{xwmlastpage}}, - right-header = \tcl{black}{\today} + right-header = \ttcl{black}{\today} ] \amltxoptions{% @@ -51,7 +52,7 @@ coordunit=pc,textwidth=\hsize,textangle=0,textscale=1.8,textxpos=0, textypos=32.5]{\xwmfadingtext[textcolor=blue,boxcolor=red, scale=1.8,height=1.5ex,letterwidth=7.8mm]{catoptions}\\[1ex]% - \tcl{blue}{\resizebox{.5\width}{!}{Setting up + \ttcl{blue}{\resizebox{.5\width}{!}{Setting up {\tt\string\futurelet} characters, securing catcodes, and parsing options}}% } @@ -59,7 +60,7 @@ \newwatermark [page=1,fontfamily=phv,fontsize=10pt,fontseries=m,color=black,textalign=center, coordunit=pc,textwidth=\hsize,textangle=0,textscale=1,textxpos=0,textypos=24]{% - \Citation[author={Michael J. Downes, 1958--2003},textcolor=black,leftmargin=0em, + \ltscitation[author={Michael J. Downes, 1958--2003},textcolor=black,leftmargin=0em, fonttype=\small]{% The \pkgg'{pcatcode} functionality would work best if it were built into the \usecsn{latex2e} kernel, but it cannot be usefully added to the kernel now without diff --git a/Master/texmf-dist/tex/latex/catoptions/catoptions.sty b/Master/texmf-dist/tex/latex/catoptions/catoptions.sty index 3c4e5f6c5f2..33f688ad049 100644 --- a/Master/texmf-dist/tex/latex/catoptions/catoptions.sty +++ b/Master/texmf-dist/tex/latex/catoptions/catoptions.sty @@ -1,5 +1,5 @@ %+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% -% This is 'catoptions' package (Version 0.2.6, September 2011) % +% This is 'catoptions' package (Version 0.2.7, October 2011) % % % % The catoptions package changes LaTeX package loading internals % % so that all subsequently loaded packages can rely on having % @@ -85,13 +85,17 @@ \catcode94=7 \catcode126=13 \edef\cpt@hashchar{\string#} +\begingroup +\catcode`#=13 +\gdef\cpt@activehash{#} +\endgroup \m@ne=-1\z@=0pt\p@=1pt \@ifdefinable\m@one{\newcount\m@one\m@one\m@ne} \@ifdefinable\z@pt{\newdimen\z@pt\z@pt\z@} \chardef\active=13 \NeedsTeXFormat{LaTeX2e}[2005/12/01] \ProvidesPackage{catoptions} - [2011/09/10 v0.2.6 Securing catcodes and parsing options (AM)] + [2011/10/22 v0.2.7 Securing catcodes and parsing options (AM)] \ifcase% \ifx\eTeXversion\cpt@undefined\z@pt\else \ifnum\eTeXversion<\tw@\z@pt\else\@ne\fi\fi @@ -99,18 +103,276 @@ {This package requires eTeX version 2 or higher.}% \expandafter\endinput \fi -\ifx\pdfstrcmp\cpt@undefined - \PackageError{catoptions} - {You aren't using pdfTeX version 1.50.0} - {This package requires pdfTeX version 1.50.0}% -\fi -\newcommand*\MsgBrk{\MessageBreak} -\def\cptloggingall{\loggingall\tracingifs\@ne} -\@ifdefinable\showcsn{% - \protected\def\showcsn#1#{\expandafter\show\csname#1\endcsname}% +\@ifdefinable\cpt@nil{\let\cpt@nil\relax} +\newcommand*\cpt@nnil{\cpt@nil} +\let\@iden\@firstofone +\@ifdefinable\iofii{\let\iofii\@firstoftwo} +\@ifdefinable\iiofii{\let\iiofii\@secondoftwo} +\@ifdefinable\ifforbreak{\newif\ifforbreak} +% \ifcsdefinable, \cpt@starorlong, \cptcommanormalize, etc, +% will change later: +\@ifdefinable\ifcsdefinable{\let\ifcsdefinable\@ifdefinable} +\@ifdefinable\cpt@starorlong{\let\cpt@starorlong\@star@or@long} +\@ifdefinable\cpt@testopt{\protected\def\cpt@testopt{\@testopt}} +\@ifdefinable\cptcommanormalize{\let\cptcommanormalize\unexpanded} +\protected\def\ifnot@nil#1{% + \edef\reserved@a{\unexpanded{#1}}% + \ifx\reserved@a\@nnil\expandafter\@gobble + \else\expandafter\@iden\fi +} +\newcommand*\cpt@for@nil{\cpt@for@nil} +% Simple, 1-dimensional comma loop. +\protected\def\cptfor#1\dofor#2{% + \def\cpt@fordo##1,{% + \edef\reserved@a{\unexpanded{##1}}% + \ifx\reserved@a\cpt@for@nil\expandafter\@gobble\else + \expandafter\@iden\fi{% + \ifforbreak\expandafter\iofii\else\expandafter\iiofii\fi + {\def\reserved@a####1\cpt@for@nil,{}\reserved@a} + {#2\cpt@fordo}% + }% + }% + \edef\reserved@a{\cptcommanormalize{#1}}% + \forbreakfalse + \expandafter\cpt@fordo\reserved@a,\cpt@for@nil,% } -\newcommand*\cptnormalcatcodes{% +% Simple, 1-dimensional tsv loop: +\protected\def\cpttfor#1\dofor#2{% + \def\cpt@tfordo##1{% + \edef\reserved@a{\unexpanded{##1}}% + \ifx\reserved@a\cpt@for@nil\expandafter\@gobble\else + \expandafter\@iden\fi{% + \ifforbreak\expandafter\iofii\else\expandafter\iiofii\fi + {\def\reserved@a####1\cpt@for@nil{}\reserved@a} + {#2\cpt@tfordo}% + }% + }% + \forbreakfalse\cpt@tfordo#1\cpt@for@nil +} +\ifcsdefinable\cptchardef{% + \protected\def\cptchardef#1#2 {% + \ifcsdefinable#1{% + \def\reserved@a##1=##2\@nil{##2 }% + \chardef#1\reserved@a=#2\@nil + }% + }% +} +\newcommand\cptswap[2]{#2#1} +\newcommand\cptswapbracefirst[2]{#2{#1}} +\newcommand\cptswapbracesecond[2]{{#2}#1} +\newcommand\cptswapbraceboth[2]{{#2}{#1}} +\cptswap{ }{\let\cptsptoken= } +\def\@space{ } +\@namedef{@gobblespace} {} +\newcommand*\cptnewbools[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname if#1##1\endcsname + {\expandafter\newif\csname if#1##1\endcsname}% + }% +} +\cptnewbools[cpt@]{st,pl,pm,cl,verbose} +\newcommand*\cptnewcounts[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname#1##1\endcsname + {\expandafter\newcount\csname#1##1\endcsname}% + }% +} +\newcommand*\cptnewdimens[2][]{% + \cptfor#2\dofor{% + \expandafter\ifcsdefinable\csname#1##1\endcsname + {\expandafter\newdimen\csname#1##1\endcsname}% + }% +} +\newcommand*\cpt@quark{\@gobble\cpt@quark} +\newcommand\ifxTF[2]{% + \ifblankTF{#1}{% + \ifblankTF{#2}\iofii\iiofii + }{% + \ifblankTF{#2}\iiofii{% + \expandafter\ifblankTF\expandafter{\@gobble#1}{% + \expandafter\ifblankTF\expandafter{\@gobble#2}{% + \ifx#1#2\expandafter\iofii\else\expandafter\iiofii\fi + }{% + \cpt@notonetokenerr{#2}% + }% + }{% + \cpt@notonetokenerr{#1}% + }% + }% + }% +} +\newcommand\ifxFT[2]{\ifxTF{#1}{#2}\iiofii\iofii} +\newcommand\ifcseqTF[2]{% + \ifx#1#2\cpt@quark\expandafter\iofii\else\expandafter\iiofii\fi +} +\newcommand\ifcseqFT[2]{\ifcseqTF{#1}{#2}\iiofii\iofii} +\newcommand*\ifxcseqTF[2]{% + \ifcseqTF{#1}{#2}{% + \iofii + }{% + \expandafter\cptswapbracefirst\expandafter{#1}% + {\expandafter\ifstrcmpTF\expandafter{#2}}% + \iofii\iiofii + }% +} +\newcommand*\defifxTF[2]{% + \begingroup + \edef\reserved@a{\unexpanded{#1}}% + \expandafter\endgroup\ifx#2\reserved@a + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\newcommand\ifnullTF[3]{% + \romannumeral\iffalse{\fi\expandafter\@secondoftwo\expandafter + {\expandafter{\string#1}\expandafter\@secondoftwo\string}% + \expandafter\@firstoftwo\expandafter{\iffalse}\fi0 #3}{0 #2}% +} +\newcommand\ifnullFT[1]{\ifnullTF{#1}\iiofii\iofii} +\newcommand\ifblankTF[1]{% + \expandafter\ifnullTF\expandafter{\@gobble#1.}% +} +\newcommand\ifblankFT[1]{\ifblankTF{#1}\iiofii\iofii} +\let\then\iffalse +\let\dolacus\iffalse +\@ifdefinable\iflacus\relax +\long\def\iflacus#1\dolacus{% + \ifcat$\detokenize\expandafter{\@gobble#1.}$% +} +\newcommand\ifbracedTF[3]{% + \romannumeral + \ifcase + \iffalse{{{\fi\expandafter\expandafter\expandafter + \@gobble\expandafter\expandafter\expandafter + {\expandafter\expandafter\expandafter{\expandafter + \iffalse\expandafter}\expandafter}\expandafter\fi + \string#1}\m@one}\@ne}\z@pt + \expandafter\@secondoftwo + \or + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi + {0 #2}{0 #3}% +} +\newcommand\ifbracedFT[1]{\ifbracedTF{#1}\iiofii\iofii} +\newcommand\ifleadspaceTF[3]{% + \romannumeral\csname + @\ifnullTF{#1}{second}{\iffalse{\fi\cpt@ifleadspace.#1 }}% + oftwo\endcsname{0 #2}{0 #3}% +} +\long\def\cpt@ifleadspace#1 {% + \expandafter\ifnullTF\expandafter{\@gobble#1}{first}{second}% + \expandafter\@gobble\expandafter{\iffalse}\fi +} +%%++ Ulrich Diez: +\newcommand\iftrailspaceTF[1]{% + \romannumeral-`\q + \csname @\expandafter\@firstofone\expandafter{% + \romannumeral\expandafter + \cpt@iftrailspace\expandafter{\cpt@removetospace.#1 }% + }% +} +\newcommand\cpt@iftrailspace[1]{% + \ifnullTF{#1}{% + \expandafter\iiofii\iofii + }{% + \ifleadspaceTF{#1}{% + \expandafter\ifnullTF\expandafter{\@gobblespace#1}{% + \expandafter\@firstoftwo\@firstoftwo + }{% + \@secondoftwo + }% + }{% + \@secondoftwo + }% + }{% + {0 first}{0 second}oftwo\endcsname + }{% + \expandafter\cpt@iftrailspace\expandafter{\cpt@removetospace.#1}% + }% +} +%%-- + +\ifxTF\pdfstrcmp\cpt@undefined{% + \RequirePackage{pdftexcmds}% + \ifxTF\pdf@strcmp\cpt@undefined{% + \cpt@err{Neither \string\pdfstrcmp nor \string\pdf@strcmp exists}\@ehc + }{% + \let\cpt@pdfstrcmp\pdf@strcmp + }% +}{% + \let\cpt@pdfstrcmp\pdfstrcmp +} +\newcommand\ifstrcmpTF[2]{% + \usename{@\ifnum\cpt@pdfstrcmp{\detokenize{#1}}% + {\detokenize{#2}}=0first\else second\fi oftwo}% +} +\newcommand\ifstrcmpFT[2]{\ifstrcmpTF{#1}{#2}\iiofii\iofii} +\newcommand*\cpt@def@[3]{% + \ifcsdefinable#3\relax + \ifcat$\detokenize{#2}$\else\protected\fi + \l@ngrel@x\csname#1def\endcsname#3% +} +\ifcsdefinable\robust@def{% + \protected\def\robust@def{\cpt@starorlong{\cpt@def@{}{p}}}% +} +\robust@def*\new@def{\cpt@starorlong{\cpt@def@{}{}}} +\robust@def*\new@gdef{\cpt@starorlong{\cpt@def@{g}{}}} +\robust@def*\robust@gdef{\cpt@starorlong{\cpt@def@{g}{p}}} +\robust@def*\new@edef{\cpt@starorlong{\cpt@def@{e}{}}} +\robust@def*\robust@edef{\cpt@starorlong{\cpt@def@{e}{p}}} +\robust@def*\new@xdef{\cpt@starorlong{\cpt@def@{x}{}}} +\robust@def*\robust@xdef{\cpt@starorlong{\cpt@def@{x}{p}}} +\robust@def*\renew@def{\cpt@starorlong{\cpt@redef@{}}} +\robust@def*\robust@redef{\cpt@starorlong{\cpt@redef@{p}}} +\robust@def*\cpt@redef@#1#2{% + \@ifundefined{\expandafter\@gobble\string#2}{}{% + \ifcpt@verbose + \@latex@info{Command '\string#2' redefined}% + \fi + }% + \ifcat$\detokenize{#1}$\else\protected\fi + \l@ngrel@x\def#2% +} +\new@def*\cpt@checkoptprefix{\@iden} +\robust@def*\provide@def{% + \cpt@checkoptprefix{% + \cpt@testst{\cpt@testcl{\cpt@providedef\relax}}% + }% +} +\robust@def*\providerobust@def{% + \cpt@checkoptprefix{% + \cpt@testst{\cpt@testcl{\cpt@providedef\protected}}% + }% +} +\robust@def*\cpt@providedef#1#2{% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ifdefTF#2{% + \ifcpt@verbose + \cpt@info{Command '\string#2' already defined: + \MsgBrk not redefined}% + \fi + \def\reserved@a{\undefcs\reserved@b}% + }{% + \def\reserved@a{% + \ifcpt@cl\global\fi\let#2\reserved@b + \undefcs\reserved@b + }% + }% + \afterassignment\reserved@a + \ifcpt@st\else\long\fi + #1\def\reserved@b +} +\new@def*\MsgBrk{\MessageBreak} +\new@def*\commentBegin{% + \begingroup + \catcode`\{=12 + \catcode`\}=12 + \catcode`\#=12 + \cpt@commentblock +} +\new@def\cpt@commentblock#1\commentEnd{\endgroup} +\robust@def*\cptnormalcatcodes{% \endlinechar13 \catcode33=12\catcode34=12\catcode35=6\catcode36=3\catcode37=14 \catcode38=4\catcode39=12\catcode40=12\catcode41=12\catcode42=12 @@ -120,17 +382,22 @@ \catcode95=8\catcode96=12\catcode123=1\catcode124=12\catcode125=2 \catcode126=13\catcode32=10\catcode13=5\catcode9=10\catcode10=12 } + \begingroup \let\s\string \escapechar\m@one -\xdef\cpt@otherchars{% - \s\!\s\"\s\#\s\$\s\%\s\&\s\'\s\(\s\)\s\*\s+\s\,\s\-\s\.\s\/\s\:% - \s\;\s\<\s\=\s\>\s\?\s\[\s\\\s\]\s\^\s\_\s\`\s\{\s\|\s\}\s\~% +\new@xdef*\cpt@oth@rchars{% + \s\!\s\"\s\$\s\&\s\'\s\(\s\)\s\*\s+\s\,\s\-\s\.\s\/\s\:% + \s\;\s\<\s\=\s\>\s\?\s\[\s\]\s\^\s\_\s\`\s\|\s\~% + %% left out: \s\\\s\%\s\{\s\}\s\# +} +\new@xdef*\cpt@otherchars{% + \cpt@oth@rchars\s\\\s\%\s\{\s\}\s\#% } \endgroup -\def\cpt@spcatcodestack{} -\def\cpt@sppushcatcodes{% +\new@def*\cpt@spcatcodestack{} +\robust@def*\cpt@sppushcatcodes{% \edef\cpt@spcatcodestack{% \catcode\number`\ =\the\catcode`\ % \catcode\number`\^^I=\the\catcode`\^^I @@ -139,7 +406,7 @@ {\cpt@spcatcodestack}% }% } -\newcommand*\BeginOverlookWhiteSpace{% +\robust@def*\BeginOverlookWhiteSpace{% \pushnumber\cpt@overlooknr \ifnum\cpt@overlooknr>\@ne \cpt@err{There is an unclosed @@ -150,26 +417,26 @@ \catcode`\^^I=9\relax \endlinechar\m@one } -\newcommand*\EndOverlookWhiteSpace{% +\robust@def*\EndOverlookWhiteSpace{% \def\reserved@a##1##{##1\xdef\cpt@spcatcodestack}% \expandafter\reserved@a\cpt@spcatcodestack \undefcs\cpt@overlooknr } -\newcommand*\BeginOverlookEndline{% +\robust@def*\BeginOverlookEndline{% \pushnumber\cpt@overlookendlinenr \ifnum\cpt@overlookendlinenr>\@ne \cpt@err{There is an unclosed \string\BeginOverlookEndline}\@ehc \fi - \chardef\cpt@savendlinechar=\number\endlinechar + \cptchardef\cpt@savendlinechar=\number\endlinechar \endlinechar\m@one } -\newcommand*\EndOverlookEndline{% +\robust@def*\EndOverlookEndline{% \endlinechar\cpt@savendlinechar \undefcs\cpt@overlookendlinenr } -\newcommand*\cpt@catcodestack{} -\newcommand*\cptpushcatcodes{% +\new@def*\cpt@catcodestack{} +\robust@def*\cptpushcatcodes{% \begingroup \def\x##1{% \ifx##1\@nnil\else @@ -185,13 +452,13 @@ } \cptpushcatcodes \cptnormalcatcodes -\newcommand*\cptpopcatcodes{% +\robust@def*\cptpopcatcodes{% \begingroup \def\x##1##{\endgroup##1\xdef\cpt@catcodestack}% \expandafter\x\cpt@catcodestack } \@ifdefinable\currentcatcodesubset\relax -\newcommand*\GetCurrentCatcodeSubset{% +\robust@def*\GetCurrentCatcodeSubset{% \begingroup \def\x##1{% \ifx##1\@nnil\else @@ -207,17 +474,23 @@ }% \expandafter\endgroup\x } -\newcommand*\cpt@setupsafeactivesedef{% +\new@def*\cpt@lq{`} +\robust@def*\cpt@setupsafeactivesedef{% + \let\cpt@setupsafeactivesedef\relax \begingroup - \endlinechar\m@one - \def\siso@do##1{\catcode`##1\string=\active}% - \simpleexpandarg\siso@@loop\cpt@otherchars + \cpttfor!"$&'()*+,-./:;<=>?[]^_`|~\dofor{% + \catcode\cpt@lq##1\string=\active + }% + \everyeof{\noexpand}% + \xdef\cpt@safeactives{\unexpanded\expandafter{\cpt@activehash}% + \scantokens{\unexpanded{!"$&'()*+,-./:;<=>?[]^_`|~}}}% \gdef\cptsafeactivesedef##1##2{% \begingroup - \def\siso@do####1{% - \ifnum\catcode`####1\string=\active\edef####1{\string####1}\fi + \expandafter\cpttfor\cpt@safeactives\dofor{% + \ifnum\catcode\cpt@lq####1\string=\active + \edef####1{\string####1}% + \fi }% - \simpleexpandarg\siso@@loop\cpt@otherchars \cptexpandsecond\endgroup {\edef\noexpand##1{\noexpand\unexpanded{##2}}}% }% @@ -225,7 +498,7 @@ } \newcommand*\declarefutureletset[2][fl@]{% \xdef\cpt@fletprefix{\cpttrimspaces{#1}}% - \cptexpandargonce{\cptfiltermergecsv[,]\cpt@fletprefixes}% + \cptexpandargonce{\cptfiltermergecsv[,]\cpt@fletprefixes} \cpt@fletprefix\nofilter \ifblankTF{#2}{% \def\neededfutureletchars{}% @@ -246,12 +519,13 @@ \globalize\neededfutureletchars \globalize\cpt@fletprefixes } + \begingroup \cptrestorecatcodes \begingroup \catcode`\3="3 \catcode`\4="4 \catcode`\7="7 \catcode`\8="8 \catcode`\A="A \catcode`\B="B \catcode`\C="C \catcode`\D="D -\gdef\cpt@flet@a#1#2{% +\robust@gdef*\cpt@flet@a#1#2{% \begingroup \edef\cpt@tempa{\noexpandcsn{\cpt@fletprefix#1}}% \edef\cpt@tempb{\noexpandcsn{if\cpt@fletprefix#1}}% @@ -286,7 +560,7 @@ }% } \endgroup -\gdef\cpt@futureletchars{% +\robust@gdef*\cpt@futureletchars{% space\@\ \@ exclam\@\!\@ dblquote\@\"\@ hash\@\#\@ dollar\@\$\@ ampersand\@\&\@ rquote\@\'\@ lparen\@\(\@ rparen\@\)\@ star\@\*\@ plus\@\+\@ comma\@\,\@ hyphen\@\-\@ period\@\.\@ slash\@\/\@ @@ -295,11 +569,11 @@ underscore\@\_\@ lquote\@\`\@ lbrace\@\{\@ vert\@\|\@ rbrace\@\}\@ tilde\@\~\@ bslash\@\\\@ } -\gdef\cptfutureletsetup{% +\robust@gdef*\cptfutureletsetup{% \gdef\cpt@activecharacters{}% \gdef\cptfutureletmacros{}% \def\cpt@flet@b##1\@##2\@{% - \ifxTF##1\end{}{% + \expandafter\ifxTF\cpt@car##1\car@nil\end{}{% \oifinset@sp@FT,{##1}\neededfutureletchars{}{% \cpt@flet@a{##1}{##2}% }% @@ -318,7 +592,7 @@ }% }% \def\cpt@fletdef##1\@##2\@{% - \ifxTF##1\end{}{% + \expandafter\ifxTF\cpt@car##1\car@nil\end{}{% \oifinset@sp@FT,{##1}\neededfutureletchars{}{% \csn@xdef{if\cpt@fletprefix##1}####1{% \noexpand\usename{@\noexpand\ifx @@ -335,7 +609,7 @@ \expandafter\cpt@flet@b\cpt@futureletchars\end\@\@ } \AtBeginDocument{\cptrestorecatcodes} -\gdef\futureletresetactives{% +\robust@gdef*\futureletresetactives{% \begingroup \defpass\cpt@tempa##1{\endgroup \def\do####1####2{\let####1=##1####2}% @@ -345,13 +619,13 @@ } \endgroup -\long\protected\def\cpt@ifnextchar#1#2#3{% +\robust@def\cpt@ifnextchar#1#2#3{% \begingroup \let\reserved@a=#1% \toks@{\endgroup#2}\toks1{\endgroup#3}% \global\futurelet\@let@token\cpt@ifnext } -\protected\def\cpt@ifnext{% +\robust@def*\cpt@ifnext{% \ifx\@let@token\@sptoken \toks2{\cpt@ifn@xt}% \else @@ -370,7 +644,7 @@ {\cpt@ifnextcharacter{#1}{#2}{#3}}% {\cpt@ifnextcharacter{#1}{#2}{#3}}% } -\long\def\cpt@ifnextcharacter#1#2#3{% +\new@def\cpt@ifnextcharacter#1#2#3{% \ifcase \ifcat\noexpand\@let@token\bgroup 1\fi \ifcat\noexpand\@let@token\egroup 1\fi @@ -380,47 +654,61 @@ \fi \next{#1}{#2}{#3}% } -\long\def\cpt@ifn@xtcharacter#1#2#3#4{% +\new@def\cpt@ifn@xtcharacter#1#2#3#4{% \escapechar92\relax \edef\x{\cpt@ifn@xtch@racter{#1}\cpt@ifn@xtch@racter{#4}}% \expandafter\endgroup\csname @\expandafter \ifx\x first\else second\fi oftwo\endcsname {#2}{#3}#4% } -\long\def\cpt@ifn@xtch@racter#1{% +\new@def\cpt@ifn@xtch@racter#1{% \expandafter\cpt@ifn@xtch@r@cter\string#1\relax\noboundary{#1}% } -\long\def\cpt@ifn@xtch@r@cter#1#2\noboundary#3{% +\new@def\cpt@ifn@xtch@r@cter#1#2\noboundary#3{% \ifx\relax#2#1\else\noexpand#3\fi } -\protected\def\cpt@starorlong#1{% +\robust@redef\cpt@ifstar#1{\ifnextcharTF*{\@firstoftwo{#1}}} +\robust@redef*\cpt@starorlong#1{% \cpt@ifstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}% } -\protected\def\cpt@ifstar#1{\ifnextcharTF*{\@firstoftwo{#1}}} -\newcommand\cptswap[2]{#2#1} -\newcommand\cptswapfirstbraced[2]{#2{#1}} -\newcommand\cptswapsecondbraced[2]{{#2}#1} -\cptswap{ }{\let\cptsptoken= } -\def\@space{ } -\@ifdefinable\ifsecondisnilTF\relax -\def\ifsecondisnilTF#1#2\cpt@nil{\ifxTF#2\cpt@nnil} -\newcommand\iflacus[1]{% - \ifcat$\detokenize\expandafter{\@gobble#1.}$% - \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +\new@def*\ifsecondisnnilTF#1#2\cpt@nil{% + \expandafter\ifxTF\cpt@car#2\car@nil\cpt@nnil } -\newcommand\aftercsname[2]{% +\new@def\aftercsname#1#2{% \expandafter\cptswap\expandafter{\csname#2\endcsname}{#1}% } -\newcommand\xaftercsname[2]{% - \expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter\cptswap - \expandafter\expandafter\expandafter{\csname#2\endcsname}{#1}% +\new@def\xaftercsname#1#2{% + \expandafter\expandafter\expandafter + \cptswap\expandafter\expandafter + \expandafter{\csname#2\endcsname}{#1}% +} +\new@def\xaftercsnamebrace#1#2{% + \expandafter\expandafter\expandafter + \cptswapbracefirst\expandafter + \expandafter\expandafter{\csname#2\endcsname}{#1}% +} +%% For private use only: +\new@def*\simpleexpandarg#1#2{\expandafter#1\expandafter{#2}} +\@ifdefinable\s@expandarg{\let\s@expandarg\simpleexpandarg} +%%-- + +\new@def*\cptexpandnext#1#2{% + \expandafter\cptswap\expandafter{#2}{#1}% +} +\new@def*\cptexpandbracenext#1#2{% + \expandafter\cptswapbracefirst\expandafter{#2}{#1}% +} +\new@def*\cptexpandsome#1\expandthis#2#3\expandstop{% + \cptexpandnext{#1}{#2}#3% } -\newcommand\cptremovescape[1]{% - \iflacus{#1}{}{\expandafter\@gobble\string#1}% +\new@def*\cptexpandbracesome#1\expandthis#2#3\expandstop{% + \cptexpandbracenext{#1}{#2}#3% } -\newcommand\cptgobblescape[1]{% - \iflacus{#1}{}{% +\new@def\cptremovescape#1{% + \ifblankTF{#1}{}{\expandafter\@gobble\string#1}% +} +\new@def\cptgobblescape#1{% + \ifblankTF{#1}{}{% \ifnum\escapechar>\@cclv\else \ifnum\escapechar<\z@pt\else \expandafter\expandafter @@ -431,19 +719,19 @@ \string#1% }% } -\@ifdefinable\defpass\relax -\@ifdefinable\edefpass\relax -\protected\def\defpass#1#2#{\afterassignment#1\long\def#1#2} -\protected\def\edefpass#1#2#{\afterassignment#1\long\edef#1#2} -\newcommand\usename[1]{\csname#1\endcsname}% long! -\newcommand\usecsn[1]{% +\robust@def*\defpass#1#2#{\afterassignment#1\long\def#1#2} +\robust@def*\edefpass#1#2#{\afterassignment#1\long\edef#1#2} +\new@def\uselivecs#1{% + \ifdefTF{#1}{#1}{\cpt@notdeferr{#1}}% +} +\new@def*\usecsifdef#1{\ifdefTF#1{#1}{}} +\new@def\usename#1{\csname#1\endcsname}% long! +\new@def\usecsn#1{% \ifcsname#1\endcsname\expandafter\@iden\else \expandafter\@gobble\fi{\usename{#1}}% } -\newcommand\uselivecs[1]{% - \ifdefTF{#1}{#1}{\cpt@notdeferr{#1}}% -} -\newcommand\uselivecsn[1]{% +\new@def*\usecsnifdef#1{\ifcsndefTF{#1}{\usename{#1}}{}} +\new@def\uselivecsn#1{% \ifcsndefTF{#1}{% \usename{#1}% }{% @@ -451,33 +739,18 @@ \cpt@err{Command '\@backslashchar#1' undefined}\@ehc }% } -\@ifdefinable\usedefname{\let\usedefname\uselivecsn} -\newcommand\ifxTF[2]{% - \usename{@\ifx#1#2\@empty first\else second\fi oftwo}% +\new@def*\ifcondTF#1\fi#2#3{% + \romannumeral#1 \expandafter\@firstoftwo\else + \expandafter\@secondoftwo\fi{0 #2}{0 #3}% } -\newcommand\ifxFT[2]{\ifxTF{#1}{#2}\@secondoftwo\@firstoftwo} -\newcommand\ifcsemptyTF[1]{\ifxTF#1\@empty} -\newcommand*\defifxTF[2]{% - \begingroup - \edef\cpt@tempa{\unexpanded{#1}}% - \expandafter\endgroup\ifx#2\cpt@tempa - \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi -} -\newcommand*\ifcondTF[1]{% - \long\def\ifcondTF##1\fi##2##3{% - \romannumeral##1#1\expandafter\@firstoftwo\else - \expandafter\@secondoftwo\fi{0 ##2}{0 ##3}% - }% -} -\ifcondTF{ } \long\def\ifcondFT#1\fi#2#3{\ifcondTF#1\fi{#3}{#2}} -\newcommand*\ifcsnameTF[1]{% - \iflacus{#1}\@secondoftwo{% +\new@def*\ifcsnameTF#1{% + \ifblankTF{#1}\@secondoftwo{% \usename{@\ifcsname#1\endcsname first\else second\fi oftwo}% }% } -\newcommand*\ifcsnameFT[1]{\ifcsnameTF{#1}\@secondoftwo\@firstoftwo} -\newcommand*\ifnamedefTF[1]{% +\new@def*\ifcsnameFT#1{\ifcsnameTF{#1}\iiofii\iofii} +\new@def*\ifnamedefTF#1{% \ifcsnameTF{#1}{% \usename{@\expandafter\ifx\csname#1\endcsname\relax second\else first\fi oftwo}% @@ -485,67 +758,38 @@ \@secondoftwo }% } -\protected\def\cpt@notdefinable{% +\robust@def*\cpt@notdefinable{% \@latex@error - {Command '\@backslashchar\reserved@a' already exists}% - {Command '\@backslashchar\reserved@a' already defined, - \MsgBrk or name '\@backslashchar\@qend\reserved@a' illegal.} + {Command '\@backslashchar\undefinablecs' already exists}% + {Command '\@backslashchar\undefinablecs' already defined, + \MsgBrk or name '\@backslashchar\@qend\undefinablecs' illegal.} } -\newcommand*\if@@definable[2]{% - \edef\reserved@a{\cptremovescape{#1}}% - \begingroup - \ifnamedefTF\reserved@a{% - \endgroup\cpt@notdefinable - }{% - \edef\reserved@b{\expandafter\@carcube\reserved@a xxx\@nil}% - \ifx\reserved@b\@qend - \toks@{\cpt@notdefinable}% - \else - \ifx\reserved@a\@qrelax - \toks@{\cpt@notdefinable}% - \else - \toks@{#2}% - \fi - \fi - \expandafter\endgroup\the\toks@ - }% -} -\@ifdefinable\ifchoicefoundTF\relax -\protected\def\ifchoicefoundTF\endgroup{% +\robust@def*\ifchoicefoundTF\endgroup{% \expandafter\endgroup\ifcpt@choicefd \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } -\protected\def\cpt@oneoftwo#1\endgroup{% +\robust@def*\cpt@oneoftwo#1\endgroup{% \let\@firstoftwo\relax \let\@secondoftwo\relax \cptpassexpanded{% \endgroup \ifcase#1\relax - \ifboolTF{cpt@choicefd}\@firstoftwo\@secondoftwo + \ifboolTF{cpt@choicefd}\iofii\iiofii \or - \ifboolTF{cpt@choicefd}\@secondoftwo\@firstoftwo + \ifboolTF{cpt@choicefd}\iiofii\iofii \else \cpt@err{Invalid number '#1'}\noexpand\@ehc \fi }% } -\if@@definable\cpt@ifseeparameter\relax -\protected\def\cpt@ifseeparameter#1#{% +\robust@def*\cpt@ifseeparameter#1#{% \xifinsetTF {\detokenize{macro parameter character}} {\meaning\@let@token}% } -\newcommand*\cptnewbool[1]{% - \expandafter\if@@definable\csname if#1\endcsname - {\expandafter\newif\csname if#1\endcsname}% -} -\newcommand*\cptnewcount[1]{% - \expandafter\if@@definable\csname#1\endcsname - {\expandafter\newcount\csname#1\endcsname}% -} \begingroup \uccode`\~=`\,% @@ -555,198 +799,96 @@ \cpt@activecomma,#1,~\cpt@nil}% }% \def\cpt@activecomma#1~#2\cpt@nil{% - \iflacus{#2} + \ifblankTF{#2} {\cpt@spacecomma#1 ,\cpt@nil} {\cpt@activecomma#1,#2\cpt@nil}% }% } \def\cpt@spacecomma#1 ,#2\cpt@nil{% - \iflacus{#2} + \ifblankTF{#2} {\cpt@commaspace#1, \cpt@nil} {\cpt@spacecomma#1,#2\cpt@nil}% } \def\cpt@commaspace#1, #2\cpt@nil{% - \iflacus{#2} + \ifblankTF{#2} {\cpt@doublecomma#1,,\cpt@nil} {\cpt@commaspace#1,#2\cpt@nil}% } \def\cpt@doublecomma#1,,#2\cpt@nil{% - \iflacus{#2} - {\iflacus{#1}{}{\expandafter\noexpand\@gobble#1}} + \ifblankTF{#2} + {\ifblankTF{#1}{}{\expandafter\noexpand\@gobble#1}} {\cpt@doublecomma#1,#2\cpt@nil}% } -\newcommand*\cptexpandnext[1]{% - \iflacus{#1}{% - \cpt@undefined - }{% - \expandafter\iflacus\expandafter{\@gobble#1}{% - \expandafter#1\expandafter - }{% - \cpt@undefined - }% - }% -} -\newcommand*\cpt@ppcmds[4]{% - \ifcase0\ifnum#1=1 1 \else\ifnum#1=-1 1 \fi\fi - \cpt@err{Invalid stack direction '#1'}\@ehc - \fi - \ifcondTF\ifnum#1=1\fi{% - \edef\reserved@a##1##{##1\gdef\expandafter\noexpand - \csname\cptremovescape#2@stack\endcsname}% - \expandafter\expandafter\expandafter\reserved@a - \csname\cptremovescape#2@stack\endcsname - }{% - \global\advance#4\@ne - \begingroup - \toks@{}\toks1{}\toks2{}% - \def\cpt@tempa##1{\cptremovescape##1@\romannumeral#4\endcsname}% - \def\do##1,{% - \ifnot@nil{##1}{% - \toks@\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\toks@\expandafter - \let\csname\cpt@tempa{##1}##1}% - \toks1\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\toks1\expandafter - \let\expandafter##1\csname\cpt@tempa{##1}}% - \toks2\expandafter\expandafter\expandafter - {\expandafter\the\expandafter\toks2\expandafter - \let\csname\cpt@tempa{##1}\cpt@undefined}% - \do - }% - }% - \edef\reserved@a{\cptcommanormalize{#3}}% - \expandafter\do\reserved@a,\@nil,% - \expandafter\xdef\csname\cptremovescape#2@stack\endcsname{% - \the\toks1\relax\the\toks2\global\advance#4\m@one - \@ifundefined{\cptremovescape#2@stack}{{}}{% - {\unexpanded\expandafter\expandafter\expandafter - {\csname\cptremovescape#2@stack\endcsname}}% - }% - }% - \expandafter\endgroup\the\toks@ - }% -} -\newcommand*\cpt@pushcmds[3]{\cpt@ppcmds\m@one#1{#2}#3} -\newcommand*\cpt@popcmds[1]{\cpt@ppcmds1#1\relax\relax} -\cptnewcount{cpt@csvdepth} -\cptnewbool{loopbreak} -\if@@definable\loopbreak{\let\loopbreak\loopbreaktrue} -\newcommand*\cpt@commanil{\cpt@commanil} -\newcommand*\docommalist{\cpt@ifstar\cpt@docommalist\cpt@doc@mmalist} -\newcommand*\cpt@docommalist[1]{% - \expandafter\cpt@doc@mmalist\expandafter{#1}% -} -\newcommand*\cpt@doc@mmalist[2]{% - \cpt@pushcmds\docommalist{\ifloopbreak,\cpt@commaact}\cpt@csvdepth - \def\cpt@commaact##1{#2}% - \def\cpt@commado##1,{% - \@nameuse{@\ifloopbreak first\else second\fi oftwo}{% - \def\reserved@a####1\cpt@commanil,{}\reserved@a - }{% - \edef\reserved@a{\unexpanded\expandafter{\@gobble##1}}% - \ifxTF\reserved@a\cpt@commanil{}{% - \expandafter\cpt@commaact\expandafter{\reserved@a}\relax - \cpt@commado.% - }% - }% - }% - \loopbreakfalse - \edef\reserved@a{\cptcommanormalize{#1}}% - \expandafter\cpt@commado\expandafter.\reserved@a,\cpt@commanil,% - \cpt@popcmds\docommalist -} -\docommalist{st,pl,pm,cl}{\cptnewbool{cpt@#1}} -\newcommand*\cpt@cmdsuffixcheck{\@iden} -\AtEndOfPackage{\DefSuffixChecker\cpt@cmdsuffixcheck{*}{!}} -\if@@definable\shelldef{% - \protected\def\shelldef{% - \cpt@cmdsuffixcheck{% - \cpt@ifstar{\cpt@sttrue\cpt@shelldef} - {\cpt@stfalse\cpt@shelldef}% - }% - }% -} -\protected\def\cpt@shelldef{% - \ifnextcharTF - !{\@firstoftwo{\cpt@cltrue\cpt@shelld@f}} - {\cpt@clfalse\cpt@shelld@f}% -} -\protected\def\cpt@shelld@f#1{% - \if\expandafter\@car\string#1x\@nil\@backslashchar\else - \@latex@error{Token '\detokenize{#1}' not escaped}\@ehc - \fi - \if@@definable#1{% - \ifcpt@cl\global\fi\ifcpt@st\else\long\fi - \protected\def#1% - }% -} -\shelldef*\cpt@notdeferr#1{% +\cptnewcounts{cpt@csvdepth} +\cptnewbools{loopbreak} +\ifcsdefinable\loopbreak{\let\loopbreak\loopbreaktrue} +\robust@def*\cpt@notdeferr#1{% \@latex@error{Command '\detokenize{#1}' isn't defined} {I expected '\detokenize{#1}' to be defined.}% } -\shelldef*\cpt@isdeferr#1{% +\robust@def*\cpt@isdeferr#1{% \@latex@error{Command '\detokenize{#1}' is already defined} {I expected '\detokenize{#1}' to be undefined.}% } -\shelldef*\cpt@notcserr#1{% +\robust@def*\cpt@notcserr#1{% \@latex@error{Token '\detokenize{#1}' not a macro \MsgBrk or is currently undefined} {I expected '\detokenize{#1}' to be defined.}% } -\shelldef*\cpt@iscserr#1{% +\robust@def*\cpt@iscserr#1{% \@latex@error{Token '\detokenize{#1}' is a macro: \MsgBrk not currently undefined} {I didn't expect '\detokenize{#1}' to be defined.}% } -\shelldef*\cpt@notescapederr#1{% +\robust@def*\cpt@notescapederr#1{% \@latex@error{Token '\detokenize{#1}' not escaped \MsgBrk or is an active character}{I expected the first token of\MsgBrk'\detokenize{#1}' to be escape character.}% } -\shelldef*\cpt@isescapederr#1{% +\robust@def*\cpt@isescapederr#1{% \@latex@error{Token '\detokenize{#1}' is escaped}{% I didn't expect the first character of '\detokenize{#1}' \MsgBrk to be the escape character.}% } -\shelldef*\cpt@notbracederr#1{% +\robust@def*\cpt@notbracederr#1{% \@latex@error{Token '\detokenize{#1}' isn't braced} {I expected '\detokenize{#1}' to be braced.}% } -\shelldef*\cpt@isbracederr#1{% +\robust@def*\cpt@isbracederr#1{% \@latex@error{Token '\detokenize{#1}' is braced} {I didn't expect '\detokenize{#1}' to be braced.}% } -\shelldef*\cpt@notonetokenerr#1{% +\robust@def*\cpt@notonetokenerr#1{% \@latex@error{'\detokenize{#1}' is not one token} {I expected '\detokenize{#1}' to be one token.}% } -\shelldef*\cpt@isonetokenerr#1{% +\robust@def*\cpt@isonetokenerr#1{% \@latex@error{'\detokenize{#1}' is one token} {I didn't expect '\detokenize{#1}' to be one token.}% } -\shelldef*\cpt@notblankerr#1{% +\robust@def*\cpt@notblankerr#1{% \@latex@error{'\detokenize{#1}' is not blank or empty} {I expected '\detokenize{#1}' to be blank.}% } -\shelldef*\cpt@isblankerr#1{% +\robust@def*\cpt@isblankerr#1{% \@latex@error {Blank/empty token for command '\detokenize{#1}'} {I didn't expect a blank argument/token here.}% } -\shelldef*\cpt@notexpandableerr#1{% +\robust@def*\cpt@notexpandableerr#1{% \@latex@error{'\detokenize{#1}' is not expandable \MsgBrk or is undefined} {I expected '\detokenize{#1}' to be expandable.}% } -\shelldef*\cpt@toodeep#1#2{% +\robust@def*\cpt@toodeep#1#2{% \@latex@error{Command '\detokenize{#1}' nested too deeply} {Command '\detokenize{#1}' nested beyond level '#2'.}% } \begingroup \catcode`\&=7 -\protected\gdef\cpt@getmacroprefix#1{% +\robust@gdef*\cpt@getmacroprefix#1{% \begingroup \edef\cpt@tempa##1{\def##1####1\detokenize{macro}:####2&}% \cpt@tempa\@ifmacro{% @@ -762,12 +904,12 @@ \cpteveryscan \cptpassexpanded{% \endgroup - \ifxTF\macroprefix\@empty{\@iden}{\noexpand\scantokens}% + \ifcsemptyTF\macroprefix\@iden{\noexpand\scantokens}% {\def\noexpand\macroprefix{\macroprefix}\relax}% }% } -\gdef\cpt@getprefix#1>#2&{#1} -\protected\gdef\ifprotectedTF#1{% +\new@gdef*\cpt@getprefix#1>#2&{#1} +\robust@gdef*\ifprotectedTF#1{% \begingroup \edef\cpt@tempa##1{\def##1####1\string\protected####2&}% \cpt@tempa\cpt@tempa{% @@ -780,13 +922,16 @@ } \endgroup -\shelldef*\shelllet#1{\cpt@ifeql{\cpt@shelllet{#1}}{\cpt@shelllet{#1}}} -\shelldef*\cpt@shelllet#1#2{% - \iflacus{#2}{% +% We need the equivalent of '\protected\let' and we want to be able to +% do \shelllet\x=\y: +\robust@def*\shelllet#1{\cpt@ifeql{\cpt@shelllet{#1}}{\cpt@shelllet{#1}}} +\robust@def*\cpt@shelllet#1#2{% + \ifblankTF{#2}{% \cpt@isblankerr\shelllet }{% - \expandafter\iflacus\expandafter{\@gobble#2}{% + \expandafter\ifblankTF\expandafter{\@gobble#2}{% \ifcsdefinable#1{% + % Here we must use \let and not \def: \ifprotectedTF#2{\let#1=#2}{% \ifcsndefinable{shell@\cptremovescape#1}{% \letcsntocs{shell@\cptremovescape#1}=#2% @@ -799,17 +944,18 @@ }% }% } -\shelldef\showruntime#1\runtime{% +\robust@def\showruntime#1\runtime{% \pdfresettimer#1% \message{Run time: \the\pdfelapsedtime}% } -\newcommand*\ifdocstartedTF{% - \ifdefTF\cpt@docstarted\@firstoftwo\@secondoftwo +\new@def*\ifdocstartedTF{% + \ifdefTF\cpt@docstarted\iofii\iiofii } -\shelldef*\UseNormalCatcodes{% +\robust@def*\UseNormalCatcodes{% \ifdocstartedTF{% - \cpt@err{\noexpand\UseNormalCatcodes is a - preamble command}\@ehc + \cpt@err + {\noexpand\UseNormalCatcodes is a preamble command} + {Preamble command in document body.}% }{}% \xdef\@pushfilename{% \gletcs\UseNormalCatcodes\UseNorm@lCatcodes @@ -818,7 +964,7 @@ \let\UseNormalCatcodes\relax \cptpushcatcodes \cptnormalcatcodes - \ifxTF\@currname\@empty{% + \ifcseqTF\@currname\@empty{% \BeforeStartOfDocument{% \cptpopcatcodes }% @@ -828,133 +974,59 @@ }% }% } -\if@@definable\UseNorm@lCatcodes{% +\ifcsdefinable\UseNorm@lCatcodes{% \global\let\UseNorm@lCatcodes\UseNormalCatcodes } -\newcommand*\newcomment{% - \begingroup - \def\comment@envir{newcomment}% - \def\do##1{\catcode`##1=12\relax}% - \dospecials - \endlinechar`\^^M\catcode`\^^M=12\relax - \cpt@commentloop -} -\newcommand*\cpt@commentend{% - \ifx\@currenvir\comment@envir - \let\endnewcomment\relax - \def\next{\endgroup\end{newcomment}}% - \else - \let\next\endgroup - \fi - \next -} -\begingroup -\catcode`\^^M=12 % -\endlinechar\m@one% -\gdef\cpt@commentloop#1^^M{% - \def\comment@stuff{#1}% - \ifx\comment@stuff\endnewcomment - \let\next\cpt@commentend - \else - \ifx\comment@stuff\end@newcomment - \let\next\cpt@commentend - \else - \ifx\comment@stuff\end@comment - \def\next{\@latex@error - {Bad end for \string\newcomment}\@ehc}% - \else - \let\next\cpt@commentloop - \fi - \fi - \fi - \next -} -\endgroup -\begingroup -\catcode`\{=12 -\catcode`\}=12 -\catcode`\!=0 -\catcode`\[=1 -\catcode`\]=2 -\catcode`\\=12 -!gdef!end@newcomm@nt[\endnewcomment] -!gdef!end@newcomment[\end{newcomment}] -!gdef!end@comment[\end{comment}] -!endgroup \long\def\@gobblethree#1#2#3{} \long\def\@firstofthree#1#2#3{#1} \long\def\@secondofthree#1#2#3{#2} \long\def\@thirdofthree#1#2#3{#3} -\let\@iden\@firstofone -\newcommand\cptalloftwo[2]{#1#2} -\if@@definable\cpt@nil{\let\cpt@nil\relax} -\def\cpt@nnil{\cpt@nil} -\newcommand*\cptrmstop{0 } -\if@@definable\cptrm{\let\cptrm\romannumeral} -\long\def\cpt@car#1#2\car@nil{#1} -\long\def\cpt@cdr#1#2\cdr@nil{#2} -\if@@definable\cpt@relax{\let\cpt@relax\relax} -\if@@definable\gobble@to@relax\relax -\long\def\gobble@to@relax#1\cpt@relax{} -\def\cpt@defrelax\fi{% - \fi\defpass\cpt@relax##1\cpt@relax{\endgroup}% -} -\long\def\remove@to@nnil#1\@nnil{} -\long\def\catch@to@nnil#1\@nnil{#1} -\long\def\remove@to@dot#1.{} -\long\def\catch@to@dot#1.{#1} -\long\def\remove@to@space#1 {} -\@namedef{@gobblespace} {} -\protected\def\ifnot@nil#1{% +\new@def\cptalloftwo#1#2{#1#2} +\new@def*\cptrmstop{0 } +\ifcsdefinable\cptrm{\let\cptrm\romannumeral} +\new@def\cpt@car#1#2\car@nil{#1} +\new@def\cpt@cdr#1#2\cdr@nil{#2} +\ifcsdefinable\cpt@relax{\let\cpt@relax\relax} +\new@def\cpt@gobbletorelax#1\cpt@relax{} +\new@def\cpt@gobbletorelax@fi@endgroup\fi#1\cpt@relax{\fi\endgroup} +\new@def\cpt@removetonnil#1\cpt@nnil{} +\new@def\cpt@catchtonnil#1\cpt@nnil{#1} +\new@def\cpt@removetodot#1.{} +\new@def\cpt@catchtodot#1.{#1} +\new@def\cpt@removetospace#1 {} +\ifcsdefinable\csvbreak{\let\csvbreak\relax} +\new@def*\cpt@csvbreak{\csvbreak} +\ifcsdefinable\csvpause{\let\csvpause\relax} +\new@def*\cpt@csvpause{\csvpause} +\ifcsdefinable\tsvbreak{\let\tsvbreak\relax} +\new@def*\cpt@tsvbreak{\tsvbreak} +\new@def*\ifcsvbreakTF#1{% \edef\reserved@a{\unexpanded{#1}}% - \ifxTF\reserved@a\@nnil\@gobble\@iden + \ifcseqTF\reserved@a\cpt@csvbreak } -\newcommand*\ifsentinelTF[1]{% - \edef\reserved@a{\unexpanded{#1}}% - \ifxTF\reserved@a\currsentinel -} -\if@@definable\csvbreak{\let\csvbreak\relax} -\newcommand*\cpt@csvbreak{\csvbreak} -\if@@definable\csvpause{\let\csvpause=\relax} -\newcommand*\cpt@csvpause{\csvpause} -\if@@definable\tsvbreak{\let\tsvbreak\relax} -\newcommand*\cpt@tsvbreak{\tsvbreak} -\newcommand*\ifcsvbreakTF[1]{% - \edef\reserved@a{\unexpanded{#1}}% - \ifxTF\reserved@a\cpt@csvbreak -} -\if@@definable\cptdoremainder{\let\cptdoremainder\@gobble} -\shelldef*\gobble@to@sentinel#1#2{% +\ifcsdefinable\cptdoremainder{\let\cptdoremainder\@gobble} +\robust@def*\gobble@to@sentinel#1#2{% \defpass\reserved@a##1#1#2{\cptdoremainder{##1}}% } -\newcommand*\cptthreexp{\expandafter\expandafter\expandafter} -\newcommand*\cptsevenxp{% +\new@def*\cptthreexp{\expandafter\expandafter\expandafter} +\new@def*\cptsevenxp{% \expandafter\expandafter\expandafter \expandafter\expandafter\expandafter\expandafter } -\shelldef\cptlocalxp#1{\begingroup\cptthreexp\endgroup#1} -\newcommand*\cptzapspaces[1]{% +\robust@def\cptlocalxp#1{\begingroup\cptthreexp\endgroup#1} +\new@def*\cptzapspaces#1{% \def\cptzapspaces##1{\romannumeral\cpt@zapspaces.##1#1\zap@nil}% } \cptzapspaces{ } \long\def\cpt@zapspaces#1 #2\zap@nil{% - \iflacus{#2}{% + \ifblankTF{#2}{% \expandafter\cptrmstop\@gobble#1% }{% \expandafter\cpt@zapspaces\expandafter.\@gobble#1#2\zap@nil }% } -\newcommand*\cptsupergobble[1]{% - \romannumeral-`\q\expandafter\@gobble\romannumeral-`\q - \expandafter\cpt@supergobble - \romannumeral\the\numexpr#1000{m\endcsname}% -} -\newcommand*\cpt@supergobble[1]{% - \csname cpt@superg@bble#1\cpt@supergobble -} -\newcommand\cpt@superg@bblem[1]{\endcsname} -\newcommand*\cptdotimes[1]{% +\new@def*\cptdotimes#1{% \ifblankTF{#1}{% \ifboolTF{cpt@useempty}{\cpt@dotimes{m}}\@gobble }{% @@ -962,7 +1034,7 @@ {\romannumeral\number#1000}% }% } -\newcommand*\cpt@dotimes[2]{% +\new@def*\cpt@dotimes#1#2{% \ifnullTF{#1}{}{% #2\relax \expandafter\ifnullTF\expandafter{\@gobble#1}{}{% @@ -970,80 +1042,72 @@ }% }% } -\newcommand*\cptexpandtimes[1]{% +\new@def*\cptexpandtimes#1{% \expandafter\cpt@expandtimes\expandafter {\romannumeral\number#1000}% } -\newcommand*\cpt@expandtimes[2]{% +\new@def*\cpt@expandtimes#1#2{% \ifnullTF{#1}{% \unexpanded{#2}% }{% \expandafter\ifnullTF\expandafter{\@gobble#1}{% \unexpanded\expandafter{#2}% }{% - \expandafter\cptswapfirstbraced\expandafter{#2}% + \expandafter\cptswapbracefirst\expandafter{#2}% {\expandafter\cpt@expandtimes\expandafter{\@gobble#1}}% }% }% } -\newcommand*\normal@reverse[1]{\cpt@normalreverse{}#1\@nnil} +\new@def*\normal@reverse#1{\cpt@normalreverse{}#1\@nnil} \long\def\cpt@normalreverse#1#2{% - \ifxTF#2\@nnil{% + \expandafter\ifxTF\cpt@car#2\car@nil\@nnil{% \ifboolTF{@test}\@iden\unexpanded{#1}% }{% \cpt@normalreverse{#2#1}% }% } -\newcommand*\robust@reverse[1]{\cpt@robustreverse{}.#1\@nnil} +\new@def*\robust@reverse#1{\cpt@robustreverse{}.#1\@nnil} \long\def\cpt@robustreverse#1#2\@nnil{% \cpt@r@bustreverse{#1}% {\simpleexpandarg\ifbracedTF{\@gobble#2}}#2\@nnil } \long\def\cpt@r@bustreverse#1#2.#3{% - \ifxTF#3\@nnil{% + \expandafter\ifxTF\cpt@car#3\car@nil\@nnil{% \ifboolTF{@test}\@iden\unexpanded{#1}% }{% #2{\cpt@robustreverse{{#3}#1}}{\cpt@robustreverse{#3#1}}.% }% } -\newcommand*\ifstrcmpTF[2]{% - \usename{@\ifnum\pdfstrcmp{\detokenize{#1}}% - {\detokenize{#2}}=0first\else second\fi oftwo}% -} -\shelldef*\ifcommandsdefinable#1{% +\robust@def*\ifcommandsdefinable#1{% \@testopt{\cpt@ifcmdsdefinable#1}\relax } \def\cpt@ifcmdsdefinable#1[#2]{% + \edef\reserved@e{\unexpanded{#2}}% \begingroup - \edef\reserved@a{\cptcommanormalize{#1}}% \@tempswafalse - \def\do##1,{% - \ifnot@nil{##1}{% - \if\expandafter\@car\string##1x\@nil\@backslashchar - \@tempswafalse - \if@@definable##1\@tempswatrue - \else - \cpt@notescapederr{##1}% - \fi - \usename{@\if@tempswa first\else second\fi oftwo}% - \do{\gobble@to@sentinel\@nil,}% - }% + \cptfor #1\dofor{% + \if\expandafter\@car\string##1x\@nil\@backslashchar + \@tempswafalse + \ifcsdefinable##1\@tempswatrue + \else + \cpt@notescapederr{##1}% + \fi + \if@tempswa\else\loopbreak\fi }% - \expandafter\do\reserved@a,\@nil,% - \ifcondTF\if@tempswa\fi{\endgroup#2}\endgroup + \if@tempswa + \aftergroup\reserved@e + \fi + \endgroup } \ifcommandsdefinable{\cpttrimspace,\cpttrimspaces}\relax \long\def\cpttrimspaces#1{\cpt@trimspaces@a\relax{#1}} -\long\def\cpt@trimspaces@strcmp#1#2{% - \csname @\ifnum\pdfstrcmp{\detokenize{#1}}% - {\detokenize{#2}}=0first\else second\fi oftwo\endcsname -} + \begingroup \catcode`\&=7\catcode`\$=7 \long\gdef\cpt@trimspaces@a#1#2{\cpt@trimspaces@b.#1$.#2& &} \long\gdef\cpt@trimspaces@b#1$#2 &{\cpt@trimspaces@c#1$#2&} \long\gdef\cpt@trimspaces@c#1$#2{% - \cpt@trimspaces@d\cpt@trimspaces@strcmp{#2}{#1}{% + \cpt@trimspaces@d\ifstrcmpTF{#2}{#1}{% \unexpanded\expandafter{\@gobble#1}% }{% \cpt@trimspaces@d\cpt@trimspaces@a{#2}{#2}% @@ -1065,14 +1129,13 @@ {\romannumeral-`\q\expandafter\noexpand\@gobble#1}% } \endgroup -\shelldef\trim@@spaces#1#2{\edef#2{\cpttrimspaces{#1}}} -\shelldef\trim@@space#1#2{\edef#2{\cpttrimspace{#1}}} - -\shelldef*\despacecontent#1{% +\robust@def\trim@@spaces#1#2{\edef#2{\cpttrimspaces{#1}}} +\robust@def\trim@@space#1#2{\edef#2{\cpttrimspace{#1}}} +\robust@def*\despacecontent#1{% \edef#1{\simpleexpandarg\cpttrimspaces{#1}}% } -\shelldef*\cptdespacecsvlist{\cpt@teststopt\cpt@despacecsvlist,} -\shelldef*\cpt@despacecsvlist[#1]#2{% +\robust@def*\cptdespacecsvlist{\cpt@teststopt\cpt@despacecsvlist,} +\robust@def*\cpt@despacecsvlist[#1]#2{% \cpt@stchoose{cpt@st}{#2}\cpt@tempa\cpt@despacecsvlist \ifcsnullTF\cpt@tempa{}{% \def\cpt@rsvda{}% @@ -1085,20 +1148,23 @@ \ifdefboolFT{cpt@st}{}{\let#2=\cpt@rsvda}% }% } -\shelldef*\newvariables#1{\@testopt{\cpt@newvariables{#1}}{}} -\if@@definable\newvariable{\let\newvariable\newvariables} -\shelldef*\cpt@newvariables#1[#2]#3{% - \@testopt{\cpt@newv@riables{#1}{#2}{#3}}{}% +\robust@def*\newvariables#1{\cpt@testopt{\cpt@newvariables{#1}}{}} +\ifcsdefinable\newvariable{\let\newvariable\newvariables} +\robust@def*\cpt@newvariables#1[#2]#3{% + \edef\reserved@a{\cpt@testopt{% + \cpt@newv@riables{\cpttrimspace{#1}}{\cpttrimspace{#2}}{#3}% + }{}}% + \reserved@a } -\shelldef*\cpt@newv@riables#1#2#3[#4]{% +\robust@def*\cpt@newv@riables#1#2#3[#4]{% \def\cpt@rsvda##1{% - \iflacus{#4}{\def\cpt@tempc{##1}}{\def\cpt@tempc{#4}}% + \ifblankTF{#4}{\def\cpt@tempc{##1}}{\def\cpt@tempc{#4}}% }% \edef\cpt@tempb{\ifstrcmpTF{#1}{if}{if}{}}% - \docommalist{#3}{% - \iflacus{##1}\gobble@to@relax\relax + \cptfor#3\dofor{% + \ifblankTF{##1}\cpt@gobbletorelax\relax \ifnamedefTF{\cpt@tempb#2##1}{% - \edef\reserved@a{\cpt@tempb#2##1}% + \edef\undefinablecs{\cpt@tempb#2##1}% \ifstrcmpTF{#1}{tog}{}{\cpt@notdefinable}% }{% \ifstrcmpTF{#1}{tog}{% @@ -1113,7 +1179,7 @@ \ifstrcmpTF{#4}{false}{% \let\cpt@togstate\@secondoftwo }{% - \iflacus{#4}{% + \ifblankTF{#4}{% \let\cpt@togstate\@secondoftwo }{% \@latex@error{Invalid toggle value '#4'}\@ehc @@ -1134,7 +1200,7 @@ \ifstrcmpTF{#4}{false}{% \def\reserved@a{01}% }{% - \iflacus{#4}{% + \ifblankTF{#4}{% \def\reserved@a{01}% }{% \@latex@error{Invalid switch value '#4'}\@ehc @@ -1155,23 +1221,25 @@ \cpt@rsvda{}% \csname#2##1\endcsname\expandafter{\cpt@tempc}% }{% - % It is dangerous to initialize boxes. - % Horizontal and vertical boxes aren't compatible: + % It is dangerous to initialize boxes here: + % horizontal and vertical boxes are incompatible. \ifstrcmpTF{#1}{box}{}{% \ifstrcmpTF{#1}{count}{% \cpt@rsvda\z@pt - \csname#2##1\endcsname\cpt@tempc\relax + \csname#2##1\endcsname=\cpt@tempc\relax }{% \ifstrcmpTF{#1}{dimen}{% \cpt@rsvda\z@pt - \csname#2##1\endcsname\cpt@tempc\relax + \csname#2##1\endcsname=\cpt@tempc\relax }{% \ifstrcmpTF{#1}{skip}{% \cpt@rsvda{\z@pt plus \z@pt minus \z@pt}% - \csname#2##1\endcsname\cpt@tempc\relax + \csname#2##1\endcsname=\cpt@tempc\relax }{% \ifstrcmpTF{#1}{write}{}{% - \cpt@newvarerr{#1}% + \ifstrcmpTF{#1}{read}{}{% + \cpt@unknownnewvar{#1}% + }% }% }% }% @@ -1185,7 +1253,7 @@ \cpt@relax }% } -\def\cpt@newvarerr#1{% +\def\cpt@unknownnewvar#1{% \if@tempswa\else \begingroup \def\x##1{Maybe you meant '##1'.}% @@ -1205,14 +1273,13 @@ \endgroup \fi } -\newvariables{if}[cpt@]{verbose,usepox,optfd,% - igopt,inpox,olddx,in,check,choicefd,useempty,swa% -}[false] +\newvariables{if}[cpt@]{usepox,optfd,igopt,inpox,olddx, + in,check,choicefd,useempty,swa}[false] \newvariables{tog}{biboolopts}[false] -\newvariables{count}[cpt@]{optdepth,grouplevel,grouptype,cnta}[\z@pt] -\newcommand*\UseEmptyEntry{\global\cpt@useemptytrue} -\newcommand*\DiscardEmptyEntry{\global\cpt@useemptyfalse} -\newcommand*\cptgetcatcode[1]{% +\newvariables{count}[cpt@]{optdepth,cnta}[\z@pt] +\new@def*\UseEmptyEntry{\global\cpt@useemptytrue} +\new@def*\DiscardEmptyEntry{\global\cpt@useemptyfalse} +\new@def*\cptgetcatcode#1{% \number \ifcat\noexpand#1\bgroup1\else \ifcat\noexpand#1\egroup2\else @@ -1227,70 +1294,26 @@ \ifcat\noexpand#1\noexpand~13\else -1\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi } -\newcommand*\cptcountspacesincs{% - \begingroup - \catcode\endlinechar=12 - \cpt@countspacesincs -} -\def\cpt@countspacesincs#1{% - \lccode`\ `\^^S\relax - \catcode\endlinechar=9 - \scantokens{\cpt@c@untspacesincs{#1}{ignoring}}% - \catcode\endlinechar=10 - \scantokens{\cpt@c@untspacesincs{#1}{counting}}% - \endgroup -} -\def\cpt@c@untspacesincs#1#2{% - \@tempcnta\z@pt - \toks@{##1}% - \lowercase{% - \toks1\expandafter{\detokenize{ }}% - \expandafter\def\expandafter\cpt@tempa\the - \expandafter\toks@\the\toks1##2\@nil{% - \ifblankTF{##2}{}{% - \advance\@tempcnta\@ne - \cpt@tempa##2\@nil - }% - }% - \expandafter\cpt@tempa\detokenize{#1 }\@nil - }% - \typeout{^^J\unexpanded{#1}}% - \typeout{Number of spaces, - #2 end-of-line characters: \the\@tempcnta.}% -} -\newcommand\ifnullTF[1]{% - \usename{@\ifnum\pdfstrcmp{}{\detokenize{#1}}% - =\z@pt first\else second\fi oftwo}% -} -\newcommand\ifnullFT[1]{\ifnullTF{#1}\@secondoftwo\@firstoftwo} -\newcommand\oifnullTF[1]{\expandafter\ifnullTF\expandafter{#1}} -\newcommand\oifnullFT[1]{\expandafter\ifnullFT\expandafter{#1}} -\newcommand\xifnullTF[1]{\cptexpandarg\ifnullTF{#1}} -\newcommand\xifnullFT[1]{\cptexpandarg\ifnullFT{#1}} -\newcommand\ifblankTF[1]{% - \usename{@\ifnum\pdfstrcmp{}{\detokenize\expandafter - {\@gobble#1.}}=\z@pt first\else second\fi oftwo}% -} -\newcommand\ifblankFT[1]{\ifblankTF{#1}\@secondoftwo\@firstoftwo} -\newcommand\oifblankTF[1]{\expandafter\ifblankTF\expandafter{#1}} -\newcommand\oifblankFT[1]{\expandafter\ifblankFT\expandafter{#1}} -\newcommand\xifblankTF[1]{% - \usename{@\ifnum\pdfstrcmp{}{\@gobble#1.}=\z@pt - first\else second\fi oftwo}% -} -\newcommand\xifblankFT[1]{\xifblankTF{#1}\@secondoftwo\@firstoftwo} -\newcommand*\ifdefTF[1]{% +\new@def\oifnullTF#1{\expandafter\ifnullTF\expandafter{#1}} +\new@def\oifnullFT#1{\expandafter\ifnullFT\expandafter{#1}} +\new@def\xifnullTF#1{\cptexpandarg\ifnullTF{#1}} +\new@def\xifnullFT#1{\cptexpandarg\ifnullFT{#1}} +\new@def\oifblankTF#1{\expandafter\ifblankTF\expandafter{#1}} +\new@def\oifblankFT#1{\expandafter\ifblankFT\expandafter{#1}} +\new@def\xifblankTF#1{\cptexpandarg\ifblankTF{#1}} +\new@def\xifblankFT#1{\xifblankTF{#1}\iiofii\iofii} +\new@def*\ifdefTF#1{% \ifblankTF{#1}\@secondoftwo{% \usename{@\ifx#1\cpt@undefined second\else \ifx#1\relax second\else first\fi\fi oftwo}% }% } -\newcommand*\ifdefFT[1]{\ifdefTF{#1}\@secondoftwo\@firstoftwo} -\newcommand*\oifdefTF[1]{\expandafter\ifdefTF\expandafter{#1}} -\newcommand*\oifdefFT[1]{\expandafter\ifdefFT\expandafter{#1}} -\newcommand*\xifdefTF[1]{\cptexpandarg\ifdefTF{#1}} -\newcommand*\xifdefFT[1]{\cptexpandarg\ifdefFT{#1}} -\newcommand*\ifcsndefTF[1]{% +\new@def*\ifdefFT#1{\ifdefTF{#1}\iiofii\iofii} +\new@def*\oifdefTF#1{\expandafter\ifdefTF\expandafter{#1}} +\new@def*\oifdefFT#1{\expandafter\ifdefFT\expandafter{#1}} +\new@def*\xifdefTF#1{\cptexpandarg\ifdefTF{#1}} +\new@def*\xifdefFT#1{\cptexpandarg\ifdefFT{#1}} +\new@def*\ifcsndefTF#1{% \ifblankTF{#1}\@gobble{% \ifcsname#1\endcsname \expandafter\@firstofone @@ -1301,98 +1324,48 @@ \aftercsname\ifdefTF{#1}% }% } -\newcommand*\ifcsndefFT[1]{\ifcsndefTF{#1}\@secondoftwo\@firstoftwo} -\newcommand*\oifcsndefTF[1]{\expandafter\ifcsndefTF\expandafter{#1}} -\newcommand*\oifcsndefFT[1]{\expandafter\ifcsndefFT\expandafter{#1}} -\newcommand*\xifcsndefTF[1]{\cptexpandarg\ifcsndefTF{#1}} -\newcommand*\xifcsndefFT[1]{\cptexpandarg\ifcsndefFT{#1}} -\shelldef*\ifcsdefinable#1#2{% +\new@def*\ifcsndefFT#1{\ifcsndefTF{#1}\iiofii\iofii} +\new@def*\oifcsndefTF#1{\expandafter\ifcsndefTF\expandafter{#1}} +\new@def*\oifcsndefFT#1{\expandafter\ifcsndefFT\expandafter{#1}} +\new@def*\xifcsndefTF#1{\cptexpandarg\ifcsndefTF{#1}} +\new@def*\xifcsndefFT#1{\cptexpandarg\ifcsndefFT{#1}} +\robust@redef*\ifcsdefinable#1#2{% \ifblankTF{#1}{% \cpt@isblankerr\ifcsdefinable }{% - \edef\reserved@a{\cptgobblescape#1}% + \edef\undefinablecs{\cptgobblescape#1}% \ifdefTF{#1}\cpt@notdefinable{% - \ifcsndefTF{end\reserved@a}\cpt@notdefinable{#2}% + \ifcsndefTF{end\undefinablecs}\cpt@notdefinable{#2}% }% }% } \ifcsdefinable\@ifcsdefinable{\let\@ifcsdefinable\ifcsdefinable} -\shelldef\rc@ifcsdefinable#1#2{\let\ifcsdefinable\@ifcsdefinable#2} -\shelldef*\ifcsndefinable#1{\cptlocalxp\aftercsname\ifcsdefinable{#1}} -\shelldef*\ifdefinableTF#1{% +\robust@def\rc@ifcsdefinable#1#2{\let\ifcsdefinable\@ifcsdefinable#2} +\robust@def*\ifcsndefinable#1{\cptlocalxp\aftercsname\ifcsdefinable{#1}} +\robust@def*\ifdefinableTF#1{% \ifblankTF{#1}{% \cpt@isblankerr\ifdefinableTF \@secondoftwo }{% \ifdefTF{#1}\@secondoftwo{% - \ifcsndefTF{end\cptgobblescape#1}\@secondoftwo\@firstoftwo + \ifcsndefTF{end\cptgobblescape#1}\iiofii\iofii }% }% } -\shelldef\cpt@def@#1#2#3{% - \ifcsdefinable#3{% - \ifnullTF{#2}{}\protected - \cptthreexp\l@ngrel@x\usename{#1def}#3% - }% -} -\ifcsdefinable\robust@def\relax -\shelldef\robust@def{\cpt@starorlong{\cpt@def@{}{p}}} -\robust@def*\new@def{\cpt@starorlong{\cpt@def@{}{}}} -\robust@def*\new@gdef{\cpt@starorlong{\cpt@def@{g}{}}} -\robust@def*\robust@gdef{\cpt@starorlong{\cpt@def@{g}{p}}} -\robust@def*\new@edef{\cpt@starorlong{\cpt@def@{e}{}}} -\robust@def*\robust@edef{\cpt@starorlong{\cpt@def@{e}{p}}} -\robust@def*\new@xdef{\cpt@starorlong{\cpt@def@{x}{}}} -\robust@def*\robust@xdef{\cpt@starorlong{\cpt@def@{x}{p}}} -\robust@def*\renew@def{\cpt@starorlong{\cpt@redef@{}}} -\robust@def*\robust@redef{\cpt@starorlong{\cpt@redef@{p}}} -\new@def*\cpt@redef@#1#2{% - \ifdefFT#2{}{% - \ifcpt@verbose - \@latex@info{Command '\string#2' redefined}% - \fi - }% - \ifstrcmpTF{#1}{p}\protected\relax\l@ngrel@x\def#2% -} -\robust@def*\provide@def{% - \cpt@cmdsuffixcheck{% - \cpt@testst{\cpt@testcl{\cpt@providedef\relax}}% - }% -} -\robust@def*\providerobust@def{% - \cpt@cmdsuffixcheck{% - \cpt@testst{\cpt@testcl{\cpt@providedef\protected}}% - }% -} -\new@def\cpt@providedef#1#2{% - \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% - \ifdefTF#2{% - \ifcpt@verbose - \cpt@info{Command '\string#2' already defined: - \MsgBrk not redefined}% - \fi - \def\reserved@a{\undefcs\reserved@b}% - }{% - \def\reserved@a{% - \ifcpt@cl\global\fi\let#2\reserved@b - \undefcs\reserved@b - }% - }% - \afterassignment\reserved@a - \ifcpt@st\else\long\fi - #1\def\reserved@b -} -\robust@def*\ltx@warn{\@latex@warning@no@line} -\robust@def*\ltx@info{\@latex@info@no@line} -\robust@def*\ltx@err{\@latex@error} -\robust@def\cpt@testopt#1#2{\ifnextcharTF[{#1}{#1[{#2}]}} -\robust@def*\cpt@ifbrack#1#2{\ifnextcharTF[{#1}{#2}} +\robust@def*\ltxmsg@warn{\@latex@warning@no@line} +\robust@def*\ltxmsg@info{\@latex@info@no@line} +\robust@def*\ltxmsg@err{\@latex@error} +\robust@redef\cpt@testopt#1#2{\ifnextcharTF[{#1}{#1[{#2}]}} +\robust@def*\cpt@testcharopt#1#2#3#4{\ifnextcharTF#2{#1}{#1#2{#3}#4}} \new@def*\cpt@xtestopt#1#2#3{% \cpt@xifbrack#1\\[\\{#2#1}{#2[{#3}]{#1}}% } \new@def*\cpt@xifbrack#1[#2\\#3#{% - \usename{@\ifblankTF{#1#2}{first}{second}oftwo}% + \ifcat$\detokenize{#1#2}$\expandafter\@firstoftwo + \else\expandafter\@secondoftwo\fi } + +\robust@def*\cpt@ifbrack#1#2{\ifnextcharTF[{#1}{#2}} \robust@def\cpt@testpnopt#1#2{\ifnextcharTF({#1}{#1({#2})}} \robust@def\cpt@testltopt#1#2{\ifnextcharTF<{#1}{#1<{#2}>}} \robust@def\cpt@ifplus#1{\ifnextcharTF+{\@firstoftwo{#1}}} @@ -1406,16 +1379,6 @@ \robust@def\cpt@teststpl#1{\cpt@testst{\cpt@testpl{#1}}} \robust@def\cpt@teststpm#1{\cpt@testst{\cpt@testpm{#1}}} \robust@def\cpt@teststopt#1#2{\cpt@testst{\cpt@testopt{#1}{#2}}} -\robust@def*\cptmaybedef{\cpt@teststpm\cpt@maybedef} -\robust@def*\cpt@maybedef#1{% - \ifboolTF{cpt@st}\@firstoftwo{% - \ifboolTF{cpt@pm}\@firstoftwo\@secondoftwo - }{% - \@gobble - }{% - \new@def#1% - }% -} \robust@def*\newletcs#1{% \begingroup \def\cpt@tempa{\relax}% @@ -1465,16 +1428,18 @@ \cpt@notonetokenerr{#1}% }% } -\robust@def*\cptletcsset#1#2{% - \docommalist{#1}{% - \oifblankTF{\@gobble##1}{}{\fulllet##1#2}% - }% +\robust@def*\fullletmanytocs#1#2{% + \cptfor#1\dofor{\fulllet{##1}{#2}}% } +\robust@def*\begintoksgroup{\begingroup\toks@{}} +\robust@def*\endtoksgroup{\expandafter\endgroup\the\toks@} \begingroup \catcode`\&=7 \new@gdef*\ifcounterTF#1{% - \ifstrcmpTF\count{#1}\@secondoftwo{% + \ifcseqTF#1\count{% + \@secondoftwo + }{% \expandafter\cpt@ifcounter@a\meaning#1:&% }% } @@ -1484,7 +1449,9 @@ } \cpt@ifcounter@a\cpt@ifcounter@a\cpt@ifcounter@b \new@gdef*\ifdimenTF#1{% - \ifstrcmpTF\dimen{#1}\@secondoftwo{% + \ifcseqTF#1\dimen{% + \@secondoftwo + }{% \expandafter\cpt@ifdimen@a\meaning#1:&% }% } @@ -1504,7 +1471,7 @@ \xdef#1{\the\numexpr#1+1}% }% }{% - \chardef#1=\@ne + \gdef#1{\@ne}% }% }{% \cpt@notonetokenerr{#1}% @@ -1535,8 +1502,10 @@ \edef\cpt@stack{\cptremovescape{#1}@stack}% \ifcsndefTF\cpt@stack{}{\csn@gdef\cpt@stack{}}% \toks@{}\toks1{}\escapechar92\relax + % Using \csv@@loop or \csv@@parse here will bomb out, + % because \pushfunctions is called within those loops: \let\xp\expandcsonce - \def\push@do##1{% + \cptfor#2\dofor{% \ifescapedTF{##1}{}{\cpt@notescapederr{##1}}% \edef\cpt@tempa{\noexpandcsn{\cptremovescape{##1}@\cptrm#3}}% \cptpassexpanded{% @@ -1545,17 +1514,9 @@ \undefcs\xp\cpt@tempa}% }% }% - \cptpushparse{#2}% \csn@xdef\cpt@stack{\the\toks1\cpt@nil{\expandcsnonce\cpt@stack}}% \expandafter\endgroup\the\toks@ } -\robust@def*\cptpushparse#1{% - \edef\reserved@a{\cptcommanormalize{#1}}% - \expandafter\cpt@pushparse\reserved@a,\@nil,% -} -\robust@def*\cpt@pushparse#1,{% - \ifnot@nil{#1}{\push@do{#1}\relax\cpt@pushparse}% -} \robust@def*\popfunctions#1#2{% \ifdefTF{#2}{% \ifnum#2=\z@pt @@ -1576,7 +1537,7 @@ }% \popnumber{#2}% } -\chardef\cpt@optionstacklimit=4 +\cptchardef\cpt@optionstacklimit=4 \robust@def*\cpt@pushstate#1#2#3{% \ifnum#3>\cpt@optionstacklimit\relax \let\x\cpt@optionstacklimit @@ -1588,7 +1549,7 @@ \MsgBrk\noexpand\documentclass }\@ehc \fi - \expandafter\pushfunctions\expandafter#1\expandafter{#2}{#3}% + \cptexpandargonce{\pushfunctions#1}{#2}{#3}% } \robust@def*\cpt@popstate#1#2{\popfunctions{#1}{#2}} \robust@def*\cpt@stchoose#1#2#3#4{% @@ -1620,7 +1581,7 @@ \cpt@tempb{}% \cpteveryscan \scantokens\expandafter{\cpt@tempa}\relax - \ifxTF#1\cpt@tempa{% + \ifcseqTF#1\cpt@tempa{% \cpt@tempb{#2}% \scantokens\expandafter{\cpt@tempa}\relax }{% @@ -1631,9 +1592,9 @@ \endgroup } \robust@def*\dofunclist{% - \pushnumber\dofunclistnr + \pushnumber\dofunclistdepth \begingroup - \edef\sav@do{\cptmakecs{sav@do@\cptrm\dofunclistnr}}% + \edef\sav@do{\cptmakecs{sav@do@\cptrm\dofunclistdepth}}% \expandafter\let\sav@do\do \expandafter\cpt@delimitcs\sav@do\cpt@nil \toks@{\def\csv@do##1}% @@ -1643,51 +1604,39 @@ \the\expandafter\toks@\expandafter{\the\toks1}% \csv@@parse } -\robust@def*\csv@@loop{% - \let\cpt@nmlz\cptswfalse - \let\cpt@inkv\cptswfalse - \cpt@teststopt\cpt@csvkvparse,% -} -\robust@def*\csv@@parse{% - \let\cpt@nmlz\cptswtrue - \let\cpt@inkv\cptswfalse - \cpt@teststopt\cpt@csvkvparse,% -} -\robust@def*\kv@@loop{% - \let\cpt@nmlz\cptswfalse - \let\cpt@inkv\cptswtrue - \cpt@teststopt\cpt@csvkvparse,% -} -\robust@def*\kv@@parse{% - \let\cpt@nmlz\cptswtrue - \let\cpt@inkv\cptswtrue - \cpt@teststopt\cpt@csvkvparse,% +\robust@def*\docommalist#1#2{\def\csv@do##1{#2}\csv@@parse{#1}} +\robust@def*\csv@@loop{\cpt@csvkvparse{01}{01}} +\robust@def*\csv@@parse{\cpt@csvkvparse{00}{01}} +\robust@def*\kv@@loop{\cpt@csvkvparse{01}{00}} +\robust@def*\kv@@parse{\cpt@csvkvparse{00}{00}} +\new@def*\cpt@csvkvparse#1#2{% + \def\cpt@nmlz{#1}\def\cpt@inkv{#2}% + \cpt@teststopt\cpt@csvkvp@rse,% } \new@def*\cpt@csvnil{\cpt@csvnil} -\newcommand*\cpt@csvkvparse[2][,]{% +\newcommand*\cpt@csvkvp@rse[2][,]{% \cpt@stchoose{cpt@st}{#2}\cpt@csvarg\cpt@csvkvparse - \pushfunctions\cpt@csvkvparse{\cpt@csvdo@a,\cpt@csvdo,% - \sav@csv@do,\ifcpt@useempty,\ifloopbreak,% - \cptdoremainder}\cpt@csvdepth + \pushfunctions\cpt@csvkvparse{\cpt@csvdo@a,\cpt@csvdo@b,\sav@csv@do,% + \cpt@loopcbk,\ifcpt@useempty,\ifloopbreak,\cptdoremainder}\cpt@csvdepth \letcstocsn\sav@csv@do{\if\cpt@inkv kv\else csv\fi @do}% \ifdefTF\sav@csv@do{}{% \cpt@err{'\string\csv@do' or '\string\kv@do' undefined}\@ehc }% \def\cpt@csvdo@a{% \ifboolTF{loopbreak}{% - \gobble@to@sentinel\cpt@csvnil#1% + \defpass\reserved@a####1\cpt@csvnil#1{\cptdoremainder{####1}}% }{% - \cpt@csvdo.% + \cpt@csvdo@b.% }% }% - \def\cpt@csvdo##1#1{% + \def\cpt@csvdo@b##1#1{% \edef\cpt@csvarg{\expandcsonce{\@gobble##1}}% - \ifxTF\cpt@csvarg\cpt@csvnil{}{% - \ifxTF\cpt@csvarg\cpt@csvbreak{% + \ifcseqTF\cpt@csvarg\cpt@csvnil{}{% + \ifcseqTF\cpt@csvarg\cpt@csvbreak{% \loopbreaktrue }{% \ifcsemptyTF\cpt@csvarg{% - \ifdefboolFT{cpt@useempty}{}{\sav@csv@do{}\relax}% + \ifboolFT{cpt@useempty}{}{\sav@csv@do{}\relax}% }{% \expandafter\sav@csv@do\expandafter{\cpt@csvarg}\relax }% @@ -1698,7 +1647,7 @@ \ifdefswitchFT{cpt@nmlz}{}{% \ifcsemptyTF\cpt@csvarg{}{% \cpt@sttrue - \usename{cpt@\ifdefswitchTF{cpt@inkv}{kv}{csv}normalize}% + \usename{cpt@\ifswitchTF{cpt@inkv}{kv}{csv}normalize}% [#1]\cpt@csvarg }% }% @@ -1706,17 +1655,18 @@ \expandafter\cpt@csvdo@a\cpt@csvarg#1\cpt@csvnil#1% \popfunctions\cpt@csvkvparse\cpt@csvdepth \ifnum\cpt@csvdepth=\z@pt - \let\cptdoremainder\@gobble - \undefcsset{\csv@do,\kv@do,\dofunclistnr}% + \cptfor\csv@do,\kv@do,\dofunclistdepth\dofor{\undefcs##1}% \fi } \robust@def\indris@nil#1\fi#2\indris@do#3\indris@nil{\fi#1#2} \newvariables{if}{lastindris}[false] -\robust@def*\indrisloop{\cpt@teststopt\cpt@indrisloop{,}} +\robust@def*\indrisloop{\cpt@teststopt\cpt@indrisloop,} \robust@def*\cpt@indrisloop[#1]#2#3{% - \pushfunctions\cpt@indrisloop - {\indris@do,\indrisnr,\iflastindris,% - \ifloopbreak,\user@do,\getnextindris}\indrisdepth + \pushfunctions\cpt@indrisloop{% + \indris@do,\indrisnr,\iflastindris,\ifloopbreak,% + \user@do,\getnextindris,\cptdoremainder + }\cpt@csvdepth + \pushnumber\indrisdepth \cpt@stchoose{cpt@st}{#2}\cpt@rsvda\indrisloop \cpt@sttrue\cpt@csvnormalize[#1]\cpt@rsvda \lastindrisfalse\loopbreakfalse @@ -1752,7 +1702,8 @@ \indris@do.##2\indris@nil }% \expandafter\indris@do\expandafter.\cpt@rsvda#1\indris@nil - \popfunctions\cpt@indrisloop\indrisdepth + \popfunctions\cpt@indrisloop\cpt@csvdepth + \popnumber\indrisdepth } \robust@def*\tsv@@loop{% \let\tsv@inparse\cptswfalse @@ -1775,13 +1726,12 @@ \expandafter\cpt@tsvparse@b\cpt@tsvarg\cpt@tsvnil \popfunctions\tsv@@parse\cpt@csvdepth \ifnum\cpt@csvdepth=\z@pt - \let\cptdoremainder\@gobble \undefcs\tsv@do \fi } \robust@def*\cpt@tsvparse@b{% \ifboolTF{loopbreak}{% - \gobble@to@sentinel\cpt@tsvnil{}% + \defpass\reserved@a##1\cpt@tsvnil{\cptdoremainder{##1}}% }{% \begingroup \let\bgr@up\bgroup @@ -1790,18 +1740,18 @@ }% } \robust@def\cpt@tsvparse@c#1{% - \ifxTF\@let@token\bgr@up{% + \ifcseqTF\@let@token\bgr@up{% \endgroup \edef\cpt@tsvarg{{\unexpanded{#1}}}% }{% \endgroup \edef\cpt@tsvarg{\usename{cpttrimspace\if\tsv@inparse s\fi}{#1}}% }% - \ifxTF\cpt@tsvarg\cpt@tsvnil{}{% - \ifxTF\cpt@tsvarg\cpt@tsvbreak{% + \ifcseqTF\cpt@tsvarg\cpt@tsvnil{}{% + \ifcseqTF\cpt@tsvarg\cpt@tsvbreak{% \loopbreak }{% - \ifxTF\@empty\cpt@tsvarg{% + \ifcsemptyTF\cpt@tsvarg{% \ifcpt@useempty\sav@tsv@do{}\relax\fi }{% \expandafter\sav@tsv@do\expandafter{\cpt@tsvarg}\relax @@ -1810,26 +1760,23 @@ \cpt@tsvparse@b }% } -% \tsv@@parse does preserve outer braces but sometimes this -% isn't required, necessitating a call to a brace stripper. -% \siso@@loop strips outer braces in its arguments and -% doesn't trim leading and trailing spaces, but can -% be nested to any level: \new@def*\cpt@sisonil{\cpt@sisonil} \robust@def*\siso@@loop#1{% - \pushfunctions\siso@@loop{\sav@siso@do,\ifloopbreak}\cpt@sisodepth + \pushfunctions\siso@@loop{\sav@siso@do,\ifloopbreak}\cpt@csvdepth \ifdefTF\siso@do{}{\cpt@notdeferr\siso@do}% \let\sav@siso@do\siso@do \loopbreakfalse \cpt@sisoloop#1\cpt@sisonil - \popfunctions\siso@@loop\cpt@sisodepth - \ifnum\cpt@sisodepth=\z@pt\undefcs\siso@do\fi + \popfunctions\siso@@loop\cpt@csvdepth + \ifnum\cpt@csvdepth=\z@pt\undefcs\siso@do\fi } \robust@def*\cpt@sisoloop#1{% \edef\siso@arg{\unexpanded{#1}}% - \ifxTF\siso@arg\cpt@sisonil{}{% + \ifcseqTF\siso@arg\cpt@sisonil{}{% \ifboolTF{loopbreak}{% - \gobble@to@sentinel\cpt@sisonil{}% + \defpass\reserved@a##1\cpt@sisonil{% + \cptdoremainder{##1}% + }% }{% \sav@siso@do{#1}\relax\cpt@sisoloop }% @@ -1848,32 +1795,38 @@ {\noexpandcsn{\cptgobblescape#2@\romannumeral\curr@level}}% } \new@def*\csliststack#1#2{% - \ifdefFT{#2}{}{% - \ifxTF#2\@empty{}{\expandcsonce{#2}#1}% - }% + \iflacus#2\dolacus\else + \expandafter\ifnullTF\expandafter{\iiofii#2{}}{% + \ifdefTF{#2}{% + \ifx#2\@empty\else\expandcsonce{#2}#1\fi + }{}% + }{% + \unexpanded{#2}#1% + }% + \fi } +\newletcs\cptliststack\csliststack \new@def*\csnliststack#1#2{% - \expandafter\ifdefFT\csname#2\endcsname{}{% - \expandafter\ifxTF\csname#2\endcsname\@empty{}% - {\expandafter\expandcsonce\csname#2\endcsname#1}% + \ifblankTF{#1}{% + \expandafter\csliststack\expandafter + {\expandafter}\csname#2\endcsname + }{% + \expandafter\csliststack\expandafter#1\csname#2\endcsname }% } -\new@def\cptafterfi#1\fi{\fi#1} -\new@def\cptafterelsefi#1\else#2\fi{\fi#1} -\new@def\cptafterfifi#1\fi#2\fi{\fi\fi#1} -\robust@def*\emptify#1{\let#1\@empty} -\robust@def*\gemptify#1{\global\let#1\@empty} +\robust@def*\cptemptify#1{\let#1\@empty} +\robust@def*\cptgemptify#1{\global\let#1\@empty} \robust@def*\genemptify{\cpt@teststcl\cpt@genemptify} \def\cpt@genemptify#1{% \ifcpt@cl\global\fi\ifcpt@st\else\long\fi\def#1{}% } -\robust@def*\emptifycsn{\aftercsname\emptify} -\robust@def*\gemptifycsn{\global\aftercsname\emptify} -\robust@def*\emptifycsset{% +\robust@def*\cptemptifycsn{\aftercsname\cptemptify} +\robust@def*\cptgemptifycsn{\global\aftercsname\cptemptify} +\robust@def*\cptemptifycsset{% \cpt@testst{\cpt@testcl\cpt@emptifycsset}% } \robust@def*\cpt@emptifycsset#1{% - \docommalist{#1}{% + \cptfor#1\dofor{% \ifsingletoken@sp@TF{##1}{% \ifescapedTF{##1}{% \ifcpt@cl\global\fi\def##1{}% @@ -1885,16 +1838,18 @@ }% }% } -\robust@def*\emptifycsnset{\cpt@testopt\cpt@emptifycsnset{}} +\robust@def*\cptemptifycsnset{\cpt@testopt\cpt@emptifycsnset{}} \robust@def*\cpt@emptifycsnset[#1]#2{% - \docommalist{#2}{\csn@def{#1##1}{}}% + \cptfor#2\dofor{\csn@def{#1##1}{}}% } \AtEndOfPackage{% \AfterStartOfDocument{% \def\do#1{% \ifcsnameTF{\cptgobblescape#1}{% - \gdef#1{\@latex@error{'\string#1' is a preamble command}% - {Move command '\string#1' to document preamble.}}% + \gdef#1{% + \@latex@error{'\string#1' is a preamble command} + {Move command '\string#1' to document preamble.}% + }% }{% \cpt@warn{Undefined command '\unexpanded{#1}': \MsgBrk appeared in \string\cptonlypreamble}% @@ -1935,17 +1890,15 @@ \robust@def*\cptelementcount{\cpt@teststopt\cpt@elemcount,} \robust@def*\cpt@elemcount[#1]#2{% \begingroup - \def\cpt@elemnr{0}% + \def\cptelemnr{0}% \edef\reserved@a{\ifcpt@st*\fi}% \def\csv@do##1{% - \edef\cpt@elemnr{\the\numexpr\cpt@elemnr+1}% + \edef\cptelemnr{\the\numexpr\cptelemnr+1}% }% \expandafter\csv@@loop\reserved@a[#1]{#2}% - \postgroupdef\cpt@elemnr\endgroup -} -\robust@def*\ifelemcountTF{% - \cpt@teststopt\cpt@ifelemcount@a,% + \postgroupdef\cptelemnr\endgroup } +\robust@def*\ifelemcountTF{\cpt@teststopt\cpt@ifelemcount@a,} \robust@def*\cpt@ifelemcount@a[#1]{% \cpt@testpnopt{\cpt@ifelemcount@b{#1}}=% } @@ -1983,16 +1936,17 @@ } \new@def*\ifcsnullTF#1{% \ifblankTF{#1}\@secondoftwo{% - \expandafter\ifblankTF\expandafter{\@gobble#1}{% - \ifxTF#1\@empty + \oifblankTF{\@gobble#1}{% + \ifcseqTF#1\@empty }{% \@secondoftwo }% }% } -\new@def*\ifcsnullFT#1{\ifcsnullTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifcsnullFT#1{\ifcsnullTF{#1}\iiofii\iofii} \new@def*\oifcsnullTF#1{\expandafter\ifcsnullTF\expandafter{#1}} \new@def*\oifcsnullFT#1{\expandafter\ifcsnullFT\expandafter{#1}} +\new@def\ifcsemptyTF#1{\ifcondTF\ifx#1\@empty\cpt@quark\fi} \new@def*\ifcsnnullTF#1{% \ifblankTF{#1}{% \@secondoftwo @@ -2009,22 +1963,22 @@ }% } \new@def*\ifcsnnullFT#1{% - \ifcsnnullTF{#1}\@secondoftwo\@firstoftwo + \ifcsnnullTF{#1}\iiofii\iofii } \new@def*\ifdefnotnullTF#1{% \ifdefTF{#1}{% - \ifcsnullTF{#1}\@secondoftwo\@firstoftwo - }\@secondoftwo + \ifcsnullTF{#1}\iiofii\iofii + }{% + \@secondoftwo + }% } \new@def*\ifcsndefnotnullTF#1{% \ifcsndefTF{#1}{% - \ifcsnnullTF{#1}\@secondoftwo\@firstoftwo - }\@secondoftwo + \ifcsnnullTF{#1}\iiofii\iofii + }{% + \@secondoftwo + }% } -%% For private use only: -\new@def*\simpleexpandarg#1#2{\expandafter#1\expandafter{#2}} -\newletcs\s@expandarg=\simpleexpandarg -%%-- \new@def*\expandcsonce#1{\unexpanded\expandafter{#1}} \new@def*\expandcsnonce#1{\aftercsname\expandcsonce{#1}} \new@def*\expandcstwice#1{\unexpanded\cptthreexp{#1}} @@ -2089,17 +2043,11 @@ \protected\def\cpt@tempb{\global\protected\@namedef}% \edef\cpt@tempc{\ifx\@currext\@pkgextension Package\else Class\fi}% \@tempswafalse - \def\do##1,{% - \ifnot@nil{##1}{% - \if@tempswa\else - \ifcsname#1##1\endcsname - \edef\reserved@a{#1##1}\@tempswatrue - \fi - \fi - \do - }% + \cptfor#2,#3,#4\dofor{% + \ifcsname#1##1\endcsname + \edef\undefinablecs{#1##1}\@tempswatrue\forbreaktrue + \fi }% - \do#2,#3,#4,\@nil,% \if@tempswa \cpt@notdefinable \else @@ -2116,23 +2064,6 @@ \interactionmode\thr@@ } \SetStyleFileMessages[cpt@]{info}{warn}{err} -\robust@def*\cptbegingroup{% - \begingroup - \cpt@grouplevel\currentgrouplevel - \cpt@grouptype\currentgrouptype -} -\robust@def*\cptendgroup{% - \ifnum\cpt@grouptype=\currentgrouptype - \ifnum\cpt@grouplevel=\currentgrouplevel\else - \cpt@err{There is a group level mismatch}\@ehc - \aftergroup\showgroups - \fi - \else - \cpt@err{There is a group type mismatch}\@ehc - \aftergroup\showgroups - \fi - \endgroup -} \new@def*\ifdefboolTF#1{% \ifblankTF{#1}{% \cpt@err{Empty boolean}\@ehc @@ -2144,15 +2075,15 @@ }% }% } -\new@def*\ifdefboolFT#1{\ifdefboolTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifdefboolFT#1{\ifdefboolTF{#1}\iiofii\iofii} \new@def*\ifboolTF#1{% \usename{@\usename{if#1}first\else second\fi oftwo}% } -\new@def*\ifboolFT#1{\ifboolTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifboolFT#1{\ifboolTF{#1}\iiofii\iofii} \new@def*\ifbooleanTF#1#{% \ifsingletokenTF{#1}{% \ifescapedTF{#1}{% - \ifdefboolTF{\cptremovescape#1}\@firstoftwo\@secondoftwo + \ifdefboolTF{\cptremovescape#1}\iofii\iiofii }{% \cpt@notescapederr }% @@ -2160,8 +2091,9 @@ \cpt@notonetokenerr{#1}% }% } -\new@def\cptiterate#1\repeat{\cpt@iterate\@gobble{#1}} +\new@def\cptiterate#1\cptrepeat{\cpt@iterate\@gobble{#1}} \newletcs\cptloop=\cptiterate +\newletcs\cptrepeat\fi \new@def\cpt@iterate\@gobble#1{% #1\relax\expandafter\cpt@iterate\fi\@gobble{#1}% } @@ -2179,51 +2111,50 @@ \new@def*\cpt@dimeq#1={#1=\dimexpr} \new@def*\cptwhilenum#1\do#2{% \ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% - \remove@to@nnil<=>\@nnil\relax#2\relax + \cpt@removetonnil<=>\cpt@nnil\relax#2\relax \cptswap{\cpt@whilenum{#1}{\relax#2\relax}}\fi } \new@def*\cpt@whilenum#1#2{% \ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% - \remove@to@nnil<=>\@nnil#2% + \cpt@removetonnil<=>\cpt@nnil#2% \expandafter\cpt@whilenum\else \expandafter\@gobbletwo\fi{#1}{#2}% } \new@def*\cptwhiledim#1\do#2{% \ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% - \remove@to@nnil<=>\@nnil\relax#2\relax + \cpt@removetonnil<=>\cpt@nnil\relax#2\relax \cptswap{\cpt@whiledim{#1}{\relax#2\relax}}\fi } \new@def*\cpt@whiledim#1#2{% \ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% - \remove@to@nnil<=>\@nnil#2% + \cpt@removetonnil<=>\cpt@nnil#2% \expandafter\cpt@whiledim\else \expandafter\@gobbletwo\fi{#1}{#2}% } \new@def*\ifnumcmpTF#1#{% \usename{@\ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% - \remove@to@nnil<=>\@nnil first\else second\fi oftwo}% + \cpt@removetonnil<=>\cpt@nnil first\else second\fi oftwo}% } \new@def*\ifnumcmpFT#1#{\usename{@\ifnumcmpTF#1{second}{first}oftwo}} -\new@def*\ifnumtestTF#1#2#3{% - \usename{@\ifnum\numexpr#1#2\numexpr#3 first\else second\fi oftwo}% -} \new@def*\ifdimcmpTF#1#{% \usename{@\ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% - \remove@to@nnil<=>\@nnil first\else second\fi oftwo}% + \cpt@removetonnil<=>\cpt@nnil first\else second\fi oftwo}% } \new@def*\ifdimcmpFT#1#{\usename{@\ifdimcmpTF#1{second}{first}oftwo}} \robust@def*\cpt@defcheck#1#2\cpt@nil{% \new@def*#1##1\cpt@nil{% \begingroup \def\cpt@tempa####1#2####2\cpt@nil{\endgroup - \@nameuse{@\ifblankTF{####2}{second}{first}oftwo}% + \usename{@\ifblankTF{####2}{second}{first}oftwo}% }% \cpt@tempa##1#2\cpt@nil }% } \cpt@defcheck\cpt@checkeq=\cpt@nil +%%-- + \robust@def*\cpt@defsplit@at#1#2\cpt@nil{% - \new@def*#1##1\cpt@nil{% + \def#1##1\cpt@nil{% \begingroup \def\cpt@tempa####1#2####2\cpt@nil{\endgroup \def\lpt{####1}\def\rpt{####2}% @@ -2236,43 +2167,139 @@ }% } \cpt@defsplit@at\cpt@split@ateq=\cpt@nil -\robust@def\DefSuffixChecker#1#2#3{% - \def#1##1##2##3{% - \begingroup - \toks@{}% + +\robust@def\DefSuffixChecker#1#2#3#4{% + \long\gdef#1##1##2##3##4{% + \begintoksgroup \def\cpt@tempa{% - \ifsingletokenTF{##2}{% - \ifsingletokenTF{##3}{% - \toks@{##1##2##3}% + \ifstrcmpTF{##4}{#2}{% + \ifstrcmpTF{##2##3}{#3#4}{% + \toks@{##1##4##2##3}% }{% - \toks@{##1##2{##3}}% + \ifstrcmpTF{##2##3}{#4#3}{% + \toks@{##1##4##3##2}% + }{% + \ifsingletokenTF{##2}{% + \ifsingletokenTF{##3}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2{##3}##4}% + }% + }{% + \ifsingletokenTF{##3}{% + \toks@{##1{##2}##3##4}% + }{% + \toks@{##1{##2}{##3}##4}% + }% + }% + }% }% }{% - \ifsingletokenTF{##3}{% - \toks@{##1{##2}##3}% + \cpt@tempb + }% + }% + \def\cpt@tempb{% + \ifstrcmpTF{##4}{#3}{% + \ifstrcmpTF{##2##3}{#2#4}{% + \toks@{##1##2##4##3}% }{% - \toks@{##1{##2}{##3}}% + \ifstrcmpTF{##2##3}{#4#2}{% + \toks@{##1##3##4##2}% + }{% + \toks@{##1##2##3##4}% + }% }% + }{% + \cpt@tempc }% }% - \defpass\cpt@tempb{% - \ifstrcmpTF{##2}{#2}{% - \cpt@tempa + \def\cpt@tempc{% + \ifstrcmpTF{##4}{#4}{% + \ifstrcmpTF{##2##3}{#2#3}{% + \toks@{##1##2##3##4}% + }{% + \ifstrcmpTF{##2##3}{#3#2}{% + \toks@{##1##3##2##4}% + }{% + \toks@{##1##2##3##4}% + }% + }% }{% + \cpt@tempd + }% + }% + \def\cpt@tempd{% + \ifstrcmpTF{##3}{#2}{% \ifstrcmpTF{##2}{#3}{% - \ifstrcmpTF{##3}{#2}{% - \toks@{##1##3##2}% + \ifsingletokenTF{##4}{% + \toks@{##1##3##2##4}% }{% - \cpt@tempa + \toks@{##1##3##2{##4}}% }% }{% - \cpt@tempa + \cpt@tempi }% + }{% + \cpt@tempe }% }% - \expandafter\endgroup\the\toks@ + \def\cpt@tempe{% + \ifstrcmpTF{##3}{#3}{% + \ifstrcmpTF{##2}{#2}{% + \ifsingletokenTF{##4}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2##3{##4}}% + }% + }{% + \cpt@tempi + }% + }{% + \cpt@tempf + }% + }% + \def\cpt@tempf{% + \ifsingletokenTF{##4}{\toks1{##4}}{\toks1{{##4}}}% + \cpt@tempg + }% + \def\cpt@tempg{% + \ifsingletokenTF{##3}{% + \ifsingletokenTF{##2}{% + \cpt@temph{##1##2##3}% + }{% + \cpt@temph{##1{##2}##3}% + }% + }{% + \ifsingletokenTF{##2}{% + \cpt@temph{##1##2{##3}}% + }{% + \cpt@temph{##1{##2}{##3}}% + }% + }% + }% + \def\cpt@temph####1{% + \cptexpanded{\toks@{\unexpanded{####1}\the\toks1}}% + }% + \def\cpt@tempi{% + \ifstrcmpTF{##2}{#4}{% + \ifsingletokenTF{##4}{% + \toks@{##1##3##2##4}% + }{% + \toks@{##1##3##2{##4}}% + }% + }{% + \ifsingletokenTF{##4}{% + \toks@{##1##2##3##4}% + }{% + \toks@{##1##2##3{##4}}% + }% + }% + }% + \cpt@tempa + \endtoksgroup }% } +\DefSuffixChecker\cpt@checkoptprefix{*}{+}{!} \new@def*\ifnumoddTF#1#{% \usename{@\ifodd#1\@empty first\else second\fi oftwo}% } @@ -2329,12 +2356,14 @@ \new@edef*\cpt@rightbracechar{% \iffalse{\fi\expandafter\@car\string}\@nil } -\new@def\cptstrcmp#1#2{% - \usename{@\ifnum\pdfstrcmp{#1}{#2}=0 first\else second\fi oftwo}% +\newcommand\xifstrcmpTF[2]{% + \usename{@\ifnum\cpt@pdfstrcmp{#1}{#2}=0first\else + second\fi oftwo}% } -\new@def\ifstrcmpFT#1#2{\ifstrcmpTF{#1}{#2}\@secondoftwo\@firstoftwo} +\new@def\xifstrcmpFT#1#2{\xifstrcmpTF{#1}{#2}\iiofii\iofii} \new@def\oifstrcmpTF#1#2{% - \cptstrcmp{\expandcsonce{#1}}{\expandcsonce{#2}}% + \expandafter\cptswapbracefirst\expandafter{#1} + {\expandafter\ifstrcmpTF\expandafter{#2}}% } \robust@def\oifstrcmp@sp@TF#1#2{% \ifsingletokenTF{#1}{% @@ -2360,61 +2389,24 @@ }% } \robust@def\oifstrcmpFT#1#2{% - \oifstrcmpTF{#1}{#2}\@secondoftwo\@firstoftwo + \oifstrcmpTF{#1}{#2}\iiofii\iofii } -\new@def\xifstrcmpTF#1#2{\cptstrcmp{#1}{#2}} -\new@def\xifstrcmpFT#1#2{\cptstrcmp{#1}{#2}\@secondoftwo\@firstoftwo} \new@def\ifstreqTF#1#2{% - \expandafter\cptswapfirstbraced\expandafter + \expandafter\cptswapbracefirst\expandafter {\romannumeral-`\q\cpttrimspaces{#1}} {\expandafter\ifstrcmpTF\expandafter {\romannumeral-`\q\cpttrimspaces{#2}}} } -\robust@def\ifstreqFT#1#2{\ifstreqTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def\ifstreqFT#1#2{\ifstreqTF{#1}{#2}\iiofii\iofii} \robust@def\oifstreqTF#1#2{\cptexpandtwoargsonce\ifstreqTF{#1}{#2}} \robust@def\oifstreqFT#1#2{\cptexpandtwoargsonce\ifstreqFT{#1}{#2}} \robust@def\xifstreqTF#1#2{\cptexpandtwoargs\ifstreqTF{#1}{#2}} \robust@def\xifstreqFT#1#2{\cptexpandtwoargs\ifstreqFT{#1}{#2}} -\newcommand\ifbracedTF[3]{% - \romannumeral - \ifcase - \iffalse{{{\fi\expandafter\expandafter\expandafter - \@gobble\expandafter\expandafter\expandafter - {\expandafter\expandafter\expandafter{\expandafter - \iffalse\expandafter}\expandafter}\expandafter\fi - \string#1}\m@ne}\@ne}\z@ - \expandafter\@secondoftwo - \or - \expandafter\@secondoftwo - \else - \expandafter\@firstoftwo - \fi - {0 #2}{0 #3}% -} -\new@def*\ifbracedFT#1{\ifbracedTF{#1}\@secondoftwo\@firstoftwo} - -% Ulrich Diez 06/02/2011: -\new@def*\ud@ifbracedTF#1#2#3{% - \romannumeral - \ifblankTF{#1}{% - 0 #3% - }{% - \ifnullTF{#1}{% - 0 #3% - }{% - \expandafter\@secondoftwo\expandafter - {\expandafter{\string#1.}\expandafter\@firstoftwo - \expandafter{\iffalse}\fi0 #2}{0 #3}% - }% - }% -} -%%-- - \new@def*\ifleftbracedTF#1{% \ifblankTF{#1}{% \@secondoftwo }{% - \@nameuse{@\if\expandafter\cpt@car\detokenize{#1}\car@nil + \usename{@\if\expandafter\cpt@car\detokenize{#1}\car@nil \expandafter\cpt@car\string{\car@nil\ifnum0=`}\fi first\else second\fi oftwo}% }% @@ -2426,7 +2418,7 @@ }\@secondoftwo }\@secondoftwo } -\new@def\ifdefeqFT#1#2{\ifdefeqTF{#1}{#2}\@secondoftwo\@firstoftwo} +\new@def\ifdefeqFT#1#2{\ifdefeqTF{#1}{#2}\iiofii\iofii} \new@def\ifcateqTF#1#{\usename{@\ifcat#1first\else second\fi oftwo}} \new@def\ifcharcmpTF#1#2{% \ifsingletokenTF{#1}{% @@ -2447,46 +2439,6 @@ \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}}% {0 #2}{0 #3}% } -\newcommand*\ifleadspaceTF[1]{% - \long\def\ifleadspaceTF##1##2##3{% - \romannumeral\@nameuse{@\ifnullTF{##1}{second}% - {\cpt@ifleadspace.##1#1\@nnil}oftwo}{0#1##2}{0#1##3}% - }% -} -\ifleadspaceTF{ } -\long\def\cpt@ifleadspace#1 {% - \expandafter\ifnullTF\expandafter{\@gobble#1}{first}{second}% - \remove@to@nnil -} -\newcommand\iftrailspaceTF[1]{% - \long\def\iftrailspaceTF##1{% - \romannumeral-`\q - \csname @\expandafter\@firstofone\expandafter{% - \romannumeral\expandafter - \cpt@iftrailspace\expandafter{\remove@to@space.##1#1}% - }% - }% -} -\iftrailspaceTF{ } -\newcommand\cpt@iftrailspace[1]{% - \ifnullTF{#1}{% - \expandafter\@secondoftwo\@firstoftwo - }{% - \ifleadspaceTF{#1}{% - \expandafter\ifnullTF\expandafter{\@gobblespace#1}{% - \expandafter\@firstoftwo\@firstoftwo - }{% - \@secondoftwo - }% - }{% - \@secondoftwo - }% - }{% - {0 first}{0 second}oftwo\endcsname - }{% - \expandafter\cpt@iftrailspace\expandafter{\remove@to@space.#1}% - }% -} \new@def\ifsingletokenTF#1#2#3{% \romannumeral\ifblankTF{#1}\@secondoftwo{% \ifbracedTF{#1}\@secondoftwo{% @@ -2495,13 +2447,11 @@ }{% \expandafter\ifblankTF\expandafter{\@gobble#1}% }% - \@firstoftwo\@secondoftwo + \iofii\iiofii }% }{0 #2}{0 #3}% } -\robust@def*\ifsingletokenFT#1{% - \ifsingletokenTF{#1}\@secondoftwo\@firstoftwo -} +\new@def\ifsingletokenFT#1{\ifsingletokenTF{#1}\iiofii\iofii} \new@def\ifsingletoken@sp@TF#1#2#3{% \romannumeral\ifblankTF{#1}{% \@secondoftwo @@ -2510,17 +2460,20 @@ \@secondoftwo }{% \expandafter\ifblankTF\expandafter{\@gobble#1}% - \@firstoftwo\@secondoftwo + \iofii\iiofii }% }{0 #2}{0 #3}% } \robust@def*\ifsingledigitTF#1{% \begingroup - \def\cpt@tempa##1#1##2##3\@@nil{% + \let\@@nil\relax + \edef\cpt@tempa##1{\def##1####1\detokenize{#1}####2####3\@@nil}% + \cpt@tempa\cpt@tempa{% \endgroup \csname @\ifx##20first\else second\fi oftwo\endcsname }% - \cpt@tempa00 01 02 03 04 05 06 07 08 09 0#1\relax\@@nil + \edef\cpt@tempb{00 01 02 03 04 05 06 07 08 09 0\detokenize{#1}}% + \expandafter\cpt@tempa\cpt@tempb\relax\@@nil } \new@def*\cpt@parserlist{,;:/|*><=-+"'} \robust@def*\cpt@checklistparser#1#2{% @@ -2531,7 +2484,7 @@ }{% \ifsingletokenTF{#1}{% \xifinsetTF{\detokenize{#1}}\cpt@parserlist{% - #2% Don't put \relax here! + #2% }{% \cpt@listparsererr{#1}% }% @@ -2544,7 +2497,7 @@ \ifblankTF{#1}{% \cpt@listparsererr{#1}% }{% - \expandafter\ifsecondisnilTF\string#1\cpt@nnil\cpt@nil{% + \expandafter\ifsecondisnnilTF\string#1\cpt@nnil\cpt@nil{% \xifinsetTF{\detokenize{#1}}\cpt@parserlist{}{% \cpt@listparsererr{#1}% }% @@ -2559,6 +2512,9 @@ \robust@def*\postgroupdef#1\endgroup{% \cptpassexpanded{\endgroup\cpt@csexit{#1}}% } +\robust@def*\postgroupcsndef#1\endgroup{% + \aftercsname\postgroupdef{#1}\endgroup +} \robust@def*\cptpassacross#1#2{% \cptpassexpanded{\unexpanded{#2}\cpt@csexit#1}% } @@ -2612,6 +2568,7 @@ \unexpanded{#1}% }% } + \begingroup \catcode`\&=7 \new@gdef*\cptfullexpand#1{% @@ -2636,9 +2593,9 @@ } \endgroup -\new@def*\IfStrEqCase#1{\cpt@xtestopt{#1}\cpt@ifstreqcase{}} +\new@def*\cptifstreqcase#1{\cpt@xtestopt{#1}\cpt@ifstreqcase{}} \new@def\cpt@ifstreqcase[#1]#2#3{% - \expandafter\cptswapfirstbraced\expandafter{#2}% + \expandafter\cptswapbracefirst\expandafter{#2}% {\cpt@ifstreqc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% } \new@def\cpt@ifstreqc@se#1#2#3\cpt@nil#4#5{% @@ -2648,8 +2605,8 @@ }% }% } -\def\cptcheckchoice#1#2#3{% - \expandafter\cptswapfirstbraced\expandafter +\new@def\cptcheckchoice#1#2#3{% + \expandafter\cptswapbracefirst\expandafter {\romannumeral-`\q\cpttrimspace{#1}} {\cpt@checkchoice#2,\cpt@mil\cpt@mil,\cpt@nil}{#3}% } @@ -2662,40 +2619,60 @@ }% }% } -\new@def*\IfStrPresentCase#1{\cpt@xtestopt{#1}\cpt@ifstrincase{}} +\new@def*\cptifstrpresentcase#1{\cpt@xtestopt{#1}\cpt@ifstrincase{}} \new@def\cpt@ifstrincase[#1]#2#3{% - \expandafter\cptswapfirstbraced\expandafter{#2}% + \expandafter\cptswapbracefirst\expandafter{#2}% {\cpt@ifstrinc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% } \new@def\cpt@ifstrinc@se#1#2#3\cpt@nil#4#5{% - \ifblankTF{#3}{#5\relax}{% - \ifinsetTF{#1}{#4}{#2\relax}{% + \ifblankTF{#3}{#5}{% + \ifinsetTF{#1}{#4}{#2}{% \cpt@ifstrinc@se#3\cpt@nil{#4}{#5}% }% }% } \robust@def\cpt@in#1#2{% \long\def\in@@##1#1{}% - \ifcat$\detokenize\expandafter{\in@@#2{}{}#1}$% - \cpt@infalse\else\cpt@intrue\fi + \edef\in@@{\detokenize\expandafter{\in@@#2{}{}#1}}% + \ifcat$\in@@$\cpt@infalse\else\cpt@intrue\fi +} +\robust@def\cptiffound#1\in#2\then{% + \cptexpandtwoargs\cpt@in{\cpttrimspace{#1}}{\cpttrimspace{#2}}% + \ifcpt@in } \robust@def\ifinsetTF#1#2{% \cpt@in{#1}{#2}% \usename{@\ifcpt@in first\else second\fi oftwo}% } -\robust@def\ifinsetFT#1#2{\ifinsetTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def\ifinsetFT#1#2{\ifinsetTF{#1}{#2}\iiofii\iofii} \robust@def\oifinsetTF#1#2{\cptexpandtwoargsonce\ifinsetTF{#1}{#2}} -\robust@def\oifinsetFT#1#2{\oifinsetTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def\oifinsetFT#1#2{\oifinsetTF{#1}{#2}\iiofii\iofii} \robust@def\xifinsetTF#1#2{\cptexpandtwoargs\ifinsetTF{#1}{#2}} -\robust@def\xifinsetFT#1#2{\xifinsetTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def\xifinsetFT#1#2{\xifinsetTF{#1}{#2}\iiofii\iofii} \robust@def\oifinset@sp@TF#1#2#3{% \begingroup - \edef\x{\detokenize{#1}}% - \edef\x{{\x\cptoxdetok{#2}\x}{\x\cptoxdetok{#3}\x}}% + \edef\parser{\detokenize{#1}}% + \edef\x{{\parser\cptoxdetok{#2}\parser} + {\parser\cptoxdetok{#3}\parser}}% \expandafter\endgroup\expandafter\ifinsetTF\x } \robust@def\oifinset@sp@FT#1#2#3{% - \oifinset@sp@TF{#1}{#2}{#3}\@secondoftwo\@firstoftwo + \oifinset@sp@TF{#1}{#2}{#3}\iiofii\iofii +} +\robust@def*\cptifpattern#1\in#2{% + \ifsingletokenTF{#2}{% + \ifdefTF{#2}{% + \ifblankTF{#1}{% + \@secondoftwo + }{% + \xifinsetTF{\detokenize{#1}}{\meaning#2}% + }% + }{% + \@secondoftwo + }% + }{% + \cpt@notonetokenerr{#2}% + }% } \robust@def*\cptaddtolist{\cpt@teststopt{\cpt@addtolist\expandcsonce{e}},} \robust@def*\cptgaddtolist{\cpt@teststopt{\cpt@addtolist\expandcsonce{x}},} @@ -2769,9 +2746,9 @@ } \robust@def*\cptdeclarefilter#1{% \edef\cpt@usefilter##1##2{% - \ifblankTF{#1}{\let##2##1}{% - \ifxTF{#1}\relax{\let##2##1}{% - \ifstrcmpTF{#1}\nofilter{\let##2##1}{% + \ifblankTF{#1}{\let##2=##1}{% + \ifcseqTF#1\relax{\let##2=##1}{% + \ifstrcmpTF{#1}\nofilter{\let##2=##1}{% \unexpanded{#1}{##1}{##2}% }% }% @@ -2790,8 +2767,9 @@ \cpt@testopt\cpt@filtermergelists{,}% } \robust@def*\cpt@filtermergelists[#1]#2#3#4{% - \edef\temp@do - {\cptmakecs{\ifxTF\temp@parse\csv@@parse{csv}{kv}@do}}% + \edef\temp@do{% + \cptmakecs{\ifcseqTF\temp@parse\csv@@parse{csv}{kv}@do}% + }% \cptdeclarefilter{#4}% \ifdefTF{#2}{}{\def#2{}}% \ifblankTF{#3}{% @@ -2902,10 +2880,12 @@ \let\cpt@replace@d#2% \expandafter\cpt@replace@a\expandafter{\cpt@replace@c}% \ifdefswitchTF{cpt@fromrepl}{}{% - \ifx\cpt@replace@d#2\ifcpt@verbose - \cpt@warn{The list in \noexpand#2 not updated: - \MsgBrk something was wrong}% - \fi\fi + \ifx\cpt@replace@d#2% + \ifcpt@verbose + \cpt@warn{The list in \noexpand#2 not updated: + \MsgBrk something was wrong}% + \fi + \fi }% \postgroupdef#2\endgroup } @@ -2915,10 +2895,9 @@ \edef\cpt@replace@a{\unexpanded{#3}}% \edef\cpt@replace@b{\unexpanded{#4}}% \edef\cpt@replace@c{\ifcpt@st*\fi}% - \def\do##1,{% - \ifnot@nil{##1}{\cpt@sttrue\cpt@csvnormalize[#1]##1\do}% + \cptfor#2,\cpt@replace@a,\cpt@replace@b\dofor{% + \cpt@sttrue\cpt@csvnormalize[#1]##1% }% - \do#2,\cpt@replace@a,\cpt@replace@b,\@nil,% \def\cpt@replace@d##1#1##2\noboundary##3#1##4\noboundary{% \expandafter\cptreplaceoneelement\cpt@replace@c[#1]#2{##1}{##3}% \ifblankTF{##2}{}{% @@ -2934,31 +2913,6 @@ }% \postgroupdef#2\endgroup } -\robust@def*\preservebracedefQ#1#2{% - \def\preserve@prefix{#1}% - \def\preserve@delimiter{#2}% -} -\preservebracedefQ\long\@nil -\robust@def*\preservebracedef#1{% - \cpt@preservebracedef - \cpt@pr@servebracedef#1.% -} -\robust@def*\PreserveBraceDef#1#2{% - \cpt@preservebracedef - \long\edef\preserve@after{\unexpanded{#1}}% - \afterassignment\preserve@after - \cpt@pr@servebracedef#2.% -} -\robust@def*\cpt@preservebracedef{% - \begingroup - \def\x{\endgroup\preserve@prefix - \def\cpt@pr@servebracedef####1####2}% - \expandafter\x\preserve@delimiter{% - \preserve@prefix\edef##1{% - \unexpanded\expandafter{\remove@to@dot##2}% - }% - }% -} \robust@def*\csnnewif#1{% \ifstrcmpTF{#1}{x}{% \cpt@err{Redefining '\cptmakecs{ifx}'?}\@ehc @@ -2989,7 +2943,7 @@ \new@def*\cpt@csndef#1#2#3#4{% \if#1n\relax \ifcsndefTF{#4}{% - \def\reserved@a{#4}\cpt@notdefinable + \def\undefinablecs{#4}\cpt@notdefinable }{}% \fi \if#2p\relax\let\reserved@a\protected\else @@ -3029,23 +2983,17 @@ \robust@def*\undefcsset{\cpt@testst{\cpt@testcl\cpt@undefcsset}} \robust@def*\cpt@undefcsset#1{% \cpt@stchoose{cpt@st}{#1}\cpt@rsvda\undefcsset - \edef\cpt@rsvda - {\expandafter\cptcommanormalize\expandafter{\cpt@rsvda}}% - \def\do##1,{% - \ifnot@nil{##1}{% - \ifsingletoken@sp@TF{##1}{% - \ifescapedTF{##1}{% - \ifcpt@cl\global\fi\undefcs##1% - }{% - \cpt@notescapederr{##1}% - }% + \expandafter\cptfor\cpt@rsvda\dofor{% + \ifsingletoken@sp@TF{##1}{% + \ifescapedTF{##1}{% + \ifcpt@cl\global\fi\undefcs##1% }{% - \cpt@notonetokenerr{##1}% + \cpt@notescapederr{##1}% }% - \do + }{% + \cpt@notonetokenerr{##1}% }% }% - \expandafter\do\cpt@rsvda,\@nil,% } \robust@def*\cpttrimleadparsers#1#2{% \ifblankTF{#1}{% @@ -3053,7 +3001,7 @@ }{}% \begingroup \ifcat$\detokenize\expandafter\expandafter\expandafter - {\expandafter\@gobble#2.}$\cpt@defrelax\fi + {\expandafter\@gobble#2.}$\cpt@gobbletorelax@fi@endgroup\fi \def\reserved@e##1#1{% \edef\reserved@a{\unexpanded\expandafter{\@gobble##1}}% \ifx\reserved@a\@empty @@ -3083,7 +3031,7 @@ \cpt@trima \postgroupdef#2\endgroup } -\robust@def*\cpttrimparsers{\cpt@testopt\cpt@trimparsers{,}} +\robust@def*\cpttrimparsers{\cpt@testopt\cpt@trimparsers,} \robust@def*\cpt@trimparsers[#1]#2{% \ifsingletokenTF{#1}{% \cpttrimleadparsers{#1}#2% @@ -3102,7 +3050,8 @@ }% } \robust@def*\stripouterbraces{\cpt@testopt\cpt@stripouterbraces\@ne} -\robust@def\cpt@stripouterbraces[#1]{% +\newletcs\stripNouterbraces\stripouterbraces +\robust@def*\cpt@stripouterbraces[#1]{% \begingroup \def\after@def##1##2##3{\postgroupdef##3\endgroup}% \@tempcnta\z@pt @@ -3114,7 +3063,7 @@ \robust@def\cpt@str@pouterbraces#1#2#3{% \advance\@tempcnta\@ne \edef#3{\unexpanded{#2}}% - \cpt@str@pouterbr@ces#2\strip@nil#3#1% + \cpt@str@pouterbr@ces#2\strip@nil{#3}{#1}% } \robust@def\cpt@str@pouterbr@ces#1\strip@nil#2#3{% \defifxTF{#1}#2{% @@ -3131,9 +3080,11 @@ \robust@def\stripallouterbraces#1#2{% \edef#2{\unexpanded\cptthreexp{\cpt@stripallouterbraces{#1}}}% } +\newletcs\cptstripallbr\stripallouterbraces \robust@def\stripallouterbracesincs#1{% \expandafter\stripallouterbraces\expandafter{#1}#1% } +\newletcs\cptstripallbrincs\stripallouterbracesincs \robust@def\cpt@stripallouterbraces#1{% \romannumeral\ifbracedTF{#1}{% \expandafter\ifnullTF\expandafter{\@gobble#1}{% @@ -3141,7 +3092,6 @@ }{0 #1}% }{0 #1}% } - \robust@def\cpt@starafter#1#2{% \begingroup \def\cpt@tempa{#1}% @@ -3150,11 +3100,11 @@ \cpt@tempc } \new@def*\cpt@staract{% - \ifxTF\@sptoken\next{% + \ifcseqTF\@sptoken\next{% \afterassignment\cpt@tempc\let\next= % }{% \cptexpandsecond\endgroup{% - \ifxTF*\next{\expandcsonce\cpt@tempb}% + \ifcseqTF*\next{\expandcsonce\cpt@tempb}% {\expandcsonce\cpt@tempa}% }% }% @@ -3182,7 +3132,7 @@ }% }% } -\new@def*\ifmacroFT#1{\ifmacroTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifmacroFT#1{\ifmacroTF{#1}\iiofii\iofii} \new@def*\oifmacroTF#1{\simpleexpandarg\ifmacroTF{#1}} \new@def*\ifcsnmacroTF{\aftercsname\ifmacroTF} \edef\cpt@ifmacro{% @@ -3190,7 +3140,7 @@ } \cpt@ifmacro{\usename{@\ifblankTF{#2}{second}{first}oftwo}} -\robust@def*\csnmeaning#1{\aftercsname\meaning{#1}} +\new@def*\csnmeaning#1{\aftercsname\meaning{#1}} \robust@def*\ifescapedTF#1{% \begingroup \escapechar92\relax @@ -3198,19 +3148,24 @@ \aftercsname\endgroup {@\ifx\x\@backslashchar first\else second\fi oftwo}% } -\robust@def*\ifescapedFT#1{\ifescapedTF{#1}\@secondoftwo\@firstoftwo} -\ifcsdefinable\maxrobustalias{\chardef\maxrobustalias20} -\newcommand*\cptrobustify[1]{% +\robust@def*\ifescapedFT#1{\ifescapedTF{#1}\iiofii\iofii} +\cptchardef\maxrobustalias50 +\robust@def*\cptrobustify#1{% \def\csv@do##1{% \ifescapedTF{##1}{% \ifdefTF{##1}{% \pushnumber\robustaliascount \ifnum\robustaliascount<\maxrobustalias\relax - \aftercsname\newletcs{rsv@\cptremovescape##1}##1% - \protected\edef##1{\cptmakecs{rsv@\cptremovescape##1}}% + \ifcsndefTF{robbase@\cptgobblescape##1}{% + \cpt@warn{Command '\string##1' is already robust: + \MsgBrk not made robust again}% + }{% + \letcsntocs{robbase@\cptgobblescape##1}##1% + \protected\edef##1{\cptmakecs{robbase@\cptgobblescape##1}}% + }% \else \cpt@err{Maximum number '\number\maxrobustalias' of - command aliases exceeded:\MsgBrk + robust command aliases exceeded:\MsgBrk You can set \noexpand\maxrobustalias higher}\@ehc \fi }{% @@ -3280,7 +3235,7 @@ \cpt@notcserr{#1}% }% } -\robust@def*\providecount#1{% +\robust@def*\cptprovidecount#1{% \ifescapedTF{#1}{% \ifdefTF{#1}{% \ifcounterTF{#1}{}{% @@ -3294,7 +3249,7 @@ \cpt@notescapederr{#1}% }% } -\robust@def*\providedimen#1{% +\robust@def*\cptprovidedimen#1{% \ifescapedTF{#1}{% \ifdefTF{#1}{% \ifdimenTF{#1}{}{% @@ -3381,7 +3336,7 @@ \cpt@notogerr{#1}\@gobbletwo }% } -\new@def*\iftogFT#1{\iftogTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\iftogFT#1{\iftogTF{#1}\iiofii\iofii} \new@def*\cptswtrue{00} \new@def*\cptswfalse{01} \def\reserved@a#1{% @@ -3453,12 +3408,12 @@ \ifcondTF\if\usename{#1}\fi }% } -\new@def*\ifdefswitchFT#1{\ifdefswitchTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifdefswitchFT#1{\ifdefswitchTF{#1}\iiofii\iofii} \new@def*\ifswitchTF#1{\ifcondTF\if\usename{#1}\fi} -\new@def*\ifswitchFT#1{\ifswitchTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifswitchFT#1{\ifswitchTF{#1}\iiofii\iofii} \new@def*\thebool@normal#1{\ifdefboolTF{#1}{true}{false}} \new@def*\thebool@reverse#1{\ifdefboolTF{#1}{false}{true}} -\newvariables{count}[cpt@]{exprcnt}[0] +\cptnewcounts{cpt@exprcnt} \robust@def*\ifexprTF#1{% \begingroup \let\cpt@expr@neg\cptswfalse @@ -3468,66 +3423,66 @@ \cpt@expr@end \cpt@expr@eval } -\def\cpt@expr@beg{% +\robust@def*\cpt@expr@beg{% \begingroup \let\cpt@expr@neg\cptswfalse \cpt@exprcnt\z@pt } -\def\cpt@expr@end{% +\robust@def*\cpt@expr@end{% \cpt@expr@eval\cpt@expr@true\cpt@expr@false } -\def\cpt@expr@eval{% +\robust@def*\cpt@expr@eval{% \aftercsname\endgroup - {@\ifnum\cpt@exprcnt<\z@pt second\else first\fi oftwo}% + {@\ifnum\cpt@exprcnt<\z@pt second\else first\fi oftwo}% } -\def\cpt@expr@true{% +\robust@def*\cpt@expr@true{% \advance\cpt@exprcnt\if\cpt@expr@neg\m@one\else\z@pt\fi \let\cpt@expr@neg\cptswfalse } -\def\cpt@expr@false{% +\robust@def*\cpt@expr@false{% \advance\cpt@exprcnt\if\cpt@expr@neg\z@pt\else\m@one\fi \let\cpt@expr@neg\cptswfalse } -\long\def\cpt@expr@bgroup#1(#2\expr@nil{% +\robust@def\cpt@expr@bgroup#1(#2\expr@nil{% \cpt@expr@egroup#1)\expr@nil \ifblankTF{#2}{}{% \cpt@expr@beg \cpt@expr@bgroup#2\expr@nil }% } -\long\def\cpt@expr@egroup#1)#2\expr@nil{% +\robust@def\cpt@expr@egroup#1)#2\expr@nil{% \cpt@expr@and#1and\expr@nil \ifblankTF{#2}{}{% \cpt@expr@end \cpt@expr@egroup#2\expr@nil }% } -\long\def\cpt@expr@and#1and#2\expr@nil{% +\robust@def\cpt@expr@and#1and#2\expr@nil{% \cpt@expr@or#1or\expr@nil \ifblankTF{#2}{}{% \cpt@exprcnt\ifnum\cpt@exprcnt<\z@pt\m@one\else\z@pt\fi \cpt@expr@and#2\expr@nil }% } -\long\def\cpt@expr@or#1or#2\expr@nil{% +\robust@def\cpt@expr@or#1or#2\expr@nil{% \cpt@expr@not#1not\expr@nil \ifblankTF{#2}{}{% \cpt@exprcnt\ifnum\cpt@exprcnt<\z@pt\z@pt\else\@ne\fi \cpt@expr@or#2\expr@nil }% } -\long\def\cpt@expr@not#1not#2\expr@nil{% +\robust@def\cpt@expr@not#1not#2\expr@nil{% \cpt@expr@tog#1tog\expr@nil \ifblankTF{#2}{}{% \let\cpt@expr@neg\cptswtrue \cpt@expr@not#2\expr@nil }% } -\long\def\cpt@expr@tog#1tog#2\expr@nil{% +\robust@def\cpt@expr@tog#1tog#2\expr@nil{% \cpt@expr@bool#1bool\expr@nil \ifblankTF{#2}{}{\cpt@expr@tog@a#2\expr@nil}% } -\long\def\cpt@expr@tog@a#1#2\expr@nil{% +\robust@def\cpt@expr@tog@a#1#2\expr@nil{% \edef\reserved@a{\cpttrimspaces{#1}}% \ifcsndefTF{cpt@tog@\reserved@a}{% \usename{cpt@tog@\reserved@a}\cpt@expr@true\cpt@expr@false @@ -3538,11 +3493,11 @@ }% \cpt@expr@tog#2\expr@nil } -\long\def\cpt@expr@bool#1bool#2\expr@nil{% +\robust@def\cpt@expr@bool#1bool#2\expr@nil{% \cpt@expr@switch#1switch\expr@nil \ifblankTF{#2}{}{\cpt@expr@bool@a#2\expr@nil}% } -\long\def\cpt@expr@bool@a#1#2\expr@nil{% +\robust@def\cpt@expr@bool@a#1#2\expr@nil{% \edef\reserved@a{\cpttrimspaces{#1}}% \ifcsndefTF{if\reserved@a}{% \ifboolTF\reserved@a\cpt@expr@true\cpt@expr@false @@ -3553,11 +3508,11 @@ }% \cpt@expr@bool#2\expr@nil } -\long\def\cpt@expr@switch#1switch#2\expr@nil{% +\robust@def\cpt@expr@switch#1switch#2\expr@nil{% \cpt@expr@test#1test\expr@nil \ifblankTF{#2}{}{\cpt@expr@switch@a#2\expr@nil}% } -\long\def\cpt@expr@switch@a#1#2\expr@nil{% +\robust@def\cpt@expr@switch@a#1#2\expr@nil{% \edef\reserved@a{\cpttrimspaces{#1}}% \ifcsndefTF\reserved@a{% \ifswitchTF\reserved@a\cpt@expr@true\cpt@expr@false @@ -3568,7 +3523,7 @@ }% \cpt@expr@switch#2\expr@nil } -\long\def\cpt@expr@test#1test#2\expr@nil{% +\robust@def\cpt@expr@test#1test#2\expr@nil{% \ifblankTF{#1}{}{% \cpt@err{Invalid piece in test expression: \MsgBrk'\detokenize{#1}'}\@ehc @@ -3577,17 +3532,110 @@ \cpt@expr@test@a#2\expr@nil }% } -\long\def\cpt@expr@test@a#1#2\expr@nil{% +\robust@def\cpt@expr@test@a#1#2\expr@nil{% \ignorespaces#1\cpt@expr@true\cpt@expr@false \cpt@expr@test#2\expr@nil } -\new@def*\cpt@beforeprocessoptions{} -\new@def*\cpt@afterprocessoptions{} +\robust@def*\cptifonepresentTF#1#2{% + \begingroup + \cpt@choicefdfalse + \def\siso@do##1{% + \ifinsetTF{##1}{#2}{% + \cpt@choicefdtrue\loopbreak + }{}% + }% + \siso@@loop{#1}% + \expandafter\endgroup\ifcpt@choicefd + \expandafter\iofii\else\expandafter\iiofii\fi +} +% #1: listcmd +% #2: comparator: < (ascending) or > (descending) +\robust@def*\cptnumbersort#1#2{% + \begingroup + \let\numcmp\ifnumcmpTF + \cpt@sortlist{#1}{#2}% +} +\robust@def*\cptbignumbersort#1#2{% + \begingroup + \ifcsndefTF{ver@fp.sty}{% + \def\reserved@a##1#2##2##3\cpt@nil{% + \def\numcmp####1#2####2####{% + \usename{FPif##2}{####1}{####2}% + \expandafter\iofii\else\expandafter\iiofii\fi + }% + }% + \reserved@a={eq}>{gt}<{lt}\cpt@nil + }{% + \cpt@err{'fp' package not loaded} + {You need to first load 'fp' package before + \MsgBrk calling \string\cptbignumbersort.}% + }% + \cptexpandarg{\cptifonepresentTF{/*-+}}{\cptoxdetok{#1}}{% + \def\siso@do##1{% + \FPeval\resulta{clip(##1)}% + \edef#1{#1{\resulta}}% + }% + \cptexpandarg{\def#1{}\siso@@loop}{#1}% + }{}% + \cpt@sortlist{#1}{#2}% +} +\robust@def*\cptalphasort#1#2{% + \begingroup + \def\numcmp##1#2##2##{% + \ifnum\cpt@pdfstrcmp{##1}{##2}#2\z@pt + \expandafter\iofii\else\expandafter\iiofii\fi + }% + \cpt@sortlist{#1}{#2}% +} +\robust@def*\cpt@sortlist#1#2{% + \def\sortedlist{}% + \cpt@s@rtlist{#1}{#2}% + \edefpass#1{\endgroup\def\noexpand#1{\sortedlist}}% +} +\new@def*\cpt@sortwrapper#1{{#1}} +\robust@def*\cpt@s@rtlist#1#2{% + \def\do##1{% + \def\smaller@bigger{}% + \defpass\do####1{% + \defifxTF{####1}\@nnil{% + \edef\sortedlist{\sortedlist\cpt@sortwrapper{##1}}% + \ifcsemptyTF\smaller@bigger{}{% + \let#1=\smaller@bigger + \cpt@s@rtlist#1#2% + }% + }{% + \numcmp####1#2##1{% + \cpt@s@rtl@st{#1}{#2}{{####1}{##1}}.% + }{% + \edef\smaller@bigger{\smaller@bigger{####1}}% + \do + }% + }% + }% + }% + \expandafter\do#1\@nil +} +\robust@def*\cpt@s@rtl@st#1#2#3#4\@nil{% + \edef#1{#3\smaller@bigger\@gobble#4}% + \cpt@s@rtlist{#1}{#2}% +} + \robust@def*\BeforeProcessOptions{% - \grightaddtocs\cpt@beforeprocessoptions + \ifcsndefTF{\@currname @\@currext @beginprocessopt}{% + \cpt@warn{\noexpand\BeforeProcessOptions wrongly located}% + \@gobble + }{% + \aftercsname\grightaddtocs{\@currname @\@currext + @beforeprocessopt}% + }% } \robust@def*\AfterProcessOptions{% - \grightaddtocs\cpt@afterprocessoptions + \ifcsndefTF{\@currname @\@currext @endprocessopt}{% + \@firstofone + }{% + \aftercsname\grightaddtocs{\@currname @\@currext + @afterprocessopt}% + }% } \robust@def*\BeforeStartOfDocument{% \grightaddtocs\cpt@beforestartdoc @@ -3599,18 +3647,27 @@ \cpt@beforestartdoc \let\BeforeStartOfDocument\@notprerr \gundefcs\cpt@beforestartdoc - \def\cpt@docstarted{}% + \gdef\cpt@docstarted{}% \begingroup } \robust@def*\AfterStartOfDocument{% \grightaddtocs\cpt@afterstartdoc } \new@def*\cpt@afterstartdoc{} +\robust@def*\AfterAfterStartOfDocument#1{% + \AtBeginDocument{% + \grightaddtocs\cpt@afterafterstartdoc{#1}% + }% +} +\new@def*\cpt@afterafterstartdoc{} \grightaddtocs\document{% \let\AfterStartOfDocument\@firstofone \cpt@afterstartdoc \let\AfterStartOfDocument\@notprerr \gundefcs\cpt@afterstartdoc + \cpt@afterafterstartdoc + \let\AfterAfterStartOfDocument\@notprerr + \gundefcs\cpt@afterafterstartdoc \ignorespaces } \gleftaddtocs\@popfilename{% @@ -3619,6 +3676,20 @@ \gundefcsn{\@currname.\@currext-cpt@hook}% }% } +% \loadifnotloaded{<package>}[<date>] +\robust@def*\loadifnotloaded#1{% + \cpt@testopt{\cpt@ifpkgnotloaded{#1}}{}% +} +\robust@def*\cpt@ifpkgnotloaded#1[#2]{% + \@ifpackageloaded{#1}{% + \@ifpackagelater{#1}{#2}{}{% + \ltxmsg@err{Loaded version of #1 package is not current}\@ehc + }% + }{% + \RequirePackage{#1}[#2]% + }% +} +% \ifpackagewithoptionsTF{<package>}{<options>} \robust@def*\ifpackagewithoptionsTF{\cpt@ifoptions\@pkgextension} \robust@def*\ifclasswithoptionsTF{\cpt@ifoptions\@clsextension} \robust@def*\cpt@ifoptions#1#2{% @@ -3629,35 +3700,63 @@ \edef\temp@optlist{\unexpanded{#1}}% \cpt@sttrue\cpt@kvnormalize[,]\temp@optlist \cpt@choicefdtrue - \def\kv@do##1{% - \oifinset@sp@TF,{##1}\temp@optlist - {}{\cpt@choicefdfalse\loopbreak}% + \def\checkopts{% + \def\kv@do####1{% + \oifinset@sp@TF,{####1}\temp@optlist + {}{\cpt@choicefdfalse\loopbreak}% + }% + \kv@@parse{#2}% + }% + \ifblankTF{#2}{% + \ifcsemptyTF\temp@optlist{}{% + \cpt@choicefdfalse + }% + }{% + \ifcsemptyTF\temp@optlist{% + \cpt@choicefdfalse + }{% + \checkopts + }% }% - \kv@@parse{#2}% \ifboolTF{cpt@choicefd} {\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% } +% If package was later loaded (before begin-document). +% \ifpackageloadedlaterTF{<package>}{<true>}{<false>} \robust@def*\ifpackageloadedlaterTF{\cpt@ifpkgloadedlater\@pkgextension} \robust@def*\ifclassloadedlaterTF{\cpt@ifpkgloadedlater\@clsextension} \robust@def*\cpt@ifpkgloadedlater#1#2#3#4{% - \usename{@if#1loaded}{#2}{}{% - \AfterStartOfDocument{% - \usename{@if#1loaded}{#2}{% - \cpt@info{\@cls@pkg\@space '#2' was loaded afterwards}% - #3\relax - }{% - \cpt@info{\@cls@pkg\@space '#2' wasn't loaded afterwards}% - #4\relax + \begingroup + \edef\elt{\ifx#1\@pkgextension package\else class\fi}% + \usename{@if\elt loaded}{#2}{% + \endgroup + \ifcpt@verbose + \cpt@info{\@cls@pkg\@space '#2' has been loaded}% + \fi + }{% + \def\elt##1##2{% + \ifcpt@verbose + \cpt@info{\@cls@pkg\@space '#2' was##1 loaded afterwards}% + \fi + \unexpanded{##2}\relax + }% + \cptexpanded{\endgroup + \AfterStartOfDocument{% + \noexpand\ifcsndefTF{ver@#2.#1}{\elt{}{#3}}{\elt{n't}{#4}}% }% }% }% } +% \cptloadpackages[<inner-parser><outer-parser>]{% +% pkga<inner>options<inner>date<outer> +% pkgb<inner>options<inner>date<outer> +% } \robust@def*\cptloadpackages{% \begingroup \endlinechar=-1 \cpt@testopt{\expandafter\endgroup\cpt@loadpackages}{|;}% } -\robust@def\cpt@loadpackages[#1]#2{% +\robust@def*\cpt@loadpackages[#1]#2{% \begingroup \toks@{}% \def\cpt@tempa##1##2\cpt@nil{% @@ -3707,7 +3806,7 @@ }{% \cptexpanded{% \toks@{\the\toks@ - \ifxTF\documentclass\@twoclasseserror + \ifcseqTF\documentclass\@twoclasseserror {\noexpand\usepackage}{\noexpand\RequirePackage}% [\expandcsonce\cpt@rsvda]{####1}[####3]% }% @@ -3736,7 +3835,7 @@ }% } \robust@def*\ifinstylefileTF{% - \ifcsemptyTF\@currname\@secondoftwo\@firstoftwo + \ifcsemptyTF\@currname\iiofii\iofii } \robust@def*\cpt@pushhash{% \begingroup @@ -3778,7 +3877,7 @@ \ifblankTF{##2}{% \toks@\expandafter{\the\toks@##1}% }{% - \cptpassexpanded{\toks@{\the\toks@##1\cpt@hashchar}}% + \cptexpanded{\toks@{\the\toks@##1\cpt@hashchar}}% \y##2\cpt@nil }% }% @@ -3789,6 +3888,7 @@ \edef#2{\the\toks@}% \postgroupdef#2\endgroup } +% * -> #2 is a listcmd, else it is a list: \robust@def*\csv@@normalize{\cpt@teststopt\cpt@csvnormalize,} \robust@def\cpt@csvnormalize[#1]#2{% \let\cpt@inkv\cptswfalse @@ -3800,12 +3900,16 @@ \cpt@normalizelist{#1}{#2}% } \ifcsdefinable\normalized@list\relax -\robust@def\cpt@normalizelist#1#2{% + +\begingroup +\catcode`\^=3 +\robust@gdef\cpt@normalizelist#1#2{% \begingroup - \let\ifnmlzst\ifcpt@st + \let\if@nmlzst\ifcpt@st \cpt@stchoose{cpt@st}{#2}\reserved@e\cpt@normalizelist \ifx\reserved@e\@empty - \def\normalized@list{}\cpt@defrelax + \def\normalized@list{}% + \cpt@gobbletorelax@fi@endgroup \fi \cpt@ch@cklistparser{#1}% \expandafter\setup@parser@nmlz\string#1% @@ -3814,17 +3918,20 @@ \expandafter\nmlz@spaceletter\string#1% \expandafter\nmlz@letterspace\string#1% \expandafter\nmlz@doubleletter\string#1% - \ifdefswitchFT{cpt@inkv}{}{% + \ifswitchFT{cpt@inkv}{}{% \nmlz@activeequal \nmlz@spaceletter=% \nmlz@letterspace=% + \toks@\expandafter{\the\toks@^?}% \nmlz@doubleletter=% \cpt@commaequalerr + \def\reserved@a##1^?##2\cpt@nil{\toks@{##1##2}}% + \expandafter\reserved@a\the\toks@\cpt@nil }% \edef\normalized@list{\the\toks@}% \cpttrimleadparsers#1\normalized@list \cptexpandsecond\endgroup{% - \ifboolTF{nmlzst}{% + \ifboolTF{@nmlzst}{% \edef\noexpand#2{\ox@unexpanded\normalized@list}% \undefcs\noexpand\normalized@list }{% @@ -3833,6 +3940,8 @@ }% \cpt@relax } +\endgroup + \def\setup@parser@nmlz#1{% \begingroup \uccode`\~=`#1% @@ -3907,6 +4016,16 @@ }% \expandafter\cpt@tempa\the\toks@,=\nmlz@nil } +\robust@def*\cptcheckbool#1#2#3{% + \lowercase{% + \edef\cpt@resa{\s@expandarg\cpttrimspaces{\cptrm-`\q#1}}% + }% + \xifinsetTF{,\cpt@resa,}{,true,false,}{% + #3\relax + }{% + \@latex@error{Invalid value '#1' for '#2'}\@ehc + }% +} \let\cpt@documentclass\cpt@undefined \robust@def*\cpt@getdocumentclass{% \def\csv@do##1{% @@ -3946,18 +4065,12 @@ \let\cpt@classoptionslist\@classoptionslist \def\@fileswith@ptions##1[##2]##3{% \edef\cpt@tempa{\cptcommanormalize{##3}}% - \cpt@choicefdfalse - \def\do####1,{% - \ifnot@nil{####1}{% - \xifinsetFT{,####1,}{,\cpt@tempa,} - {}\cpt@choicefdtrue - \do + \cptfor xkeyval,kvoptions,ltxkeys\dofor{% + \xifinsetFT{,####1,}{,\cpt@tempa,}{}{% + \let\@classoptionslist\cpt@classoptionslist + \forbreaktrue }% }% - \do xkeyval,kvoptions,ltxkeys,\@nil,% - \ifcpt@choicefd - \let\@classoptionslist\cpt@classoptionslist - \fi \cpt@ifbrack{\@fileswith@pti@ns##1[##2]##3}% {\@fileswith@pti@ns##1[##2]##3[]}% }% @@ -3979,7 +4092,7 @@ \cpt@isblankerr\RecoverAtRequirePackage }% \begingroup - \docommalist{#1}{% + \cptfor#1\dofor{% \ifescapedTF{##1}{% \ifdefTF{##1}{}{% \cpt@notdeferr{##1}% @@ -4147,16 +4260,6 @@ \let\cmdoption\cptswfalse \cpt@testfam\cpt@declarecmdoptions } -\robust@def*\cptcheckbool#1#2#3{% - \lowercase{% - \edef\cpt@resa{\s@expandarg\cpttrimspaces{\cptrm-`\q#1}}% - }% - \xifinsetTF{,\cpt@resa,}{,true,false,}{% - #3\relax - }{% - \@latex@error{Invalid value '#1' for '#2'}\@ehc - }% -} \robust@def*\cpt@declarecmdoption<#1>#2{% \trim@@space{#1}\cpt@currfam \trim@@space{#2}\cpt@curropt @@ -4301,7 +4404,8 @@ \robust@def\cpt@d@cl@reswoptions#1#2#3(#4)#5{% \trim@@spaces{#1}\cpt@currfam \begingroup - \toks@{{#3}(#4){#5}}\toks1{}% + \toks@{{#3}(#4){#5}}% + \toks1{}% \def\csv@do##1{% \cpt@badoptionerr{##1}% \cptexpanded{% @@ -4490,6 +4594,9 @@ } \robust@def*\cpt@define@default@ds<#1>#2{% \csn@def{#1@default@ds}##1##2##3{#2}% + \AtEndOfPackage{% + \let\cpt@define@default@ds\rsv@cpt@define@default@ds + }% \protected\def\cpt@define@default@ds<##1>##2{% \cpt@err{'\string\XDeclareOption*' multiply defined in \MsgBrk\@cls@pkg\space'\@currname'}{Multiple star @@ -4497,14 +4604,17 @@ \@cls@pkg\@space'\@currname'.}% }% } +\newletcs\rsv@cpt@define@default@ds\cpt@define@default@ds \RecoverAtRequirePackage\cpt@define@default@ds \new@def*\cpt@optionlist#1{% \ifcsndefFT{opt@#1}{}{\unexpanded\cptsevenxp{\usename{opt@#1}}}% } \newletcs\cpt@processedoptions\@empty \robust@def*\XProcessOptions{% - \cpt@beforeprocessoptions - \let\cpt@beforeprocessoptions\relax + \csn@def{\@currname @\@currext @beginprocessopt}{}% + \letcstocsn\reserved@a{\@currname @\@currext @beforeprocessopt}% + \letcsntocs{\@currname @\@currext @beforeprocessopt}\relax + \ifdefTF\reserved@a\reserved@a\relax \cpt@inpoxtrue \let\@fileswith@pti@ns\@badrequireerror \edef\cpt@testname{\@currname.\@currext}% @@ -4528,14 +4638,15 @@ }% } \robust@def*\cpt@yprocessoptions#1[#2]{% - \iflacus{#2}{% + \ifblankTF{#2}{% \def\cpt@currna{}% }{% \edef\cpt@currna{\cptcommanormalize{#2}}% }% - \docommalist{#1}{% + \def\csv@do##1{% \cpt@ypr@cessoptions{##1}% }% + \csv@@parse{#1}% \cpt@pr@cessoptions \cpt@pr@cessopti@ns } @@ -4570,14 +4681,15 @@ }% } \robust@def*\cpt@xprocessoptions#1[#2]{% - \iflacus{#2}{% + \ifblankTF{#2}{% \def\cpt@currna{}% }{% \edef\cpt@currna{\cptcommanormalize{#2}}% }% - \docommalist{#1}{% + \def\csv@do##1{% \cpt@xpr@cessoptions{##1}% }% + \csv@@parse{#1}% \cpt@pr@cessoptions \cpt@pr@cessopti@ns } @@ -4651,17 +4763,19 @@ \let\@fileswith@pti@ns\@@fileswith@pti@ns \cpt@olddxfalse \AtEndOfPackage{\let\@unprocessedoptions\relax}% - \cpt@afterprocessoptions - \let\cpt@afterprocessoptions\relax + \letcstocsn\reserved@a{\@currname @\@currext @afterprocessopt}% + \letcsntocs{\@currname @\@currext @afterprocessopt}\relax + \ifdefTF\reserved@a\reserved@a\relax + \csn@def{\@currname @\@currext @endprocessopt}{}% } \robust@def*\ifindefaultdsTF{% \begingroup - \def\reserved@e{\@firstoftwo\@secondoftwo}% + \def\reserved@e{\iofii\iiofii}% \cpt@ifin@default@ds } \robust@def*\ifindefaultdsFT{% \begingroup - \def\reserved@e{\@secondoftwo\@firstoftwo}% + \def\reserved@e{\iiofii\iofii}% \cpt@ifin@default@ds } \robust@def*\cpt@ifin@default@ds#1{% @@ -4852,7 +4966,7 @@ \cptgaddtolist*\cpt@processedoptions\CurrentOption }% \ifcsnullTF\OptionFound{}{\cpt@removecurroption\OptionFound}% - \ifxTF\OptionFound\CurrentOption{}{% + \ifcseqTF\OptionFound\CurrentOption{}{% \cpt@removecurroption\CurrentOption }% }% @@ -4881,7 +4995,7 @@ % Only 'article', 'report', 'memoir' options have been added % to \XExternalOptions. Other external options (eg, those of % script and KOMA-Script classes) haven't been added. -\newcommand*\XExternalOptions{% +\new@def*\XExternalOptions{% 10pt,11pt,12pt,14pt,17pt,20pt,25pt,30pt,36pt,48pt,60pt,% a0paper,a1paper,a2paper,a3paper,a4paper,a6paper,% b0paper,b1paper,b2paper,b3paper,b4paper,b5paper,b6paper,% @@ -4938,7 +5052,7 @@ }% \edef\cpt@tempb{\cpt@currfam @ds@\cpt@curropt}% \@onelevel@sanitize\cpt@tempb - \ifxTF\cpt@tempa\cpt@tempb{% + \ifcseqTF\cpt@tempa\cpt@tempb{% \begingroup \csn@def{\cpt@currfam @ds@\cpt@curropt}##1{% \toks@{\def\cpt@currval{##1}}% @@ -4964,7 +5078,7 @@ \cptexpandargonce{\cptfilterremovekv[,]% \@unusedoptionlist}{#1}\nofilter } -\robust@def*\cpt@cleanup#1{% +\robust@def*\cpt@optioncleanup#1{% \ifmacroTF{#1}{}{\cpt@notcserr{#1}}% \BeforeStartOfDocument{% \ifdefFT#1{}{% @@ -4985,7 +5099,7 @@ }% } \BeforeStartOfDocument{% - \cpt@cleanup\cpt@processedoptions + \cpt@optioncleanup\cpt@processedoptions } \robust@redef*\@fileswith@pti@ns#1[#2]#3[#4]{% \begingroup @@ -4997,7 +5111,7 @@ }% \def\file@withopts##1{\cptpassexpanded{\toks@{##1}}}% \toks@{}% - \ifxTF#1\@clsextension{% + \ifcseqTF#1\@clsextension{% \ifx\@classoptionslist\relax \xdef\@classoptionslist{\expandcsonce\fileopts}% \file@withopts{\fileswithopts{#3}{#1\@documentclasshook}}% @@ -5025,16 +5139,19 @@ \defpass\reserved@a{% \@ifl@aded\@currext{#1}{% \cpt@ifoptions\@currext{#1}{#2}{}{% - \edef\reserved@a{\cpt@optionlist{#1.\@currext}}% - \@onelevel@sanitize\reserved@a - \ltx@err{Option clash for \@cls@pkg\space #1}{% - The package #1 has already been loaded - with options:\MsgBrk - \space\space[\reserved@a].\MsgBrk - There has now been an attempt to load it with options - \MsgBrk\space\space[\unexpanded{#2}].\MsgBrk - Adding the global options:\MsgBrk - \space\space'\reserved@a,\unexpanded{#2}'\MsgBrk + \edef\reserved@e{\cpt@optionlist{#1.\@currext}}% + \@onelevel@sanitize\reserved@e + \despacecontent\reserved@e + \ltxmsg@err{Option clash for \@cls@pkg\@space #1}{% + The package '#1' has already been loaded + with \ifx\reserved@e\@empty no options\MsgBrk\else + options:\MsgBrk\@space\@space[\reserved@e]\fi.\MsgBrk + There has now been an attempt to load it with + \iflacus#2\dolacus no options\else options + \MsgBrk\@space\@space[\unexpanded{#2}]\fi. + \MsgBrk Adding the global options:\MsgBrk + \@space\@space'\ifx\reserved@e\@empty\else + \reserved@e\ifblankTF{#2}{}{,}\fi\unexpanded{#2}'\MsgBrk to your \noexpand\documentclass declaration may fix this. }% }% @@ -5057,30 +5174,33 @@ \expandafter\endcsname\@space v \@nil\cpt@tempc \@ifl@ter\@currext{#1}{#3}{}{% \cptexpandarg\AtEndDocument{% - \ltx@warn{% + \ltxmsg@warn{% You requested,\on@line, version\MsgBrk \cpt@tempb\@space of \@cls@pkg\@space #1,\MsgBrk but only version \cpt@tempc\MsgBrk is available }% }% }% - \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi + \ifx\@currext + \@clsextension\let\LoadClass\@twoloadclasserror + \fi \@popfilename \@reset@ptions }% } \robust@def*\cpt@removevalues#1{% - \docommalist{#1}{\cpt@rem@vevalues{##1}}% + \cptfor#1\dofor{\cpt@rem@vevalues{##1}}% } \robust@def*\cpt@rem@vevalues#1{% - \ifxTF#1\@empty\gobble@to@relax\relax - \xifinsetTF{=}{\cptoxdetok{#1}}{}\gobble@to@relax + \ifcseqTF#1\@empty\cpt@gobbletorelax\relax + \xifinsetTF{=}{\cptoxdetok{#1}}{}\cpt@gobbletorelax \begingroup \def\cpt@resa{}% \def\cpt@resb##1=##2\cpt@nil{% \edef\cpt@resa{\csliststack,\cpt@resa\unexpanded{##1}}% }% - \docommalist*{#1}{\cpt@resb##1=\cpt@nil}% + \def\kv@do##1{\cpt@resb##1=\cpt@nil}% + \kv@@parse*{#1}% \let#1\cpt@resa \postgroupdef#1\endgroup \cpt@relax @@ -5090,10 +5210,11 @@ \edef\CurrentOption{\unexpanded{#1}}% \cpt@sttrue\cpt@kvnormalize[,]\CurrentOption \cpt@removevalues\CurrentOption - \docommalist*\CurrentOption{% + \def\csv@do##1{% \def\CurrentOption{##1}% \csname ds@##1\endcsname }% + \csv@@parse*\CurrentOption \popfunctions\ExecuteOptions\cpt@optdepth } \robust@redef\@pass@ptions#1#2#3{% @@ -5147,33 +5268,38 @@ \ifx\@currext\@clsextension\else\expandcsonce \@classoptionslist,\fi\expandcsonce\@curroptions }% - \docommalist*\@declaredoptions{% + \def\csv@do##1{% \def\CurrentOption{##1}% \oifinset@sp@TF,\CurrentOption\@curr@ptions{% \@use@ption \letcsntocs{ds@##1}\@empty }{}% }% + \csv@@parse*\@declaredoptions \@process@pti@ns } \robust@redef*\@xprocess@ptions{% - \ifxTF\@currext\@clsextension{}{% - \docommalist*\@classoptionslist{% + \ifcseqTF\@currext\@clsextension{}{% + \def\csv@do##1{% \def\CurrentOption{##1}% \oifinset@sp@TF,\CurrentOption\@declaredoptions{% \@use@ption \letcsntocs{ds@##1}\@empty }{}% }% + \csv@@parse*\@classoptionslist }% \@process@pti@ns } \robust@redef*\@process@pti@ns{% - \docommalist*\@curroptions{% + \def\csv@do##1{% \def\CurrentOption{##1}% \ifcsndefTF{ds@##1}\@use@ption{\@use@ption\default@ds}% }% - \docommalist*\@declaredoptions{\letcsntocs{ds@##1}\relax}% + \csv@@parse*\@curroptions + \expandafter\cptfor\@declaredoptions\dofor{% + \letcsntocs{ds@##1}\relax + }% \popfunctions\ProcessOptions\cpt@optdepth \let\@fileswith@pti@ns\@@fileswith@pti@ns \AtEndOfPackage{\let\@unprocessedoptions\relax}% @@ -5207,6 +5333,7 @@ }% \ifdefTF\cpt@documentclass\endgroup\cpt@tempa } + \cptonlypreamble{% \cptonlypreamble,\cptloadpackages,\ifpackagewithoptionsTF, \ifclasswithoptionsTF,\cpt@ifoptions, @@ -5222,7 +5349,8 @@ \cpt@findoption@b,\cpt@processoptions,\cpt@xprocessoptions, \cpt@yprocessoptions,\cpt@pr@cessoptions,\BeforeStartOfDocument, \AfterStartOfDocument,\XInvalidOptionHandler,\XDeclareInvalidOption, - \XDeclareInvalidOptions,\XUnknownOptionHandler,\XExternalOptions + \XDeclareInvalidOptions,\XUnknownOptionHandler,\XExternalOptions, + \AfterProcessOptions,\BeforeProcessOptions,\loadifnotloaded } \XDeclareBiBooleanOptions{verbose,silent}[true](cpt@){}{} \XDeclareBiBooleanOptions{draft,final}[true](cpt@){}{} @@ -5255,4 +5383,3 @@ \endinput %% End of file catoptions.sty %% - |