diff options
author | Karl Berry <karl@freefriends.org> | 2011-04-20 01:01:50 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-04-20 01:01:50 +0000 |
commit | 7fdcf9031f72f16e589f323b53e9b8e70460ccd3 (patch) | |
tree | 29b01d0c33f8d29c44537e9615b3fb396c778c27 | |
parent | e4d3b62937c429d281f1e1fca5957ea8611abd23 (diff) |
catoptions (19apr11)
git-svn-id: svn://tug.org/texlive/trunk@22128 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/README | 12 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf | bin | 350403 -> 388677 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex | 261 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg | 29 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/catoptions/catoptions.sty | 2936 |
5 files changed, 2158 insertions, 1080 deletions
diff --git a/Master/texmf-dist/doc/latex/catoptions/README b/Master/texmf-dist/doc/latex/catoptions/README index 209718e379d..49831b28d7f 100644 --- a/Master/texmf-dist/doc/latex/catoptions/README +++ b/Master/texmf-dist/doc/latex/catoptions/README @@ -2,9 +2,9 @@ This is the README file for the 'catoptions' package. SUMMARY The 'catoptions' package changes package loading internals so -that all subsequently loaded packages can rely on normal/standard -catcodes of all ASCII characters. The package defines canonical -control sequences to represent all the visible ASCII characters. +that all subsequently loaded packages can rely on normal/standard +catcodes of all ASCII characters. The package defines canonical +control sequences to represent all the visible ASCII characters. It also provides robust options parsing mechanisms, in addition to many TeX programming tools. @@ -12,10 +12,10 @@ AUTHOR Ahmed Musa RELATED PACKAGES -The 'catoptions' package is based on the 'pcatcode' package -by Michael J. Downes and David M. Jones. +The catcode section of the 'catoptions' package is based on +the 'pcatcode' package by Michael J. Downes and David M. Jones. VERSION -Version 0.2, February 2011 +Version 0.2b, April 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 9aeba1d85e3..2ef01da6887 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 d6d4a9acee6..4b9a1c0b4d6 100644 --- a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex +++ b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex @@ -3,6 +3,7 @@ \makeatletter \WrapQuotes \NoPrintNotes +\def\XDecS{\fx{\XDeclareOption}\RedStar\sspace} \makeindex \begin{document} @@ -11,7 +12,7 @@ \title{The \texttt{\color{blue}catoptions} Package\titleref{t1}} \titlenote[t1]{The package is available at \iftogTF{pdf}{\url{\@titleurl}}{\url{\@shorttitleurl}}.} -\version{0.2} +\version{0.2b} \titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/catoptions/} \shorttitleurl{http://www.ctan.org/} \author{Ahmed Musa \Email{a.musa@rocketmail.com}\\Preston, Lancashire, UK} @@ -19,7 +20,7 @@ \def\abstractname{\textsf{Summary}} \begin{abstract} \small - The \pkg'{catoptions} provides several extensions to the \pkgm'{pcatcode}. Apart from the tools related to setting up, preserving and restoring category codes, it includes many \texorlatex programming tools and even new list and options processing interfaces. It modifies the \latex kernel's options parsing mechanism to forestall premature expansion of options and values (in the manner of the \pkgs'{xkvltxp,kvoptions-patch}), so that the \pkg'{catoptions} may be loaded even before \hx{\documentclass}. In fact, the package is meant to be loaded on top of other packages, so as to exploit its catcode preserving scheme. Among other reasons, this necessitated the development of the options parsing scheme of this package. Only the catcode and options parsing facilities are treated in this manual; the macro programming interfaces will be covered in the documentation of the \pkg'{ltxtools}. The machinery of the \pkg'{catoptions} adds no cost to the simple syntax of \LaTeX's native options parser. Users who are already familiar with \LaTeX's legacy options processing don't necessarily have to invest the time that is essential in learning the extensive machinery of existing key-value and option parsers, although those other packages (\eg, \pkgs{xkeyval, kvsetkeys, kvoptions, skeyval, rkeyval, pgfkeys, pgfopts}) contain richer featuresets. Existing packages don't have to be modified to use the features of the \pkg'{catoptions}. The \pkg'{catoptions}, while maintaining simplicity, does not strip off even one level of outer braces in parsing package options and in list processing. It robustly normalizes key-values and options prior to parsing. The options parsing scheme of the \pkg'{catoptions} has been tried as a replacement parser on many packages, including \pkgs'{hyperref, cleveref, natbib} without difficulties. + The \pkg'{catoptions} provides several extensions to the \pkgm'{pcatcode}. Apart from the tools related to setting up, preserving and restoring category codes, it includes many \texorlatex programming tools and even new list and options processing interfaces. It modifies the \latex kernel's options parsing mechanism to forestall premature expansion of options and values (in the manner of the \pkgs'{xkvltxp,kvoptions-patch}), so that the \pkg'{catoptions} may be loaded even before \hx{\documentclass}. In fact, the package is meant to be loaded on top of other packages, so as to exploit its catcode preserving scheme. Among other reasons, this necessitated the development of the options parsing scheme of this package. Only the catcode and options parsing facilities are treated in this manual; the application programming interfaces will be covered in the documentation of the \pkg'{ltxtools}. The machinery of the \pkg'{catoptions} adds no cost to the simple syntax of \LaTeX's native options parser. Users who are already familiar with \LaTeX's legacy options processing don't necessarily have to invest the time that is essential in learning the extensive machinery of existing key-value and option parsers. Existing packages don't have to be modified to use the features of the \pkg'{catoptions}. The \pkg'{catoptions}, while maintaining simplicity, does not strip off even one level of outer braces in parsing package options and in list processing. It robustly normalizes key-values and options prior to parsing. The options parsing scheme of the \pkg'{catoptions} has been tried as a replacement parser on the \pkgnoidx{article} class and on many packages, including \pkgs'{hyperref, cleveref, natbib} without difficulties. \end{abstract} \let\licensename\relax @@ -38,15 +39,14 @@ width=1.0\hsize]\tableofcontents \end{xwmshade} - \docsection(sec:motivation){Motivation} -My motivation for turning to the \pkgnoidx'{pcatcode} was to save myself the trouble of declaring category codes at the beginning of my packages. After spending some time on the \pkgnoidx'{pcatcode}, I discovered I had learnt enough to make changes and additions to some of its macros and functionality. After completing the catcode stuff in the \pkg'{catoptions}, I wanted to pass options to the package. If the package is to be loaded on top of other packages, as intended, then its options parsing scheme should be independent of other packages. But realizing the trouble with passing expandable option values to packages and classes via the \latex kernel's scheme, I decided to implement modifications to the kernel's options parser. Apart from the problem of premature expansion of options and values by the \latex kernel, outer curly braces in option values are lost during parsing. Indeed, the kernel's option parsing scheme doesn't recognize option values indicated with the equality sign. And the syntaxes (if not also the semantics) of \cptuse{latex3}, whose options parser is presumably more robust than that of \cptuse{latex2e}, calls for additional investment in time that may not be readily affordable to some users. +\lletter{M}{y motivation} for turning to the \pkgnoidx'{pcatcode} was to save myself the trouble of declaring category codes at the beginning of my packages. After spending some time on the \pkgnoidx'{pcatcode}, I discovered I had learnt enough to make changes and additions to some of its macros and functionality. After completing the catcode stuff in the \pkg'{catoptions}, I wanted to pass options to the package. If the package is to be loaded on top of other packages, as intended, then its options parsing scheme should be independent of other packages. But realizing the trouble with passing expandable option values to packages and classes via the \latex kernel's scheme, I decided to implement modifications to the kernel's options parser. Apart from the problem of premature expansion of options and values by the \latex kernel, outer curly braces in option values are lost during parsing. Indeed, the kernel's option parsing scheme doesn't recognize option values indicated with the equality sign. \docsection(sec:pkg-options)<Package options>{Package options} -The \pkg'{catoptions} has the options shown in \cref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to put information onto the log file when existing commands are being redefined by means of, say, the command \fx{\robust@redef} (which has the same syntax with \tex's legacy \hx{\def}). 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 \cref{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 @@ -115,7 +115,7 @@ to see the current catcode setup. The command \fx{\cptfutureletsetup} is describ \RequirePackage[verbose, usepox]{catoptions} \UseNormalCatcodes \finish{example} -%\fxi*{\UseNormalCatcodes} +\dummyfxi*{\UseNormalCatcodes} \docsection(sec:future-letting){Future-letting of \headq{other} characters} @@ -129,7 +129,7 @@ slash|R(/) colon|R(:) semicolon|R(;) less|R(<) equal|R(=) greater|R(>) question| rbracket|R(]) hat|R(^) underscore|R(_) lquote|R(`) lbrace|R({) vert|R(|rv) rbrace|R(}) tilde|R(~) bslash|R(\) \finish{example} -%\fxim*{\cptfutureletsetup} +\dummyfxim*{\cptfutureletsetup} However, for efficiency reasons, the canonical control sequences will be defined for only the characters (or their names) appearing in the user-supplied list \fx{\declarefutureletset}, whose syntax is @@ -196,7 +196,7 @@ where \quotedtt{all} means that control sequences should be defined for all the This will yield control sequences that may never be needed. While such a facility does exist, using it will be inefficient despite the large capacities of many modern text engines. -The use syntaxes for the commands \xfnn\bs{{stub}{char}} and \xfnn\bs{{if}{stub}{char}} are as follows: +The use syntaxes for the commands \fnl{{stub}{char}} and \fnl{{if}{stub}{char}} are as follows: \start{example}[Futurelet characters] \futurelet\next\cmd |textbf(|R(*)) @@ -204,7 +204,7 @@ The use syntaxes for the commands \xfnn\bs{{stub}{char}} and \xfnn\bs{{if}{stub} \def\cmd{\iffl@star\next{`I saw star'}{`I didn't see star'}} \finish{example} -Notice that \fx{\ifx\fl@comma\next} is a conventional \tex test, while \fx{\iffl@...} expects two \latex branches (\ffx'{\@firstoftwo,\@secondoftwo}). It may be argued that these commands are needlessly too many and may be defined by means of only two macros. That would appear a valid point, but the commands are meant to be easy to recall and use. If, for example, you are testing for the presence of \fx{\tilde}, you simply do \fx{\iffl@tilde\next{...}{...}}, assuming a \ang{stub} of \fx{fl@}. +Notice that \fx{\ifx\fl@comma\next} is a conventional \tex test, while \fx{\iffl@...} expects two \latex branches (\ffx'{\@firstoftwo,\@secondoftwo}). The commands are meant to be easy to recall and use. If, for example, you are testing for the presence of \fx{\tilde}, you simply do \fx{\iffl@tilde\next{...}{...}}, assuming a \ang{stub} of \fx{fl@}. After setting up \fx{\futurelet} characters with \fx{\cptfutureletsetup}, you can reset active characters to catcode~13 by \fx{\futureletresetactives}. @@ -227,7 +227,7 @@ $Id: mypackage.sty,v 0.1 2011/01/01 09:00:00 My Name Exp $ \finish{newmacro} \fxim*{\SetStyleFileMessages} -Here, \ang{stub} is an optional prefix for the three package messages described below. The default value of \ang{stub} is the first three characters of the package or class name (\hx{\@currname}) concatenated with the \quoted{at} sign \quoted{\fx{@}}. The mandatory arguments \ang{err}, \ang{warn}, and \ang{info} are the suffices for the package error, warning and information messages, respectively. +Here, \ang{stub} is an optional prefix for the three package messages described below. The default value of \ang{stub} is the first three characters of the package or class name (\hx{\@currname}) concatenated with the \quoted{at} sign \quotedfx{@}. The mandatory arguments \ang{err}, \ang{warn}, and \ang{info} are the suffices for the package error, warning and information messages, respectively. For instance, with the declaration @@ -260,18 +260,18 @@ 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. \start{newmacro}[\XDeclareOption] -\XDeclareOption<|nang(fam)>{|nang(option)}[|nang(default)]{|nang(fn)} +\XDeclareOption<|nang(fam)>{|nang(opt)}[|nang(default)]{|nang(fn)} \XDeclareOption|*<|nang(fam)>{|nang(fn)} \finish{newmacro} \fxim*{\XDeclareOption} -The \unstform of the macro \fx{\XDeclareOption} declares an option that can be used as a package or class option and executed by \fx{\XExecuteOptions} or \fx{\XProcessOptions}. This macro is similar to the standard \latex macro \hx{\DeclareOption}, but with this command the user can pass a value to the option as well. That value can be accessed by using \fx{#1} or \fx{\currval} in \ang{fn}. This will contain \ang{default} when no value has been specified for the option. The default value of the optional argument \ang{default} is empty. This implies that when the user does not assign a value to \ang{option} and when no default value has been defined, no error message will ensue. The optional argument \ang{fam} can be used to specify a unique family for the option. When the argument is not used, the macro will insert the default family name (namely, \fx{\@currname.\@currext}). The current option name is available in \fx{\curropt}. +The \unstform of the macro \fx{\XDeclareOption} declares an option that can be used as a package or class option and executed by \fx{\XExecuteOptions} or \fx{\XProcessOptions}. This macro is similar to the standard \latex macro \hx{\DeclareOption}, but with this command the user can pass a value to the option as well. That value can be accessed by using \fx{#1} or \fx{\currval} in \ang{fn}. This will contain \ang{default} when no value has been specified for the option. The default value of the optional argument \ang{default} is empty. This implies that when the user does not assign a value to \ang{opt} and when no default value has been defined, no error message will ensue. The optional argument \ang{fam} can be used to specify a unique family for the option. When the argument is not used, the macro will insert the default family name (namely, \fx{\@currname.\@currext}). The current option name is available in \fx{\curropt}. \start{example}[\XDeclareOption] \ProvidesPackage{mypackage}[\StyleFileInfo] \newif\ifmybool \XDeclareOption{mybool}[true]{\@nameuse{mybool#1}} -\XDeclareOption{leftmargin}[.5\hsize]{\setlength\leftmargin{#1}} +\XDeclareOption{leftmargin}[.5\hsize]{\setlength\leftmargin{#1}}|xwmlabel(mac:leftmargin) \finish{example} The options \ffx'{mybool,leftmargin} could then be called via any of the following statements: @@ -285,82 +285,162 @@ The options \ffx'{mybool,leftmargin} could then be called via any of the followi \documentclass[mybool,leftmargin=20\p@]{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. 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. +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. + + +\start{newmacro}[\XUnknownOptionHandler] +\XUnknownOptionHandler<|nang(fams)>[|nang(na)]{|nang(handler)} +\finish{newmacro} +\fxim*{\XUnknownOptionHandler} + +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}. \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] +define/.code=|nang(callback) +\finish{example} +\fxim*{define/.code} + +then the unknown option \fx{\cpt@curropt} 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}. You can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{callback} to refer to the current option family, option name, and option value, respectively. -The following example produces a warning when the user supplies an option that was not previously declared. +If \fx{\cpt@currval} is \hx{true} or \hx{false}, the new (\ie, unknown) 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}.) Note that the token \quoted{define} in the above syntax is not escaped. +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>{% + \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|*{\PackageWarningNoLine{mypackage}{Unknown option - `\CurrentOption' ignored}} +\XDeclareOption|*{\PassOptionsToClass{#2=#3}{article}} \finish{example} +The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the call-back shown. + +\start{example}[\XUnknownOptionHandler] +\XUnknownOptionHandler<mypackage>{% + define/.code=\def\x##1{##1\relax `option #2 = value #3' in family `#1'}% + \PackageWarningNoLine{mypackage}{Unknown option `#2' of family `#1' defined}% +} +\finish{example} + +If no default family handler has been provided by the user (through the macro \XDecS or \fx{\XUnknownOptionHandler}) for an undeclared option, and the option doesn't appear in the list \fx{\ExternalOptions}, then that option will be logged (\ie, entered in the transcript file) as undefined at the end of the document. By default, \fx{\ExternalOptions} contains all \hhx'{article,report,memoir} class options. The user can update the \fx{\ExternalOptions} list by means of the following commands: + +\start+{newmacro}[\AddToExternalOptions,\RemoveFromExternalOptions] +\AddToExternalOptions{|nang(opts)} +\RemoveFromExternalOptions{|nang(opts)} +\finish{newmacro} +\fxim*{\ExternalOptions,\AddToExternalOptions,\RemoveFromExternalOptions} + +where \ang{opts} are the comma-separated option names to be added to, or removed from, the list. + \start{newmacro}[\XDeclareOptions] -\XDeclareOptions<|nang(fam)>{|nang(options)}[|nang(default)]{|nang(fn)} +\XDeclareOptions<|nang(fam)>{|nang(opts)}[|nang(default)]{|nang(fn)} \finish{newmacro} \fxim*{\XDeclareOptions} -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{options}. Each option in the list \ang{options} 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. +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} \start{newmacro}[\XDeclareCommandOption] -\XDeclareCommandOption<|nang(fam)>{|nang(option)}[|nang(default)]|(pref|){|nang(fn)} +\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{option}, also create a macro \fnn{{pref}{option}} 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 \quoted{\fx{\@currname @}} prefixed with the letters \fx{cmd}. +The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl{{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(options)}[|nang(default)]|(pref|){|nang(fn)} +\XDeclareCommandOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} \finish{newmacro} \fxim*{\XDeclareCommandOptions} -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{options}. Each option in the list \ang{options} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. - +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}. \start{newmacro}[\XDeclareBooleanOption] -\XDeclareBooleanOption<|nang(fam)>{|nang(option)}[|nang(default)]|(pref|){|nang(fn)} +\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{option}, also create a boolean \fnn{{if}{pref}{option}}. 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 \quoted{\fx{\@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{{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(options)}[|nang(default)]|(pref|){|nang(fn)} +\XDeclareBooleanOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} \finish{newmacro} \fxim*{\XDeclareBooleanOptions} -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{options}. Again, each option in the list \ang{options} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. - +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}. \start{newmacro}[\XDeclareBiBooleanOptions] -\XDeclareBiBooleanOptions<|nang(fam)>{|nang(opt1),|nang(opt2)}[|nang(default)]|(pref|){|nang(fn1)}{|nang(fn2)} +\XDeclareBiBooleanOptions<|A(fam)>{|A(opt1),|A(opt2)}[|A(default)]|(|A(pref)|){|A(fn1)}{|A(fn2)} \finish{newmacro} \fxim*{\XDeclareBiBooleanOptions} 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. - \start{newmacro}[\XExecuteOptions] -\XExecuteOptions<|nang(fam)>{|nang(options)} +\XExecuteOptions<|nang(fams)>{|nang(opts)}[|nang(na)] \finish{newmacro} \fxim*{\XExecuteOptions} -The re-entrant \fx{\XExecuteOptions} macro sets options created by \fx{\XDeclareOption} and is basically a means of setting up the default values of the options. The optional argument \ang{fam} can be used to specify a list of families that define the options. When the argument is not used, the macro will insert the default family name (\fx{\@currname.\@currext}). This macro will not use the declaration done by \fx{\XDeclareOption}\RedStar when undeclared options appear in its argument. Instead, in this case the macro will issue a warning and ignore the option. This differs from the behavior of \latex's \hx{\ExecuteOptions}. +The re-entrant \fx{\XExecuteOptions} macro sets options created by \fx{\XDeclareOption} and is basically a means of setting up the default values of the options. The optional argument \ang{fams} can be used to specify a list of \emph{families} that define the options. When the argument is not used, the macro will insert the default family name (\fx{\@currname.\@currext}). The set \ang{na} is the list of keys to be ignored (\ie, not executed if they appear in \ang{opts}). + +This macro will not use the declaration done by \XDecS when undeclared options appear in its argument. Instead, in this case the macro will issue a warning and ignore the option. This differs from the behavior of \latex's \hx{\ExecuteOptions}. \start{example}[\XExecuteOptions] \XExecuteOptions{leftmargin=0pt} \finish{example} -%\fxi*{\XExecuteOptions} +\dummyfxi*{\XExecuteOptions} -This initializes \hx{\leftmargin} to 0pt. +This initializes the option \hx{\leftmargin} of \macref{mac:leftmargin} to 0pt. \start{newmacro}[\XProcessOptions] -\XProcessOptions<|nang(fam)>[|nang(na)] -\XProcessOptions|*<|nang(fam)>[|nang(na)] +\XProcessOptions<|nang(fams)>[|nang(na)] +\XProcessOptions|*<|nang(fams)>[|nang(na)] \finish{newmacro} \fxim*{\XProcessOptions} -The re-entrant \fx{\XProcessOptions} macro processes the options and values passed by the user to the class or package. The optional argument \ang{fam} can be used to specify the 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 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. @@ -380,6 +460,9 @@ The implementation here differs significantly from the \latex kernel's scheme of \@nameuse{boola#1}% \ifboola\let\eat\@gobble\fi } +\XDeclareOptions<testclass>{opta,optb}[true]{% + \def\alloptsfunc##1{\def\tempa{##1}}% +} |com(No need for \newif when declaring boolean options:) \XDeclareBooleanOption<testclass>{boolb}[true]|(test@|){% \iftest@boolb @@ -388,18 +471,14 @@ The implementation here differs significantly from the \latex kernel's scheme of } \XDeclareBiBooleanOptions{draft,final}[true](test@){}{} \XDeclareCommandOption<testclass>{color}[blue]|(test@|){% - \def\text{\textcolor{\test@color}{Result of test}}% + Load `color' package } +|com(Disable option `color' at \AtBeginDocument:) +\XDisableOption|*<testclass>{color} \XDeclareOption<testclass>{align}[left]{% - \ifstrcmpTF{#1}{left}{% - \let\align\raggedright - }{% - \ifstrcmpTF{#1}{right}{% - \let\align\raggedleft - }{% - \ifstrcmpTF{#1}{center}{% - \let\align\centering - }{% + \ifstrcmpTF{#1}{left}{\let\align\raggedright}{% + \ifstrcmpTF{#1}{right}{\let\align\raggedleft}{% + \ifstrcmpTF{#1}{center}{\let\align\centering}{% \@latex@error{Invalid value `#1' for align}{% You have issued an illegal value `#1' for the variable `align'. }% @@ -407,11 +486,16 @@ The implementation here differs significantly from the \latex kernel's scheme of }% }% } -\XDeclareOption*<testclass>{\PassOptionsToClass{\CurrentOption}{article}} +\XDeclareInvalidOption<testclass>{deadoption} +\XDeclareOption|*<testclass>{% + define/.code=\PassOptionsToClass\CurrentOption{article}% +} \XExecuteOptions<testclass>{boola,boolb} -\XProcessOptions*<testclass>\relax +\XProcessOptions|*<testclass>\relax \LoadClass{article} -\RequirePackage{xcolor} +\cptloadpackages{% + |nang(pkg name)|rv|nang(pkg opts)|rv|nang(pkg date)|R(;)...|R(;)|nang(more packages) +} \endinput |com(This is a sample document:) @@ -435,6 +519,40 @@ The implementation here differs significantly from the \latex kernel's scheme of \end{document} \finish{example} +\start{newmacro}[\ifoptdefTF] +\ifoptdefTF<|nang(fams)>{|nang(opt)}{|nang(true)}{|nang(false)} +\ifoptdefFT<|nang(fams)>{|nang(opt)}{|nang(false)}{|nang(true)} +\finish{newmacro} +\fxim*{\ifoptdefTF} + +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}. + + +\start{newmacro}[\XDisableOptions] +\XDisableOptions<|nang(fams)>{|nang(opts)} +\XDisableOptions|*<|nang(fams)>{|nang(opts)} +\finish{newmacro} +\fxim*{\XDisableOptions} + +The command \fx{\XDisableOptions} disables all the options in the list \ang{opts} that can be found in the families \ang{fams}, \ie, it makes the options invalid thereafter. If any of the options in the list \ang{opts} can't be found in the families \ang{fams}, it is simply ignored without warning: since families can be mixed in \ang{fams}, it wouldn't be meaningful issuing several warnings in this case. + +The \stform of \fx{\XDisableOptions} delays the invalidation of the \ang{opts} until the invocation of \hx{\AtBeginDocument}. 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}. + +\start{newmacro}[\XLogDisabledOptions] +\XLogDisabledOptions<|nang(fams)> +\finish{newmacro} +\fxim*{\XLogDisabledOptions} + +The command \fx{\XLogDisabledOptions}, which can be called before and after 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. + \docsection(sec:normalize)<Normalizing lists>{Normalizing csv and kv lists} @@ -480,17 +598,19 @@ The command \fx{\kv@@normalize} normalizes a list of key-value pairs, returning \docsection(csv-kv-parse)<Parsing lists>{Parsing csv and kv lists} -\start{newmacro}[\csv@@parse,\kv@@parse] +\start+{newmacro}[\csv@@loop,\csv@@parse,\kv@@parse] +\csv@@loop[|nang(parser)][|nang(list)] +\csv@@loop|*[|nang(parser)][|nang(listcmd)] \csv@@parse[|nang(parser)][|nang(list)] \csv@@parse|*[|nang(parser)][|nang(listcmd)] \kv@@parse[|nang(parser)][|nang(list)] \kv@@parse|*[|nang(parser)][|nang(listcmd)] \finish{newmacro} -\fxim*{\csv@@parse,\kv@@parse} +\fxim*{\csv@@parse,\kv@@parse,\csv@@loop} -The macros \ffx'{\csv@@parse,\kv@@parse} call \ffx'{\csv@@normalize, \kv@@normalize}, respectively. The macro \fx{\csv@@parse} is meant for general csv-list processing with an arbitrary parser, while the command \fx{\kv@@parse} is designed for processing key-value lists. The macros \ffx'{\csv@@parse,\kv@@parse} loop over a given \ang{parser}-separated \ang{list} and execute the user-defined, parametered commands \ffx'{\csv@do,\kv@do}, respectively, for every item in the list, passing the item as an argument and preserving outer braces. +The macros \ffx'{\csv@@parse,\kv@@parse} (and their \stform+) call \ffx'{\csv@@normalize, \kv@@normalize}, respectively. On the other hand, the macro \fx{\csv@@loop} and its \stform don't call \fx{\csv@@normalize} (since not every list will require normalization). This is the only difference between \fx{\csv@@loop} and \fx{\csv@@parse}. The macros \fx{\csv@@loop} and \fx{\csv@@parse} are meant for general csv-list processing with an arbitrary parser, while the command \fx{\kv@@parse} is designed for processing key-value lists. These macros loop over a given \ang{parser}-separated \ang{list} and execute the user-defined, one-parameter commands \ffx'{\csv@do,\kv@do}, respectively, for every item in the list, passing the item as an argument and preserving outer braces. -The commands \ffx'{\csv@@parse,\kv@@parse} aren't expandable. White spaces before and after the list separator are always ignored. If an item contains \ang{parser} or starts with a space, it must be wrapped in curly braces. The braces will persist thereafter, but will of course be removed during printing (if the items are printed). The default value of \ang{parser} is comma (\qcomma). +The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@parse} aren't expandable. White spaces before and after the list separator are always ignored. If an item contains \ang{parser} or starts with a space, it must be wrapped in curly braces. The braces will persist thereafter, but will of course be removed during printing (if the items are printed). The default value of \ang{parser} is comma (\qcomma). The starred variants of \ffx'{\csv@@parse,\kv@@parse} expand \ang{listcmd} once before commencing the loop. @@ -547,17 +667,44 @@ fi \finish{example} +\docsection(tsv-parse)<Iterating tokenwise>{Parsing \headq{tsv} lists} + +\start+{newmacro}[\tsv@@parse,\tsv@@loop] +\tsv@@loop[|nang(list)] +\tsv@@loop|*[|nang(listcmd)] +\tsv@@parse[|nang(list)] +\tsv@@parse|*[|nang(listcmd)] +\finish{newmacro} +\fxim*{\tsv@@parse,\tsv@@loop} + +The macros \ffx'{\tsv@@loop,\tsv@@parse} loop over \quoted{non-separated} tokens (tsv-list), picking each token as an argument and applying the one-parameter, user-supplied, function \fx{\tsv@do} to it while preserving outer braces in the item. The macros \ffx'{\tsv@@loop, \tsv@@parse} are meant for general tsv-list processing. + +The macros \ffx'{\tsv@@loop,\tsv@@parse} (and their \stform+) of course don't call \fx{\csv@@normalize} or \fx{\kv@@normalize}, but instead they trim leading and trailing spaces of individual tokens/entries. The only difference between \fx{\tsv@@loop} and \fx{\tsv@@parse} is that the former calls \fx{\normal@despace}, while the latter calls \fx{\robust@despace}. The function \fx{\robust@despace} trims all leading and trailing spaces (including chains of implicit spaces) around its argument, while \fx{\normal@despace} trims only one leading and one trailing space around its argument. Both \ffx'{\normal@despace,\robust@despace} preserve outer braces around their arguments. The expandable form of \fx{\normal@despace} is \fx{\xp@despace}. + +The starred variants of \ffx'{\tsv@@loop,\tsv@@parse} expand \ang{listcmd} once before commencing the loop. + +Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \fx{@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} before commencing the iteration. Both commands \ffx'{\tsv@@loop,\tsv@@parse} can be nested to any level and can be mixed. + + \docsection(sec:version-hist){Version history} 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.2b}{2011/04/02} + \item The following commands have been introduced \secref{sec:options-parse} + \start{veritem} + \XDeclareInvalidOptions \XUnknownOptionHandler \XDisableOptions + \XLogDisabledOptions \ifoptdisabledTF \ifoptdefTF + \finish{veritem} + + \end{version} \begin{version}{0.2}{2011/02/15} \item For efficiency reasons, canonical control sequences for futurelet characters are no longer defined automatically. The user is now responsible for specifying the canonical control sequences that should be defined.\secref{sec:future-letting} \item The following plural-form commands have been introduced \secref{sec:options-parse} \start{veritem} - \XDeclareOptions \XDeclareCommandOptions \XDeclareBooleanOptions - \XDeclareBiBooleanOptions + \XDeclareOptions \XDeclareCommandOptions + \XDeclareBooleanOptions \XDeclareBiBooleanOptions \finish{veritem} \end{version} diff --git a/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg b/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg index 1cc3526577b..4a0e466c07b 100644 --- a/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg +++ b/Master/texmf-dist/tex/latex/catoptions/catoptions-guide.cfg @@ -1,6 +1,5 @@ \ProvidesFile{catoptions-guide.cfg}% - [2011/02/21 v0.2 Definitions file for catoptions-guide.tex (AM)] - + [2011/03/10 v0.2b Definitions file for catoptions-guide.tex (AM)] \usepackage[printwatermark]{xwatermark} \usepackage{array} \usepackage{colortbl} @@ -12,12 +11,12 @@ showpagenos = true, showheadrule = true, showfootrule = false, - ycoord = -.45\paperheight, - xcoord = 0, - scale = 1.5, + ypos = -.45\paperheight, + xpos = 0, + scale = 1, angle = 0, lhead = {The \textcolor{maccolor}{catoptions} package}, - style = {Page~\thepage~of~\pageref{xwmlastpage}}, + style = {\textsc{Page~\thepage~of~\pageref{xwmlastpage}}}, rhead = \tcl{black}{\today} ] @@ -47,21 +46,19 @@ \newletcs\pucolor\makepurple \AtBeginDocument{\redef*\thefootnote{\fnsymbol{footnote}}} -%\dummywatermark \newwatermark -[page=1,fontfamily=phv,fontsize=11pt,fontseries=m,align=center, - coordunit=pc,width=\hsize,angle=0,scale=1.8,xcoord=0,ycoord=32.5] - {\fadingtext[textcolor=blue,boxcolor=red, - scale=1.8,letterwidth=7.8mm,height=1.5ex]{catoptions}\\[1ex] - \tcl{blue}{\resizebox{.5\width}{!}{Setting up - {\tt\string\futurelet} characters, restoring catcodes, +[page=1,fontfamily=phv,fontsize=11pt,fontseries=m,textalign=center, + 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 + {\tt\string\futurelet} characters, securing catcodes, and parsing options}}% } -%\dummywatermark \newwatermark -[page=1,fontfamily=phv,fontsize=10pt,fontseries=m,color=black,align=center, - coordunit=pc,width=\hsize,angle=0,scale=1,xcoord=0,ycoord=24]{% +[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, fonttype=\small]{% The \pkgnoidx'{pcatcode} functionality would work best if it were built into the diff --git a/Master/texmf-dist/tex/latex/catoptions/catoptions.sty b/Master/texmf-dist/tex/latex/catoptions/catoptions.sty index cbfc83ab3ca..328c96e7345 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, August 2010) % +% This is 'catoptions' package (Version 0.2b, March 2011) % % % % The catoptions package changes LaTeX package loading internals % % so that all subsequently loaded packages can rely on having % @@ -20,15 +20,15 @@ % % % The LPPL maintenance status of this software is 'author-maintained'. % % % -% Copyright (c) 2011 Ahmed Musa (a.musa@rocketmail.com). % +% Copyright (c) 2010-2011 Ahmed Musa (a.musa@rocketmail.com). % % % %+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \begingroup \chardef\%\catcode37\catcode37 14\relax\expandafter\iffalse\string\ -\fi\let\e\endlinechar\chardef\E\e\e13\chardef\n\catcode\e\catcode\e5 % -\chardef\s\catcode32 \catcode32 10 -\chardef\=\catcode61 \catcode61 12 +\fi\let\e\endlinechar\chardef\E\e\e13\chardef\n\catcode\e\catcode\e5% +\chardef\s\catcode32 \catcode32\string=10 +\chardef\=\catcode61 \catcode61\string=12 \chardef\l=\catcode123 \catcode123=1 \chardef\r=\catcode125 \catcode125=2 \chardef\[=\catcode91 \catcode91=12 @@ -73,7 +73,7 @@ } \x \catcode37 14\relax\expandafter\iffalse\string\ -\fi\endlinechar13\catcode13 5 % +\fi\endlinechar13\catcode13 5% \catcode61\string=12 \catcode32=10 \catcode123=1 @@ -84,12 +84,14 @@ \catcode47=12 \catcode94=7 \catcode126=13 -\chardef\cpt@xiipt=12 +\m@ne=-1\z@=0pt\p@=1pt +\newcount\cpt@mone\cpt@mone\m@ne +\chardef\cpt@xii=12 \chardef\active=13 -\chardef\cpt@xciipt=92 +\chardef\cpt@xcii=92 \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{catoptions} - [2011/02/021 v0.2 Preserving catcodes and parsing options (AM)] + [2011/03/10 v0.2b Securing catcodes and parsing options (AM)] \ifcase% \ifx\eTeXversion\cpt@undefined\z@\else \ifnum\eTeXversion<\tw@\z@\else\@ne\fi\fi @@ -97,6 +99,7 @@ {This package requires eTeX version 2 or later.}% \expandafter\endinput \fi +\def\cptloggingall{\loggingall\tracingifs\@ne} \def\cptnormalcatcodes{% \endlinechar13 \catcode33=12\catcode34=12\catcode35=6\catcode36=3\catcode37=14 @@ -115,15 +118,22 @@ \s\;\s\<\s\=\s\>\s\?\s\[\s\\\s\]\s\^\s\_\s\`\s\{\s\|\s\}\s\~% } \endgroup + \newcommand*\BeginOverlookWhiteSpace{% - \edef\cpt@spacecatcode{\the\catcode`\ }% - \edef\cpt@tabcatcode{\the\catcode`\^^I}% + \pushnumber\overlook@nr + \ifnum\overlook@nr>\@ne + \cpt@err{There is an unclosed + \string\BeginOverlookWhiteSpace}\@ehc + \fi + \chardef\cpt@spacecatcode=\number\catcode`\ % + \chardef\cpt@tabcatcode=\number\catcode`\^^I \chardef\cpt@endlinechar=\number\endlinechar \catcode`\ =9\relax \catcode`\^^I=9\relax \endlinechar\m@ne } \newcommand*\EndOverlookWhiteSpace{% + \popnumber\overlook@nr \catcode`\ =\cpt@spacecatcode \catcode`\^^I=\cpt@tabcatcode \endlinechar\cpt@endlinechar @@ -154,7 +164,7 @@ \newcommand*\GetCurrentCatcodeSubset{% \begingroup \def\x##1{% - \ifx##1\cpt@nnil\else + \ifx##1\@nnil\else \@space(\string##1\@firstofone{:\number\catcode`##1})% \expandafter\x \fi @@ -162,15 +172,32 @@ \edef\x{% \def\noexpand\currentcatcodesubset{% \x\^^I\^^J\^^L\^^M\ \!\"\#\$\%\&% - \'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\}\|\~\cpt@nnil + \'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\}\|\~\@nnil }% }% \expandafter\endgroup\x } +\newcommand*\setup@safe@actives@edef{% + \begingroup + \endlinechar\m@ne + \def\siso@do##1{\catcode`##1\string=\active}% + \simpleexpandarg\siso@@loop\cpt@otherchars + \gdef\safe@actives@edef##1##2{% + \begingroup + \def\siso@do####1{% + \ifnum\catcode`####1\string=\active\edef####1{\string####1}\fi + }% + \simpleexpandarg\siso@@loop\cpt@otherchars + \cptpassexpanded{% + \endgroup\edef\noexpand##1{\noexpand\unexpanded{##2}}% + }% + } + \endgroup +} \newcommand*\declarefutureletset[2][fl@]{% \xdef\cpt@fletprefix{\xp@despace{#1}}% - \cptexpandargonce - {\cpt@filtermergelists[,]\cpt@fletprefixes}\cpt@fletprefix{}% + \cptexpandargonce{\cpt@filtermergelists[,]\cpt@fletprefixes}% + \cpt@fletprefix\nofilter \ifblankTF{#2}{% \def\neededfutureletchars{}% }{% @@ -180,7 +207,7 @@ \def\neededfutureletchars{}% \def\cpt@tempa##1\@##2\@{% \ifx##1\end\else - \cptaddtocommalist\neededfutureletchars{##1}% + \cptgaddtolist\neededfutureletchars{##1}% \expandafter\cpt@tempa \fi }% @@ -199,8 +226,7 @@ \begingroup \edef\cpt@tempa{\noexpandcsn{\cpt@fletprefix#1}}% \edef\cpt@tempb{\noexpandcsn{if\cpt@fletprefix#1}}% - \xifinsetTF - {,\cptoxdetok\cpt@tempa,}{,\cptoxdetok\cptfutureletmacros,}{}{% + \if@sp@inlistTF,\cpt@tempa\cptfutureletmacros{}{% \xdef\cptfutureletmacros{% \ifcsnullTF\cptfutureletmacros{}% {\expandcsonce\cptfutureletmacros,}% @@ -208,10 +234,7 @@ }% }% \def\siso@do##1{\lccode`##1=`#2}% - \simplesisoloop{034678BCD}% - \lccode`\0=`#2\lccode`\3=`#2\lccode`\4=`#2\lccode`\6=`#2% - \lccode`\7=`#2\lccode`\8=`#2\lccode`\B=`#2\lccode`\C=`#2% - \lccode`\D=`#2% + \siso@@loop{034678BCD}% \ifnum\catcode`#2=\active \def\do##1{\noexpand\do\noexpand##1\noexpand}% \lowercase{% @@ -247,27 +270,27 @@ \gdef\cpt@activecharacters{}% \gdef\cptfutureletmacros{}% \def\cpt@flet@b##1\@##2\@{% - \ifx##1\end\else - \xifinsetFT{##1}\neededfutureletchars{}{% + \ifxTF##1\end{}{% + \if@sp@inlistFT,{##1}\neededfutureletchars{}{% \cpt@flet@a{##1}{##2}% }% - \expandafter\cpt@flet@b - \fi + \cpt@flet@b + }% }% - \def\fifo@do##1{% - \gundefcsn{##1\currentoption}% - \gundefcsn{if##1\currentoption}% + \def\comma@do##1{% + \gundefcsn{##1\curropt}% + \gundefcsn{if##1\curropt}% }% \def\cpt@fletundef##1\@##2\@{% - \ifx##1\end\else - \def\currentoption{##1}% - \simpleexpandarg\simplefifoloop{\cpt@fletprefixes}% - \expandafter\cpt@fletundef - \fi + \ifxTF##1\end{}{% + \def\curropt{##1}% + \simpleexpandarg\comma@@loop\cpt@fletprefixes + \cpt@fletundef + }% }% \def\cpt@fletdef##1\@##2\@{% \ifxTF##1\end{}{% - \xifinsetFT{##1}\neededfutureletchars{}{% + \if@sp@inlistFT,{##1}\neededfutureletchars{}{% \csn@xdef{if\cpt@fletprefix##1}####1{% \noexpand\usecsn{@\noexpand\ifx \noexpandcsn{\cpt@fletprefix##1}% @@ -284,14 +307,41 @@ } \AtBeginDocument{\cptrestorecatcodes} \gdef\futureletresetactives{% - \def\do##1##2{\let##1= ##2}% + \begingroup + \defpass\cpt@tempa##1{\endgroup + \def\do####1####2{\let####1=##1####2}% + }{ }% \cpt@activecharacters \let\do\relax } \endgroup -\@ifdefinable\UseNormalCatcodes\relax -\protected\def\UseNormalCatcodes{% +\newcommand*\ifcptcond[1]{% + \def\ifcptcond##1\fi##2##3{% + \romannumeral + ##1#1\expandafter\@firstoftwo\else + \expandafter\@secondoftwo\fi{0 ##2}{0 ##3}% + }% +} +\ifcptcond{ } +% \shell-def'ed macros don't have to be 'definable': +\@ifdefinable\shelldef{\protected\def\shelldef{\protected\def}} +\@ifdefinable\shelledef{\shelldef\shelledef{\protected\edef}} +% \shell-let macros must be 'definable': +\newcommand*\shelllet{} +\shelldef\shelllet#1#2{% + \ifcptcond\ifx\\#2\\\fi + {\@latex@error{Empty token for \string\shelllet}\@ehc}% + {\ifcptcond\expandafter\ifx\expandafter\\\@gobble#2\\\fi} + {\ifcptdefinable#1{\shelllet@a#1{#2}}}% + {\@latex@error{Multiple tokens '\detokenize{#2}'}\@ehc}% +} +\newcommand*\shelllet@a[2]{% + \aftercsname\newletcs{rsv@@\cptremovescape#1}{#2}% + \shelledef#1{\cptmakecs{rsv@@\cptremovescape#1}}% +} +\newcommand*\UseNormalCatcodes{} +\shelldef\UseNormalCatcodes{% \ifcsnullTF\@currname{% \cpt@warn{\noexpand\UseNormalCatcodes issued in document: ignored}% @@ -301,50 +351,186 @@ \cptnormalcatcodes \AfterEndOfStyleFile{% \cptpopcatcodes - \let\UseNormalCatcodes\rc@UseNormalCatcodes + \let\UseNormalCatcodes\rsv@UseNormalCatcodes }% }% } -\@ifdefinable\rc@UseNormalCatcodes{% - \global\let\rc@UseNormalCatcodes\UseNormalCatcodes +\newcommand*\rsv@UseNormalCatcodes{} +\global\let\rsv@UseNormalCatcodes\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@ne% +\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 +%\traceon +\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 + \newcommand\cptswap[2]{#2#1} \newcommand\cptswapfirstbraced[2]{#2{#1}} +\newcommand\cptswapsecondbraced[2]{{#2}#1} \cptswap{ }{\let\@sptoken= } \def\@space{ } \newcommand\usecsn[1]{\csname#1\endcsname}% long \newcommand\gusecsn[1]{\global\csname#1\endcsname} \newcommand\cptuse[1]{\ifcsndefFT{#1}{}{\usecsn{#1}}} +\newcommand\uselivecs[1]{% + \ifdefTF{#1}{#1}{% + \cpt@err{Command 'string#1' undefined}\@ehc + }% +} +\newcommand\uselivecsn[1]{% + \ifcsndefTF{#1}{% + \usecsn{#1}% + }{% + \let\relax\relax + \cpt@err{Command '\@backslashchar#1' undefined}\@ehc + }% +} \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} -\protected\def\cpt@nil{} -\def\cpt@nnil{\cpt@nil} -\protected\def\cpt@unique{\cpt@unique} +\newcommand*\newsentinel[1]{% + \@ifdefinable{#1}{\protected\edef#1{\string#1}}% +} +\newcommand*\ifsentinelTF[2]{% + \begingroup + \def#2{#2}% + \expandafter\endgroup + \ifx#1#2\expandafter\@firstoftwo\else + \expandafter\@secondoftwo\fi +} +\newcommand*\ifsentinelFT[2]{% + \ifsentinelTF{#1}{#2}\@secondoftwo\@firstoftwo +} +\newsentinel\cpt@nil \long\def\cpt@car#1#2\car@nil{#1} \long\def\cpt@cdr#1#2\cdr@nil{#2} \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} -\@ifdefinable\cpt@rnm{\let\cpt@rnm\romannumeral} -\def\cptthreexp{\expandafter\expandafter\expandafter} -\def\cptsevenxp{\expandafter\expandafter\expandafter +\newcommand*\remove@to@sentinel[2]{% + \begingroup + \defpass\cpt@tempa##1#1#2{% + \endgroup\remainder@do{##1}% + }% +} +\newcommand*\cptthreexp{\expandafter\expandafter\expandafter} +\newcommand*\cptsevenxp{\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter\expandafter} -\protected\def\cptlocalxp#1{\begingroup\cptthreexp\endgroup#1} -\protected\def\cptlocalxpxp{\cptlocalxp\expandafter} +\shelldef\cptlocalxp#1{\begingroup\cptthreexp\endgroup#1} +\shelldef\cptlocalxpxp{\cptlocalxp\expandafter} \newcommand*\cptzapspaces[1]{% - \def\cptzapspaces##1{\cpt@rnm0\cpt@zapspaces.\@space##1#1\cpt@nil}% + \def\cptzapspaces##1{% + \romannumeral0\cpt@zapspaces.\@space##1#1\zap@nil + }% } \cptzapspaces{ } -\def\cpt@zapspaces#1 #2\cpt@nil{% - \usecsn{@\ifx\cpt@unique#2\cpt@unique first\else second\fi oftwo}% +\long\def\cpt@zapspaces#1 #2\zap@nil{% + \usecsn{@\ifx\\#2\\first\else second\fi oftwo}% {\remove@to@dot#1}{% \expandafter\cpt@zapspaces\expandafter - .\remove@to@dot#1#2\cpt@nil + .\remove@to@dot#1#2\zap@nil + }% +} +\newcommand*\cptdotimes[1]{% + \ifblankTF{#1}{% + \if@boolTF{cpt@useempty}{\cpt@dotimes{m}}\@gobble + }{% + \expandafter\cpt@dotimes\expandafter + {\romannumeral\number#1000}% + }% +} +\newcommand*\cpt@dotimes[2]{% + \ifnullTF{#1}{}{% + #2\relax + \expandafter\ifnullTF\expandafter{\@gobble#1}{}{% + \expandafter\cpt@dotimes\expandafter{\@gobble#1}{#2}% + }% + }% +} +\newcommand*\cptexpandtimes[1]{% + \expandafter\cpt@expandtimes\expandafter + {\romannumeral\number#1000}% +} +\newcommand*\cpt@expandtimes[2]{% + \ifnullTF{#1}{% + \unexpanded{#2}% + }{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% + \unexpanded\expandafter{#2}% + }{% + \expandafter\cptswapfirstbraced\expandafter{#2}% + {\expandafter\cpt@expandtimes\expandafter{\@gobble#1}}% + }% + }% +} +\newcommand*\normal@reverse[1]{\cpt@normalreverse{}#1\@nnil} +\long\def\cpt@normalreverse#1#2{% + \ifxTF#2\@nnil{% + \if@boolTF{@test}\@iden\unexpanded{#1}% + }{% + \cpt@normalreverse{#2#1}% + }% +} +\newcommand*\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{% + \if@boolTF{@test}\@iden\unexpanded{#1}% + }{% + #2{\cpt@robustreverse{{#3}#1}}{\cpt@robustreverse{#3#1}}.% }% } \newcommand*\ifpdfstrcmpTF[2]{% @@ -352,57 +538,166 @@ {\detokenize{#2}}=\z@ first\else second\fi oftwo}% } \@ifdefinable\kernel@for{\let\kernel@for\@for} -\newcommand*\newvariables[1]{\@testopt{\cpt@newvariables{#1}}{}}% -\protected\def\cpt@newvariables#1[#2]#3{% +\newcommand*\IfCommandsDefinable[1]{% + \@testopt{\cpt@ifcmdsdefinable#1}{}% +} +\def\cpt@ifcmdsdefinable#1[#2]{% + \kernel@for\cpt@tempa:=\noexpand#1\do{% + \edef\cpt@tempa{% + \unexpanded\expandafter{% + \ifnum0=0\expandafter\noexpand\cpt@tempa}\fi + }% + \expandafter\@ifdefinable\cpt@tempa{#2}% + }% +} +\IfCommandsDefinable{\normal@despace,\robust@despace,\xp@despace, + \despace@cs,\despacecontent,\robdespacecontent,\despacecsvlist, + \robdespacecsvlist,\newvariables}[\relax] +\def\cpt@tempa#1{% + \shelldef\normal@despace##1##2{% + \edef##2{% + \unexpanded\expandafter{\romannumeral-`\q + \cpt@normaldespace.##1\despace@nil#1\despace@nil}% + }% + }% + \def\cpt@normaldespace##1#1\despace@nil{% + \cpt@norm@ldespace##1\despace@nil + }% + \def\cpt@norm@ldespace##1\despace@nil##2{% + \expandafter\noexpand\@gobble##1% + }% + \def\xp@despace##1{% + \cpt@xpdespace.##1\despace@nil#1\despace@nil + }% + \def\cpt@xpdespace##1#1\despace@nil{% + \cpt@xpd@space##1\despace@nil + }% + \def\cpt@xpd@space##1\despace@nil##2{% + \unexpanded\expandafter{% + \ifnum0=0\expandafter\noexpand\@gobble##1}\fi + }% +} +\cpt@tempa{ } +\shelldef\robust@despace#1#2{% + \edef#2{\unexpanded{#1}}% + \let\despace@tempa#2% + \normal@despace{#1}#2% + \ifxTF#2\despace@tempa{% + \undefcs\despace@tempa + }{% + \expandafter\robust@despace\expandafter{#2}#2% + }% +} +\shelldef\despace@cs{\cpt@testst\cpt@despacecs} +\def\cpt@despacecs#1{% + \usecsn{\ifcpt@st rob\fi despacecontent}{#1}% +} +\shelldef\despacecontent#1{% + \expandafter\normal@despace\expandafter{#1}#1% +} +\shelldef\robdespacecontent#1{% + \expandafter\robust@despace\expandafter{#1}#1% +} +\shelldef\despacecsvlist{% + \chardef\despace@type\z@ + \cpt@testopt\cpt@despacecsvlist{,}% +} +\shelldef\robdespacecsvlist{% + \chardef\despace@type\@ne + \cpt@testopt\cpt@despacecsvlist{,}% +} +\def\cpt@despacecsvlist[#1]#2{% + \begingroup + \let\cpt@resb\@empty + \UseEmptyEntry + \ifnum\despace@type=\z@\let\do\normal@despace\else + \let\do\robust@despace\fi + \def\csv@do##1{% + \do{##1}\cpt@resa + \cptaddtolist*[#1]\cpt@resb\cpt@resa + }% + \csv@@loop*[#1]#2% + \let#2\cpt@resb + \exitgroupdef#2% + \undefcs\despace@type +} +\outer\shelldef\newvariables#1{\@testopt{\cpt@newvariables{#1}}{}} +\def\cpt@newvariables#1[#2]#3{% \@testopt{\cpt@newv@riables{#1}{#2}{#3}}{}% } -\protected\def\cpt@newv@riables#1#2#3[#4]{% - \def\cpt@rsvda##1{% - \ifx\cpt@unique#4\cpt@unique\def\cpt@tempc{##1}\else - \def\cpt@tempc{#4}\fi +\def\cpt@newv@riables#1#2#3[#4]{% + \def\cpt@resa##1{% + \ifx\noindent#4\noindent + \def\cpt@tempc{##1}\else\def\cpt@tempc{#4}\fi }% \edef\cpt@tempb{\ifpdfstrcmpTF{#1}{if}{if}{}}% - \kernel@for\cpt@tempa:=\cpt@rnm0\cptzapspaces{\@space#3}\do{% + \kernel@for\cpt@tempa:=\noexpand#3\do{% + \edef\cpt@tempa{% + \expandafter\xp@despace\expandafter{\cpt@tempa}% + }% \usecsn{@\ifcsname\cpt@tempb#2\cpt@tempa\endcsname first\else second\fi oftwo}% {% - \edef\reserved@a{\cpt@tempb#2\cpt@tempa}\@notdefinable + \edef\reserved@a{\cpt@tempb#2\cpt@tempa}% + \@notdefinable }{% - \csname new#1\expandafter\endcsname\csname - \cpt@tempb#2\cpt@tempa\endcsname + \ifpdfstrcmpTF{#1}{togsw}{% + \v@true + \ifcsndefTF{cpt@togsw@#2\cpt@tempa}{% + \cpt@err{Toggle switch '#2\cpt@tempa' already defined}\@ehc + }{% + \cpt@gettogswstate{#4}% + \letcsntocs{cpt@togsw@#2\cpt@tempa}\cpt@togswstate + }% + }{% + \v@false + \csname new#1\expandafter\endcsname\csname + \cpt@tempb#2\cpt@tempa\endcsname + }% \ifpdfstrcmpTF{#1}{if}{% - \cpt@rsvda{false}% + \cpt@resa{false}% \csname#2\cpt@tempa\cpt@tempc\endcsname }{% \ifpdfstrcmpTF{#1}{toks}{% - \cpt@rsvda{}% + \cpt@resa{}% \csname#2\cpt@tempa\endcsname\expandafter{\cpt@tempc}% }{% \ifpdfstrcmpTF{#1}{box}{% - \cpt@rsvda\z@ + \cpt@resa\z@ \setbox\csname#2\cpt@tempa\endcsname\newboxtype - to\cpt@tempc{\newboxcontent}\relax + to\cpt@tempc{\newboxcontent}% }{% - \cpt@rsvda\z@ - \csname#2\cpt@tempa\endcsname\cpt@tempc\relax + \ifpdfstrcmpTF{#1}{count}{% + \cpt@resa\z@ + \csname#2\cpt@tempa\endcsname\cpt@tempc\relax + }{% + \ifpdfstrcmpTF{#1}{dimen}{% + \cpt@resa\z@ + \csname#2\cpt@tempa\endcsname\cpt@tempc\relax + }{% + \ifv@\else + \cpt@err{Unknown variable type '#1'}\@ehc + \fi + }% + }% }% }% }% }% }% } -\@ifdefinable\newboxtype{\let\newboxtype=\hbox} -\@ifdefinable\newboxcontent{\def\newboxcontent{}} -\newvariables{if}[cpt@]{st,pl,pm,verbose,usepox,optf,igopt, - inpox,olddx}\relax -\newvariables{if}[@]{iscounter,breakloop,choicefd,useempty, - checklp,robdes}\relax -\newvariables{count}[cpt@]{depth,grouplevel,grouptype}\relax -\@ifdefinable\cptbreakloop{\let\cptbreakloop\@breaklooptrue} -\newcommand*\UseEmptyEntry{\global\@useemptytrue} -\newcommand*\DiscardEmptyEntry{\global\@useemptyfalse} -\newcommand*\UseRobustDespace{\global\@robdestrue} -\newcommand*\UseNormalDespace{\global\@robdesfalse} +\IfCommandsDefinable{\newboxtype,\newboxcontent}\relax +\let\newboxtype\hbox +\def\newboxcontent{} +\newvariables{if}[cpt@]{st,pl,pm,verbose,usepox,optfd, + igopt,inpox,olddx,in,check,breakloop,choicefd,useempty, + normalize,despace,robdespace,twincall,bibool}[false] +\newvariables{count}[cpt@]{depth,optdepth,grouplevel,grouptype}[\z@] +\@ifdefinable\cptbreakloop{\let\cptbreakloop\cpt@breaklooptrue} +\newcommand*\UseEmptyEntry{\global\cpt@useemptytrue} +\newcommand*\DiscardEmptyEntry{\global\cpt@useemptyfalse} +\newcommand*\UseRobustDespace{\global\cpt@robdespacetrue} +\newcommand*\UseNormalDespace{\global\cpt@robdespacefalse} \newcommand*\MsgBrk{\MessageBreak} \newcommand*\cptgetcatcode[1]{% \number @@ -420,19 +715,20 @@ -1\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi } \newcommand\cptremovescape[1]{% - \ifx\cpt@unique#1\cpt@unique + \ifx\noboundary#1\noboundary \expandafter\@gobble\else\expandafter\@iden\fi {\expandafter\@gobble\string#1}% } \newcommand\cptgobblescape[1]{% - \ifx\cpt@unique#1\cpt@unique + \ifx\noboundary#1\noboundary \expandafter\@gobble\else\expandafter\@iden\fi {\ifnum\escapechar>\@cclv\else - \ifnum\escapechar<\z@\else - \expandafter\expandafter - \csname @gobble\ifnum\escapechar=\@xxxii @space\fi - \cptthreexp\endcsname - \fi\fi + \ifnum\escapechar<\z@\else + \expandafter\expandafter + \csname @gobble\ifnum\escapechar=\@xxxii @space\fi + \cptthreexp\endcsname + \fi + \fi \string#1}% } \newcommand\ifnullTF[1]{% @@ -458,8 +754,10 @@ \newcommand\xifblankTF[1]{\cptexpandarg\ifblankTF{#1}} \newcommand\xifblankFT[1]{\cptexpandarg\ifblankFT{#1}} \newcommand*\ifdefTF[1]{% - \usecsn{@\ifdefined#1\ifx#1\relax second\else first\fi - \else second\fi oftwo}% + \usecsn{@\ifx\\#1\\second\else first\fi oftwo}% + {\usecsn{@\ifx#1\cpt@undefined second\else + \ifx#1\relax second\else first\fi\fi oftwo}}% + \@secondoftwo } \newcommand*\ifdefFT[1]{\ifdefTF{#1}\@secondoftwo\@firstoftwo} \newcommand*\oifdefTF[1]{\expandafter\ifdefTF\expandafter{#1}} @@ -479,13 +777,15 @@ \newcommand*\oifcsndefFT[1]{\expandafter\ifcsndefFT\expandafter{#1}} \newcommand*\xifcsndefTF[1]{\cptexpandarg\ifcsndefTF{#1}} \newcommand*\xifcsndefFT[1]{\cptexpandarg\ifcsndefFT{#1}} -\newcommand*\newletcs[2]{\ifcptdefinable{#1}{\let#1=#2}} \newcommand*\ifcptdefinable[2]{% \edef\reserved@a{\cptgobblescape#1}% \ifdefTF{#1}\@notdefinable{% \ifcsndefTF{end\reserved@a}\@notdefinable{#2}% }% } +\newcommand*\newletcs[2]{\ifcptdefinable{#1}{\let#1=#2}} +\newcommand*\newgletcs[2]{\ifcptdefinable{#1}{\global\let#1=#2}} +\newcommand*\cptglet{\global\let} \newcommand\cpt@def@[3]{% \ifcptdefinable#3{% \ifnullTF{#2}{}\protected @@ -493,7 +793,7 @@ }% } \ifcptdefinable\robust@def\relax -\protected\def\robust@def{\@star@or@long{\cpt@def@{}{p}}} +\shelldef\robust@def{\@star@or@long{\cpt@def@{}{p}}} \robust@def*\new@def{\@star@or@long{\cpt@def@{}{}}} \robust@def*\new@gdef{\@star@or@long{\cpt@def@{g}{}}} \robust@def*\robust@gdef{\@star@or@long{\cpt@def@{g}{p}}} @@ -511,26 +811,87 @@ }% \ifstrcmpTF{#1}{p}\protected\relax\l@ngrel@x\def#2% } +\robust@def*\maybe@def#1{\cpt@teststpm{\cpt@maybe@def{#1}}} +\robust@def*\cpt@maybe@def#1{% + \if@boolTF{cpt@st}\@firstoftwo{% + \if@boolTF{cpt@pm}\@firstoftwo\@secondoftwo + }\@gobble{\new@def#1}% +} +\robust@def*\fulllet{\@testtrue\cpt@fulllet} +\robust@def*\fullnewlet{\@testfalse\cpt@fulllet} +\robust@def*\cpt@fulllet#1#2{% + \normal@despace{#1}\cpt@tempa + \normal@despace{#2}\cpt@tempb + \cpt@fullleterr\cpt@tempa\cpt@tempb + \if@test + \cptthreexp\let\expandafter\cpt@tempa\cpt@tempb + \else + \cptthreexp\newletcs\expandafter\cpt@tempa\cpt@tempb + \fi + \oifdefFT\cpt@tempb{}{% + \ifcsndefTF{\expandafter\string\cpt@tempb}{% + \letcsntocsn{\expandafter\string\cpt@tempa} + {\expandafter\string\cpt@tempb}% + }{% + \ifcsndefFT{\expandafter\cptgobblescape\cpt@tempb\@space}{}{% + \letcsntocsn{\expandafter\cptgobblescape\cpt@tempa\@space} + {\expandafter\cptgobblescape\cpt@tempb\@space}% + \ifcsndefFT{\expandafter\string\cpt@tempb\@space}{}{% + \letcsntocsn{\expandafter\string\cpt@tempa\@space} + {\expandafter\string\cpt@tempb\@space}% + }% + }% + }% + }% +} +\new@def*\cpt@fullleterr#1#2{% + \simpleexpandarg\ifsingletokenTF{#1}{% + \simpleexpandarg\ifsingletokenTF{#2}{}{% + \cpt@err{Multiple or blank argument '\expandcsonce{#2}'}\@ehc + }% + }{% + \cpt@err{Multiple or blank argument '\expandcsonce{#1}'}\@ehc + }% +} +\robust@def*\cptletcsset#1{% + \def\comma@do##1{% + \oifblankTF{\@gobble##1}{}{\fulllet##1}% + }% + \comma@@loop{#1}% +} \new@def*\ifcounterTF#1{% - \ifstrcmpTF{\count}{#1}\@secondoftwo{% - \expandafter\cpt@ifcounter@a\meaning#1:\cpt@unique + \ifstrcmpTF\count{#1}\@secondoftwo{% + \expandafter\cpt@ifcounter@a\meaning#1:\noboundary }% } \edef\cpt@ifcounter@a#1#2{% - \def#1##1:##2\cpt@unique{#2##1\string\count\cpt@unique}% - \def#2##1\string\count##2\cpt@unique{\noexpand\ifblankTF{##1}}% + \def#1##1:##2\noboundary{#2##1\string\count\noboundary}% + \def#2##1\string\count##2\noboundary{\noexpand\ifblankTF{##1}}% } \cpt@ifcounter@a\cpt@ifcounter@a\cpt@ifcounter@b -\robust@def*\pushnumber#1{% - \ifdefTF#1{% - \edef#1{\the\numexpr#1+1}% - }{% - \let#1\@ne +% Can't be called \ifdimTF (=\ifdimcmpTF): +\new@def*\ifdimensionTF#1{% + \ifstrcmpTF\dimen{#1}\@secondoftwo{% + \expandafter\cpt@ifdimen@a\meaning#1:\noboundary }% } +\edef\cpt@ifdimen@a#1#2{% + \def#1##1:##2\noboundary{#2##1\string\dimen\noboundary}% + \def#2##1\string\dimen##2\noboundary{\noexpand\ifblankTF{##1}}% +} +\cpt@ifdimen@a\cpt@ifdimen@a\cpt@ifdimen@b +\robust@def*\pushnumeric#1{% + \usecsn{push\ifcounterTF#1{count}{numb}er}#1% +} +\robust@def*\popnumeric#1{% + \usecsn{pop\ifcounterTF#1{count}{numb}er}#1% +} +\robust@def*\pushnumber#1{% + \ifdefTF{#1}{\edef#1{\the\numexpr#1+1}}{\chardef#1\@ne}% +} \robust@def*\popnumber#1{% \ifdefTF#1{% - \ifnumTF#1=\z@{% + \ifnumcmpTF#1=\z@{% \let\relax\relax \cpt@err{Number '\string#1' is already 0}\@ehc }{% @@ -543,77 +904,90 @@ } \robust@def*\pushcounter#1{% \ifdefTF#1{% - \if@iscounter + \ifcounterTF#1{% \global\advance#1\@ne - \else - \ifcounterTF#1{% - \global\advance#1\@ne - }{% - \cpt@err{Number '\string#1' isn't a counter}\@ehc - }% - \fi + }{% + \cpt@err{Number '\string#1' isn't a counter}\@ehc + }% }{% \usecsn{newcount}#1% }% - \@iscounterfalse } \robust@def*\popcounter#1{% \ifdefTF#1{% - \ifnumTF#1=\z@{% + \ifnumcmpTF#1=\z@{% \cpt@err{Counter or number '\string#1' is already 0}\@ehc }{% - \if@iscounter - \global\advance#1\m@ne - \else - \ifcounterTF#1{% - \global\advance#1\m@ne - }{% - \cpt@err{Number '\string#1' isn't a counter}\@ehc - }% - \fi + \ifcounterTF#1{\global\advance#1\cpt@mone}{% + \cpt@err{Number '\string#1' isn't a counter}\@ehc + }% }% }{% \cpt@err{Counter '\string#1' is undefined}\@ehc }% - \@iscounterfalse } -\new@def*\push@rnarg#1{\expandafter\cptremovescape\push@arg @\cpt@rnm#1} +\new@def*\push@rnarg#1{% + \expandafter\cptremovescape\push@arg @\romannumeral#1% +} \robust@def*\pushfunctions#1#2{% - \ifcounterTF#2{% - \@iscountertrue\pushcounter#2% + \ifdefTF#2{% + \ifcounterTF#2{% + \global\advance#2\@ne + }{% + \xdef#2{\the\numexpr#2+1}% + }% }{% - \global\pushnumber#2% + \chardef#2\@ne }% - \def\push@@do{\letcsntocs{\push@rnarg{#2}}}% - \def\push@do{\expandafter\push@@do\push@arg}% - \let\rc@escapechar\escapechar\escapechar\cpt@xciipt + \def\push@do{% + \cptexpandsecondonce{\letcsntocs{\push@rnarg{#2}}}\push@arg + }% + \let\rsv@escapechar\escapechar\escapechar\cpt@xcii \pushingloop{#1}% - \escapechar\rc@escapechar + \escapechar\rsv@escapechar } \robust@def*\popfunctions#1#2{% - \ifnum#2=\z@ - \cpt@err{Number '\string#2' is currently '0'}\@ehc - \fi + \ifdefTF#2{% + \ifnum#2=\z@ + \cpt@err{Number '\string#2' is currently '0'}\@ehc + \fi + }{% + \cpt@err{Pop function with unknown number \string#2?}\@ehc + }% \def\push@do{% \expandafter\letcstocsn\push@arg{\push@rnarg{#2}}% \undefcsn{\push@rnarg{#2}}% }% - \let\rc@escapechar\escapechar\escapechar\cpt@xciipt + \let\rsv@escapechar\escapechar\escapechar\cpt@xcii \pushingloop{#1}% - \escapechar\rc@escapechar + \escapechar\rsv@escapechar \ifcounterTF#2{% - \@iscountertrue\popcounter#2% + \global\advance#2\cpt@mone }{% - \global\popnumber#2% + \xdef#2{\the\numexpr#2-1}% + }% +} +% Why separate \pushcsvinternals from \pushfunctions? +% There is a reason: +\robust@def*\pushcsvinternals#1#2{% + \def\push@do{% + \cptexpandsecondonce{\letcsntocs{\push@rnarg{#2}}}\push@arg }% + \pushingloop{#1}% +} +\robust@def*\popcsvinternals#1#2{% + \def\push@do{% + \expandafter\letcstocsn\push@arg{\push@rnarg{#2}}% + \undefcsn{\push@rnarg{#2}}% + }% + \pushingloop{#1}% } -\robust@def*\pushingloop#1{\cpt@pushingloop#1,\cpt@nil,} -\robust@def*\cpt@pushingloop#1,{% - \edef\push@arg{\unexpanded{#1}}% - \ifxTF\push@arg\cpt@nnil{}{% - \normal@despacecontent\push@arg - \push@do\relax\cpt@pushingloop +\robust@def*\pushingloop#1{% + \def\comma@do##1{% + \normal@despace{##1}\push@arg + \push@do\relax }% + \comma@@loop{#1}% } \robust@def*\cpt@toodeep#1#2{% \cpt@err{Command '\string#1' nested too deeply}% @@ -621,241 +995,163 @@ \MsgBrk to depth(s) higher than #2.}% \@gobble } -\robust@def*\oneDloop{% - \@robdestrue\cpt@ifstar\oneDloop@b\oneDloop@a -} -\robust@def*\normaloneDloop{% - \@robdesfalse\cpt@ifstar\oneDloop@b\oneDloop@a -} -\robust@def\oneDloop@b#1{\expandafter\oneDloop@a\expandafter{#1}} -\robust@def\oneDloop@a#1#2#3{% - \pushnumber\oneDloopdepth - \ifnum\oneDloopdepth>\@ne\cpt@toodeep\oneDloop1\fi - \@breakloopfalse - \cpt@Dloop@a#1,\cpt@nil,\cpt@unique#2{#3}% - \popnumber\oneDloopdepth - \UseNormalDespace -} -\robust@def*\xDloop{% - \@robdestrue\cpt@ifstar\xDloop@b\xDloop@a -} -\robust@def*\normalxDloop{% - \@robdesfalse\cpt@ifstar\xDloop@b\xDloop@a -} -\robust@def\xDloop@b#1{\expandafter\xDloop@a\expandafter{#1}} -\robust@def\xDloop@a#1#2#3{% - \pushfunctions - {#2,\if@useempty,\if@breakloop,\if@robdes}\cpt@depth - \@breakloopfalse - \cpt@Dloop@a#1,\cpt@nil,\cpt@unique#2{#3}% - \popfunctions - {#2,\if@useempty,\if@breakloop,\if@robdes}\cpt@depth - \UseNormalDespace -} -\robust@def*\cpt@Dloop@a{% - \if@boolTF{@breakloop}{% - \defpass\gobble@remainder##1\cpt@unique##2##3{}% - }{% - \cpt@Dloop@b.% - }% +\robust@def*\csv@@loop{% + \cpt@normalizefalse + \chardef\csv@kv@type\z@ + \cpt@teststoptb\cpt@csvkvparse } -\robust@def\cpt@Dloop@b#1,#2\cpt@unique#3#4{% - \edef#3{\expandcsonce{\remove@to@dot#1}}% - \ifxTF#3\cpt@nnil{}{% - \ifcsnullTF#3{% - \if@useempty#4\relax\fi - }{% - \usecsn{\if@robdes robust\else normal\fi - @despacecontent}#3% - #4\relax - }% - \cpt@Dloop@a#2\cpt@unique#3{#4}% - }% -} -\robust@def*\foreachitem{\cpt@testst\cpt@foreach} -\newcommand\cpt@foreach[4][,]{% - \pushfunctions - {#3,\if@useempty,\if@breakloop,\if@robdes}\cpt@depth - \@breakloopfalse - \ifcpt@st\let#3#2\else\edef#3{\unexpanded{#2}}\fi - \long\def\cpt@foreach@a{% - \if@boolTF{@breakloop}{% - \defpass\gobble@remainder####1\cpt@unique####2####3{}% +\robust@def*\csv@@parse{% + \cpt@normalizetrue + \chardef\csv@kv@type\z@ + \cpt@teststoptb\cpt@csvkvparse +} +\robust@def*\kv@@parse{% + \cpt@normalizetrue + \chardef\csv@kv@type\@ne + \cpt@teststoptb\cpt@csvkvparse +} +\newletcs\remainder@do\@gobble +\newsentinel\csv@nil +\newcount\csv@depth\csv@depth\cpt@mone +\newcommand\cpt@csvkvparse[2][,]{% + \if@boolTF{cpt@st}{\let\csv@arg#2}{\edef\csv@arg{\unexpanded{#2}}}% + \advance\csv@depth\@ne + \ifnumcmpFT\csv@depth>\z@{}{% + \pushcsvinternals{\csv@parse@a,\csv@parse@b,\csv@kv@do, + \ifcpt@useempty,\ifcpt@breakloop,\ifcpt@normalize, + \remainder@do}\csv@depth + }% + \letcstocsn\csv@kv@do{\ifnum\csv@kv@type=\z@ csv\else kv\fi @do}% + \ifdefTF\csv@kv@do{}{% + \cpt@err{'\string\csv@do' or '\string\kv@do' undefined}\@ehc + }% + \long\def\csv@parse@a{% + \if@boolTF{cpt@breakloop}{% + \defpass\cpt@tempa####1\csv@nil#1{\remainder@do{####1}}% }{% - \cpt@foreach@b.% + \csv@parse@b.% }% }% - \long\def\cpt@foreach@b##1#1##2\cpt@unique##3##4{% - \edef##3{\expandcsonce{\remove@to@dot##1}}% - \ifxTF##3\cpt@nnil{}{% - \ifcsnullTF##3{% - \if@useempty##4\relax\fi + \long\def\csv@parse@b##1#1{% + \edef\csv@arg{\expandcsonce{\@gobble##1}}% + \ifsentinelTF\csv@arg\csv@nil{}{% + \ifcsnullTF\csv@arg{% + \if@boolFT{cpt@useempty}{}{\csv@kv@do{}\relax}% }{% - \usecsn{\if@robdes robust\else normal\fi - @despacecontent}##3% - ##4\relax + \expandafter\csv@kv@do\expandafter{\csv@arg}\relax }% - \cpt@foreach@a##2\cpt@unique##3{##4}% + \csv@parse@a }% }% - \expandafter\cpt@foreach@a#3#1\cpt@nil#1\cpt@unique#3{#4}% - \popfunctions - {#3,\if@useempty,\if@breakloop,\if@robdes}\cpt@depth - \UseNormalDespace -} -\robust@def*\oneDfifo{\cpt@teststoptb\cpt@oneDfifo} -\robust@def*\cpt@oneDfifo[#1]#2{% - \declarefifoparser{#1}% - \pushnumber\oneDfifodepth - \ifnum\oneDfifodepth>\@ne\cpt@toodeep\oneDfifo1\fi - \let\on@currlevel\@secondoftwo - \@breakloopfalse - \begingroup - \if@boolTF{cpt@st}% - {\let\reserved@a#2}{\edef\reserved@a{\unexpanded{#2}}}% - \expandafter\endgroup\expandafter\cpt@fifoloop@a - \reserved@a#1\cpt@nil#1% - \popnumber\oneDfifodepth - \let\on@currlevel\rc@on@currlevel -} -\robust@def*\xDfifo{\cpt@teststoptb\cpt@xDfifo} -\robust@def*\cpt@xDfifo[#1]#2{% - \declarefifoparser{#1}% - \pushfunctions{\fifo@do,\if@breakloop,\if@useempty}\cpt@depth - \let\curr@level\cpt@depth - \@breakloopfalse - \begingroup - \if@boolTF{cpt@st}% - {\let\reserved@a#2}{\edef\reserved@a{\unexpanded{#2}}}% - \expandafter\endgroup\expandafter\cpt@fifoloop@a - \reserved@a#1\cpt@nil#1% - \popfunctions{\fifo@do,\if@breakloop,\if@useempty}\cpt@depth -} -\robust@def*\declarefifoparser#1{% - \protected\def\cpt@fifoloop@a{% - \if@boolTF{@breakloop}{% - \defpass\gobble@remainder####1\cpt@nil#1{}% - }{% - \cpt@fifoloop@b.% + \if@boolFT{cpt@normalize}{}{% + \ifcsnullTF\csv@arg{}{% + \cpt@sttrue + \usecsn{cpt@\ifnum\csv@kv@type=\@ne kv\else csv\fi normalize}% + [#1]\csv@arg }% }% - \protected\def\cpt@fifoloop@b##1#1{% - \edef\fifo@arg{\expandcsonce{\@gobble##1}}% - \ifxTF\fifo@arg\cpt@nnil{}{% - \ifcsnullTF\fifo@arg{% - \if@boolTF{@useempty}{\on@currlevel{}\fifo@do{}\relax}{}% - }{% - \cptexpandargonce{\on@currlevel{}\fifo@do}\fifo@arg\relax - }% - \cpt@fifoloop@a - }% + \cpt@breakloopfalse + \expandafter\csv@parse@a\csv@arg#1\csv@nil#1% + \ifnumcmpFT\csv@depth>\z@{% + \ifnum\csv@depth=\z@ + \global\let\remainder@do\@gobble + \gundefcs\csv@kv@do + \fi + }{% + \popcsvinternals{\csv@parse@a,\csv@parse@b,\csv@kv@do,\ifcpt@useempty, + \ifcpt@breakloop,\ifcpt@normalize,\remainder@do}\csv@depth + }% + \advance\csv@depth\cpt@mone +} +% Apart from \pushingloop and some simple jobs, \comma@@loop +% isn't necessary. \pushingloop can't use \csv@@loop, since +% \csv@@loop calls \pushingloop to push its internals: +\newsentinel\comma@nil +\robust@def*\comma@@loop#1{% + \pushnumber\comma@depth + \ifnum\comma@depth>\@ne\cpt@toodeep\comma@@loop1\fi + \cpt@commaloop#1,\comma@nil,% + \popnumber\comma@depth + \undefcs\comma@do +} +\robust@def*\cpt@commaloop#1,{% + \def\comma@arg{#1}% + \ifsentinelTF\comma@arg\comma@nil{}{% + \comma@do{#1}\relax\cpt@commaloop + }% +} +\robust@def*\tsv@@loop{% + \cpt@despacetrue\cpt@robdespacefalse + \cpt@testst\cpt@tsvparse@a +} +\robust@def*\tsv@@parse{% + \cpt@despacetrue\cpt@robdespacetrue + \cpt@testst\cpt@tsvparse@a +} +\newsentinel\tsv@nil +\robust@def\cpt@tsvparse@a#1{% + \if@boolTF{cpt@st}{\let\tsv@arg#1}{\edef\tsv@arg{\unexpanded{#1}}}% + \advance\csv@depth\@ne + \ifnumcmpFT\csv@depth>\z@{}{% + \pushcsvinternals{\tsv@do,\ifcpt@useempty,\ifcpt@breakloop,% + \ifcpt@despace,\ifcpt@robdespace,\remainder@do}\csv@depth + }% + \cpt@breakloopfalse + \expandafter\cpt@tsvparse@b\tsv@arg\tsv@nil + \ifnumcmpFT\csv@depth>\z@{% + \ifnum\csv@depth=\z@ + \global\let\remainder@do\@gobble + \gundefcs\tsv@do + \fi + }{% + \popcsvinternals{\tsv@do,\ifcpt@useempty,\ifcpt@breakloop,% + \ifcpt@despace,\ifcpt@robdespace,\remainder@do}\csv@depth }% + \advance\csv@depth\cpt@mone } -\robust@def*\simplefifoloop#1{\cpt@simplefifoloop#1,\cpt@nil,} -\robust@def*\cpt@simplefifoloop#1,{% - \edef\fifo@arg{\unexpanded{#1}}% - \ifx\fifo@arg\cpt@nnil\else - \fifo@do{#1}\relax - \expandafter\cpt@simplefifoloop - \fi -} -\let\rc@on@currlevel\on@currlevel -\robust@def*\oneDsiso{\cpt@testst\cpt@oneDsiso} -\robust@def\cpt@oneDsiso#1{% - \pushnumber\oneDsisodepth - \ifnum\oneDsisodepth>\@ne\cpt@toodeep\oneDsiso1\fi - \let\on@currlevel\@secondoftwo - \@breakloopfalse - \begingroup - \if@boolTF{cpt@st}% - {\let\reserved@a#1}{\edef\reserved@a{\unexpanded{#1}}}% - \expandafter\endgroup\expandafter\cpt@sisoloop\reserved@a\sisorepeat - \popnumber\oneDsisodepth - \let\on@currlevel\rc@on@currlevel -} -\robust@def*\xDsiso{\cpt@testst\cpt@xDsiso} -\robust@def\cpt@xDsiso#1{% - \pushfunctions{\siso@do,\if@useempty,\if@breakloop}\cpt@depth - \let\curr@level\cpt@depth - \@breakloopfalse - \begingroup - \ifcpt@st\let\reserved@a#1\else\edef\reserved@a{\unexpanded{#1}}\fi - \expandafter\endgroup\expandafter\cpt@sisoloop\reserved@a\sisorepeat - \popfunctions{\siso@do,\if@useempty,\if@breakloop}\cpt@depth -} -\robust@def*\cpt@sisoloop{% - \if@boolTF{@breakloop}{% - \defpass\gobble@remainder##1\sisorepeat{}% +\robust@def*\cpt@tsvparse@b{% + \if@boolTF{cpt@breakloop}{% + \defpass\cpt@tempa##1\tsv@nil{\remainder@do{##1}}% }{% \begingroup \let\temp@bgroup\bgroup \let\bgroup\cpt@undefined - \futurelet\next\cpt@sisol@op - }% -} -\robust@def\cpt@sisol@op#1{% - \expandafter\endgroup - \ifx\next\temp@bgroup\def\siso@arg{{#1}}\else\def\siso@arg{#1}\fi - \ifblankTF{#1}{% - \if@useempty\on@currlevel{}\siso@do{}\relax\fi - }{% - \ifx#1\sisorepeat\sisorepeat\fi - \cptexpandargonce{\on@currlevel{}\siso@do}\siso@arg\relax + \futurelet\next\cpt@tsvparse@c }% - \cpt@sisoloop } -\robust@def\sisorepeat#1\cpt@sisoloop{\fi} -\robust@def*\simplesisoloop#1{\cpt@simplesisoloop#1\cpt@nnil} -\robust@def*\cpt@simplesisoloop#1{% - \ifxTF#1\cpt@nnil{}{% - \siso@do{#1}\relax - \cpt@simplesisoloop +\robust@def\cpt@tsvparse@c#1{% + \cptpassexpanded{\endgroup\edef\noexpand\tsv@arg + {\noexpand\unexpanded{\ifxTF\next\temp@bgroup + {{\unexpanded{#1}}}{\unexpanded{#1}}}}}% + \if@boolFT{cpt@despace}{}{% + \usecsn{\ifcpt@robdespace rob\fi despacecontent}\tsv@arg }% -} -\robust@def*\csv@@parse{% - \let\csv@kv@nr\z@ - \cpt@teststoptb\csv@kv@parse -} -\robust@def*\kv@@parse{% - \let\csv@kv@nr\@ne - \cpt@teststoptb\csv@kv@parse -} -\newcommand\csv@kv@parse[2][,]{% - \letcstocsn\csv@kv@do{\ifnum\csv@kv@nr=\z@ csv\else kv\fi @do}% - \ifdefTF\csv@kv@do{}{% - \cpt@err{'\string\csv@do' or '\string\kv@do' undefined}\@ehc - }% - \long\def\csv@tempa{% - \if@boolTF{@breakloop}{% - \defpass\gobble@remainder####1\cpt@nil#1{}% + \ifsentinelTF\tsv@arg\tsv@nil{}{% + \ifcsnullTF\tsv@arg{% + \ifcpt@useempty\tsv@do{}\relax\fi }{% - \csv@tempb.% + \expandafter\tsv@do\expandafter{\tsv@arg}\relax }% + \cpt@tsvparse@b }% - \long\def\csv@tempb##1#1{% - \edef\csv@tempc{\expandcsonce{\remove@to@dot##1}}% - \ifxTF\csv@tempc\cpt@nnil{}{% - \ifcsnullTF\csv@tempc{% - \if@boolTF{@useempty}{\on@currlevel{}\csv@kv@do{}\relax}{}% - }{% - \expandafter\on@currlevel\expandafter\@empty - \expandafter\csv@kv@do\expandafter{\csv@tempc}\relax - }% - \csv@tempa - }% - }% - \if@boolTF{cpt@st}% - {\let\csv@tempc#2}{\edef\csv@tempc{\unexpanded{#2}}}% - \ifcsnullTF\csv@tempc{}{% - \cpt@sttrue - \usecsn{cpt@\ifnum\csv@kv@nr=\@ne kv\else csv\fi normalize}% - [#1]\csv@tempc +} +% Fast, but non-robust and non-nesting, tsv parser. +% \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. +\newsentinel\siso@nil +\robust@def*\siso@@loop#1{% + \pushnumber\siso@depth + \ifnum\siso@depth>\@ne\cpt@toodeep\siso@@loop1\fi + \cpt@sisoloop#1\siso@nil + \popnumber\siso@depth +} +\robust@def*\cpt@sisoloop#1{% + \def\siso@arg{#1}% + \ifsentinelTF\siso@arg\siso@nil{}{% + \siso@do{#1}\relax + \cpt@sisoloop }% - \pushfunctions{\csv@kv@do,\if@useempty,\if@breakloop}\cpt@depth - \@breakloopfalse - \let\curr@level\cpt@depth - \expandafter\csv@tempa\csv@tempc#1\cpt@nil#1% - \popfunctions{\csv@kv@do,\if@useempty,\if@breakloop}\cpt@depth } \robust@def*\on@currlevel#1#2{% \ifdefTF\curr@level{% @@ -866,8 +1162,11 @@ }{% \cpt@err{'\string\curr@level' undefined}\@ehc }% - \cptexpandsecond - {#1}{\noexpandcsn{\cptgobblescape#2@\cpt@rnm\curr@level}}% + \cptexpandsecond{#1} + {\noexpandcsn{\cptgobblescape#2@\romannumeral\curr@level}}% +} +\new@def*\cptliststack#1#2{% + \ifx#2\@empty\@empty\else\expandcsonce{#2}#1\fi } \new@def\cptafterfi#1\fi{\fi#1} \new@def\cptafterelsefi#1\else#2\fi{\fi#1} @@ -881,30 +1180,44 @@ \robust@def*\emptifycsn{\aftercsname\emptify} \robust@def*\gemptifycsn{\global\aftercsname\emptify} \robust@def*\emptifycsset#1{% - \normaloneDloop{#1}\cpt@tempa{% - \expandafter\ifescapedTF\expandafter{\cpt@tempa}{% - \expandafter\def\cpt@tempa{}% + \def\comma@do##1{% + \ifsingletokenFT{#1}{% + \cpt@err{Multiple tokens '\detokenize{##1}'}\@ehc }{% - \cpt@err{Can't emptify unescaped macro}\@ehc + \ifescapedTF{##1}{% + \def##1{}% + }{% + \cpt@err{Can't emptify unescaped macro '\string##1'}\@ehc + }% }% }% + \comma@@loop{#1}% } -\robust@def*\cptonlypreamble#1{% +\robust@def*\cptonlypreamble{\cpt@testst\cpt@onlypreamble} +\robust@def*\cpt@onlypreamble#1{% + \let\ifv@\ifcpt@st \begingroup \def\cpt@resa{}% - \normaloneDloop{#1}\cpt@tempa{% + \def\comma@do##1{% + \normal@despace{##1}\cpt@tempa \ifcsnullTF\cpt@tempa{}{% \simpleexpandarg\ifescapedFT\cpt@tempa{% \cpt@err{'\expandcsonce\cpt@tempa' not a command}\@ehc }{% \simpleexpandarg\ifsingletokenTF\cpt@tempa{% - \xifinsetTF{,\expandcsonce\cpt@tempa,} + \xifinsetTF{,\expandcsonce\cpt@tempa,}% {,\expandcsonce\cpt@resa,}{% \cpt@warn{Command '\expandcsonce\cpt@tempa' multiply - \MsgBrk submitted to \string\cptonlypreamble}% + \MsgBrk submitted to \string\cptonlypreamble: + ignored}% }{% - \expandafter\@onlypreamble\cpt@tempa - \cptaddtocommalist\cpt@resa\cpt@tempa + \cptaddtolist*\cpt@resa\cpt@tempa + \ifv@ + \cptexpandarg\AtEndOfPackage + {\noexpand\@onlypreamble\expandcsonce\cpt@tempa}% + \else + \expandafter\@onlypreamble\cpt@tempa + \fi }% }{% \cpt@err{Invalid multiple arguments @@ -913,19 +1226,31 @@ }% }% }% + \comma@@loop{#1}% \endgroup } -\newletcs\IfFileExistsTF\IfFileExists -\new@def*\IfFileExistsFT#1{\IfFileExists{#1}\@secondoftwo\@firstoftwo} +\robust@def*\ifelementcountTF{% + \cpt@testopt\cpt@ifelementcount{,}% +} +\robust@def*\cpt@ifelementcount[#1]#2#3{% + \def\csv@do##1{\pushnumber\reserved@a}% + \chardef\reserved@a\z@ + \csv@@loop*[#1]{#2}% + \ifcptcond\ifnum\reserved@a>#3\fi +} \new@def*\ifcsnullTF#1{% - \@nameuse{@\expandafter\ifx\expandafter\cpt@unique - \@gobble#1.\cpt@unique second\else first\fi oftwo}% + \@nameuse{@\expandafter\ifx\expandafter\noboundary + \@gobble#1.\noboundary second\else first\fi oftwo}% {\@nameuse{@\ifx#1\@empty first\else second\fi oftwo}}% \@secondoftwo } \new@def*\ifcsnullFT#1{\ifcsnullTF{#1}\@secondoftwo\@firstoftwo} -\new@def*\oifcsnullTF#1{\expandafter\ifcsnullTF#1} -\new@def*\oifcsnullFT#1{\expandafter\ifcsnullFT#1} +\new@def*\oifcsnullTF#1{\expandafter\ifcsnullTF\expandafter{#1}} +\new@def*\oifcsnullFT#1{\expandafter\ifcsnullFT\expandafter{#1}} +\new@def*\xifcsnullTF#1{% + \expandafter\ifcsnullTF\expandafter + {\romannumeral-`\q\cptfullexpand{#1}}% +} \new@def*\ifcsnnullTF#1{% \ifblankTF{#1}{% \@secondoftwo @@ -941,40 +1266,59 @@ }% }% } -\new@def*\ifcsnnullFT#1{\ifcsnnullTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifcsnnullFT#1{% + \ifcsnnullTF{#1}\@secondoftwo\@firstoftwo +} \new@def*\ifdefnotnullTF#1{% - \ifdefTF{#1}{\ifcsnullTF{#1}\@secondoftwo\@firstoftwo}\@secondoftwo + \ifdefTF{#1}{% + \ifcsnullTF{#1}\@secondoftwo\@firstoftwo + }\@secondoftwo } -\new@def*\ifdefnotnullFT#1{\ifdefnotnullTF{#1}\@secondoftwo\@firstoftwo} -\robust@def*\advexpandarg#1#2{% - \ifsingletokenTF{#1}{% - \expandafter#1\expandafter{#2}% - }{% - \LTS@err{Argument \detokenize{#1} has more than one token}\@ehc - }% +\new@def*\ifdefnotnullFT#1{% + \ifdefnotnullTF{#1}\@secondoftwo\@firstoftwo +} +\new@def*\ifcsndefnotnullTF#1{% + \ifcsndefTF{#1}{% + \ifcsnnullTF{#1}\@secondoftwo\@firstoftwo + }\@secondoftwo +} +\new@def*\ifcsndefnotnullFT#1{% + \ifcsndefnotnullTF{#1}\@secondoftwo\@firstoftwo } +% For private use only where #1 is surely one token: \new@def*\simpleexpandarg#1#2{\expandafter#1\expandafter{#2}} + \new@def*\expandcsonce#1{\unexpanded\expandafter{#1}} \new@def*\expandcsnonce#1{\cptthreexp\expandcsonce\usecsn{#1}} +\new@def*\expandcstwice#1{\unexpanded\cptthreexp{#1}} +\new@def*\expandcsntwice#1{\aftercsname\expandcstwice{#1}} \new@def*\noexpandcsn#1{\expandcsonce{\csname#1\endcsname}} -\let\cptmakecs\noexpandcsn +\newletcs\cptmakecs\noexpandcsn \new@def*\cptoxdetok#1{\detokenize\expandafter{#1}} \new@def*\cpttxdetok#1{\detokenize\cptthreexp{#1}} \new@def*\cptsxdetok#1{\detokenize\cptsevenxp{#1}} \robust@def\cptpassexpanded#1{% \begingroup\protected@edef\x{\endgroup#1}\x } -\let\cptexpanded\cptpassexpanded +\newletcs\cptexpanded\cptpassexpanded +\long\def\cptfullexpand#1{% + \romannumeral-`\q\cpt@fullexpand{#1}{}% +} +\long\def\cpt@fullexpand#1{% + \expandafter\cpt@fullexp@nd\romannumeral-`\q#1\exp@nil +} +\long\def\cpt@fullexp@nd#1#2\exp@nil#3{% + \ifblankTF{#2}{#3#1}{\cpt@fullexpand{#2}{#3#1}}% +} \robust@def\cptpassunexpanded#1{\begingroup\long\def\x{\endgroup#1}\x} +\newletcs\cptpassasis\cptpassunexpanded \robust@def\defpass#1#2#{\afterassignment#1\long\def#1#2} \robust@def\edefpass#1#2#{\afterassignment#1\long\edef#1#2} \robust@def*\cptexpandarg#1#2{\cptpassexpanded{\unexpanded{#1}{#2}}} -\let\cptexpandargbraced\cptexpandarg \robust@def*\cptexpandargonce#1#2{% \cptpassexpanded{\unexpanded{#1}{\expandcsonce{#2}}}% } \robust@def*\cptexpandsecond#1#2{\cptpassexpanded{\unexpanded{#1}#2}} -\let\cptexpandargunbraced\cptexpandsecond \robust@def*\cptexpandsecondonce#1#2{% \cptpassexpanded{\unexpanded{#1}\expandcsonce{#2}}% } @@ -1010,22 +1354,23 @@ \begingroup \catcode`\ =9\catcode`\^^I=9\relax \edef\cpt@tempa{\expandafter\@carcube\@currname\@nil @}% - \def\cpt@tempb{\@testopt{\expandafter\endgroup\cpt@SetStyleFileMessages}}% + \def\cpt@tempb{\@testopt{\expandafter\endgroup + \cpt@SetStyleFileMessages}}% \expandafter\cpt@tempb\expandafter{\cpt@tempa}% } \robust@def*\cpt@SetStyleFileMessages[#1]#2#3#4{% \begingroup \def\cpt@tempa##1{\noexpandcsn{##1}}% - \protected\def\cpt@tempb{\global\protected\@namedef}% + \shelldef\cpt@tempb{\global\protected\@namedef}% \edef\cpt@tempc{\ifx\@currext\@pkgextension Package\else Class\fi}% \@tempswafalse - \kernel@for\cpt@rsvda:={#2,#3,#4}\do{% - \ifcsname#1\cpt@rsvda\endcsname - \@tempswatrue\let\cpt@rsvdb\cpt@rsvda + \kernel@for\cpt@resa:={#2,#3,#4}\do{% + \ifcsname#1\cpt@resa\endcsname + \@tempswatrue\let\cpt@resb\cpt@resa \fi }% \if@tempswa - \def\reserved@a{#1\cpt@rsvdb}\@notdefinable + \def\reserved@a{#1\cpt@resb}\@notdefinable \else \cptpassexpanded{% \cpt@tempb{#1#2}####1{\cpt@tempa{\cpt@tempc Info}% @@ -1067,32 +1412,139 @@ \new@def*\ifboolFT#1{\ifboolTF{#1}\@secondoftwo\@firstoftwo} \new@def*\ifbooleanTF#1#{\ifboolTF{#1}} \new@def*\if@boolTF#1{% - \usecsn{if#1}\expandafter\@firstoftwo\else - \expandafter\@secondoftwo\fi + \usecsn{@\usecsn{if#1}first\else second\fi oftwo}% } \new@def*\if@boolFT#1{\if@boolTF{#1}\@secondoftwo\@firstoftwo} -\new@def*\ifnumTF#1#{% - \usecsn{@\ifnum#1first\else second\fi oftwo}% +\new@def\cptiterate#1\repeat{\cpt@iterate\@gobble{#1}} +\new@def\cpt@iterate\@gobble#1{% + #1\relax\expandafter\cpt@iterate\fi\@gobble{#1}% +} +\new@def\cptwhilecond#1\fi#2{% + #1#2\relax\cptswap{\cpt@whilecond{#1#2\relax}\fi}\fi +} +\new@def\cpt@whilecond#1\fi{% + #1\expandafter\cpt@whilecond\else\@gobbletwo\fi{#1}\fi +} +\new@def*\cpt@numlt#1<{#1<\numexpr} +\new@def*\cpt@numgt#1>{#1>\numexpr} +\new@def*\cpt@numeq#1={#1=\numexpr} +\new@def*\cpt@dimlt#1<{#1<\dimexpr} +\new@def*\cpt@dimgt#1>{#1>\dimexpr} +\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 + \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% + \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 + \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% + \expandafter\cpt@whiledim\else + \expandafter\@gobbletwo\fi{#1}{#2}% +} +\new@def*\ifnumcmpTF#1#{% + \usecsn{@\ifnum\numexpr\cpt@numlt\cpt@numgt\cpt@numeq#1% + \remove@to@nnil<=>\@nnil first\else second\fi oftwo}% +} +\new@def*\ifnumcmpFT#1#{\usecsn{@\ifnumcmpTF#1{second}{first}oftwo}} +\new@def*\ifdimcmpTF#1#{% + \usecsn{@\ifdim\dimexpr\cpt@dimlt\cpt@dimgt\cpt@dimeq#1% + \remove@to@nnil<=>\@nnil first\else second\fi oftwo}% +} +\new@def*\ifdimcmpFT#1#{\usecsn{@\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}% + }% + \cpt@tempa##1#2\cpt@nil + }% } -\new@def*\ifnumFT#1#{\usecsn{@\ifnumTF#1{second}{first}oftwo}} -\new@def*\ifoddTF#1#{% +\def\siso@do#1{\cpt@defcheck#1\cpt@nil}% +\siso@@loop{% + {\cpt@checkeq=}{\cpt@checkgt>}{\cpt@checklt<}{\cpt@checkhyp-}% +} +\robust@def*\cpt@defsplit@at#1#2\cpt@nil{% + \new@def*#1##1\cpt@nil{% + \begingroup + \def\cpt@tempa####1#2####2\cpt@nil{\endgroup + \def\lpt{####1}\def\rpt{####2}% + }% + \ifinsetTF{#2}{##1}{% + \cpt@tempa##1#2\cpt@nil + }{% + \def\lpt{##1}\def\rpt{}% + }% + }% +} +\def\siso@do#1{\cpt@defsplit@at#1\cpt@nil}% +\siso@@loop{% + {\cpt@split@ateq=}{\cpt@split@atgt>}% + {\cpt@split@atlt<}{\cpt@split@athyp-}% +} +\robust@def\DefSuffixChecker#1#2#3{% + \def#1##1##2##3{% + \begingroup + \toks@{}% + \def\xwm@tempa{% + \ifsingleTF{##2}{% + \ifsingleTF{##3}{\toks@{##1##2##3}}{\toks@{##1##2{##3}}}% + }{% + \ifsingleTF{##3}{\toks@{##1{##2}##3}}{\toks@{##1{##2}{##3}}}% + }% + }% + \defpass\xwm@tempb{% + \ifstrcmpTF{##2}{#2}{\xwm@tempa}{% + \ifstrcmpTF{##2}{#3}{% + \ifstrcmpTF{##3}{#2}{\toks@{##1##3##2}}{\xwm@tempa}% + }{\xwm@tempa}% + }% + }% + \expandafter\endgroup\the\toks@ + }% +} +\new@def*\ifnumoddTF#1#{% \usecsn{@\ifodd#1\@empty first\else second\fi oftwo}% } -\new@def*\ifoddFT#1#{\usecsn{@\ifoddTF#1{second}{first}oftwo}} +\new@def*\ifnumoddFT#1#{\usecsn{@\ifnumoddTF#1{second}{first}oftwo}} +\newletcs\ifnumevenTF\ifnumoddFT \robust@def*\cptnumdef#1#2{\edef#1{\the\numexpr#2}} \robust@def*\cptdimdef#1#2{\edef#1{\the\dimexpr#2}} \robust@def*\cptnumadd#1#2{\edef#1{\the\numexpr#1+#2}} \robust@def*\cptdimadd#1#2{\edef#1{\the\dimexpr#1+#2}} \new@edef*\@leftbracechar{\expandafter\@car\string{\@nil\iffalse}\fi} \new@def\cptstrcmp#1#2{% - \ifnum\pdfstrcmp{#1}{#2}=\z@\expandafter\@firstoftwo\else - \expandafter\@secondoftwo\fi + \ifcptcond\ifnum\pdfstrcmp{#1}{#2}=\z@\fi } \new@def\ifstrcmpTF#1#2{% \cptstrcmp{\detokenize{#1}}{\detokenize{#2}}% } \new@def\ifstrcmpFT#1#2{\ifstrcmpTF{#1}{#2}\@secondoftwo\@firstoftwo} \robust@def\oifstrcmpTF#1#2{\cptexpandtwoargsonce\ifstrcmpTF{#1}{#2}} +\robust@def\oif@sp@strcmpTF#1#2{% + \ifsingletokenTF{#1}{% + \ifsingletokenTF{#2}{% + \ifnum\pdfstrcmp{\expandcsonce{#1}}{\expandcsonce{#2}}=\z@ + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi + }{% + \cpt@err{'\detokenize{#2}' not a single token}\@ehc + }% + }{% + \cpt@err{'\detokenize{#1}' not a single token}\@ehc + }% +} \robust@def\oifstrcmpFT#1#2{\cptexpandtwoargsonce\ifstrcmpFT{#1}{#2}} \robust@def\xifstrcmpTF#1#2{\cptexpandtwoargs\ifstrcmpTF{#1}{#2}} \robust@def\xifstrcmpFT#1#2{\cptexpandtwoargs\ifstrcmpFT{#1}{#2}} @@ -1112,7 +1564,7 @@ \long\def\ifbracedTF#1{% \cptstrcmp{\detokenize\expandafter{\@gobble#1.}}{}\@secondoftwo{% \cptstrcmp{\detokenize\expandafter{\@gobble#1}}{}{% - \cptstrcmp{\expandafter\cpt@car\detokenize{#1}\car@nil}{\@leftbracechar}% + \cptstrcmp{\expandafter\cpt@car\detokenize{#1}\car@nil}\@leftbracechar \@firstoftwo\@secondoftwo }{% \@secondoftwo @@ -1122,7 +1574,7 @@ \newcommand\ifbracedFT[1]{\ifbracedTF{#1}\@secondoftwo\@firstoftwo} \long\def\ifleftbracedTF#1{% \cptstrcmp{\detokenize\expandafter{\@gobble#1.}}{}\@secondoftwo{% - \cptstrcmp{\expandafter\cpt@car\detokenize{#1}\car@nil}{\@leftbracechar}% + \cptstrcmp{\expandafter\cpt@car\detokenize{#1}\car@nil}\@leftbracechar \@firstoftwo\@secondoftwo }% } @@ -1130,21 +1582,22 @@ \usecsn{@\ifx#1#2\@empty first\else second\fi oftwo}% } \new@def\ifxFT#1#2{\ifxTF{#1}{#2}\@secondoftwo\@firstoftwo} -\new@def*\ifcptdefeqTF#1#2{% +\new@def*\ifdefeqTF#1#2{% \ifdefTF{#1}{% \ifdefTF{#2}{% \usecsn{@\ifx#1#2first\else second\fi of oftwo}% }\@secondoftwo }\@secondoftwo } -\new@def\ifcatTF#1#{% +\new@def\ifdefeqFT#1#2{\ifdefeqTF{#1}{#2}\@secondoftwo\@firstoftwo} +\new@def\ifcateqTF#1#{% \usecsn{@\ifcat#1first\else second\fi oftwo}% } \new@def\ifcharcmpTF#1#2{% \ifsingletokenTF{#1}{% \ifsingletokenTF{#2}{% - \usecsn{@\if\detokenize\expandafter{\cpt@rnm\expandafter - \cptswap\expandafter{\cpt@rnm-`\q#2}{-`\q#1}}% + \usecsn{@\if\detokenize\expandafter{\romannumeral\expandafter + \cptswap\expandafter{\romannumeral-`\q#2}{-`\q#1}}% first\else second\fi oftwo}% }{% \cpt@err{More than one token in '\detokenize{#2}'}\@ehc @@ -1157,14 +1610,14 @@ } \new@def\ifcharcmpFT#1#2{\ifcharcmpTF{#1}{#2}\@secondoftwo\@firstoftwo} \new@def\ifexpandableTF#1#2#3{% - \cpt@rnm\ifleftbracedTF{#1}\@secondoftwo{% + \romannumeral\ifleftbracedTF{#1}\@secondoftwo{% \ifblankTF{#1}\@secondoftwo{\expandafter\ifx\noexpand#1#1% \expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}}% {0 #2}{0 #3}% } \new@def*\iffirstisspaceTF#1{% \long\def\iffirstisspaceTF##1##2##3{% - \cpt@rnm\usecsn{@\ifblankTF{##1}{second}% + \romannumeral\usecsn{@\ifblankTF{##1}{second}% {\cpt@iffirstisspace.##1#1\@nnil}oftwo}{0#1##2}{0#1##3}% }% } @@ -1174,29 +1627,41 @@ \remove@to@nnil } \new@def\ifsingletokenTF#1#2#3{% - \cpt@rnm\ifblankTF{#1}\@secondoftwo{% + \romannumeral-`\q\ifblankTF{#1}\@secondoftwo{% \ifbracedTF{#1}\@secondoftwo{% \iffirstisspaceTF{#1}{% \expandafter\ifblankTF\expandafter{\@gobblespace#1}% }{% - \expandafter\ifblankTF\expandafter{\@secondoftwo#1{}}% + \expandafter\ifblankTF\expandafter{\@gobble#1}% }% \@firstoftwo\@secondoftwo }% - }{0 #2}{0 #3}% + }{#2}{#3}% } +\newletcs\ifsingleTF\ifsingletokenTF \robust@def*\ifsingletokenFT#1{% \ifsingletokenTF{#1}\@secondoftwo\@firstoftwo } +\new@def\if@sp@singletokenTF#1#2#3{% + \romannumeral-`\q\ifblankTF{#1}\@secondoftwo{% + \ifbracedTF{#1}\@secondoftwo{% + \expandafter\ifblankTF\expandafter{\@gobble#1}% + \@firstoftwo\@secondoftwo + }% + }{#2}{#3}% +} +\robust@def*\cpt@listparser@err#1{% + \@latex@error{Invalid list parser '#1'}\@ehc +} \robust@def*\cpt@checklistparser#1#2{% \ifsingletokenTF{#1}{% - \xifinsetTF{\detokenize{#1}}{\detokenize{,;:/+-|*&}}{% - #2 + \xifinsetTF{\cptoxdetok{#1}}{\detokenize{,;:/+-|*&}}{% + #2% }{% - \cpt@err{Invalid list parser '#1'}\@ehc + \cpt@listparser@err{#1}% }% }{% - \cpt@err{Invalid list parser '#1'}\@ehc + \cpt@listparser@err{#1}% }% } \robust@def\exitgroupdef#1{% @@ -1205,26 +1670,30 @@ } \robust@def*\cptaftergroup#1{% \advance\@tempcnta\@ne - \csn@xdef{cpt@aftergroup@\cpt@rnm\@tempcnta}{% - \gundefcsn{cpt@aftergroup@\cpt@rnm\@tempcnta}% - \unexpanded\ifnullTF{#1}{}\expandafter{#1}% + \csn@xdef{cpt@aftergroup@\romannumeral\@tempcnta}{% + \gundefcsn{cpt@aftergroup@\romannumeral\@tempcnta}% + \unexpanded\ifblankTF{#1}{}\expandafter{#1}% }% - \aftercsname\aftergroup{cpt@aftergroup@\cpt@rnm\@tempcnta}% + \aftercsname\aftergroup{cpt@aftergroup@\romannumeral\@tempcnta}% } \robust@def\cptafterassignment#1{% \begingroup \advance\@tempcnta\@ne - \csn@xdef{cpt@afterassignment@\cpt@rnm\@tempcnta}{% - \gundefcsn{cpt@afterassignment@\cpt@rnm\@tempcnta}% - \unexpanded\ifnullTF{#1}{}\expandafter{#1}% + \csn@xdef{cpt@afterassignment@\romannumeral\@tempcnta}{% + \gundefcsn{cpt@afterassignment@\romannumeral\@tempcnta}% + \unexpanded\ifblankTF{#1}{}\expandafter{#1}% }% \aftercsname{\endgroup\afterassignment}{% - cpt@afterassignment@\cpt@rnm\@tempcnta}% + cpt@afterassignment@\romannumeral\@tempcnta}% } \robust@def*\cptexpandmacro#1#2{% - \ifcptmacroTF{#1}{% - \ifexpandableTF{#1}{% - \simpleexpandarg\cptexpandmacro{#1}% + \ifsingletokenTF{#1}{% + \ifcptmacroTF{#1}{% + \ifexpandableTF{#1}{% + \simpleexpandarg\cptexpandmacro{#1}#2% + }{% + \edef#2{\unexpanded{#1}}% + }% }{% \edef#2{\unexpanded{#1}}% }% @@ -1232,21 +1701,43 @@ \edef#2{\unexpanded{#1}}% }% } +% Donald Arseneau's \@ifnextchar: \robust@def\cpt@ifnextchar#1#2#3{% - \kernel@ifnextchar\bgroup - {\kernel@ifnextchar{#1}{#2}{#3}}{\cpt@ifn@xtchar{#1}{#2}{#3}}% + \begingroup + \@ifnextchar\relax + {\cpt@ifnextchar@a{#1}{#2}{#3}}% + {\cpt@ifnextchar@a{#1}{#2}{#3}}% +} +\robust@def\cpt@ifnextchar@a#1#2#3{% + \ifcase + \ifcat\noexpand\@let@token\bgroup 1\fi + \ifcat\noexpand\@let@token\egroup 1\fi + 0\let\next\cpt@ifnextchar@b + \else + \def\next{\endgroup\@ifnextchar}% + \fi + \expandafter\next\expandafter{\string#1}{#2}{#3}% +} +\robust@def\cpt@ifnextchar@b#1#2#3#4{% + \escapechar92\relax + \edef\cpt@tempa{\cpt@ifnextchar@c{#1}\cpt@ifnextchar@c{#4}}% + \expandafter\endgroup\csname\expandafter @\expandafter + \ifx\cpt@tempa first\else second\fi oftwo\endcsname + {#2}{#3}#4% } -\robust@def\cpt@ifn@xtchar#1#2#3#4{% - \csname @\if\detokenize{#1#4}first\else - second\fi oftwo\endcsname{#2}{#3}#4% +\new@def\cpt@ifnextchar@c#1{% + \expandafter\cpt@ifnextchar@d\string#1\relax\noindent{#1}% +} +\new@def\cpt@ifnextchar@d#1#2\noindent#3{% + \ifx\relax#2#1\else\noexpand#3\fi } \robust@def\cpt@testopt#1#2{\cpt@ifnextchar[{#1}{#1[{#2}]}} \robust@def*\cpt@ifbrack#1#2{\cpt@ifnextchar[{#1}{#2}} \new@def*\cpt@xtestopt#1#2#3{% - \cpt@xifbrack#1\cpt@unique[\cpt@unique{#2#1}{#2[{#3}]{#1}}% + \cpt@xifbrack#1\noboundary[\noboundary{#2#1}{#2[{#3}]{#1}}% } -\new@def*\cpt@xifbrack#1[#2\cpt@unique#3#{% - \usecsn{@\ifnullTF{#1#2}{first}{second}oftwo}% +\new@def*\cpt@xifbrack#1[#2\noboundary#3#{% + \usecsn{@\ifblankTF{#1#2}{first}{second}oftwo}% } \robust@def\cpt@testpnopt#1#2{\cpt@ifnextchar({#1}{#1({#2})}} \robust@def\cpt@ifstar#1{\cpt@ifnextchar*{\@firstoftwo{#1}}} @@ -1259,28 +1750,45 @@ \robust@def\cpt@teststpm#1{\cpt@testst{\cpt@testpm{#1}}} \robust@def\cpt@teststopta#1{\cpt@testst{\cpt@testopt{#1}{}}} \robust@def\cpt@teststoptb#1{\cpt@testst{\cpt@testopt{#1}{,}}} -\new@def*\ifcptstrcase#1{\cpt@xtestopt{#1}\cpt@ifstrcase{}} -\new@def\cpt@ifstrcase[#1]#2#3{% +\robust@def\cpt@teststoptc#1#2{\cpt@testst{\cpt@testopt{#1}{#2}}} +\new@def*\ifstreqcase#1{\cpt@xtestopt{#1}\cpt@ifstreqcase{}} +\new@def\cpt@ifstreqcase[#1]#2#3{% \expandafter\cptswapfirstbraced\expandafter{#2}% - {\cpt@ifstrc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% + {\cpt@ifstreqc@se#3\cpt@mil\cpt@mil\cpt@nil}{#1}% } -\new@def\cpt@ifstrc@se#1#2#3\cpt@nil#4#5{% - \ifnullTF{#3}{#5}{% +\new@def\cpt@ifstreqc@se#1#2#3\cpt@nil#4#5{% + \ifblankTF{#3}{#5}{% \ifstrcmpTF{#1}{#4}{#2}{% - \cpt@ifstrc@se#3\cpt@nil{#4}{#5}% + \cpt@ifstreqc@se#3\cpt@nil{#4}{#5}% }% }% } +\new@def*\ifstrincase#1{\cpt@xtestopt{#1}\cpt@ifstrincase{}} +\new@def\cpt@ifstrincase[#1]#2#3{% + \expandafter\cptswapfirstbraced\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}{% + \ifinsetTF{#1}{#4}{#2}{% + \cpt@ifstrinc@se#3\cpt@nil{#4}{#5}% + }% + }% +} +% LaTeX kernel's \in@ (which is used frequently elsewhere) +% is not reliable in cases like \in@{cc}{abc}. So we provide +% a modified form of it here: \robust@def\cptinset#1#2{% \begingroup \def\in@@##1#1##2##3\in@@{\endgroup - \ifx##2\in@\in@false\else\in@true\fi + \ifx##2\cptinset\cpt@infalse\else\cpt@intrue\fi }% - \in@@#2{\in@@}#1\in@\in@@ + \in@@#2{\in@@}#1\cptinset\in@@ } +\newletcs\cpt@in\cptinset \robust@def\ifinsetTF#1#2{% \cptinset{#1}{#2}% - \@nameuse{@\ifin@ first\else second\fi oftwo}% + \@nameuse{@\ifcpt@in first\else second\fi oftwo}% } \robust@def\ifinsetFT#1#2{\ifinsetTF{#1}{#2}\@secondoftwo\@firstoftwo} \robust@def\oifinsetTF#1#2{% @@ -1295,184 +1803,135 @@ \expandafter\endgroup\expandafter\ifinsetTF\cpt@tempa } \robust@def\xifinsetFT#1#2{\xifinsetTF{#1}{#2}\@secondoftwo\@firstoftwo} -\robust@def*\cptaddtolist{\cpt@teststoptb\cpt@addtolist} -\robust@def\cpt@addtolist[#1]#2#3{% - \if@checklp\cpt@checklistparser{#1}\relax\fi +\robust@def\if@sp@inlistTF#1#2#3{% + \xifinsetTF{\detokenize{#1}\cptoxdetok{#2}\detokenize{#1}}% + {\detokenize{#1}\cptoxdetok{#3}\detokenize{#1}}% +} +\robust@def\if@sp@inlistFT#1#2#3{% + \if@sp@inlistTF{#1}{#2}{#3}\@secondoftwo\@firstoftwo +} +\robust@def*\cptaddtotoks#1{% + \long\shelldef\cptaddtotoks##1##2{% + \toks##1\oifblankTF{\the\toks##1}{{##2}}% + {\expandafter{\the\toks##1#1##2}}% + }% +} +\cptaddtotoks{ } +\robust@def*\cptaddtolist{\cpt@teststoptb{\cpt@addtolist\expandcsonce{e}}} +\robust@def*\cptgaddtolist{\cpt@teststoptb{\cpt@addtolist\expandcsonce{x}}} +\robust@def*\cptxaddtolist{\cpt@teststoptb{\cpt@addtolist\@firstofone{e}}} +\robust@def*\cptgxaddtolist{\cpt@teststoptb{\cpt@addtolist\@firstofone{x}}} +\robust@def\cpt@addtolist#1#2[#3]#4#5{% + \ifcpt@check\cpt@checklistparser{#3}\relax\fi \begingroup \def\cpt@tempa{\endgroup - \ifdefTF#2{% - \ifcpt@st - \protected@edef#2{\ifcsnullTF#2{}{\expandcsonce#2#1}#3}% - \else - \edef#2{\ifcsnullTF#2{}{\expandcsonce#2#1}\unexpanded{#3}}% - \fi + \ifdefTF#4{% + \if@boolTF{cpt@st}{% + \usecsn{protected@#2def}#4{\cptliststack#3#4#1{#5}}% + }{% + \usecsn{#2def}#4{\cptliststack#3#4\unexpanded{#5}}% + }% }{% - \ifcpt@st - \protected@edef#2{#3}% - \else - \edef#2{\unexpanded{#3}}% - \fi + \if@boolTF{cpt@st}{% + \usecsn{protected@#2def}#4{#1{#5}}% + }{% + \usecsn{#2def}#4{\unexpanded{#5}}% + }% }% }% - \ifblankTF{#3}{\if@useempty\cpt@tempa\else\endgroup\fi}% - \cpt@tempa + \ifblankTF{#5}{\ifcpt@useempty\cpt@tempa\else\endgroup\fi}\cpt@tempa } -\robust@def*\cptaddtocommalist#1#2{% - \ifdefTF{#1}{% - \xdef#1{% - \ifcsnullTF#1{}{\expandcsonce{#1},}\expandcsonce{#2}% - }% - }{% - \xdef#1{\expandcsonce{#2}}% - }% +\robust@def*\cptfilterremoveelements{% + \cpt@testopt\cpt@filterremoveelements{,}% } -\robust@def*\cptkilloneelement{\cpt@testopt\cpt@killoneelement{,}} -\robust@def\cpt@killoneelement[#1]#2#3{% - \if@checklp\cpt@checklistparser{#1}\relax\fi - \begingroup - \@onelevel@sanitize#3% - \edef\cpt@rsvda{\detokenize{#2}}% - \cpttrimparser[#1]\cpt@rsvda - \cptpassexpanded{\unexpanded{\def\cpt@rsvdb##1#1}\cpt@rsvda}% - #1##2\cpt@nil{##1#1##2\cpt@mil}% - \def\cpt@rsvdc##1#1\cpt@mil##2\cpt@mil{\ifx#1##1\@empty\else##1\fi}% - \cptpassexpanded{\edef\noexpand#3{\unexpanded{\expandafter\cpt@rsvdc - \cpt@rsvdb}#1#3#1\noexpand\cpt@mil#1\cpt@rsvda#1\cpt@nil}}% - \exitgroupdef#3% - \cptscantokens#3% -} -\robust@def*\cptkillelements{\cpt@testopt\cpt@killelements{,}} -\robust@def\cpt@killelements[#1]#2#3{% - \edef\kill@tempa{\unexpanded{#2}}% - \cpt@sttrue\cpt@csvnormalize[#1]\kill@tempa - \cpt@sttrue\cpt@csvnormalize[#1]#3% - \pushfunctions\if@checklp\cpt@depth - \@checklpfalse - \long\def\fifo@do##1{\cpt@killoneelement[#1]{##1}#3}% - \expandafter\simplefifoloop\expandafter{\kill@tempa}% - \undefcs\kill@tempa - \popfunctions\if@checklp\cpt@depth -} -\robust@def*\cptremoveoneelement{\cpt@testopt\cpt@removeoneelement{,}} -\robust@def\cpt@removeoneelement[#1]#2#3{% - \if@checklp\cpt@checklistparser{#1}\relax\fi +\robust@def*\cpt@filterremoveelements[#1]#2#3#4{% \begingroup - \def\cpt@removeone##1#1#2#1##2\remove@nil{% - \gdef#3{##1#1##2}% - \xifinsetFT{\remove@nil#1}{\remove@nil\expandcsonce{#3}}{}{% - \def\cpt@removeone#1####1\remove@nil{\gdef#3{####1}}% - \expandafter\cpt@removeone#3\remove@nil - }% - \xifinsetFT{#1\remove@nil}{\expandcsonce{#3}\remove@nil}{}{% - \def\cpt@removeone####1#1\remove@nil{\gdef#3{####1}}% - \expandafter\cpt@removeone#3\remove@nil + \cptdeclarefilter{#4}% + \ifdefTF{#2}{}{\def#2{}}% + \edef\cpt@delete{\unexpanded{#3}}% + \ifcsnullTF\cpt@delete{}{% + \cpt@sttrue\cpt@csvnormalize[#1]\cpt@delete + }% + \edef\cpt@tempd##1{% + {\detokenize{#1}\noexpand\cptoxdetok{##1}\detokenize{#1}}% + {\detokenize{#1}\cptoxdetok\cpt@delete\detokenize{#1}}% + }% + \def\cpt@tempc{}% + \def\csv@do##1{% + \edef\cpt@tempa{\unexpanded{##1}}% + \cpt@usefilter\cpt@tempa\cpt@tempb + % no \if@sp@inlistTF here: + \expandafter\xifinsetTF\cpt@tempd\cpt@tempb{}{% + \cptaddtolist[#1]\cpt@tempc{##1}% }% }% - \xifinsetFT{#1\unexpanded{#2}#1}{#1\expandcsonce{#3}#1}{}{% - \protected\def\remove@nil{}% - \expandafter\cpt@removeone\expandafter#1#3#1\remove@nil + \ifcsnullTF#2{}{% + \ifcsnullTF\cpt@delete{}{% + \csv@@parse*[#1]#2% + }% }% - \endgroup -} -\robust@def*\cptremoveelements{\cpt@testopt\cpt@removeelements{,}} -\robust@def\cpt@removeelements[#1]#2#3{% - \edef\remove@tempa{\unexpanded{#2}}% - \cpt@sttrue\cpt@csvnormalize[#1]\remove@tempa - \cpt@sttrue\cpt@csvnormalize[#1]#3% - \pushfunctions\if@checklp\cpt@depth - \@checklpfalse - \long\def\fifo@do##1{\cpt@removeoneelement[#1]{##1}#3}% - \expandafter\simplefifoloop\expandafter{\remove@tempa}% - \undefcs\remove@tempa - \popfunctions\if@checklp\cpt@depth + \let#2\cpt@tempc + \exitgroupdef#2% } \robust@def*\cptdeclarefilter#1{% \edef\cpt@usefilter##1##2{% \ifblankTF{#1}{\let##2##1}{% - \ifxTF{#1}\relax{\let##2##1}{\unexpanded{#1}{##1}{##2}}% + \ifxTF{#1}\relax{\let##2##1}{% + \ifstrcmpTF{#1}\nofilter{\let##2##1}{% + \unexpanded{#1}{##1}{##2}% + }% + }% }% }% } +\newletcs\everymergeitem\@iden \robust@def*\cptfiltermergelists{\cpt@testopt\cpt@filtermergelists{,}} \robust@def*\cpt@filtermergelists[#1]#2#3#4{% \begingroup \cptdeclarefilter{#4}% - \ifdefTF{#2}{% - \ifcsnullTF#2{}{\cpt@sttrue\cpt@csvnormalize[#1]#2}% - }{% - \def#2{}% - }% + \ifdefTF{#2}{}{\def#2{}}% \ifblankTF{#3}{% \def\cpt@update{}% }{% \edef\cpt@update{\unexpanded{#3}}% - \cpt@sttrue\cpt@csvnormalize[#1]\cpt@update }% \def\cpt@add##1{% - \edef#2{\ifx#2\@empty\else\expandcsonce#2#1\fi - \expandcsonce{##1}}% + \edef#2{\cptliststack#1#2% + \everymergeitem{\expandcsonce{##1}}}% }% - \def\fifo@do##1{% - \@choicefdfalse + \def\csv@do##1{% + \cpt@choicefdfalse \edef\cpt@merge@a{\unexpanded{##1}}% \cpt@usefilter\cpt@merge@a\cpt@merge@b - \def\fifo@do####1{% + \def\csv@do####1{% \edef\cpt@merge@c{\unexpanded{####1}}% \cpt@usefilter\cpt@merge@c\cpt@merge@d \cptscantokens\cpt@merge@b \cptscantokens\cpt@merge@d \ifx\cpt@merge@b\cpt@merge@d - \@choicefdtrue\cpt@add\cpt@merge@a + \cpt@choicefdtrue\cpt@add\cpt@merge@a \else \cpt@add\cpt@merge@c \fi }% - \cptexpandargonce{\def#2{}\cpt@stfalse\cpt@xDfifo[#1]}#2% - \if@boolTF{@choicefd}{}{\cpt@add\cpt@merge@a}% + \cptexpandargonce{\def#2{}\csv@@parse[#1]}#2% + \if@boolTF{cpt@choicefd}{}{\cpt@add\cpt@merge@a}% }% \ifcsnullTF#2{% \edef#2{\expandcsonce\cpt@update}% }{% \ifcsnullTF\cpt@update{}{% - \cpt@sttrue\cpt@xDfifo[#1]\cpt@update + \csv@@parse*[#1]\cpt@update }% }% \exitgroupdef#2% -} -\robust@def*\cptfilterremoveelements{% - \cpt@testopt\cpt@filterremoveelements{,}% -} -\robust@def*\cpt@filterremoveelements[#1]#2#3#4{% - \begingroup - \cptdeclarefilter{#4}% - \ifdefTF{#2}{}{\def#2{}}% - \ifcsnullTF#2{}{\cpt@sttrue\cpt@csvnormalize[#1]#2}% - \edef\cpt@delete{\unexpanded{#3}}% - \ifcsnullTF\cpt@delete - {}{\cpt@sttrue\cpt@csvnormalize[#1]\cpt@delete}% - \edef\cpt@tempd##1{% - {\detokenize{#1}\noexpand\cptoxdetok{##1}\detokenize{#1}}% - {\detokenize{#1}\cptoxdetok\cpt@delete\detokenize{#1}}% - }% - \def\cpt@tempc{}% - \def\fifo@do##1{% - \edef\cpt@tempa{\unexpanded{##1}}% - \cpt@usefilter\cpt@tempa\cpt@tempb - \expandafter\xifinsetTF\cpt@tempd\cpt@tempb{}{% - \cpt@stfalse\cpt@addtolist[#1]\cpt@tempc{##1}% - }% - }% - \ifcsnullTF#2{}{% - \ifcsnullTF\cpt@delete{}{\cpt@sttrue\cpt@oneDfifo[#1]#2}% - }% - \let#2\cpt@tempc - \exitgroupdef#2% + \let\everymergeitem\@firstofone } \robust@def*\preservebracedefQ#1#2{% \def\preserve@prefix{#1}% \def\preserve@delimiter{#2}% } -\preservebracedefQ{\long}{\@nil} +\preservebracedefQ\long\@nil \robust@def*\preservebracedef#1{% \cpt@preservebracedef \cpt@pr@servebracedef#1.% @@ -1493,8 +1952,14 @@ }% }% } -\robust@def*\cptglet{\global\let} \@namedef{@gobblespace} {} +\robust@def*\csn@newif#1{% + \ifstrcmpTF{#1}{x}{% + \cpt@err{Redefining '\cptmakecs{ifx}'?}\@ehc + }{% + \usecsn{newif\cptthreexp}\usecsn{if#1}% + }% +} \robust@def*\csn@def#1{\cptthreexp\def\usecsn{#1}} \robust@def*\csn@gdef#1{\cptthreexp\gdef\usecsn{#1}} \robust@def*\csn@edef#1{\cptthreexp\edef\usecsn{#1}} @@ -1538,8 +2003,9 @@ \robust@def*\undefcsset{\cpt@testst\cpt@undefcsset} \robust@def*\cpt@undefcsset#1{% \ifcpt@st\let\cpt@tempa#1\else\def\cpt@tempa{#1}\fi - \normaloneDloop*\cpt@tempa\cpt@tempa{% - \expandafter\ifescapedTF\expandafter{\cpt@tempa}{% + \def\comma@do##1{% + \normal@despace{##1}\cpt@tempa + \simpleexpandarg\ifescapedTF\cpt@tempa{% \expandafter\undefcs\cpt@tempa }{% \cpt@err{I can't find escape in token @@ -1547,28 +2013,31 @@ Maybe it's an active character}\@ehc }% }% + \simpleexpandarg\comma@@loop\cpt@tempa } \robust@def*\cpttrimparser{\cpt@testopt\cpt@trimparser{,}} \robust@def\cpt@trimparser[#1]#2{% \begingroup \edef\cpt@tempd{\detokenize{#1}}% - \let\trimparser@nil\cpt@nil + \let\trimpr@nil\cpt@nil \def\cpt@trimb{% - \xifinsetFT{\cpt@tempd\trimparser@nil}{\cptoxdetok{#2}\trimparser@nil}{}{% - \cptexpandsecond{\def\cpt@trimc####1}\cpt@tempd\trimparser@nil{% + \xifinsetFT{\cpt@tempd\trimpr@nil}{\cptoxdetok{#2}\trimpr@nil}{}{% + \cptexpandsecond + {\def\cpt@trimc####1}\cpt@tempd\trimpr@nil{% \edef#2{\expandcsonce{\@gobble####1}}% \cpt@trimb }% - \expandafter\cpt@trimc\expandafter.#2\trimparser@nil + \expandafter\cpt@trimc\expandafter.#2\trimpr@nil }% }% \defpass\cpt@trima{% - \xifinsetTF{\trimparser@nil\cpt@tempd}{\trimparser@nil\cptoxdetok{#2}}{% - \expandafter\def\expandafter\cpt@trimc\cpt@tempd####1\trimparser@nil{% + \xifinsetTF{\trimpr@nil\cpt@tempd}{\trimpr@nil\cptoxdetok{#2}}{% + \expandafter\def\expandafter\cpt@trimc + \cpt@tempd####1\trimpr@nil{% \edef#2{\unexpanded{####1}}% \cpt@trima }% - \expandafter\cpt@trimc#2\trimparser@nil + \expandafter\cpt@trimc#2\trimpr@nil }{% \cpt@trimb }% @@ -1579,22 +2048,22 @@ \robust@def\cpt@stripouterbraces[#1]{% \begingroup \def\after@def##1##2##3{\exitgroupdef{##3}}% - \let\nr\z@ + \@tempcnta\z@ \catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \cpt@str@pouterbraces{#1}% } \robust@def\cpt@str@pouterbraces#1#2#3{% - \edef\nr{\the\numexpr\nr+1}% + \advance\@tempcnta\@ne \edef#3{\unexpanded{#2}}% \cpt@str@pouterbr@ces#2\strip@nil#3#1% } \robust@def\cpt@str@pouterbr@ces#1\strip@nil#2#3{% - \defcmp@ifx{#1}#2% + \defcmpifx{#1}#2% \expandafter\after@def \else - \ifnum\nr>#3\relax + \ifnum\@tempcnta>#3\relax \cptthreexp\after@def \else \cptthreexp\cpt@str@pouterbraces @@ -1603,100 +2072,63 @@ {#3}{#1}{#2}% } \robust@def\stripallouterbraces#1#2{% - \edef#2{% - \unexpanded\cptthreexp{\cpt@stripallouterbraces{#1}}% - }% + \edef#2{\unexpanded\cptthreexp{\cpt@stripallouterbraces{#1}}}% } \robust@def\stripallouterbraces@incs#1{% \expandafter\stripallouterbraces\expandafter{#1}#1% } +%% Based on a solution by Ulrich Diez: \robust@def\cpt@stripallouterbraces#1{% - \cpt@rnm\ifbracedTF{#1}{% - \expandafter\ifnullTF\expandafter{\@secondoftwo#1{}}{% + \romannumeral\ifbracedTF{#1}{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% \expandafter\@gobble\cpt@stripallouterbraces#1% }{0 #1}% }{0 #1}% } -\robust@def\defcmp@ifx#1#2{% +%% + +\robust@def\defcmpifx#1#2{% \begingroup \edef\cpt@tempa{\unexpanded{#1}}% \expandafter\endgroup\ifx#2\cpt@tempa } -\robust@def\defcmp@ifxTF#1#2{% +\robust@def\defcmpifxTF#1#2{% \begingroup \edef\cpt@tempa{\unexpanded{#1}}% \ifxTF#2\cpt@tempa {\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% } +\robust@def\defcmpifxFT#1#2{% + \defcmpifxTF{#1}{#2}\@secondoftwo\@firstoftwo +} +\robust@def\cpt@starafter#1#2{% + \begingroup + \def\cpt@tempa{#1}% + \def\cpt@tempb##1{#1{#2}}% + \def\cpt@tempc{\futurelet\next\cpt@staract}% + \cpt@tempc +} +\new@def*\cpt@staract{% + \ifxTF\@sptoken\next{% + \afterassignment\cpt@tempc\let\next= % + }{% + \cptpassexpanded{\endgroup + \ifxTF*\next{\expandcsonce\cpt@tempb}% + {\expandcsonce\cpt@tempa}% + }% + }% +} \robust@def*\cptbracearg{\cpt@testopt\cpt@bracearg\@ne} \robust@def\cpt@bracearg[#1]#2#3{% \begingroup - \let\nr\z@ + \@tempcnta\z@ \loop \edef#3{\unexpanded{{#2}}}% - \pushnumber\nr - \ifnum\nr<#1\relax + \advance\@tempcnta\@ne + \ifnum\@tempcnta<#1\relax \repeat \exitgroupdef#3% } -\defpass\cpt@tempa#1{% - \new@def\xp@despace##1{% - \cpt@rnm-`\q\cpt@normaldespace.##1\despace@nil#1\despace@nil - }% - \robust@def\normal@despace##1##2{% - \edef##2{% - \unexpanded\expandafter - {\cpt@rnm-`\q\cpt@normaldespace.##1\despace@nil#1\despace@nil}% - }% - }% - \robust@def\cpt@normaldespace##1#1\despace@nil{% - \cpt@norm@ldespace##1\despace@nil - }% - \robust@def\cpt@norm@ldespace##1\despace@nil##2{% - \expandafter\noexpand\@gobble##1% - }% -}{ } -\robust@def\robust@despace#1#2{% - \edef#2{\unexpanded{#1}}% - \let\despace@tempa#2% - \normal@despace{#1}#2% - \ifxTF#2\despace@tempa{}{% - \expandafter\robust@despace\expandafter{#2}#2% - }% -} -\new@def*\despacecs{\cpt@testpm\cpt@despacecs} -\new@def*\cpt@despacecs#1{% - \usecsn{\ifcpt@pm robust\else normal\fi @despacecontent}{#1}% -} -\robust@def*\normal@despacecontent#1{% - \expandafter\normal@despace\expandafter{#1}#1% -} -\robust@def*\robust@despacecontent#1{% - \expandafter\robust@despace\expandafter{#1}#1% -} -\robust@def*\normal@despacecsvlist{% - \let\despace@type\z@ - \cpt@testopt\cpt@despacecsvlist{,}% -} -\robust@def*\robust@despacecsvlist{% - \let\despace@type\@ne - \cpt@testopt\cpt@despacecsvlist{,}% -} -\robust@def*\cpt@despacecsvlist[#1]#2{% - \begingroup - \let\cpt@rsvdb\@empty - \UseEmptyEntry - \ifnum\despace@type=\z@\let\do\normal@despace\else - \let\do\robust@despace\fi - \def\fifo@do##1{% - \do{##1}\cpt@rsvda - \cpt@sttrue\cpt@addtolist[#1]\cpt@rsvdb\cpt@rsvda - }% - \cpt@sttrue\cpt@oneDfifo[#1]{#2}% - \let#2\cpt@rsvdb - \exitgroupdef#2% - \undefcs\despace@type -} \new@edef*\ifcptmacroTF#1{% \unexpanded{\expandafter\cpt@ifmacro\meaning}% #1\detokenize{macro}:\cpt@nil @@ -1705,7 +2137,11 @@ \edef\cpt@ifmacro{% \def\noexpand\cpt@ifmacro##1\detokenize{macro}:##2\cpt@nil } +\robust@def*\csnmeaning#1{\aftercsname\meaning{#1}} \cpt@ifmacro{\usecsn{@\ifblankTF{#2}{second}{first}oftwo}} +\robust@def*\cpt@nomacroerr#1{% + \cpt@err{Argument '\detokenize{#1}' isn't a macro}\@ehc +} \robust@def*\ifescapedTF#1{% \begingroup\escapechar92\relax \edef\cpt@tempa{\expandafter\cpt@car\string#1x\car@nil}% @@ -1713,20 +2149,25 @@ \@backslashchar first\else second\fi oftwo}% } \robust@def*\ifescapedFT#1{\ifescapedTF{#1}\@secondoftwo\@firstoftwo} -\newcommand*\simplerobustify[1]{% - \def\fifo@do##1{% - \ifescapedTF{##1}{% - \ifdefTF##1{% - \aftercsname\newletcs{rcv@\cptgobblescape##1}##1% - \protected\edef##1{\noexpandcsn{rcv@\cptgobblescape##1}}% +\ifcptdefinable\robustaliascount\relax +\newcommand*\cptrobustify[1]{% + \def\comma@do##1{% + \normal@despace{##1}\cpt@tempa + \simpleexpandarg\ifescapedTF\cpt@tempa{% + \oifdefTF\cpt@tempa{% + \cptexpandsecondonce{\aftercsname\newletcs + {rsv@\expandafter\cptremovescape\cpt@tempa}}\cpt@tempa + \expandafter\protected\expandafter\edef\cpt@tempa + {\noexpandcsn{rsv@\expandafter\cptremovescape\cpt@tempa}}% + \pushnumber\robustaliascount }{% - \cpt@err{Command '\string##1' undefined}\@ehc + \cpt@err{Command '\string\cpt@tempa' undefined}\@ehc }% }{% - \cpt@err{String '\detokenize{##1}' not escaped}\@ehc + \cpt@err{String '\detokenize{\cpt@tempa}' not escaped}\@ehc }% }% - \simplefifoloop{#1}% + \comma@@loop{#1}% } \robust@def*\leftaddtocs{% \let\cpt@def\edef\let\swap\cptswap\cpt@addtocs @@ -1744,6 +2185,23 @@ \robust@def*\grightaddtocsn{\aftercsname\grightaddtocs} \robust@def*\leftaddtocsn{\aftercsname\leftaddtocs} \robust@def*\gleftaddtocsn{\aftercsname\gleftaddtocs} +\robust@def*\cpteveryscantokens{% + \everyeof{\noexpand}% + \endlinechar\m@ne + \makeatletter + \catcode`\ =10 + \catcode`\\\z@ + \catcode`\{\@ne + \catcode`\}\tw@ +} +% #1 must be a non-parametered macro: +\robust@def*\cptscantokens#1{% + \begingroup + \edef#1{\long\def\string#1{\cptoxdetok{#1}}}% + \cpteveryscantokens + \scantokens\expandafter{#1}\relax + \exitgroupdef#1% +} \robust@def\cpt@addtocs#1#2{% \cpt@getmacroprefix{#1}% \ifdefTF#1{% @@ -1755,22 +2213,69 @@ } \robust@def*\cpt@getmacroprefix#1{% \begingroup - \edef\cpt@tempa##1{\def##1####1\detokenize{macro}:####2\cpt@unique}% + \edef\cpt@tempa##1{\def##1####1\detokenize{macro}:####2\noboundary}% \cpt@tempa\@ifmacro{% \def\macroprefix{##1}% \usecsn{@\ifblankTF{##2}{second}{first}oftwo}% }% - \edef\cpt@tempb##1{##1\detokenize{macro}:\cpt@unique}% + \edef\cpt@tempb##1{##1\detokenize{macro}:\noboundary}% \cpt@tempb{\expandafter\@ifmacro\meaning#1}{% \@testtrue }{% \@testfalse\def\macroprefix{}% }% + \cpteveryscantokens \cptpassexpanded{% \endgroup\noexpand\scantokens {\def\noexpand\macroprefix{\macroprefix}\relax}% }% } +\robust@def*\cpt@gettogswstate#1{% + \lowercase{% + \ifinsetTF{,#1,}{,true,on,}{% + \let\cpt@togswstate\@firstoftwo + }{% + \ifinsetTF{,#1,}{,false,off,}{% + \let\cpt@togswstate\@secondoftwo + }{% + \@latex@error{Invalid toggle switch value '#1'}% + {Valid toggle switch values are 'true' and 'false'.}% + }% + }% + }% +} +\robust@def*\cpt@undeftogswerr#1{% + \cpt@err{Toggle switch '#1' undefined}\@ehc +} +\robust@def*\settogswtrue#1{% + \ifcsndefTF{cpt@togsw@#1}{% + \letcsntocs{cpt@togsw@#1}\@firstoftwo + }{\cpt@undeftogswerr{#1}}% +} +\robust@def*\settogswfalse#1{% + \ifcsndefTF{cpt@togsw@#1}{% + \letcsntocs{cpt@togsw@#1}\@secondoftwo + }{\cpt@undeftogswerr{#1}}% +} +\new@def*\iftogswTF#1{% + \ifcsndefTF{cpt@togsw@#1}% + {\usecsn{cpt@togsw@#1}}% + {\cpt@undeftogswerr{#1}\@gobbletwo}% +} +\new@def*\iftogswFT#1{\iftogswTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\settogsw#1#2{% + \ifcsndefTF{cpt@togsw@#1}{% + \cpt@gettogswstate{#2}% + \letcsntocs{cpt@togsw@#1}\cpt@togswstate + }{\cpt@undeftogswerr{#1}}% +} +\robust@def*\killtogsw#1{% + \ifcsndefTF{cpt@togsw@#1}{% + \letcsntocs{cpt@togsw@#1}\cpt@undefined + }{% + \cpt@info{Toggle switch '#1' not defined: not killed}% + }% +} \robust@def*\BeforeStartOfDocument{% \grightaddtocs\cpt@beforestartdoc@hook } @@ -1796,22 +2301,72 @@ } \gleftaddtocs\@popfilename{% \usecsn{% - @\ifcsname\@currname.\@currext-cpt@h@@k\endcsname + @\ifcsname\@currname.\@currext-cpt@hook\endcsname iden\else gobble\fi }% - {\usecsn{\@currname.\@currext-cpt@h@@k}}% - \gundefcsn{\@currname.\@currext-cpt@h@@k}% + {\usecsn{\@currname.\@currext-cpt@hook}}% + \gundefcsn{\@currname.\@currext-cpt@hook}% } -\def\cptloadpackages#1{% - \ifcsnullTF\@currname{% - \cpt@err{Not in a style or class file}\@ehc - }{% - \def\cpt@loadpackages##1##2##3\cpt@nil{% - \@ifpackageloaded{##1}{}{\RequirePackage[##2]{##1}[##3]}% +\robust@def*\ifpackagewithTF{\cpt@ifoptions\@pkgextension} +\robust@def*\ifclasswithTF{\cpt@ifoptions\@clsextension} +\robust@def*\cpt@ifoptions#1#2{% + \cptexpandarg\cpt@ifopti@ns{\cpt@optionlist{#2.#1}}% +} +\robust@def*\cpt@ifopti@ns#1#2{% + \cpt@stfalse\cpt@kvnormalize[,]{#1}% + \let\temp@optlist\cpt@normalizedlist + \cpt@choicefdtrue + \def\kv@do##1{% + \if@sp@inlistTF,{##1}\temp@optlist + {}{\cpt@choicefdfalse\cptbreakloop}% + }% + \kv@@parse{#2}% + \undefcs\temp@optlist + \if@boolTF{cpt@choicefd}\@firstoftwo\@secondoftwo +} +\robust@def*\ifpackageafterTF{\cpt@ifpkgafter\@pkgextension} +\robust@def*\ifclassafterTF{\cpt@ifpkgafter\@clsextension} +\robust@def*\cpt@ifpkgafter#1#2#3{% + \usecsn{@if#1loaded}{#2}{}{% + \AfterStartOfDocument{% + \usecsn{@if#1loaded}{#2}{% + \cpt@warn{\@cls@pkg '#2' was loaded afterwards}% + #3\relax + }{}% }% - \@useemptyfalse - \normalxDloop{#1}\cpt@tempa{% - \expandafter\cpt@loadpackages\cpt@tempa\cpt@nil + }% +} +\robust@def*\cptloadpackages{% + \begingroup + \toks@{}% + \begingroup + \catcode`\;=12\catcode`\|=12 + \endlinechar\m@ne + \expandafter\endgroup\cpt@loadpackages +} +\robust@def\cpt@loadpackages#1{% + \cpt@useemptyfalse + \def\csv@do##1{% + \cpt@lo@dpackages##1|||\cpt@nil + }% + \csv@@parse[;]{#1}% + \expandafter\endgroup\the\toks@ +} +\robust@def\cpt@lo@dpackages#1|#2|#3|#4\cpt@nil{% + \stripallouterbraces{#2}\cpt@tempb + \cpt@sttrue\cpt@kvnormalize[,]\cpt@tempb + \@ifpackageloaded{#1}{% + \edef\cpt@tempa{\cpt@optionlist{#1.\@pkgextension}}% + \ifx\cpt@tempa\cpt@tempb\else + \cpt@err{Option clash for package #1.\@pkgextension}\@ehc + \expandafter\@gobbletwo + \fi + }{% + \cptexpanded{% + \cptaddtotoks0{% + \ifcsnullTF\@currname{\noexpand\usepackage}{% + \noexpand\RequirePackage}[\cpt@tempb]{#1}[#3]% + }% }% }% } @@ -1819,7 +2374,7 @@ \begingroup \def\cpt@tempa{\endgroup \expandafter\grightaddtocs - \csname\@currname.\@currext-cpt@h@@k\endcsname + \csname\@currname.\@currext-cpt@hook\endcsname }% \ifcsnullTF\@currname\endgroup\cpt@tempa } @@ -1875,51 +2430,36 @@ \edef#2{\the\toks@}% \exitgroupdef#2% } -\robust@def*\cpteveryscantokens{% - \everyeof{\noexpand}% - \endlinechar\m@ne - \makeatletter - \catcode`\ =10\relax - \catcode`\\\z@ - \catcode`\{\@ne - \catcode`\}\tw@ -} -\robust@def*\cptscantokens#1{% - \begingroup - \edef#1{\def\string#1{\cptoxdetok{#1}}}% - \cpteveryscantokens - \scantokens\expandafter{#1}\relax - \exitgroupdef#1% -} \cptonlypreamble{% - \cptpushcatcodes,\cptpopcatcodes, - \UseNormalCatcodes,\rc@UseNormalCatcodes, - \StyleFilePurpose,\StyleFileInfo,\AfterEndOfStyleFile, - \StyleFileRCSInfo,\SetStyleFileMessages, - \XDeclareOption,\XDeclareCommandOption,\XDeclareBooleanOption, - \XDeclareCommandOptions,\XDeclareBooleanOptions, + \cptloadpackages,\ifpackagewithTF,\ifclasswithTF,\cpt@ifoptions, + \cptpushcatcodes,\cptpopcatcodes,\UseNormalCatcodes, + \rsv@UseNormalCatcodes,\StyleFilePurpose,\StyleFileInfo, + \AfterEndOfStyleFile,\StyleFileRCSInfo,\SetStyleFileMessages, + \XDeclareOption,\XDeclareOptions,\XDeclareCommandOption, + \XDeclareCommandOptions,\XDeclareBooleanOption,\XDeclareBooleanOptions, \XDeclareBiBooleanOptions,\XProcessOptions,\XExecuteOptions, - \cpt@processedoptions,\cpt@optionlist,\cpt@splitoption, - \cpt@processoptions,\cpt@xprocessoptions,\cpt@pr@cessoptions, - \cpt@pr@c@ssoptions,\BeforeStartOfDocument, - \AfterStartOfDocument + \cpt@processedoptions,\cpt@optionlist,\cpt@findoption@a, + \cpt@findoption@b,\cpt@processoptions,\cpt@xprocessoptions, + \cpt@yprocessoptions,\cpt@pr@cessoptions,\BeforeStartOfDocument, + \AfterStartOfDocument,\XInvalidOptionHandler,\XDeclareInvalidOption, + \XDeclareInvalidOptions,\XUnknownOptionHandler,\ExternalOptions } \robust@def*\csv@@normalize{\cpt@teststoptb\cpt@csvnormalize} \robust@def\cpt@csvnormalize[#1]#2{% - \let\normalize@listtype\z@ - \csv@kv@normalize{#1}{#2}\normalized@csvlist + \chardef\normalize@listtype\z@ + \csv@kv@normalize{#1}{#2}\cpt@normalizedlist } \robust@def*\kv@@normalize{\cpt@teststoptb\cpt@kvnormalize} \robust@def\cpt@kvnormalize[#1]#2{% - \let\normalize@listtype\@ne - \csv@kv@normalize{#1}{#2}\normalized@kvlist + \chardef\normalize@listtype\@ne + \csv@kv@normalize{#1}{#2}\cpt@normalizedlist } \robust@def\csv@kv@normalize#1#2#3{% - \let\if@normst\ifcpt@st + \let\ifcpt@normst\ifcpt@st \cpt@checklistparser{#1}\relax \begingroup \expandafter\setup@parser@normalize\string#1% - \if@normst + \ifcpt@normst \toks@\expandafter{\expandafter#1#2#1}% \else \toks@{#1#2#1}% @@ -1928,18 +2468,18 @@ \expandafter\normalize@spaceletter\string#1% \expandafter\normalize@letterspace\string#1% \expandafter\normalize@doubleletter\string#1% - \ifnumFT\normalize@listtype=\@ne{}{% + \ifnumcmpFT\normalize@listtype=\@ne{}{% \normalize@activeequal \expandafter\normalize@spaceletter\string=% \expandafter\normalize@letterspace\string=% \expandafter\normalize@doubleletter\string=% - \commaequal@err + \cpt@commaequalerr }% \edef#3{\the\toks@}% \expandafter\cpttrimparser\expandafter[\string#1]#3% \exitgroupdef#3% - \if@normst\let#2#3\undefcs#3\fi - \undefcs\if@normst + \ifcpt@normst\let#2#3\undefcs#3\fi + \undefcs\ifcpt@normst } \def\setup@parser@normalize#1{% \begingroup @@ -1956,7 +2496,8 @@ }% } \begingroup -\uccode`\~\string=`\=% +\catcode`\=\string=12 +\uccode`\~=`\=% \uppercase{\endgroup \def\normalize@activeequal{% \def\cpt@tempa##1~##2\cpt@nil{% @@ -2006,7 +2547,7 @@ \expandafter\cpt@tempa\the\toks@##1#1\cpt@nil }% }{ } -\robust@def*\commaequal@err{% +\robust@def*\cpt@commaequalerr{% \def\cpt@tempa##1,=##2\cpt@nil{% \ifblankTF{##2}{}{% \cpt@err{There is 'comma' next to 'equal' (,=) in @@ -2017,8 +2558,8 @@ } \let\cpt@documentclass\cpt@undefined \robust@def*\cpt@getdocumentclass{% - \normaloneDloop*\@filelist\cpt@tempa{% - \filename@parse\cpt@tempa + \def\csv@do##1{% + \filename@parse{##1}% \ifx\filename@ext\@clsextension \ifcsndefFT{opt@\filename@area\filename@base.\filename@ext}{}{% \xdef\cpt@documentclass{% @@ -2026,24 +2567,20 @@ }% }% \fi - \ifx\cpt@documentclass\cpt@undefined\else\@breaklooptrue\fi + \ifx\cpt@documentclass\cpt@undefined\else\cpt@breaklooptrue\fi }% + \csv@@parse*\@filelist \ifdefTF\cpt@documentclass{}{% \@latex@info@no@line{'catoptions' package loaded before \string\documentclass: \MsgBrk no problem}% }% } -\cptpassunexpanded{% - \ifx\@filelist\relax - \else - \ifx\@filelist\@gobble - \else - \ifx\@filelist\@empty - \else - \cptsevenxp\cpt@getdocumentclass - \fi - \fi - \fi +\cptpassasis{% + \ifxTF\@filelist\relax{}{% + \ifxTF\@filelist\@gobble{}{% + \ifxTF\@filelist\@empty\relax\cpt@getdocumentclass + }% + }% \ifxTF\cpt@documentclass\cpt@undefined{% \let\cpt@documentclass\@empty \let\cpt@classoptionslist\@empty @@ -2054,16 +2591,28 @@ }% }% \let\cpt@classoptionslist\@classoptionslist - \cptexpandargonce{\emptify\@classoptionslist - \normaloneDloop}\@classoptionslist\cpt@tempa{% - \oifinsetTF{=}\cpt@tempa{}{% - \cptaddtocommalist\@classoptionslist\cpt@tempa + \def\@fileswith@ptions##1[##2]##3{% + \ifstreqTF{##3}{xkeyval}{% + \let\@classoptionslist\cpt@classoptionslist + }{% + \ifstreqFT{##3}{kvoptions}{}{% + \let\@classoptionslist\cpt@classoptionslist + }% }% + \cpt@ifbrack{\@fileswith@pti@ns##1[##2]##3}% + {\@fileswith@pti@ns##1[##2]##3[]}% }% + \def\comma@do##1{% + \ifinsetTF{=}{##1}{}{% + \cptgaddtolist\@classoptionslist{##1}% + }% + }% + \cptexpandargonce{\emptify\@classoptionslist\comma@@loop}% + \@classoptionslist }% } \robust@def*\cpt@testfam#1{% - \cpt@ifnextchar<{#1}{#1<{\@currname.\@currext}>}% + \cpt@ifnextchar<{#1}{#1<\@currname.\@currext>}% } \robust@redef\@pass@ptions#1#2#3{% \begingroup @@ -2089,14 +2638,14 @@ } \robust@redef*\OptionNotUsed{% \ifx\@currext\@clsextension - \cptaddtocommalist\@unusedoptionlist\CurrentOption + \cptexpandargonce{\cpt@filtermergelists[,]% + \@unusedoptionlist}\CurrentOption\nofilter \fi } \robust@redef*\@use@ption{% - \xifinsetFT{,\cptoxdetok\CurrentOption,}% - {,\cptoxdetok\@unusedoptionlist,}{}{% - \cptexpandargonce{\cpt@killoneelement[,]}\CurrentOption - \@unusedoptionlist + \if@sp@inlistFT,\CurrentOption\@unusedoptionlist{}{% + \cptexpandargonce{\cpt@filterremoveelements[,]% + \@unusedoptionlist}\CurrentOption\nofilter }% \csname ds@\CurrentOption\endcsname } @@ -2120,62 +2669,81 @@ }{% \edef\cpt@tempa{\cptzapspaces{#3}}% \DiscardEmptyEntry - \normaloneDloop*\cpt@tempa\cpt@tempa{% - \file@withopts{\the\toks@\fileswithopts{\cpt@tempa}\@pkgextension}% + \def\csv@do##1{% + \file@withopts{\the\toks@\fileswithopts{##1}\@pkgextension}% }% + \csv@@loop*\cpt@tempa }% \expandafter\endgroup\the\toks@ } \let\@@fileswith@pti@ns\@fileswith@pti@ns -\robust@def*\RecoverAtEndOfPackage#1{% - \letcsntocs{rc@\expandafter\@gobble\string#1}#1% - \begingroup - \edef\cpt@tempa{% - \let\unexpanded{#1}% - \noexpandcsn{rc@\expandafter\@gobble\string#1}% +\robust@def*\RecoverAtRequirePackage#1{% + \ifblankFT{#1}{}{% + \cpt@err{Blank argument to command + \string\RecoverAtRequirePackage}\@ehc + \@gobble }% + \begingroup \edef\cpt@tempb{\expandcsnonce{\@currname.\@currext-h@@k}}% - \xifinsetTF{\cptoxdetok\cpt@tempa}{\cptoxdetok\cpt@tempb}{}{% - \expandafter\AtEndOfPackage\expandafter{\cpt@tempa}% - }% - \xifinsetTF{\cptoxdetok\cpt@tempa}{\cptoxdetok\RequirePackage}{}{% - \xdef\RequirePackage{% - \expandcsonce\cpt@tempa\expandcsonce\RequirePackage + \def\comma@do##1{% + \ifescapedTF{##1}{% + \ifdefTF#1{}{% + \cpt@err{Undefined argument to command\MsgBrk + \string\RecoverAtRequirePackage}\@ehc + }% + }{% + \cpt@err{Non-escaped argument to command\MsgBrk + \string\RecoverAtRequirePackage}\@ehc + \@gobble + }% + \cptthreexp\ifcptdefinable\usecsn{rsv@\cptremovescape##1}{% + \gletcsntocs{rsv@\cptremovescape##1}##1% + }% + \edef\cpt@tempa{% + \cptglet\unexpanded{##1}=\noexpandcsn{rsv@\cptremovescape##1}% + }% + \xifinsetTF{\cptoxdetok\cpt@tempa}{\cptoxdetok\cpt@tempb}{}{% + \expandafter\AtEndOfPackage\expandafter{\cpt@tempa}% + }% + \xifinsetTF{\cptoxdetok\cpt@tempa}{\cptoxdetok\RequirePackage}{}{% + \xdef\RequirePackage{% + \expandcsonce\cpt@tempa\expandcsonce\RequirePackage + }% }% }% + \comma@@loop{#1}% \endgroup } -\RecoverAtEndOfPackage\cpt@defdefault@ds -\robust@def*\cpt@badoptionerr{% - \expandafter\ifescapedTF\expandafter{\curropt}{% - \cpt@err{Bad option name '\expandcsonce\curropt'}\@ehc +\robust@def*\cpt@badoptionerr#1{% + \expandafter\ifescapedTF\expandafter{#1}{% + \cpt@err{Bad option name '\expandcsonce{#1}'}\@ehc }{% - \expandafter\ifcptmacroFT\expandafter{\curropt}{}{% - \cpt@err{Bad option name '\expandcsonce\curropt'}\@ehc + \expandafter\ifcptmacroFT\expandafter{#1}{}{% + \cpt@err{Bad option name '\expandcsonce{#1}'}\@ehc }% }% } \robust@def*\XDeclareOption{% \let\@fileswith@pti@ns\@badrequireerror \cpt@ifstar - {\cpt@testfam\cpt@defdefault@ds}% + {\cpt@testfam\cpt@define@default@ds}% {\cpt@testfam\cpt@declareoption}% } \robust@def*\cpt@declareoption<#1>#2{% - \normal@despace{#1}\currfam - \normal@despace{#2}\curropt - \cpt@badoptionerr + \normal@despace{#1}\cpt@currfam + \normal@despace{#2}\cpt@curropt + \cpt@badoptionerr\cpt@curropt \cptexpandarg\cpt@testopt - {\cpt@d@clareoption{\currfam}{\curropt}}{}% + {\cpt@d@clareoption{\cpt@currfam}{\cpt@curropt}}{}% } \robust@def\cpt@d@clareoption#1#2[#3]#4{% \cpt@d@cl@reoption{#1}{#2}{#3}% \if@boolTF{cpt@olddx}{% - \global\long\csn@edef{#1@ds@#2}{\unexpanded{#4}}% + \long\csn@xdef{#1@ds@#2}{\unexpanded{#4}}% }{% \begingroup \long\def\cpt@tempa##1{\endgroup - \global\long\csn@def{#1@ds@#2}####1{##1}% + \long\csn@gdef{#1@ds@#2}####1{##1}% }% \cpt@tempa{#4}% }% @@ -2195,38 +2763,98 @@ } \robust@def\cpt@d@clareoptions#1#2[#3]#4{% \edef\curr@fam{\xp@despace{#1}}% - \def\curr@opts{#2}% - \cpt@sttrue\cpt@csvnormalize[,]\curr@opts - \def\fifo@do##1{% - \def\curropt{##1}% - \cpt@badoptionerr - \expandafter\cpt@d@clareoption - \expandafter{\curr@fam}{##1}[#3]{#4}% + \def\csv@do##1{% + \cpt@badoptionerr{##1}% + \simpleexpandarg\cpt@d@clareoption\curr@fam{##1}[#3]{#4}% }% - \cpt@stfalse\cptexpandargonce{\cpt@xDfifo[,]}\curr@opts - \undefcs\curr@opts\undefcs\curr@fam + \csv@@parse[,]{#2}% + \undefcs\curr@fam +} + +\robust@def*\XInvalidOptionHandler{% + \cpt@testfam\cpt@invalidoptionhandler +} +\robust@def*\cpt@invalidoptionhandler<#1>#2{% + \def\comma@do##1{% + \normal@despace{##1}\cpt@currfam + \ifcsndefTF{\cpt@currfam @invalidoptionerr}{% + \cpt@err{Invalid option handler already defined + \MsgBrk for family '\cpt@currfam'}{% + Second invalid option handler for family + '\cpt@currfam'? + }% + }{% + \csn@gdef{\cpt@currfam @invalidoptionerr}####1{#2####1}% + }% + }% + \comma@@loop{#1}% +} +\robust@def*\XDeclareInvalidOptions{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@ifstar{% + \cpt@err{Invalid star suffix for command + \MsgBrk\string\XDeclareInvalidOption}\@ehc + }{% + \cpt@testfam\cpt@declarenulloptions + }% +} +\newletcs\XDeclareInvalidOption\XDeclareInvalidOptions +\robust@def*\cpt@declarenulloptions<#1>#2{% + \def\csv@do##1{% + \cpt@d@clarenulloptions{##1}{#2}% + }% + \csv@@parse[,]{#1}% + \cpt@olddxfalse +} +\robust@def*\cpt@d@clarenulloptions#1#2{% + \def\csv@do##1{% + \ifcsndefTF{#1@ds@##1}{% + \cpt@err{Option '##1' of family '#1' + \MsgBrk is already defined}\@ehc + }{% + \cpt@badoptionerr{##1}% + \cpt@d@cl@reoption{#1}{##1}{}% + \ifcsndefTF{#1@invalidoptionerr}{% + \gletcsntocsn{#1@ds@##1}{#1@invalidoptionerr}% + }{% + \begingroup + \def\cpt@temp@err{% + \cpt@err{Option '##1' of family '#1' + \MsgBrk is invalid or null}{% + Invalid option '##1' of family '#1'.}% + }% + \if@boolTF{cpt@olddx}{% + \long\csn@xdef{#1@ds@##1}{\cpt@temp@err}% + }{% + \long\csn@xdef{#1@ds@##1}####1{\cpt@temp@err}% + }% + \endgroup + }% + }% + }% + \csv@@parse[,]{#2}% } \robust@def*\XDeclareCommandOption{% \let\@fileswith@pti@ns\@badrequireerror - \let\cmdoption\@ne + \chardef\cmdoption\@ne \cpt@testfam\cpt@declarecmdoption } \robust@def*\XDeclareCommandOptions{% \let\@fileswith@pti@ns\@badrequireerror - \let\cmdoption\@ne + \chardef\cmdoption\@ne \cpt@testfam\cpt@declarecmdoptions } \robust@def*\XDeclareBooleanOption{% \let\@fileswith@pti@ns\@badrequireerror - \let\cmdoption\z@ + \chardef\cmdoption\z@ \cpt@testfam\cpt@declarecmdoption } \robust@def*\cpt@declarecmdoption<#1>#2{% - \normal@despace{#1}\currfam - \normal@despace{#2}\curropt - \cpt@badoptionerr + \normal@despace{#1}\cpt@currfam + \normal@despace{#2}\cpt@curropt + \cpt@badoptionerr\cpt@curropt \cptexpandarg\cpt@testopt - {\cpt@d@clarecmdoption{\currfam}{\curropt}}{}% + {\cpt@d@clarecmdoption{\cpt@currfam}{\cpt@curropt}}{}% } \robust@def\cpt@d@clarecmdoption#1#2[#3]{% \cptexpandarg{\cpt@testpnopt{\cpt@d@cl@recmdoption @@ -2235,24 +2863,24 @@ \robust@def\cpt@d@cl@recmdoption#1#2#3(#4)#5{% \cpt@d@cl@reoption{#1}{#2}{#3}% \ifnum\cmdoption=\@ne - \def\cpt@rsvda{\csn@def{#4#2}{####1}}% + \def\cpt@resa{\csn@def{#4#2}{####1}}% \else - \cptexpandsecond{\usecsn{newif}}{\noexpandcsn{if#4#2}}% - \def\cpt@rsvda{% + \csn@newif{#4#2}% + \def\cpt@resa{% \ifinsetTF{,####1,}{,true,false,}{}{% \@latex@error{Invalid value for option '#2'}\@ehc }% \cptuse{#4#2####1}% }% \fi - \long\def\cpt@rsvdb##1{% + \long\def\cpt@resb##1{% \long\csn@gdef{#1@ds@#2}####1{##1\relax}% }% - \expandafter\cpt@rsvdb\expandafter{\cpt@rsvda#5}% + \expandafter\cpt@resb\expandafter{\cpt@resa#5}% } \robust@def*\XDeclareBooleanOptions{% \let\@fileswith@pti@ns\@badrequireerror - \let\cmdoption\z@ + \chardef\cmdoption\z@ \cpt@testfam\cpt@declarecmdoptions } \robust@def*\cpt@declarecmdoptions<#1>#2{% @@ -2264,27 +2892,23 @@ } \robust@def\cpt@d@cl@recmdoptions#1#2#3(#4)#5{% \edef\curr@fam{\xp@despace{#1}}% - \def\curr@opts{#2}% - \cpt@sttrue\cpt@csvnormalize[,]\curr@opts - \def\fifo@do##1{% - \def\curropt{##1}% - \cpt@badoptionerr - \expandafter\cpt@d@cl@recmdoption - \expandafter{\curr@fam}{##1}{#3}(#4){#5}% + \def\csv@do##1{% + \cpt@badoptionerr{##1}% + \simpleexpandarg\cpt@d@cl@recmdoption\curr@fam{##1}{#3}(#4){#5}% }% - \cpt@stfalse\cptexpandargonce{\cpt@xDfifo[,]}\curr@opts - \undefcs\curr@opts\undefcs\curr@fam + \csv@@parse[,]{#2}% + \undefcs\curr@fam } \robust@def*\XDeclareBiBooleanOptions{% \let\@fileswith@pti@ns\@badrequireerror - \let\cmdoption\z@ + \chardef\cmdoption\z@ \cpt@testfam\cpt@declarebibooloptions } \robust@def*\cpt@declarebibooloptions<#1>#2{% \begingroup \@tempcnta\z@ - \def\fifo@do##1{\advance\@tempcnta\@ne}% - \simplefifoloop{#2}% + \def\comma@do##1{\advance\@tempcnta\@ne}% + \comma@@loop{#2}% \ifnum\@tempcnta>\tw@ \cpt@err{Biboolean options '#2' more than 2}\@ehc \aftergroup\@gobble @@ -2305,79 +2929,235 @@ \edef\curr@fam{\xp@despace{#1}}% \def\curr@opts{#2}% \cpt@sttrue\cpt@csvnormalize[,]\curr@opts - \edef\do@prompted##1##2##3{% - \unexpanded{\cptsevenxp\ifstrcmpTF\cptthreexp}% - {\noexpand\csname#4##1@prompted\noexpand\endcsname}{true}{}{% - \XExecuteOptions<\curr@fam>{##2=##3}% - }% - }% \begingroup \def\cpt@tempa##1,##2\cpt@nil{% - \endgroup - \csn@def{#4##1@prompted}{false}% - \csn@def{#4##2@prompted}{false}% - \simpleexpandarg\cpt@d@cl@recmdoption\curr@fam{##1}{#3}(#4){% - #5% - \csn@def{#4##2@prompted}{true}% - \ifboolTF{#4##1}{% - \do@prompted{##1}{##2}{false}% - }{% - \do@prompted{##1}{##2}{true}% + \def\cpt@tempa####1{% + \endgroup + \cpt@newv@riables{togsw}{####1@}{##1,##2}[false]% + \cpt@d@cl@recmdoption{####1}{##1}{#3}(#4){% + #5\relax + \settogswtrue{####1@##2}% + \iftogswTF{####1@##1}{}{% + \cpt@bibooltrue + \ifboolTF{#4##1}{% + \XExecuteOptions<####1>{##2=false}% + }{% + \XExecuteOptions<####1>{##2=true}% + }% + }% + \settogswfalse{####1@##2}% + \cpt@biboolfalse }% - \csn@def{#4##2@prompted}{false}% - }% - \simpleexpandarg\cpt@d@cl@recmdoption\curr@fam{##2}{#3}(#4){% - #6% - \csn@def{#4##1@prompted}{true}% - \ifboolTF{#4##2}{% - \do@prompted{##2}{##1}{false}% - }{% - \do@prompted{##2}{##1}{true}% + \cpt@d@cl@recmdoption{####1}{##2}{#3}(#4){% + #6\relax + \settogswtrue{####1@##1}% + \iftogswTF{####1@##2}{}{% + \cpt@bibooltrue + \ifboolTF{#4##2}{% + \XExecuteOptions<####1>{##1=false}% + }{% + \XExecuteOptions<####1>{##1=true}% + }% + }% + \settogswfalse{####1@##1}% + \cpt@biboolfalse }% - \csn@def{#4##1@prompted}{false}% }% + \expandafter\cpt@tempa\expandafter{\curr@fam}% }% \expandafter\cpt@tempa\curr@opts\cpt@nil \undefcs\curr@opts\undefcs\curr@fam } \robust@def\cpt@d@cl@reoption#1#2#3{% \ifcsndefTF{#1@declaredoptions}{% - \xifinsetTF{,\detokenize{#2},}{,\cpt@getdeclaredoptions{#1},}{% + \xifinsetTF{,\cptoxdetok{#2},}{,\cpt@getdeclaredoptions{#1},}{% \cpt@warn{Option '#2' multiply defined\MsgBrk in family '#1'\MsgBrk (in \@cls@pkg\@space'\@currname')% }% }{% - \cpt@stfalse - \cptexpandarg{\cpt@addtolist[,]}% - {\noexpandcsn{#1@declaredoptions}}{#2}% + \aftercsname{\cptaddtolist*}{#1@declaredoptions}{#2}% }% }{% - \csn@def{#1@declaredoptions}{#2}% + \csn@xdef{#1@declaredoptions}{\expandcsonce{#2}}% }% - \global\csn@edef{#1@ds@#2@default}{% + \csn@xdef{#1@ds@#2@default}{% \noexpandcsn{#1@ds@#2}{\unexpanded{#3}}% }% } +\robust@def*\XDisableOptions{% + \cpt@testst{% + \let\ifv@\ifcpt@st + \cpt@testfam\cpt@disableoption + }% +} +\robust@def*\cpt@disableoption<#1>#2{% + \def\csv@do##1{% + \cpt@dis@bleoption{##1}{#2}% + }% + \csv@@parse[,]{#1}% + \undefcs\ifv@ +} +\robust@def*\cpt@dis@bleoption#1#2{% + \def\csv@do##1{% + \ifcsndefFT{#1@ds@##1}{% + \cpt@info{Option '##1' of family '#1'\MsgBrk + is undeclared: not disabled} + }{% + \cptpassexpanded{% + \ifv@\noexpand\AtBeginDocument{\fi + \cpt@filtermergelists[,]% + \noexpandcsn{#1@disabledoptions}{##1}% + \noexpand\nofilter + \noexpand\undefcsn{#1@ds@##1@default}% + \csn@gdef{#1@ds@##1}{% + \noexpand\@latex@error{% + Key '##1' of families '#1' is disabled + }{% + Key '##1' of family '#1'\MsgBrk + has been disabled. You can't set or reset\MsgBrk + it at this late stage. Perhaps you should\MsgBrk + have set it earlier in \string\documentclass\MsgBrk + or \string\usepackage + }% + }% + \ifv@}\fi + }% + }% + }% + \csv@@parse[,]{#2}% +} +\robust@def*\XLogDisabledOptions{% + \cpt@ifnextchar<\cpt@disabledoptionlist + \cpt@dis@bledoptionlist +} +\robust@def*\cpt@disabledoptionlist<#1>{% + \cpt@dis@bledoptionlist{#1}% +} +\robust@def*\cpt@dis@bledoptionlist#1{% + \def\cpt@disablea##1{% + \ifcsndefTF{##1@disabledoptions}{% + \cpt@info{Disabled options of family '##1': + ^^J\expandcsnonce{##1@disabledoptions}}% + }{% + \cpt@info{No disabled options in family '##1' + \MsgBrk at this point\ifcsnullTF\@currname{} + {:\@space You can try the command + \MsgBrk\noexpand\XLogDisabledOptions again after + \MsgBrk begin document}}% + }% + }% + \def\cpt@disableb##1##2{% + \cpt@err{Command \noexpand\XLogDisabledOptions issued + \MsgBrk in document but family name contains + \MsgBrk ##1 extension \string##2, + \MsgBrk a preamble command}\@ehc + }% + \def\csv@do##1{% + \ifcsnullFT\@currname{% + \cpt@disablea{##1}% + }{% + \ifinsetTF\@pkgextension{##1}{% + \cpt@disableb{package}\@pkgextension + }{% + \ifinsetTF\@clsextension{##1}{% + \cpt@disableb{class}\@clsextension + }{% + \cpt@disablea{##1}% + }% + }% + }% + }% + \ifblankTF{#1}{}{\csv@@parse{#1}}% + \undefcsset{\cpt@disablea,\cpt@disableb}% +} +\robust@def*\ifoptdisabledTF{% + \v@true + \cpt@testfam\cpt@ifoptdisabled +} +\robust@def*\ifoptdisabledFT{% + \v@false + \cpt@testfam\cpt@ifoptdisabled +} +\robust@def*\cpt@ifoptdisabled<#1>#2{% + \cpt@choicefdfalse + \def\csv@do##1{% + \cpt@ifoptdis@bled{##1}{#2}% + }% + \csv@@parse[,]{#1}% + \if@boolTF{v@}\if@boolTF\if@boolFT{cpt@choicefd}% +} +\robust@def*\cpt@ifoptdis@bled#1#2{% + \ifcsndefFT{#1@disabledoptions}{}{% + \xifinsetFT{#2}{\expandcsnonce{#1@disabledoptions}}{}{% + \cptbreakloop\cpt@choicefdtrue + }% + }% +} +\robust@def*\ifoptdefTF{% + \v@true + \cpt@testfam\cpt@ifoptdef +} +\robust@def*\ifoptdefFT{% + \v@false + \cpt@testfam\cpt@ifoptdef +} +\robust@def*\cpt@ifoptdef<#1>#2{% + \cpt@choicefdfalse + \def\csv@do##1{% + \cpt@ifoptd@f{##1}{#2}% + }% + \csv@@parse[,]{#1}% + \if@boolTF{v@}\if@boolTF\if@boolFT{cpt@choicefd}% +} +\robust@def*\cpt@ifoptd@f#1#2{% + \ifcsndefFT{#1@ds@#2}{}{% + \cptbreakloop\cpt@choicefdtrue + }% +} \new@def*\cpt@getdeclaredoptions#1{% - \ifcsnnullTF{#1@declaredoptions}{}{% - \detokenize\cptsevenxp{\usecsn{#1@declaredoptions}}% + \ifcsndefFT{#1@declaredoptions}{}{% + \ifcsnnullTF{#1@declaredoptions}{}{% + \detokenize\cptsevenxp{\usecsn{#1@declaredoptions}}% + }% + }% +} +\robust@def*\XUnknownOptionHandler{% + \cpt@testfam\cpt@unknownoptionhandler +} +\robust@def*\cpt@unknownoptionhandler<#1>{% + \cpt@testopt{\cpt@unkn@wnoptionhandler#1}{}% +} +\robust@def*\cpt@unkn@wnoptionhandler#1[#2]#3{% + \edef\unknown@ds{% + \unexpanded{\csn@def{\cpt@tempa @default@ds}##1##2##3{#3}}% }% + \def\csv@do##1{% + \ifcsndefFT{##1@default@ds}{}{% + \cpt@warn{Unknown option handler for family + \MsgBrk '##1' replaced}% + }% + \def\cpt@tempa{##1}\unknown@ds + \csn@def{##1@default@na}{#2}% + }% + \csv@@parse[,]{#1}% + \undefcs\unknown@ds } -\robust@def*\cpt@defdefault@ds<#1>#2{% - \csn@edef{#1@default@ds}{\unexpanded{#2}}% - \protected\def\cpt@defdefault@ds<##1>##2{% +\robust@def*\cpt@define@default@ds<#1>#2{% + \csn@def{#1@default@ds}##1##2##3{#2}% + \shelldef\cpt@define@default@ds<##1>##2{% \cpt@err{'\string\XDeclareOption*' multiply defined in \MsgBrk\@cls@pkg\space'\@currname'}{Multiple star - variant of \string\XDeclareOption\@space in + variant of \noexpand\XDeclareOption in \@cls@pkg\@space'\@currname'.}% }% } -\newletcs\rc@cpt@defdefault@ds\cpt@defdefault@ds +\RecoverAtRequirePackage\cpt@define@default@ds \new@def*\cpt@optionlist#1{% \ifcsndefFT{opt@#1}{}{\unexpanded\cptsevenxp{\usecsn{opt@#1}}}% } \newletcs\cpt@processedoptions\@empty \robust@def*\XProcessOptions{% + \cpt@inpoxtrue \let\@fileswith@pti@ns\@badrequireerror \edef\cpt@testname{\@currname.\@currext}% \ifx\cpt@testname\cpt@documentclass @@ -2388,32 +3168,40 @@ \expandcsonce\cpt@classoptionslist\fi }% \edef\@curroptions{\cpt@optionlist{\@currname.\@currext}}% - \ifcsnullTF\@curroptions{}% + \ifcsnullTF\@curroptions\@empty {\cpt@sttrue\cpt@kvnormalize[,]\@curroptions}% - \cpt@ifstar - {\cpt@sttrue\cpt@testfam\cpt@processoptions}% - {\cpt@stfalse\cpt@testfam\cpt@processoptions}% + \cpt@testst{\cpt@testfam\cpt@processoptions}% } \robust@def*\cpt@processoptions<#1>{% \if@boolTF{cpt@st}{% \cpt@testopt{\cpt@xprocessoptions#1}{}% }{% - \cpt@testopt{\cpt@pr@cessoptions#1}{}% + \cpt@testopt{\cpt@yprocessoptions#1}{}% }% } -\robust@def*\cpt@pr@cessoptions#1[#2]{% - \normal@despace{#1}\currfam +\robust@def*\cpt@yprocessoptions#1[#2]{% + \edef\cpt@currna{\unexpanded{#2}}% + \ifcsnullTF\cpt@currna{} + {\cpt@sttrue\cpt@csvnormalize[,]\cpt@currna}% + \def\csv@do##1{% + \cpt@ypr@cessoptions{##1}% + }% + \csv@@parse[,]{#1}% + \cpt@pr@cessoptions{#1}% + \cpt@pr@cessopti@ns +} +\robust@def*\cpt@ypr@cessoptions#1{% + \edef\cpt@currfam{\unexpanded{#1}}% \def\kv@do##1{% \edef\CurrentOption{\unexpanded{##1}}% \ifcsnullTF\CurrentOption{}{% - \cpt@splitoption\z@ - \if@boolFT{cpt@optf}{}{% - \cpt@inpoxtrue - \ifcsndefFT{#1@ds@\curropt}{}{% - \ifblankTF{#2}{% + \cpt@findoption@a + \if@boolFT{cpt@optfd}{}{% + \ifcsndefFT{#1@ds@\cpt@curropt}{}{% + \ifcsnullTF\cpt@currna{% \cpt@igoptfalse }{% - \oifinsetTF{\curropt}{#2}{% + \if@sp@inlistTF,\cpt@curropt\cpt@currna{% \cpt@igopttrue }{% \cpt@igoptfalse @@ -2425,24 +3213,35 @@ }% }% \ifcsnullTF\cpt@classoptions{}{% - \cptexpandarg{\kv@@parse*}{\noexpandcsn{#1@declaredoptions}}% + \ifcsnnullTF{#1@declaredoptions}{}{% + \cptexpandsecond{\kv@@parse*}{\noexpandcsn{#1@declaredoptions}}% + }% }% - \cpt@pr@c@ssoptions{#1}{#2}% } \robust@def*\cpt@xprocessoptions#1[#2]{% - \normal@despace{#1}\currfam + \edef\cpt@currna{\unexpanded{#2}}% + \ifcsnullTF\cpt@currna{} + {\cpt@sttrue\cpt@csvnormalize[,]\cpt@currna}% + \def\csv@do##1{% + \cpt@xpr@cessoptions{##1}% + }% + \csv@@parse[,]{#1}% + \cpt@pr@cessoptions{#1}% + \cpt@pr@cessopti@ns +} +\robust@def*\cpt@xpr@cessoptions#1{% + \def\cpt@currfam{#1}% + \edef\DeclaredOptions{\cpt@getdeclaredoptions\cpt@currfam}% \def\kv@do##1{% \edef\CurrentOption{\unexpanded{##1}}% \ifcsnullTF\CurrentOption{}{% - \cpt@splitoption\@ne - \xifinsetFT{,\cptoxdetok\curropt,}% - {,\cpt@getdeclaredoptions{#1},}{}{% - \cpt@inpoxtrue - \ifcsndefFT{#1@ds@\curropt}{}{% - \ifblankTF{#2}{% + \cpt@findoption@b + \if@sp@inlistFT,\cpt@curropt\DeclaredOptions{}{% + \ifcsndefFT{#1@ds@\cpt@curropt}{}{% + \ifcsnullTF\cpt@currna{% \cpt@igoptfalse }{% - \oifinsetTF{\curropt}{#2}{% + \if@sp@inlistTF,\cpt@curropt\cpt@currna{% \cpt@igopttrue }{% \cpt@igoptfalse @@ -2454,213 +3253,345 @@ }% }% \ifcsnullTF\cpt@classoptions{}{\kv@@parse*\cpt@classoptions}% - \cpt@pr@c@ssoptions{#1}{#2}% } -\robust@def*\cpt@pr@c@ssoptions#1#2{% - \normal@despace{#1}\currfam +\robust@def*\cpt@pr@cessoptions#1{% + \def\cpt@fams{#1}% \def\kv@do##1{% \edef\CurrentOption{\unexpanded{##1}}% \ifcsnullTF\CurrentOption{}{% - \cpt@splitoption\@ne - \cpt@inpoxtrue - \ifcsndefTF{#1@ds@\curropt}{% - \ifblankTF{#2}{% - \cpt@igoptfalse - }{% - \oifinsetTF{\curropt}{#2}{% - \cpt@igopttrue - }{% + \cpt@findoption@b + \def\csv@do####1{% + \def\cpt@currfam{####1}% + \ifcsndefTF{\cpt@currfam @ds@\cpt@curropt}{% + \ifcsnullTF\cpt@currna{% \cpt@igoptfalse + }{% + \if@sp@inlistTF,\cpt@curropt\cpt@currna{% + \cpt@igopttrue + }{% + \cpt@igoptfalse + }% }% - }% - \cpt@useoption - }{% - \ifcsndefTF{#1@default@ds}{% - \usecsn{#1@default@ds}% + \cpt@useoption }{% - \default@ds + \if@sp@inlistTF,\cpt@curropt\ExternalOptions{}{% + \cpt@addto@undef@opts + \cpt@use@default@ds + }% }% }% + \ifcsnullTF\cpt@fams{}{\csv@@loop*[,]\cpt@fams}% }% }% - \ifcsnullTF\@curroptions{}{\kv@@parse*\@curroptions}% + \ifcsnullTF\@curroptions{}{\kv@@parse*[,]\@curroptions}% +} +\robust@def*\cpt@pr@cessopti@ns{% \let\CurrentOption\@empty - \ifx\cpt@documentclass\cpt@undefined - \cptglet\cpt@pr@cessedoptions\cpt@processedoptions - \else - \let\cpt@pr@cessedoptions\@empty - \fi + \ifx\cpt@documentclass\cpt@undefined\else + \let\cpt@processedoptions\@empty\fi \undefcs\cpt@classoptions - \let\cpt@processedoptions\@empty \let\@fileswith@pti@ns\@@fileswith@pti@ns \cpt@olddxfalse \AtEndOfPackage{\let\@unprocessedoptions\relax}% } -\robust@def*\XExecuteOptions{\cpt@testfam\cpt@executeoptions} +\robust@def*\cpt@use@default@ds{% + \begingroup + \let\@xp\expandcsonce + \ifcsndefTF{\cpt@currfam @default@na}{}{% + \csn@def{\cpt@currfam @default@na}{}% + }% + \toks@{\default@ds}% + \ifcsndefFT{\cpt@currfam @default@ds}{}{% + \edef\cpt@tempa{\expandcsnonce{\cpt@currfam @default@na}}% + \if@sp@inlistTF,\cpt@curropt\cpt@tempa{}{% + \edef\cpt@tempa{% + {\@xp\cpt@currfam}{\@xp\cpt@curropt}{\@xp\cpt@currval}% + }% + \edef\cpt@tempb{\cptmakecs{\cpt@currfam @default@ds}}% + \edef\cpt@tempc{% + \unexpanded\cptsevenxp{\expandafter\cpt@tempb\cpt@tempa}% + }% + \xifinsetFT{\detokenize{define/.code=}}{\cptoxdetok\cpt@tempc}{% + \toks@\cptthreexp{\expandafter\cpt@tempb\cpt@tempa}% + }{% + \cptexpandmacro\cpt@currval\curr@val + \despacecontent\curr@val + \def\cpt@tempb{\XDeclareBooleanOption}% + \let\cmd\@empty + \oifstrcmpTF{true}\curr@val{}{% + \oifstrcmpTF{false}\curr@val{}{% + \def\cpt@tempb{\XDeclareCommandOption}% + \def\cmd{cmd}% + }% + }% + \def\cpt@tempa##1define/.code=##2\cpt@nil{% + \cptexpanded{\toks@{% + \cpt@tempb<\cpt@currfam>{\cpt@curropt}[\@xp\curr@val]% + (\cmd\@currname @){\unexpanded{##2}}% + \XExecuteOptions<\cpt@currfam>{\cpt@curropt=\@xp\curr@val}% + }}% + }% + \expandafter\cpt@tempa\cpt@tempc\cpt@nil + }% + }% + }% + \expandafter\endgroup\the\toks@ +} +\robust@def*\XExecuteOptions{% + \cpt@inpoxfalse + \cpt@testfam\cpt@executeoptions +} \robust@def*\cpt@executeoptions<#1>#2{% - \normal@despace{#1}\currfam - \let\cpt@executedoptions\@empty - \let\rc@CurrentOption\CurrentOption + \cpt@testopt{\cpt@ex@cuteoptions{#1}{#2}}{}% +} +\robust@def*\cpt@ex@cuteoptions#1#2[#3]{% + \edef\cpt@currna{\unexpanded{#3}}% + \ifcsnullTF\cpt@currna{}{% + \cpt@sttrue\cpt@csvnormalize[,]\cpt@currna + }% + \def\csv@do##1{% + \cpt@ex@cuteopti@ns{##1}{#2}% + }% + \csv@@parse[,]{#1}% + \cpt@olddxfalse + \undefcsset{\ExecutedOptions,\exec@warnlist}% +} +\robust@def*\cpt@ex@cuteopti@ns#1#2{% + \def\cpt@currfam{#1}% + \ifnum\cpt@optdepth=\z@ + \csn@def{\cpt@currfam @executedoptions}{}% + \csn@def{\cpt@currfam @exec@warnlist}{}% + \fi + \edef\DeclaredOptions{\cpt@getdeclaredoptions\cpt@currfam}% \def\kv@do##1{% \edef\CurrentOption{\unexpanded{##1}}% \ifcsnullTF\CurrentOption{}{% - \cpt@splitoption\@ne - \xifinsetTF{,\cptoxdetok\curropt,}% - {,\cpt@getdeclaredoptions{#1},}{% - \xifinsetTF{,\cptoxdetok\curropt,}% - {,\cptoxdetok\cpt@executedoptions,}{% - \cpt@warn{Option '\curropt' multiply submitted to - \MsgBrk\string\XExecuteOptions: re-executed}% + \cpt@findoption@b + \edef\ExecutedOptions{% + \expandcsnonce{\cpt@currfam @executedoptions}% + }% + \edef\exec@warnlist{% + \expandcsnonce{\cpt@currfam @exec@warnlist}% + }% + \if@sp@inlistTF,\cpt@curropt\cpt@currna{}{% + \cpt@igoptfalse + \if@sp@inlistTF,\cpt@curropt\DeclaredOptions{% + \if@sp@inlistTF,\cpt@curropt\ExecutedOptions{% + \if@sp@inlistTF,\cpt@curropt\exec@warnlist{}{% + \ifcpt@bibool\else + \cpt@warn{Option '\cpt@curropt' of family + '\cpt@currfam'\MsgBrk multiply submitted to + \string\XExecuteOptions:\MsgBrk re-executed}% + \fi + \aftercsname{\cptgaddtolist*} + {\cpt@currfam @exec@warnlist}\cpt@curropt + }% + }{% + \aftercsname{\cptgaddtolist*} + {\cpt@currfam @executedoptions}\cpt@curropt + }% + \cpt@useoption }{% - \cptaddtocommalist\cpt@executedoptions\curropt + \cpt@addto@undecl@opts }% - \cpt@inpoxfalse\cpt@igoptfalse\cpt@useoption - }{% - \cpt@warn{Option '\expandcsonce\curropt' not - declared: ignored}% }% }% }% \kv@@parse{#2}% - \let\CurrentOption\rc@CurrentOption - \let\cpt@executedoptions\@empty - \cpt@olddxfalse } -\robust@def\cpt@splitoption#1{% - \ifcase#1\relax - \cpt@optffalse - \oneDloop@b\cpt@classoptions\@currentoption{% - \ifcsnullTF\@currentoption{}{% - \xifinsetTF{=}{\cptoxdetok\@currentoption}{% - \expandafter\cpt@split@ption\@currentoption=\cpt@nil - }{% - \let\@curropt\@currentoption - \let\@currval\@empty - }% - \let\currval\@currval - \ifx\@curropt\CurrentOption - \cpt@optftrue\@breaklooptrue - \let\curropt\@curropt - \let\currentoption\@currentoption - \fi +\robust@def\cpt@findoption@a{% + \cpt@optfdfalse + \def\csv@do##1{% + \ifblankTF{##1}{}{% + \xifinsetTF{=}{\detokenize{##1}}{% + \cpt@splitoption##1=\split@nil + }{% + \edef\cpt@curropt{\unexpanded{##1}}% + \let\cpt@currval\@empty }% + \ifx\cpt@curropt\CurrentOption + \cpt@optfdtrue\cpt@breaklooptrue + \edef\OptionFound{\unexpanded{##1}}% + \else + \let\cpt@curropt\@empty + \let\OptionFound\@empty + \fi }% - \or - \let\currentoption\CurrentOption - \xifinsetTF{=}{\cptoxdetok\CurrentOption}{% - \expandafter\cpt@split@ption\CurrentOption=\cpt@nil - \let\curropt\@curropt - \let\currval\@currval - }{% - \let\curropt\CurrentOption - \let\currval\@empty - }% - \else - \cpt@err{Invalid case '\expandcsonce{#1}' for - command '\string\cpt@splitoption'}\@ehc - \fi + }% + \csv@@parse*[,]\cpt@classoptions } -\def\cpt@split@ption#1=#2\cpt@nil{% - \edef\@curropt{\unexpanded{#1}}% - \ifinsetTF{=\cpt@nil}{#2\cpt@nil}{% +\robust@def\cpt@findoption@b{% + \let\OptionFound\CurrentOption + \xifinsetTF{=}{\cptoxdetok\CurrentOption}{% + \expandafter\cpt@splitoption\CurrentOption=\split@nil + }{% + \let\cpt@curropt\CurrentOption + \let\cpt@currval\@empty + }% +} +\robust@def\cpt@splitoption#1=#2\split@nil{% + \normal@despace{#1}\cpt@curropt + \ifinsetTF{=\split@nil}{#2\split@nil}{% \begingroup - \def\cpt@tempa##1=##2\cpt@nil{\endgroup - \edef\@currval{\expandcsonce{\remove@to@dot##1}}% + \defpass\cpt@tempa##1=##2\split@nil{\endgroup + \simpleexpandarg\normal@despace{\@gobble##1}\cpt@currval }% - \cpt@tempa.#2\cpt@nil + .#2\split@nil }{% - \edef\@currval{\unexpanded{#2}}% + \normal@despace{#2}\cpt@currval }% } \robust@def*\cpt@useoption{% - \ifcpt@inpox - \xifinsetTF{,\cptoxdetok\CurrentOption,}% - {,\cptoxdetok\cpt@processedoptions,}{}{% - \cptaddtocommalist\cpt@processedoptions\CurrentOption - }% - \remove@curr@option\currentoption - \ifx\currentoption\CurrentOption\else - \remove@curr@option\CurrentOption - \fi - \fi - \ifcpt@igopt\else - \ifcpt@olddx - \cptuse{\currfam @ds@\curropt}% - \else - \ifcsndefFT{\currfam @ds@\curropt}{}{% - \ifcsnullTF\currval{% + \if@boolFT{cpt@inpox}{}{% + \if@sp@inlistTF,\CurrentOption\cpt@processedoptions{}{% + \cptgaddtolist*\cpt@processedoptions\CurrentOption + }% + \ifcsnullTF\OptionFound{}{\cpt@removecurroption\OptionFound}% + \ifxTF\OptionFound\CurrentOption{}{% + \cpt@removecurroption\CurrentOption + }% + }% + \if@boolTF{cpt@igopt}{}{% + \ifcsndefFT{\cpt@currfam @ds@\cpt@curropt}{}{% + \if@boolTF{cpt@olddx}{% + \cptuse{\cpt@currfam @ds@\cpt@curropt}% + }{% + \ifcsnullTF\cpt@currval{% \cptthreexp\cpt@usedefault - \csname\currfam @ds@\curropt @default\endcsname\cpt@nil + \csname\cpt@currfam @ds@\cpt@curropt + @default\endcsname\cpt@nil }{% - \cpt@use@ption + \cpt@useoption@a }% }% - \fi - \fi + }% + }% } -\robust@def*\cpt@use@ption{% +\robust@def*\cpt@useoption@a{% \cpt@pushoptionstate - \cptexpandargonce{\cptuse{\currfam @ds@\curropt}}\currval\relax + \cptexpandargonce{\cptuse{\cpt@currfam @ds@\cpt@curropt}}% + \cpt@currval\relax \cpt@popoptionstate } +\new@def*\ExternalOptions{% + 10pt,11pt,12pt,14pt,17pt,20pt,25pt,30pt,36pt,48pt,60pt,% + a0paper,a1paper,a2paper,a3paper,a4paper,a6paper,% + b0paper,b1paper,b2paper,b3paper,b4paper,b5paper,b6paper,% + letterpaper,legalpaper,executivepaper,landscape,oneside,% + twoside,draft,final,titlepage,notitlepage,onecolumn,% + twocolumn,leqno,fleqn,openbib,openright,openleft,openany,% + article,ms,showtrims,oldfontcommands,extrafontsizes,noetex% +} +\robust@def*\AddToExternalOptions#1{% + \cpt@filtermergelists[,]\ExternalOptions{#1}\nofilter +} +\robust@def*\RemoveFromExternalOptions#1{% + \cpt@filterremoveelements[,]\ExternalOptions{#1}\nofilter +} +\robust@def*\cpt@addto@undecl@opts{% + \edef\everymergeitem##1{\@space##1}% + \cptexpandarg{\cpt@filtermergelists[;]\cpt@undeclaredopts}% + {\cpt@currfam,\cpt@curropt,\cpt@currval}\nofilter +} +\robust@def*\cpt@addto@undef@opts{% + \edef\everymergeitem##1{\@space##1}% + \if@sp@inlistTF,\cpt@curropt\ExternalOptions{}{% + \cptexpandarg{\cpt@filtermergelists[;]\cpt@undefinedopts}% + {\cpt@currfam,\cpt@curropt,\cpt@currval}\nofilter + }% +} +\AfterStartOfDocument{\AtEndDocument{% + \ifdefFT\cpt@undeclaredopts{}{% + \ifcsnullTF\cpt@undeclaredopts{}{% + \edef\cpt@undeclaredopts{% + \simpleexpandarg\xp@despace\cpt@undeclaredopts + }% + \cpt@warn{% + Undeclared options found in \string\XExecuteOptions + \MsgBrk (family,option,value): + ^^J\expandcsonce\cpt@undeclaredopts + }% + }% + }% + \ifdefFT\cpt@undefinedopts{}{% + \ifcsnullTF\cpt@undefinedopts{}{% + \edef\cpt@undefinedopts{% + \simpleexpandarg\xp@despace\cpt@undefinedopts + }% + \cpt@warn{% + Undefined options (family,option,value): + ^^J\expandcsonce\cpt@undefinedopts + \MsgBrk Default action taken in each case + }% + }% + }% +}} \robust@def*\cpt@usedefault#1#2\cpt@nil{% \ifcptmacroTF{#1}{% - \edef\cpt@tempa{\expandafter\@gobble\string#1}% + \edef\cpt@tempa{\cptremovescape#1}% }{% - \cpt@err{Invalid option macro passed to command - '\string\cpt@usedefault'}\@ehc + \cpt@nomacroerr{#1}% }% - \edef\cpt@tempb{\currfam @ds@\curropt}% + \edef\cpt@tempb{\cpt@currfam @ds@\cpt@curropt}% \@onelevel@sanitize\cpt@tempb \ifxTF\cpt@tempa\cpt@tempb{% \begingroup - \csn@def{\currfam @ds@\curropt}##1{% - \toks@{\def\currval{##1}}% + \csn@def{\cpt@currfam @ds@\cpt@curropt}##1{% + \toks@{\def\cpt@currval{##1}}% }% - \cptuse{\currfam @ds@\curropt @default}% + \cptuse{\cpt@currfam @ds@\cpt@curropt @default}% \expandafter\endgroup\the\toks@ - \cpt@use@ption + \cpt@useoption@a }{% \cpt@warn{Non-standard default function for option - '\expandcsonce\curropt':\MsgBrk Executed anyway}% + '\expandcsonce\cpt@curropt':\MsgBrk Executed anyway}% \cpt@pushoptionstate - \cptuse{\currfam @ds@\curropt @default}\relax + \cptuse{\cpt@currfam @ds@\cpt@curropt @default}\relax \cpt@popoptionstate }% } +\robust@def*\cpt@optionstate{% + \cpt@currfam,\cpt@currna,\cpt@curropt,\cpt@currval,% + \CurrentOption,\OptionFound,\ifcpt@inpox,\ifcpt@optfd,% + \ifcpt@igopt,\DeclaredOptions +} \robust@def*\cpt@pushoptionstate{% - \pushfunctions{\currfam,\curropt,\currval,\CurrentOption,% - \currentoption,\ifcpt@inpox,\ifcpt@optf,\ifcpt@igopt}\cpt@optdepth + \simpleexpandarg\pushfunctions\cpt@optionstate\cpt@optdepth } \robust@def*\cpt@popoptionstate{% - \popfunctions{\currfam,\curropt,\currval,\CurrentOption,% - \currentoption,\ifcpt@inpox,\ifcpt@optf,\ifcpt@igopt}\cpt@optdepth -} -\robust@def*\remove@curr@option#1{% - \cptexpandargonce{\cpt@killoneelement[,]}{#1}\@unusedoptionlist -} -\BeforeStartOfDocument{% - \ifdefFT\cpt@pr@cessedoptions{}{% - \ifcsnullTF\cpt@pr@cessedoptions{}{% - \ifcsnullTF\@unusedoptionlist{}{% - \oneDloop@b\cpt@pr@cessedoptions\cpt@tempa{% - \xifinsetFT{,\cptoxdetok\cpt@tempa,}% - {,\cptoxdetok\@unusedoptionlist,}{}{% - \remove@curr@option\cpt@tempa + \simpleexpandarg\popfunctions\cpt@optionstate\cpt@optdepth +} +\robust@def*\cpt@removecurroption#1{% + \cptexpandargonce{\cpt@filterremoveelements[,]% + \@unusedoptionlist}{#1}\nofilter +} +\robust@def*\CleanupUnusedOptionlist#1{% + \ifcptmacroTF{#1}{}{\cpt@nomacroerr{#1}}% + \BeforeStartOfDocument{% + \ifdefFT#1{}{% + \ifcsnullTF#1{}{% + \ifcsnullTF\@unusedoptionlist{}{% + \def\comma@do##1{% + \normal@despace{##1}\cpt@tempa + \if@sp@inlistFT,\cpt@tempa\@unusedoptionlist{}{% + \cpt@removecurroption\cpt@tempa + }% }% + \simpleexpandarg\comma@@loop#1% }% }% }% + \globalize\@unusedoptionlist + \emptify#1% }% - \globalize\@unusedoptionlist - \undefcs\cpt@pr@cessedoptions } +\CleanupUnusedOptionlist\cpt@processedoptions \cptpassunexpanded{% \begingroup \def\cpt@tempa{\endgroup - \cptglet\cpt@kernel@DeclareOption\DeclareOption - \cptglet\cpt@kernel@ProcessOptions\ProcessOptions - \cptglet\cpt@kernel@ExecuteOptions\ExecuteOptions + \newgletcs\kernel@DeclareOption\DeclareOption + \newgletcs\kernel@ProcessOptions\ProcessOptions + \newgletcs\kernel@ExecuteOptions\ExecuteOptions \gdef\DeclareOption{\cpt@olddxtrue\XDeclareOption}% \gdef\ProcessOptions{\cpt@olddxtrue\XProcessOptions}% \gdef\ExecuteOptions{\cpt@olddxtrue\XExecuteOptions}% @@ -2670,9 +3601,9 @@ \let\documentclass\@twoclasseserror \if@compatibility\else \def\usepackage{% - \cptglet\DeclareOption\cpt@kernel@DeclareOption - \cptglet\ProcessOptions\cpt@kernel@ProcessOptions - \cptglet\ExecuteOptions\cpt@kernel@ExecuteOptions + \cptglet\DeclareOption\kernel@DeclareOption + \cptglet\ProcessOptions\kernel@ProcessOptions + \cptglet\ExecuteOptions\kernel@ExecuteOptions \cpt@olddxfalse \RequirePackage }% @@ -2686,7 +3617,7 @@ \expandafter\cpt@tempa\else\expandafter\endgroup\fi } \XDeclareBooleanOption{verbose}[true](cpt@){} -\XDeclareBiBooleanOptions{draft,final}[true](mp@){}{} +\XDeclareBiBooleanOptions{draft,final}[true](cpt@){}{} \XDeclareBooleanOption{usepox}[true](cpt@){% \ifcpt@usepox \AtEndOfPackage{% @@ -2696,13 +3627,16 @@ }% \fi } +\XDisableOptions*{draft,final} \XDeclareOption*{\cpt@warn{Unknown option '\CurrentOption' ignored}} \XExecuteOptions{verbose=false,usepox=true} -\XProcessOptions* - +\XProcessOptions*\relax \cptpopcatcodes \cptrestorecatcodes \declarefutureletset[fl@]{lbracket,star,rquote} +\shelllet\@ltx@warn\@latex@warning@no@line +\shelllet\@ltx@info\@latex@info@no@line +\shelllet\@ltx@err\@latex@error \endinput |