From 215b9a864d5829070bdc66ba736986eb72e5143e Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 9 Jun 2009 23:31:15 +0000 Subject: expl3 1407 (9jun09) git-svn-id: svn://tug.org/texlive/trunk@13686 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/expl3/README | 289 ++ Master/texmf-dist/doc/latex/expl3/expl3.pdf | Bin 155938 -> 510353 bytes Master/texmf-dist/doc/latex/expl3/l32eproc.pdf | Bin 108445 -> 0 bytes Master/texmf-dist/doc/latex/expl3/l3obsolete.txt | 9 + .../texmf-dist/doc/latex/expl3/l3obsolete2008.txt | 296 ++ Master/texmf-dist/doc/latex/expl3/readme-dev.txt | 120 + Master/texmf-dist/doc/latex/expl3/readme.txt | 315 -- Master/texmf-dist/doc/latex/expl3/source3.pdf | Bin 953706 -> 4120684 bytes Master/texmf-dist/makeindex/expl3/l3doc.ist | 72 + Master/texmf-dist/source/latex/expl3/expl3.dtx | 970 +++++ Master/texmf-dist/source/latex/expl3/expl3.tex | 753 ---- Master/texmf-dist/source/latex/expl3/l3.ins | 225 +- Master/texmf-dist/source/latex/expl3/l32eproc.tex | 523 --- Master/texmf-dist/source/latex/expl3/l3alloc.dtx | 146 +- Master/texmf-dist/source/latex/expl3/l3basics.dtx | 4072 +++++++++++--------- Master/texmf-dist/source/latex/expl3/l3box.dtx | 541 ++- Master/texmf-dist/source/latex/expl3/l3calc.dtx | 493 ++- Master/texmf-dist/source/latex/expl3/l3chk.dtx | 173 +- Master/texmf-dist/source/latex/expl3/l3clist.dtx | 988 ++--- Master/texmf-dist/source/latex/expl3/l3doc.dtx | 1674 ++++++++ Master/texmf-dist/source/latex/expl3/l3expan.dtx | 1378 ++++--- Master/texmf-dist/source/latex/expl3/l3file.dtx | 412 ++ Master/texmf-dist/source/latex/expl3/l3final.dtx | 54 +- Master/texmf-dist/source/latex/expl3/l3format.ins | 147 +- Master/texmf-dist/source/latex/expl3/l3int.dtx | 904 ++--- Master/texmf-dist/source/latex/expl3/l3intexpr.dtx | 642 +++ Master/texmf-dist/source/latex/expl3/l3io.dtx | 524 ++- Master/texmf-dist/source/latex/expl3/l3keyval.dtx | 273 +- .../texmf-dist/source/latex/expl3/l3messages.dtx | 966 ----- Master/texmf-dist/source/latex/expl3/l3msg.dtx | 1336 +++++++ Master/texmf-dist/source/latex/expl3/l3names.dtx | 705 ++-- Master/texmf-dist/source/latex/expl3/l3num.dtx | 504 +-- Master/texmf-dist/source/latex/expl3/l3precom.dtx | 192 +- Master/texmf-dist/source/latex/expl3/l3prg.dtx | 1599 ++++---- Master/texmf-dist/source/latex/expl3/l3prop.dtx | 786 ++-- Master/texmf-dist/source/latex/expl3/l3quark.dtx | 375 +- Master/texmf-dist/source/latex/expl3/l3seq.dtx | 841 ++-- Master/texmf-dist/source/latex/expl3/l3skip.dtx | 575 +-- Master/texmf-dist/source/latex/expl3/l3tl.dtx | 2269 +++++++++++ Master/texmf-dist/source/latex/expl3/l3tlp.dtx | 2054 ---------- Master/texmf-dist/source/latex/expl3/l3token.dtx | 1751 ++++----- Master/texmf-dist/source/latex/expl3/l3toks.dtx | 963 ++--- Master/texmf-dist/source/latex/expl3/l3vers.dtx | 72 +- Master/texmf-dist/source/latex/expl3/l3xref.dtx | 180 +- Master/texmf-dist/source/latex/expl3/source3.tex | 633 ++- Master/texmf-dist/source/latex/expl3/test1.tex | 89 - Master/texmf-dist/source/latex/expl3/test2.tex | 73 - Master/texmf-dist/source/latex/expl3/test3.tex | 135 - Master/texmf-dist/tex/latex/expl3/expl3.sty | 84 + Master/texmf-dist/tex/latex/expl3/l3basics.sty | 1102 +++--- Master/texmf-dist/tex/latex/expl3/l3box.sty | 212 +- Master/texmf-dist/tex/latex/expl3/l3calc.sty | 302 +- Master/texmf-dist/tex/latex/expl3/l3chk.sty | 81 +- Master/texmf-dist/tex/latex/expl3/l3clist.sty | 319 +- Master/texmf-dist/tex/latex/expl3/l3doc.cls | 1050 +++-- Master/texmf-dist/tex/latex/expl3/l3expan.sty | 367 +- Master/texmf-dist/tex/latex/expl3/l3file.sty | 161 + Master/texmf-dist/tex/latex/expl3/l3int.sty | 378 +- Master/texmf-dist/tex/latex/expl3/l3intexpr.sty | 203 + Master/texmf-dist/tex/latex/expl3/l3io.sty | 116 +- Master/texmf-dist/tex/latex/expl3/l3keyval.sty | 144 +- Master/texmf-dist/tex/latex/expl3/l3messages.sty | 316 -- Master/texmf-dist/tex/latex/expl3/l3msg.sty | 487 +++ Master/texmf-dist/tex/latex/expl3/l3names.sty | 169 +- Master/texmf-dist/tex/latex/expl3/l3num.sty | 145 +- Master/texmf-dist/tex/latex/expl3/l3precom.sty | 74 +- Master/texmf-dist/tex/latex/expl3/l3prg.sty | 472 +-- Master/texmf-dist/tex/latex/expl3/l3prop.sty | 265 +- Master/texmf-dist/tex/latex/expl3/l3quark.sty | 143 +- Master/texmf-dist/tex/latex/expl3/l3seq.sty | 249 +- Master/texmf-dist/tex/latex/expl3/l3skip.sty | 224 +- Master/texmf-dist/tex/latex/expl3/l3tl.sty | 610 +++ Master/texmf-dist/tex/latex/expl3/l3tlp.sty | 506 --- Master/texmf-dist/tex/latex/expl3/l3token.sty | 709 ++-- Master/texmf-dist/tex/latex/expl3/l3toks.sty | 220 +- Master/texmf-dist/tex/latex/expl3/l3vers.dtx | 142 + Master/texmf-dist/tex/latex/expl3/l3xref.sty | 72 +- 77 files changed, 23313 insertions(+), 18100 deletions(-) create mode 100644 Master/texmf-dist/doc/latex/expl3/README delete mode 100644 Master/texmf-dist/doc/latex/expl3/l32eproc.pdf create mode 100644 Master/texmf-dist/doc/latex/expl3/l3obsolete.txt create mode 100644 Master/texmf-dist/doc/latex/expl3/l3obsolete2008.txt create mode 100644 Master/texmf-dist/doc/latex/expl3/readme-dev.txt delete mode 100644 Master/texmf-dist/doc/latex/expl3/readme.txt create mode 100644 Master/texmf-dist/makeindex/expl3/l3doc.ist create mode 100644 Master/texmf-dist/source/latex/expl3/expl3.dtx delete mode 100644 Master/texmf-dist/source/latex/expl3/expl3.tex delete mode 100644 Master/texmf-dist/source/latex/expl3/l32eproc.tex create mode 100644 Master/texmf-dist/source/latex/expl3/l3doc.dtx create mode 100644 Master/texmf-dist/source/latex/expl3/l3file.dtx create mode 100644 Master/texmf-dist/source/latex/expl3/l3intexpr.dtx delete mode 100644 Master/texmf-dist/source/latex/expl3/l3messages.dtx create mode 100644 Master/texmf-dist/source/latex/expl3/l3msg.dtx create mode 100644 Master/texmf-dist/source/latex/expl3/l3tl.dtx delete mode 100644 Master/texmf-dist/source/latex/expl3/l3tlp.dtx delete mode 100644 Master/texmf-dist/source/latex/expl3/test1.tex delete mode 100644 Master/texmf-dist/source/latex/expl3/test2.tex delete mode 100644 Master/texmf-dist/source/latex/expl3/test3.tex create mode 100644 Master/texmf-dist/tex/latex/expl3/expl3.sty create mode 100644 Master/texmf-dist/tex/latex/expl3/l3file.sty create mode 100644 Master/texmf-dist/tex/latex/expl3/l3intexpr.sty delete mode 100644 Master/texmf-dist/tex/latex/expl3/l3messages.sty create mode 100644 Master/texmf-dist/tex/latex/expl3/l3msg.sty create mode 100644 Master/texmf-dist/tex/latex/expl3/l3tl.sty delete mode 100644 Master/texmf-dist/tex/latex/expl3/l3tlp.sty create mode 100644 Master/texmf-dist/tex/latex/expl3/l3vers.dtx (limited to 'Master') diff --git a/Master/texmf-dist/doc/latex/expl3/README b/Master/texmf-dist/doc/latex/expl3/README new file mode 100644 index 00000000000..67059036d41 --- /dev/null +++ b/Master/texmf-dist/doc/latex/expl3/README @@ -0,0 +1,289 @@ + + An Experimental LaTeX3 Programming Convention + ============================================= + + 2009/06/02 + + +WHERE TO GET IT +--------------- + +The files in this distribution represent a snapshot of selected files +from the Subversion (SVN) repository of the LaTeX3 Project. + +To obtain current versions of the files, visit + which contains further +instructions. + +OVERVIEW +-------- + +The files of the expl3 bundle provide a low-level API for TeX +programmers with special syntax conventions, completely separating it +from document level syntax. Hence, the commands provided are not +intended for use at the document level nor for use in describing +design layouts in document class files. + +This API provides the foundation on which the LaTeX3 kernel and other +advanced extensions are built. Special care has been taken so that +they can be used within a LaTeX2e context as regular packages. + +While expl3 is still experimental, the bundle is now regarded as +broadly stable. The syntax conventions and functions provided are now +ready for wider use. There may still be changes to some functions, but +these will be minor when compared to the scope of expl3. + + +THE GUILTY PERSONS +------------------ + + Frank Mittelbach, Denys Duchier, Johannes Braams, Michael Downes, + David Carlisle, Alan Jeffrey, Chris Rowley, Rainer Schoepf + Javier Bezos, Morten Hoegholm, Thomas Lotze, Will Robertson, + Joseph Wright + + +DISCUSSION +---------- + +Discussion concerning the approach, suggestions for improvements, changes, +additions, etc. should be addressed to the list LATEX-L. + +You can subscribe to this list by sending mail to + + listserv@urz.uni-heidelberg.de + +with the body containing + + subscribe LATEX-L + + +BUGS +---- + +If you find a real bug that makes a package stop working you can +report it via the standard LaTeX bug reporting mechanism of the LaTeX +distribution (see bugs.txt there) using the category "Experimental +LaTeX kernel". However please do *not* use this method for +suggestions / comments / improvements / etc. For this the list LATEX-L +should be used instead. + +Also please don't expect these package to work with *any* code that +floats around in the LaTeX2e world. :-) + + + +MANIFEST +-------- + +The following packages are in this release: + + +l3names +======= + +Documents the general naming scheme, and gives new names to all the TeX +primitives. + +If this package is used with the option [removeoldnames] then the +original TeX primitive names (\hbox, \def, ...) are made *undefined* and +so free to be defined for other purposes if needed. Of course this +breaks almost all existing LaTeX2 code, but it may be used for testing +purposes, see test2.tex. + +The option removeoldnames has been disabled temporarily. + +l3basics +======== + +Some basic definitions that are used by the other packages. + +l3chk +===== + +Functions that check definitions. +(Comparable to LaTeX2's \newcommand/\renewcommand.) + +l3alloc +======= + +Generic functions for allocating registers. + +l3toks +====== + +TeX's token registers. (Can be compiled with checking enabled) + +l3tl +===== + +Token Lists and Token List variables, a basic LaTeX3 datatype for storing +token lists. (These are essentially macros with no arguments.) The module also +provides functions for arbitrary token lists. (Package can be compiled +with checking enabled.) + +l3expan +======= + +The argument expansion module. One of the main features of the language +proposed here is a systematic treatment of the handling of argument +expansion. The basic functions for preprocessing command arguments are +defined here. + +l3quark +======= + +A `quark' is a command that is defined to expand to itself. So it may +not be directly used (it would generate an infinite loop) but has many +uses as special markers within LaTeX code. + +l3seq +===== + +A module implementing the basic list and stack datatypes. + +l3clist +======= + +A module implementing the handling of comma separated lists + +l3prop +====== + +Property lists are the datatype for handling key/value assignments. + +l3int +===== + +Integer and fake integer registers. With eTeX/Omega becoming more and +more accessible this module is, at least in parts only of historical +significance. (Can be compiled with checking enabled) + +l3num +===== + +Storing numbers as token-lists in macros + +l3skip +====== + +Dealing with length registers + +l3precom +========= + +Low-level pointer-related code, with further checking and tracing. + +l3io +==== + +Low-level input and ouput. + +l3prg +===== + +Experimental control structures. This covers booleans and various +other code. + +l3box +===== + +Low level box handling code + +l3token +===== + +Functions that investigate tokens and determine of which categories +they are. For instance, is the token in question expandable or not? Is +it a macro taking arguments? Also functions for peeking ahead in the +token stream. + +l3xref +===== + +Module providing the low-level interface for cross references. This +module also contains a test file which is generated along with the +package. + +l3msg +===== + +Module providing a new mechanism to provide user messages. + +l3calc +===== + +Module for using infix notation for the built-in register types +(lengths and counters). + +l3keyval +===== + +Module for extracting data from a key=val list for further processing. + +===================================================================== + +Install file +============= + +l3.ins +====== + +Process with plain TeX or LaTeX2e to generate the experimental +packages. + +===================================================================== + +Experimental LaTeX3 Format +========================== + +l3vers.dtx +========== + +This file contains the version information and other release related +coding. + +l3final.dtx +=========== + +This file is reserved for the last minute coding for producing a +format (such as the dump instruction). + +l3format.ins +============ + +Process with plain TeX or LaTeX2e to generate the experimental +format file lbase.ltx and its companion lbase.ini. +The run pdfetex --ini "*lbase.ini" to produce the experimental +format. + +===================================================================== + +source3.tex +=========== + +Run this file with pdfLaTeX: +pdflatex source3 to produce the documentation. +Doing this will produce three extra files (source3.ist, l3doc.cfg and +l3full.cfg). The first of these is a style file for makeindex; the +others or configuration files for the documentation class. +If you want to full documentation including the code listings than +rename l3full.cfg to l3doc.cfg and run LaTeX again. +Alternatively, run (in extended mode) + pdflatex "\PassOptionsToClass{full}{l3doc}\input{source3}" +After that run makeindex to produce the index, like so: +makeindex -s source3.ist source3 +and rerun LaTeX. + +expl3.dtx +========= + +This provides a single "load point" for the entire expl3 bundle. +Running pdflatex expl3.dtx will produce a general overview document +explaining the basics of expl3 programming. + +===================================================================== + +--- Copyright 1998 -- 2009 + The LaTeX3 Project. All rights reserved --- + diff --git a/Master/texmf-dist/doc/latex/expl3/expl3.pdf b/Master/texmf-dist/doc/latex/expl3/expl3.pdf index 189b52ee082..0343e931674 100644 Binary files a/Master/texmf-dist/doc/latex/expl3/expl3.pdf and b/Master/texmf-dist/doc/latex/expl3/expl3.pdf differ diff --git a/Master/texmf-dist/doc/latex/expl3/l32eproc.pdf b/Master/texmf-dist/doc/latex/expl3/l32eproc.pdf deleted file mode 100644 index 2ccd85c6f1b..00000000000 Binary files a/Master/texmf-dist/doc/latex/expl3/l32eproc.pdf and /dev/null differ diff --git a/Master/texmf-dist/doc/latex/expl3/l3obsolete.txt b/Master/texmf-dist/doc/latex/expl3/l3obsolete.txt new file mode 100644 index 00000000000..5c1073fe333 --- /dev/null +++ b/Master/texmf-dist/doc/latex/expl3/l3obsolete.txt @@ -0,0 +1,9 @@ +l3obsolete +========== + +This file lists expl3 commands that have been removed or +replaced with respect to the version on the TeX Live 2009 disk. + +========== + +Nothing yet! \ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/expl3/l3obsolete2008.txt b/Master/texmf-dist/doc/latex/expl3/l3obsolete2008.txt new file mode 100644 index 00000000000..20b83ff0bcb --- /dev/null +++ b/Master/texmf-dist/doc/latex/expl3/l3obsolete2008.txt @@ -0,0 +1,296 @@ +l3obsolete2008 +============== + +This file lists expl3 commands that have been removed or +replaced with respect to the version on the TeX Live 2008 disk. + +========== + +\CodeStart -> \ExplSyntaxOn +\CodeStop -> \ExplSyntaxOff +\NamesStart -> \ExplSyntaxNamesOn +\NamesStop -> \ExplSyntaxNamesOff + +\cs_use:c -> \use:c +\use:cc -> \exp_args:cc + +\use_arg_i:n -> \use:n +\use_arg_i:nn -> \use_i:nn +\use_arg_i:nnn -> \use_i:nnn +\use_arg_i:nnnn -> \use_i:nnnn +\use_arg_i_ii:nn -> \use:nn + +\use_arg_i_after_else:nw -> \use_i_after_else:nw +\use_arg_i_after_fi:nw -> \use_i_after_fi:nw +\use_arg_i_after_or:nw -> \use_i_after_or:nw +\use_arg_i_after_orelse:nw -> \use_i_after_orelse:nw +\use_arg_i_delimit_by_q_nil:nw -> \use_i_delimit_by_q_nil:nw +\use_arg_i_delimit_by_q_stop:nw -> \use_i_delimit_by_q_stop:nw +\use_arg_i_delimit_by_q_recursion_stop:nw -> + \use_i_delimit_by_q_recursion_stop:nw + +\use_arg_ii:nn -> \use_ii:nn +\use_arg_ii:nnn -> \use_ii:nnn +\use_arg_ii:nnnn -> \use_ii:nnnn +\use_arg_iii:nnn -> \use_iii:nnn +\use_arg_iii:nnnn -> \use_iii:nnnn +\use_arg_iv:nnnn -> \use_iv:nnnn + +\cs_free:NTF -> \cs_if_free:NTF +\cs_free:NT -> \cs_if_free:NT +\cs_free:NF -> \cs_if_free:NF +\cs_free:cTF -> \cs_if_free:cTF +\cs_free:cT -> \cs_if_free:cT +\cs_free:cF -> \cs_if_free:cF + +\cs_really_free:cTF -> \cs_if_really_free:cTF +\cs_really_free:cT -> \cs_if_really_free:cT +\cs_really_free:cF -> \cs_if_really_free:cF + +\cs_if_eq_p:NN -> \cs_if_eq_name_p:NN +\chk_new_cs:N -> \chk_if_new_cs:N +\chk_exist_cs:N -> \chk_if_exist_cs:N +\chk_exist_cs:c -> \chk_if_exist_cs:c + +\cmd_declare:Nnn -> Undefined. Use \def:NNn instead. +\cmd_arg_list_build -> Undefined (auxiliary function used for the above). + +\tl_put_left:cx -> Undefined. Define your own, if you need it. +\tl_gput_left:cx -> Undefined. Ditto. +\tl_put_right:cc -> Undefined. Ditto. +\seq_gput_right:cc -> Undefined. Ditto. +\clist_gput_right:cc -> Undefined. Ditto. + +\token_to_string:N -> \token_to_str:N + + + + + + + +\let:NwN -> \cs_set_eq:NwN + +\def:No -> -> \cs_set_nopar:No +\gdef:No -> \cs_gset_nopar:No + + +\def:Npn -> \cs_set_nopar:Npn +\def:Npx -> \cs_set_nopar:Npx +\def:cpn -> \cs_set_nopar:cpn +\def:cpx -> \cs_set_nopar:cpx + +\def:NNn -> \cs_set_nopar:NNn +\def:NNx -> \cs_set_nopar:NNx +\def:cNn -> \cs_set_nopar:cNn +\def:cNx -> \cs_set_nopar:cNx + +\def_protected:Npn -> \cs_set_protected_nopar:Npn +\def_protected:Npx -> \cs_set_protected_nopar:Npx +\def_protected:cpn -> \cs_set_protected_nopar:cpn +\def_protected:cpx -> \cs_set_protected_nopar:cpx + +\def_protected:NNn -> \cs_set_protected_nopar:NNn +\def_protected:NNx -> \cs_set_protected_nopar:NNx +\def_protected:cNn -> \cs_set_protected_nopar:cNn +\def_protected:cNx -> \cs_set_protected_nopar:cNx + +\def_protected_long:Npn -> \cs_set_protected:Npn +\def_protected_long:Npx -> \cs_set_protected:Npx +\def_protected_long:cpn -> \cs_set_protected:cpn +\def_protected_long:cpx -> \cs_set_protected:cpx + +\def_protected_long:NNn -> \cs_set_protected:NNn +\def_protected_long:NNx -> \cs_set_protected:NNx +\def_protected_long:cNn -> \cs_set_protected:cNn +\def_protected_long:cNx -> \cs_set_protected:cNx + +\def_new:Npn -> \cs_new_nopar:Npn +\def_new:Npx -> \cs_new_nopar:Npx +\def_new:cpn -> \cs_new_nopar:cpn +\def_new:cpx -> \cs_new_nopar:cpx + +\def_new:NNn -> \cs_new_nopar:NNn +\def_new:NNx -> \cs_new_nopar:NNx +\def_new:cNn -> \cs_new_nopar:cNn +\def_new:cNx -> \cs_new_nopar:cNx + +\def_protected_new:Npn -> \cs_new_protected_nopar:Npn +\def_protected_new:Npx -> \cs_new_protected_nopar:Npx +\def_protected_new:cpn -> \cs_new_protected_nopar:cpn +\def_protected_new:cpx -> \cs_new_protected_nopar:cpx + +\def_protected_new:NNn -> \cs_new_protected_nopar:NNn +\def_protected_new:NNx -> \cs_new_protected_nopar:NNx +\def_protected_new:cNn -> \cs_new_protected_nopar:cNn +\def_protected_new:cNx -> \cs_new_protected_nopar:cNx + +\def_protected_long_new:Npn -> \cs_new_protected:Npn +\def_protected_long_new:Npx -> \cs_new_protected:Npx +\def_protected_long_new:cpn -> \cs_new_protected:cpn +\def_protected_long_new:cpx -> \cs_new_protected:cpx + +\def_protected_long_new:NNn -> \cs_new_protected:NNn +\def_protected_long_new:NNx -> \cs_new_protected:NNx +\def_protected_long_new:cNn -> \cs_new_protected:cNn +\def_protected_long_new:cNx -> \cs_new_protected:cNx + +\def_long:Npn -> \cs_set:Npn +\def_long:Npx -> \cs_set:Npx +\def_long:cpn -> \cs_set:cpn +\def_long:cpx -> \cs_set:cpx + +\def_long:NNn -> \cs_set:NNn +\def_long:NNx -> \cs_set:NNx +\def_long:cNn -> \cs_set:cNn +\def_long:cNx -> \cs_set:cNx + +\def_long_new:Npn -> \cs_new:Npn +\def_long_new:Npx -> \cs_new:Npx +\def_long_new:cpn -> \cs_new:cpn +\def_long_new:cpx -> \cs_new:cpx + +\def_long_new:NNn -> \cs_new:NNn +\def_long_new:NNx -> \cs_new:NNx +\def_long_new:cNn -> \cs_new:cNn +\def_long_new:cNx -> \cs_new:cNx + + +\gdef:Npn -> \cs_gset_nopar:Npn +\gdef:Npx -> \cs_gset_nopar:Npx +\gdef:cpn -> \cs_gset_nopar:cpn +\gdef:cpx -> \cs_gset_nopar:cpx + +\gdef:NNn -> \cs_gset_nopar:NNn +\gdef:NNx -> \cs_gset_nopar:NNx +\gdef:cNn -> \cs_gset_nopar:cNn +\gdef:cNx -> \cs_gset_nopar:cNx + +\gdef_protected:Npn -> \cs_gset_protected_nopar:Npn +\gdef_protected:Npx -> \cs_gset_protected_nopar:Npx +\gdef_protected:cpn -> \cs_gset_protected_nopar:cpn +\gdef_protected:cpx -> \cs_gset_protected_nopar:cpx + +\gdef_protected:NNn -> \cs_gset_protected_nopar:NNn +\gdef_protected:NNx -> \cs_gset_protected_nopar:NNx +\gdef_protected:cNn -> \cs_gset_protected_nopar:cNn +\gdef_protected:cNx -> \cs_gset_protected_nopar:cNx + +\gdef_protected_long:Npn -> \cs_gset_protected:Npn +\gdef_protected_long:Npx -> \cs_gset_protected:Npx +\gdef_protected_long:cpn -> \cs_gset_protected:cpn +\gdef_protected_long:cpx -> \cs_gset_protected:cpx + +\gdef_protected_long:NNn -> \cs_gset_protected:NNn +\gdef_protected_long:NNx -> \cs_gset_protected:NNx +\gdef_protected_long:cNn -> \cs_gset_protected:cNn +\gdef_protected_long:cNx -> \cs_gset_protected:cNx + +\gdef_protected_long_new:Npn -> \cs_gnew_protected:Npn +\gdef_protected_long_new:Npx -> \cs_gnew_protected:Npx +\gdef_protected_long_new:cpn -> \cs_gnew_protected:cpn +\gdef_protected_long_new:cpx -> \cs_gnew_protected:cpx + +\gdef_protected_long_new:NNn -> \cs_gnew_protected:NNn +\gdef_protected_long_new:NNx -> \cs_gnew_protected:NNx +\gdef_protected_long_new:cNn -> \cs_gnew_protected:cNn +\gdef_protected_long_new:cNx -> \cs_gnew_protected:cNx + +\gdef_long:Npn -> \cs_gset:Npn +\gdef_long:Npx -> \cs_gset:Npx +\gdef_long:cpn -> \cs_gset:cpn +\gdef_long:cpx -> \cs_gset:cpx + +\gdef_long:NNn -> \cs_gset:NNn +\gdef_long:NNx -> \cs_gset:NNx +\gdef_long:cNn -> \cs_gset:cNn +\gdef_long:cNx -> \cs_gset:cNx + +\gdef_new:Npn -> \cs_gnew_nopar:Npn +\gdef_new:Npx -> \cs_gnew_nopar:Npx +\gdef_new:cpn -> \cs_gnew_nopar:cpn +\gdef_new:cpx -> \cs_gnew_nopar:cpx + +\gdef_new:NNn -> \cs_gnew_nopar:NNn +\gdef_new:NNx -> \cs_gnew_nopar:NNx +\gdef_new:cNn -> \cs_gnew_nopar:cNn +\gdef_new:cNx -> \cs_gnew_nopar:cNx + +\gdef_protected_new:Npn -> \cs_gnew_protected_nopar:Npn +\gdef_protected_new:Npx -> \cs_gnew_protected_nopar:Npx +\gdef_protected_new:cpn -> \cs_gnew_protected_nopar:cpn +\gdef_protected_new:cpx -> \cs_gnew_protected_nopar:cpx + +\gdef_protected_new:NNn -> \cs_gnew_protected_nopar:NNn +\gdef_protected_new:NNx -> \cs_gnew_protected_nopar:NNx +\gdef_protected_new:cNn -> \cs_gnew_protected_nopar:cNn +\gdef_protected_new:cNx -> \cs_gnew_protected_nopar:cNx + +\gdef_long_new:Npn -> \cs_gnew:Npn +\gdef_long_new:Npx -> \cs_gnew:Npx +\gdef_long_new:cpn -> \cs_gnew:cpn +\gdef_long_new:cpx -> \cs_gnew:cpx + +\gdef_long_new:NNn -> \cs_gnew:NNn +\gdef_long_new:NNx -> \cs_gnew:NNx +\gdef_long_new:cNn -> \cs_gnew:cNn +\gdef_long_new:cNx -> \cs_gnew:cNx + +\let:NN -> \cs_set_eq:NN +\let:Nc -> \cs_set_eq:Nc +\let:cN -> \cs_set_eq:cN +\let:cc -> \cs_set_eq:cc + +\glet:NN -> \cs_gset_eq:NN +\glet:Nc -> \cs_gset_eq:Nc +\glet:cN -> \cs_gset_eq:cN +\glet:cc -> \cs_gset_eq:cc + +\let_new:NN -> \cs_new_eq:NN +\let_new:Nc -> \cs_new_eq:Nc +\let_new:cN -> \cs_new_eq:cN +\let_new:cc -> \cs_new_eq:cc + +\glet_new:NN -> \cs_gnew_eq:NN +\glet_new:Nc -> \cs_gnew_eq:Nc +\glet_new:cN -> \cs_gnew_eq:cN +\glet_new:cc -> \cs_gnew_eq:cc + + + + + + + +%% Copyright (C) 1990-2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- \ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/expl3/readme-dev.txt b/Master/texmf-dist/doc/latex/expl3/readme-dev.txt new file mode 100644 index 00000000000..bae4259fe22 --- /dev/null +++ b/Master/texmf-dist/doc/latex/expl3/readme-dev.txt @@ -0,0 +1,120 @@ + + The EXPL3 bundle for LaTeX3 Programming + ======================================= + +GETTING STARTED for developers +------------------------------ + +Welcome! +This is a short guide to how the expl3 bundle is set up, +and how you can get started programming with and +contributing to it. + +First, some signposts: +Email discussion list +SVN repository +SVN repository RRS feed + +Those interested in receiving emails containing the diff +of every commit to the repository should ask on the discussion list. + +For more information, please look in the official README +and in the documentation expl3.pdf. + + +INSTALLATION +------------ + +When you pull down the SVN repository, you'll generally +want two things: the actual packages files so you can +use the `expl3` bundle, and the documentation. + +## Obtaining the code in the SVN repository + +Execute something like this: + + mkdir l3svn + svn checkout http://www.latex-project.org/svnroot/experimental/trunk/ l3svn + +This will give you both the xpackages and the expl3 bundle +contained within the `l3in2e/` directory, plus a few extras. +This readme only concerns the expl3 bundle. + + +## Package files + +Install `expl3` in your local texmf directory with + + make localinstall + +The installation directory is detected automatically, +and in a normal TeXLive distribution will be used +in preference to any existing `expl3` code directory. +(I.e., after the above command your regular documents +will use the new versions of the modules.) + + +## Documentation + +For an individual module, generate the documentation with + + make doc F= + +For example, `make doc F=l3quark`. This will produce +`l3quark.pdf`, which includes the documentation for that +module and its implementation source code. + +To generate the complete reference documentation for +the `expl3` bundle, source3.pdf: + + make sourcedoc + +Note that source3.pdf does not include the modules' +implementation source code; therefore, source3.pdf is a +rough subset (plus index) of the complete set of typeset +module PDFs. + +To generate `source3.pdf` and the documentation for +each module, run + + make alldoc + + +HACKING +------- + +There are two main things you need to know when making +changes to the expl3 bundle. + +1. We have a regression test suite +2. Don't break it + +To make sure things are working, run + + make check + +If you change something, run that again. All working? Great! +Please send your diffs to the discussion list and we can talk +about adding your code. + +You can find more information about the test suite in + + l3in2e/testfiles/README.txt + +On a less critical level, we also have a method to check +that our documentation is somewhat self-consistent. Run + + make checkdoc + +and each module will be compiled and verified that what +is defined in the module is also documented. + +Note that it only checks what we *claim* we are defining +in the documentation; it does not literally check the code. +It will also check that each module's documentation +still compiles without errors. + + +--- Copyright 1998 -- 2009 + The LaTeX3 Project. All rights reserved --- + diff --git a/Master/texmf-dist/doc/latex/expl3/readme.txt b/Master/texmf-dist/doc/latex/expl3/readme.txt deleted file mode 100644 index 81202555eaa..00000000000 --- a/Master/texmf-dist/doc/latex/expl3/readme.txt +++ /dev/null @@ -1,315 +0,0 @@ - - Experimental Packages Demonstrating - A Possible LaTeX3 Programming Convention - ======================================== - - 2008/08/05 - - -WHERE TO GET IT ---------------- - -The files in this distribution represent a snapshot of selected files -from the Subversion (SVN) repository of the LaTeX3 Project. - -To obtain current versions of the files, visit - which contains further -instructions. - -OVERVIEW --------- - -The files of the expl3 bundle provide a low-level API for TeX -programmers with special syntax conventions, completely separating it -from document level syntax. Hence, the commands provided are not -intended for use at the document level nor for use in describing -design layouts in document class files. - -This API provides the foundation on which the LaTeX3 kernel and other -advanced extensions are built. Special care has been taken so that -they can be used within a LaTeX2e context as regular packages. - -While the existing code is approaching a stable state, we cannot -guarantee that names of packages or commands they define will not -change. This is also related to the history of the code: It has been -developed over time and has been used in previous versions for -prototypes implementations, experiments, etc. It may therefore -occasionally contain references to parts that are at present not -distributed. - - -THE GUILTY PERSONS ------------------- - - Frank Mittelbach, Denys Duchier, Johannes Braams, Michael Downes, - David Carlisle, Alan Jeffrey, Chris Rowley, Rainer Schoepf - Javier Bezos, Morten Hoegholm, Thomas Lotze - - -DISCUSSION ----------- - -Discussion concerning the approach, suggestions for improvements, changes, -additions, etc. should be addressed to the list LATEX-L. - -You can subscribe to this list by sending mail to - - listserv@urz.uni-heidelberg.de - -with the body containing - - subscribe LATEX-L - - -BUGS ----- - -If you find a real bug that makes a package stop working you can -report it via the standard LaTeX bug reporting mechanism of the LaTeX -distribution (see bugs.txt there) using the category "Experimental -LaTeX kernel". However please do *not* use this method for -suggestions / comments / improvements / etc. For this the list LATEX-L -should be used instead. - -Also please don't expect these package to work with *any* code that -floats around in the LaTeX2e world. :-) - - - -MANIFEST --------- - -The following packages are in this release: - - -l3names -======= - -Documents the general naming scheme, and gives new names to all the TeX -primitives. - -If this package is used with the option [removeoldnames] then the -original TeX primitive names (\hbox, \def, ...) are made *undefined* and -so free to be defined for other purposes if needed. Of course this -breaks almost all existing LaTeX2 code, but it may be used for testing -purposes, see test2.tex. - -The option removeoldnames has been disabled temporarily. - -l3basics -======== - -Some basic definitions that are used by the other packages. - -l3chk -===== - -Functions that check definitions. -(Comparable to LaTeX2's \newcommand/\renewcommand.) - -l3alloc -======= - -Generic functions for allocating registers. - -l3toks -====== - -TeX's token registers. (Can be compiled with checking enabled) - -l3tlp -===== - -Token List Pointers. A basic LaTeX3 datatype for storing token lists. -(These are essentially macros with no arguments.) The module also -provides functions for arbitrary token lists. (Package can be compiled -with checking enabled.) - -l3expan -======= - -The argument expansion module. One of the main features of the language -proposed here is a systematic treatment of the handling of argument -expansion. The basic functions for preprocessing command arguments are -defined here. - -l3quark -======= - -A `quark' is a command that is defined to expand to itself. So it may -not be directly used (it would generate an infinite loop) but has many -uses as special markers within LaTeX code. - -l3seq -===== - -A module implementing the basic list and stack datatypes. - -l3clist -======= - -A module implementing the handling of comma separated lists - -l3prop -====== - -Property lists are the datatype for handling key/value assignments. - -l3int -===== - -Integer and fake integer registers. With eTeX/Omega becoming more and -more accessible this module is, at least in parts only of historical -significance. (Can be compiled with checking enabled) - -l3num -===== - -Storing numbers as token-lists in macros - -l3skip -====== - -Dealing with length registers - -l3precom -========= - -Low-level pointer-related code, with further checking and tracing. - -l3io -==== - -Low-level input and ouput. - -l3prg -===== - -Experimental control structures. This covers booleans and various -other code. - -l3box -===== - -Low level box handling code - -l3token -===== - -Functions that investigate tokens and determine of which categories -they are. For instance, is the token in question expandable or not? Is -it a macro taking arguments? Also functions for peeking ahead in the -token stream. - -l3xref -===== - -Module providing the low-level interface for cross references. This -module also contains a test file which is generated along with the -package. - -l3messages -===== - -Module providing a new mechanism to provide longer warning and error -messages based on storing the messages in external files. - -l3calc -===== - -Module for using infix notation for the built-in register types -(lengths and counters). - -l3keyval -===== - -Module for extracting data from a key=val list for further processing. - -===================================================================== - -Install file -============= - -l3.ins -====== - -Process with plain TeX or LaTeX2e to generate the experimental -packages. - -===================================================================== - -Experimental LaTeX3 Format -========================== - -l3vers.dtx -========== - -This file contains the version information and other release related -coding. - -l3final.dtx -=========== - -This file is reserved for the last minute coding for producing a -format (such as the dump instruction). - -source3.tex -=========== - -Run this file with pdfLaTeX in extended mode: -pdflatex "*source3.tex" to produce the documentation. -Doing this will produce three extra files (source3.ist, l3doc.cfg and -l3full.cfg). The first of these is a style file for makeindex; the -others or configuration files for the documentation class. -If you want to full documentation including the code listings than -rename l3full.cfg to l3doc.cfg and run LaTeX again. -Alternatively, run (in extended mode) - pdflatex "\PassOptionsToClass{full}{l3doc}\input{source3}" -After that run makeindex to produce the index, like so: -makeindex -s source3.ist source3 -and rerun LaTeX. - -l3format.ins -============ - -Process with plain TeX or LaTeX2e to generate the experimental -format file lbase.ltx and its companion lbase.ini. -The run pdfetex --ini "*lbase.ini" to produce the experimental -format. - -===================================================================== - -Test Files -========== - -Two test files show the expansion module at work. - -test1.tex -========= - -Test document showing the expansion module at work. - -test2.tex -========= - -The same test as the file test1, but this time the l3names package is -loaded with [removeoldnames]. This is useful for testing, but as it -breaks all LaTeX2 code, it is not so useful for documents. (For -example {document} would generate an error.) In this mode -\RequirePackage may be used to load further packages, as demonstrated -in this file, but any other LaTeX2 command is likely to fail. - -The option removeoldnames has been disabled temporarily and so this -test file is of limited use. - -test3.tex -========= - -This tests the io and precomp modules. - - -===================================================================== - ---- Copyright 1998 -- 2008 - The LaTeX3 Project. All rights reserved --- - diff --git a/Master/texmf-dist/doc/latex/expl3/source3.pdf b/Master/texmf-dist/doc/latex/expl3/source3.pdf index 29d7985fe97..6cfe59cae8f 100644 Binary files a/Master/texmf-dist/doc/latex/expl3/source3.pdf and b/Master/texmf-dist/doc/latex/expl3/source3.pdf differ diff --git a/Master/texmf-dist/makeindex/expl3/l3doc.ist b/Master/texmf-dist/makeindex/expl3/l3doc.ist new file mode 100644 index 00000000000..542cffda9ca --- /dev/null +++ b/Master/texmf-dist/makeindex/expl3/l3doc.ist @@ -0,0 +1,72 @@ +%% +%% This is file `l3doc.ist', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% l3doc.dtx (with options: `docist') +%% +%% +%% EXPERIMENTAL CODE +%% +%% Do not distribute this file without also distributing the +%% source files specified above. +%% +%% Do not distribute a modified version of this file. +%% +%% +%% File: l3doc.dtx Copyright (C) 1990-2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +actual '=' +quote '!' +level '>' +preamble +"\n \\begin{theindex} \n \\makeatletter\\scan@allowedfalse\n" +postamble +"\n\n \\end{theindex}\n" +item_x1 "\\efill \n \\subitem " +item_x2 "\\efill \n \\subsubitem " +delim_0 "\\pfill " +delim_1 "\\pfill " +delim_2 "\\pfill " +lethead_prefix "{\\bfseries\\hfil " +lethead_suffix "\\hfil}\\nopagebreak\n" +lethead_flag 1 +heading_prefix "{\\bfseries\\hfil " +heading_suffix "\\hfil}\\nopagebreak\n" +headings_flag 1 + +page_precedence "rnaA" +%% +%% +%% End of file `l3doc.ist'. diff --git a/Master/texmf-dist/source/latex/expl3/expl3.dtx b/Master/texmf-dist/source/latex/expl3/expl3.dtx new file mode 100644 index 00000000000..a22e1b53417 --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/expl3.dtx @@ -0,0 +1,970 @@ +% \iffalse +%% File: expl3.dtx Copyright (C) 1990-2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ + +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +% +%<*driver|package> +\RequirePackage{l3names} +% +%\fi +\GetIdInfo$Id: expl3.dtx 1381 2009-06-01 20:36:02Z joseph $ + {L3 Experimental code bundle wrapper}% +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass{l3doc} +\usepackage{shortvrb,hypdoc} +\MakeShortVerb{\|} +\hyphenation{para-meters para-meter} +% I have found at least 3 other hyphenations of this in various refs, +% but I did also find this, which is my personal favourite ---chris +\hyphenation{ignore ignored ignores} +\begin{document} +\DocInput{\filename.\filenameext} +\end{document} +% +% \fi +% +% \providecommand\acro[1]{\textsc{\MakeLowercase{#1}}} +% \providecommand\ie{i.e.,~} +% \providecommand\eg{e.g.,~} +% \newenvironment{arg-description}{% +% \begin{itemize}\def\makelabel##1{\hss\llap{\bfseries##1}}}{\end{itemize}} +% +% \title{The \textsf{expl3} package and philosophy\thanks{This file +% has version number \fileversion, last +% revised \filedate.}} +% \author{\Team} +% \date{\filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \begin{abstract} +% +% This paper gives a brief introduction to a new set of programming +% conventions that have been designed to meet the requirements of +% implementing large scale \TeX\ macro programming projects such as +% \LaTeX. +% +% The main features of the system described are: +% \begin{itemize} +% \item classification of the macros (or, in \LaTeX{} terminology, +% commands) into \LaTeX{} functions and \LaTeX{} parameters, and also +% into modules containing related commands; +% \item a systematic naming scheme based on these +% classifications; +% \item a simple mechanism for controlling the expansion of a function's +% arguments. +% \end{itemize} +% This system is being used as the basis for +% \TeX{} programming within the \LaTeX3 project. +% Note that the language is not intended for either +% document mark-up or style specification. +% +% An earlier description of the \LaTeX3 programming language is +% available from \url{http://www.latex-project.org/papers}. +% \end{abstract} +% +% +% \section{Introduction} +% +% This paper describes the conventions for a \TeX-based programming +% language which is intended to provide a more consistent and rational +% environment for the construction of large scale systems, such as +% \LaTeX, using \TeX{} macros. +% +% Variants of this language have been in use by The \LaTeX3 Project Team +% since around 1990 but the syntax specification to be outlined here +% should \emph{not} be considered final. This is an experimental +% language thus many aspects, such as the syntax conventions and naming +% schemes, may (and probably will) change as more experience is gained +% with using the language in practice. +% +% The next section shows where this language fits into a complete +% \TeX-based document processing system. We then describe the major +% features of the syntactic structure of command names, including the +% argument specification syntax used in function names. +% +% The practical ideas behind this argument syntax will be explained, +% together with the semantics of the expansion control mechanism and the +% interface used to define variant forms of functions. The paper also +% discusses some advantages of the syntax for parameter names. +% +% As we shall demonstrate, the use of a structured naming scheme and of +% variant forms for functions greatly improves the readability of the +% code and hence also its reliability. Moreover, experience has shown +% that the longer command names which result from the new syntax do not +% make the process of \emph{writing} code significantly harder +% (especially when using a reasonably intelligent editor). +% +% The final section gives some details of our plans to distribute parts +% of this system. Although the paper is now a little dated, more general +% information concerning the work of the \LaTeX3 Project can be found +% in Ref.~\cite{tub:MR97-1}. +% +% +% \section{Languages and interfaces} +% \label{sec:langs} +% +% It is possible to identify several distinct languages related to the +% various interfaces that are needed in a \TeX-based document processing +% system. This section looks at those we consider most important for +% the \LaTeX3 system. +% +% \begin{description} +% \item[Document mark-up] This comprises those commands (often called tags) +% that are to embedded in the document (the |.tex| file). +% +% It is generally accepted that such mark-up should be essentially +% \emph{declarative}. +% It may be traditional \TeX-based mark-up such as +% \LaTeXe, as described in~\cite{A-W:LLa94} and~\cite{A-W:GMS94}, +% or a mark-up language defined via \acro{SGML} or \acro{XML}. +% +% One problem with more traditional \TeX\ coding conventions (as +% described in~\cite{A-W:K-TB}) is that the names and syntax of \TeX's +% primitive formatting commands are ingeniously designed to be +% `natural' when used directly by the author as document mark-up or in +% macros. Ironically, the ubiquity (and widely recognised +% superiority) of logical mark-up has meant that such explicit +% formatting commands are almost never needed in documents or in +% author-defined macros. Thus they are used almost exclusively by +% \TeX{} programmers to define higher-level commands; and their +% idiosyncratic syntax is not at all popular with this community. +% Moreover, many of them have names that could be very useful as +% document mark-up tags were they not pre-empted as primitives (\eg +% |\box| or |\special|). +% +% \item[Designer interface] This relates a (human) typographic +% designer's specification for a document to a program that `formats +% the document'. It should ideally use a declarative language that +% facilitates expression of the relationship and spacing rules specified +% for the layout of the various document elements. +% +% This language is not embedded in document text and it will be very +% different in form to the document mark-up language. For +% \acro{SGML}-based systems the \acro{DSSSL} language may come to play +% this role. For \LaTeX, this level was almost completely missing +% from \LaTeX2.09; \LaTeXe\ made some improvements in this area but it +% is still the case that implementing a design specification in +% \LaTeX\ requires far more `low-level' coding than is acceptable. +% \item[Programmer interface] +% This language is the implementation +% language within which the basic typesetting functionality is +% implemented, building upon the primitives of \TeX\ (or a +% successor program). +% It may also be used to implement the previous +% two languages `within' \TeX, as in the current \LaTeX\ system. +% \end{description} +% +% Only the last of these three interfaces is covered by this paper, +% which describes a system aimed at providing a suitable basis for +% coding large scale projects in \TeX{} (but this should not preclude its +% use for smaller projects). Its main distinguishing features are +% summarised here. +% +% \begin{itemize} +% \item A consistent naming scheme for all commands, including \TeX\ +% primitives. +% \item The classification of commands as \LaTeX{} functions or \LaTeX{} +% parameters, and also their division into modules according to their +% functionality. +% \item A simple mechanism for controlling argument expansion. +% \item Provision of a set of core \LaTeX{} functions that is sufficient +% for handling programming constructs such as queues, sets, +% stacks, property lists. +% \item A \TeX{} programming environment in which, for example, all +% white space is ignored. +% \end{itemize} +% +% \section{The naming scheme} +% \label{sec:scheme} +% +% The naming conventions for this programming language distinguish +% between \textit{functions} and \textit{parameters}. Functions can have +% arguments and they are executed. Parameters can be assigned values +% and they are used in arguments to functions; they are not directly +% executed but are manipulated by mutator and accessor functions. +% Functions and parameters with a related functionality (for example +% accessing counters, or manipulating token-lists, etc.)\ are collected +% together into a +% \textit{module}. +% +% +% Note that all these terms are only \LaTeX{} terminology and are not, +% for example, intended to indicate that the commands have these +% properties when considered in the context of basic \TeX{} or in any +% more general programming context. +% +% +% \subsection{Examples} +% \label{sec:ex} +% +% Before giving the details of the naming scheme, here are a few typical +% examples to indicate the flavour of the scheme; first some parameter +% names. +% \begin{quote} +% |\l_tmpa_box| is a local parameter (hence the~|l_| prefix) +% corresponding to a box register.\\ +% |\g_tmpa_int| is a global parameter (hence the~|g_| prefix) +% corresponding to an integer register (\ie a \TeX{} count register).\\ +% |\c_empty_toks| +% is the constant~(|c_|) token register parameter that is for ever empty. +% \end{quote} +% Now here is an example of a typical function name. +% +% |\seq_push:Nn| is the function which puts the token list specified by +% its second argument onto the stack specified by its first argument. +% The different natures of the two arguments are indicated by the~|:Nn| +% suffix. The first argument must be a single token which `names' +% the stack parameter: such single-token arguments are denoted~|N|. +% The second argument is a normal \TeX\ `undelimited argument', which +% may either be a single token or a balanced, brace-delimited token +% list (which we shall here call a \textit{braced token list}): the~|n| +% denotes such a `normal' argument form. The name of the function +% indicates it belongs to the |seq| module. +% +%^^A |\seq_push:cn| would be similar to the above, but in this case the~|c| +%^^A means that the stack-name is specified in the first argument by a +%^^A token list that expands, using |\csname...|, to a control sequence that +%^^A is the \emph{name} of the stack parameter. +%^^A +%^^A \noindent +%^^A The names of these two functions also indicate that they are in the +%^^A module called |seq|. +% +% +% \subsection{Formal syntax of the conventions} +% \label{sec:namesyn} +% +% We shall now look in more detail at the syntax of these names.\\ +% The syntax of parameter names is as follows: +% \begin{quote} +% |\|\m{access}|_|\m{module}|_|\m{description}|_|\m{type} +% \end{quote} +% The syntax of function names is as follows: +% \begin{quote} +% |\|\m{module}|_|\m{description}|:|\m{arg-spec} +% \end{quote} +% +% +% \subsection{Modules and descriptions} +% \label{sec:modules} +% +% The syntax of all names contains +% \begin{quote} +% \m{module} and \m{description}: +% \end{quote} +% these both give information about the command. +% +% A \textit{module} is a collection of +% closely related functions and parameters. +% Typical module names include~|int| for integer parameters +% and related functions,~|seq| for sequences and~|box| for boxes. +% +% Packages providing new programming functionality will add new modules +% as needed; the programmer can choose any unused name, consisting +% of letters only, for a module. +% +% The \textit{description} gives more detailed information about the +% function or parameter, and provides a unique name for it. It should +% consist of letters and, possibly,~|_|~characters. +% +% As a semi-formalized concept the letter |g| is sometimes used to +% prefix certain parts of the \m{description} +% to mark the function as ``globally acting'', e.g., |\int_set:Nn| is +% a local operation while |\int_gset:Nn| is a global operation. This +% of course goes hand in hand with when to use |\l_| and |\g_| +% variable prefixes. +% +% \subsection{Parameters: access and type} +% \label{sec:parms} +% +% The \m{access} part of the name describes how the parameter can be +% accessed. Parameters are primarily classified as local, global or +% constant (there are further, more technical, classes). This +% \textit{access} type appears as a code at the beginning of the name; +% the codes used include: +% \begin{arg-description} +% \item[c] +% constants (global parameters whose value should not be changed); +% \item[g] +% parameters whose value should only be set globally; +% \item[l] +% parameters whose value should only be set locally. +% \end{arg-description} +% +% The \m{type} will normally (except when introducing a new data-type) +% be in the list of available \textit{data-types}; these include the +% primitive \TeX\ data-types, such as the various registers, but to +% these will be added data-types built within the \LaTeX{} programming +% system. +% +% Here are some typical data-type names: +% \begin{description} +% \item[int] integer-valued count register; +% \item[tl] token list variables: placeholders for token lists; +% \item[toks] token register; +% \item[box] box register; +% \item[skip] `rubber' lengths; +% \item[dim] `rigid' lengths; +% \item[num] A `fake' integer type using only macros. Useful for +% setting up allocation routines; +% \item[seq] `sequence': a data-type used to implement lists +% (with access at both ends) and stacks; +% \item[prop] property list; +% \item[clist] comma separated list; +% \item[stream] an input or output stream (for reading from or writing to, respectively); +% \item[bool] either true or false. +% \end{description} +% When the \m{type} and \m{module} are identical (as often happens in +% the more basic modules) the \m{module} part is often omitted for +% aesthetic reasons. +% +% +% \subsection{Functions: basic argument specifications} +% \label{sec:args} +% +% Function names end with an \m{arg-spec} after a colon. This +% gives an indication of the types of argument that a function takes, +% and provides a convenient method of naming similar functions that +% differ only in their argument forms (see the next section for +% examples). +% +% The \m{arg-spec} consists of a (possibly empty) list of characters, +% each denoting one argument of the function. It is important to +% understand that `argument' here refers to the effective argument of +% the \LaTeX{} function, not to an argument at the \TeX-level. Indeed, +% the top level \TeX\ macro that has this name typically has no +% arguments. This is an extension of the existing \LaTeX\ convention +% where one says that |\section| has an optional argument and a +% mandatory argument, whereas the \TeX\ macro |\section| actually has +% zero parameters at the \TeX\ level, it merely calls an internal \LaTeX\ +% command which in turn calls others that look ahead for star forms and +% optional arguments. +% +% All functions have a base form with arguments using one of the +% following argument specifiers. +% \begin{arg-description} +% \item[n] Unexpanded token or braced token list.\\ +% This is a standard \TeX\ undelimited macro argument. +% \item[N] Single token (unlike~|n|, the argument must \emph{not} be +% surrounded by braces).\\ +% A typical example of a command taking an~|N| +% argument is~|\cs_set|, in which the command being defined must be +% unbraced. +% \item[p] Primitive \TeX\ parameter specification.\\ +% This can be something simple like~|#1#2#3|, but may use arbitrary +% delimited argument syntax such as: |#1,#2\q_stop#3|. This is used +% when defining functions. +% \item[T,F] +% These are special cases of~|n| arguments, used for the +% true and false code in conditional commands. +% \end{arg-description} +% There are two other specifiers with more general meanings: +% \begin{arg-description} +% \item[D] This means: \textbf{Do not +% use}. This special case is used +% for \TeX\ primitives and other commands that are provided for use +% only while bootstrapping the \LaTeX\ kernel. If the \TeX\ primitive +% needs to be used in other contexts it will be given an alternative, +% more appropriate, name with a useful argument specification. The +% argument syntax of these is often weird, in the sense described next. +% \item[w] This means that the argument syntax is `weird' in that it +% does not follow any standard rule. It is used for functions with +% arguments that take non standard forms: examples are \TeX-level +% delimited arguments and the boolean tests needed after certain +% primitive |\if|\ldots\ commands. +% \end{arg-description} +% +% In case of "n" arguments that consist of a +% single token the surrounding braces can be omitted in nearly all +% situations---functions that force the use of braces even for single +% token arguments are explicitly mentioned. For example, "\seq_gpush:Nn" +% is a function that takes two arguments, the first is a single token +% (the sequence) and the second may consist of several tokens surrounded +% by braces. +% +% This concept of argument specification makes it easy to read the code +% and should be followed when defining new functions. +% +% +% +% +% \section{Expansion control} +% \label{sec:exp} +% +% Let's take a look at some typical operations one might want to +% perform. Suppose we maintain a stack of open files and we use the +% stack |\g_io_file_name_seq| to keep track of them (|io| is the +% input-output file module). The basic operation +% here is to push a name onto this stack which could be done by the +% operation +% \begin{quote} +% "\seq_gpush:Nn" \\ +% " \g_io_file_name_seq" \\ +% " {#1}" +% \end{quote} +% where |#1| is the filename. In other words, this operation would +% push the file name as is. +% +% However, we might face a situation where +% the filename is stored in a register of some sort, say +% |\l_io_curr_file_tl|. In this case we want to retrieve the value of +% the register. If we simply use +% \begin{quote} +% "\seq_gpush:Nn" \\ +% " \g_io_file_name_seq" \\ +% " \l_io_curr_file_tl " +% \end{quote} +% we will not get the value of the register pushed onto the stack, +% only the register name itself. Instead a suitable number of +% "\exp_after:wN" would be necessary (together with extra braces) to +% change the order of execution, i.e. +% \begin{quote} +% "\exp_after:wN" \\ +% " \seq_gpush:Nn" \\ +% "\exp_after:wN" \\ +% " \g_io_file_name_seq" \\ +% "\exp_after:wN" \\ +% " {\l_io_curr_file_tl}" +% \end{quote} +% +% The above example is probably the simplest case but already shows +% how the code changes to something difficult to +% understand. Furthermore there is an assumption in this: That the +% storage bin reveals its contents after exactly one +% expansion. Relying on this means that you cannot do proper checking +% plus you have to know exactly how a storage bin acts in order to get +% the correct number of expansions. Therefore \LaTeX3 provides the +% programmer with a general scheme that keeps the code compact and +% easy to understand. +% +% To denote that some argument to a function needs special treatment one +% just uses different letters in the argument part of the function to +% mark the desired behavior. In the above example one would write +% \begin{quote} +% "\seq_gpush:NV" \\ +% " \g_io_file_name_seq " \\ +% " \l_io_curr_file_tl " +% \end{quote} +% to achieve the desired effect. Here the "V" is for ``retrieve the +% value of the register'' (the second argument) before passing it to +% the base function. +% +% +% The following letters can be used to denote special treatment of +% arguments before passing it to the base function: +% \begin{description} +% \item[c] Character string used as a command name.\\ The argument (a +% token or braced token list) must, when fully expanded, produce a +% sequence of characters which is then used to construct a command +% name (via~|\csname|, |\endcsname|). This command name is the +% single token that is passed to the function as the argument. Hence +% \begin{quote} +% "\seq_gpush:cV {g_file_name_stack} \l_tmpa_tl" +% \end{quote} +% is equivalent to +% \begin{quote} +% "\seq_gpush:NV \g_file_name_stack \l_tmpa_tl". +% \end{quote} +% +% \item[V] Value of a register.\\ +% This means that the register in question is returned, be it an +% integer, a length type register, a macro storage register or +% similar. The value is returned to the function as a braced token list. +% +% \item[v] Value of a register, constructed from a character string +% used as a command name.\\ +% This is a combination of |c| and |V| which first constructs a +% control sequence from the argument and then returns the value. +% +% \item[x] Fully-expanded token or braced token list.\\ +% This means that the argument is expanded as in the replacement +% text of an~|\edef|, and the expansion is passed to the function as +% a braced token list. This means that expansion takes place until +% only unexpandable tokens are left. +% +% \item[o] One-level-expanded token or braced token list.\\ +% This means that the argument is expanded one level, as by +% |\expandafter|, and the expansion is passed to the function as a braced +% token list. Note that if the original argument is a braced +% token list then only the first token in that list is expanded. +% +% \item[f] Almost the same as the |x| type except here the token list +% is expanded fully until the first unexpandable token is found and +% the rest is left unchanged. Note that if this function finds a +% space at the beginning of the argument it will gobble it and not +% expand the next argument. +% \end{description} +% +% +% \subsection{Simpler means better} +% \label{sec;simpler} +% +% Anyone who programs in \TeX\ is frustratingly familiar with the +% problem of arranging that arguments to functions are suitably expanded +% before the function is called. To illustrate how expansion control +% can bring instant relief to this problem we shall consider two +% examples copied from \texttt{latex.ltx}. +% +% \begin{verbatim} +% \global\expandafter\let +% \csname\cf@encoding \string#1\expandafter\endcsname +% \csname ?\string#1\endcsname +% \end{verbatim} +% This first piece of code is in essence simply a global |\let| whose +% two arguments firstly have to be constructed before |\let| is +% executed. The |#1| is a control sequence name such as +% |\textcurrency|. The token to be defined is obtained by +% concatenating the characters of the current font encoding stored in +% |\cf@encoding|, which has to be fully expanded, and the name of the +% symbol. The second token is the same except it uses the default +% encoding |?|. The result is a mess of interwoven |\expandafter| +% and |\csname| beloved of all \TeX\ programmers, and the code is +% essentially unreadable. +% +% Using the conventions and functionality outlined here, the task would +% be achieved with code such as this: +% \begin{verbatim} +% \cs_gset_eq:cc {\cf@encoding \string #1} +% {?\string #1} +% \end{verbatim} +% The command |\cs_gset_eq:cc| is a global~|\let| that generates +% command names out of both of its arguments before making the +% definition. This produces code that is far more readable and more +% likely to be correct first time. +% +% Here is the second example. +% \begin{verbatim} +% \expandafter +% \in@ +% \csname sym#3% +% \expandafter +% \endcsname +% \expandafter +% {% +% \group@list}% +% \end{verbatim} +% This piece of code is part of the definition of another function. It +% first produces two things: a token list, by expanding |\group@list| once; +% and a token whose name comes from~`|sym#3|'. Then the function~|\in@| +% is called and this tests if its first argument occurs in the token list +% of its second argument. +% +% Again we can improve enormously on the code. First we shall rename +% the function~|\in@| according to our conventions. A function such as +% this but taking two normal `\texttt{n}' arguments might reasonably be +% named |\seq_test_in:Nn|; thus the variant function we need will be +% defined with the appropriate argument types and its name will be +% |\seq_test_in:cV|. Now this code fragment will be simply: +% \begin{verbatim} +% \seq_test_in:cV {sym#3} \l_group_seq +% \end{verbatim} +% Note that, in addition to the lack of |\expandafter|, the space after +% the~|}| will be silently ignored since all white space is ignored in +% this programming environment. +% +% +% \subsection{New functions from old} +% \label{sec:newfunc} +% +% For many common functions the \LaTeX3 kernel will provide variants +% with a range of argument forms, and similarly it is expected that +% extension packages providing new functions will make them available in +% the all the commonly needed forms. +% +% However, there will be occasions where it is necessary to construct a +% new such variant form; therefore the expansion module provides a +% straightforward mechanism for the creation of functions with any +% required argument type, starting from a function that takes `normal' +% \TeX\ undelimited arguments. +% +% To illustrate this let us suppose you have a `base function' +% |\demo_cmd:nnn| that takes three normal arguments, and that you need +% to construct the variant |\demo_cmd:cnx|, for which the first argument +% is used to construct the \emph{name} of a command, whilst the third +% argument must be fully expanded before being passed to +% |\demo_cmd:nnn|. +% To produce the variant form from the base form, simply use this: +% \begin{verbatim} +% \cs_generate_variant:Nn \demo_cmd:nnn {cnx} +% \end{verbatim} +% This defines the variant form so that you can then write, for example: +% \begin{verbatim} +% \demo_cmd:cnx {abc} {pq} {\rst \xyz } +% \end{verbatim} +% rather than \ldots\ well, something like this! +% \begin{verbatim} +% \def \tempa {{pq}}% +% \edef \tempb {\rst \xyz}% +% \expandafter +% \demo@cmd:nnn +% \csname abc% +% \expandafter +% \expandafter +% \expandafter +% \endcsname +% \expandafter +% \tempa +% \expandafter +% {% +% \tempb +% }% +% \end{verbatim} +% +% Another example: you may wish to declare a function +% |\demo_cmd_b:xcxcx|, a variant of an existing function +% |\demo_cmd_b:nnnnn|, that fully +% expands arguments 1,~3 and~5, and produces commands to pass as +% arguments 2 and~4 using~|\csname|. +% The definition you need is simply +% \begin{verbatim} +% \cs_generate_variant:Nn +% \demo_cmd_b:nnnnn {xcxcx} +% \end{verbatim} +% +% This extension mechanism is written so that if the same new form of +% some existing command is implemented by two extension packages then the +% two definitions will be identical and thus no conflict will occur. +% +% +% \section{Parameter assignments and accessor functions} +% \label{sec:access} +% +% \subsection{Checking assignments} +% \label{sec:check} +% +% One of the advantages of having a consistent scheme is that the system +% can provide more extensive error-checking and debugging facilities. +% For example, an accessor function that makes a \emph{global} +% assignment of a value to a parameter can check that it is not passed +% the name of a \emph{local} parameter as that argument: it does this by +% checking that the name starts with~|\g_|. +% +% Such checking is probably too slow for normal use, but the code can +% have hooks built in that allow a format to be made in which all +% functions perform this kind of check. +% +% A typical section of the source^^A +% \footnote{This code uses the \textsf{docstrip} +% system described in~\cite{A-W:GMS94}, Section~14.3.} +% for such code might look like this +% (recall that all white space is ignored): +% +% \begin{verbatim} +% %<*!check> +% \cs_new_eq:NN +% \toks_gset:Nn \tex_global:D +% % +% %<*check> +% \cs_new_nopar:Npn +% \toks_gset:Nn #1 +% { +% \chk_global:N #1 +% \tex_global:D #1 +% } +% % +% \end{verbatim} +% In the above code the function |\toks_gset:Nn| takes a single +% token~(|N|) specifying a token register, and globally sets it to the +% value passed in the second argument. +% +% A typical use of it would be: +% \begin{verbatim} +% \toks_gset:Nn \g_xxx_toks {} +% \end{verbatim} +% In the normal definition, |\toks_gset:Nn| can be simply~|\let| +% to~|\global| because the primitive \TeX{} token register does not +% require any explicit assignment function: +% this is done by the |%<*!check>| code above. +% +% The alternative definition first checks that the argument +% passed as~|#1| is the name of a global parameter and raises an error +% if it is not. It does this by taking apart the command name passed +% as~|#1| and checking that it starts~|\g_|. +% +% \subsection{Consistency} +% \label{sec:cons} +% +% The primitive \TeX\ syntax for register assignments has a very minimal +% syntax and, apart from box functions, there are no explicit functions +% for assigning values to these registers. +% +% This makes it impossible to implement alternative data-types with a +% syntax that is both consistent and at all similar to the syntax for +% the primitives; moreover, it encourages a coding style that is very +% error prone. +% +% As in the |\toks_gset:Nn| example given above, all \LaTeX\ data-types +% are provided with explicit functions for assignment and for use, even +% when these have essentially empty definitions. This allows for better +% error-checking as described above; it also allows the construction of +% further data-types with a similar interface, even when the +% implementation of the associated functions is very complex. +% +% For example, the `fake-integer' (\texttt{num}) data-type mentioned +% above will appear at the \LaTeX{} programming level to be exactly like +% the data-type based on primitive count registers; however, internally +% it makes no use of count registers. Typical functions in this module +% are illustrated here. +% +% \begin{verbatim} +% \num_new:N \l_tmpa_num +% \end{verbatim} +% This declares the local parameter |\l_example_num| as a fake-counter. +% +% \begin{verbatim} +% \num_add:Nn \l_example_num \c_thirty_two +% \end{verbatim} +% This increments the value of this fake-counter by 32. +% +% +% \section{The experimental distribution} +% \label{sec:dist} +% +% The initial implementations of a \LaTeX\ programming language using +% this kind of syntax remain unreleased (and not completely functional); +% they partly pre-date \LaTeXe! The planned distribution will provide a +% subset of the functionality of those implementations, in the form of +% packages to be used on top of \LaTeXe. +% +% The intention is to allow experienced \TeX\ programmers to experiment +% with the system and to comment on the interface. This means that +% \textbf{\itshape the interface will change}. No part of this system, +% including the name of anything, should be relied upon as being +% available in a later release. Please do \emph{experiment} with these +% packages, but do \emph{not} use them for code that you expect to keep +% unchanged over a long period. +% +% In view of the intended experimental use for this distribution we +% shall, in the first instance, produce only a few modules for use with +% \LaTeXe. These will set up the conventions and the basic functionality +% of, for example, the expansion mechanism; they will also implement some +% of the basic programming constructs, such as token-lists and sequences. +% They are intended only to give a flavour of the code: the full \LaTeX3 +% kernel will provide a very rich set of programming constructs so that +% packages can efficiently share code, in contrast with the situation in +% the current \LaTeX\ where every large package must implement its own +% version of queues, stacks, etc., as necessary. +% +% At time of writing the \textsf{expl3} bundle consists of the +% following modules. +% +% This distribution will also contain the \LaTeX\ source for the latest +% version of this document, a docstrip install file and three small test +% files. +% +% \begin{description} +% \providecommand\explpkg[2]{\item[#1]#2} +% \explpkg{l3basics}{ +% This contains the basic definition modules used +% by the other packages. +% } +% \explpkg{l3box}{ +% Primitives for dealing with boxes. +% } +% \explpkg{l3calc}{ +% A re-implementation of the \LaTeXe\ package \pkg{calc} package in +% \pkg{expl3} that provides extended methods for numeric and dimensional +% calculations and assignments. +% } +% \explpkg{l3chk}{ +% A module that provides functionality comparable to +% \LaTeX's \cmd{\newcommand} and \cmd{\renewcommand}, and also the +% extra level of +% checking for ensure internal consistency in the code. +% } +% \explpkg{l3clist}{ +% Methods for manipulating comma-separated token lists. +% } +% \explpkg{l3expan}{ +% This is the argument expansion module discussed above. +% } +% \explpkg{l3int}{ +% This implements the integer data-type \texttt{int}. +% } +% \explpkg{l3io}{ +% A module providing low level input and output functions. +% } +% \explpkg{l3keyval}{ +% A re-implementation of the \LaTeXe\ package \pkg{keyval}; +% provides low-level macros for dealing with lists of the form +% \texttt{\{ key1=val1 , key2=val2 \}}. +% } +% \explpkg{l3messages/l3msg}{ +% Communicating with the user. +% } +% \explpkg{l3names}{ +% This sets up the basic naming scheme and renames all +% the \TeX\ primitives. If it is loaded with the option +% \texttt{[removeoldnames]} then the old primitive names such as~\cmd{\box} +% become \emph{undefined} and are thus available for user +% definition. Caution: use of this option will certainly break existing +% \TeX\ code! +% } +% \explpkg{l3num}{ +% This implements the `fake integer' datatype \texttt{num}. +% } +% \explpkg{l3precom}{ +% A `pre-compilation' module that provides functions dealing with pointer +% creation and handling, and using external files to record the state of the current +% definitions. +% } +% \explpkg{l3prg}{ +% Program control structures such as boolean data type |bool|, generic +% do-while loops, case-switches, sorting routines and stepwise loops. +% } +% \explpkg{l3prop}{ +% This implements the data-type for `property lists' that are used, in +% particular, for storing key/value pairs. +% } +% \explpkg{l3quark}{ +% A `quark' is a command that is defined to expand to +% itself! Therefore they must never be expanded as this will generate +% infinite recursion; they do however have many uses, \eg as +% special markers and delimiters within code. +% } +% \explpkg{l3seq}{ +% This implements data-types such as queues and stacks. +% } +% \explpkg{l3skip}{ +% Implements the `rubber length' datatype \texttt{skip} and the +% `rigid length' datatype |dim|. +% } +% \explpkg{l3tl}{ +% This implements a basic data-type, called a \textit{token-list +% variable} (|tl var.|), used for storing named token lists: these are +% essentially \TeX{} macros with no arguments. +% } +% \explpkg{l3token}{ +% Analysing token lists and token streams, including peeking ahead to +% see what's coming next and inspecting tokens to detect which kind +% they are. +% } +% \explpkg{l3toks}{ +% A data-type corresponding to \TeX's primitive token registers. +% } +% \explpkg{l3xref}{ +% Data structure for low-level document cross-referencing. This +% provided the foundation for Heiko Oberdiek's \pkg{zref} package. +% } +% \end{description} +% +% \begin{thebibliography}{1} +% +% \bibitem{A-W:K-TB} +% Donald E Knuth +% \newblock {\em The {\TeX}book}. +% \newblock Addison-Wesley, Reading, Massachusetts, 1984. +% +% \bibitem{A-W:GMS94} +% Goossens, Mittelbach and Samarin. +% \newblock {\em The {\LaTeX} Companion}. +% \newblock Addison-Wesley, Reading, Massachusetts, 1994. +% +% \bibitem{A-W:LLa94} +% Leslie Lamport. +% \newblock {\em {\LaTeX:} A Document Preparation System}. +% \newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994. +% +% \bibitem{tub:MR97-1} +% Frank Mittelbach and Chris Rowley. +% \newblock `The {\LaTeX3} Project'. +% \newblock {\em {TUG}boat}, +% Vol.\,18, No.\,3, pp.\,195--198, 1997. +% +% \end{thebibliography} +% +% \end{documentation} +% +% \begin{implementation} +% +% \subsection{\pkg{expl3} implementation} +% +% Well, it's not complicated |:)| +% +%<*package> +% \begin{macrocode} +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +% \end{macrocode} +% +% We already loaded \pkg{l3names} at the beginning of the \acro{dtx} file. +% +% The \pkg{l3chk} package is omitted since it is only used for conditional +% processing with full error-checking turned on. Most users will generally +% not need to do this, and we haven't set it up yet, anyway. +% +% Fundamentals: +% \begin{macrocode} +\RequirePackage{ + l3basics, + l3expan, + l3tl, + l3num, + l3intexpr, + l3quark, + l3seq, + l3toks, + l3int, + l3prg, + l3clist, + l3token, + l3io, + l3prop, + l3msg, + l3skip, +} +% \end{macrocode} +% All the rest: +% \begin{macrocode} +\RequirePackage{ + l3box, + l3keyval, + l3precom, + l3calc, + l3xref, + l3file +} +% \end{macrocode} +% +% +% \end{implementation} +% +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/expl3.tex b/Master/texmf-dist/source/latex/expl3/expl3.tex deleted file mode 100644 index 8d9e1880667..00000000000 --- a/Master/texmf-dist/source/latex/expl3/expl3.tex +++ /dev/null @@ -1,753 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% based on version for the TUGboat proceedings -% Copyright 1997--98 David Carlisle, Chris Rowley, Frank Mittelbach -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% $Id: expl3.tex 246 2004-11-11 08:20:37Z mittelba $ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\documentclass{article} - -\usepackage{shortvrb} -\MakeShortVerb{\|} - -% A couple of \provide.. so document runs with -% both ltugproc and ltxguide classes -% -\providecommand \m [1]{$\langle$\textit{#1}$\rangle$} -%\providecommand \netaddress {\date} -\providecommand \acro [1]{\textsc{\MakeLowercase{#1}}} -\providecommand \ie {i.e.,~} -\providecommand \eg {e.g.,~} - -\hyphenation{para-meters para-meter} -% I have found at least 3 other hyphenations of this in various refs, -% but I did also find this, which is my personal favourite ---chris - -\hyphenation{ignore ignored ignores} - -\begin{document} - -\title{The \LaTeX3 Programming Language---\\ -a proposed system for \TeX\ macro programming} - - -\author{\copyright~David Carlisle, Chris Rowley and\\ Frank Mittelbach\\ -\LaTeX3 project\\ -\texttt{latex-l@urz.uni-heidelberg.de}} - - -\maketitle - -\begin{abstract} - -This paper gives s brief introduction to a new set of programming -conventions that have been designed to meet the requirements of -implementing large scale \TeX\ macro programming projects such as -\LaTeX. - -The main features of the system described are: -\begin{itemize} -\item classification of the macros (or, in \LaTeX{} terminology, - commands) into \LaTeX{} functions and \LaTeX{} parameters, and also - into modules containing related commands; -\item a systematic naming scheme based on these - classifications; -\item a simple mechanism for controlling the expansion of a function's -arguments. -\end{itemize} -A system such as this is being used experimentally as the basis for -\TeX{} programming within the \LaTeX3 project. -Note that the language is not intended for either -document mark-up or style specification. - -This paper is based on a talk given by David Carlisle in San -Francisco, July 1997, but it describes the work of several people: -principally - Frank Mittelbach and - Denys Duchier, -together with - Johannes Braams, - David Carlisle, - Michael Downes, - Alan Jeffrey, - Chris Rowley and - Rainer Sch\"opf. -\end{abstract} - -\vspace{4pt} - - -\section{Introduction} - -This paper describes the conventions for a \TeX-based programming -language which is intended to provide a more consistent and rational -environment for the construction of large scale systems, such as -\LaTeX, using \TeX{} macros. - -Variants of this language have been in use by The \LaTeX3 Project Team -since around 1990 but the syntax specification to be outlined here -should \emph{not} be considered final. This is an experimental -language thus many aspects, such as the syntax conventions and naming -schemes, may (and probably will) change as more experience is gained -with using the language in practice. - -The next section shows where this language fits into a complete -\TeX-based document processing system. We then describe the major -features of the syntactic structure of command names, including the -argument specification syntax used in function names. - -The practical ideas behind this argument syntax will be explained, -together with the semantics of the expansion control mechanism and the -interface used to define variant forms of functions. The paper also -discusses some advantages of the syntax for parameter names. - -As we shall demonstrate, the use of a structured naming scheme and of -variant forms for functions greatly improves the readability of the -code and hence also its reliability. Moreover, experience has shown -that the longer command names which result from the new syntax do not -make the process of \emph{writing} code significantly harder -(especially when using a reasonably intelligent editor). - -The final section gives some details of our plans to distribute parts -of this system during the next year. -More general information concerning the work of the \LaTeX3 Project -can be found in~\cite{tub:MR98-1}. - - -\section{Languages and interfaces} -\label{sec:langs} - -It is possible to identify several distinct languages related to the -various interfaces that are needed in a \TeX-based document processing -system. This section looks at those we consider most important for -the \LaTeX3 system. - -\begin{description} -\item[Document mark-up] This comprises those commands (often called tags) - that are to embedded in the document (the |.tex| file). - - It is generally accepted that such mark-up should be essentially - \emph{declarative}. - It may be traditional \TeX-based mark-up such as - \LaTeXe, as described in~\cite{A-W:LLa94} and~\cite{A-W:GMS94}, - or a mark-up language defined via \acro{SGML} or \acro{XML}. - - One problem with more traditional \TeX\ coding conventions (as - described in~\cite{A-W:K-TB}) is that the names and syntax of \TeX's - primitive formatting commands are ingeniously designed to be - `natural' when used directly by the author as document mark-up or in - macros. Ironically, the ubiquity (and widely recognised - superiority) of logical mark-up has meant that such explicit - formatting commands are almost never needed in documents or in - author-defined macros. Thus they are used almost exclusively by - \TeX{} programmers to define higher-level commands; and their - idiosyncratic syntax is not at all popular with this community. - Moreover, many of them have names that could be very useful as - document mark-up tags were they not pre-empted as primitives (\eg - |\box| or |\special|). - -\item[Designer interface] This relates a (human) typographic - designer's specification for a document to a program that `formats - the document'. It should ideally use a declarative language that - facilitates expression of the relationship and spacing rules specified - for the layout of the various document elements. - - This language is not embedded in document text and it will be very - different in form to the document mark-up language. For - \acro{SGML}-based systems the \acro{DSSSL} language may come to play - this role. For \LaTeX, this level was almost completely missing - from \LaTeX2.09; \LaTeXe\ made some improvements in this area but it - is still the case that implementing a design specification in - \LaTeX\ requires far more `low-level' coding than is acceptable. -\item[Programmer interface] - This language is the implementation - language within which the basic typesetting functionality is - implemented, building upon the primitives of \TeX\ (or a - successor program). - It may also be used to implement the previous - two languages `within' \TeX, as in the current \LaTeX\ system. -\end{description} - -Only the last of these three interfaces is covered by this paper, -which describes a system aimed at providing a suitable basis for -coding large scale projects in \TeX{} (but this should not preclude its -use for smaller projects). Its main distinguishing features are -summarised here. - -\begin{itemize} -\item A consistent naming scheme for all commands, including \TeX\ - primitives. -\item The classification of commands as \LaTeX{} functions or \LaTeX{} - parameters, and also their division into modules according to their - functionality. -\item A simple mechanism for controlling argument expansion. -\item Provision of a set of core \LaTeX{} functions that is sufficient - for handling programming constructs such as queues, sets, - stacks, property lists. -\item A \TeX{} programming environment in which, for example, all - white space is ignored. -\end{itemize} - -\section{The naming scheme} -\label{sec:scheme} - -The naming conventions for this programming language distinguish -between \textit{functions} and \textit{parameters}. Functions can have -arguments and they are executed. Parameters can be assigned values -and they are used in arguments to functions; they are not directly -executed but are manipulated by mutator and accessor functions. -Functions and parameters with a related functionality (for example -accessing counters, or manipulating token-lists, etc.)\ are collected -together into a -\textit{module}. - - -Note that all these terms are only \LaTeX{} terminology and are not, -for example, intended to indicate that the commands have these -properties when considered in the context of basic \TeX{} or in any -more general programming context. - - -\subsection{Examples} -\label{sec:ex} - -Before giving the details of the naming scheme, here are a few typical -examples to indicate the flavour of the scheme; first some parameter -names. -\begin{quote} -|\l_tmpa_box| is a local parameter (hence the~|l_| prefix) -corresponding to a box register.\\ -|\g_tmpa_int| is a global parameter (hence the~|g_| prefix) -corresponding to an integer register (\ie a \TeX{} count register).\\ -|\c_empty_toks| -is the constant~(|c_|) token register parameter that is for ever empty. -\end{quote} -Now here is an example of a typical function name. - -|\seq_push:Nn| is the function which puts the token list specified by -its second argument onto the stack specified by its first argument. -The different natures of the two arguments are indicated by the~|:Nn| -suffix. The first argument must be a single token which `names' -the stack parameter: such single-token arguments are denoted~|N|. -The second argument is a normal \TeX\ `undelimited argument', which -may either be a single token or a balanced, brace-delimited token -list (which we shall here call a \textit{braced token list}): the~|n| -denotes such a `normal' argument form. - -|\seq_push:cn| would be similar to the above, but in this case the~|c| -means that the stack-name is specified in the first argument by a -token list that expands, using |\csname...|, to a control sequence that -is the \emph{name} of the stack parameter. - -\noindent -The names of these two functions also indicate that they are in the -module called |seq|. - - -\subsection{Formal syntax of the conventions} -\label{sec:namesyn} - -We shall now look in more detail at the syntax of these names.\\ -The syntax of parameter names is as follows: - \begin{quote} - |\|\m{access}|_|\m{module}|_|\m{description}|_|\m{type} - \end{quote} -The syntax of function names is as follows: - \begin{quote} - |\|\m{module}|_|\m{description}|:|\m{arg-spec} - \end{quote} - - -\subsection{Modules and descriptions} -\label{sec:modules} - -The syntax of all names contains -\begin{quote} - \m{module} and \m{description}: -\end{quote} -these both give information about the command. - -A \textit{module} is a collection of -closely related functions and parameters. -Typical module names include~|int| for integer parameters -and related functions,~|seq| for sequences and~|box| for boxes. - -Packages providing new programming functionality will add new modules -as needed; the programmer can choose any unused name, consisting -of letters only, for a module. - -The \textit{description} gives more detailed information about the -function or parameter, and provides a unique name for it. It should -consist of letters and, possibly,~|_|~characters. - -\subsection{Parameters: access and type} -\label{sec:parms} - -The \m{access} part of the name describes how the parameter can be -accessed. Parameters are primarily classified as local, global or -constant (there are further, more technical, classes). This -\textit{access} type appears as a code at the beginning of the name; -the codes used include: -\begin{itemize} -\item[\bf c] - constants (global parameters whose value should not be changed); -\item[\bf g] - parameters whose value should only be set globally; -\item[\bf l] - parameters whose value should only be set locally. -\end{itemize} - -The \m{type} will normally (except when introducing a new data-type) -be in the list of available \textit{data-types}; these include the -primitive \TeX\ data-types, such as the various registers, but to -these will be added data-types built within the \LaTeX{} programming -system. - -Here are some typical data-type names: -\begin{description} -\item[int] integer-valued count register; -\item[toks] token register; -\item[box] box register; -\item[fint] `Fake-integer': (or fake-counter) a data type created to - avoid problems with the limited number of available count registers - in (standard) \TeX; -\item[seq] `sequence': a data-type used to implement lists - (with access at both ends) and stacks; -\item[plist] property list -\end{description} -When the \m{type} and \m{module} are identical (as often happens in -the more basic modules) the \m{module} part is often omitted for -aesthetic reasons. - - -\subsection{Functions: argument specifications} -\label{sec:args} - - Function names end with an \m{arg-spec} after a colon. This - gives an indication of the types of argument that a function takes, - and provides a convenient method of naming similar functions that - differ only in their argument forms (see the next section for - examples). - - The \m{arg-spec} consists of a (possibly empty) list of characters, - each denoting one argument of the function. It is important to - understand that `argument' here refers to the effective argument of - the \LaTeX{} function, not to an argument at the \TeX-level. Indeed, - the top level \TeX\ macro that has this name typically has no - arguments. This is an extension of the existing \LaTeX\ convention - where one says that |\section| has an optional argument and a - mandatory argument, whereas the \TeX\ macro |\section| actually has - zero parameters at the \TeX\ level, it merely calls an internal \LaTeX\ - command which in turn calls others that look ahead for star forms and - optional arguments. - -The list of possible argument specifiers includes the following. -\begin{itemize} -\item[\bf n] Unexpanded token or braced token list.\\ - This is a standard \TeX\ undelimited macro argument. -\item[\bf o] One-level-expanded token or braced token list.\\ - This means that the argument is expanded one level, as by - |\expandafter|, and the expansion is passed to the function as a braced - token list. Note that if the original argument is a braced - token list then only the first token in that list is expanded. -\item[\bf x] Fully-expanded token or braced token list.\\ - This means that the argument is expanded as in the replacement text of - an~|\edef|, and the expansion is passed to the function as a - braced token list. -\item[\bf c] Character string used as a command name.\\ The argument (a - token or braced token list) must, when fully expanded, produce a - sequence of characters which is then used to construct a command - name (via~|\csname|, |\endcsname|). This command name is the single - token that is passed to the function as the argument. -\item[\bf N] Single token (unlike~|n|, the argument must \emph{not} be - surrounded by braces).\\ - A typical example of a command taking an~|N| - argument is~|\def|, in which the command being defined must be - unbraced. - \item[\bf O] One-level-expanded single token (unbraced).\\ - As for~|o|, the one-level expansion is passed (as a - braced token list) to the function. - \item[\bf X] Fully-expanded single token (unbraced).\\ - As for~|x|, the full expansion is passed (as a - braced token list) to the function. - \item[\bf C] Character string used as a command name - then one-level expanded.\\ - The form of the argument is exactly as for~|c|, but the - resulting token is then expanded one level (as for~|O|), and - the expansion is passed to the function as a braced token list. - \item[\bf p] Primitive \TeX\ parameter specification.\\ - This can be something simple like~|#1#2#3|, but may use arbitrary - delimited argument syntax such as: |#1,#2\q_stop#3|. - \item[\bf T,F\hspace{-10pt}] - \hspace{10pt}% - These are special cases of~|n| arguments, used for the - true and false code in conditional commands. -\end{itemize} -There are two other specifiers with more general meanings: -\begin{itemize} -\item[\bf D] This means: \textbf{Do not use}. This special case is used - for \TeX\ primitives and other commands that are provided for use - only while bootstrapping the \LaTeX\ kernel. If the \TeX\ primitive - needs to be used in other contexts it will be given an alternative, - more appropriate, name with a useful argument specification. The - argument syntax of these is often weird, in the sense described next. - \item[\bf w] This means that the argument syntax is `weird' in that it - does not follow any standard rule. It is used for functions with - arguments that take non standard forms: examples are \TeX-level - delimited arguments and the boolean tests needed after certain - primitive |\if|\ldots\ commands. -\end{itemize} - - -\section{Expansion control} -\label{sec:exp} - -\subsection{Simpler means better} -\label{sec;simpler} - -Anyone who programs in \TeX\ is frustratingly familiar with the -problem of arranging that arguments to functions are suitably expanded -before the function is called. To illustrate how expansion control -can bring instant relief to this problem we shall consider two -examples copied from \texttt{latex.ltx}. - -\begin{verbatim} - \global - \expandafter - \expandafter - \expandafter - \let - \expandafter - \reserved@a - \csname \curr@fontshape \endcsname -\end{verbatim} -This first piece of code is in essence simply a -global |\let|. However, the token to be defined is obtained by -expanding |\reserved@a| one level; and, worse, the token to which it -is to be let is obtained by fully expanding |\curr@fontshape| and then -using the characters produced by that expansion to construct a command -name. The result is a mess of interwoven |\expandafter| and~|\csname| -beloved of all \TeX\ programmers, and the code is essentially -unreadable. - -Using the conventions and functionality outlined here, the task would -be achieved with code such as this: -\begin{verbatim} - \glet:Oc \g_reserved_a_tlp - \l_current_font_shape_tlp -\end{verbatim} -The command |\glet:Oc| is a global~|\let| that expands its -first argument once, and generates a command name out of its second -argument, before making the definition. This produces code that -is far more readable and more likely to be correct first time. - -Here is the second example. -\begin{verbatim} - \expandafter - \in@ - \csname sym#3% - \expandafter - \endcsname - \expandafter - {% - \group@list}% -\end{verbatim} -This piece of code is part of the definition of another function. It -first produces two things: a token list, by expanding |\group@list| once; -and a token whose name comes from~`|sym#3|'. Then the function~|\in@| -is called and this tests if its first argument occurs in the token list -of its second argument. - -Again we can improve enormously on the code. First we shall rename -the function~|\in@| according to our conventions. A function such as -this but taking two normal `\texttt{n}' arguments might reasonably be -named |\seq_test_in:nn|; thus the variant function we need will be -defined with the appropriate argument types and its name will be -|\seq_test_in:cO|. Now this code fragment will be simply: -\begin{verbatim} - \seq_test_in:cO {sym#3} \l_group_seq -\end{verbatim} -Note that, in addition to the lack of |\expandafter|, the space after -the~|}| will be silently ignored since all white space is ignored in -this programming environment. - - -\subsection{New functions from old} -\label{sec:newfunc} - -For many common functions the \LaTeX3 kernel will provide variants -with a range of argument forms, and similarly it is expected that -extension packages providing new functions will make them available in -the all the commonly needed forms. - -However, there will be occasions where it is necessary to construct a -new such variant form; therefore the expansion module provides a -straightforward mechanism for the creation of functions with any -required argument type, starting from a function that takes `normal' -\TeX\ undelimited arguments. - -To illustrate this let us suppose you have a `base function' -|\demo_cmd:nnn| that takes three normal arguments, and that you need -to construct the variant |\demo_cmd:cnx|, for which the first argument -is used to construct the \emph{name} of a command, whilst the third -argument must be fully expanded before being passed to -|\demo_cmd:nnn|. -To produce the variant form from the base form, simply use this: -\begin{verbatim} - \exp_def_form:nnn {demo_cmd} {nnn} {cnx} -\end{verbatim} -This defines the variant form so that you can then write, for example: -\begin{verbatim} - \demo_cmd:cnx {abc} {pq} {\rst \xyz } -\end{verbatim} -rather than \ldots\ well, something like this! -\begin{verbatim} - \def \tempa {{pq}}% - \edef \tempb {\rst \xyz}% - \expandafter - \demo@cmd - \csname abc% - \expandafter - \expandafter - \expandafter - \endcsname - \expandafter - \tempa - \expandafter - {% - \tempb - }% -\end{verbatim} - -Another example: you may wish to declare a function -|\demo_cmd_b:xcxcx|, a variant of an existing function -|\demo_cmd_b:nnnnn|, that fully -expands arguments 1,~3 and~5, and produces commands to pass as -arguments 2 and~4 using~|\csname|. -The definition you need is simply -\begin{verbatim} - \exp_def_form:nnn - {demo_cmd_b} {nnnnn} {xcxcx} -\end{verbatim} - -This extension mechanism is written so that if the same new form of -some existing command is implemented by two extension packages then the -two definitions will be identical and thus no conflict will occur. - - -\section{Parameter assignments and accessor functions} -\label{sec:access} - -\subsection{Checking assignments} -\label{sec:check} - -One of the advantages of having a consistent scheme is that the system -can provide more extensive error-checking and debugging facilities. -For example, an accessor function that makes a \emph{global} -assignment of a value to a parameter can check that it is not passed -the name of a \emph{local} parameter as that argument: it does this by -checking that the name starts with~|\g_|. - -Such checking is probably too slow for normal use, but the code can -have hooks built in that allow a format to be made in which all -functions perform this kind of check. - -A typical section of the source% -\footnote{This code uses the \textsf{docstrip} -system described in~\cite{A-W:GMS94}, Section~14.3.} -for such code might look like this -(recall that all white space is ignored): - -\begin{verbatim} - %<*!check> - \let_new:NN - \toks_gset:Nn \tex_global:D - % - %<*check> - \def_new:Npn - \toks_gset:Nn #1 - { - \chk_global:N #1 - \tex_global:D #1 - } - % -\end{verbatim} -In the above code the function |\toks_gset:Nn| takes a single -token~(|N|) specifying a token register, and globally sets it to the -value passed in the second argument. - -A typical use of it would be: -\begin{verbatim} - \toks_gset \g_xxx_toks {} -\end{verbatim} -In the normal definition, |\toks_gset| can be simply~|\let| -to~|\global| because the primitive \TeX{} token register does not -require any explicit assignment function: -this is done by the |%<*!check>| code above. - -The alternative definition first checks that the argument -passed as~|#1| is the name of a global parameter and raises an error -if it is not. It does this by taking apart the command name passed -as~|#1| and checking that it starts~|\g_|. - -\subsection{Consistency} -\label{sec:cons} - -The primitive \TeX\ syntax for register assignments has a very minimal -syntax and, apart from box functions, there are no explicit functions -for assigning values to these registers. - -This makes it impossible to implement alternative data-types with a -syntax that is both consistent and at all similar to the syntax for -the primitives; moreover, it encourages a coding style that is very -error prone. - -As in the |\toks_gset:Nn| example given above, all \LaTeX\ data-types -are provided with explicit functions for assignment and for use, even -when these have essentially empty definitions. This allows for better -error-checking as described above; it also allows the construction of -further data-types with a similar interface, even when the -implementation of the associated functions is very complex. - -For example, the `fake-counter' (\texttt{fint}) data-type mentioned -above will appear at the \LaTeX{} programming level to be exactly like -the data-type based on primitive count registers; however, internally -it makes no use of count registers. Typical functions in this module -are illustrated here. - -\begin{verbatim} -\fint_new:N \l_tmpa_fint -\end{verbatim} -This declares the local parameter |\l_example_fint| as a fake-counter. - -\begin{verbatim} -\fint_add:Nn \l_example_fint \c_thirty_two -\end{verbatim} -This increments the value of this fake-counter by 32. - - -\section{The experimental distribution} -\label{sec:dist} - -The initial implementations of a \LaTeX\ programming language using -this kind of syntax remain unreleased (and not completely functional); -they partly pre-date \LaTeXe! The planned distribution will provide a -subset of the functionality of those implementations, in the form of -packages to be used on top of \LaTeXe. - -The intention is to allow experienced \TeX\ programmers to experiment -with the system and to comment on the interface. This means that -\textbf{\itshape the interface will change}. No part of this system, -including the name of anything, should be relied upon as being -available in a later release. Please do \emph{experiment} with these -packages, but do \emph{not} use them for code that you expect to keep -unchanged over a long period. - -In view of the intended experimental use for this distribution we -shall, in the first instance, produce only a few modules for use with -\LaTeXe. These will set up the conventions and the basic functionality -of, for example, the expansion mechanism; they will also implement some -of the basic programming constructs, such as token-lists and sequences. -They are intended only to give a flavour of the code: the full \LaTeX3 -kernel will provide a very rich set of programming constructs so that -packages can efficiently share code, in contrast with the situation in -the current \LaTeX\ where every large package must implement its own -version of queues, stacks, etc., as necessary. - -In the first release of this experimental system at least the -following modules will be distributed. -\begin{description} -\item[l3names] This sets up the basic naming scheme and renames all -the \TeX\ primitives. If it is loaded with the option -\texttt{[removeoldnames]} then the old primitive names such as~|\box| -become \emph{undefined} and are thus available for user -definition. Caution: use of this option will certainly break existing -\TeX\ code! - -\item [l3basics] -This contains the basic definition modules used -by the other packages. - -\item[l3chk] A module that provides functionality comparable to -\LaTeX's |\newcommand| and |\renewcommand|, and also the extra level of -checking described above in section~\ref{sec:check}. - -\item[l3tlp] -This implements a basic data-type, called a \textit{token-list -pointer}, used for storing named token lists: these are essentially -\TeX{} macros with no arguments. - -\item[l3expan] This is the argument expansion module discussed above. - -\item[l3quark] A `quark' is a command that is defined to expand to -itself! Therefore they must never be expanded as this will generate -infinite recursion; they do however have many uses, \eg as -special markers and delimiters within code. - -\item[l3seq] -This implements data-types such as queues and stacks. - -\item[l3prop] -This implements the data-type for `property lists' that are used, in -particular, for storing key/value pairs. - -\item[l3int] -This implements the integer and `fake integer' data-types. - -\item[l3toks] -A data-type corresponding to \TeX's primitive token registers. - -\item[l3io] -A module providing low level input and output functions. - -\item[l3precom] -A `pre-compilation' module that provides functions dealing with pointer -creation and handling, and using external files to record the state of the current -definitions. -\end{description} -This distribution will also contain the \LaTeX\ source for the latest -version of this document, a docstrip install file and three small test -files. - - -In later releases we plan to add further modules and a full-fledged -example of the use of the new language: a proto-type implementation -for the ideas described in the article `Language Information in -Structured Documents: A Model for Mark-up and -Rendering'~\cite{tub:MR98-2}. - -\begin{thebibliography}{1} - -\bibitem{A-W:K-TB} -Donald E Knuth -\newblock {\em The {\TeX}book}. -\newblock Addison-Wesley, Reading, Massachusetts, 1984. - -\bibitem{A-W:GMS94} -Goossens, Mittelbach and Samarin. -\newblock {\em The {\LaTeX} Companion}. -\newblock Addison-Wesley, Reading, Massachusetts, 1994. - -\bibitem{A-W:LLa94} -Leslie Lamport. -\newblock {\em {\LaTeX:} A Document Preparation System}. -\newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994. - -\bibitem{tub:MR98-1} -Frank Mittelbach and Chris Rowley. -\newblock The {\LaTeX3} Project. -\newblock {\em {TUG}boat}, ????? ??? 1998. - -\bibitem{tub:MR98-2} -Frank Mittelbach and Chris Rowley. -\newblock Language Information in -Structured Documents: A Model for Mark-up and Rendering. -\newblock {\em {TUG}boat}, ????? ??? 1998. - -\end{thebibliography} - -\end{document} - - - - - diff --git a/Master/texmf-dist/source/latex/expl3/l3.ins b/Master/texmf-dist/source/latex/expl3/l3.ins index 14ac72c8532..9280d68eac5 100644 --- a/Master/texmf-dist/source/latex/expl3/l3.ins +++ b/Master/texmf-dist/source/latex/expl3/l3.ins @@ -1,107 +1,118 @@ - -\input docstrip.tex -\askforoverwritefalse - -\preamble - - -EXPERIMENTAL CODE - -Do not distribute this file without also distributing the -source files specified above. - -Do not distribute a modified version of this file. - - -\endpreamble -% stop docstrip adding \endinput -\postamble -\endpostamble - -\keepsilent - -% l3names.sty sets up the naming scheme for TeX primitives. -\generate{\file{l3names.sty}{\from{l3names.dtx}{package}}} - - - -% Define some basic commands to get us started with the new -% programming style. -\generate{\file{l3basics.sty}{\from{l3basics.dtx}{package,trace}}} - - -% Define some basic commands that check various conditions -% related to defining commands eg defined/undefined global/local -% Not sure how much of this really makes sense as a package, but... -\generate{\file{l3chk.sty}{\from{l3chk.dtx}{package,trace}}} - - -%% toks register handling (can be compiled with check module) -\generate{\file{l3toks.sty}{\from{l3toks.dtx}{package,trace}}} - - -%% tlp handling -\generate{\file{l3tlp.sty}{\from{l3tlp.dtx}{package,trace}}} - - -%% LaTeX3 expansion module -\generate{\file{l3expan.sty}{\from{l3expan.dtx}{package,trace}}} - - -%% LaTeX3 quarks. -\generate{\file{l3quark.sty}{\from{l3quark.dtx}{package,trace}}} - - -%% LaTeX3 sequences. -\generate{\file{l3seq.sty}{\from{l3seq.dtx}{package,trace}}} - - -%% LaTeX3 clists. -\generate{\file{l3clist.sty}{\from{l3clist.dtx}{package,trace}}} - - -%% LaTeX3 property lists. -\generate{\file{l3prop.sty}{\from{l3prop.dtx}{package,trace}}} - - -%% LaTeX3 integer registers. (can be compiled with check module) -\generate{\file{l3int.sty}{\from{l3int.dtx}{package,trace}}} - - -%% LaTeX3 fake integer macros. -\generate{\file{l3num.sty}{\from{l3num.dtx}{package,trace}}} - -%% LaTeX3 skip registers. -\generate{\file{l3skip.sty}{\from{l3skip.dtx}{package,trace}}} - - -%% LaTeX3 precompilation -\generate{\file{l3precom.sty}{\from{l3precom.dtx}{package,precompile,trace}}} - -%% LaTeX3 I/O module. -\generate{\file{l3io.sty}{\from{l3io.dtx}{package,trace}}} - -%% LaTeX3 program control structures (loops, booleans, ...) -\generate{\file{l3prg.sty}{\from{l3prg.dtx}{package}}} - -%% LaTeX3 box module -\generate{\file{l3box.sty}{\from{l3box.dtx}{package}}} - -%% LaTeX3 messages -\generate{\file{l3messages.sty}{\from{l3messages.dtx}{package}}} - -%% LaTeX3 tokens -\generate{\file{l3token.sty}{\from{l3token.dtx}{package}}} - -%% LaTeX3 cross references -\generate{\file{l3xref.sty}{\from{l3xref.dtx}{package}}} -\generate{\file{l3xref-test.tex}{\from{l3xref.dtx}{testfile}}} - -%% LaTeX3 calc module -\generate{\file{l3calc.sty}{\from{l3calc.dtx}{package}}} - -%% LaTeX3 keyval module -\generate{\file{l3keyval.sty}{\from{l3keyval.dtx}{package}}} - - -\endbatchfile + +\input docstrip.tex +\askforoverwritefalse + +\preamble + + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble + +\keepsilent + +% wrapper package for the expl3 bundle +\generate{\file{expl3.sty}{\from{expl3.dtx}{package}}} + + +% l3names.sty sets up the naming scheme for TeX primitives. +\generate{\file{l3names.sty}{\from{l3names.dtx}{package}}} + + + +% Define some basic commands to get us started with the new +% programming style. +\generate{\file{l3basics.sty}{\from{l3basics.dtx}{package,trace}}} + + +% Define some basic commands that check various conditions +% related to defining commands eg defined/undefined global/local +% Not sure how much of this really makes sense as a package, but... +\generate{\file{l3chk.sty}{\from{l3chk.dtx}{package,trace}}} + + +%% toks register handling (can be compiled with check module) +\generate{\file{l3toks.sty}{\from{l3toks.dtx}{package,trace}}} + + +%% token lists +\generate{\file{l3tl.sty}{\from{l3tl.dtx}{package,trace}}} + + +%% LaTeX3 expansion module +\generate{\file{l3expan.sty}{\from{l3expan.dtx}{package,trace}}} + + +%% LaTeX3 quarks. +\generate{\file{l3quark.sty}{\from{l3quark.dtx}{package,trace}}} + + +%% LaTeX3 sequences. +\generate{\file{l3seq.sty}{\from{l3seq.dtx}{package,trace}}} + + +%% LaTeX3 clists. +\generate{\file{l3clist.sty}{\from{l3clist.dtx}{package,trace}}} + + +%% LaTeX3 property lists. +\generate{\file{l3prop.sty}{\from{l3prop.dtx}{package,trace}}} + + +%% LaTeX3 integer registers. (can be compiled with check module) +\generate{\file{l3int.sty}{\from{l3int.dtx}{package,trace}}} + + +%% LaTeX3 fake integer macros. +\generate{\file{l3num.sty}{\from{l3num.dtx}{package,trace}}} + +%% LaTeX3 integer expressions. +\generate{\file{l3intexpr.sty}{\from{l3intexpr.dtx}{package,trace}}} + + +%% LaTeX3 skip registers. +\generate{\file{l3skip.sty}{\from{l3skip.dtx}{package,trace}}} + + +%% LaTeX3 precompilation +\generate{\file{l3precom.sty}{\from{l3precom.dtx}{package,precompile,trace}}} + +%% LaTeX3 I/O module. +\generate{\file{l3io.sty}{\from{l3io.dtx}{package,trace}}} + +%% LaTeX3 program control structures (loops, booleans, ...) +\generate{\file{l3prg.sty}{\from{l3prg.dtx}{package}}} + +%% LaTeX3 box module +\generate{\file{l3box.sty}{\from{l3box.dtx}{package}}} + +%% LaTeX3 messages +\generate{\file{l3msg.sty}{\from{l3msg.dtx}{package}}} + +%% LaTeX3 tokens +\generate{\file{l3token.sty}{\from{l3token.dtx}{package}}} + +%% LaTeX3 cross references +\generate{\file{l3xref.sty}{\from{l3xref.dtx}{package}}} +%%\generate{\file{l3xref-test.tex}{\from{l3xref.dtx}{testfile}}} + +%% LaTeX3 calc module +\generate{\file{l3calc.sty}{\from{l3calc.dtx}{package}}} + +%% LaTeX3 keyval module +\generate{\file{l3keyval.sty}{\from{l3keyval.dtx}{package}}} + +%% LaTeX3 file loading +\generate{\file{l3file.sty}{\from{l3file.dtx}{package}}} + + +\endbatchfile diff --git a/Master/texmf-dist/source/latex/expl3/l32eproc.tex b/Master/texmf-dist/source/latex/expl3/l32eproc.tex deleted file mode 100644 index d560c0c2338..00000000000 --- a/Master/texmf-dist/source/latex/expl3/l32eproc.tex +++ /dev/null @@ -1,523 +0,0 @@ -\documentclass - {ltugproc} -% {ltxguide} - -\usepackage{shortvrb} -\MakeShortVerb{\|} -\setlength\hfuzz{10pt} - -% A couple of \provide.. so document runs with -% both ltugproc and ltxguide classes -% -\providecommand\m[1]{$\langle$\textit{#1}$\rangle$} -\providecommand\netaddress{\date} -\providecommand\acro[1]{\textsc{\MakeLowercase{#1}}} - -\begin{document} -\title{The \LaTeX3 Programming Language\\ -A syntax proposal for \TeX\ macro programming} - - -\author{The \LaTeX3 Project} -\netaddress{latex-l@urz.uni-heidelberg.de} - - - -\begin{abstract} -This paper proposes a new set of programming conventions suitable for -implementing large scale \TeX\ programming projects such as \LaTeX. -(This syntax is not suitable for either document -markup, or as a style specification language.) - -The main features include a systematic naming scheme for all commands, -and a systematic mechanism for controlling the expansion of arguments -to functions. - -The syntax is under consideration as a basis for programming within -the \LaTeX3 project. - -This paper is based on a talk given by David -Carlisle but describes the work of several people, principally: - Frank Mittelbach, - Denys Duchier, - Rainer Sch\"opf, - Chris Rowley, - Michael Downes, - Johannes Braams, - David Carlisle and - Alan Jeffrey. -\end{abstract} - -\maketitle - - -\section{Introduction} -This paper describes a \TeX\ based language which is intended to -provide a more consistent and rational programming environment for the -construction of large scale \TeX\ macro projects such as \LaTeX. - -Variants of this language have been in use within the \LaTeX3 project -since around 1990 but the syntax specification to be outlined here -should \emph{not} be considered final. This is an experimental -language, and the syntax and command names may (and probably will) -change as more experience is gained with using the language in -practice. - -\section{Programming Interface levels for \LaTeX} - -One may identify several distinct languages that one might want to see -in a \TeX\ based system. This paper will \emph{only} be concerned with -the last of these three. - -\begin{description} -\item[Document Markup] This language consists of the commands that are - to be embedded in the document instance. It is generally accepted - that such a language should be essentially \emph{declarative}. - One might consider a traditional \TeX\ based markup such as the - \LaTeX2 markup as described in \cite{A-W:LLa94}, or alternatively one - might consider an \acro{SGML} based markup. - - One problem with more traditional \TeX\ coding conventions is that - the command names and syntax of the \TeX\ primitives are designed to - have a `natural' syntax when used directly by the author as document - markup. In fact one almost never uses the primitives in this - way, rather they are just used to define higher level commands. - -\item[Designer's Interface] In order to easily translate a (human) - designer's design specification into a program that accepts the - document instance one would ideally like to have a declarative - language that allows the relationships and spacing rules of the - various document elements to be easily expressed. As this language - is not embedded within the document text, it may take a rather - different form to the markup language described above. For - \acro{SGML} based systems one may consider the \acro{DSSSL} language - as playing this role. For \LaTeX2, then this level was essentially - missing in \LaTeX2.09. \LaTeXe\ made some improvements in this area - but it is still the case that implementing a design specification in - \LaTeX\ requires more `low level' coding than would be desired. -\item[Programmer's Interface] - This language, the subject of this paper, is the implementation - language in which the basic typesetting functionality is - implemented, building upon the primitives supplied by \TeX\ (or a - successor program). It may also be used to implement the previous - two languages `within' \TeX, as in the current \LaTeX\ system. -\end{description} - - -\section{Programming language: Main Features} - -The language outlined in this paper aims to provide a suitable -base for coding large (and small) scale projects in \TeX. -Its main distinguishing features are the following. -\begin{itemize} -\item Consistent naming scheme for all functions, including \TeX\ - primitives. -\item Standard mechanisms for controlling argument expansion. -\item Provision of sufficiently rich set of core functions for - handling programming constructs such as: - sequences, sets, stacks, property lists, etc. -\item White space ignored. -\end{itemize} - -\section{Naming Scheme} - -The name space is divided between \emph{Functions} and -\emph{Parameters}. Functions (normally) take arguments and are -executed, Parameters are usually passed as arguments to functions. -They are not directly executed, but accessed though accessor functions. - -Functions and parameters associated with a similar function (for -example accessing counters, or manipulating lists, etc.) are arranged -into \emph{modules}. Before giving the details of the form of the -command names, we give a few examples. - -|\l_tmpa_box| is a local parameter (hence the |l_| prefix) -corresponding to a box register. - -|\g_tmpa_box| is a global parameter (hence the |g_| prefix) -corresponding to a box register. - -|\c_one| is the constant (|c_|) parameter with value one. - -|\cnt_add:Nn| is the function which adds the value specified by -its second argument to the count register specified by its first -argument. The different natures of the two arguments are indicated by -the |:Nn| suffix. The first argument must be a single token specifying -the name of the count parameter. Such single token arguments are -denoted |N|. The second argument is a normal \TeX\ `non-delimited -argument' which may either be a single token, or a brace delimited -token list containing an expression for the value to be added. -The |n| denotes such `normal' argument forms. - -|\cnt_add:cn| is similar to the above, but in this case the the -counter is specified in the first argument by a list of tokens that -expands to the \emph{name} of the count parameter. - -These examples should give the basic flavour of the scheme. Parameters -are classified into local, global or constant (there are further more -technical cases in addition to these three) and this access type is -shown by |\l_|, |\g_| or |\c_|. Functions are arranged by -\emph{module} (The |cnt| module in these cases) with a descriptive -name followed by an indication of the type of argument to be passed. - -In more detail the specification of the names is as follows. - -Functions have the following general syntax: - \begin{quote} - |\|\m{module}|_|\m{description}|:|\m{arg-spec} - \end{quote} - The programmer can chose an arbitrary \m{module} name (consisting - of letters only) a group of functions with related functionality are - then all given names prefixed by this module name. The \m{description} - is a description of the functionality of the function, and should - consist of letters, and possibly |_| characters. \m{arg-spec} - describes the type of arguments as will be described below. - -The syntax of parameters is as follows: - \begin{quote} - |\|\m{access}|_|\m{module}|_|\m{description}|_|\m{type} - \end{quote} - \m{access} describes how the parameter can be accessed. The - principal access types are \emph{constant}, \emph{local} or - \emph{global}. As described below, some special access types relate - to \TeX\ primitive parameters. The meanings of \m{module} and - \m{description} in the parameter syntax is the same as that for - functions. Finally \m{type} should denote the type of parameter, - such as |cnt| for count registers, etc. - - - -Typical \m{module} names in the kernel include |cnt| for integer count -related functions, |seq| for functions relating to sequences, |box|, -etc. Normally additional packages adding new functionality would add -new modules as needed. - -The \m{description} is an arbitrary name for the function or -parameter, consisting of letters, or the |_| character. - -Function names always end with an \m{arg-spec} after a final colon. -This gives an indication of the types of argument that a function -takes, and provides a convenient method of naming similar functions -that just differ by their argument forms, as will be explained below. - -The \m{arg-spec} consists of a (possibly empty) list of characters -each denoting one argument that the function takes. It is important to -note that `argument' here refers to the conceptual argument of the -function. -The top level \TeX\ macro that has this name typically has no -arguments. This is similar to the existing \LaTeX\ convention where one -says that |\section| has an optional argument and a mandatory -argument, whereas the \TeX\ macro |\section| actually takes no -parameters at the \TeX\ level, it merely calls some standard \LaTeX\ -internal functions which look ahead for star forms and optional -arguments. The list of possible argument specifiers includes: -\begin{description} -\item[n] Unexpanded token (or token-list if in braces). In other words - this is a standard \TeX\ undelimited macro argument. -\item[o] One time expanded token or token-list. In the case of a token - list then only the first token in the list is expanded. -\item[x] Fully expanded token or token-list. Typically this means that - the argument is expanded in the style of |\edef| (|\def:Npx|) before - being passed to the function. -\item[c] A character string used (after expansion) as a command name. - The argument (a token or braced token list) should expand to a - sequence of characters which is then used to construct a command - name (via |\csname|, |\cs:w|). This command token is passed as the - argument to the function. - \item[N] A single token. (Unlike |n|, this argument must not be - surrounded by braces). A typical example of a command taking an N - argument is |\def|, in which the command being defined must be - unbraced. - \item[O] Single unbraced token that is expanded once and passed (as a - braced token list) to the function. - \item[X] Single unbraced token that is fully expanded and passed (as a - braced token list) to the function. - \item[C] A character string used as for |c| arguments but the - resulting command token is then expanded (as for |O|) and the - result passed as a braced token list to the function. - \item[p] A primitive \TeX\ parameter specification. This can be - something simple like |#1#2#3| but may be arbitrary delimited - argument syntax, such as |#1,#2\q_stop#3|. - \item[T, F] These are special cases of |n| arguments, used as the - true and false cases in conditional tests. - \item[D] `Do not use'. This special case is used for \TeX\ primitives - that are only used while bootstrapping the \LaTeX\ kernel. If the - \TeX\ primitive needs to be used in other contexts it will be given - an alternative name with a more appropriate argument specification. - \item[w] `weird' syntax. Used for arguments that take non standard - forms, usually delimited arguments that are needed internally to - implement certain modules, and also the boolean tests of many of the - primitive |\if|\ldots\ tests. -\end{description} - - -For parameters, the \m{type} should be from the list of available -data types (which include the primitive \TeX\ registers, but also -data types built within the system). - -Possible values for \m{type} include: -\begin{description} -\item[cnt] Integer valued counter. -\item[toks] Token register. -\item[box] Box register. -\item[fcnt] `Fake' count register. A data type supplied by the kernel - to avoid problems with the limited number of available count - registers in (standard) \TeX. -\end{description} - -The \m{access} codes that are used in parameter names include -\begin{description} -\item[c] Constants. -\item[l] Parameters that should only be set locally. -\item[g] Parameters that should only be set globally. -\end{description} - -\section{Checking Parameter assignments} -One of the advantages of having a consistent scheme is that the system -can provide more extensive error checking and debugging facilities. -For example a function that makes a global assignment can check that -it is not passed a local parameter as argument by checking that the -name of the command to be assigned starts with |\g_|. Such checking is -probably too slow for production runs, but the kernel has hooks built -in to allow a format to be made in which all functions perform this -kind of check. A typical section of code might look like -\begin{verbatim} -%<*check> -\def_new:Npn \toks_gset:Nn #1 { - \chk_global:N #1 - \pref_global:D #1 -} -% -%<*!check> -\let_new:NN - \toks_gset:Nn \pref_global:D -% -\end{verbatim} -The function |\toks_gset:Nn| takes a single token (|N|) specifying a -token register, and globally sets it to the value passed in the second -argument. So typical use would be -\begin{verbatim} -\toks_gset \g_xxx_toks {some value} -\end{verbatim} -In the normal definition, |\toks_gset| can be defined just to be |\let| -to |\global|, as the primitive token register does not require any -explicit assignment function. This is the |%<*!check>| code above. -However the alternative definition first checks that the argument -passed as |#1| is a global parameter and raises an error if it is not. -It does this by taking apart the command name passed as |#1| and -checking that it starts |\g_|. - -\section{Consistent use of accessor functions} -The primitive \TeX\ syntax for register assignments has a very minimal -syntax, and apart from box functions there are no explicit functions -for assignment or use of the registers. This makes it very difficult -to implement alternative data types with a syntax that is at all -similar to the syntax for the primitives, and also encourages a coding -style that is very error prone. - -As noted in the example given above, The \LaTeX\ data types are -provided with explicit functions for setting and using the parameters -even when these have essentially empty definitions. This allows for -better error checking as described above, and also allows the -construction of alternative data types with a similar interface. -For example the `fake counter' data type mentioned previously works at -the user level just like the data type based on primitive count -registers, internally it does not use count registers though. -Typical functions in the |fcnt| module include: - - -\verb|\fcnt_new:N \l_tempa_fcnt|\\ -Declare the local parameter |\l_tempa_fcnt| as a fake counter. - -\verb|\fcnt_add:Nn \l_tempa_fcnt \c_thirty_two|\\ -Increment the counter by 32. - -\section{Expansion Control} -Anyone who programs in \TeX\ is used to the problem of arranging that -arguments to functions are suitably expanded before the function is -called. A couple of real examples copied from \texttt{latex.ltx}: -\begin{verbatim} -\global - \expandafter\expandafter\expandafter - \let - \expandafter - \reserved@a - \csname\curr@fontshape\endcsname - -\expandafter - \in@ - \csname sym#3\expandafter\endcsname - \expandafter{\group@list}% -\end{verbatim} -The first piece of code is a global |\let|. The token to be defined -is obtained by expanding \verb|\reserved@a| one level. The command -that it is to be let too is obtained by fully expanding -\verb|\curr@fontshape| and then using the tokens produced by that -expansion to construct a command name. This results in the mess -of interwoven \verb|\expandafter| and \verb|\csname| beloved of all -\TeX\ programmers, and code that is essentially unreadable. - -A similar construction using the conventions outlined here would be -\begin{verbatim} -\glet:Oc - \reserved_a: \l_current_font_shape_tlp -\end{verbatim} -The command \verb|\glet:Oc| is a global |\let| that expands its -argument once, and generates a command name out of its second -argument, before making the definition. This produces coe that -is far more readable. - -Similarly the second piece of code above produces a token list by -expanding \verb|\group@list| once, and then creates a command name out -of `\verb|sym#3|' (this is inside the definition of another fumction). -The function |\in@| is called which tests if its first argument occurs -in the token list of its second argument. - -Again it would be much clearer, if the above function \verb|\in@| was -called (say) \verb|\test_if_in:nn| (a function taking two normal -`\texttt{n}' arguments) and then a variant function was defined with -the appropriate argument types and simply called as follows: -\begin{verbatim} -\test_if_in:co {sym#3} \group_list: -\end{verbatim} -Note that apart from the lack of \verb|\expandafter| the space after -\verb|}| will be silently ignored. - - -For many common functions the kernel will provide functions with a -range of argument forms, and similarly it is expected that extension -packages providing new functions will make then available in the more -common forms. However There will be occasions where it is necessary -to construct such a variant form. - -A consistent mechanism is provided by the kernel to produce functions -with any argument type, starting from a function that takes `normal' -\TeX\ delimited arguments. Suppose you have a function \verb|\cmd:nnn| -that takes two arguments, and you need to construct \verb|\cmd:cnx| -a variant form in which the first argument is passed as a \emph{name} -of a command, and the third argument must be fully expanded before -being passed to \verb|\cmd:nnn|. - -One simply defines \verb|\cmd:cx| as follows: -\begin{verbatim} -\def:Nn \cmd:cnx {\exp_args:Ncnx \cmd:nnn} -\end{verbatim} -The function \verb|\exp_args:Ncnx| takes as its first (\texttt{N}) -argument the `base' function, and then grabs the next three arguments -from the token stream, acts on the first with \verb|\csname|, and the -last with \verb|\edef| and then constructs a call to the base function -with suitably transformed arguments. So -\begin{verbatim} -\cmd:cnx {abc}{pq}{\rst\xyz} -\end{verbatim} -is equivalent, but emminently more readable, to -\begin{verbatim} -\edef\temp{\rst\xyz} -\expandafter\cmd:nnn - \csname abc\expandafter\endcsname - \expandafter{% - \expandafter p\expandafter q% - \expandafter}% - \expandafter{\temp} -\end{verbatim} - -A large range of argument processing functions are provided in -addition to \verb|\exp_args:Ncnx|. If you need a particular argument -combination for which a function is not provided, one may be -constructed in a simple way. For example you need to construct -\verb|\exp_args:Nxcxcxc| a function that fully expands arguments -1,~3 and~5 of a given function, and produces commands to pass as -arguments 2,~4 and~6 using \verb|\csname|. The definition is simply -\begin{verbatim} -\def:Npn \exp_args:Nxcxcxc - {\::x\::c\::x\::c\::x\::c\:::} -\end{verbatim} -Similar functions, |::o| etc exist for all the other argument types, -and they may be strung together in any order, terminated by -\verb|\:::| to create a function which processes arguments in the -desired way. - -As hopefully demonstrated, the use of variant forms greatly improves -the readability of the code, and experience shows that the longer -command names which result from the new syntax do not realy make the -process of \emph{writing} the code any harder. - -\section{The Current Experimental Distribution} -The initial implementations of a \TeX\ format using this kind of -syntax were made with an unreleased (and non functional) format -(which pre-dates \LaTeXe!) The current distribution consists of a -subset of the functionality of that format, converted to run as -packages on top of \LaTeXe. - -The intention is to allow experienced \TeX\ programmers to experiment -on the system and to comment on the interface. This means that -\textbf{\itshape the interface will change}. No part of this system, -including the names of any commands should be relied upon as being -available in a later release. Please do \emph{experiment} with these -packages, but do not use them for documents that you expect to keep -unchanged over a long period. - -In view of the proposed experimental use for this distribution, we -currently have only converted a few modules for use with \LaTeXe. -These set up the basic conventions, and then implement a few basic -programming constructs such as lists and sequences. These are really -to give a flavour of the code, and to indicate that the intention is -that the kernel provide a sufficiently rich set of programming -constructs so that packages may use them and thus more efficiently -share code, unlike the situation in the current \LaTeX\ where every -large package implements its own version of lists, stacks etc. - -The current packages are: -\begin{description} -\item[l3names] -Sets up the basic naming scheme, including naming the \TeX\ -primitives. If used with the option \texttt{[removeoldnames]} -then the old primitive names such as \verb|\box| are \emph{undefined} -and thus made available for user definitions. Use of this option might -possibly break existing \TeX\ code! - -\item [l3basics] -Some basic definitions that are used by the other packages. - -\item[l3chk] -Functions to check (and make) definitions (comparable to the existing -\verb|\newcommand| or \verb|\renewcommand|). - -\item[l3tlp] -Token List Pointers. A basic \LaTeX3 data type for storing token lists. -(These are essentially macros with no arguments.) - - -\item[l3expan] -The argument expansion module discussed in the previous section. - - -\item[l3quarq] - -A `quark' is a command that is defined to expand to itself. So it may -not be directly used (it would generate an infinite loop) but has many -uses as special markers within \LaTeX\ code. - - -\item[l3seq] -A module implementing the basic list and stack data types. - -\item[l3prop] -Property lists are the data type for handling key/value assignments. -\end{description} - -The distribution also contains the \TeX\ source for this document, a -docstrip install file and two small test files. - -\begin{thebibliography}{1} - -\bibitem{A-W:LLa94} -Leslie Lamport. -\newblock {\em {\LaTeX:} A Document Preparation System}. -\newblock Addison-Wesley, Reading, Massachusetts, second edition, 1994. - -\end{thebibliography} - -\end{document} - - diff --git a/Master/texmf-dist/source/latex/expl3/l3alloc.dtx b/Master/texmf-dist/source/latex/expl3/l3alloc.dtx index 76f141a25b0..a2031c45493 100644 --- a/Master/texmf-dist/source/latex/expl3/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3alloc.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3alloc.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3alloc.dtx Copyright (C) 1990-2006,2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3alloc.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3alloc.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental register allocation}% %\iffalse %<*driver> @@ -44,7 +44,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -60,6 +60,8 @@ % \date{\filedate} % \maketitle % +% \begin{documentation} +% % \section{Allocating registers and the like} % % This module provides the basic mechanism for allocating \TeX's @@ -77,9 +79,9 @@ % \item The other registers (|\tex_count:D|, |\tex_dimen:D|, % |\tex_skip:D|, |\tex_muskip:D|, |\tex_box:D|, and |\tex_toks:D| % range from 0 to 32768, but registers numbered above 255 are -% accessed somewhat less efficient. +% accessed somewhat less efficiently. % \item Registers could be allocated both globally and locally; the -% use of regsiters could also be globaly or locally. Here we +% use of registers could also be globaly or locally. Here we % provide support for globally allocated registers for both % gloabl and local use and for locally allocated registers for % local use only. @@ -88,60 +90,67 @@ % register was allocated last and which registers can not be % allocated by the standard mechanisms. % -% \subsection{Functions} +% \section{Functions} % % \begin{function}{\alloc_setup_type:nnn} % \begin{syntax} -% "\alloc_setup_type:nnn" +% "\alloc_setup_type:nnn" \Arg{type} \Arg{g_start_num} \Arg{l_start_num} % \end{syntax} % Sets up the storage needed for the administration of registers of % type .\\ % should be a token list in braces, it can be one of % "int", "dimen", "skip", "muskip", "box", "toks", "ior", "iow", % "pattern", or "ins".\\ -% is the number of the first not allocated global +% is the number of the first non-allocated global % register, it will be incremented by 1 when the allocation is done. -% is the number of the first not allocated local +% is the number of the first non-allocated local % register, it will be decremented by 1 when the allocation is done. % \end{function} % % \begin{function}{\alloc_reg:NnNN} % \begin{syntax} -% "\alloc_reg:NnNN" +% "\alloc_reg:NnNN" "g"$\big/$"l" % \end{syntax} -% Performs the allocation of a register of type to copntrol +% Performs the allocation of a register of type to control % sequence , using the command . The "g" or "l" -% indicaties whether the allocation should be global or local. +% indicates whether the allocation should be global or local. % This macro is the basic building block for the definition of the % "\""_new:N" commands % \end{function} % -% \StopEventually{} +% \end{documentation} % -% \subsection{The Implementation} +% \begin{implementation} % -% We start by ensuring that the required packages are loaded when -% this file is loaded as a package on top of \LaTeXe. +% \section{\pkg{l3alloc} implementation} % -% \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3expan} -%\RequirePackage{l3num} -%\RequirePackage{l3seq}\par -% \end{macrocode} +% \subsection{Internal functions} % +% \begin{function}{ \alloc_next_g:n | +% \alloc_next_l:n } +% \begin{syntax} +% "\alloc_next_g:n" \Arg{type} +% \end{syntax} +% These functions find the next free register for the specified type. +% \end{function} +% +% \subsection{Module code} % % \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % % \begin{macro}{\alloc_setup_type:nnn} % For each type of register we need to `counters' that hold the % last allocated global or local register. We also need a sequence -% to store the `excpetions'. +% to store the `exceptions'. % \begin{macrocode} -\def_new:Npn \alloc_setup_type:nnn #1 #2 #3{ +\cs_new_nopar:Npn \alloc_setup_type:nnn #1 #2 #3{ \num_new:c {g_ #1 _allocation_num} \num_new:c {l_ #1 _allocation_num} \seq_new:c {g_ #1 _allocation_seq} @@ -156,27 +165,28 @@ % These routines find the next free register. For globally allocated % registers we first increment the counter that keeps track of them. % \begin{macrocode} -\def_new:Npn \alloc_next_g:n #1 { +\cs_new_nopar:Npn \alloc_next_g:n #1 { \num_gincr:c {g_ #1 _allocation_num} % \end{macrocode} % Then we need to check whether we have run out of registers. % \begin{macrocode} - \num_compare:cNcTF {g_ #1 _allocation_num} = {l_ #1 _allocation_num} - {\io_put_term:x{We~ ran~ out~ of~ registers~ of~ type~ g_#1!}} - { + \intexpr_compare:nTF { + \num_use:c{g_ #1 _allocation_num} = \num_use:c{l_ #1 _allocation_num} + } + {\iow_term:x{We~ ran~ out~ of~ registers~ of~ type~ g_#1!}} + { % \end{macrocode} -% We also need to check wether the value of the counter already +% We also need to check whether the value of the counter already % occurs in the list of already allocated registers. % \begin{macrocode} - \seq_if_in:cxTF {g_ #1 _allocation_seq} - {\num_use:c{g_ #1 _allocation_num}} - {\io_put_term:x{\num_use:c{g_ #1 _allocation_num}~Already~ allocated!} + \seq_if_in:cxT {g_ #1 _allocation_seq} + {\num_use:c{g_ #1 _allocation_num}} % \end{macrocode} % If it does, we find the next value. % \begin{macrocode} + { \iow_term:x{\num_use:c{g_ #1 _allocation_num}~already~allocated!} \alloc_next_g:n {#1} } - {\use_noop:} - } + } % \end{macrocode} % By now the |.._allocation_num| counter will contain the number of % the register we will assign a control seuence for. @@ -185,42 +195,47 @@ % \end{macrocode} % For the locally allocated registers we have a similar function. % \begin{macrocode} -\def_new:Npn \alloc_next_l:n #1 { +\cs_new_nopar:Npn \alloc_next_l:n #1 { \num_gdecr:c {l_ #1 _allocation_num} - \num_compare:cNcTF {g_ #1 _allocation_num} = {l_ #1 _allocation_num} - {\io_put_term:x{We~ ran~ out~ of~ registers~ of~ type~ l_#1!}} +% \end{macrocode} +% (Will: should that be "\num_decr" (no "g") ?!) +% \begin{macrocode} + \intexpr_compare:nTF { + \num_use:c{g_ #1 _allocation_num} = \num_use:c{l_ #1 _allocation_num} + } + {\iow_term:x{We~ ran~ out~ of~ registers~ of~ type~ l_#1!}} { \seq_if_in:cxTF {g_ #1 _allocation_seq} {\num_use:c{l_ #1 _allocation_num}} - {\io_put_term:x{\num_use:c{l_ #1 _allocation_num}~Already~ allocated!} + { \iow_term:x{\num_use:c{l_ #1 _allocation_num}~already~allocated!} \alloc_next_l:n {#1} } - {\io_put_term:x{\num_use:c{l_ #1 _allocation_num}~Free!}} - } + { \iow_term:x{\num_use:c{l_ #1 _allocation_num}~free!} } + } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\alloc_reg:NnNN} -% This internal macro performs the actual allocation. It's first +% This internal macro performs the actual allocation. Its first % argument is either 'g' for a globally allocated register or `l' % for a locally allocated register. The second argument is the % type of register to allocate, the third argument is the command % to use and the fourth argument is the control sequence that is to % be defined to point to the register. % \begin{macrocode} -\def_new:Npn \alloc_reg:NnNN #1 #2 #3 #4{ +\cs_new_nopar:Npn \alloc_reg:NnNN #1 #2 #3 #4{ % \end{macrocode} % It first checks that the control sequence that is to denote the % register does not already exist. % \begin{macrocode} - \chk_new_cs:N #4 + \chk_if_free_cs:N #4 % \end{macrocode} % Next, it decides whether a prefix is needed for the allocation % command; % \begin{macrocode} - \if:w#1g - \exp_after:NN \pref_global:D + \if:w #1 g + \exp_after:wN \pref_global:D \fi: % \end{macrocode} % And finally the actual allocation takes place. @@ -230,45 +245,28 @@ % \end{macrocode} % All that's left to do is write a message in the log file. % \begin{macrocode} - \io_put_log:x{ - \token_to_string:N#4=#2~register~\num_use:c{#1_ #2 _allocation_num}} + \iow_log:x{ + \token_to_str:N#4=#2~register~\num_use:c{#1_ #2 _allocation_num}} % \end{macrocode} -% Finally, it calls |\alloc_next_| to find the next free register +% Finally, it calls |\alloc_next_|\meta{\texttt{\textup g}/\texttt{\textup l}} to find the next free register % number. % \begin{macrocode} - \cs_use:c{alloc_next_#1:n} {#2} + \use:c{alloc_next_#1:n} {#2} } % \end{macrocode} % \end{macro} % +% \begin{macrocode} +% +% \end{macrocode} % % \begin{macrocode} %<*showmemory> \showMemUsage % -% % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.6 2006/03/20 18:26:32 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.5 2006/01/15 14:02:58 braams -% Added a \SopEventually{} command -% -% Revision 1.4 2005/12/27 16:02:18 morten -% Changed RCS information retrieval -% -% Revision 1.3 2005/04/06 22:32:38 braams -% Removed the functins that belong in other modules; -% Fixed the naming conventions -% -% Revision 1.2 2005/04/05 22:12:44 braams -% First, working, version of the regsiter allocation support -% -% Revision 1.1 2005/03/16 22:50:02 braams -% Initial register allocation module +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3basics.dtx b/Master/texmf-dist/source/latex/expl3/l3basics.dtx index e34e42f2732..ecbafc5d6b9 100644 --- a/Master/texmf-dist/source/latex/expl3/l3basics.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3basics.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3basics.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3basics.dtx Copyright (C) 1990-2008 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -35,7 +35,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3basics.dtx 702 2007-11-27 14:21:49Z morten $ +\GetIdInfo$Id: l3basics.dtx 1365 2009-05-31 17:26:17Z mittelba $ {L3 Experimental basic definitions} %\iffalse %<*driver> @@ -43,9 +43,9 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3basics.dtx} \end{document} % % \fi @@ -59,41 +59,116 @@ % \date{\filedate} % \maketitle % +% \begin{documentation} % % As the name suggest this package holds some basic definitions which % are needed by most or all other packages in this set. % -% \section{Basics} -% -% Here we describe those functions that used all over the place. With +% Here we describe those functions that are used all over the place. With % that we mean functions dealing with the construction and testing of % control sequences. Furthermore the basic parts of conditional % processing are covered; conditional processing dealing with specific % data types is described in the modules specific for the respective % data types. % -% \subsection{Predicates and conditionals} +% \section{Predicates and conditionals} +% \label{sec:predicates} +% +% \LaTeX3 has three concepts for conditional flow processing: +% \begin{description} +% +% \item[Branching conditionals] +% Functions that carry out a test and then execute, depending on its +% result, either the code supplied in the \m{true arg} or the \m{false +% arg}. +% These arguments are denoted with "T" and "F" repectively. An +% example would be +% \begin{quote} +% "\cs_if_free:cTF{abc}" \Arg{true code} \Arg{false code} +% \end{quote} +% a function that will turn the first argument into a control sequence +% (since it's marked as "c") then checks whether this control sequence +% is still free and then depending on the result carry out the code in +% the second argument (true case) or in the third argument (false +% case). +% +% These type of functions are known as `conditionals'; whenever a "TF" +% function is defined it will usually be accompanied by "T" and "F" +% functions as well. These are provided for convenience when the +% branch only needs to go a single way. Package writers are free to +% choose which types to define but the kernel definitions will always +% provide all three versions. +% +% Important to note is that these branching conditionals with \m{true +% code} and/or \m{false code} are always defined in a way that the +% code of the chosen alternative can operate on following tokens in +% the input stream. +% +% These conditional functions may or may not be fully expandable, but if they +% are expandable they will be accompanied by a `predicate' for the same test +% as described below. +% +% \item[Predicates] +% `Predicates' are functions that return a special type of boolean +% value which can be tested by the function "\if_predicate:w" +% or in the boolean expression parser. All functions of this type +% are expandable and have names that end with "_p" in the +% description part. For example, +% \begin{quote} +% "\cs_if_free_p:N" +% \end{quote} +% would be a predicate function for the same type of test as the +% conditional described above. It would return `true' if its argument (a +% single token denoted by "N") is still free for definition. It would be used +% in constructions like +% \begin{quote} +% "\if_predicate:w \cs_if_free_p:N \l_tmpz_tl" \m{true code} "\else:" +% \m{false code} "\fi:" +% \end{quote} +% or in expressions utilizing the boolean logic parser: +% \begin{quote} +% "\bool_if:nTF {" \\ +% " \cs_if_free_p:N \l_tmpz_tl || \cs_if_free_p:N \g_tmpz_tl " \\ +% "}" +% \Arg{true code} \Arg{false code} +% \end{quote} % -% \subsubsection{Primitive conditionals} +% Like their branching cousins, predicate functions ensure that all +% underlying primitive "\else:" or "\fi:" have been removed before +% returning the boolean true or false values.\footnote{If defined +% using the interface provided.} +% +% For each predicate defined, a `predicate conditional' will also exist that +% behaves like a conditional described above. +% +% \item[Primitive conditionals] +% There is a third variety of conditional, which is the original concept used in +% plain \TeX{} and \LaTeX. Their use is discouraged in \pkg{expl3} (although +% still used in low-level definitions) because they are more fragile and +% in many cases require more expansion control (hence more code) than the two +% types of conditionals described above. +% \end{description} +% +% +% \subsection{Primitive conditionals} % % The \eTeX\ engine itself provides many different conditionals. Some % expand whatever comes after them and others don't. Hence the names % for these underlying functions will often contain a |:w| part but % higher level functions are often available. See for instance -% |\int_compare_p:nNn| which is a wrapper for |\if_num:w|. +% |\intexpr_compare_p:nNn| which is a wrapper for |\if_num:w|. % % Certain conditionals deal with specific data types like boxes and % fonts and are described there. The ones described below are either % the universal conditionals or deal with control sequences. We will % prefix primitive conditionals with |\if_|. % -% \begin{function}{% -% \if_true: | -% \if_false: | -% \else: | -% \fi: | -% \reverse_if:N | -% } +% \begin{function}{ \if_true: / (EXP) | +% \if_false: / (EXP) | +% \or: / (EXP) | +% \else: / (EXP) | +% \fi: / (EXP) | +% \reverse_if:N / (EXP) } % \begin{syntax} % "\if_true:" "\else:" "\fi:" \\ % "\if_false:" "\else:" "\fi:" \\ @@ -101,37 +176,31 @@ % \end{syntax} % "\if_true:" always executes , while "\if_false:" always % executes . "\reverse_if:N" reverses any two-way primitive -% conditional. "\else:" and "\fi:" delimit the branches of the conditional. +% conditional. "\else:" and "\fi:" delimit the branches of the +% conditional. "\or:" is used in case switches, see \pkg{l3intexpr} +% for more. +% \begin{texnote} +% These are equivalent to their corresponding \TeX\ primitive +% conditionals; |\reverse_if:N| is \eTeX's |\unless|. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \if_meaning:NN | -% \if_cs_meaning_eq:NN | -% \if_token_eq:NN | -% } +% \begin{function}{ \if_meaning:w / (EXP) } % \begin{syntax} -% "\if_meaning:NN" "\else:" -% "\fi:" \\ -% "\if_cs_meaning_eq:NN" "\else:" -% "\fi:" \\ -% "\if_token_eq:NN" "\else:" "\fi:" +% "\if_meaning:w" "\else:" "\fi:" % \end{syntax} -% "\if_meaning:NN" executes when the replacement text, -% i.e., the expansion of and are the same, otherwise it -% executes . However this name isn't really that -% good. What the \TeX\ primitive does is compare two tokens to see if -% they are equal. Hence this is actually a "token" functions. A -% similar argument applies to the situation where it is used to -% compare control sequences, where it is the meaning being compared. -% Something to be cleaned up at some point. +% "\if_meaning:w" executes when and are the same, +% otherwise it executes . +% and could be functions, variables, tokens; in all cases the +% \emph{unexpanded} definitions are compared. +% \begin{texnote} +% This is \TeX's |\ifx|. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \if:w | -% \if_charcode:w | -% \if_catcode:w -% } +% \begin{function}{ \if:w / (EXP) | +% \if_charcode:w / (EXP) | +% \if_catcode:w / (EXP) } % \begin{syntax} % "\if:w" "\else:" "\fi:" \\ % "\if_catcode:w" "\else:" "\else:" "\fi:" +% \end{syntax} +% This function takes a predicate function and +% branches according to the result. (In practice this function would also +% accept a single boolean variable in place of the but to make the +% coding clearer this should be done through "\if_bool:N".) +% \end{function} +% +% +% +% \begin{function}{\if_bool:N / (EXP)} +% \begin{syntax} +% "\if_bool:N" "\else:" "\fi:" +% \end{syntax} +% This function takes a boolean variable and +% branches according to the result. +% \end{function} +% +% +% \begin{function}{ \if_cs_exist:N / (EXP) | +% \if_cs_exist:w / (EXP) } % \begin{syntax} % "\if_cs_exist:N" "\else:" "\fi:" \\ % "\if_cs_exist:w" "\cs_end:" "\else:" "\else:" "\fi:" +% "\if_mode_horizontal:" "\else:" "\fi:" % \end{syntax} % Execute if currently in horizontal mode, otherwise % execute . Similar for the other functions. % \end{function} % -% \subsubsection{Non-primitive conditionals} +% \subsection{Non-primitive conditionals} % -% \begin{function}{% -% \cs_if_eq_p:NN -% } +% \begin{function}{ \cs_if_eq_name_p:NN } % \begin{syntax} -% "\cs_if_eq_p:NN" +% "\cs_if_eq_name_p:NN" % \end{syntax} % Returns `true' if and are textually the same, i.e.\ have % the same name, otherwise it returns `false'. % \end{function} % -% \begin{function}{% -% \cs_if_eq:NNTF | -% \cs_if_eq:NNT | -% \cs_if_eq:NNF | -% \cs_if_eq:cNTF | -% \cs_if_eq:cNT | -% \cs_if_eq:cNF | -% \cs_if_eq:NcTF | -% \cs_if_eq:NcT | -% \cs_if_eq:NcF | -% \cs_if_eq:ccTF | -% \cs_if_eq:ccT | -% \cs_if_eq:ccF -% } +% \begin{function}{ \cs_if_eq_p:NN / (EXP) | +% \cs_if_eq_p:cN / (EXP) | +% \cs_if_eq_p:Nc / (EXP) | +% \cs_if_eq_p:cc / (EXP) | +% \cs_if_eq:NN / (TF)(EXP) | +% \cs_if_eq:cN / (TF)(EXP) | +% \cs_if_eq:Nc / (TF)(EXP) | +% \cs_if_eq:cc / (TF)(EXP) } % \begin{syntax} -% "\cs_if_eq:NNTF" "{""}{""}" +% "\cs_if_eq_p:NNTF" +% "\cs_if_eq:NNTF" \Arg{true code} \Arg{false code} % \end{syntax} -% These functions check if and have same meaning and then -% execute either or . +% These functions check if and have same meaning. % \end{function} % % -% \begin{function}{% -% \cs_if_free_p:N -% } +% \begin{function}{ \cs_if_free_p:N / (EXP) | +% \cs_if_free_p:c / (EXP) | +% \cs_if_free:N / (TF)(EXP) | +% \cs_if_free:c / (TF)(EXP) } % \begin{syntax} % "\cs_if_free_p:N" +% "\cs_if_free:NTF" \Arg{true code} \Arg{false code} % \end{syntax} -% Returns `true' if is either undefined or equal to "\scan_stop:". -% However, it returns `false' if is textually "\c_undefined" (the -% constantly undefined function), or textually "\scan_stop:". +% Returns `true' if is either undefined or equal to +% "\tex_relax:D" (the function that is assigned to newly created +% control sequences by \TeX{} when "\cs:w" "..." "\cs_end:" is +% used). In addition to this, `true' is only returned if does not +% have a signature equal to "D", i.e., `do not use' functions are not +% free to be redefined. % \end{function} % -% \begin{function}{% -% \cs_if_free:NTF | -% \cs_if_free:NT | -% \cs_if_free:NF | -% \cs_if_free:cTF | -% \cs_if_free:cT | -% \cs_if_free:cF -% } +% \begin{function}{ \cs_if_exist_p:N / (EXP) | +% \cs_if_exist_p:c / (EXP) | +% \cs_if_exist:N / (TF)(EXP) | +% \cs_if_exist:c / (TF)(EXP) } % \begin{syntax} -% "\cs_if_free:NTF" "{""}{""}" +% "\cs_if_exist_p:N" +% "\cs_if_exist:NTF" \Arg{true code} \Arg{false code} % \end{syntax} -% These functions check if is free and then execute either or . -% \begin{texnote} -% The conditional "\cs_if_free:cTF" is the \LaTeX3 implementation of -% the \LaTeX2 function \tn{@ifundefined}. The other functions -% haven't been around before. -% \end{texnote} +% These functions check if exists, i.e., if is present in +% the hash table and is not the primitive "\tex_relax:D". % \end{function} % -% \begin{function}{% -% \cs_if_really_free:cTF | -% \cs_if_really_free:cF | -% \cs_if_really_free:cT -% } +% \begin{function}{ \cs_if_do_not_use_p:N / (EXP) } % \begin{syntax} -% "\cs_if_really_free:cTF" "{""}" "{""} {""}" +% "\cs_if_do_not_use_p:N" % \end{syntax} -% Similar to "\cs_if_free:cTF" but does not put anything previously -% undefined into the hash table. Useful for special control sequences -% like "\foo/bar" which cannot be entered as one token. +% These functions check if has the arg spec "D" for `\emph{do not use}'. +% There are no "TF"-type conditionals for this function as it is only used +% internally and not expected to be widely used. (For now, anyway.) % \end{function} % -% \begin{function}{% -% \cs_if_exist_p:N -% } +% \begin{function}{ \chk_if_free_cs:N } % \begin{syntax} -% "\cs_if_exist_p:N" +% "\chk_if_free_cs:N" % \end{syntax} -% This function does the opposite of "\cs_if_free_p:N". +% This function checks that is \m{free} according to the criteria +% for "\cs_if_free_p:N" above. If not, an error is generated. % \end{function} % -% \begin{function}{% -% \cs_if_exist:NTF | -% \cs_if_exist:NT | -% \cs_if_exist:NF | -% \cs_if_exist:cTF | -% \cs_if_exist:cT | -% \cs_if_exist:cF -% } +% \begin{function}{ \chk_if_exist_cs:N | +% \chk_if_exist_cs:c } % \begin{syntax} -% "\cs_if_exist:NTF" "{""}{""}" +% "\chk_if_exist_cs:N" % \end{syntax} -% These functions check if exists and then execute either or . Exactly the opposite of "\cs_if_free:NTF". +% This function checks that is defined. If it is not an error +% is generated. % \end{function} % -% \begin{function}{% -% \cs_if_really_exist:cTF | -% \cs_if_really_exist:cF | -% \cs_if_really_exist:cT -% } +% \begin{variable}{ \c_true_bool | \c_false_bool } % \begin{syntax} -% "\cs_if_really_exist:cTF" "{""}" "{""} {""}" % \end{syntax} -% The opposite of "\cs_if_really_free:cTF". -% \end{function} +% Constants that represent `true' or `false', respectively. Used to +% implement predicates. +% \end{variable} % +% \subsection{Applications} % -% \begin{function}{% -% \chk_new_cs:N | -% } +% \begin{function}{ \str_if_eq_p:nn / (EXP) } % \begin{syntax} -% "\chk_new_cs:N" +% "\str_if_eq_p:nn" \Arg{string1} \Arg{string2} % \end{syntax} -% This function checks that is so far either undefined or equals -% "\scan_stop:" (the function that is assigned to newly created -% control sequences by \TeX{} when "\cs:w" "..." "\cs_end:" is -% used). +% Expands to `true' if is the same as , +% otherwise `false'. Ignores spaces within the strings. % \end{function} % -% \begin{function}{% -% \chk_exist_cs:N | -% \chk_exist_cs:c -% } +% \begin{function}{ \str_if_eq_var_p:nf / (EXP) } % \begin{syntax} -% "\chk_exist_cs:N" +% "\str_if_eq_var_p:nf" \Arg{string1} \Arg{string2} % \end{syntax} -% This function checks that is defined. If it is not an error -% is generated. +% A variant of "\str_if_eq_p:nn" which has the advantage of +% obeying spaces in at least the second argument. % \end{function} % % -% \begin{variable}{% -% \c_true | -% \c_false -% } +% \section{Control sequences} +% +% \begin{function}{ \cs:w / (EXP) | \cs_end: / (EXP) } % \begin{syntax} +% "\cs:w" "\cs_end:" % \end{syntax} -% Constants that represent `true' or `false', respectively. Used to -% implement predicates. -% \end{variable} +% This is the \TeX{} internal way of generating a control sequence from +% some token list. get expanded and must ultimately result in a +% sequence of characters. +% \begin{texnote} +% These functions are the primitives \tn{csname} and \tn{endcsname}. +% "\cs:w" is considered weird because it expands tokens until it reaches +% "\cs_end:". +% \end{texnote} +% \end{function} % +% \begin{function}{ \cs_show:N | +% \cs_show:c } +% \begin{syntax} +% "\cs_show:N" +% "\cs_show:c" \Arg{arg} +% \end{syntax} +% This function shows in the console output the \emph{meaning} of the control +% sequence or that created by . +% \begin{texnote} +% This is \TeX's |\show| and associated csname version of it. +% \end{texnote} +% \end{function} % +% \begin{function}{ \cs_meaning:N / (EXP) | +% \cs_meaning:c / (EXP) } +% \begin{syntax} +% "\cs_meaning:N" +% "\cs_meaning:c" \Arg{arg} +% \end{syntax} +% This function expands to the \emph{meaning} of the control sequence or +% that created by . +% \begin{texnote} +% This is \TeX's |\meaning| and associated csname version of it. +% \end{texnote} +% \end{function} % -% \subsection{Selecting and discarding tokens from the input stream} +% \section{Selecting and discarding tokens from the input stream} % -% The conditional processing could not have been implemented without +% The conditional processing cannot be implemented without % being able to gobble and select which tokens to use from the input % stream. +% % -% \begin{function}{% -% \use_none:n | -% \use_none:nn | -% \use_none:nnn | -% \use_none:nnnn | -% \use_none:nnnnn | -% \use_none:nnnnnn | -% \use_none:nnnnnnn | -% \use_none:nnnnnnnn | -% \use_none:nnnnnnnnn | -% } +% \begin{function}{ \use:n / (EXP) | +% \use:nn / (EXP) | +% \use:nnn / (EXP) | +% \use:nnnn / (EXP) } % \begin{syntax} -% "\use_none:n" "{""}"\\ -% "\use_none:nn" "{""}{""}" +% "\use:n" \Arg{arg} % \end{syntax} -% These functions gobble the tokens or brace groups from the input -% stream. +% Functions that returns all of their arguments to the input stream after +% removing the surrounding braces around each argument. +% \begin{texnote} +% "\use:n" is \LaTeXe's "\@firstofone"/"\@iden". +% \end{texnote} % \end{function} % +% \begin{function}{ \use:c / (EXP) } +% \begin{syntax} +% "\use:c" \Arg{cs} +% \end{syntax} +% Function that returns to the input stream the control sequence created from +% its argument. Requires two expansions before a control sequence is returned. +% \begin{texnote} +% "\use:c" is \LaTeXe's "\@nameuse". +% \end{texnote} +% \end{function} % -% \begin{function}{\use_arg_i:n} +% \begin{function}{ \use_none:n / (EXP) | +% \use_none:nn / (EXP) | +% \use_none:nnn / (EXP) | +% \use_none:nnnn / (EXP) | +% \use_none:nnnnn / (EXP) | +% \use_none:nnnnnn / (EXP) | +% \use_none:nnnnnnn / (EXP) | +% \use_none:nnnnnnnn / (EXP) | +% \use_none:nnnnnnnnn / (EXP) } % \begin{syntax} -% "\use_arg_i:n" "{" "}" +% "\use_none:n" \Arg{arg1}\\ +% "\use_none:nn" \Arg{arg1} \Arg{arg2} % \end{syntax} -% Function that executes the next argument after removing the -% surrounding braces. Used to implement conditionals. +% These functions gobble the tokens or brace groups from the input +% stream. +% \begin{texnote} +% "\use_none:n", "\use_none:nn", "\use_none:nnnn" are \LaTeXe's +% "\@gobble", "\@gobbletwo", and "\@gobblefour". +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nn | -% \use_arg_ii:nn | -% } +% \begin{function}{ \use_i:nn / (EXP) | +% \use_ii:nn / (EXP) } % \begin{syntax} -% "\use_arg_i:nn" "{" "}{" "}" +% "\use_i:nn" \Arg{code1} \Arg{code2} % \end{syntax} % Functions that execute the first or second argument respectively, % after removing the surrounding braces. Primarily used to implement % conditionals. +% \begin{texnote} +% These are \LaTeXe's "\@firstoftwo" and "\@secondoftwo", respectively. +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nnn | -% \use_arg_ii:nnn | -% \use_arg_iii:nnn | -% } +% \begin{function}{ \use_i:nnn / (EXP) | +% \use_ii:nnn / (EXP) | +% \use_iii:nnn / (EXP) } % \begin{syntax} -% "\use_arg_i:nnn" "{" "}{" "}{" "}" +% "\use_i:nnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} % \end{syntax} % Functions that pick up one of three arguments and execute them after -% removing the surrounding braces. Should be described somewhere else. +% removing the surrounding braces. +% \begin{texnote} +% \LaTeXe\ has only "\@thirdofthree". +% \end{texnote} % \end{function} % -% \begin{function}{% -% \use_arg_i:nnnn | -% \use_arg_ii:nnnn | -% \use_arg_iii:nnnn | -% \use_arg_iv:nnnn | -% } +% \begin{function}{ \use_i:nnnn / (EXP) | +% \use_ii:nnnn / (EXP) | +% \use_iii:nnnn / (EXP) | +% \use_iv:nnnn / (EXP) } % \begin{syntax} -% "\use_arg_i:nnnn" "{" "}{" "}{" "}{" "}" +% "\use_i:nnnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} \Arg{arg4} % \end{syntax} % Functions that pick up one of four arguments and execute them after % removing the surrounding braces. % \end{function} % -% A different kind of functions for selecting tokens from the token -% stream are those that use delimited arguments. +% \subsection{Extending the interface} % -% \begin{function}{% -% \use_none_delimit_by_q_nil:w | -% \use_none_delimit_by_q_stop:w | -% } +% \begin{function}{ \use_i_ii:nnn / (EXP) } +% \begin{syntax} +% "\use_i_ii:nnn" \Arg{arg1} \Arg{arg2} \Arg{arg3} +% \end{syntax} +% This function used in the expansion module reads three arguments and +% returns (without braces) the first and second argument while +% discarding the third argument. +% +% If you wish to select multiple arguments while discarding others, +% use a syntax like this. Its definition is +% \begin{verbatim} +% \cs_set:Npn \use_i_ii:nnn #1#2#3 {#1#2} +% \end{verbatim} +% \end{function} +% +% \subsection{Selecting tokens from delimited arguments} +% +% A different kind of function for selecting tokens from the token +% stream are those that use delimited arguments. +% +% \begin{function}{ \use_none_delimit_by_q_nil:w / (EXP) | +% \use_none_delimit_by_q_stop:w / (EXP) | +% \use_none_delimit_by_q_recursion_stop:w / (EXP) } % \begin{syntax} % "\use_none_delimit_by_q_nil:w" "\q_nil" % \end{syntax} % Gobbles . Useful in gobbling the remainder in a list -% structure. +% structure or terminating recursion. % \end{function} % -% \begin{function}{% -% \use_arg_i_delimit_by_q_nil:nw | -% \use_arg_i_delimit_by_q_stop:nw | -% } +% \begin{function}{ \use_i_delimit_by_q_nil:nw / (EXP) | +% \use_i_delimit_by_q_stop:nw / (EXP) | +% \use_i_delimit_by_q_recursion_stop:nw / (EXP) } % \begin{syntax} -% "\use_arg_i_delimit_by_q_nil:nw" "{""}" "\q_nil" +% "\use_i_delimit_by_q_nil:nw" \Arg{arg} "\q_nil" % \end{syntax} % Gobbles and executes afterwards. This can also % be used to get the first item in a token list. % \end{function} % % -% \begin{function}{% -% \use_arg_i_after_fi:nw | -% \use_arg_i_after_else:nw | -% \use_arg_i_after_or:nw | -% \use_arg_i_after_orelse:nw -% } +% \begin{function}{ \use_i_after_fi:nw / (EXP) | +% \use_i_after_else:nw / (EXP) | +% \use_i_after_or:nw / (EXP) | +% \use_i_after_orelse:nw / (EXP) } % \begin{syntax} -% "\use_arg_i_after_fi:nw" "{""}" "\fi:" -% "\use_arg_i_after_else:nw" "{""}" "\else:" "\fi:" -% "\use_arg_i_after_or:nw" "{""}" "\or:" "\fi:" -% "\use_arg_i_after_orelse:nw" "{""}" "\or:/\else:" "\fi:" +% "\use_i_after_fi:nw" \Arg{arg} "\fi:" +% "\use_i_after_else:nw" \Arg{arg} "\else:" "\fi:" +% "\use_i_after_or:nw" \Arg{arg} "\or:" "\fi:" +% "\use_i_after_orelse:nw" \Arg{arg} "\or:/\else:" "\fi:" % \end{syntax} % Executes after executing closing out -% "\fi:". "\use_arg_i_after_orelse:nw" can be used anywhere where -% "\use_arg_i_after_else:nw" or "\use_arg_i_after_or:nw" are used. +% "\fi:". "\use_i_after_orelse:nw" can be used anywhere where +% "\use_i_after_else:nw" or "\use_i_after_or:nw" are used. % \end{function} % -% \subsection{Internal functions} % -% \begin{function}{% -% \cs:w | -% \cs_end: -% } +% \section{That which belongs in other modules but needs to be defined earlier} +% +% \begin{function}{ \exp_after:wN / (EXP) } % \begin{syntax} -% "\cs:w" "\cs_end:" +% "\exp_after:wN" % \end{syntax} -% This is the \TeX{} internal way of generating a control sequence from -% some token list. get expanded and must ultimately result in a -% sequence of characters. +% Expands once and then continues processing from . % \begin{texnote} -% These functions are the primitives \tn{csname} and \tn{endcsname}. -% "\cs:w" is considered weird because it expands tokens until it reaches -% "\cs_end:". -% \end{texnote} +% This is \TeX's \tn{expandafter}. +% \end{texnote} % \end{function} % -% \begin{function}{\pref_global:D | -% \pref_long:D | -% \pref_protected:D | -% } +% \begin{function}{ \exp_not:N / (EXP) | \exp_not:n / (EXP) } % \begin{syntax} -% "\pref_global:D" "\def:Npn" +% "\exp_not:N" +% "\exp_not:n" \Arg{tokens} % \end{syntax} -% Prefix functions that can be used in front of some definition -% functions (namely \ldots). The result of prefixing a function -% definition with "\pref_global:D" makes the definition global, -% "\pref_long:D" change the argument scanning mechanism so that it -% allows "\par" tokens in the argument of the prefixed function, -% and "\pref_protected:D" makes the definition robust in "\write"s etc. -% -% -% None of these internal functions should be used by a programmer since -% the necessary combinations are all available as separate function, -% e.g., "\def_long:Npn" is internally implemented as "\pref_long:D" -% "\def:Npn". +% In an expanding context, this function prevents or from +% expanding. % \begin{texnote} -% These prefixes are the primitives \tn{global}, \tn{long}, and -% \tn{protected}. The \tn{outer} isn't used at all within \LaTeX3 -% because \ldots +% These are \TeX's \tn{noexpand} and \eTeX's \tn{unexpanded}, respectively. % \end{texnote} % \end{function} % +% \begin{function}{ \prg_do_nothing: / (EXP) } +% This is as close as we get to a null operation or no-op. +% \begin{texnote} +% Definition as in \LaTeX's \tn{\@empty} but not used for the same thing. +% \end{texnote} +% \end{function} % -% -% \begin{function}{\io_put_log:x | -% \io_put_term:x | -% \io_put_deferred:Nx | -% } +% \begin{function}{ \iow_log:x | +% \iow_term:x | +% \iow_shipout_x:Nn } % \begin{syntax} -% "\io_put_log:x" "{""}" -% "\io_put_deferred:Nx" "{""}" +% "\iow_log:x" \Arg{message} +% "\iow_shipout_x:Nn" \Arg{message} % \end{syntax} % Writes to either to log or the terminal. % \end{function} % -% \subsection{Defining functions} +% \begin{function}{ \msg_kernel_bug:x } +% \begin{syntax} +% "\msg_kernel_bug:x" \Arg{message} +% \end{syntax} +% Internal function for calling errors in our code. +% \end{function} +% +% \begin{function}{ \cs_record_meaning:N } +% Placeholder for a function to be defined by \file{l3chk}. +% \end{function} +% +% \begin{variable}{ \c_minus_one | \c_zero | \c_sixteen } +% Numeric constants. +% \end{variable} +% +% +% +% \section{Defining functions} % % % There are two types of function definitions in \LaTeX3: versions % that check if the function name is still unused, and versions that -% simply make the definition. The later are used for internal scratch +% simply make the definition. The latter are used for internal scratch % functions that get new meanings all over the place. % % For each type there is an additional choice to be made: Does the % function to be defined contain delimited arguments? The answer in -% 99\% of the cases is no, so in most cases the programmer just want -% to input the number of arguments, which is basically how -% \cs{newcommand} in \LaTeXe{} works. Therefore we provide functions -% that expect a number as the primary type and later on in this module -% you can find the ones with the more primitive syntax. +% 99\% of the cases is no. For this type the programmer will know the +% number of arguments and in most cases use the argument signature to +% signal this, e.g., "\foo_bar:nnn" presumably takes three +% arguments. We therefore also provide functions that automatically +% detect how many arguments are required and construct the parameter +% text on the fly. % % A definition of a new function can be done locally and globally. Currently % nearly all function definitions are done locally on top level, in @@ -528,104 +648,126 @@ % as individual functions. % \end{texnote} % -% -% \subsubsection{Defining new functions} -% -% Firstly comes to variants most used namely those taking a number to -% denote the number of arguments. -% -% \begin{function}{\def_new:NNn | -% \def_new:NNx | -% \def_new:cNn | -% \def_new:cNx +% A slew of functions are defined in the following sections for defining +% new functions. Here's a quick summary to get an idea of what's available: +% {\centering +% "\cs_"("g")("new"/"set")("_protected")("_nopar")":"("N"/"c")("p")("n"/"x") +% \par} +% That stands for, respectively, the following variations: +% \begin{description} +% \item[\texttt g] Global or local; +% \item[\texttt{new}/\texttt{set}] +% Define a new function or re-define an existing one; +% \item[\texttt{protected}] +% Prevent expansion of the function in "x" arguments; +% \item[\texttt{nopar}] Restrict the argument(s) from containing "\par"; +% \item[\texttt N/\texttt c] Either a control sequence or a `csname'; +% \item[\texttt p] +% Either the a primitive \TeX\ argument or the number of arguments +% is detected from the argument signature, i.e., |\foo:nnn| is +% assumed to have three arguments |#1#2#3|; +% \item[\texttt n/\texttt x] Either an unexpanded or an expanded definition. +% \end{description} +% That adds up to 128 variations (!). However, the system is very +% logical and only a handful will usually be required often. +% +% +% +% \subsection{Defining new functions using primitive parameter text} +% +% +% \begin{function}{\cs_new:Npn | +% \cs_new:Npx | +% \cs_new:cpn | +% \cs_new:cpx % } % \begin{syntax} -% "\def_new:NNn" "{" "}" +% "\cs_new:Npn" \Arg{code} % \end{syntax} -% Defines a new function, making sure that is unused so far. -% is the number of arguments which is in the interval $[0,9]$ -% otherwise an error is raised. It is under the responsibility of the -% programmer to name the new function according to the rules laid out -% in the previous section. is either passed literally or may -% be subject to expansion (under the "x" variants). +% Defines a function that may contain "\par" tokens in the argument(s) +% when called. This is not allowed for normal functions. % \end{function} % -% \begin{function}{\gdef_new:NNn | -% \gdef_new:cNn | -% \gdef_new:NNx | -% \gdef_new:cNx +% \begin{function}{\cs_gnew:Npn | +% \cs_gnew:Npx | +% \cs_gnew:cpn | +% \cs_gnew:cpx % } % \begin{syntax} -% "\gdef_new:NNn" "{" "}" +% "\cs_gnew:Npn" \Arg{code} % \end{syntax} -% Like "\def_new:NNn" but defines the new function globally. +% Global versions of the above functions. % \end{function} % -% \begin{function}{\def_long_new:NNn | -% \def_long_new:NNx | -% \def_long_new:cNn | -% \def_long_new:cNx +% \begin{function}{\cs_new_nopar:Npn | +% \cs_new_nopar:Npx | +% \cs_new_nopar:cpn | +% \cs_new_nopar:cpx % } % \begin{syntax} -% "\def_long_new:NNn" "{" "}" +% "\cs_new_nopar:Npn" \Arg{code} % \end{syntax} -% Defines a function that may contain "\par" tokens in the argument(s) -% when called. This is not allowed for normal functions. +% Defines a new function, making sure that is unused so far. +% may consist of arbitrary parameter specification in \TeX{} +% syntax. It is under the responsibility of the programmer to name the +% new function according to the rules laid out in the previous section. +% is either passed literally or may be subject to expansion +% (under the "x" variants). % \end{function} % -% \begin{function}{\gdef_long_new:NNn | -% \gdef_long_new:NNx | -% \gdef_long_new:cNn | -% \gdef_long_new:cNx +% \begin{function}{\cs_gnew_nopar:Npn | +% \cs_gnew_nopar:Npx | +% \cs_gnew_nopar:cpn | +% \cs_gnew_nopar:cpx % } % \begin{syntax} -% "\gdef_long_new:NNn" "{" "}" +% "\cs_gnew_nopar:Npn" \Arg{code} % \end{syntax} -% Global versions of the above functions. +% Like "\cs_new_nopar:Npn" but defines the new function globally. See +% comments above. % \end{function} % -% \begin{function}{\def_protected_new:NNn | -% \def_protected_new:NNx | -% \def_protected_new:cNn | -% \def_protected_new:cNx +% \begin{function}{\cs_new_protected:Npn | +% \cs_new_protected:Npx | +% \cs_new_protected:cpn | +% \cs_new_protected:cpx % } % \begin{syntax} -% "\def_protected_new:NNn" "{" "}" +% "\cs_new_protected:Npn" \Arg{code} % \end{syntax} -% Defines a function that does not expand when inside an |x| type -% expansion. +% Defines a function that is both robust and may contain "\par" tokens +% in the argument(s) when called. % \end{function} % -% \begin{function}{\gdef_protected_new:NNn | -% \gdef_protected_new:NNx | -% \gdef_protected_new:cNn | -% \gdef_protected_new:cNx -% } +% \begin{function}{ \cs_gnew_protected:Npn | +% \cs_gnew_protected:Npx | +% \cs_gnew_protected:cpn | +% \cs_gnew_protected:cpx } % \begin{syntax} -% "\gdef_protected_new:NNn" "{" "}" +% "\cs_gnew_protected:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long_new:NNn | -% \def_protected_long_new:NNx | -% \def_protected_long_new:cNn | -% \def_protected_long_new:cNx +% \begin{function}{\cs_new_protected_nopar:Npn | +% \cs_new_protected_nopar:Npx | +% \cs_new_protected_nopar:cpn | +% \cs_new_protected_nopar:cpx % } % \begin{syntax} -% "\def_protected_long_new:NNn" "{" "}" +% "\cs_new_protected_nopar:Npn" \Arg{code} % \end{syntax} -% Defines a function that is both robust and may contain "\par" tokens -% in the argument(s) when called. +% Defines a function that does not expand when inside an |x| type +% expansion. % \end{function} % -% \begin{function}{\gdef_protected_long_new:NNn | -% \gdef_protected_long_new:NNx | -% \gdef_protected_long_new:cNn | -% \gdef_protected_long_new:cNx +% \begin{function}{\cs_gnew_protected_nopar:Npn | +% \cs_gnew_protected_nopar:Npx | +% \cs_gnew_protected_nopar:cpn | +% \cs_gnew_protected_nopar:cpx % } % \begin{syntax} -% "\gdef_protected_long_new:NNn" "{" "}" +% "\cs_gnew_protected_nopar:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} @@ -634,367 +776,385 @@ % % % -% Secondly comes the ones where the programmer can use delimited -% arguments. Rarely needed outside the kernel. % % -% \begin{function}{\def_new:Npn | -% \def_new:Npx | -% \def_new:cpn | -% \def_new:cpx -% } -% \begin{syntax} -% "\def_new:Npn" "{" "}" -% \end{syntax} -% Defines a new function, making sure that is unused so far. -% may consist of arbitrary parameter specification in \TeX{} -% syntax. It is under the responsibility of the programmer to name the -% new function according to the rules laid out in the previous section. -% is either passed literally or may be subject to expansion -% (under the "x" variants). -% \end{function} % -% \begin{function}{\gdef_new:Npn | -% \gdef_new:cpn | -% \gdef_new:Npx | -% \gdef_new:cpx -% } -% \begin{syntax} -% "\gdef_new:Npn" "{" "}" -% \end{syntax} -% Like "\def_new:Npn" but defines the new function globally. See -% comments above. -% \end{function} % -% \begin{function}{\def_long_new:Npn | -% \def_long_new:Npx | -% \def_long_new:cpn | -% \def_long_new:cpx +% \subsection{Defining new functions using the signature} +% +% +% \begin{function}{\cs_new:Nn | +% \cs_new:Nx | +% \cs_new:cn | +% \cs_new:cx % } % \begin{syntax} -% "\def_long_new:Npn" "{" "}" +% "\cs_new:Nn" \Arg{code} % \end{syntax} -% Defines a function that may contain "\par" tokens in the argument(s) -% when called. This is not allowed for normal functions. +% Defines a new function, making sure that is unused so far. The +% parameter text is automatically detected from the length of the +% function signature. If is missing a colon in its name, an error +% is raised. It is under the responsibility of the programmer to name +% the new function according to the rules laid out in the previous +% section. is either passed literally or may be subject to +% expansion (under the "x" variants). +% \begin{texnote} +% Internally, these use \TeX's "\long". These forms are +% recommended for low-level definitions as experience has shown that "\par" +% tokens often turn up in programming situations that wouldn't have been +% expected. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef_long_new:Npn | -% \gdef_long_new:Npx | -% \gdef_long_new:cpn | -% \gdef_long_new:cpx +% \begin{function}{\cs_gnew:Nn | +% \cs_gnew:Nx | +% \cs_gnew:cn | +% \cs_gnew:cx % } % \begin{syntax} -% "\gdef_long_new:Npn" "{" "}" +% "\cs_gnew:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_new:Npn | -% \def_protected_new:Npx | -% \def_protected_new:cpn | -% \def_protected_new:cpx +% \begin{function}{\cs_new_nopar:Nn | +% \cs_new_nopar:Nx | +% \cs_new_nopar:cn | +% \cs_new_nopar:cx % } % \begin{syntax} -% "\def_protected_new:Npn" "{" "}" +% "\cs_new_nopar:Nn" \Arg{code} % \end{syntax} -% Defines a function that does not expand when inside an |x| type -% expansion. +% Version of the above in which "\par" is not allowed to appear within the +% argument(s) of the defined functions. % \end{function} % -% \begin{function}{\gdef_protected_new:Npn | -% \gdef_protected_new:Npx | -% \gdef_protected_new:cpn | -% \gdef_protected_new:cpx +% \begin{function}{\cs_gnew_nopar:Nn | +% \cs_gnew_nopar:Nx | +% \cs_gnew_nopar:cn | +% \cs_gnew_nopar:cx % } % \begin{syntax} -% "\gdef_protected_new:Npn" "{" "}" +% "\cs_gnew_nopar:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long_new:Npn | -% \def_protected_long_new:Npx | -% \def_protected_long_new:cpn | -% \def_protected_long_new:cpx +% \begin{function}{\cs_new_protected:Nn | +% \cs_new_protected:Nx | +% \cs_new_protected:cn | +% \cs_new_protected:cx % } % \begin{syntax} -% "\def_protected_long_new:Npn" "{" "}" +% "\cs_new_protected:Nn" \Arg{code} % \end{syntax} % Defines a function that is both robust and may contain "\par" tokens % in the argument(s) when called. % \end{function} % -% \begin{function}{\gdef_protected_long_new:Npn | -% \gdef_protected_long_new:Npx | -% \gdef_protected_long_new:cpn | -% \gdef_protected_long_new:cpx +% \begin{function}{\cs_gnew_protected:Nn | +% \cs_gnew_protected:Nx | +% \cs_gnew_protected:cn | +% \cs_gnew_protected:cx % } % \begin{syntax} -% "\gdef_protected_long_new:Npn" "{" "}" +% "\cs_gnew_protected:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\let_new:NN | -% \let_new:cN | -% \let_new:Nc | -% \let_new:cc | -% \glet_new:NN| -% \glet_new:cN| -% \glet_new:Nc| -% \glet_new:cc } +% \begin{function}{\cs_new_protected_nopar:Nn | +% \cs_new_protected_nopar:Nx | +% \cs_new_protected_nopar:cn | +% \cs_new_protected_nopar:cx +% } % \begin{syntax} -% "\let_new:NN" +% "\cs_new_protected_nopar:Nn" \Arg{code} % \end{syntax} -% Gives the function the current meaning of . Again, we may -% do this always globally. +% Defines a function that does not expand when inside an |x| type +% expansion. "\par" is not allowed in the argument(s) of the defined function. % \end{function} % -% -% -% \subsubsection{Undefining functions} -% -% \begin{function}{ \cs_gundefine:N +% \begin{function}{\cs_gnew_protected_nopar:Nn | +% \cs_gnew_protected_nopar:Nx | +% \cs_gnew_protected_nopar:cn | +% \cs_gnew_protected_nopar:cx % } % \begin{syntax} -% "\cs_gundefine:N" +% "\cs_gnew_protected_nopar:Nn" \Arg{code} % \end{syntax} -% Undefines the control sequence. +% Global versions of the above functions. % \end{function} % -% \subsubsection{Defining internal functions (no checks)} +% +% +% \subsection{Defining functions using primitive parameter text} +% % % Besides the function definitions that check whether or not their % argument is an unused function we need function definitions that % overwrite currently used definitions. The following functions are % provided for this purpose. % -% First comes the versions expecting a number to denote the number of -% arguments. -% -% \begin{function}{\def:NNn | -% \def:NNx | -% \def:cNn | -% \def:cNx | +% \begin{function}{\cs_set:Npn | +% \cs_set:Npx | +% \cs_set:cpn | +% \cs_set:cpx | % } % \begin{syntax} -% "\def:NNn" "{" "}" +% "\cs_set:Npn" \Arg{code} % \end{syntax} -% Like "\def_new:NNn" etc.\ but does not check the name. +% Like "\cs_set_nopar:Npn" but allows "\par" tokens in the arguments of the +% function being defined. +% \begin{texnote} +% These are equivalent to \TeX's "\long\def" and so on. These forms are +% recommended for low-level definitions as experience has shown that "\par" +% tokens often turn up in programming situations that wouldn't have been +% expected. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef:NNn | -% \gdef:NNx | -% \gdef:cNn | -% \gdef:cNx | +% \begin{function}{\cs_gset:Npn | +% \cs_gset:Npx | +% \cs_gset:cpn | +% \cs_gset:cpx | % } % \begin{syntax} -% "\gdef:NNn" "{" "}" +% "\cs_gset:Npn" \Arg{code} % \end{syntax} -% Like "\def:NNn" but defines the globally. +% Global variant of "\cs_set:Npn". % \end{function} % -% -% \begin{function}{\def_long:NNn | -% \def_long:NNx | -% \def_long:cNn | -% \def_long:cNx | +% \begin{function}{\cs_set_nopar:Npn | +% \cs_set_nopar:Npx | +% \cs_set_nopar:cpn | +% \cs_set_nopar:cpx | % } % \begin{syntax} -% "\def_long:NNn" "{" "}" +% "\cs_set_nopar:Npn" \Arg{code} % \end{syntax} -% Like "\def:NNn" but allows "\par" tokens in the arguments of the -% function being defined. +% Like "\cs_new_nopar:Npn" etc.\ but does not check the name. +% \begin{texnote} +% "\cs_set_nopar:Npn" is the \LaTeX3 name for \TeX{}'s \tn{def} and +% "\cs_set_nopar:Npx" corresponds to the primitive \tn{edef}. The +% "\cs_set_nopar:cpn" function was known in \LaTeX2 as \tn{@namedef}. +% "\cs_set_nopar:cpx" has no equivalent. +% \end{texnote} % \end{function} % -% \begin{function}{\gdef_long:NNn | -% \gdef_long:NNx | -% \gdef_long:cNn | -% \gdef_long:cNx | +% \begin{function}{\cs_gset_nopar:Npn | +% \cs_gset_nopar:Npx | +% \cs_gset_nopar:cpn | +% \cs_gset_nopar:cpx | % } % \begin{syntax} -% "\gdef_long:NNn" "{" "}" +% "\cs_gset_nopar:Npn" \Arg{code} % \end{syntax} -% Global variant of "\def_long:NNn". +% Like "\cs_set_nopar:Npn" but defines the globally. +% \begin{texnote} +% "\cs_gset_nopar:Npn" and "\cs_gset_nopar:Npx" +% are \TeX's \tn{gdef} and \tn{xdef}. +% \end{texnote} % \end{function} % -% \begin{function}{\def_protected:NNn | -% \def_protected:cNn | -% \def_protected:NNx | -% \def_protected:cNx | +% +% \begin{function}{\cs_set_protected:Npn | +% \cs_set_protected:Npx | +% \cs_set_protected:cpn | +% \cs_set_protected:cpx | % } % \begin{syntax} -% "\def_protected:NNn" "{" "}" +% "\cs_set_protected:Npn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% This also comes as a |long| version. If you for some reason want to -% expand it inside an |x| type expansion, prefix it with -% |\exp_after:NN \use_noop:|. +% These varieties allow |\par| tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef_protected:NNn | -% \gdef_protected:cNn | -% \gdef_protected:NNx | -% \gdef_protected:cNx | +% \begin{function}{\cs_gset_protected:Npn | +% \cs_gset_protected:Npx | +% \cs_gset_protected:cpn | +% \cs_gset_protected:cpx | % } % \begin{syntax} -% "\gdef_protected:NNn" "{" "}" +% "\cs_gset_protected:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long:NNn | -% \def_protected_long:cNn | -% \def_protected_long:NNx | -% \def_protected_long:cNx | +% \begin{function}{\cs_set_protected_nopar:Npn | +% \cs_set_protected_nopar:Npx | +% \cs_set_protected_nopar:cpn | +% \cs_set_protected_nopar:cpx | % } % \begin{syntax} -% "\def_protected_long:NNn" "{" "}" +% "\cs_set_protected_nopar:Npn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% These varieties also allow |\par| tokens in the arguments of the -% function being defined. +% If you want for some reason to expand it inside an |x| type expansion, +% prefix it with |\exp_after:wN \prg_do_nothing:|. % \end{function} % -% \begin{function}{\gdef_protected_long:NNn | -% \gdef_protected_long:cNn | -% \gdef_protected_long:NNx | -% \gdef_protected_long:cNx | +% \begin{function}{\cs_gset_protected_nopar:Npn | +% \cs_gset_protected_nopar:Npx | +% \cs_gset_protected_nopar:cpn | +% \cs_gset_protected_nopar:cpx | % } % \begin{syntax} -% "\gdef_protected_long:NNn" "{" "}" +% "\cs_gset_protected_nopar:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% Secondly the ones that use the primitive parameter build-up: % -% \begin{function}{\def:Npn | -% \def:Npx | -% \def:cpn | -% \def:cpx | +% \subsection{Defining functions using the signature (no checks)} +% +% As above but now detecting the parameter text from inspecting the +% signature. +% +% \begin{function}{\cs_set:Nn | +% \cs_set:Nx | +% \cs_set:cn | +% \cs_set:cx | % } % \begin{syntax} -% "\def:Npn" "{" "}" +% "\cs_set:Nn" \Arg{code} % \end{syntax} -% Like "\def_new:Npn" etc.\ but does not check the name. -% \begin{texnote} -% "\def:Npn" is the \LaTeX3 name for \TeX{}'s \tn{def} and "\def:Npx" -% corresponds to the primitive \tn{edef}. The "\def:cpn" function was -% known in \LaTeX2 as \tn{@namedef}. "\def:cpx" has no equivalent. -% \end{texnote} +% Like "\cs_set_nopar:Nn" but allows "\par" tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef:Npn | -% \gdef:Npx | -% \gdef:cpn | -% \gdef:cpx | +% \begin{function}{\cs_gset:Nn | +% \cs_gset:Nx | +% \cs_gset:cn | +% \cs_gset:cx | % } % \begin{syntax} -% "\gdef:Npn" "{" "}" +% "\cs_gset:Nn" \Arg{code} % \end{syntax} -% Like "\def:Npn" but defines the globally. -% \begin{texnote} -% "\gdef:Npn" and "\gdef:Npx" are known to \TeX{}hackers as \tn{gdef} -% and \tn{xdef}. -% \end{texnote} +% Global variant of "\cs_set:Nn". % \end{function} % -% -% \begin{function}{\def_long:Npn | -% \def_long:Npx | -% \def_long:cpn | -% \def_long:cpx | +% \begin{function}{\cs_set_nopar:Nn | +% \cs_set_nopar:Nx | +% \cs_set_nopar:cn | +% \cs_set_nopar:cx | % } % \begin{syntax} -% "\def_long:Npn" "{" "}" +% "\cs_set_nopar:Nn" \Arg{code} % \end{syntax} -% Like "\def:Npn" but allows "\par" tokens in the arguments of the -% function being defined. +% Like "\cs_new_nopar:Nn" etc.\ but does not check the name. % \end{function} % -% \begin{function}{\gdef_long:Npn | -% \gdef_long:Npx | -% \gdef_long:cpn | -% \gdef_long:cpx | +% \begin{function}{\cs_gset_nopar:Nn | +% \cs_gset_nopar:Nx | +% \cs_gset_nopar:cn | +% \cs_gset_nopar:cx | % } % \begin{syntax} -% "\gdef_long:Npn" "{" "}" +% "\cs_gset_nopar:Nn" \Arg{code} % \end{syntax} -% Global variant of "\def_long:Npn". +% Like "\cs_set_nopar:Nn" but defines the globally. % \end{function} % -% \begin{function}{\def_protected:Npn | -% \def_protected:cpn | -% \def_protected:Npx | -% \def_protected:cpx | +% \begin{function}{\cs_set_protected:Nn | +% \cs_set_protected:cn | +% \cs_set_protected:Nx | +% \cs_set_protected:cx | % } % \begin{syntax} -% "\def_protected:Npn" "{" "}" +% "\cs_set_protected:Nn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% This also comes as a |long| version. If you for some reason want to -% expand it inside an |x| type expansion, prefix it with -% |\exp_after:NN \use_noop:|. +% These varieties also allow |\par| tokens in the arguments of the +% function being defined. % \end{function} % -% \begin{function}{\gdef_protected:Npn | -% \gdef_protected:cpn | -% \gdef_protected:Npx | -% \gdef_protected:cpx | +% \begin{function}{\cs_gset_protected:Nn | +% \cs_gset_protected:cn | +% \cs_gset_protected:Nx | +% \cs_gset_protected:cx | % } % \begin{syntax} -% "\gdef_protected:Npn" "{" "}" +% "\cs_gset_protected:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % -% \begin{function}{\def_protected_long:Npn | -% \def_protected_long:cpn | -% \def_protected_long:Npx | -% \def_protected_long:cpx | +% \begin{function}{\cs_set_protected_nopar:Nn | +% \cs_set_protected_nopar:cn | +% \cs_set_protected_nopar:Nx | +% \cs_set_protected_nopar:cx | % } % \begin{syntax} -% "\def_protected_long:Npn" "{" "}" +% "\cs_set_protected_nopar:Nn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. -% These varieties also allow |\par| tokens in the arguments of the -% function being defined. +% This also comes as a |long| version. If you for some reason want to +% expand it inside an |x| type expansion, prefix it with +% |\exp_after:wN \prg_do_nothing:|. % \end{function} % -% \begin{function}{\gdef_protected_long:Npn | -% \gdef_protected_long:cpn | -% \gdef_protected_long:Npx | -% \gdef_protected_long:cpx | +% \begin{function}{\cs_gset_protected_nopar:Nn | +% \cs_gset_protected_nopar:cn | +% \cs_gset_protected_nopar:Nx | +% \cs_gset_protected_nopar:cx | % } % \begin{syntax} -% "\gdef_protected_long:Npn" "{" "}" +% "\cs_gset_protected_nopar:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % -% \begin{function}{\let:NN | -% \let:cN | -% \let:Nc | -% \let:cc | -% \glet:NN | -% \glet:cN | -% \glet:Nc | -% \glet:cc -% } +% \subsection{Undefining functions} +% +% \begin{function}{ \cs_gundefine:N } +% \begin{syntax} +% "\cs_gundefine:N" +% \end{syntax} +% Undefines the control sequence globally. +% \end{function} +% +% +% \subsection{Copying function definitions} +% +% \begin{function}{ \cs_new_eq:NN | +% \cs_new_eq:cN | +% \cs_new_eq:Nc | +% \cs_new_eq:cc | +% \cs_gnew_eq:NN | +% \cs_gnew_eq:cN | +% \cs_gnew_eq:Nc | +% \cs_gnew_eq:cc } % \begin{syntax} -% "\let:cN" +% "\cs_new_eq:NN" +% \end{syntax} +% Gives the function locally or globally the current meaning of . +% If already exists then an error is called. +% \end{function} +% +% +% \begin{function}{\cs_set_eq:NN | +% \cs_set_eq:cN | +% \cs_set_eq:Nc | +% \cs_set_eq:cc | +% \cs_gset_eq:NN | +% \cs_gset_eq:cN | +% \cs_gset_eq:Nc | +% \cs_gset_eq:cc } +% \begin{syntax} +% "\cs_set_eq:cN" % \end{syntax} % Gives the function the current meaning of . Again, we may % always do this globally. % \end{function} % -% \begin{function}{\let:NwN} +% \begin{function}{\cs_set_eq:NwN} % \begin{syntax} -% "\let:NwN" -% "\let:NwN" "=" +% "\cs_set_eq:NwN" +% "\cs_set_eq:NwN" "=" % \end{syntax} % These functions assign the meaning of locally or globally to the % function . Because the \TeX{} primitive operation is being used @@ -1002,67 +1162,109 @@ % and the name contains a "w". (Not happy about this % convention!). % \begin{texnote} -% "\let:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. +% "\cs_set_eq:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. % \end{texnote} % \end{function} % +% \subsection{Internal functions} % -% \subsection{Defining test functions} % +% \begin{function}{ \pref_global:D | +% \pref_long:D | +% \pref_protected:D } +% \begin{syntax} +% "\pref_global:D" "\cs_set_nopar:Npn" +% \end{syntax} +% Prefix functions that can be used in front of some definition +% functions (namely \ldots). The result of prefixing a function +% definition with "\pref_global:D" makes the definition global, +% "\pref_long:D" change the argument scanning mechanism so that it +% allows "\par" tokens in the argument of the prefixed function, +% and "\pref_protected:D" makes the definition robust in "\write"s etc. % -% \begin{function}{ -% \def_test_function:npn | -% \def_long_test_function:npn | -% \def_test_function_new:npn | -% \def_long_test_function_new:npn | -% } -% \begin{syntax} -% "\def_test_function_new:npn" "{"name"}" "{""}" -% \end{syntax} -% Define all the common test cases for a simple test to reduce the -% risk of typos. As an example here's how we defined the functions -% "\cs_free:cTF", "\cs_free:cT" and "\cs_free:cF". You just have to -% fill in the test. -% \begin{verbatim} -% \def_test_function:npn{cs_free:c} #1 { -% \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -% \end{verbatim} -% Be careful not to use this function inside some primitive -% conditional as \TeX\ will most likely get confused because of the -% unmatched conditionals. +% None of these internal functions should be used by a programmer since +% the necessary combinations are all available as separate function, +% e.g., "\cs_set:Npn" is internally implemented as "\pref_long:D" +% "\cs_set_nopar:Npn". +% \begin{texnote} +% These prefixes are the primitives \tn{global}, \tn{long}, and +% \tn{protected}. The \tn{outer} prefix isn't used at all within \LaTeX3 +% because \ldots (it causes more hassle than it's worth? It's nevery proved +% useful in any meaningful way?) +% \end{texnote} % \end{function} % +% \section{The innards of a function} % -% \subsection{The innards of a function} -% -% \begin{function}{\cs_to_str:N} +% \begin{function}{\cs_to_str:N / (EXP)} % \begin{syntax} % "\cs_to_str:N" % \end{syntax} -% This function return the name of as a sequence of letters with +% This function returns the name of as a sequence of letters with % the escape character removed. % \end{function} % -% \begin{function}{\token_to_string:N} +% \begin{function}{\token_to_str:N / (EXP) | \token_to_str:c / (EXP)} % \begin{syntax} -% "\token_to_string:N" +% "\token_to_str:N" % \end{syntax} % This function return the name of as a sequence of letters % including the escape character. +% \begin{texnote} +% This is \TeX's \tn{string}. +% \end{texnote} % \end{function} % -% \begin{function}{\token_to_meaning:N} +% \begin{function}{\token_to_meaning:N / (EXP)} % \begin{syntax} % "\token_to_meaning:N" % \end{syntax} % This function returns the type and definition of as a sequence % of letters. +% \begin{texnote} +% This is \TeX's \tn{meaning}. +% \end{texnote} +% \end{function} +% +% +% \begin{function}{\cs_get_function_name:N / (EXP) | +% \cs_get_function_signature:N / (EXP)} +% \begin{syntax} +% "\cs_get_function_name:N" "\"":" +% \end{syntax} +% The "name" variant strips off the leading escape character and the +% trailing argument specification (including the colon) to return +% . The "signature" variants does the same but returns the +% signature instead. +% \end{function} +% +% +% \begin{function}{\cs_split_function:NN / (EXP)} +% \begin{syntax} +% "\cs_split_function:NN" "\"":" +% \end{syntax} +% Strips off the leading escape character, splits off the signature +% without the colon, informs whether or not a colon was present and +% then prefixes these results with , i.e., \Arg{name}\Arg{signature}\meta{true}/\meta{false}. For +% example, "\cs_get_function_name:N" is nothing more than +% "\cs_split_function:NN" "\"":" "\use_i:nnn". +% \end{function} +% +% +% \begin{function}{\cs_get_arg_count_from_signature:N / (EXP)} +% \begin{syntax} +% "\cs_get_arg_count_from_signature:N" "\"":" +% \end{syntax} +% Returns the number of chars in , signifying the number of arguments +% that the function uses. % \end{function} % +% % Other functions regarding arbitrary tokens can be found in the % \textsf{l3token} module. % -% \subsection{Grouping and scanning} +% \section{Grouping and scanning} % % \begin{function}{\scan_stop:} % \begin{syntax} @@ -1087,32 +1289,52 @@ % \end{texnote} % \end{function} % +% \begin{function}{\group_execute_after:N} +% \begin{syntax} +% "\group_execute_after:N" +% \end{syntax} +% Adds to the list of tokens to be inserted after the +% current group ends (through an explicit or implicit "\group_end:"). +% \begin{texnote} +% This is \TeX's \tn{aftergroup}. +% \end{texnote} +% \end{function} +% % -% \subsection{Engine specific definitions} +% \section{Checking the engine} +% +% \begin{function}{\xetex_if_engine: / (TF)(EXP)} +% \begin{syntax} +% "\xetex_if_engine:TF" \Arg{true code} \Arg{false code} +% \end{syntax} +% This function detects if we're running a Xe\TeX-based format. +% \end{function} % -% \begin{function}{\engine_if_aleph:TF} +% \begin{function}{\luatex_if_engine: / (TF)(EXP)} % \begin{syntax} -% "\engine_if_aleph:TF" "{""}" "{""}" +% "\luatex_if_engine:TF" \Arg{true code} \Arg{false code} % \end{syntax} -% This function detects if we're running an Aleph based format. This -% is particularly useful when allocating registers. +% This function detects if we're running a Lua\TeX-based format. % \end{function} % +% \begin{variable}{\c_xetex_is_engine_bool|\c_luatex_is_engine_bool} +% Boolean variables used for the above functions. +% \end{variable} % +% \end{documentation} % -% \StopEventually{} +% \begin{implementation} % +% \section{\pkg{l3basics} implementation} % -% \subsection{The Implementation} -% We start by ensuring that the required packages are loaded. We need -% \textsf{l3names} to get things going but we actually need it very -% early on, so it is loaded at the very top of this file. Also, most -% of the code below won't run until \textsf{l3expan} has been +% We need \textsf{l3names} to get things going but we actually need it very +% early on, so it is loaded at the very top of the file \file{l3basics.dtx}. +% Also, most of the code below won't run until \textsf{l3expan} has been % loaded. % -% \subsubsection{Renaming some \TeX{} primitives (again)} +% \subsection{Renaming some \TeX{} primitives (again)} % -% \begin{macro}{\let:NwN} +% \begin{macro}{\cs_set_eq:NwN} % Having given all the tex primitives a consistent name, we need to % give sensible names to the ones we actually want to use. % These will be defined as needed in the appropriate modules, but @@ -1120,30 +1342,39 @@ % in terms of csname usage, an alternative scheme would be to just use % the ``tex\ldots D'' name in the cases where no good alternative exists.} % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> -\tex_let:D \let:NwN \tex_let:D +\tex_let:D \cs_set_eq:NwN \tex_let:D % \end{macrocode} % \end{macro} % \begin{macro}{\if_true:} % \begin{macro}{\if_false:} +% \begin{macro}{\or:} % \begin{macro}{\else:} % \begin{macro}{\fi:} % \begin{macro}{\reverse_if:N} % \begin{macro}{\if:w} +% \begin{macro}{\if_bool:N} +% \begin{macro}{\if_predicate:w} % \begin{macro}{\if_charcode:w} % \begin{macro}{\if_catcode:w} % Then some conditionals. % \begin{macrocode} -\let:NwN \if_true: \tex_iftrue:D -\let:NwN \if_false: \tex_iffalse:D -\let:NwN \else: \tex_else:D -\let:NwN \fi: \tex_fi:D -\let:NwN \reverse_if:N \etex_unless:D -\let:NwN \if:w \tex_if:D -\let:NwN \if_charcode:w \tex_if:D -\let:NwN \if_catcode:w \tex_ifcat:D +\cs_set_eq:NwN \if_true: \tex_iftrue:D +\cs_set_eq:NwN \if_false: \tex_iffalse:D +\cs_set_eq:NwN \or: \tex_or:D +\cs_set_eq:NwN \else: \tex_else:D +\cs_set_eq:NwN \fi: \tex_fi:D +\cs_set_eq:NwN \reverse_if:N \etex_unless:D +\cs_set_eq:NwN \if:w \tex_if:D +\cs_set_eq:NwN \if_bool:N \tex_ifodd:D +\cs_set_eq:NwN \if_predicate:w \tex_ifodd:D +\cs_set_eq:NwN \if_charcode:w \tex_if:D +\cs_set_eq:NwN \if_catcode:w \tex_ifcat:D % \end{macrocode} % \end{macro} % \end{macro} @@ -1153,28 +1384,26 @@ % \end{macro} % \end{macro} % \end{macro} -% \begin{macro}{\if_meaning:NN} -% \begin{macro}{\if_token_eq:NN} -% \begin{macro}{\if_cs_meaning_eq:NN} -% Some different names for |\ifx|.\footnote{MH: Clean up at some point} -% \begin{macrocode} -\let:NwN \if_meaning:NN \tex_ifx:D -\let:NwN \if_token_eq:NN \tex_ifx:D -\let:NwN \if_cs_meaning_eq:NN\tex_ifx:D -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% +% \begin{macro}{\if_meaning:w} +% \begin{macrocode} +\cs_set_eq:NwN \if_meaning:w \tex_ifx:D +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\if_mode_math:} % \begin{macro}{\if_mode_horizontal:} % \begin{macro}{\if_mode_vertical:} % \begin{macro}{\if_mode_inner:} % \TeX{} lets us detect some if its modes. % \begin{macrocode} -\let:NwN \if_mode_math: \tex_ifmmode:D -\let:NwN \if_mode_horizontal:\tex_ifhmode:D -\let:NwN \if_mode_vertical: \tex_ifvmode:D -\let:NwN \if_mode_inner: \tex_ifinner:D +\cs_set_eq:NwN \if_mode_math: \tex_ifmmode:D +\cs_set_eq:NwN \if_mode_horizontal: \tex_ifhmode:D +\cs_set_eq:NwN \if_mode_vertical: \tex_ifvmode:D +\cs_set_eq:NwN \if_mode_inner: \tex_ifinner:D % \end{macrocode} % \end{macro} % \end{macro} @@ -1183,29 +1412,30 @@ % \begin{macro}{\if_cs_exist:N} % \begin{macro}{\if_cs_exist:w} % \begin{macrocode} -\let:NwN \if_cs_exist:N \etex_ifdefined:D -\let:NwN \if_cs_exist:w \etex_ifcsname:D +\cs_set_eq:NwN \if_cs_exist:N \etex_ifdefined:D +\cs_set_eq:NwN \if_cs_exist:w \etex_ifcsname:D % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\exp_after:NN} +% \begin{macro}{\exp_after:wN} % \begin{macro}{\exp_not:N} % \begin{macro}{\exp_not:n} % The three |\exp_| functions are used in the \textsf{l3expan} module % where they are described. % \begin{macrocode} -\let:NwN \exp_after:NN \tex_expandafter:D -\let:NwN \exp_not:N \tex_noexpand:D -\let:NwN \exp_not:n \etex_unexpanded:D +\cs_set_eq:NwN \exp_after:wN \tex_expandafter:D +\cs_set_eq:NwN \exp_not:N \tex_noexpand:D +\cs_set_eq:NwN \exp_not:n \etex_unexpanded:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\io_put_deferred:Nx} +% \begin{macro}{\iow_shipout_x:Nn} % \begin{macro}{\token_to_meaning:N} -% \begin{macro}{\token_to_string:N} +% \begin{macro}{\token_to_str:N} +% \begin{macro}{\token_to_str:c} % \begin{macro}{\cs:w} % \begin{macro}{\cs_end:} % \begin{macro}{\cs_meaning:N} @@ -1213,15 +1443,16 @@ % \begin{macro}{\cs_show:N} % \begin{macro}{\cs_show:c} % \begin{macrocode} -\let:NwN \io_put_deferred:Nx \tex_write:D -\let:NwN \token_to_meaning:N \tex_meaning:D -\let:NwN \token_to_string:N \tex_string:D -\let:NwN \cs:w \tex_csname:D -\let:NwN \cs_end: \tex_endcsname:D -\let:NwN \cs_meaning:N \tex_meaning:D -\tex_def:D \cs_meaning:c #1{\exp_after:NN\cs_meaning:N\cs:w #1\cs_end:} -\let:NwN \cs_show:N \tex_show:D -\tex_def:D \cs_show:c #1{\exp_after:NN\cs_show:N\cs:w #1\cs_end:} +\cs_set_eq:NwN \iow_shipout_x:Nn \tex_write:D +\cs_set_eq:NwN \token_to_meaning:N \tex_meaning:D +\cs_set_eq:NwN \token_to_str:N \tex_string:D +\cs_set_eq:NwN \cs:w \tex_csname:D +\cs_set_eq:NwN \cs_end: \tex_endcsname:D +\cs_set_eq:NwN \cs_meaning:N \tex_meaning:D +\tex_def:D \cs_meaning:c {\exp_args:Nc\cs_meaning:N} +\cs_set_eq:NwN \cs_show:N \tex_show:D +\tex_def:D \cs_show:c {\exp_args:Nc\cs_show:N} +\tex_def:D \token_to_str:c {\exp_args:Nc\token_to_str:N} % \end{macrocode} % \end{macro} % \end{macro} @@ -1232,6 +1463,8 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% % \begin{macro}{\scan_stop:} % \begin{macro}{\group_begin:} % \begin{macro}{\group_end:} @@ -1239,70 +1472,69 @@ % versions that are safe inside alignments. These safe versions are % defined in the \textsf{l3prg} module. % \begin{macrocode} -\let:NwN \scan_stop: \tex_relax:D -\let:NwN \group_begin: \tex_begingroup:D -\let:NwN \group_end: \tex_endgroup:D +\cs_set_eq:NwN \scan_stop: \tex_relax:D +\cs_set_eq:NwN \group_begin: \tex_begingroup:D +\cs_set_eq:NwN \group_end: \tex_endgroup:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\group_execute_after:N} % \begin{macrocode} -\let:NwN \group_execute_after:N \tex_aftergroup:D +\cs_set_eq:NwN \group_execute_after:N \tex_aftergroup:D % \end{macrocode} % \end{macro} -% \begin{macro}{\the_internal:D} % \begin{macro}{\pref_global:D} % \begin{macro}{\pref_long:D} % \begin{macro}{\pref_protected:D} -% These following names are temporary and should be removed as soon -% as possible (April 1998). % \begin{macrocode} -\let:NwN \the_internal:D \tex_the:D -\let:NwN \pref_global:D \tex_global:D -% \end{macrocode} -% "\pref_long:D" has been documented for years but didn't exist\dots{} -% Added it and the robustness prefix. -% \begin{macrocode} -\let:NwN \pref_long:D \tex_long:D -\let:NwN \pref_protected:D \etex_protected:D +\cs_set_eq:NwN \pref_global:D \tex_global:D +\cs_set_eq:NwN \pref_long:D \tex_long:D +\cs_set_eq:NwN \pref_protected:D \etex_protected:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % % -% \subsubsection {Defining functions} +% \subsection {Defining functions} % % % We start by providing functions for the typical definition % functions. First the local ones. % -% \begin{macro}{\def:Npn} -% \begin{macro}{\def:Npx} -% \begin{macro}{\def_long:Npn} -% \begin{macro}{\def_long:Npx} -% \begin{macro}{\def_protected:Npn} -% \begin{macro}{\def_protected:Npx} -% \begin{macro}{\def_protected_long:Npn} -% \begin{macro}{\def_protected_long:Npx} +% \begin{macro}{\cs_set_nopar:Npn} +% \begin{macro}{\cs_set_nopar:Npx} +% \begin{macro}{\cs_set:Npn} +% \begin{macro}{\cs_set:Npx} +% \begin{macro}{\cs_set_protected_nopar:Npn} +% \begin{macro}{\cs_set_protected_nopar:Npx} +% \begin{macro}{\cs_set_protected:Npn} +% \begin{macro}{\cs_set_protected:Npx} % All assignment functions in \LaTeX3 should be naturally robust; % after all, the \TeX\ primitives for assignments are and it can be % a cause of problems if others aren't. % \begin{macrocode} -\let:NwN \def:Npn \tex_def:D -\let:NwN \def:Npx \tex_edef:D -\pref_protected:D \def:Npn \def_long:Npn {\pref_long:D \def:Npn} -\pref_protected:D \def:Npn \def_long:Npx {\pref_long:D \def:Npx} -\pref_protected:D \def:Npn \def_protected:Npn {\pref_protected:D \def:Npn} -\pref_protected:D \def:Npn \def_protected:Npx {\pref_protected:D \def:Npx} -\def_protected:Npn \def_protected_long:Npn { - \pref_protected:D \pref_long:D \def:Npn +\cs_set_eq:NwN \cs_set_nopar:Npn \tex_def:D +\cs_set_eq:NwN \cs_set_nopar:Npx \tex_edef:D +\pref_protected:D \cs_set_nopar:Npn \cs_set:Npn { + \pref_long:D \cs_set_nopar:Npn +} +\pref_protected:D \cs_set_nopar:Npn \cs_set:Npx { + \pref_long:D \cs_set_nopar:Npx } -\def_protected:Npn \def_protected_long:Npx { - \pref_protected:D \pref_long:D \def:Npx +\pref_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npn { + \pref_protected:D \cs_set_nopar:Npn +} +\pref_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npx { + \pref_protected:D \cs_set_nopar:Npx +} +\cs_set_protected_nopar:Npn \cs_set_protected:Npn { + \pref_protected:D \pref_long:D \cs_set_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_set_protected:Npx { + \pref_protected:D \pref_long:D \cs_set_nopar:Npx } % \end{macrocode} % \end{macro} @@ -1314,27 +1546,35 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\gdef:Npn} -% \begin{macro}{\gdef:Npx} -% \begin{macro}{\gdef_long:Npn} -% \begin{macro}{\gdef_long:Npx} -% \begin{macro}{\gdef_protected:Npn} -% \begin{macro}{\gdef_protected:Npx} -% \begin{macro}{\gdef_protected_long:Npn} -% \begin{macro}{\gdef_protected_long:Npx} +% \begin{macro}{\cs_gset_nopar:Npn} +% \begin{macro}{\cs_gset_nopar:Npx} +% \begin{macro}{\cs_gset:Npn} +% \begin{macro}{\cs_gset:Npx} +% \begin{macro}{\cs_gset_protected_nopar:Npn} +% \begin{macro}{\cs_gset_protected_nopar:Npx} +% \begin{macro}{\cs_gset_protected:Npn} +% \begin{macro}{\cs_gset_protected:Npx} % Global versions of the above functions. % \begin{macrocode} -\let:NwN \gdef:Npn \tex_gdef:D -\let:NwN \gdef:Npx \tex_xdef:D -\def_protected:Npn \gdef_long:Npn {\pref_long:D \gdef:Npn} -\def_protected:Npn \gdef_long:Npx {\pref_long:D \gdef:Npx} -\def_protected:Npn \gdef_protected:Npn {\pref_protected:D \gdef:Npn} -\def_protected:Npn \gdef_protected:Npx {\pref_protected:D \gdef:Npx} -\def_protected:Npn \gdef_protected_long:Npn { - \pref_protected:D \pref_long:D \gdef:Npn +\cs_set_eq:NwN \cs_gset_nopar:Npn \tex_gdef:D +\cs_set_eq:NwN \cs_gset_nopar:Npx \tex_xdef:D +\cs_set_protected_nopar:Npn \cs_gset:Npn { + \pref_long:D \cs_gset_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_gset:Npx { + \pref_long:D \cs_gset_nopar:Npx } -\def_protected:Npn \gdef_protected_long:Npx { - \pref_protected:D \pref_long:D \gdef:Npx +\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npn { + \pref_protected:D \cs_gset_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npx { + \pref_protected:D \cs_gset_nopar:Npx +} +\cs_set_protected_nopar:Npn \cs_gset_protected:Npn { + \pref_protected:D \pref_long:D \cs_gset_nopar:Npn +} +\cs_set_protected_nopar:Npn \cs_gset_protected:Npx { + \pref_protected:D \pref_long:D \cs_gset_nopar:Npx } % \end{macrocode} % \end{macro} @@ -1346,746 +1586,891 @@ % \end{macro} % \end{macro} % -% \subsubsection{Predicate implementation} % -% I think Michael originated the idea of expandable boolean tests. At -% first these were supposed to expand into either \texttt{TT} or -% \texttt{TF} to be tested using |\if:w| but this was later changed to -% \texttt{00} and \texttt{01}, so they can be used in logical -% operations (see the \textsf{l3prg} module). We need this from the -% get-go. % -% \begin{macro}{\c_true} -% \begin{macro}{\c_false} -% Here are the canonical boolean values. +% \subsection{Selecting tokens} +% +% \begin{macro}{\use:c} +% This macro grabs its argument and returns a csname from it. % \begin{macrocode} -\def:Npn \c_true {00} -\def:Npn \c_false {01} +\cs_set:Npn \use:c #1 { \cs:w#1\cs_end: } % \end{macrocode} % \end{macro} -% \end{macro} -% -% \subsubsection {Defining and checking (new) functions} % -% \begin{macro}{\c_minus_one} -% \begin{macro}{\c_sixteen} -% We need the constants |\c_minus_one| and |\c_sixteen| now for -% writing information to the log and the terminal but the -% rest are defined in the \textsf{l3num} module -- at least for the -% ones that can be defined with |\tex_chardef:D| or -% |\tex_mathchardef:D|. Otherwise the \textsf{l3int} module is -% required but it can't be used until the allocation has been set -% up properly! The actual allocation mechanism is in -% \textsf{l3alloc} and as \TeX{} wants to reserve count registers -% 0--9, the first available one is~10 so we use that for -% |\c_minus_one|. +% \begin{macro}{\use:n} +% \begin{macro}{\use:nn} +% \begin{macro}{\use:nnn} +% \begin{macro}{\use:nnnn} +% These macro grabs its arguments and returns it back to the input +% (with outer braces removed). "\use:n" is defined earlier for bootstrapping. % \begin{macrocode} -%<*!initex> -\let:NwN \c_minus_one\m@ne -% -%<*!package> -\tex_countdef:D \c_minus_one = 10 \scan_stop: -\c_minus_one = -1 \scan_stop: -% -\tex_chardef:D \c_sixteen = 16\scan_stop: +\cs_set:Npn \use:n #1 {#1} +\cs_set:Npn \use:nn #1#2 {#1#2} +\cs_set:Npn \use:nnn #1#2#3 {#1#2#3} +\cs_set:Npn \use:nnnn #1#2#3#4 {#1#2#3#4} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % -% We provide two kinds of functions that can be used to define -% control sequences. On the one hand we have functions that check -% if their argument doesn't already exist, they are called -% |\..._new|. The second type of defining functions doesn't check -% if the argument is already defined. +% \begin{macro}{\use_i:nn} +% \begin{macro}{\use_ii:nn} +% These macros are needed to provide functions with true and false +% cases, as introduced by Michael some time ago. By using +% |\exp_after:wN| |\use_i:nn | |\else:| constructions it +% is possible to write code where the true or false case is able to +% access the following tokens from the input stream, which is not +% possible if the |\c_true_bool| syntax is used. +% \begin{macrocode} +\cs_set:Npn \use_i:nn #1#2 {#1} +\cs_set:Npn \use_ii:nn #1#2 {#2} +% \end{macrocode} +% \end{macro} +% \end{macro} % -% Before we can define them, we need some auxiliary macros that -% allow us to generate error messages. The definitions here are -% only temporary, they will be redefined later on. % -% \begin{macro}{\io_put_log:x} -% \begin{macro}{\io_put_term:x} -% We define a routine to write only to the log file. And a -% similar one for writing to both the log file and the terminal. % +% \begin{macro}{\use_i:nnn} +% \begin{macro}{\use_ii:nnn} +% \begin{macro}{\use_iii:nnn} +% \begin{macro}{\use_i:nnnn} +% \begin{macro}{\use_ii:nnnn} +% \begin{macro}{\use_iii:nnnn} +% \begin{macro}{\use_iv:nnnn} +% \begin{macro}{\use_i_ii:nnn} +% We also need something for picking up arguments from a longer +% list. % \begin{macrocode} -\def:Npn \io_put_log:x{ - \tex_immediate:D\io_put_deferred:Nx \c_minus_one } -\def:Npn \io_put_term:x{ - \tex_immediate:D\io_put_deferred:Nx \c_sixteen } +\cs_set:Npn \use_i:nnn #1#2#3{#1} +\cs_set:Npn \use_ii:nnn #1#2#3{#2} +\cs_set:Npn \use_iii:nnn #1#2#3{#3} +\cs_set:Npn \use_i:nnnn #1#2#3#4{#1} +\cs_set:Npn \use_ii:nnnn #1#2#3#4{#2} +\cs_set:Npn \use_iii:nnnn #1#2#3#4{#3} +\cs_set:Npn \use_iv:nnnn #1#2#3#4{#4} +\cs_set:Npn \use_i_ii:nnn #1#2#3{#1#2} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\err_latex_bug:x} -% This will show internal errors. +% \begin{macro}{\use_none_delimit_by_q_nil:w} +% \begin{macro}{\use_none_delimit_by_q_stop:w} +% \begin{macro}{\use_none_delimit_by_q_recursion_stop:w} +% Functions that gobble everything until they see either |\q_nil| or +% |\q_stop| resp. % \begin{macrocode} -\def:Npn\err_latex_bug:x#1{ - \io_put_term:x{This~is~a~LaTeX~bug!~Check~coding!}\tex_errmessage:D{#1}} +\cs_set:Npn \use_none_delimit_by_q_nil:w #1\q_nil{} +\cs_set:Npn \use_none_delimit_by_q_stop:w #1\q_stop{} +\cs_set:Npn \use_none_delimit_by_q_recursion_stop:w #1 \q_recursion_stop {} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\cs_record_meaning:N} -% This macro will be used later on for tracing purposes. But we -% need some more modules to define it, so we just give some dummy -% definition here. +% \begin{macro}{\use_i_delimit_by_q_nil:nw} +% \begin{macro}{\use_i_delimit_by_q_stop:nw} +% \begin{macro}{\use_i_delimit_by_q_recursion_stop:nw} +% Same as above but execute first argument after gobbling. Very +% useful when you need to skip the rest of a mapping sequence but +% want an easy way to control what should be expanded next. % \begin{macrocode} -%<*trace> -\def:Npn \cs_record_meaning:N#1{} -% +\cs_set:Npn \use_i_delimit_by_q_nil:nw #1#2\q_nil{#1} +\cs_set:Npn \use_i_delimit_by_q_stop:nw #1#2\q_stop{#1} +\cs_set:Npn \use_i_delimit_by_q_recursion_stop:nw #1#2 \q_recursion_stop {#1} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% % -% We need these two to make |\chk_new_cs:N| bulletproof. +% \begin{macro}{\use_i_after_fi:nw} +% \begin{macro}{\use_i_after_else:nw} +% \begin{macro}{\use_i_after_or:nw} +% \begin{macro}{\use_i_after_orelse:nw} +% Returns the first argument after ending the conditional. % \begin{macrocode} -\def_long:Npn \use_none:n #1{} -\def_long:Npn \use_arg_i:n #1{#1} -% \end{macrocode} -% \begin{macro}{\chk_new_cs:N} -% This command is called by |\def_new:Npn| and |\let_new:NN| etc.\ -% to make sure that the argument sequence is not already in use. If -% it is, an error is signalled. It checks if \m{csname} is -% undefined or |\scan_stop:|. Otherwise an error message is -% issued. We have to make sure we don't put the argument into the -% conditional processing since it may be an |\if...| type function! -% \begin {macrocode} -\def:Npn \chk_new_cs:N #1{ - \if:w \cs_if_free_p:N #1 - \exp_after:NN \use_none:n - \else: - \exp_after:NN \use_arg_i:n - \fi: - { - \err_latex_bug:x {Command~name~`\token_to_string:N #1'~ - already~defined!~ - Current~meaning:~\token_to_meaning:N #1 - } - } -%<*trace> - \cs_record_meaning:N#1 -% \io_put_term:x{Defining~\token_to_string:N #1~on~%} - \io_put_log:x{Defining~\token_to_string:N #1~on~ - line~\tex_the:D \tex_inputlineno:D} -% -} +\cs_set:Npn \use_i_after_fi:nw #1\fi:{\fi: #1} +\cs_set:Npn \use_i_after_else:nw #1\else:#2\fi:{\fi: #1} +\cs_set:Npn \use_i_after_or:nw #1\or: #2\fi: {\fi:#1} +\cs_set:Npn \use_i_after_orelse:nw #1 #2#3\fi: {\fi:#1} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % -% On 2005/11/20 Morten said: I think names for testing if a certain -% condition is true or false should always contain |if| to avoid -% confusion. This is what we do for lots of other types of test -% functions. For now I have defined both names for the functions -% checking names of control sequences. +% \subsection{Gobbling tokens from input} % -% \begin{macro}{\cs_if_exist_p:N} -% Expands into |\c_true| if the control sequence given as its -% argument \emph{is} in use. +% \begin{macro}{\use_none:n} +% \begin{macro}{\use_none:nn} +% \begin{macro}{\use_none:nnn} +% \begin{macro}{\use_none:nnnn} +% \begin{macro}{\use_none:nnnnn} +% \begin{macro}{\use_none:nnnnnn} +% \begin{macro}{\use_none:nnnnnnn} +% \begin{macro}{\use_none:nnnnnnnn} +% \begin{macro}{\use_none:nnnnnnnnn} +% To gobble tokens from the input we use a standard naming +% convention: the number of tokens gobbled is given by the number of +% |n|'s following the |:| in the name. Although defining +% |\use_none:nnn| and above as separate calls of |\use_none:n| and +% |\use_none:nn| is slightly faster, this is very non-intuitive to +% the programmer who will assume that expanding such a function once +% will take care of gobbling all the tokens in one go. % \begin{macrocode} -\def:Npn \cs_if_exist_p:N #1{ - \if:w \cs_if_free_p:N #1 - \c_false - \else: - \c_true \fi:} +\cs_set:Npn \use_none:n #1{} +\cs_set:Npn \use_none:nn #1#2{} +\cs_set:Npn \use_none:nnn #1#2#3{} +\cs_set:Npn \use_none:nnnn #1#2#3#4{} +\cs_set:Npn \use_none:nnnnn #1#2#3#4#5{} +\cs_set:Npn \use_none:nnnnnn #1#2#3#4#5#6{} +\cs_set:Npn \use_none:nnnnnnn #1#2#3#4#5#6#7{} +\cs_set:Npn \use_none:nnnnnnnn #1#2#3#4#5#6#7#8{} +\cs_set:Npn \use_none:nnnnnnnnn #1#2#3#4#5#6#7#8#9{} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\chk_if_exist_cs:N } -% \begin{macro}{\chk_if_exist_cs:c } -% This function issues a warning message when the control sequence -% in its argument does not exist. +% \subsection{Expansion control from l3expan} +% +% \begin{macro}{\exp_args:Nc} +% Moved here for now as it is going to be used right away. % \begin{macrocode} -\def:Npn \chk_if_exist_cs:N #1 { - \if:w \cs_if_exist_p:N #1 - \else: - \err_latex_bug:x{Command~ `\token_to_string:N #1'~ - not~ yet~ defined!} - \fi:} -\def:Npn \chk_if_exist_cs:c #1 { - \exp_after:NN \chk_if_exist_cs:N \cs:w #1\cs_end: } +\cs_set:Npn \exp_args:Nc #1#2{\exp_after:wN#1\cs:w#2\cs_end:} % \end{macrocode} % \end{macro} +% +% \subsection{Conditional processing and definitions} +% +% Underneath any predicate function (|_p|) or other conditional forms +% (|TF|, etc.) is a built-in logic saying that it after all of the +% testing and processing must return the \meta{state} this leaves +% \TeX\ in. Therefore, a simple user interface could be something like +% \begin{verbatim} +% \if_meaning:w #1#2 \prg_return_true: \else: +% \if_meaning:w #1#3 \prg_return_true: \else: +% \prg_return_false: +% \fi: \fi: +% \end{verbatim} +% Usually, a \TeX\ programmer would have to insert a number of +% |\exp_after:wN|s to ensure the state value is returned at exactly +% the point where the last conditional is finished. However, that +% obscures the code and forces the \TeX\ programmer to prove that +% he/she knows the $2^{n}-1$ table. We therefore provide the simpler +% interface. +% +% \begin{macro}{\prg_return_true:} +% \begin{macro}{\prg_return_false:} +% These break statements put \TeX\ in a \m{true} or \m{false} state. +% The idea is that the expansion of |\tex_romannumeral:D \c_zero| is +% \m{null} so we set off a |\tex_romannumeral:D|. It will on its +% way expand any |\else:| or |\fi:| that are waiting to be discarded +% anyway before finally arriving at the |\c_zero| we will place +% right after the conditional. After this expansion has terminated, +% we issue either |\if_true:| or |\if_false:| to put \TeX\ in the +% correct state. +% \begin{macrocode} +\cs_set:Npn \prg_return_true: { \exp_after:wN\if_true:\tex_romannumeral:D } +\cs_set:Npn \prg_return_false: {\exp_after:wN\if_false:\tex_romannumeral:D } +% \end{macrocode} +% An extended state space could instead utilize |\tex_ifcase:D|: +% \begin{verbatim} +% \cs_set:Npn \prg_return_true: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_zero \tex_romannumeral:D +% } +% \cs_set:Npn \prg_return_false: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_one \tex_romannumeral:D +% } +% \cs_set:Npn \prg_return_error: { +% \exp_after:wN\tex_ifcase:D \exp_after:wN \c_two \tex_romannumeral:D +% } +% \end{verbatim} +% \end{macro} % \end{macro} % -% \begin{macro}{\cs_if_free_p:N} -% Expands into |\c_true| if the control sequence given as its -% argument is not yet in use. Note that we make sure to expand -% into |\c_false| if the control sequence is textually -% |\c_undefined| or |\scan_stop:|, so that we don't end up -% (re)defining them. +% \begin{macro}{\prg_set_conditional:Npnn,\prg_new_conditional:Npnn, +% \prg_set_protected_conditional:Npnn,\prg_new_protected_conditional:Npnn} +% The user functions for the types using parameter text from the +% programmer. Call aux function to grab parameters, split the base +% function into name and signature and then use, e.g., |\cs_set:Npn| +% to define it with. % \begin{macrocode} -\def:Npn \cs_if_free_p:N #1{ - \if_cs_exist:N #1 - \if_meaning:NN#1\scan_stop: - \if:w\cs_if_eq_name_p:NN #1\scan_stop: - \c_false \else: \c_true \fi: - \else: - \c_false - \fi: - \else: - \if:w \cs_if_eq_name_p:NN #1\c_undefined - \c_false \else: \c_true \fi: - \fi: +\cs_set:Npn \prg_set_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set:Npn {parm} + } +} +\cs_set:Npn \prg_new_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new:Npn {parm} + } +} +\cs_set:Npn \prg_set_protected_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set_protected:Npn {parm} + } +} +\cs_set:Npn \prg_new_protected_conditional:Npnn #1{ + \prg_get_parm_aux:nw{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new_protected:Npn {parm} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prg_set_conditional:Nnn,\prg_new_conditional:Nnn, +% \prg_set_protected_conditional:Nnn,\prg_new_protected_conditional:Nnn} +% The user functions for the types automatically inserting the +% correct parameter text based on the signature. Call aux function +% after calculating number of arguments, split the base function +% into name and signature and then use, e.g., |\cs_set:Npn| to +% define it with. +% \begin{macrocode} +\cs_set:Npn \prg_set_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} +\cs_set:Npn \prg_new_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} + +\cs_set:Npn \prg_set_protected_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_set_protected:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} +} + +\cs_set:Npn \prg_new_protected_conditional:Nnn #1{ + \exp_args:Nnf \prg_get_count_aux:nn{ + \cs_split_function:NN #1 \prg_generate_conditional_aux:nnNNnnnn + \cs_new_protected:Npn {count} + }{\cs_get_arg_count_from_signature:N #1} } -\let:NwN \cs_free_p:N \cs_if_free_p:N % \end{macrocode} % \end{macro} % -% -% \begin{macro}{\str_if_eq_p:nn} -% \begin{macro}{\str_if_eq_p_aux:w} -% Takes 2 lists of characters as arguments and expands into -% |\c_true| if they are equal, and |\c_false| otherwise. Note that -% in the current implementation spaces in these strings are -% ignored.\footnote{This is a function which could use -% \cs{tlist_compare:xx}.} +% \begin{macro}[aux]{\prg_get_parm_aux:nw,\prg_get_count_aux:nn} +% For the "Npnn" type we must grab the parameter text before +% continuing. We make this a very generic function that takes one +% argument before reading everything up to a left brace. Something +% similar for the "Nnn" type. % \begin{macrocode} -\def:Npn \str_if_eq_p:nn #1#2{ - \str_if_eq_p_aux:w #1\scan_stop:\\#2\scan_stop:\\ -} -\def:Npn \str_if_eq_p_aux:w #1#2\\#3#4\\{ - \if_meaning:NN#1#3 - \if_meaning:NN#1\scan_stop:\c_true \else: - \if_meaning:NN#3\scan_stop:\c_false \else: - \str_if_eq_p_aux:w #2\\#4\\\fi:\fi: - \else:\c_false \fi:} +\cs_set:Npn \prg_get_count_aux:nn #1#2 {#1{#2}} +\cs_set:Npn \prg_get_parm_aux:nw #1#2#{#1{#2}} % \end{macrocode} % \end{macro} -% \end{macro} +% \begin{macro}[aux]{\prg_generate_conditional_parm_aux:nnNNnnnn, +% \prg_generate_conditional_parm_aux:nw} % -% \begin{macro}{\cs_if_eq_name_p:NN} -% An application of the above function, already streamlined for -% speed, so I put it in here. It takes two control sequences as -% arguments and expands into true iff they have the same name. -% We make it long in case one of them is |\par|! +% The workhorse here is going through a list of desired forms, i.e., +% p, TF, T and F. The first three arguments come from splitting up +% the base form of the conditional, which gives the name, signature +% and a boolean to signal whether or not there was a colon in the +% name. For the time being, we do not use this piece of information +% but could well throw an error. The fourth argument is how to +% define this function, the fifth is the text "parm" or "count" for +% which version to use to define the functions, the sixth is the +% parameters to use (possibly empty) or number of arguments, the +% seventh is the list of forms to define, the eight is the +% replacement text which we will augment when defining the forms. % \begin{macrocode} -\def_long:Npn \cs_if_eq_name_p:NN #1#2{ - \exp_after:NN\exp_after:NN - \exp_after:NN\str_if_eq_p_aux:w - \exp_after:NN\token_to_string:N - \exp_after:NN#1 - \exp_after:NN\scan_stop: - \exp_after:NN\\ - \token_to_string:N#2\scan_stop:\\} +\cs_set:Npn \prg_generate_conditional_aux:nnNNnnnn #1#2#3#4#5#6#7#8{ + \prg_generate_conditional_aux:nnw{#5}{ + #4{#1}{#2}{#6}{#8} + }#7,?, \q_recursion_stop +} +% \end{macrocode} +% Looping through the list of desired forms. First is the text "parm" +% or "count", second is five arguments packed together and third is +% the form. Use text and form to call the correct type. +% \begin{macrocode} +\cs_set:Npn \prg_generate_conditional_aux:nnw #1#2#3,{ + \if:w ?#3 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + \use:c{prg_generate_#3_form_#1:Nnnnn} #2 + \prg_generate_conditional_aux:nnw{#1}{#2} +} % \end{macrocode} % \end{macro} % +% \begin{macro}[aux]{\prg_generate_p_form_parm:Nnnnn, +% \prg_generate_TF_form_parm:Nnnnn, +% \prg_generate_T_form_parm:Nnnnn, +% \prg_generate_F_form_parm:Nnnnn +% } +% How to generate the various forms. The "parm" types here takes the +% following arguments: 1: how to define (an N-type), 2: name, 3: +% signature, 4: parameter text (or empty), 5: replacement. +% \begin{macrocode} +\cs_set:Npn \prg_generate_p_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc #1 {#2_p:#3}#4{#5 \c_zero + \exp_after:wN\c_true_bool\else:\exp_after:wN\c_false_bool\fi: + } +} +\cs_set:Npn \prg_generate_TF_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3TF}#4{#5 \c_zero + \exp_after:wN \use_i:nn \else: \exp_after:wN \use_ii:nn \fi: + } +} +\cs_set:Npn \prg_generate_T_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3T}#4{#5 \c_zero + \else:\exp_after:wN\use_none:nn\fi:\use:n + } +} +\cs_set:Npn \prg_generate_F_form_parm:Nnnnn #1#2#3#4#5{ + \exp_args:Nc#1 {#2:#3F}#4{#5 \c_zero + \exp_after:wN\use_none:nn\fi:\use:n + } +} +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\str_if_eq_var_p:nf} -% \begin{macro}{\str_if_eq_var_start:nnN} -% \begin{macro}{\str_if_eq_var_stop:w} -% A variant of |\str_if_eq_p:nn| which has the advantage of obeying -% spaces in at least the second argument. See \textsf{l3quark} for -% an application. From the hand of David Kastrup with slight -% modifications to make it fit with the remainder of the expl3 -% language. -% -% The macro builds a string of |\if:w \fi:| pairs from the first -% argument. The idea is to turn the comparison of |ab| and |cde| -% into -% \begin{verbatim} -% \tex_number:D -% \if:w \scan_stop: \if:w b\if:w a cde\scan_stop: '\fi: \fi: \fi: -% 13 -% \end{verbatim} -% The |'| is important here. If all tests are true, the |'| is read -% as part of the number in which case the returned number is |13| in -% octal notation so |\tex_number:D| returns |11|. If one test -% returns false the |'| is never seen and then we get just |13|. We -% wrap the whole process in an external |\if:w| in order to make it -% return either |\c_true| or |\c_false| since some parts of -% \textsf{l3prg} expect a predicate to return one of these two -% tokens. +% \begin{macro}[aux]{\prg_generate_p_form_count:Nnnnn, +% \prg_generate_TF_form_count:Nnnnn, +% \prg_generate_T_form_count:Nnnnn, +% \prg_generate_F_form_count:Nnnnn +% } +% How to generate the various forms. The "count" types here use a +% number to insert the correct parameter text, otherwise like the +% "parm" functions above. % \begin{macrocode} -\def:Npn \str_if_eq_var_p:nf#1{ - \if:w \tex_number:D\str_if_eq_var_start:nnN{}{}#1\scan_stop: +\cs_set:Npn \prg_generate_p_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2_p:#3} #1 {#4}{#5 \c_zero + \exp_after:wN\c_true_bool\else:\exp_after:wN\c_false_bool\fi: + } } -\def:Npn\str_if_eq_var_start:nnN#1#2#3{ - \if:w#3\scan_stop:\exp_after:NN\str_if_eq_var_stop:w\fi: - \str_if_eq_var_start:nnN{\if:w#3#1}{#2\fi:} +\cs_set:Npn \prg_generate_TF_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3TF} #1 {#4}{#5 \c_zero + \exp_after:wN\use_i:nn\else:\exp_after:wN\use_ii:nn\fi: + } } -\def:Npn\str_if_eq_var_stop:w\str_if_eq_var_start:nnN#1#2#3{ - #1#3\scan_stop:'#213~\c_true\else:\c_false\fi: +\cs_set:Npn \prg_generate_T_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3T} #1 {#4}{#5 \c_zero + \else:\exp_after:wN\use_none:nn\fi:\use:n + } +} +\cs_set:Npn \prg_generate_F_form_count:Nnnnn #1#2#3#4#5{ + \cs_generate_from_arg_count:cNnn {#2:#3F} #1 {#4}{#5 \c_zero + \exp_after:wN\use_none:nn\fi:\use:n + } } % \end{macrocode} % \end{macro} +% +% All that is left is to define the canonical boolean true and false. +% I think Michael originated the idea of expandable boolean tests. At +% first these were supposed to expand into either \texttt{TT} or +% \texttt{TF} to be tested using |\if:w| but this was later changed to +% \texttt{00} and \texttt{01}, so they could be used in logical +% operations. Later again they were changed to being numerical +% constants with values of $1$ for true and $0$ for false. We need +% this from the get-go. +% +% \begin{macro}{\c_true_bool} +% \begin{macro}{\c_false_bool} +% Here are the canonical boolean values. +% \begin{macrocode} +\tex_chardef:D \c_true_bool = 1~ +\tex_chardef:D \c_false_bool = 0~ +% \end{macrocode} % \end{macro} % \end{macro} % % +% \subsection{Dissecting a control sequence} % -% -% \subsubsection{More new definitions} +% \begin{macro}{\cs_to_str:N} +% \begin{macro}[aux]{\cs_to_str_aux:w} +% This converts a control sequence into the character string of its +% name, removing the leading escape character. This turns out to be +% a non-trivial matter as there a different cases: +% \begin{itemize} +% \item The usual case of a printable escape character; +% \item the case of a non-printable escape characters, e.g., when +% the value of |\tex_escapechar:D| is negative; +% \item when the escape character is a space. +% \end{itemize} +% The route chosen is this: If |\token_to_str:N \a| produces a +% non-space escape char, then this will produce two tokens. If the +% escape char is non-printable, only one token is produced. If the +% escape char is a space, then a space token plus one token +% character token is produced. If we augment the result of this +% expansion with the letters |ax| we get the following three +% scenarios (with \meta{X} being a printable non-space escape +% character): +% \begin{itemize} +% \item \meta{X}"aax" +% \item "aax" +% \item " aax" +% \end{itemize} +% In the second and third case, putting an auxiliary function in front +% reading undelimited arguments will treat them the same, removing the +% space token for us automatically. Therefore, if we test the second +% and third argument of what such a function reads, in case 1 we will +% get true and in cases 2 and 3 we will get false. If we choose to +% optimize for the usual case of a printable escape char, we can do it +% like this (again getting TeX to remove the leading space for us): +% \begin{macrocode} +\cs_set_nopar:Npn \cs_to_str:N { + \if:w \exp_after:wN \cs_str_aux:w\token_to_str:N \a ax\q_nil + \else: + \exp_after:wN \exp_after:wN\exp_after:wN \use_ii:nn + \fi: + \exp_after:wN \use_none:n \token_to_str:N +} +\cs_set:Npn \cs_str_aux:w #1#2#3#4\q_nil{#2#3} +% \end{macrocode} +% \end{macro} +% \end{macro} % % +% \begin{macro}{\cs_split_function:NN} +% \begin{macro}[aux]{\cs_split_function_aux:w} +% \begin{macro}[aux]{\cs_split_function_auxii:w} +% This function takes a function name and splits it into name with +% the escape char removed and argument specification. In addition to +% this, a third argument, a boolean \m{true} or \m{false} is +% returned with \m{true} for when there is a colon in the function +% and \m{false} if there is not. Lastly, the second argument of +% |\cs_split_function:NN| is supposed to be a function +% taking three variables, one for name, one for signature, and one +% for the boolean. For example, +% "\cs_split_function:NN\foo_bar:cnx\use_i:nnn" as input +% becomes "\use_i:nnn {foo_bar}{cnx}\c_true_bool". % -% \begin{macro}{\def_new:Npn} -% \begin{macro}{\def_new:Npx} -% \begin{macro}{\def_long_new:Npn} -% \begin{macro}{\def_long_new:Npx} -% \begin{macro}{\def_protected_new:Npn} -% \begin{macro}{\def_protected_new:Npx} -% \begin{macro}{\def_protected_long_new:Npn} -% \begin{macro}{\def_protected_long_new:Npx} -% These are like |\def:Npn| and |\let:NN|, but they first check that -% the argument command is not already in use. You may use -% |\pref_global:D|, |\pref_long:D|, |\pref_protected:D|, and -% |\tex_outer:D| as prefixes. -% \begin {macrocode} -\def_protected:Npn \def_new:Npn #1{\chk_new_cs:N #1 - \def:Npn #1} -\def_protected:Npn \def_new:Npx #1{\chk_new_cs:N #1 - \def:Npx #1} -\def_protected:Npn \def_long_new:Npn #1{\chk_new_cs:N #1 - \def_long:Npn #1} -\def_protected:Npn \def_long_new:Npx #1{\chk_new_cs:N #1 - \def_long:Npx #1} -\def_protected:Npn \def_protected_new:Npn #1{\chk_new_cs:N #1 - \def_protected:Npn #1} -\def_protected:Npn \def_protected_new:Npx #1{\chk_new_cs:N #1 - \def_protected:Npx #1} -\def_protected:Npn \def_protected_long_new:Npn #1{\chk_new_cs:N #1 - \def_protected_long:Npn #1} -\def_protected:Npn \def_protected_long_new:Npx #1{\chk_new_cs:N #1 - \def_protected_long:Npx #1} +% Can't use a literal ":" because it has the wrong catcode here, so +% it's transformed from "@" with "\tex_lowercase:D". +% \begin{macrocode} +\group_begin: + \tex_lccode:D `\@ = `\: \scan_stop: + \tex_catcode:D `\@ = 12~ +\tex_lowercase:D { + \group_end: +% \end{macrocode} +% First ensure that we actually get a properly evaluated str as we +% don't know how many expansions |\cs_to_str:N| requires. Insert +% extra colon to catch the error cases. +% \begin{macrocode} +\cs_set:Npn \cs_split_function:NN #1#2{ + \exp_after:wN \cs_split_function_aux:w + \tex_romannumeral:D -`\q \cs_to_str:N #1 @a \q_nil #2 +} +% \end{macrocode} +% If no colon in the name, |#2| is |a| with catcode 11 and |#3| is +% empty. If colon in the name, then either |#2| is a colon or the +% first letter of the signature. The letters here have catcode 12. +% If a colon was given we need to a) split off the colon and quark at +% the end and b) ensure we return the name, signature and boolean true +% We can't use |\quark_if_no_value:NTF| yet but this is very safe +% anyway as all tokens have catcode~12. +% \begin{macrocode} +\cs_set:Npn \cs_split_function_aux:w #1@#2#3\q_nil#4{ + \if_meaning:w a#2 + \exp_after:wN \use_i:nn + \else: + \exp_after:wN\use_ii:nn + \fi: + {#4{#1}{}\c_false_bool} + {\cs_split_function_auxii:w#2#3\q_nil #4{#1}} +} +\cs_set:Npn \cs_split_function_auxii:w #1@a\q_nil#2#3{ + #2{#3}{#1}\c_true_bool +} +% \end{macrocode} +% End of lowercase +% \begin{macrocode} +} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\gdef_new:Npn} -% \begin{macro}{\gdef_new:Npx} -% \begin{macro}{\gdef_long_new:Npn} -% \begin{macro}{\gdef_long_new:Npx} -% \begin{macro}{\gdef_protected_new:Npn} -% \begin{macro}{\gdef_protected_new:Npx} -% \begin{macro}{\gdef_protected_long_new:Npn} -% \begin{macro}{\gdef_protected_long_new:Npx} -% Global versions of the above functions. -% \begin {macrocode} -\def_protected_new:Npn \gdef_new:Npn #1{\chk_new_cs:N #1 - \gdef:Npn #1} -\def_protected_new:Npn \gdef_new:Npx #1{\chk_new_cs:N #1 - \gdef:Npx #1} -\def_protected_new:Npn \gdef_long_new:Npn #1{\chk_new_cs:N #1 - \gdef_long:Npn #1} -\def_protected_new:Npn \gdef_long_new:Npx #1{\chk_new_cs:N #1 - \gdef_long:Npx #1} -\def_protected_new:Npn \gdef_protected_new:Npn #1{\chk_new_cs:N #1 - \gdef_protected:Npn #1} -\def_protected_new:Npn \gdef_protected_new:Npx #1{\chk_new_cs:N #1 - \gdef_protected:Npx #1} -\def_protected_new:Npn \gdef_protected_long_new:Npn #1{\chk_new_cs:N #1 - \gdef_protected_long:Npn #1} -\def_protected_new:Npn \gdef_protected_long_new:Npx #1{\chk_new_cs:N #1 - \gdef_protected_long:Npx #1} +% \begin{macro}{\cs_get_function_name:N, \cs_get_function_signature:N } +% Now returning the name is trivial: just discard the last two +% arguments. Similar for signature. +% \begin{macrocode} +\cs_set:Npn \cs_get_function_name:N #1 { + \cs_split_function:NN #1\use_i:nnn +} +\cs_set:Npn \cs_get_function_signature:N #1 { + \cs_split_function:NN #1\use_ii:nnn +} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % +% \subsection{Exist or free} % -% \begin{macro}{\def:cpn} -% \begin{macro}{\def:cpx} -% \begin{macro}{\gdef:cpn} -% \begin{macro}{\gdef:cpx} -% \begin{macro}{\def_new:cpn} -% \begin{macro}{\def_new:cpx} -% \begin{macro}{\gdef_new:cpn} -% \begin{macro}{\gdef_new:cpx} -% Like |\def:Npn| and |\def_new:Npn|, except that the first argument -% consists of the sequence of characters that should be used to form -% the name of the desired control sequence (the |c| stands for -% csname argument, see the expansion module.). Global versions are -% also provided. +% A control sequence is said to \emph{exist} (to be used) if has an entry in +% the hash table and its meaning is different from the primitive +% "\tex_relax:D" token. A control sequence is said to be \emph{free} +% (to be defined) if it does not already exist and also meets the +% requirement that it does not contain a "D" signature. The reasoning +% behind this is that most of the time, a check for a free control +% sequence is when we wish to make a new control sequence and we do +% not want to let the user define a new ``do not use'' control +% sequence. % -% |\def:cpn|\m{string}\m{rep-text} will turn \m{string} into a -% csname and then assign \m {rep-text} to it by using |\def:Npn|. -% This means that there might be a parameter string between the two -% arguments. +% \begin{macro}{\cs_if_exist_p:N,\cs_if_exist_p:c} +% \begin{macro}[TF]{\cs_if_exist:N,\cs_if_exist:c} +% Two versions for checking existence. For the "N" form we firstly +% check for "\tex_relax:D" and then if it is in the hash +% table. There is no problem when inputting something like "\else:" +% or "\fi:" as \TeX\ will only ever skip input in case the token +% tested against is "\tex_relax:D". % \begin{macrocode} -\def_new:Npn \def:cpn #1{\exp_after:NN \def:Npn \cs:w #1\cs_end:} -\def_new:Npn \def:cpx #1{\exp_after:NN \def:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef:cpn #1{\exp_after:NN \gdef:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef:cpx #1{\exp_after:NN \gdef:Npx \cs:w #1\cs_end:} -\def_new:Npn \def_new:cpn #1{\exp_after:NN \def_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_new:cpx #1{\exp_after:NN \def_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_new:cpn #1{\exp_after:NN \gdef_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_new:cpx #1{\exp_after:NN \gdef_new:Npx \cs:w #1\cs_end:} +\prg_set_conditional:Npnn \cs_if_exist:N #1 {p,TF,T,F}{ + \if_meaning:w #1\tex_relax:D + \prg_return_false: + \else: + \if_cs_exist:N #1 + \prg_return_true: + \else: + \prg_return_false: + \fi: + \fi: +} +% \end{macrocode} +% For the "c" form we firstly check if it is in the hash table and +% then for "\tex_relax:D" so that we do not add it to the hash table +% unless it was already there. Here we have to be careful as the text +% to be skipped if the first test is false may contain tokens that +% disturb the scanner. Therefore, we ensure that the second test is +% performed after the first one has concluded completely. +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_exist:c #1 {p,TF,T,F}{ + \if_cs_exist:w #1 \cs_end: + \exp_after:wN \use_i:nn + \else: + \exp_after:wN \use_ii:nn + \fi: + { + \exp_after:wN \if_meaning:w \cs:w #1\cs_end: \tex_relax:D + \prg_return_false: + \else: + \prg_return_true: + \fi: + } + \prg_return_false: +} % \end{macrocode} % \end{macro} % \end{macro} +% +% \begin{macro}{\cs_if_do_not_use_p:N} +% \begin{macro}[aux]{\cs_if_do_not_use_aux:nnN} +% \begin{macrocode} +\cs_set:Npn \cs_if_do_not_use_p:N #1{ + \cs_split_function:NN #1 \cs_if_do_not_use_aux:nnN +} +\cs_set:Npn \cs_if_do_not_use_aux:nnN #1#2#3{ + \exp_after:wN\str_if_eq_p:nn \token_to_str:N D {#2} +} +% \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} +% +% \begin{macro}{\cs_if_free_p:N,\cs_if_free_p:c} +% \begin{macro}[TF]{\cs_if_free:N,\cs_if_free:c} +% The simple implementation is one using the boolean expression +% parser: If it is exists or is do not use, then return false. +% \begin{verbatim} +% \prg_set_conditional:Npnn \cs_if_free:N #1{p,TF,T,F}{ +% \bool_if:nTF {\cs_if_exist_p:N #1 || \cs_if_do_not_use_p:N #1} +% {\prg_return_false:}{\prg_return_true:} +% } +% \end{verbatim} +% However, this functionality may not be available this early on. We +% do something similar: The numerical values of true and false is one +% and zero respectively, which we can use. The problem again here is +% that the token we are checking may in fact be something that can +% disturb the scanner, so we have to be careful. We would like to do +% minimal evaluation so we ensure this. +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_free:N #1{p,TF,T,F}{ + \tex_ifnum:D \cs_if_exist_p:N #1 =\c_zero + \exp_after:wN \use_i:nn + \else: + \exp_after:wN \use_ii:nn + \fi: + { + \tex_ifnum:D \cs_if_do_not_use_p:N #1 =\c_zero + \prg_return_true: + \else: + \prg_return_false: + \fi: + } + \prg_return_false: +} +\cs_set_nopar:Npn \cs_if_free_p:c{\exp_args:Nc\cs_if_free_p:N} +\cs_set_nopar:Npn \cs_if_free:cTF{\exp_args:Nc\cs_if_free:NTF} +\cs_set_nopar:Npn \cs_if_free:cT{\exp_args:Nc\cs_if_free:NT} +\cs_set_nopar:Npn \cs_if_free:cF{\exp_args:Nc\cs_if_free:NF} +% \end{macrocode} % \end{macro} % \end{macro} % % +% \subsection{Defining and checking (new) functions} % -% \begin{macro}{\def_long:cpn} -% \begin{macro}{\def_long:cpx} -% \begin{macro}{\gdef_long:cpn} -% \begin{macro}{\gdef_long:cpx} -% \begin{macro}{\def_long_new:cpn} -% \begin{macro}{\def_long_new:cpx} -% \begin{macro}{\gdef_long_new:cpn} -% \begin{macro}{\gdef_long_new:cpx} -% Variants of the |\def_long:Npn| versions which make a csname out -% of the first arguments. We may also do this globally. +% \begin{macro}{\c_minus_one} +% \begin{macro}{\c_zero} +% \begin{macro}{\c_sixteen} +% We need the constants |\c_minus_one| and |\c_sixteen| now for +% writing information to the log and the terminal and |\c_zero| +% which is used by some functions in the \textsf{l3num}module. The +% rest are defined in the \textsf{l3int} module -- at least for the +% ones that can be defined with |\tex_chardef:D| or +% |\tex_mathchardef:D|. For other constants the \textsf{l3int} module is +% required but it can't be used until the allocation has been set +% up properly! The actual allocation mechanism is in +% \textsf{l3alloc} and as \TeX{} wants to reserve count registers +% 0--9, the first available one is~10 so we use that for +% |\c_minus_one|. % \begin{macrocode} -\def_new:Npn \def_long:cpn #1{\exp_after:NN \def_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_long:cpx #1{ - \exp_after:NN\def_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_long:cpn #1{ - \exp_after:NN \gdef_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_long:cpx #1{ - \exp_after:NN\gdef_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_long_new:cpn #1{ - \exp_after:NN \def_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_long_new:cpx #1{ - \exp_after:NN \def_long_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_long_new:cpn #1{ - \exp_after:NN \gdef_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_long_new:cpx #1{ - \exp_after:NN \gdef_long_new:Npx \cs:w #1\cs_end:} +%<*!initex> +\cs_set_eq:NwN \c_minus_one\m@ne +% +%<*!package> +\tex_countdef:D \c_minus_one = 10 ~ +\c_minus_one = -1 ~ +% +\tex_chardef:D \c_sixteen = 16~ +\tex_chardef:D \c_zero = 0~ % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_protected:cpn} -% \begin{macro}{\def_protected:cpx} -% \begin{macro}{\gdef_protected:cpn} -% \begin{macro}{\gdef_protected:cpx} -% \begin{macro}{\def_protected_new:cpn} -% \begin{macro}{\def_protected_new:cpx} -% \begin{macro}{\gdef_protected_new:cpn} -% \begin{macro}{\gdef_protected_new:cpx} -% Variants of the |\def_protected:Npn| versions which make a csname -% out of the first arguments. We may also do this globally. +% We provide two kinds of functions that can be used to define +% control sequences. On the one hand we have functions that check +% if their argument doesn't already exist, they are called +% |\..._new|. The second type of defining functions doesn't check +% if the argument is already defined. +% +% Before we can define them, we need some auxiliary macros that +% allow us to generate error messages. The definitions here are +% only temporary, they will be redefined later on. +% +% \begin{macro}{\iow_log:x} +% \begin{macro}{\iow_term:x} +% We define a routine to write only to the log file. And a +% similar one for writing to both the log file and the terminal. +% % \begin{macrocode} -\def_new:Npn \def_protected:cpn #1{ - \exp_after:NN \def_protected:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected:cpx #1{ - \exp_after:NN\def_protected:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_protected:cpn #1{ - \exp_after:NN \gdef_protected:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected:cpx #1{ - \exp_after:NN\gdef_protected:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_protected_new:cpn #1{ - \exp_after:NN \def_protected_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_new:cpx #1{ - \exp_after:NN \def_protected_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_new:cpn #1{ - \exp_after:NN \gdef_protected_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_new:cpx #1{ - \exp_after:NN \gdef_protected_new:Npx \cs:w #1\cs_end:} +\cs_set_nopar:Npn \iow_log:x { + \tex_immediate:D \iow_shipout_x:Nn \c_minus_one +} +\cs_set_nopar:Npn \iow_term:x { + \tex_immediate:D \iow_shipout_x:Nn \c_sixteen +} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_protected_long:cpn} -% \begin{macro}{\def_protected_long:cpx} -% \begin{macro}{\gdef_protected_long:cpn} -% \begin{macro}{\gdef_protected_long:cpx} -% \begin{macro}{\def_protected_long_new:cpn} -% \begin{macro}{\def_protected_long_new:cpx} -% \begin{macro}{\gdef_protected_long_new:cpn} -% \begin{macro}{\gdef_protected_long_new:cpx} -% Variants of the |\def_protected_long:Npn| versions which make a csname -% out of the first arguments. We may also do this globally. +% \begin{macro}{\msg_kernel_bug:x} +% This will show internal errors. % \begin{macrocode} -\def_new:Npn \def_protected_long:cpn #1{ - \exp_after:NN \def_protected_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_long:cpx #1{ - \exp_after:NN\def_protected_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long:cpn #1{ - \exp_after:NN \gdef_protected_long:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long:cpx #1{ - \exp_after:NN\gdef_protected_long:Npx\cs:w #1\cs_end:} -\def_new:Npn \def_protected_long_new:cpn #1{ - \exp_after:NN \def_protected_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \def_protected_long_new:cpx #1{ - \exp_after:NN \def_protected_long_new:Npx \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long_new:cpn #1{ - \exp_after:NN \gdef_protected_long_new:Npn \cs:w #1\cs_end:} -\def_new:Npn \gdef_protected_long_new:cpx #1{ - \exp_after:NN \gdef_protected_long_new:Npx \cs:w #1\cs_end:} +\cs_set_nopar:Npn \msg_kernel_bug:x #1 { + \iow_term:x { This~is~a~LaTeX~bug:~check~coding! } + \tex_errmessage:D {#1} +} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% -% \begin{macro}{\def_aux_0:NNn} -% \begin{macro}{\def_aux_1:NNn} -% \begin{macro}{\def_aux_2:NNn} -% \begin{macro}{\def_aux_3:NNn} -% \begin{macro}{\def_aux_4:NNn} -% \begin{macro}{\def_aux_5:NNn} -% \begin{macro}{\def_aux_6:NNn} -% \begin{macro}{\def_aux_7:NNn} -% \begin{macro}{\def_aux_8:NNn} -% \begin{macro}{\def_aux_9:NNn} -% \begin{macro}{\def_aux:NNnn} -% \begin{macro}{\def_aux:Ncnn} -% \begin{macro}{\def_arg_number_error_msg:Nn} -% Defining a function with $n$ arguments. First some helper functions. +% \begin{macro}{\cs_record_meaning:N} +% This macro will be used later on for tracing purposes. But we +% need some more modules to define it, so we just give some dummy +% definition here. % \begin{macrocode} -\def_new:cpn {def_aux_0:NNn} #1#2 {#1 #2 } -\def_new:cpn {def_aux_1:NNn} #1#2 {#1 #2 ##1 } -\def_new:cpn {def_aux_2:NNn} #1#2 {#1 #2 ##1##2 } -\def_new:cpn {def_aux_3:NNn} #1#2 {#1 #2 ##1##2##3 } -\def_new:cpn {def_aux_4:NNn} #1#2 {#1 #2 ##1##2##3##4 } -\def_new:cpn {def_aux_5:NNn} #1#2 {#1 #2 ##1##2##3##4##5 } -\def_new:cpn {def_aux_6:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6 } -\def_new:cpn {def_aux_7:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7 } -\def_new:cpn {def_aux_8:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8 } -\def_new:cpn {def_aux_9:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8##9 } +%<*trace> +\cs_set:Npn \cs_record_meaning:N #1{} +% % \end{macrocode} -% Then the function itself which checks for the existance of such a -% helper function. If it doesn't exist, return an error. Otherwise -% call it to define \verb|#2| with the correct number of arguments. -% \begin{macrocode} -\def_protected_long_new:Npn \def_aux:NNnn #1#2#3#4 { - \cs_if_really_exist:cTF {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} - { - \cs_use:c {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} #1 #2 {#4} +% \end{macro} +% +% \begin{macro}{\chk_if_free_cs:N} +% This command is called by |\cs_new_nopar:Npn| and |\cs_new_eq:NN| etc.\ +% to make sure that the argument sequence is not already in use. If +% it is, an error is signalled. It checks if \m{csname} is +% undefined or |\scan_stop:|. Otherwise an error message is +% issued. We have to make sure we don't put the argument into the +% conditional processing since it may be an |\if...| type function! +% \begin {macrocode} +\cs_set_nopar:Npn \chk_if_free_cs:N #1{ + \cs_if_free:NF #1 + { + \msg_kernel_bug:x {Command~name~`\token_to_str:N #1'~ + already~defined!~ + Current~meaning:~\token_to_meaning:N #1 + } } - { \def_arg_number_error_msg:Nn #2{#3} } +%<*trace> + \cs_record_meaning:N#1 +% \iow_term:x{Defining~\token_to_str:N #1~on~%} + \iow_log:x{Defining~\token_to_str:N #1~on~ + line~\tex_the:D \tex_inputlineno:D} +% } -\def_new:Npn \def_aux:Ncnn #1#2{ - \exp_after:NN \def_aux:NNnn \exp_after:NN #1 \cs:w #2\cs_end:} % \end{macrocode} -% The error message. +% \end{macro} +% +% \begin{macro}{\chk_if_exist_cs:N } +% \begin{macro}{\chk_if_exist_cs:c } +% This function issues a warning message when the control sequence +% in its argument does not exist. % \begin{macrocode} -\def_new:Npn \def_arg_number_error_msg:Nn #1#2 { - \err_latex_bug:x{ - You're~ trying~ to~ define~ the~ command~ `\token_to_string:N #1'~ - with~ \use_arg_i:n{\tex_the:D\etex_numexpr:D #2\scan_stop:} ~ - arguments~ but~ I~ only~ allow~ 0-9~ arguments.~ I~ can~ probably~ - not~ help~ you~ here - } +\cs_set_nopar:Npn \chk_if_exist_cs:N #1 { + \cs_if_exist:NF #1 + { + \msg_kernel_bug:x {Command~ `\token_to_str:N #1'~ + not~ yet~ defined!} + } } +\cs_set_nopar:Npn \chk_if_exist_cs:c {\exp_args:Nc \chk_if_exist_cs:N } % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_aux_use_0_parameter:} -% \begin{macro}{\def_aux_use_1_parameter:} -% \begin{macro}{\def_aux_use_2_parameter:} -% \begin{macro}{\def_aux_use_3_parameter:} -% \begin{macro}{\def_aux_use_4_parameter:} -% \begin{macro}{\def_aux_use_5_parameter:} -% \begin{macro}{\def_aux_use_6_parameter:} -% \begin{macro}{\def_aux_use_7_parameter:} -% \begin{macro}{\def_aux_use_8_parameter:} -% \begin{macro}{\def_aux_use_9_parameter:} -% Something similar to |\def_aux_9:NNn| but for using the -% parameters. +% +% \begin{macro}{\str_if_eq_p:nn} +% \begin{macro}[aux]{\str_if_eq_p_aux:w} +% Takes 2 lists of characters as arguments and expands into +% |\c_true_bool| if they are equal, and |\c_false_bool| otherwise. Note that +% in the current implementation spaces in these strings are +% ignored.\footnote{This is a function which could use +% \cs{tlist_compare:xx}.} % \begin{macrocode} -\def:cpn{def_aux_use_0_parameter:}{} -\def:cpn{def_aux_use_1_parameter:}{{##1}} -\def:cpn{def_aux_use_2_parameter:}{{##1}{##2}} -\def:cpn{def_aux_use_3_parameter:}{{##1}{##2}{##3}} -\def:cpn{def_aux_use_4_parameter:}{{##1}{##2}{##3}{##4}} -\def:cpn{def_aux_use_5_parameter:}{{##1}{##2}{##3}{##4}{##5}} -\def:cpn{def_aux_use_6_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}} -\def:cpn{def_aux_use_7_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}} -\def:cpn{def_aux_use_8_parameter:}{ - {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}} -\def:cpn{def_aux_use_9_parameter:}{ - {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}} +\prg_set_conditional:Npnn \str_if_eq:nn #1#2{p}{ + \str_if_eq_p_aux:w #1\scan_stop:\\#2\scan_stop:\\ +} +\cs_set_nopar:Npn \str_if_eq_p_aux:w #1#2\\#3#4\\{ + \if_meaning:w#1#3 + \if_meaning:w#1\scan_stop:\prg_return_true: \else: + \if_meaning:w#3\scan_stop:\prg_return_false: \else: + \str_if_eq_p_aux:w #2\\#4\\\fi:\fi: + \else:\prg_return_false: \fi:} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def:NNn} -% \begin{macro}{\def:NNx} -% \begin{macro}{\def:cNn} -% \begin{macro}{\def:cNx} -% \begin{macro}{\gdef:NNn} -% \begin{macro}{\gdef:NNx} -% \begin{macro}{\gdef:cNn} -% \begin{macro}{\gdef:cNx} -% \begin{macro}{\def_new:NNn} -% \begin{macro}{\def_new:NNx} -% \begin{macro}{\def_new:cNn} -% \begin{macro}{\def_new:cNx} -% \begin{macro}{\gdef_new:NNn} -% \begin{macro}{\gdef_new:NNx} -% \begin{macro}{\gdef_new:cNn} -% \begin{macro}{\gdef_new:cNx} -% Defining macros without delimited arguments is now relatively -% easy. First local and global versions of the usual |\def:Npn| -% operation. +% \begin{macro}{\cs_if_eq_name_p:NN} +% An application of the above function, already streamlined for +% speed, so I put it in here. It takes two control sequences as +% arguments and expands into true iff they have the same name. +% We make it long in case one of them is |\par|! % \begin{macrocode} -\def_new:Npn \def:NNn { \def_aux:NNnn \def:Npn } -\def_new:Npn \def:NNx { \def_aux:NNnn \def:Npx } -\def_new:Npn \def:cNn { \def_aux:Ncnn \def:Npn } -\def_new:Npn \def:cNx { \def_aux:Ncnn \def:Npx } -\def_new:Npn \gdef:NNn { \def_aux:NNnn \gdef:Npn } -\def_new:Npn \gdef:NNx { \def_aux:NNnn \gdef:Npx } -\def_new:Npn \gdef:cNn { \def_aux:Ncnn \gdef:Npn } -\def_new:Npn \gdef:cNx { \def_aux:Ncnn \gdef:Npx } -\def_new:Npn \def_new:NNn { \def_aux:NNnn \def_new:Npn } -\def_new:Npn \def_new:NNx { \def_aux:NNnn \def_new:Npx } -\def_new:Npn \def_new:cNn { \def_aux:Ncnn \def_new:Npn } -\def_new:Npn \def_new:cNx { \def_aux:Ncnn \def_new:Npx } -\def_new:Npn \gdef_new:NNn { \def_aux:NNnn \gdef_new:Npn } -\def_new:Npn \gdef_new:NNx { \def_aux:NNnn \gdef_new:Npx } -\def_new:Npn \gdef_new:cNn { \def_aux:Ncnn \gdef_new:Npn } -\def_new:Npn \gdef_new:cNx { \def_aux:Ncnn \gdef_new:Npx } +\prg_set_conditional:Npnn \cs_if_eq_name:NN #1#2{p}{ + \exp_after:wN\exp_after:wN + \exp_after:wN\str_if_eq_p_aux:w + \exp_after:wN\token_to_str:N + \exp_after:wN#1 + \exp_after:wN\scan_stop: + \exp_after:wN\\ + \token_to_str:N#2\scan_stop:\\} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\def_long:NNn} -% \begin{macro}{\def_long:NNx} -% \begin{macro}{\def_long:cNn} -% \begin{macro}{\def_long:cNx} -% \begin{macro}{\gdef_long:NNn} -% \begin{macro}{\gdef_long:NNx} -% \begin{macro}{\gdef_long:cNn} -% \begin{macro}{\gdef_long:cNx} -% \begin{macro}{\def_long_new:NNn} -% \begin{macro}{\def_long_new:NNx} -% \begin{macro}{\def_long_new:cNn} -% \begin{macro}{\def_long_new:cNx} -% \begin{macro}{\gdef_long_new:NNn} -% \begin{macro}{\gdef_long_new:NNx} -% \begin{macro}{\gdef_long_new:cNn} -% \begin{macro}{\gdef_long_new:cNx} -% Long versions of the above. +% +% \begin{macro}{\str_if_eq_var_p:nf} +% \begin{macro}[aux]{\str_if_eq_var_start:nnN} +% \begin{macro}[aux]{\str_if_eq_var_stop:w} +% A variant of |\str_if_eq_p:nn| which has the advantage of obeying +% spaces in at least the second argument. See \textsf{l3quark} for +% an application. From the hand of David Kastrup with slight +% modifications to make it fit with the remainder of the expl3 +% language. +% +% The macro builds a string of |\if:w \fi:| pairs from the first +% argument. The idea is to turn the comparison of |ab| and |cde| +% into +% \begin{verbatim} +% \tex_number:D +% \if:w \scan_stop: \if:w b\if:w a cde\scan_stop: '\fi: \fi: \fi: +% 13 +% \end{verbatim} +% The |'| is important here. If all tests are true, the |'| is read +% as part of the number in which case the returned number is |13| in +% octal notation so |\tex_number:D| returns |11|. If one test +% returns false the |'| is never seen and then we get just |13|. We +% wrap the whole process in an external |\if:w| in order to make it +% return either |\c_true_bool| or |\c_false_bool| since some parts of +% \textsf{l3prg} expect a predicate to return one of these two +% tokens. % \begin{macrocode} -\def_new:Npn \def_long:NNn { \def_aux:NNnn \def_long:Npn } -\def_new:Npn \def_long:NNx { \def_aux:NNnn \def_long:Npx } -\def_new:Npn \def_long:cNn { \def_aux:Ncnn \def_long:Npn } -\def_new:Npn \def_long:cNx { \def_aux:Ncnn \def_long:Npx } -\def_new:Npn \gdef_long:NNn { \def_aux:NNnn \gdef_long:Npn } -\def_new:Npn \gdef_long:NNx { \def_aux:NNnn \gdef_long:Npx } -\def_new:Npn \gdef_long:cNn { \def_aux:Ncnn \gdef_long:Npn } -\def_new:Npn \gdef_long:cNx { \def_aux:Ncnn \gdef_long:Npx } -\def_new:Npn \def_long_new:NNn { \def_aux:NNnn \def_long_new:Npn } -\def_new:Npn \def_long_new:NNx { \def_aux:NNnn \def_long_new:Npx } -\def_new:Npn \def_long_new:cNn { \def_aux:Ncnn \def_long_new:Npn } -\def_new:Npn \def_long_new:cNx { \def_aux:Ncnn \def_long_new:Npx } -\def_new:Npn \gdef_long_new:NNn { \def_aux:NNnn \gdef_long_new:Npn } -\def_new:Npn \gdef_long_new:NNx { \def_aux:NNnn \gdef_long_new:Npx } -\def_new:Npn \gdef_long_new:cNn { \def_aux:Ncnn \gdef_long_new:Npn } -\def_new:Npn \gdef_long_new:cNx { \def_aux:Ncnn \gdef_long_new:Npx } +\prg_set_conditional:Npnn \str_if_eq_var:nf #1#2 {p} { + \if:w \tex_number:D\str_if_eq_var_start:nnN{}{}#1\scan_stop:{#2} +} +\cs_set_nopar:Npn\str_if_eq_var_start:nnN#1#2#3{ + \if:w#3\scan_stop:\exp_after:wN\str_if_eq_var_stop:w\fi: + \str_if_eq_var_start:nnN{\if:w#3#1}{#2\fi:} +} +\cs_set:Npn\str_if_eq_var_stop:w\str_if_eq_var_start:nnN#1#2#3{ + #1#3\scan_stop:'#213~\prg_return_true:\else:\prg_return_false:\fi: +} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\def_protected:NNn} -% \begin{macro}{\def_protected:NNx} -% \begin{macro}{\def_protected:cNn} -% \begin{macro}{\def_protected:cNx} -% \begin{macro}{\gdef_protected:NNn} -% \begin{macro}{\gdef_protected:NNx} -% \begin{macro}{\gdef_protected:cNn} -% \begin{macro}{\gdef_protected:cNx} -% \begin{macro}{\def_protected_new:NNn} -% \begin{macro}{\def_protected_new:NNx} -% \begin{macro}{\def_protected_new:cNn} -% \begin{macro}{\def_protected_new:cNx} -% \begin{macro}{\gdef_protected_new:NNn} -% \begin{macro}{\gdef_protected_new:NNx} -% \begin{macro}{\gdef_protected_new:cNn} -% \begin{macro}{\gdef_protected_new:cNx} -% Protected versions of the above. -% \begin{macrocode} -\def_new:Npn \def_protected:NNn { \def_aux:NNnn \def_protected:Npn } -\def_new:Npn \def_protected:NNx { \def_aux:NNnn \def_protected:Npx } -\def_new:Npn \def_protected:cNn { \def_aux:Ncnn \def_protected:Npn } -\def_new:Npn \def_protected:cNx { \def_aux:Ncnn \def_protected:Npx } -\def_new:Npn \gdef_protected:NNn { \def_aux:NNnn \gdef_protected:Npn } -\def_new:Npn \gdef_protected:NNx { \def_aux:NNnn \gdef_protected:Npx } -\def_new:Npn \gdef_protected:cNn { \def_aux:Ncnn \gdef_protected:Npn } -\def_new:Npn \gdef_protected:cNx { \def_aux:Ncnn \gdef_protected:Npx } -\def_new:Npn \def_protected_new:NNn { \def_aux:NNnn \def_protected_new:Npn } -\def_new:Npn \def_protected_new:NNx { \def_aux:NNnn \def_protected_new:Npx } -\def_new:Npn \def_protected_new:cNn { \def_aux:Ncnn \def_protected_new:Npn } -\def_new:Npn \def_protected_new:cNx { \def_aux:Ncnn \def_protected_new:Npx } -\def_new:Npn \gdef_protected_new:NNn { \def_aux:NNnn \gdef_protected_new:Npn } -\def_new:Npn \gdef_protected_new:NNx { \def_aux:NNnn \gdef_protected_new:Npx } -\def_new:Npn \gdef_protected_new:cNn { \def_aux:Ncnn \gdef_protected_new:Npn } -\def_new:Npn \gdef_protected_new:cNx { \def_aux:Ncnn \gdef_protected_new:Npx } +% +% +% \subsection{More new definitions} +% +% +% +% \begin{macro}{\cs_new_nopar:Npn} +% \begin{macro}{\cs_new_nopar:Npx} +% \begin{macro}{\cs_new:Npn} +% \begin{macro}{\cs_new:Npx} +% \begin{macro}{\cs_new_protected_nopar:Npn} +% \begin{macro}{\cs_new_protected_nopar:Npx} +% \begin{macro}{\cs_new_protected:Npn} +% \begin{macro}{\cs_new_protected:Npx} +% These are like |\cs_set_nopar:Npn| and |\cs_set_eq:NN|, but they +% first check that the argument command is not already in use. You +% may use |\pref_global:D|, |\pref_long:D|, |\pref_protected:D|, and +% |\tex_outer:D| as prefixes. +% \begin {macrocode} +\cs_set:Npn \cs_tmp:w #1#2{ + \cs_set_protected_nopar:Npn #1 ##1 { + \chk_if_free_cs:N ##1 + #2 ##1 + } +} +\cs_tmp:w \cs_new_nopar:Npn \cs_set_nopar:Npn +\cs_tmp:w \cs_new_nopar:Npx\cs_set_nopar:Npx +\cs_tmp:w \cs_new:Npn \cs_set:Npn +\cs_tmp:w \cs_new:Npx\cs_set:Npx +\cs_tmp:w \cs_new_protected_nopar:Npn \cs_set_protected_nopar:Npn +\cs_tmp:w \cs_new_protected_nopar:Npx\cs_set_protected_nopar:Npx +\cs_tmp:w \cs_new_protected:Npn \cs_set_protected:Npn +\cs_tmp:w \cs_new_protected:Npx\cs_set_protected:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -2095,6 +2480,26 @@ % \end{macro} % \end{macro} % \end{macro} +% +% \begin{macro}{\cs_gnew_nopar:Npn} +% \begin{macro}{\cs_gnew_nopar:Npx} +% \begin{macro}{\cs_gnew:Npn} +% \begin{macro}{\cs_gnew:Npx} +% \begin{macro}{\cs_gnew_protected_nopar:Npn} +% \begin{macro}{\cs_gnew_protected_nopar:Npx} +% \begin{macro}{\cs_gnew_protected:Npn} +% \begin{macro}{\cs_gnew_protected:Npx} +% Global versions of the above functions. +% \begin {macrocode} +\cs_tmp:w \cs_gnew_nopar:Npn \cs_gset_nopar:Npn +\cs_tmp:w \cs_gnew_nopar:Npx \cs_gset_nopar:Npx +\cs_tmp:w \cs_gnew:Npn \cs_gset:Npn +\cs_tmp:w \cs_gnew:Npx \cs_gset:Npx +\cs_tmp:w \cs_gnew_protected_nopar:Npn \cs_gset_protected_nopar:Npn +\cs_tmp:w \cs_gnew_protected_nopar:Npx \cs_gset_protected_nopar:Npx +\cs_tmp:w \cs_gnew_protected:Npn \cs_gset_protected:Npn +\cs_tmp:w \cs_gnew_protected:Npx \cs_gset_protected:Npx +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2104,48 +2509,37 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\def_protected_long:NNn} -% \begin{macro}{\def_protected_long:NNx} -% \begin{macro}{\def_protected_long:cNn} -% \begin{macro}{\def_protected_long:cNx} -% \begin{macro}{\gdef_protected_long:NNn} -% \begin{macro}{\gdef_protected_long:NNx} -% \begin{macro}{\gdef_protected_long:cNn} -% \begin{macro}{\gdef_protected_long:cNx} -% \begin{macro}{\def_protected_long_new:NNn} -% \begin{macro}{\def_protected_long_new:NNx} -% \begin{macro}{\def_protected_long_new:cNn} -% \begin{macro}{\def_protected_long_new:cNx} -% \begin{macro}{\gdef_protected_long_new:NNn} -% \begin{macro}{\gdef_protected_long_new:NNx} -% \begin{macro}{\gdef_protected_long_new:cNn} -% \begin{macro}{\gdef_protected_long_new:cNx} -% And finally both long and protected. +% +% \begin{macro}{\cs_set_nopar:cpn} +% \begin{macro}{\cs_set_nopar:cpx} +% \begin{macro}{\cs_gset_nopar:cpn} +% \begin{macro}{\cs_gset_nopar:cpx} +% \begin{macro}{\cs_new_nopar:cpn} +% \begin{macro}{\cs_new_nopar:cpx} +% \begin{macro}{\cs_gnew_nopar:cpn} +% \begin{macro}{\cs_gnew_nopar:cpx} +% Like |\cs_set_nopar:Npn| and |\cs_new_nopar:Npn|, except that the +% first argument consists of the sequence of characters that should +% be used to form the name of the desired control sequence (the |c| +% stands for csname argument, see the expansion module). Global +% versions are also provided. +% +% |\cs_set_nopar:cpn|\m{string}\m{rep-text} will turn \m{string} +% into a csname and then assign \m {rep-text} to it by using +% |\cs_set_nopar:Npn|. This means that there might be a parameter +% string between the two arguments. % \begin{macrocode} -\def_new:Npn \def_protected_long:NNn { \def_aux:NNnn \def_protected_long:Npn } -\def_new:Npn \def_protected_long:NNx { \def_aux:NNnn \def_protected_long:Npx } -\def_new:Npn \def_protected_long:cNn { \def_aux:Ncnn \def_protected_long:Npn } -\def_new:Npn \def_protected_long:cNx { \def_aux:Ncnn \def_protected_long:Npx } -\def_new:Npn \gdef_protected_long:NNn { \def_aux:NNnn \gdef_protected_long:Npn } -\def_new:Npn \gdef_protected_long:NNx { \def_aux:NNnn \gdef_protected_long:Npx } -\def_new:Npn \gdef_protected_long:cNn { \def_aux:Ncnn \gdef_protected_long:Npn } -\def_new:Npn \gdef_protected_long:cNx { \def_aux:Ncnn \gdef_protected_long:Npx } -\def_new:Npn \def_protected_long_new:NNn { - \def_aux:NNnn \def_protected_long_new:Npn } -\def_new:Npn \def_protected_long_new:NNx { - \def_aux:NNnn \def_protected_long_new:Npx } -\def_new:Npn \def_protected_long_new:cNn { - \def_aux:Ncnn \def_protected_long_new:Npn } -\def_new:Npn \def_protected_long_new:cNx { - \def_aux:Ncnn \def_protected_long_new:Npx } -\def_new:Npn \gdef_protected_long_new:NNn { - \def_aux:NNnn \gdef_protected_long_new:Npn } -\def_new:Npn \gdef_protected_long_new:NNx { - \def_aux:NNnn \gdef_protected_long_new:Npx } -\def_new:Npn \gdef_protected_long_new:cNn { - \def_aux:Ncnn \gdef_protected_long_new:Npn } -\def_new:Npn \gdef_protected_long_new:cNx { - \def_aux:Ncnn \gdef_protected_long_new:Npx } +\cs_set:Npn \cs_tmp:w #1#2{ + \cs_new_nopar:Npn #1 { \exp_args:Nc #2 } +} +\cs_tmp:w \cs_set_nopar:cpn \cs_set_nopar:Npn +\cs_tmp:w \cs_set_nopar:cpx \cs_set_nopar:Npx +\cs_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn +\cs_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx +\cs_tmp:w \cs_new_nopar:cpn \cs_new_nopar:Npn +\cs_tmp:w \cs_new_nopar:cpx \cs_new_nopar:Npx +\cs_tmp:w \cs_gnew_nopar:cpn \cs_gnew_nopar:Npn +\cs_tmp:w \cs_gnew_nopar:cpx \cs_gnew_nopar:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -2155,6 +2549,29 @@ % \end{macro} % \end{macro} % \end{macro} +% +% +% +% \begin{macro}{\cs_set:cpn} +% \begin{macro}{\cs_set:cpx} +% \begin{macro}{\cs_gset:cpn} +% \begin{macro}{\cs_gset:cpx} +% \begin{macro}{\cs_new:cpn} +% \begin{macro}{\cs_new:cpx} +% \begin{macro}{\cs_gnew:cpn} +% \begin{macro}{\cs_gnew:cpx} +% Variants of the |\cs_set:Npn| versions which make a csname out +% of the first arguments. We may also do this globally. +% \begin{macrocode} +\cs_tmp:w \cs_set:cpn \cs_set:Npn +\cs_tmp:w \cs_set:cpx \cs_set:Npx +\cs_tmp:w \cs_gset:cpn \cs_gset:Npn +\cs_tmp:w \cs_gset:cpx \cs_gset:Npx +\cs_tmp:w \cs_new:cpn \cs_new:Npn +\cs_tmp:w \cs_new:cpx \cs_new:Npx +\cs_tmp:w \cs_gnew:cpn \cs_gnew:Npn +\cs_tmp:w \cs_gnew:cpx \cs_gnew:Npx +% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} @@ -2164,33 +2581,25 @@ % \end{macro} % \end{macro} % -% -% \begin{macro}{\let:NN} -% \begin{macro}{\let:cN} -% \begin{macro}{\let:Nc} -% \begin{macro}{\let:cc} -% \begin{macro}{\let_new:NN} -% \begin{macro}{\let_new:cN} -% \begin{macro}{\let_new:Nc} -% \begin{macro}{\let_new:cc} -% These macros allow us to copy the definition of a control sequence -% to another control sequence. -% \begin{macrocode} -\def_protected_long_new:Npn \let:NN #1{ -% \end{macrocode} -% The |=| sign allows us to define funny char tokens like .|=| -% itself or \verb*= = with this function. For the definition of -% |\c_space_chartok{~}| to work we need the |~| after the |=| +% \begin{macro}{\cs_set_protected_nopar:cpn} +% \begin{macro}{\cs_set_protected_nopar:cpx} +% \begin{macro}{\cs_gset_protected_nopar:cpn} +% \begin{macro}{\cs_gset_protected_nopar:cpx} +% \begin{macro}{\cs_new_protected_nopar:cpn} +% \begin{macro}{\cs_new_protected_nopar:cpx} +% \begin{macro}{\cs_gnew_protected_nopar:cpn} +% \begin{macro}{\cs_gnew_protected_nopar:cpx} +% Variants of the |\cs_set_protected_nopar:Npn| versions which make a csname +% out of the first arguments. We may also do this globally. % \begin{macrocode} - \let:NwN #1=~} -\def_new:Npn\let:cN #1 {\exp_after:NN\let:NN\cs:w#1\cs_end:} -\def_new:Npn\let:Nc{\exp_args:NNc\let:NN} -\def_new:Npn\let:cc{\exp_args:Ncc\let:NN} -\def_new:Npn \let_new:NN #1{\chk_new_cs:N #1 - \let:NN #1} -\def_new:Npn \let_new:cN {\exp_args:Nc \let_new:NN} -\def_new:Npn \let_new:Nc {\exp_args:NNc \let_new:NN} -\def_new:Npn \let_new:cc {\exp_args:Ncc \let_new:NN} +\cs_tmp:w \cs_set_protected_nopar:cpn \cs_set_protected_nopar:Npn +\cs_tmp:w \cs_set_protected_nopar:cpx \cs_set_protected_nopar:Npx +\cs_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn +\cs_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx +\cs_tmp:w \cs_new_protected_nopar:cpn \cs_new_protected_nopar:Npn +\cs_tmp:w \cs_new_protected_nopar:cpx \cs_new_protected_nopar:Npx +\cs_tmp:w \cs_gnew_protected_nopar:cpn \cs_gnew_protected_nopar:Npn +\cs_tmp:w \cs_gnew_protected_nopar:cpx \cs_gnew_protected_nopar:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -2201,25 +2610,25 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\glet:NN} -% \begin{macro}{\glet:cN} -% \begin{macro}{\glet:Nc} -% \begin{macro}{\glet:cc} -% \begin{macro}{\glet_new:NN} -% \begin{macro}{\glet_new:cN} -% \begin{macro}{\glet_new:Nc} -% \begin{macro}{\glet_new:cc} -% These are global versions of some of the previously defined functions. +% \begin{macro}{\cs_set_protected:cpn} +% \begin{macro}{\cs_set_protected:cpx} +% \begin{macro}{\cs_gset_protected:cpn} +% \begin{macro}{\cs_gset_protected:cpx} +% \begin{macro}{\cs_new_protected:cpn} +% \begin{macro}{\cs_new_protected:cpx} +% \begin{macro}{\cs_gnew_protected:cpn} +% \begin{macro}{\cs_gnew_protected:cpx} +% Variants of the |\cs_set_protected:Npn| versions which make a csname +% out of the first arguments. We may also do this globally. % \begin{macrocode} -\def_protected_new:Npn \glet:NN {\pref_global:D \let:NN} -\def_protected_new:Npn \glet:Nc {\exp_args:NNc \glet:NN} -\def_protected_new:Npn \glet:cN {\exp_args:Nc \glet:NN} -\def_new:Npn \glet:cc {\exp_args:Ncc \glet:NN} -\def_new:Npn \glet_new:NN #1{\chk_new_cs:N #1 - \tex_global:D\let:NN #1} -\def_new:Npn \glet_new:cN {\exp_args:Nc \glet_new:NN} -\def_new:Npn \glet_new:Nc {\exp_args:NNc \glet_new:NN} -\def_new:Npn \glet_new:cc {\exp_args:Ncc \glet_new:NN} +\cs_tmp:w \cs_set_protected:cpn \cs_set_protected:Npn +\cs_tmp:w \cs_set_protected:cpx \cs_set_protected:Npx +\cs_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn +\cs_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx +\cs_tmp:w \cs_new_protected:cpn \cs_new_protected:Npn +\cs_tmp:w \cs_new_protected:cpx \cs_new_protected:Npx +\cs_tmp:w \cs_gnew_protected:cpn \cs_gnew_protected:Npn +\cs_tmp:w \cs_gnew_protected:cpx \cs_gnew_protected:Npx % \end{macrocode} % \end{macro} % \end{macro} @@ -2231,81 +2640,31 @@ % \end{macro} % % -% \begin{macro}{\def:No} -% \begin{macro}{\gdef:No} -% |\def:No| expands its second argument one time before making -% the definition. -% \begin{macrocode} -\def_new:Npn \def:No{\exp_args:NNo\def:Npn} -\def_new:Npn \gdef:No {\exp_args:NNo\gdef:Npn} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\def_test_function_aux:Nnnn} -% \begin{macro}{\def_test_function_aux:Nnnx} -% \begin{macro}{\def_test_function:npn} -% \begin{macro}{\def_test_function:npx} -% \begin{macro}{\def_long_test_function:npn} -% \begin{macro}{\def_long_test_function:npx} -% \begin{macro}{\def_test_function_new:npn} -% \begin{macro}{\def_test_function_new:npx} -% \begin{macro}{\def_long_test_function_new:npn} -% \begin{macro}{\def_long_test_function_new:npx} -% We will often be defining several almost identical TF, T and F -% type functions so it makes sense for us to define a small function -% that will do this for us so that we are less likely to introduce -% typos (it does tend to happen). By doing it in two steps as below -% we can still retain a simple interface where you write the \TeX\ -% parameters as usual. Just don't do it when you're already within a -% conditional! -% -% I think the ways of exiting conditionals below are as fast as they -% get. Using |\reverse_if:N| instead of |\else:| didn't give any -% difference I could measure. +% \begin{macro}[aux]{\use_0_parameter:} +% \begin{macro}[aux]{\use_1_parameter:} +% \begin{macro}[aux]{\use_2_parameter:} +% \begin{macro}[aux]{\use_3_parameter:} +% \begin{macro}[aux]{\use_4_parameter:} +% \begin{macro}[aux]{\use_5_parameter:} +% \begin{macro}[aux]{\use_6_parameter:} +% \begin{macro}[aux]{\use_7_parameter:} +% \begin{macro}[aux]{\use_8_parameter:} +% \begin{macro}[aux]{\use_9_parameter:} +% For using parameters, i.e., when you need to define a function to +% process three parameters. See \textsf{xparse} for an application. % \begin{macrocode} -\def_long_new:Npn \def_test_function_aux:Nnnn #1#2#3#4{ - #1 {#2TF} #3 {#4 - \exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:} - #1 {#2FT} #3 {#4 - \exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:} - #1 {#2T} #3 {#4 - \else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n} - #1 {#2F} #3 {#4 - \exp_after:NN\use_none:nn\fi:\use_arg_i:n}} -\def_long_new:Npn \def_test_function_aux:Nnnx #1#2#3#4{ - #1 {#2TF} #3 {#4 - \exp_not:n{\exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:}} - #1 {#2FT} #3 {#4 - \exp_not:n{\exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:}} - #1 {#2T} #3 {#4 - \exp_not:n{\else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n}} - #1 {#2F} #3 {#4 - \exp_not:n{\exp_after:NN\use_none:nn\fi:\use_arg_i:n}}} -\def_long_new:Npn \def_test_function:npn #1#2#{ - \def_test_function_aux:Nnnn \def:cpn {#1}{#2} -} -\def_long_new:Npn \def_test_function:npx #1#2#{ - \def_test_function_aux:Nnnx \def:cpx {#1}{#2} -} -\def_long_new:Npn \def_long_test_function:npn #1#2#{ - \def_test_function_aux:Nnnn \def_long:cpn {#1}{#2} -} -\def_long_new:Npn \def_long_test_function:npx #1#2#{ - \def_test_function_aux:Nnnx \def_long:cpx {#1}{#2} -} -\def_long_new:Npn \def_test_function_new:npn #1#2#{ - \def_test_function_aux:Nnnn \def_new:cpn {#1}{#2} -} -\def_long_new:Npn \def_long_test_function_new:npn #1#2#{ - \def_test_function_aux:Nnnn \def_long_new:cpn {#1}{#2} -} -\def_long_new:Npn \def_test_function_new:npx #1#2#{ - \def_test_function_aux:Nnnx \def_new:cpx {#1}{#2} -} -\def_long_new:Npn \def_long_test_function_new:npx #1#2#{ - \def_test_function_aux:Nnnx \def_long_new:cpx {#1}{#2} -} +\cs_set_nopar:cpn{use_0_parameter:}{} +\cs_set_nopar:cpn{use_1_parameter:}{{##1}} +\cs_set_nopar:cpn{use_2_parameter:}{{##1}{##2}} +\cs_set_nopar:cpn{use_3_parameter:}{{##1}{##2}{##3}} +\cs_set_nopar:cpn{use_4_parameter:}{{##1}{##2}{##3}{##4}} +\cs_set_nopar:cpn{use_5_parameter:}{{##1}{##2}{##3}{##4}{##5}} +\cs_set_nopar:cpn{use_6_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}} +\cs_set_nopar:cpn{use_7_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}} +\cs_set_nopar:cpn{use_8_parameter:}{ + {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}} +\cs_set_nopar:cpn{use_9_parameter:}{ + {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}} % \end{macrocode} % \end{macro} % \end{macro} @@ -2318,180 +2677,330 @@ % \end{macro} % \end{macro} % +% \subsection{Copying definitions} +% +% \begin{macro}{\cs_set_eq:NN} +% \begin{macro}{\cs_set_eq:cN} +% \begin{macro}{\cs_set_eq:Nc} +% \begin{macro}{\cs_set_eq:cc} +% These macros allow us to copy the definition of a control sequence +% to another control sequence. +% +% The |=| sign allows us to define funny char tokens like |=| +% itself or \verb*= = with this function. For the definition of +% |\c_space_chartok{~}| to work we need the |~| after the |=|. +% +% |\cs_set_eq:NN| is long to avoid problems with a literal argument +% of |\par|. While |\cs_new_eq:NN| will probably never be correct +% with a first argument of |\par|, define it long in order to throw +% an `already defined' error rather than `runaway argument'. % -% \subsubsection{Further checking} +% The |c| variants are not protected in order for their arguments to +% be constructed in the correct context. % -% \begin{macro}{\cs_if_free:NTF} -% \begin{macro}{\cs_if_free:NT} -% \begin{macro}{\cs_if_free:NF} -% The old |\@ifundefined| of \LaTeX{} 2.09 is re-implemented in the -% function |\cs_free:cTF|, again in a way that |\else:| and |\fi:| -% are removed. In this implementation this is absolutely -% necessary because functions inside the conditional parts expect -% to read further input from outside the conditional. Actually, -% the first part of the code below is more general, since it checks -% \m{csnames} directly and therefore allows both |\scan_stop:| and -% |\c_undefined|. % \begin{macrocode} -\def_long_test_function_new:npn {cs_if_free:N}#1{\if:w\cs_if_free_p:N #1} -\let:NN \cs_free:NTF \cs_if_free:NTF -\let:NN \cs_free:NT \cs_if_free:NT -\let:NN \cs_free:NF \cs_if_free:NF +\cs_set_protected:Npn \cs_set_eq:NN #1 { \cs_set_eq:NwN #1=~ } +\cs_set_nopar:Npn \cs_set_eq:cN { \exp_args:Nc \cs_set_eq:NN } +\cs_set_nopar:Npn \cs_set_eq:Nc { \exp_args:NNc \cs_set_eq:NN } +\cs_set_nopar:Npn \cs_set_eq:cc { \exp_args:Ncc \cs_set_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\cs_if_free:cTF} -% \begin{macro}{\cs_if_free:cT} -% \begin{macro}{\cs_if_free:cF} -% We have to implement the |c| variants `by hand' because a different -% test is necessary and I don't want the overhead for the test with -% |\if:w|. What a mistake Don made by making this a -% feature of |\cs:w|. If I'm not totally mistaken this -% feature alone has cost him more than 600\$ for bug-checks. +% \begin{macro}{\cs_new_eq:NN} +% \begin{macro}{\cs_new_eq:cN} +% \begin{macro}{\cs_new_eq:Nc} +% \begin{macro}{\cs_new_eq:cc} % \begin{macrocode} -\def_long_test_function_new:npn {cs_if_free:c}#1{ - \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -\let:NN \cs_free:cTF \cs_if_free:cTF -\let:NN \cs_free:cT \cs_if_free:cT -\let:NN \cs_free:cF \cs_if_free:cF +\cs_new_protected:Npn \cs_new_eq:NN #1 { + \chk_if_free_cs:N #1 + \cs_set_eq:NN #1 +} +\cs_new_nopar:Npn \cs_new_eq:cN { \exp_args:Nc \cs_new_eq:NN } +\cs_new_nopar:Npn \cs_new_eq:Nc { \exp_args:NNc \cs_new_eq:NN } +\cs_new_nopar:Npn \cs_new_eq:cc { \exp_args:Ncc \cs_new_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\cs_if_really_free:cTF} -% \begin{macro}{\cs_if_really_free:cT} -% \begin{macro}{\cs_if_really_free:cF} -% These versions are for special control sequences that can only be -% formed through |\cs:w ... \cs_end:|. They do not turn the control -% sequence formed into |\scan_stop:|. +% \begin{macro}{\cs_gset_eq:NN} +% \begin{macro}{\cs_gset_eq:cN} +% \begin{macro}{\cs_gset_eq:Nc} +% \begin{macro}{\cs_gset_eq:cc} % \begin{macrocode} -\def_long_test_function_new:npn {cs_if_really_free:c}#1{ - \reverse_if:N\if_cs_exist:w #1\cs_end:} -\let:NN \cs_really_free:cTF \cs_if_really_free:cTF -\let:NN \cs_really_free:cT \cs_if_really_free:cT -\let:NN \cs_really_free:cF \cs_if_really_free:cF +\cs_new_protected:Npn \cs_gset_eq:NN { \pref_global:D \cs_set_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:Nc { \exp_args:NNc \cs_gset_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:cN { \exp_args:Nc \cs_gset_eq:NN } +\cs_new_nopar:Npn \cs_gset_eq:cc { \exp_args:Ncc \cs_gset_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}{\cs_if_exist:NTF} -% \begin{macro}{\cs_if_exist:NT} -% \begin{macro}{\cs_if_exist:NF} -% \begin{macro}{\cs_if_exist:cTF} -% \begin{macro}{\cs_if_exist:cT} -% \begin{macro}{\cs_if_exist:cF} -% \begin{macro}{\cs_if_really_exist:cTF} -% \begin{macro}{\cs_if_really_exist:cT} -% \begin{macro}{\cs_if_really_exist:cF} -% Now the same functions but with reverse logic: test if the control -% sequence exists. +% \begin{macro}{\cs_gnew_eq:NN} +% \begin{macro}{\cs_gnew_eq:cN} +% \begin{macro}{\cs_gnew_eq:Nc} +% \begin{macro}{\cs_gnew_eq:cc} % \begin{macrocode} -\def_long_test_function_new:npn {cs_if_exist:N}#1{\if:w\cs_if_exist_p:N #1} -\def_long_test_function_new:npn {cs_if_exist:c}#1{ - \exp_after:NN\reverse_if:N - \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} -\def_long_test_function_new:npn {cs_if_really_exist:c}#1{ - \if_cs_exist:w #1\cs_end:} +\cs_new_protected:Npn \cs_gnew_eq:NN #1 { + \chk_if_free_cs:N #1 + \pref_global:D \cs_set_eq:NN #1 +} +\cs_new_nopar:Npn \cs_gnew_eq:cN { \exp_args:Nc \cs_gnew_eq:NN } +\cs_new_nopar:Npn \cs_gnew_eq:Nc { \exp_args:NNc \cs_gnew_eq:NN } +\cs_new_nopar:Npn \cs_gnew_eq:cc { \exp_args:Ncc \cs_gnew_eq:NN } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \subsubsection{Freeing memory} +% \subsection{Undefining functions} % % \begin{macro}{\cs_gundefine:N } % The following function is used to free the main memory from the % definition of some function that isn't in use any longer. % \begin{macrocode} -\def_new:Npn \cs_gundefine:N #1{\glet:NN #1\c_undefined} +\cs_new_nopar:Npn \cs_gundefine:N #1{\cs_gset_eq:NN #1\c_undefined:D} % \end{macrocode} % \end{macro} % % -% \subsubsection{Engine specific definitions} +% \subsection{Engine specific definitions} % -% \begin{macro}{\engine_if_aleph:TF} +% \begin{macro}{\c_xetex_is_engine_bool,\c_luatex_is_engine_bool} +% \begin{macro}[TF]{\xetex_if_engine:,\luatex_if_engine:} % In some cases it will be useful to know which engine we're running. +% Don't provide a "_p" predicate because the "_bool" is used for the +% same thing. +% \begin{macrocode} +\if_cs_exist:N \xetex_version:D + \cs_new_eq:NN \c_xetex_is_engine_bool \c_true_bool +\else: + \cs_new_eq:NN \c_xetex_is_engine_bool \c_false_bool +\fi: +\prg_new_conditional:Npnn \xetex_if_engine: {TF,T,F} { + \if_bool:N \c_xetex_is_engine_bool + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% % \begin{macrocode} -\def_test_function_new:npn {engine_if_aleph:}{\if_cs_exist:N \aleph_textdir:D} +\if_cs_exist:N \luatex_directlua:D + \cs_new_eq:NN \c_luatex_is_engine_bool \c_true_bool +\else: + \cs_new_eq:NN \c_luatex_is_engine_bool \c_false_bool +\fi: +\prg_set_conditional:Npnn \xetex_if_engine: {TF,T,F}{ + \if_bool:N \c_xetex_is_engine_bool \prg_return_true: + \else: \prg_return_false: \fi: +} +\prg_set_conditional:Npnn \luatex_if_engine: {TF,T,F}{ + \if_bool:N \c_luatex_is_engine_bool \prg_return_true: + \else: \prg_return_false: \fi: +} % \end{macrocode} % \end{macro} +% \end{macro} % % % -% \subsubsection{Selecting tokens} % -% \begin{macro}{\use_arg_i:n} -% This macro grabs its argument and returns it back to the input -% (with outer braces removed). +% \subsection{Scratch functions} +% +% \begin{macro}{\prg_do_nothing:} +% I don't think this function belongs here, but one place is as +% good as any other. I want to use this function when I want to +% express `no operation'. It is for example used in templates where +% depending on the users settings we have to either select an function that +% does something, or one that does nothing. % \begin{macrocode} -%\def_long_new:Npn \use_arg_i:n #1{#1}% moved earlier +\cs_new_nopar:Npn \prg_do_nothing: {} % \end{macrocode} % \end{macro} % -% \begin{macro}{\use:c} -% \begin{macro}{\cs_use:c} -% \begin{macro}{\use:cc} -% This macro grabs its argument and returns a csname from it. +% +% \subsection{Defining functions from a given number of arguments} +% +% \begin{macro}{\cs_get_arg_count_from_signature:N} +% \begin{macro}[aux]{\cs_get_arg_count_from_signature_aux:nnN} +% \begin{macro}[aux]{\cs_get_arg_count_from_signature_auxii:w} +% Counting the number of tokens in the signature, i.e., the number +% of arguments the function should take. If there is no signature, +% we return that there is $-1$ arguments to signal an error. +% Otherwise we insert the string |9876543210| after the signature. +% If the signature is empty, the number we want is $0$ so we remove +% the first nine tokens and return the tenth. Similarly, if the +% signature is |nnn| we want to remove the nine tokens |nnn987654| +% and return $3$. Therefore, we simply remove the first nine tokens +% and then return the tenth. % \begin{macrocode} -\def_new:Npn \use:c #1{\cs:w #1\cs_end:} -\def_new:Npn \cs_use:c #1 { \cs:w#1\cs_end: } +\cs_set:Npn \cs_get_arg_count_from_signature:N #1{ + \cs_split_function:NN #1 \cs_get_arg_count_from_signature_aux:nnN +} +\cs_set:Npn \cs_get_arg_count_from_signature_aux:nnN #1#2#3{ + \if_predicate:w #3 % \bool_if:NTF here + \exp_after:wN \use_i:nn + \else: + \exp_after:wN\use_ii:nn + \fi: + { + \exp_after:wN \cs_get_arg_count_from_signature_auxii:w + \use_none:nnnnnnnnn #2 9876543210\q_nil + } + {-1} +} +\cs_set:Npn \cs_get_arg_count_from_signature_auxii:w #1#2\q_nil{#1} % \end{macrocode} -% THE NAME IS COMPLETELY WRONG!!!!! -% Morten says: Perhaps this is really |\exp_args:cc| instead? +% A variant form we need right away. % \begin{macrocode} -\def_new:Npn \use:cc #1#2 - {\cs:w #1\exp_after:NN\cs_end:\cs:w #2\cs_end:} +\cs_set_nopar:Npn \cs_get_arg_count_from_signature:c { + \exp_args:Nc \cs_get_arg_count_from_signature:N +} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\use_arg_i:nn} -% \begin{macro}{\use_arg_ii:nn} -% These macros are needed to provide functions with true and false -% cases, as introduced by Michael some time ago. By using -% |\exp_after:NN| |\use_arg_i:nn | |\else:| constructions it -% is possible to write code where the true or false case is able to -% access the following tokens from the input stream, which is not -% possible if the |\c_true| syntax is used. +% +% +% +% \begin{macro}[aux]{\cs_generate_from_arg_count:NNnn} +% \begin{macro}[aux]{\cs_generate_from_arg_count_error_msg:Nn} +% We provide a constructor function for defining functions with a +% given number of arguments. For this we need to choose the correct +% parameter text and then use that when defining. Since \TeX\ +% supports from zero to nine arguments, we use a simple switch to +% choose the correct parameter text, ensuring the result is returned +% after finishing the conditional. If it is not between zero and +% nine, we throw an error. +% +% 1: function to define, 2: with what to define it, 3: the number of +% args it requires and 4: the replacement text +% \begin{macrocode} +\cs_set:Npn \cs_generate_from_arg_count:NNnn #1#2#3#4{ + \tex_ifcase:D \etex_numexpr:D #3\tex_relax:D + \use_i_after_orelse:nw{#2#1} + \or: + \use_i_after_orelse:nw{#2#1 ##1} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7##8} + \or: + \use_i_after_orelse:nw{#2#1 ##1##2##3##4##5##6##7##8##9} + \else: + \use_i_after_fi:nw{ + \cs_generate_from_arg_count_error_msg:Nn#1{#3} + \use_none:n % to remove replacement text + } + \fi: + {#4} +} +% \end{macrocode} +% A variant form we need right away. +% \begin{macrocode} +\cs_set_nopar:Npn \cs_generate_from_arg_count:cNnn { + \exp_args:Nc \cs_generate_from_arg_count:NNnn +} +% \end{macrocode} +% The error message. Elsewhere we use the value of $-1$ to signal a +% missing colon in a function, so provide a hint for help on this. % \begin{macrocode} -\def_long_new:Npn \use_arg_i:nn #1#2{#1} -\def_long_new:Npn \use_arg_ii:nn #1#2{#2} +\cs_set:Npn \cs_generate_from_arg_count_error_msg:Nn #1#2 { + \msg_kernel_bug:x { + You're~ trying~ to~ define~ the~ command~ `\token_to_str:N #1'~ + with~ \use:n{\tex_the:D\etex_numexpr:D #2\tex_relax:D} ~ + arguments~ but~ I~ only~ allow~ 0-9~arguments.~Perhaps~you~ + forgot~to~use~a~colon~in~the~function~name?~ + I~ can~ probably~ not~ help~ you~ here + } +} % \end{macrocode} % \end{macro} % \end{macro} % % % -% \begin{macro}{\use_arg_i:nnn} -% \begin{macro}{\use_arg_ii:nnn} -% \begin{macro}{\use_arg_iii:nnn} -% \begin{macro}{\use_arg_i:nnnn} -% \begin{macro}{\use_arg_ii:nnnn} -% \begin{macro}{\use_arg_iii:nnnn} -% \begin{macro}{\use_arg_iv:nnnn} -% We also need something for picking up arguments from a longer -% list. +% +% \subsection{Using the signature to define functions} +% +% We can now combine some of the tools we have to provide a simple +% interface for defining functions. We define some simpler functions +% with user interface |\cs_set:Nn \foo_bar:nn {#1,#2}|, i.e., the +% number of arguments is read from the signature. +% +% +% \begin{macro}{\cs_set:Nn} +% \begin{macro}{\cs_set:Nx} +% \begin{macro}{\cs_set_nopar:Nn} +% \begin{macro}{\cs_set_nopar:Nx} +% \begin{macro}{\cs_set_protected:Nn} +% \begin{macro}{\cs_set_protected:Nx} +% \begin{macro}{\cs_set_protected_nopar:Nn} +% \begin{macro}{\cs_set_protected_nopar:Nx} +% \begin{macro}{\cs_gset:Nn} +% \begin{macro}{\cs_gset:Nx} +% \begin{macro}{\cs_gset_nopar:Nn} +% \begin{macro}{\cs_gset_nopar:Nx} +% \begin{macro}{\cs_gset_protected:Nn} +% \begin{macro}{\cs_gset_protected:Nx} +% \begin{macro}{\cs_gset_protected_nopar:Nn} +% \begin{macro}{\cs_gset_protected_nopar:Nx} +% We want to define |\cs_set:Nn| as +% \begin{verbatim} +% \cs_set_protected:Npn \cs_set:Nn #1#2{ +% \cs_generate_from_arg_count:NNnn #1\cs_set:Npn +% {\cs_get_arg_count_from_signature:N #1}{#2} +% } +% \end{verbatim} +% In short, to define |\cs_set:Nn| we need just use |\cs_set:Npn|, +% everything else is the same for each variant. Therefore, we can +% make it simpler by temporarily defining a function to do this for +% us. +% \begin{macrocode} +\cs_set:Npn \cs_tmp:w #1#2#3{ + \cs_set_protected:cpx {cs_#1:#2}##1##2{ + \exp_not:N \cs_generate_from_arg_count:NNnn ##1 + \exp_after:wN \exp_not:N \cs:w cs_#1:#3 \cs_end: + {\exp_not:N\cs_get_arg_count_from_signature:N ##1}{##2} + } +} +% \end{macrocode} +% Then we define the 32 variants beginning with |N|. % \begin{macrocode} -\def_long_new:NNn \use_arg_i:nnn 3{#1} -\def_long_new:NNn \use_arg_ii:nnn 3{#2} -\def_long_new:NNn \use_arg_iii:nnn 3{#3} -\def_long_new:NNn \use_arg_i:nnnn 4{#1} -\def_long_new:NNn \use_arg_ii:nnnn 4{#2} -\def_long_new:NNn \use_arg_iii:nnnn 4{#3} -\def_long_new:NNn \use_arg_iv:nnnn 4{#4} +\cs_tmp:w {set}{Nn}{Npn} +\cs_tmp:w {set}{Nx}{Npx} +\cs_tmp:w {set_nopar}{Nn}{Npn} +\cs_tmp:w {set_nopar}{Nx}{Npx} +\cs_tmp:w {set_protected}{Nn}{Npn} +\cs_tmp:w {set_protected}{Nx}{Npx} +\cs_tmp:w {set_protected_nopar}{Nn}{Npn} +\cs_tmp:w {set_protected_nopar}{Nx}{Npx} +\cs_tmp:w {gset}{Nn}{Npn} +\cs_tmp:w {gset}{Nx}{Npx} +\cs_tmp:w {gset_nopar}{Nn}{Npn} +\cs_tmp:w {gset_nopar}{Nx}{Npx} +\cs_tmp:w {gset_protected}{Nn}{Npn} +\cs_tmp:w {gset_protected}{Nx}{Npx} +\cs_tmp:w {gset_protected_nopar}{Nn}{Npn} +\cs_tmp:w {gset_protected_nopar}{Nx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} @@ -2500,83 +3009,49 @@ % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\use_arg_i_ii:nn} -% And a function for grabbing two arguments and returning them -% again. -% \begin{macrocode} -\def_long_new:NNn\use_arg_i_ii:nn 2{#1#2} -% \end{macrocode} % \end{macro} -% -% \begin{macro}{\use_none_delimit_by_q_nil:w} -% \begin{macro}{\use_none_delimit_by_q_stop:w} -% Functions that gobble everything until they see either |\q_nil| or -% |\q_stop| resp. -% \begin{macrocode} -\def_long_new:Npn \use_none_delimit_by_q_nil:w #1\q_nil{} -\def_long_new:Npn \use_none_delimit_by_q_stop:w #1\q_stop{} -% \end{macrocode} % \end{macro} % \end{macro} -% -% \begin{macro}{\use_arg_i_delimit_by_q_nil:nw} -% \begin{macro}{\use_arg_i_delimit_by_q_stop:nw} -% Same as above but execute first argument after gobbling. Very -% useful when you need to skip the rest of a mapping sequence but -% want an easy way to control what should be expanded next. -% \begin{macrocode} -\def_long_new:Npn \use_arg_i_delimit_by_q_nil:nw #1#2\q_nil{#1} -\def_long_new:Npn \use_arg_i_delimit_by_q_stop:nw #1#2\q_stop{#1} -% \end{macrocode} % \end{macro} % \end{macro} -% -% -% \begin{macro}{\use_arg_i_after_fi:nw} -% \begin{macro}{\use_arg_i_after_else:nw} -% \begin{macro}{\use_arg_i_after_or:nw} -% \begin{macro}{\use_arg_i_after_or:nw} -% Returns the first argument after ending the conditional. -% \begin{macrocode} -\def_long_new:Npn \use_arg_i_after_fi:nw #1\fi:{\fi: #1} -\def_long_new:Npn \use_arg_i_after_else:nw #1\else:#2\fi:{\fi: #1} -\def_long_new:Npn \use_arg_i_after_or:nw #1\or: #2\fi: {\fi:#1} -\def_long_new:Npn \use_arg_i_after_orelse:nw #1 #2#3\fi: {\fi:#1} -% \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \subsubsection{Gobbling tokens from input} -% -% \begin{macro}{\use_none:n} -% \begin{macro}{\use_none:nn} -% \begin{macro}{\use_none:nnn} -% \begin{macro}{\use_none:nnnn} -% \begin{macro}{\use_none:nnnnn} -% \begin{macro}{\use_none:nnnnnn} -% \begin{macro}{\use_none:nnnnnnn} -% \begin{macro}{\use_none:nnnnnnnn} -% \begin{macro}{\use_none:nnnnnnnnn} -% To gobble tokens from the input we use a standard naming -% convention: the number of tokens gobbled is given by the number of -% |n|'s following the |:| in the name. Although defining -% |\use_none:nnn| and above as separate calls of |\use_none:n| and -% |\use_none:nn| is slightly faster, this is very non-intuitive to -% the programmer who will assume that expanding such a function once -% will take care of gobbling all the tokens in one go. +% \begin{macro}{\cs_new:Nn} +% \begin{macro}{\cs_new:Nx} +% \begin{macro}{\cs_new_nopar:Nn} +% \begin{macro}{\cs_new_nopar:Nx} +% \begin{macro}{\cs_new_protected:Nn} +% \begin{macro}{\cs_new_protected:Nx} +% \begin{macro}{\cs_new_protected_nopar:Nn} +% \begin{macro}{\cs_new_protected_nopar:Nx} +% \begin{macro}{\cs_gnew:Nn} +% \begin{macro}{\cs_gnew:Nx} +% \begin{macro}{\cs_gnew_nopar:Nn} +% \begin{macro}{\cs_gnew_nopar:Nx} +% \begin{macro}{\cs_gnew_protected:Nn} +% \begin{macro}{\cs_gnew_protected:Nx} +% \begin{macro}{\cs_gnew_protected_nopar:Nn} +% \begin{macro}{\cs_gnew_protected_nopar:Nx} % \begin{macrocode} -%\def_long_new:NNn \use_none:n 1{}% moved earlier -\def_long_new:NNn \use_none:nn 2{} -\def_long_new:NNn \use_none:nnn 3{} -\def_long_new:NNn \use_none:nnnn 4{} -\def_long_new:NNn \use_none:nnnnn 5{} -\def_long_new:NNn \use_none:nnnnnn 6{} -\def_long_new:NNn \use_none:nnnnnnn 7{} -\def_long_new:NNn \use_none:nnnnnnnn 8{} -\def_long_new:NNn \use_none:nnnnnnnnn 9{} +\cs_tmp:w {new}{Nn}{Npn} +\cs_tmp:w {new}{Nx}{Npx} +\cs_tmp:w {new_nopar}{Nn}{Npn} +\cs_tmp:w {new_nopar}{Nx}{Npx} +\cs_tmp:w {new_protected}{Nn}{Npn} +\cs_tmp:w {new_protected}{Nx}{Npx} +\cs_tmp:w {new_protected_nopar}{Nn}{Npn} +\cs_tmp:w {new_protected_nopar}{Nx}{Npx} +\cs_tmp:w {gnew}{Nn}{Npn} +\cs_tmp:w {gnew}{Nx}{Npx} +\cs_tmp:w {gnew_nopar}{Nn}{Npn} +\cs_tmp:w {gnew_nopar}{Nx}{Npx} +\cs_tmp:w {gnew_protected}{Nn}{Npn} +\cs_tmp:w {gnew_protected}{Nx}{Npx} +\cs_tmp:w {gnew_protected_nopar}{Nn}{Npn} +\cs_tmp:w {gnew_protected_nopar}{Nx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} @@ -2587,75 +3062,115 @@ % \end{macro} % \end{macro} % \end{macro} -% -% -% \subsubsection{Scratch functions} -% -% \begin{macro}{\gtmp:w} -% This function is for global scratch definitions that are used -% immediately afterwards. It should be used when we need a function -% that operates on input, i.e.\ has arguments. If we want to save -% only some tokens for later use, token-list scratch variables -% should be used. -% \begin{macrocode} -\def_new:Npn \gtmp:w {} -% \end{macrocode} % \end{macro} -% -% \begin{macro}{\tmp:w} -% This is a local version of the previous function. -% \begin{macrocode} -\def_new:Npn \tmp:w {} -% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % \end{macro} % -% \begin{macro}{\use_noop:} -% I don't think this function belongs here, but one place is as -% good as any other. I want to use this function when I want to -% express `no operation'. +% Then something similar for the |c| variants. +% \begin{verbatim} +% \cs_set_protected:Npn \cs_set:cn #1#2{ +% \cs_generate_from_arg_count:cNnn {#1}\cs_set:Npn +% {\cs_get_arg_count_from_signature:c {#1}}{#2} +% } +% \end{verbatim} % \begin{macrocode} -\def_new:Npn \use_noop: {} +\cs_set:Npn \cs_tmp:w #1#2#3{ + \cs_set_protected:cpx {cs_#1:#2}##1##2{ + \exp_not:N\cs_generate_from_arg_count:cNnn {##1} + \exp_after:wN \exp_not:N \cs:w cs_#1:#3 \cs_end: + {\exp_not:N\cs_get_arg_count_from_signature:c {##1}}{##2} + } +} % \end{macrocode} -% \end{macro} -% -% \subsubsection{Strings and input stream token lists} -% -% \begin{macro}{\cs_to_str:N} -% This converts a control sequence into the character string of its -% name, removing the leading escape character. +% \begin{macro}{\cs_set:cn} +% \begin{macro}{\cs_set:cx} +% \begin{macro}{\cs_set_nopar:cn} +% \begin{macro}{\cs_set_nopar:cx} +% \begin{macro}{\cs_set_protected:cn} +% \begin{macro}{\cs_set_protected:cx} +% \begin{macro}{\cs_set_protected_nopar:cn} +% \begin{macro}{\cs_set_protected_nopar:cx} +% \begin{macro}{\cs_gset:cn} +% \begin{macro}{\cs_gset:cx} +% \begin{macro}{\cs_gset_nopar:cn} +% \begin{macro}{\cs_gset_nopar:cx} +% \begin{macro}{\cs_gset_protected:cn} +% \begin{macro}{\cs_gset_protected:cx} +% \begin{macro}{\cs_gset_protected_nopar:cn} +% \begin{macro}{\cs_gset_protected_nopar:cx} +% The 32 |c| variants. % \begin{macrocode} -\def_new:Npn \cs_to_str:N {\exp_after:NN\use_none:n \token_to_string:N} +\cs_tmp:w {set}{cn}{Npn} +\cs_tmp:w {set}{cx}{Npx} +\cs_tmp:w {set_nopar}{cn}{Npn} +\cs_tmp:w {set_nopar}{cx}{Npx} +\cs_tmp:w {set_protected}{cn}{Npn} +\cs_tmp:w {set_protected}{cx}{Npx} +\cs_tmp:w {set_protected_nopar}{cn}{Npn} +\cs_tmp:w {set_protected_nopar}{cx}{Npx} +\cs_tmp:w {gset}{cn}{Npn} +\cs_tmp:w {gset}{cx}{Npx} +\cs_tmp:w {gset_nopar}{cn}{Npn} +\cs_tmp:w {gset_nopar}{cx}{Npx} +\cs_tmp:w {gset_protected}{cn}{Npn} +\cs_tmp:w {gset_protected}{cx}{Npx} +\cs_tmp:w {gset_protected_nopar}{cn}{Npn} +\cs_tmp:w {gset_protected_nopar}{cx}{Npx} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % -% -% -% -% -% \begin{macro}{\cs_if_eq:NNTF} -% \begin{macro}{\cs_if_eq:NNT} -% \begin{macro}{\cs_if_eq:NNF} -% \begin{macro}{\cs_if_eq:cNTF} -% \begin{macro}{\cs_if_eq:cNT} -% \begin{macro}{\cs_if_eq:cNF} -% \begin{macro}{\cs_if_eq:NcTF} -% \begin{macro}{\cs_if_eq:NcT} -% \begin{macro}{\cs_if_eq:NcF} -% \begin{macro}{\cs_if_eq:ccTF} -% \begin{macro}{\cs_if_eq:ccT} -% \begin{macro}{\cs_if_eq:ccF} -% Check if two control sequences are identical. +% \begin{macro}{\cs_new:cn} +% \begin{macro}{\cs_new:cx} +% \begin{macro}{\cs_new_nopar:cn} +% \begin{macro}{\cs_new_nopar:cx} +% \begin{macro}{\cs_new_protected:cn} +% \begin{macro}{\cs_new_protected:cx} +% \begin{macro}{\cs_new_protected_nopar:cn} +% \begin{macro}{\cs_new_protected_nopar:cx} +% \begin{macro}{\cs_gnew:cn} +% \begin{macro}{\cs_gnew:cx} +% \begin{macro}{\cs_gnew_nopar:cn} +% \begin{macro}{\cs_gnew_nopar:cx} +% \begin{macro}{\cs_gnew_protected:cn} +% \begin{macro}{\cs_gnew_protected:cx} +% \begin{macro}{\cs_gnew_protected_nopar:cn} +% \begin{macro}{\cs_gnew_protected_nopar:cx} % \begin{macrocode} -\def_test_function_new:npn {cs_if_eq:NN} #1#2{\if_meaning:NN #1#2} -\def_new:Npn \cs_if_eq:cNTF {\exp_args:Nc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:cNT {\exp_args:Nc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:cNF {\exp_args:Nc \cs_if_eq:NNF} -\def_new:Npn \cs_if_eq:NcTF {\exp_args:NNc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:NcT {\exp_args:NNc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:NcF {\exp_args:NNc \cs_if_eq:NNF} -\def_new:Npn \cs_if_eq:ccTF {\exp_args:Ncc \cs_if_eq:NNTF} -\def_new:Npn \cs_if_eq:ccT {\exp_args:Ncc \cs_if_eq:NNT} -\def_new:Npn \cs_if_eq:ccF {\exp_args:Ncc \cs_if_eq:NNF} +\cs_tmp:w {new}{cn}{Npn} +\cs_tmp:w {new}{cx}{Npx} +\cs_tmp:w {new_nopar}{cn}{Npn} +\cs_tmp:w {new_nopar}{cx}{Npx} +\cs_tmp:w {new_protected}{cn}{Npn} +\cs_tmp:w {new_protected}{cx}{Npx} +\cs_tmp:w {new_protected_nopar}{cn}{Npn} +\cs_tmp:w {new_protected_nopar}{cx}{Npx} +\cs_tmp:w {gnew}{cn}{Npn} +\cs_tmp:w {gnew}{cx}{Npx} +\cs_tmp:w {gnew_nopar}{cn}{Npn} +\cs_tmp:w {gnew_nopar}{cx}{Npx} +\cs_tmp:w {gnew_protected}{cn}{Npn} +\cs_tmp:w {gnew_protected}{cx}{Npx} +\cs_tmp:w {gnew_protected_nopar}{cn}{Npn} +\cs_tmp:w {gnew_protected_nopar}{cx}{Npx} % \end{macrocode} % \end{macro} % \end{macro} @@ -2669,158 +3184,101 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% +% +% +% \begin{macro}{\cs_if_eq_p:NN,\cs_if_eq_p:cN,\cs_if_eq_p:Nc,\cs_if_eq_p:cc} +% \begin{macro}[TF]{\cs_if_eq:NN,\cs_if_eq:cN,\cs_if_eq:Nc,\cs_if_eq:cc} +% Check if two control sequences are identical. +% \begin{macrocode} +\prg_set_conditional:Npnn \cs_if_eq:NN #1#2{p,TF,T,F}{ + \if_meaning:w #1#2 + \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_new_nopar:Npn \cs_if_eq_p:cN {\exp_args:Nc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:cNTF {\exp_args:Nc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:cNT {\exp_args:Nc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:cNF {\exp_args:Nc \cs_if_eq:NNF} +\cs_new_nopar:Npn \cs_if_eq_p:Nc {\exp_args:NNc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:NcTF {\exp_args:NNc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:NcT {\exp_args:NNc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:NcF {\exp_args:NNc \cs_if_eq:NNF} +\cs_new_nopar:Npn \cs_if_eq_p:cc {\exp_args:Ncc \cs_if_eq_p:NN} +\cs_new_nopar:Npn \cs_if_eq:ccTF {\exp_args:Ncc \cs_if_eq:NNTF} +\cs_new_nopar:Npn \cs_if_eq:ccT {\exp_args:Ncc \cs_if_eq:NNT} +\cs_new_nopar:Npn \cs_if_eq:ccF {\exp_args:Ncc \cs_if_eq:NNF} +% \end{macrocode} +% \end{macro} +% \end{macro} % % Finally some code that is needed as we do not distribute the file % module at the moment (so we simply define the needed function via an % existing \LaTeX{} command) and some other stuff which was set up % elsewhere, in undistributed modules. % \begin{macrocode} -\def_new:Npn\file_not_found:nTF #1#2#3{\IfFileExists{#1}{#3}{#2}} +\cs_new_nopar:Npn\file_not_found:nTF #1#2#3{\IfFileExists{#1}{#3}{#2}} % \end{macrocode} % % -% \subsubsection{Predicates and conditionals} -% \label{sec:predicates} -% -% \LaTeX3 has three concepts for conditional flow processing: -% \begin{enumerate} -% -% \item -% Functions that carry out a test an then execute, depending on its -% result, either the code supplied in the \m{true arg} or the \m{false -% arg}. These arguments are denoted with "T" and "F" repectively. An -% example would be -% \begin{quote} -% "\cs_free:cTF{abc}{...}{...}" -% \end{quote} -% a function that will turn the first argument into a control sequence -% (since its marked as "c") then checks whether this control sequence is -% still free and then depending on the result carry out the code in the -% second argument (true case) or in the third argument (false case). -% -% \item -% Functions that return a special type of boolean value which can be -% tested by the function "\if:w". All functions of this type -% have names that end with "_p" in the description part. For example -% \begin{quote} -% "\cs_free_p:N" -% \end{quote} -% would be a predicate function for the same type of test as the -% function above. It would return `true' if its argument (a single token -% denoted by "N") is still free for definition. It would be used in -% constructions like -% \begin{quote} -% "\if:w \cs_free_p:N \l_foo_bar ... \else: ... \fi:" -% \end{quote} -% -% \item -% Actually there is a third one, namely the original concept used in -% plain \TeX{}. This belongs to the second form but needs further -% thoughts. -% \end{enumerate} -% -% Important to note is that conditionals with \m{true code} and/or -% \m{false code} are always defined in a way that the code of the chosen -% alternative can operate on following tokens in the input stream while -% the predicate implementations always have an "\else:" or "\fi:" -% interfering. This can be important in scanner implementations. % +% \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn} +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional:NNn #1#2#3 { + \prg_set_eq_conditional_aux:NNNn \cs_set_eq:cc #1#2 {#3} +} +\cs_set:Npn \prg_new_eq_conditional:NNn #1#2#3 { + \prg_set_eq_conditional_aux:NNNn \cs_new_eq:cc #1#2 {#3} +} +% \end{macrocode} +% \begin{macro}[aux]{\prg_set_eq_conditional_aux:NNNn, +% \prg_set_eq_conditional_aux:NNNw} +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional_aux:NNNn #1#2#3#4 { + \prg_set_eq_conditional_aux:NNNw #1#2#3#4,?,\q_recursion_stop +} +% \end{macrocode} +% Manual clist loop over argument "#4". +% \begin{macrocode} +\cs_set:Npn \prg_set_eq_conditional_aux:NNNw #1#2#3#4, { + \if:w ? #4 \scan_stop: + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + #1 { + \exp_args:NNc \cs_split_function:NN #2 {prg_conditional_form_#4:nnn} + }{ + \exp_args:NNc \cs_split_function:NN #3 {prg_conditional_form_#4:nnn} + } + \prg_set_eq_conditional_aux:NNNw #1{#2}{#3} +} +% \end{macrocode} +% \begin{macrocode} +\cs_set:Npn \prg_conditional_form_p:nnn #1#2#3 {#1_p:#2} +\cs_set:Npn \prg_conditional_form_TF:nnn #1#2#3 {#1:#2TF} +\cs_set:Npn \prg_conditional_form_T:nnn #1#2#3 {#1:#2T} +\cs_set:Npn \prg_conditional_form_F:nnn #1#2#3 {#1:#2F} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \begin{macrocode} % +% \end{macrocode} +% +% \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.38 2006/08/06 17:05:25 morten -% Make \chk_new_cs:N bulletproof -% -% Revision 1.37 2006/07/30 14:37:47 morten -% Added \str_if_eq_var_p:nf -% -% Revision 1.36 2006/07/23 13:43:21 morten -% Removed extra occurrence of \str_if_eq_p:nn -% -% Revision 1.35 2006/07/17 22:25:31 morten -% Fix logic of \chk_new_cs:N and rename \cs_if_eq_p:NN to -% \cs_if_eq_name_p:NN because it is not their meaning but their names -% which are compared. -% -% Revision 1.34 2006/07/08 22:46:17 morten -% Rearranged some code and added complete set of \use_none: -% functions. -% -% Revision 1.33 2006/07/06 14:53:56 morten -% Added \def:NNn functions, reorganized code and much much more. -% -% Revision 1.32 2006/06/03 17:14:43 morten -% Added more \use_arg_... functions. -% -% Revision 1.31 2006/03/20 18:26:33 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.30 2006/01/22 19:35:46 morten -% Changed \use_none:nnn to gobble all tokens in one go and added -% \use_arg_i_ii:nn for l3keyval. -% -% Revision 1.29 2006/01/16 09:47:49 morten -% Fixed deleted brace +% \end{implementation} % -% Revision 1.28 2006/01/15 19:08:28 morten -% Fixed typos in some \if names -% -% Revision 1.27 2006/01/04 01:29:36 morten -% Changed "robust" to "protected". -% -% Revision 1.26 2005/12/27 09:53:55 morten -% Fixed some names, added a few more \use_... functions, changed RCS -% information retrieval -% -% Revision 1.25 2005/12/23 11:16:15 morten -% *** empty log message *** -% -% Revision 1.24 2005/12/02 15:21:55 morten -% Fixed minor typo -% -% Revision 1.23 2005/11/20 07:10:03 morten -% Added a few missing functions. New function type -% \def_test_function:npn to help define TF-type functions. -% -% Revision 1.22 2005/11/08 04:16:17 morten -% Fixed typo. -% -% Revision 1.21 2005/10/27 22:35:13 morten -% Cleaned up a bit and moved some code to l3num. -% -% Revision 1.20 2005/07/12 16:10:24 morten -% Allow \cs_if_eq_p:NN to accept \par. (Yes, real life experience) -% -% Revision 1.19 2005/04/06 21:34:55 morten -% Added more functions. Moved \engine_aleph:TF from l3prg -% -% Revision 1.18 2005/03/25 23:52:24 braams -% The definition of \next needs to be seen at initex time, -% not at typesetting time -% -% Revision 1.17 2005/03/22 23:28:46 morten -% Moved some code to l3prg, removed obsolete code, cleaned up documentation. -% -% Revision 1.16 2005/03/16 22:31:44 braams -% Changed definition of \c_zero and \c_minus_one -% -% Revision 1.15 2005/03/15 23:16:27 braams -% Some tweaking with the docstrip guards to get the documentation to -% come out right. -% -% Revision 1.14 2005/03/15 22:50:00 braams -% Made loadable by initex as the second file -% -% Revision 1.13 2005/03/11 21:32:21 braams -% Fixed the use of RCS information; -% moved \RequirePackage after \StopEventually +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3box.dtx b/Master/texmf-dist/source/latex/expl3/l3box.dtx index c697225b8b3..bf619435d63 100644 --- a/Master/texmf-dist/source/latex/expl3/l3box.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3box.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3box.dtx Copyright (C) 2005-2007 LaTeX3 project +%% File: l3box.dtx Copyright (C) 2005-2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3box.dtx 718 2007-12-16 22:59:58Z morten $ +\GetIdInfo$Id: l3box.dtx 1375 2009-06-01 12:28:52Z joseph $ {L3 Experimental Box module} %\iffalse %<*driver> @@ -44,9 +44,9 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3box.dtx} \end{document} % % \fi @@ -60,20 +60,19 @@ % \date{\filedate} % \maketitle % -% \section{Boxes} -% +% \begin{documentation} % % There are three kinds of box operations: horizontal mode denoted % with prefix |\hbox_|, vertical mode with prefix |\vbox_|, and the % generic operations working in both modes with prefix |\box_|. % % -% \subsection{Generic functions} +% \section{Generic functions} % % \begin{function}{% % \box_new:N | % \box_new:c | -% \box_new_l:N +%^^A \box_new_l:N % } % \begin{syntax} % "\box_new:N" @@ -103,18 +102,34 @@ % \end{texnote} % \end{function} % +% \begin{function}{\box_if_horizontal_p:N | +% \box_if_horizontal_p:c | +% \box_if_horizontal:N / (TF) | +% \box_if_horizontal:c / (TF) } +% \begin{syntax} +% "\box_if_horizontal:NTF" \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if is an horizontal box and executes accordingly. +% \end{function} +% +% \begin{function}{\box_if_vertical_p:N | +% \box_if_vertical_p:c | +% \box_if_vertical:N / (TF) | +% \box_if_vertical:c / (TF) } +% \begin{syntax} +% "\box_if_vertical:NTF" \Arg{true code} \Arg{false code} +% \end{syntax} +% Tests if is a vertical box and executes accordingly. +% \end{function} +% % \begin{function}{% % \box_if_empty_p:N | % \box_if_empty_p:c | -% \box_if_empty:NTF | -% \box_if_empty:cTF | -% \box_if_empty:NT | -% \box_if_empty:cT | -% \box_if_empty:NF | -% \box_if_empty:cF | +% \box_if_empty:N / (TF) | +% \box_if_empty:c / (TF) | % } % \begin{syntax} -% "\box_if_empty:NTF" "{"\m{true code}"}" "{"\m{false code}"}" +% "\box_if_empty:NTF" \Arg{true code} \Arg{false code} % \end{syntax} % Tests if is empty (void) and executes "code" according to the % test outcome. @@ -160,8 +175,8 @@ % \begin{syntax} % "\box_set_to_last:N" % \end{syntax} -% Sets equal to the previous box |\R_last_box| and removes -% |\R_last_box| from the current list (unless in outer vertical +% Sets equal to the previous box |\l_last_box| and removes +% |\l_last_box| from the current list (unless in outer vertical % or math mode). % \end{function} % @@ -172,7 +187,7 @@ % \box_move_down:nn | % } % \begin{syntax} -% "\box_move_left:nn" "{""}" "{""}" +% "\box_move_left:nn" \Arg{dimen} \Arg{box function} % \end{syntax} % Moves in the direction specified. is either an operation on a box such as "\box_use:N" or a @@ -258,23 +273,25 @@ % % % \begin{variable}{% -% \R_last_box | +% \l_last_box | % } % \begin{syntax} % \end{syntax} -% "\R_last_box" is a read-only box register. You can set other -% boxes to this box, which will then be removed from the current -% list. +% "\l_last_box" is more or less a read-only box register managed by the +% engine. It denotes the last box on the current list if there is one, +% otherwise it is void. You can set other +% boxes to this box, with the result that the last box on the current list is +% removed at the same time (so it is with variable with side-effects). % \end{variable} % % -% \subsection{Horizontal mode} +% \section{Horizontal mode} % % \begin{function}{% % \hbox:n | % } % \begin{syntax} -% "\hbox:n" "{""}" +% "\hbox:n" \Arg{contents} % \end{syntax} % Places a "hbox" of natural size. % \end{function} @@ -286,7 +303,7 @@ % \hbox_gset:cn | % } % \begin{syntax} -% "\hbox_set:Nn" "{"\m{contents}"}" +% "\hbox_set:Nn" \Arg{contents} % \end{syntax} % Sets to be a vertical mode box containing \m{contents}. It has % it's natural size. "\hbox_gset:Nn" does it globally. @@ -300,7 +317,7 @@ % \hbox_gset_to_wd:cnn | % } % \begin{syntax} -% "\hbox_set_to_wd:Nnn" "{"\m{dimen}"}" "{"\m{contents}"}" +% "\hbox_set_to_wd:Nnn" \Arg{dimen} \Arg{contents} % \end{syntax} % Sets to contain \m{contents} and have width . % "\hbox_gset_to_wd:Nn" does it globally. @@ -309,11 +326,14 @@ % % \begin{function}{% % \hbox_to_wd:nn | +% \hbox_to_zero:n | % } % \begin{syntax} -% "\hbox_to_wd:nn" "{""}" +% "\hbox_to_wd:nn" \Arg{dimen} +% "\hbox_to_zero:n" % \end{syntax} -% Places a of width containing . +% Places a of width containing . "\hbox_to_zero:n" +% is a shorthand for a width of zero. % \end{function} % % @@ -336,7 +356,9 @@ % % \begin{function}{% % \hbox_unpack:N | +% \hbox_unpack:c | % \hbox_unpack_clear:N | +% \hbox_unpack_clear:c | % } % \begin{syntax} % "\hbox_unpack:N" @@ -352,7 +374,17 @@ % % % -% \subsection{Vertical mode} +% \section{Vertical mode} +% +% \begin{function}{% +% \vbox:n | +% } +% \begin{syntax} +% "\vbox:n" \Arg{contents} +% \end{syntax} +% Places a "vbox" of natural size with baseline equal to the baseline +% of the last line in the box. +% \end{function} % % \begin{function}{% % \vbox_set:Nn | @@ -361,10 +393,10 @@ % \vbox_gset:cn | % } % \begin{syntax} -% "\vbox_set:Nn" "{"\m{contents}"}" +% "\vbox_set:Nn" \Arg{contents} % \end{syntax} % Sets to be a vertical mode box containing \m{contents}. It has -% it's natural size. "\vbox_gset:Nn" does it globally. +% its natural size. "\vbox_gset:Nn" does it globally. % \end{function} % % @@ -376,7 +408,7 @@ % \vbox_gset_to_ht:ccn | % } % \begin{syntax} -% "\vbox_set_to_ht:Nnn" "{"\m{dimen}"}" "{"\m{contents}"}" +% "\vbox_set_to_ht:Nnn" \Arg{dimen} \Arg{contents} % \end{syntax} % Sets to contain \m{contents} and have total height . % "\vbox_gset_to_ht:Nn" does it globally. @@ -401,7 +433,7 @@ % \vbox_set_split_to_ht:NNn | % } % \begin{syntax} -% "\vbox_set_split_to_ht:NNn" "{""}" +% "\vbox_set_split_to_ht:NNn" \Arg{dimen} % \end{syntax} % Sets to contain the top part of . % \begin{texnote} @@ -410,21 +442,11 @@ % \end{function} % % \begin{function}{% -% \vbox:n | -% } -% \begin{syntax} -% "\vbox:n" "{""}" -% \end{syntax} -% Places a "vbox" of natural size with baseline equal to the baseline -% of the last line in the box. -% \end{function} -% -% \begin{function}{% % \vbox_to_ht:nn | % \vbox_to_zero:n | % } % \begin{syntax} -% "\vbox_to_ht:nn" "{""}" \\ +% "\vbox_to_ht:nn" \Arg{dimen} \\ % "\vbox_to_zero:n" % \end{syntax} % Places a of size containing . @@ -433,7 +455,9 @@ % % \begin{function}{% % \vbox_unpack:N | +% \vbox_unpack:c | % \vbox_unpack_clear:N | +% \vbox_unpack_clear:c | % } % \begin{syntax} % "\vbox_unpack:N" @@ -446,19 +470,22 @@ % \end{function} % % -% \StopEventually{} +% \end{documentation} % +% \begin{implementation} % % -% \subsection{The Implementation} +% +% \section{\pkg{l3box} implementation} % % % Announce and ensure that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3prg,l3token}\par -%\RequirePackage{l3chk}\par +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % @@ -466,11 +493,10 @@ % comment it very extensively. % % -% \subsubsection{Generic boxes} +% \subsection{Generic boxes} % -% \begin{macro}{\box_new:N} -% \begin{macro}{\box_new_l:N} -% \begin{macro}{\box_new:c} +% \begin{macro}{\box_new:N,\box_new:c} +%^^A \begin{macro}{\box_new_l:N} % Defining a new \m{box} register. % \begin{macrocode} %<*initex> @@ -480,19 +506,26 @@ % shouldn't be allocated\dots % \begin{macrocode} \seq_put_right:Nn \g_box_allocation_seq {255} -\def_new:Npn \box_new:N #1 {\alloc_reg:NnNN g {box} \tex_mathchardef:D #1} -\def_new:Npn \box_new_l:N #1 {\alloc_reg:NnNN l {box} \tex_mathchardef:D #1} +\cs_new_nopar:Npn \box_new:N #1 {\alloc_reg:NnNN g {box} \tex_mathchardef:D #1} +\cs_new_nopar:Npn \box_new_l:N #1 {\alloc_reg:NnNN l {box} \tex_mathchardef:D #1} % % \end{macrocode} % When we run on top of \LaTeX, we just use its allocation % mechanism. % \begin{macrocode} -%\let_new:NN \box_new:N \newbox -\def_new:Npn \box_new:c {\exp_args:Nc \box_new:N} +%<*package> +\cs_new:Npn \box_new:N #1 { + \chk_if_free_cs:N #1 + \newbox #1 +} +% +% \end{macrocode} +% +% \begin{macrocode} +\cs_generate_variant:Nn \box_new:N {c} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} +%^^A \end{macro} % % \begin{macro}{\if_hbox:N} % \begin{macro}{\if_vbox:N} @@ -500,97 +533,97 @@ % The primitives for testing if a \m{box} is empty/void or which % type of box it is. % \begin{macrocode} -\let_new:NN \if_hbox:N \tex_ifhbox:D -\let_new:NN \if_vbox:N \tex_ifvbox:D -\let_new:NN \if_box_empty:N \tex_ifvoid:D +\cs_new_eq:NN \if_hbox:N \tex_ifhbox:D +\cs_new_eq:NN \if_vbox:N \tex_ifvbox:D +\cs_new_eq:NN \if_box_empty:N \tex_ifvoid:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % +% +% \begin{macro}{\box_if_horizontal_p:N,\box_if_horizontal_p:c} +% \begin{macro}{\box_if_vertical_p:N,\box_if_vertical_p:c} +% \begin{macro}[TF]{\box_if_horizontal:N,\box_if_horizontal:c} +% \begin{macro}[TF]{\box_if_vertical:N,\box_if_vertical:c} +% \begin{macrocode} +\prg_new_conditional:Nnn \box_if_horizontal:N {p,TF,T,F} { + \tex_ifhbox:D #1 \prg_return_true: \else: \prg_return_false: \fi: +} +\prg_new_conditional:Nnn \box_if_vertical:N {p,TF,T,F} { + \tex_ifvbox:D #1 \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_generate_variant:Nn \box_if_horizontal_p:N {c} +\cs_generate_variant:Nn \box_if_horizontal:NTF {c} +\cs_generate_variant:Nn \box_if_horizontal:NT {c} +\cs_generate_variant:Nn \box_if_horizontal:NF {c} +\cs_generate_variant:Nn \box_if_vertical_p:N {c} +\cs_generate_variant:Nn \box_if_vertical:NTF {c} +\cs_generate_variant:Nn \box_if_vertical:NT {c} +\cs_generate_variant:Nn \box_if_vertical:NF {c} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{\box_if_empty_p:N} % \begin{macro}{\box_if_empty_p:c} -% \begin{macro}{\box_if_empty:NTF} -% \begin{macro}{\box_if_empty:cTF} -% \begin{macro}{\box_if_empty:NT} -% \begin{macro}{\box_if_empty:cT} -% \begin{macro}{\box_if_empty:NF} -% \begin{macro}{\box_if_empty:cF} +% \begin{macro}[TF]{\box_if_empty:N} +% \begin{macro}[TF]{\box_if_empty:c} % Testing if a \m{box} is empty/void. % \begin{macrocode} -\def_new:Npn \box_if_empty_p:N #1{ - \if_box_empty:N #1 \c_true \else: \c_false \fi:} -\def_new:Npn \box_if_empty_p:c {\exp_args:Nc \box_if_empty_p:N} -\def_test_function_new:npn {box_if_empty:N}#1{\if_box_empty:N #1} -\def_new:Npn \box_if_empty:cTF {\exp_args:Nc \box_if_empty:NTF} -\def_new:Npn \box_if_empty:cT {\exp_args:Nc \box_if_empty:NT} -\def_new:Npn \box_if_empty:cF {\exp_args:Nc \box_if_empty:NF} +\prg_new_conditional:Nnn \box_if_empty:N {p,TF,T,F} { + \tex_ifvoid:D #1 \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_generate_variant:Nn \box_if_empty_p:N {c} +\cs_generate_variant:Nn \box_if_empty:NTF {c} +\cs_generate_variant:Nn \box_if_empty:NT {c} +\cs_generate_variant:Nn \box_if_empty:NF {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\box_set_eq:NN} -% \begin{macro}{\box_set_eq:cN} -% \begin{macro}{\box_set_eq:Nc} -% \begin{macro}{\box_set_eq:cc} +% \begin{macro}{\box_set_eq:NN,\box_set_eq:cN, +% \box_set_eq:Nc,\box_set_eq:cc} % Assigning the contents of a box to be another box. % This clears the second box globally (that's how \TeX{} does it). % \begin{macrocode} -\def_new:Npn \box_set_eq:NN #1#2 {\tex_setbox:D #1 \tex_box:D #2} -\def_new:Npn \box_set_eq:cN {\exp_args:Nc \box_set_eq:NN} -\def_new:Npn \box_set_eq:Nc {\exp_args:NNc \box_set_eq:NN} -\def_new:Npn \box_set_eq:cc {\exp_args:Ncc \box_set_eq:NN} +\cs_new_nopar:Npn \box_set_eq:NN #1#2 {\tex_setbox:D #1 \tex_box:D #2} +\cs_generate_variant:Nn \box_set_eq:NN {cN,Nc,cc} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\box_gset_eq:NN} -% \begin{macro}{\box_gset_eq:cN} -% \begin{macro}{\box_gset_eq:Nc} -% \begin{macro}{\box_gset_eq:cc} +% \begin{macro}{\box_gset_eq:NN,\box_gset_eq:cN, +% \box_gset_eq:Nc,\box_gset_eq:cc} % Global version of the above. % \begin{macrocode} -\def_new:Npn \box_gset_eq:NN {\pref_global:D\box_set_eq:NN} -\def_new:Npn \box_gset_eq:cN {\exp_args:Nc \box_gset_eq:NN} -\def_new:Npn \box_gset_eq:Nc {\exp_args:NNc \box_gset_eq:NN} -\def_new:Npn \box_gset_eq:cc {\exp_args:Ncc \box_gset_eq:NN} +\cs_new_nopar:Npn \box_gset_eq:NN {\pref_global:D\box_set_eq:NN} +\cs_generate_variant:Nn \box_gset_eq:NN {cN,Nc,cc} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\R_last_box} +% \begin{macro}{\l_last_box} % A different name for this read-only primitive. % \begin{macrocode} -\let_new:NN \R_last_box \tex_lastbox:D +\cs_new_eq:NN \l_last_box \tex_lastbox:D % \end{macrocode} % \end{macro} % -% \begin{macro}{\box_set_to_last:N} -% \begin{macro}{\box_set_to_last:c} -% \begin{macro}{\box_gset_to_last:N} -% \begin{macro}{\box_gset_to_last:c} +% \begin{macro}{\box_set_to_last:N,\box_set_to_last:c} +% \begin{macro}{\box_gset_to_last:N,\box_gset_to_last:c} % Set a box to the previous box. % \begin{macrocode} -\def_new:Npn \box_set_to_last:N #1{\tex_setbox:D#1\R_last_box} -\def_new:Npn \box_set_to_last:c {\exp_args:Nc \box_set_to_last:N} -\def_new:Npn \box_gset_to_last:N {\pref_global:D \box_set_to_last:N} -\def_new:Npn \box_gset_to_last:c {\exp_args:Nc \box_gset_to_last:N} +\cs_new_nopar:Npn \box_set_to_last:N #1{\tex_setbox:D#1\l_last_box} +\cs_generate_variant:Nn \box_set_to_last:N {c} +\cs_new_nopar:Npn \box_gset_to_last:N {\pref_global:D \box_set_to_last:N} +\cs_generate_variant:Nn \box_gset_to_last:N {c} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}{\box_move_left:nn} % \begin{macro}{\box_move_right:nn} @@ -598,89 +631,73 @@ % \begin{macro}{\box_move_down:nn} % Move box material in different directions. % \begin{macrocode} -\def_long_new:Npn \box_move_left:nn #1#2{\tex_moveleft:D\dim_eval:n{#1}{#2}} -\def_long_new:Npn \box_move_right:nn #1#2{\tex_moveright:D\dim_eval:n{#1}{#2}} -\def_long_new:Npn \box_move_up:nn #1#2{\tex_raise:D\dim_eval:n{#1}{#2}} -\def_long_new:Npn \box_move_down:nn #1#2{\tex_lower:D\dim_eval:n{#1}{#2}} +\cs_new:Npn \box_move_left:nn #1#2{\tex_moveleft:D\dim_eval:n{#1}{#2}} +\cs_new:Npn \box_move_right:nn #1#2{\tex_moveright:D\dim_eval:n{#1}{#2}} +\cs_new:Npn \box_move_up:nn #1#2{\tex_raise:D\dim_eval:n{#1}{#2}} +\cs_new:Npn \box_move_down:nn #1#2{\tex_lower:D\dim_eval:n{#1}{#2}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\box_clear:N} -% \begin{macro}{\box_clear:c} -% \begin{macro}{\box_gclear:N} -% \begin{macro}{\box_gclear:c} +% \begin{macro}{\box_clear:N,\box_clear:c} +% \begin{macro}{\box_gclear:N,\box_gclear:c} % Clear a \m{box} register. % \begin{macrocode} -\def_new:Npn \box_clear:N #1{\box_set_eq:NN #1 \c_empty_box } -\def_new:Npn \box_clear:c {\exp_args:Nc \box_clear:N } -\def_new:Npn \box_gclear:N {\pref_global:D\box_clear:N} -\def_new:Npn \box_gclear:c {\exp_args:Nc \box_gclear:c } +\cs_new_nopar:Npn \box_clear:N #1{\box_set_eq:NN #1 \c_empty_box } +\cs_generate_variant:Nn \box_clear:N {c} +\cs_new_nopar:Npn \box_gclear:N {\pref_global:D\box_clear:N} +\cs_generate_variant:Nn \box_gclear:N {c} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\box_ht:N} -% \begin{macro}{\box_ht:c} -% \begin{macro}{\box_dp:N} -% \begin{macro}{\box_dp:c} -% \begin{macro}{\box_wd:n} -% \begin{macro}{\box_wd:c} +% \begin{macro}{\box_ht:N,\box_ht:c} +% \begin{macro}{\box_dp:N,\box_dp:c} +% \begin{macro}{\box_wd:N,\box_wd:c} % Accessing the height, depth, and width of a \m{box} register. % \begin{macrocode} -\let_new:NN \box_ht:N \tex_ht:D -\def_new:Npn \box_ht:c {\exp_args:Nc \box_ht:N} -\let_new:NN \box_dp:N \tex_dp:D -\def_new:Npn \box_dp:c {\exp_args:Nc \box_dp:N} -\let_new:NN \box_wd:N \tex_wd:D -\def_new:Npn \box_wd:c {\exp_args:Nc \box_wd:N} +\cs_new_eq:NN \box_ht:N \tex_ht:D +\cs_new_eq:NN \box_dp:N \tex_dp:D +\cs_new_eq:NN \box_wd:N \tex_wd:D +\cs_generate_variant:Nn \box_ht:N {c} +\cs_generate_variant:Nn \box_dp:N {c} +\cs_generate_variant:Nn \box_wd:N {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\box_use_clear:N} -% \begin{macro}{\box_use_clear:c} -% \begin{macro}{\box_use:N} -% \begin{macro}{\box_use:c} -% Using a \m{box}. This is just \TeX{} primitives with meaningful +% \begin{macro}{\box_use_clear:N,\box_use_clear:c} +% \begin{macro}{\box_use:N,\box_use:c} +% Using a \m{box}. These are just \TeX{} primitives with meaningful % names. % \begin{macrocode} -\let_new:NN \box_use_clear:N \tex_box:D -\def_new:Npn \box_use_clear:c {\exp_args:Nc \box_use_clear:N} -\let_new:NN \box_use:N \tex_copy:D -\def_new:Npn \box_use:c {\exp_args:Nc \box_use:N} +\cs_new_eq:NN \box_use_clear:N \tex_box:D +\cs_generate_variant:Nn \box_use_clear:N {c} +\cs_new_eq:NN \box_use:N \tex_copy:D +\cs_generate_variant:Nn \box_use:N {c} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\box_show:N} -% \begin{macro}{\box_show:c} +% \begin{macro}{\box_show:N,\box_show:c} % Show the contents of a box and write it into the log file. % \begin{macrocode} -\let:NN \box_show:N \tex_showbox:D -\def_new:Npn \box_show:c {\exp_args:Nc \box_show:N} +\cs_set_eq:NN \box_show:N \tex_showbox:D +\cs_generate_variant:Nn \box_show:N {c} % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}{\c_empty_box} % \begin{macro}{\l_tmpa_box} % \begin{macro}{\l_tmpb_box} % We allocate some \m{box} registers here (and borrow a few from \LaTeX). % \begin{macrocode} -%\let:NN \c_empty_box \voidb@x -%\let_new:NN \l_tmpa_box \@tempboxa +%\cs_set_eq:NN \c_empty_box \voidb@x +%\cs_new_eq:NN \l_tmpa_box \@tempboxa %\box_new:N \c_empty_box %\box_new:N \l_tmpa_box \box_new:N \l_tmpb_box @@ -690,66 +707,56 @@ % \end{macro} % % -% \subsubsection{Vertical boxes} +% \subsection{Vertical boxes} % % % \begin{macro}{\vbox:n} % Put a vertical box directly into the input stream. % \begin{macrocode} -\def_new:Npn \vbox:n {\tex_vbox:D \scan_stop:} +\cs_new_nopar:Npn \vbox:n {\tex_vbox:D \scan_stop:} % \end{macrocode} % \end{macro} % -% \begin{macro}{\vbox_set:Nn} -% \begin{macro}{\vbox_set:cn} -% \begin{macro}{\vbox_gset:Nn} -% \begin{macro}{\vbox_gset:cn} +% \begin{macro}{\vbox_set:Nn,\vbox_set:cn} +% \begin{macro}{\vbox_gset:Nn,\vbox_gset:cn} % Storing material in a vertical box with a natural height. % \begin{macrocode} -\def_long_new:Npn \vbox_set:Nn #1#2 {\tex_setbox:D #1 \tex_vbox:D {#2}} -\def_new:Npn \vbox_set:cn {\exp_args:Nc \vbox_set:Nn} -\def_new:Npn \vbox_gset:Nn {\pref_global:D \vbox_set:Nn} -\def_new:Npn \vbox_gset:cn {\exp_args:Nc \vbox_gset:Nn} +\cs_new:Npn \vbox_set:Nn #1#2 {\tex_setbox:D #1 \tex_vbox:D {#2}} +\cs_generate_variant:Nn \vbox_set:Nn {cn} +\cs_new_nopar:Npn \vbox_gset:Nn {\pref_global:D \vbox_set:Nn} +\cs_generate_variant:Nn \vbox_gset:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\vbox_set_to_ht:Nnn} -% \begin{macro}{\vbox_set_to_ht:cnn} -% \begin{macro}{\vbox_gset_to_ht:Nnn} -% \begin{macro}{\vbox_gset_to_ht:cnn} -% \begin{macro}{\vbox_gset_to_ht:ccn} +% \begin{macro}{\vbox_set_to_ht:Nnn,\vbox_set_to_ht:cnn} +% \begin{macro}{\vbox_gset_to_ht:Nnn,\vbox_gset_to_ht:cnn,\vbox_gset_to_ht:ccn} % Storing material in a vertical box with a specified height. % \begin{macrocode} -\def_long_new:Npn \vbox_set_to_ht:Nnn #1#2#3 { - \tex_setbox:D #1 \tex_vbox:D to #2 {#3}} -\def_new:Npn \vbox_set_to_ht:cnn{\exp_args:Nc \vbox_set_to_ht:Nnn } -\def_new:Npn \vbox_gset_to_ht:Nnn {\pref_global:D \vbox_set_to_ht:Nnn } -\def_new:Npn \vbox_gset_to_ht:cnn{\exp_args:Nc \vbox_gset_to_ht:Nnn } -\def_new:Npn \vbox_gset_to_ht:ccn {\exp_args:Ncc \vbox_gset_to_ht:Nnn} +\cs_new:Npn \vbox_set_to_ht:Nnn #1#2#3 { + \tex_setbox:D #1 \tex_vbox:D to #2 {#3} +} +\cs_generate_variant:Nn \vbox_set_to_ht:Nnn {cnn} +\cs_new_nopar:Npn \vbox_gset_to_ht:Nnn { \pref_global:D \vbox_set_to_ht:Nnn } +\cs_generate_variant:Nn \vbox_gset_to_ht:Nnn {cnn,ccn} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % % \begin{macro}{\vbox_set_inline_begin:N} % \begin{macro}{\vbox_set_inline_end:} % \begin{macro}{\vbox_gset_inline_begin:N} -% \begin{macro}{\vbox_set_inline_end:} +% \begin{macro}{\vbox_gset_inline_end:} % Storing material in a vertical box. This type is useful in % environment definitions. % \begin{macrocode} -\def_new:Npn \vbox_set_inline_begin:N #1 { +\cs_new_nopar:Npn \vbox_set_inline_begin:N #1 { \tex_setbox:D #1 \tex_vbox:D \c_group_begin_token } -\let_new:NN \vbox_set_inline_end: \c_group_end_token -\def_new:Npn \vbox_gset_inline_begin:N { +\cs_new_eq:NN \vbox_set_inline_end: \c_group_end_token +\cs_new_nopar:Npn \vbox_gset_inline_begin:N { \pref_global:D \vbox_set_inline_begin:N } -\let_new:NN \vbox_gset_inline_end: \c_group_end_token +\cs_new_eq:NN \vbox_gset_inline_end: \c_group_end_token % \end{macrocode} % \end{macro} % \end{macro} @@ -761,8 +768,8 @@ % \begin{macro}{\vbox_to_zero:n} % Put a vertical box directly into the input stream. % \begin{macrocode} -\def_long_new:Npn \vbox_to_ht:nn #1#2{\tex_vbox:D to \dim_eval:n{#1}{#2}} -\def_long_new:Npn \vbox_to_zero:n #1 {\tex_vbox:D to \c_zero_dim {#1}} +\cs_new:Npn \vbox_to_ht:nn #1#2{\tex_vbox:D to \dim_eval:n{#1}{#2}} +\cs_new:Npn \vbox_to_zero:n #1 {\tex_vbox:D to \c_zero_dim {#1}} % \end{macrocode} % \end{macro} % \end{macro} @@ -770,130 +777,111 @@ % \begin{macro}{\vbox_set_split_to_ht:NNn} % Splitting a vertical box in two. % \begin{macrocode} -\def_new:Npn \vbox_set_split_to_ht:NNn #1#2#3{ +\cs_new_nopar:Npn \vbox_set_split_to_ht:NNn #1#2#3{ \tex_setbox:D #1 \tex_vsplit:D #2 to #3 } % \end{macrocode} % \end{macro} % -% \begin{macro}{\vbox_unpack:N} -% \begin{macro}{\vbox_unpack:c} -% \begin{macro}{\vbox_unpack_clear:N} -% \begin{macro}{\vbox_unpack_clear:c} +% \begin{macro}{\vbox_unpack:N,\vbox_unpack:c} +% \begin{macro}{\vbox_unpack_clear:N,\vbox_unpack_clear:c} % Unpacking a box and if requested also clear it. % \begin{macrocode} -\let_new:NN \vbox_unpack:N \tex_unvcopy:D -\def_new:Npn \vbox_unpack:c {\exp_args:Nc \vbox_unpack:N} -\let_new:NN \vbox_unpack_clear:N \tex_unvbox:D -\def_new:Npn \vbox_unpack_clear:c {\exp_args:Nc \vbox_unpack_clear:N} +\cs_new_eq:NN \vbox_unpack:N \tex_unvcopy:D +\cs_generate_variant:Nn \vbox_unpack:N {c} +\cs_new_eq:NN \vbox_unpack_clear:N \tex_unvbox:D +\cs_generate_variant:Nn \vbox_unpack_clear:N {c} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % % % % % -% \subsubsection{Horizontal boxes} +% \subsection{Horizontal boxes} % % % \begin{macro}{\hbox:n} % Put a horizontal box directly into the input stream. % \begin{macrocode} -\def_new:Npn \hbox:n {\tex_hbox:D \scan_stop:} +\cs_new_nopar:Npn \hbox:n {\tex_hbox:D \scan_stop:} % \end{macrocode} % \end{macro} % -% \begin{macro}{\hbox_set:Nn} -% \begin{macro}{\hbox_set:cn} -% \begin{macro}{\hbox_gset:Nn} -% \begin{macro}{\hbox_gset:cn} +% \begin{macro}{\hbox_set:Nn,\hbox_set:cn} +% \begin{macro}{\hbox_gset:Nn,\hbox_gset:cn} % Assigning the contents of a box to be another box. % This clears the second box globally (that's how \TeX{} does it). % \begin{macrocode} -\def_long_new:Npn \hbox_set:Nn #1#2 {\tex_setbox:D #1 \tex_hbox:D {#2}} -\def_new:Npn \hbox_set:cn {\exp_args:Nc \hbox_set:Nn} -\def_new:Npn \hbox_gset:Nn {\pref_global:D \hbox_set:Nn} -\def_new:Npn \hbox_gset:cn {\exp_args:Nc \hbox_gset:Nn} +\cs_new:Npn \hbox_set:Nn #1#2 {\tex_setbox:D #1 \tex_hbox:D {#2}} +\cs_generate_variant:Nn \hbox_set:Nn {cn} +\cs_new_nopar:Npn \hbox_gset:Nn {\pref_global:D \hbox_set:Nn} +\cs_generate_variant:Nn \hbox_gset:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\hbox_set_to_wd:Nnn} -% \begin{macro}{\hbox_set_to_wd:cnn} -% \begin{macro}{\hbox_gset_to_wd:Nnn} -% \begin{macro}{\hbox_gset_to_wd:cnn} +% \begin{macro}{\hbox_set_to_wd:Nnn,\hbox_set_to_wd:cnn} +% \begin{macro}{\hbox_gset_to_wd:Nnn,\hbox_gset_to_wd:cnn} % Storing material in a horizontal box with a specified width. % \begin{macrocode} -\def_long_new:Npn \hbox_set_to_wd:Nnn #1#2#3 { - \tex_setbox:D #1 \tex_hbox:D to \dim_eval:n{#2} {#3}} -\def_new:Npn \hbox_set_to_wd:cnn{\exp_args:Nc \hbox_set_to_wd:Nnn } -\def_new:Npn \hbox_gset_to_wd:Nnn {\pref_global:D \hbox_set_to_wd:Nnn } -\def_new:Npn \hbox_gset_to_wd:cnn{\exp_args:Nc \hbox_gset_to_wd:Nnn } +\cs_new:Npn \hbox_set_to_wd:Nnn #1#2#3 { + \tex_setbox:D #1 \tex_hbox:D to \dim_eval:n{#2} {#3} +} +\cs_generate_variant:Nn \hbox_set_to_wd:Nnn {cnn} +\cs_new_nopar:Npn \hbox_gset_to_wd:Nnn {\pref_global:D \hbox_set_to_wd:Nnn } +\cs_generate_variant:Nn \hbox_gset_to_wd:Nnn {cnn} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\hbox_set_inline_begin:N} -% \begin{macro}{\hbox_set_inline_begin:c} -% \begin{macro}{\hbox_set_inline_end:} -% \begin{macro}{\hbox_gset_inline_begin:N} -% \begin{macro}{\hbox_gset_inline_begin:c} +% \begin{macro}{\hbox_set_inline_begin:N,\hbox_set_inline_begin:c} % \begin{macro}{\hbox_set_inline_end:} +% \begin{macro}{\hbox_gset_inline_begin:N,\hbox_gset_inline_begin:c} +% \begin{macro}{\hbox_gset_inline_end:} % Storing material in a horizontal box. This type is useful in % environment definitions. % \begin{macrocode} -\def_new:Npn \hbox_set_inline_begin:N #1 { - \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token } -\def:Npn \hbox_set_inline_begin:c {\exp_args:Nc - \hbox_set_inline_begin:N} -\let_new:NN \hbox_set_inline_end: \c_group_end_token -\def_new:Npn \hbox_gset_inline_begin:N { - \pref_global:D \hbox_set_inline_begin:N } -\def:Npn \hbox_gset_inline_begin:c {\exp_args:Nc - \hbox_gset_inline_begin:N } -\let_new:NN \hbox_gset_inline_end: \c_group_end_token +\cs_new_nopar:Npn \hbox_set_inline_begin:N #1 { + \tex_setbox:D #1 \tex_hbox:D \c_group_begin_token +} +\cs_generate_variant:Nn \hbox_set_inline_begin:N {c} +\cs_new_eq:NN \hbox_set_inline_end: \c_group_end_token +\cs_new_nopar:Npn \hbox_gset_inline_begin:N { + \pref_global:D \hbox_set_inline_begin:N +} +\cs_generate_variant:Nn \hbox_gset_inline_begin:N {c} +\cs_new_eq:NN \hbox_gset_inline_end: \c_group_end_token % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}{\hbox_to_wd:nn} % \begin{macro}{\hbox_to_zero:n} % Put a horizontal box directly into the input stream. % \begin{macrocode} -\def_long_new:Npn \hbox_to_wd:nn #1#2 {\tex_hbox:D to #1 {#2}} -\def_long_new:Npn \hbox_to_zero:n #1 {\tex_hbox:D to \c_zero_skip {#1}} +\cs_new:Npn \hbox_to_wd:nn #1#2 {\tex_hbox:D to #1 {#2}} +\cs_new:Npn \hbox_to_zero:n #1 {\tex_hbox:D to \c_zero_skip {#1}} % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\hbox_unpack:N} -% \begin{macro}{\hbox_unpack:c} -% \begin{macro}{\hbox_unpack_clear:N} -% \begin{macro}{\hbox_unpack_clear:c} +% \begin{macro}{\hbox_unpack:N,\hbox_unpack:c} +% \begin{macro}{\hbox_unpack_clear:N,\hbox_unpack_clear:c} % Unpacking a box and if requested also clear it. % \begin{macrocode} -\let_new:NN \hbox_unpack:N \tex_unhcopy:D -\def_new:Npn \hbox_unpack:c {\exp_args:Nc \hbox_unpack:N} -\let_new:NN \hbox_unpack_clear:N \tex_unhbox:D -\def_new:Npn \hbox_unpack_clear:c {\exp_args:Nc \hbox_unpack_clear:N} +\cs_new_eq:NN \hbox_unpack:N \tex_unhcopy:D +\cs_generate_variant:Nn \hbox_unpack:N {c} +\cs_new_eq:NN \hbox_unpack_clear:N \tex_unhbox:D +\cs_generate_variant:Nn \hbox_unpack_clear:N {c} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} % % % @@ -910,40 +898,15 @@ % % \begin{macrocode} % +% \end{macrocode} +% +% \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.10 2006/03/20 18:26:34 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.9 2006/01/19 22:30:30 morten -% Added functions for accessing \tex_lastbox:D and moving box material -% in the four directions. -% -% Revision 1.8 2005/12/27 16:04:12 morten -% Changed RCS information retrieval -% -% Revision 1.7 2005/10/27 23:11:12 morten -% Moved \if_hbox:N, \if_vbox:N and _if_box_empty:N here -% -% Revision 1.6 2005/04/25 16:15:17 morten -% Fixed \bgroup/\egroup and made it run under initex -% -% Revision 1.5 2005/04/06 22:35:33 braams -% Now we have register allocation fitted -% -% Revision 1.4 2005/03/26 21:08:12 morten -% Fix \c_zero -> \c_zero_skip -% -% Revision 1.3 2005/03/16 22:36:46 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.2 2005/03/11 21:31:07 braams -% Fixed the use of RCS information; added \StopEventually +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3calc.dtx b/Master/texmf-dist/source/latex/expl3/l3calc.dtx index 842e68864c7..c9519f13ca4 100644 --- a/Master/texmf-dist/source/latex/expl3/l3calc.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3calc.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3calc.dtx Copyright (C) 2006 LaTeX3 project +%% File: l3calc.dtx Copyright (C) 2006,2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -35,7 +35,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3calc.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3calc.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental calc module} %\iffalse %<*driver> @@ -43,7 +43,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -58,8 +58,8 @@ % \date{\filedate} % \maketitle % -% \section{Infix notation arithmetic} -% +% \begin{documentation} +% % This is pretty much a straight adaption of the \textsf{calc} package % and as such has same syntax for the \meta{calc expression}. However, % there are some noticeable differences. @@ -83,16 +83,51 @@ % the original \textsf{calc} package providing the same functionality % and will prevent the original \textsf{calc} package from loading. % +% \section{User functions} +% +% +% \begin{function}{ \maxof | +% \minof | +% \widthof | +% \heightof | +% \depthof | +% \totalheightof | +% \ratio | +% \real | +% \setlength | +% \gsetlength | +% \addtolength | +% \gaddtolength | +% \setcounter | +% \addtocounter | +% \stepcounter } +% See documentation for \LaTeXe\ package \pkg{calc}. +% \end{function} +% +% \begin{function}{ \calc_maxof:nn | +% \calc_minof:nn | +% \calc_widthof:n | +% \calc_heightof:n | +% \calc_depthof:n | +% \calc_totalheightof:n | +% \calc_ratio:nn | +% \calc_real:n | +% \calc_setcounter:nn | +% \calc_addtocounter:nn | +% \calc_stepcounter:n } +% Equivalent commands as the above in the \pkg{expl3} namespace. +% \end{function} +% % \begin{function}{ % \calc_int_set:Nn | % \calc_int_gset:Nn | % \calc_int_add:Nn | % \calc_int_gadd:Nn | % \calc_int_sub:Nn | -% \calc_int_gsub:Nn | +% \calc_int_gsub:Nn % } % \begin{syntax} -% "\calc_int_set:Nn" "{""}" +% "\calc_int_set:Nn" \Arg{calc expression} % \end{syntax} % Evaluates and either adds or subtracts it from % or sets to it. These operations can also be global. @@ -108,7 +143,7 @@ % \calc_dim_gsub:Nn | % } % \begin{syntax} -% "\calc_dim_set:Nn" "{""}" +% "\calc_dim_set:Nn" \Arg{calc expression} % \end{syntax} % Evaluates and either adds or subtracts it from % or sets to it. These operations can also be global. @@ -124,7 +159,7 @@ % \calc_skip_gsub:Nn | % } % \begin{syntax} -% "\calc_skip_set:Nn" "{""}" +% "\calc_skip_set:Nn" \Arg{calc expression} % \end{syntax} % Evaluates and either adds or subtracts it from % or sets to it. These operations can also be global. @@ -140,7 +175,7 @@ % \calc_muskip_gsub:Nn | % } % \begin{syntax} -% "\calc_muskip_set:Nn" "{""}" +% "\calc_muskip_set:Nn" \Arg{calc expression} % \end{syntax} % Evaluates and either adds or subtracts it from % or sets to it. These operations can also be @@ -152,8 +187,8 @@ % \calc_calculate_box_size:nnn | % } % \begin{syntax} -% "\calc_calculate_box_size:nnn" "{""}" \\ -% "{" ... "}" "{""}" +% "\calc_calculate_box_size:nnn" \Arg{dim-set} \\ +% "{" ... "}" \Arg{contents} % \end{syntax} % Sets in a temporary box "\l_tmpa_box". Then % is put in front of a loop that inserts "+"\meta{item$\sb{i}$} in @@ -172,9 +207,72 @@ % \end{verbatim} % \end{function} % -% \StopEventually{} +% \end{documentation} +% +% \begin{implementation} +% % -% \subsection{The Implementation} +% \section{\pkg{l3calc} implementation} +% +% \subsection{Variables} +% +% \begin{function}{ \l_calc_expression_tl | +% \g_calc_A_register | +% \l_calc_B_register | +% \l_calc_current_type_int | +% \g_calc_A_int | +% \l_calc_B_int | +% \l_calc_C_int | +% \g_calc_A_dim | +% \l_calc_B_dim | +% \l_calc_C_dim | +% \g_calc_A_skip | +% \l_calc_B_skip | +% \l_calc_C_skip | +% \g_calc_A_muskip | +% \l_calc_B_muskip | +% \l_calc_C_muskip } +% Internal registers. +% \end{function} +% +% \subsection{Internal functions} +% +% \begin{function}{ \calc_assign_generic:NNNNnn | +% \calc_pre_scan:N | +% \calc_open:w | +% \calc_init_B: | +% \calc_numeric: | +% \calc_close: | +% \calc_post_scan:N | +% \calc_multiply:N | +% \calc_divide:N | +% \calc_generic_add_or_subtract:N | +% \calc_add: | +% \calc_subtract: | +% \calc_add_A_to_B: | +% \calc_subtract_A_from_B: | +% \calc_generic_multiply_or_divide:N | +% \calc_multiply_B_by_A: | +% \calc_divide_B_by_A: | +% \calc_multiply: | +% \calc_divide: | +% \calc_textsize:Nn | +% \calc_ratio_multiply:nn | +% \calc_ratio_divide:nn | +% \calc_real_evaluate:nn | +% \calc_real_multiply:n | +% \calc_real_divide:n | +% \calc_maxmin_operation:Nnn | +% \calc_maxmin_generic:Nnn | +% \calc_maxmin_div_or_mul:NNnn | +% \calc_maxmin_multiply: | +% \calc_maxmin_multiply: | +% \calc_error:N | +% \calc_chk_document_counter:nn } +% Awaiting better documentation ":)" +% \end{function} +% +% \subsection{Module code} % % Since this is basically a re-worked version of the \textsf{calc} % package, I haven't bothered with too many comments except for in the @@ -186,23 +284,21 @@ %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} -\RequirePackage{l3int} -\RequirePackage{l3skip} -\RequirePackage{l3box} +\package_check_loaded_expl: % %<*initex|package> % \end{macrocode} % % -% \begin{macro}{\l_calc_expression_tlp} +% \begin{macro}{\l_calc_expression_tl} % \begin{macro}{\g_calc_A_register} % \begin{macro}{\l_calc_B_register} % \begin{macro}{\l_calc_current_type_int} % Here we define some registers and pointers we will need. % \begin{macrocode} -\tlp_new:Nn\l_calc_expression_tlp{} -\def_new:Npn \g_calc_A_register{} -\def_new:Npn \l_calc_B_register{} +\tl_new:Nn\l_calc_expression_tl{} +\cs_new_nopar:Npn \g_calc_A_register{} +\cs_new_nopar:Npn \l_calc_B_register{} \int_new:N \l_calc_current_type_int % \end{macrocode} % \end{macro} @@ -261,17 +357,17 @@ % little extra work so that |\real| and |\ratio| can still be used % by the user. % \begin{macrocode} -\def_long_new:Npn \calc_assign_generic:NNNNnn#1#2#3#4#5#6{ - \let:NN\g_calc_A_register#2 - \let:NN\l_calc_B_register#3 +\cs_new:Npn \calc_assign_generic:NNNNnn#1#2#3#4#5#6{ + \cs_set_eq:NN\g_calc_A_register#2 + \cs_set_eq:NN\l_calc_B_register#3 \int_set:Nn \l_calc_current_type_int {#1} \group_begin: - \let:NN \real \calc_real:n - \let:NN \ratio\calc_ratio:nn - \tlp_set:Nx\l_calc_expression_tlp{#6} - \exp_after:NN + \cs_set_eq:NN \real \calc_real:n + \cs_set_eq:NN \ratio\calc_ratio:nn + \tl_set:Nx\l_calc_expression_tl{#6} + \exp_after:wN \group_end: - \exp_after:NN\calc_open:w\exp_after:NN(\l_calc_expression_tlp ! + \exp_after:wN\calc_open:w\exp_after:wN(\l_calc_expression_tl ! \pref_global:D\g_calc_A_register\l_calc_B_register \group_end: #4{#5}\l_calc_B_register @@ -280,11 +376,11 @@ % A simpler version relying on |\real| and |\ratio| having our % definition is % \begin{verbatim} -% \def_long_new:Npn \calc_assign_generic:NNNNnn#1#2#3#4#5#6{ -% \let:NN\g_calc_A_register#2\let:NN\l_calc_B_register#3 +% \cs_new:Npn \calc_assign_generic:NNNNnn#1#2#3#4#5#6{ +% \cs_set_eq:NN\g_calc_A_register#2\cs_set_eq:NN\l_calc_B_register#3 % \int_set:Nn \l_calc_current_type_int {#1} -% \tlp_set:Nx\l_calc_expression_tlp{#6} -% \exp_after:NN\calc_open:w\exp_after:NN(\l_calc_expression_tlp ! +% \tl_set:Nx\l_calc_expression_tl{#6} +% \exp_after:wN\calc_open:w\exp_after:wN(\l_calc_expression_tl ! % \pref_global:D\g_calc_A_register\l_calc_B_register % \group_end: % #4{#5}\l_calc_B_register @@ -303,22 +399,22 @@ % Here are the individual versions for the different register % types. First integer registers. % \begin{macrocode} -\def_new:Npn\calc_int_set:Nn{ +\cs_new_nopar:Npn\calc_int_set:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_set:Nn } -\def_new:Npn\calc_int_gset:Nn{ +\cs_new_nopar:Npn\calc_int_gset:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_gset:Nn } -\def_new:Npn\calc_int_add:Nn{ +\cs_new_nopar:Npn\calc_int_add:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_add:Nn } -\def_new:Npn\calc_int_gadd:Nn{ +\cs_new_nopar:Npn\calc_int_gadd:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_gadd:Nn } -\def_new:Npn\calc_int_sub:Nn{ +\cs_new_nopar:Npn\calc_int_sub:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_sub:Nn } -\def_new:Npn\calc_int_gsub:Nn{ +\cs_new_nopar:Npn\calc_int_gsub:Nn{ \calc_assign_generic:NNNNnn\c_zero\g_calc_A_int\l_calc_B_int\int_gsub:Nn } % \end{macrocode} @@ -337,22 +433,22 @@ % \begin{macro}{\calc_dim_gsub:Nn} % Dimens. % \begin{macrocode} -\def_new:Npn\calc_dim_set:Nn{ +\cs_new_nopar:Npn\calc_dim_set:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_dim\l_calc_B_dim\dim_set:Nn } -\def_new:Npn\calc_dim_gset:Nn{ +\cs_new_nopar:Npn\calc_dim_gset:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_dim\l_calc_B_dim\dim_gset:Nn } -\def_new:Npn\calc_dim_add:Nn{ +\cs_new_nopar:Npn\calc_dim_add:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_dim\l_calc_B_dim\dim_add:Nn } -\def_new:Npn\calc_dim_gadd:Nn{ +\cs_new_nopar:Npn\calc_dim_gadd:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_dim\l_calc_B_dim\dim_gadd:Nn } -\def_new:Npn\calc_dim_sub:Nn{ +\cs_new_nopar:Npn\calc_dim_sub:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_int\l_calc_B_int\dim_sub:Nn } -\def_new:Npn\calc_dim_gsub:Nn{ +\cs_new_nopar:Npn\calc_dim_gsub:Nn{ \calc_assign_generic:NNNNnn\c_one\g_calc_A_int\l_calc_B_int\dim_gsub:Nn } % \end{macrocode} @@ -371,22 +467,22 @@ % \begin{macro}{\calc_skip_gsub:Nn} % Skips. % \begin{macrocode} -\def_new:Npn\calc_skip_set:Nn{ +\cs_new_nopar:Npn\calc_skip_set:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_set:Nn } -\def_new:Npn\calc_skip_gset:Nn{ +\cs_new_nopar:Npn\calc_skip_gset:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_gset:Nn } -\def_new:Npn\calc_skip_add:Nn{ +\cs_new_nopar:Npn\calc_skip_add:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_add:Nn } -\def_new:Npn\calc_skip_gadd:Nn{ +\cs_new_nopar:Npn\calc_skip_gadd:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_gadd:Nn } -\def_new:Npn\calc_skip_sub:Nn{ +\cs_new_nopar:Npn\calc_skip_sub:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_sub:Nn } -\def_new:Npn\calc_skip_gsub:Nn{ +\cs_new_nopar:Npn\calc_skip_gsub:Nn{ \calc_assign_generic:NNNNnn\c_two\g_calc_A_skip\l_calc_B_skip\skip_gsub:Nn } % \end{macrocode} @@ -405,27 +501,27 @@ % \begin{macro}{\calc_muskip_gsub:Nn} % Muskips. % \begin{macrocode} -\def_new:Npn\calc_muskip_set:Nn{ +\cs_new_nopar:Npn\calc_muskip_set:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_set:Nn } -\def_new:Npn\calc_muskip_gset:Nn{ +\cs_new_nopar:Npn\calc_muskip_gset:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_gset:Nn } -\def_new:Npn\calc_muskip_add:Nn{ +\cs_new_nopar:Npn\calc_muskip_add:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_add:Nn } -\def_new:Npn\calc_muskip_gadd:Nn{ +\cs_new_nopar:Npn\calc_muskip_gadd:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_gadd:Nn } -\def_new:Npn\calc_muskip_sub:Nn{ +\cs_new_nopar:Npn\calc_muskip_sub:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_add:Nn } -\def_new:Npn\calc_muskip_gsub:Nn{ +\cs_new_nopar:Npn\calc_muskip_gsub:Nn{ \calc_assign_generic:NNNNnn\c_three\g_calc_A_muskip\l_calc_B_muskip \muskip_gadd:Nn } @@ -442,13 +538,13 @@ % In case we found one of the special operations, this should just % be executed. % \begin{macrocode} -\def_new:Npn \calc_pre_scan:N #1{ - \if_meaning:NN(#1 - \exp_after:NN\calc_open:w +\cs_new_nopar:Npn \calc_pre_scan:N #1{ + \if_meaning:w(#1 + \exp_after:wN\calc_open:w \else: - \if_meaning:NN \calc_textsize:Nn #1 + \if_meaning:w \calc_textsize:Nn #1 \else: - \if_meaning:NN \calc_maxmin_operation:Nnn #1 + \if_meaning:w \calc_maxmin_operation:Nnn #1 \else: % \end{macrocode} % |\calc_numeric:| uses a primitive assignment so doesn't care about @@ -464,7 +560,7 @@ % % \begin{macro}{\calc_open:w} % \begin{macrocode} -\def_new:Npn \calc_open:w({ +\cs_new_nopar:Npn \calc_open:w({ \group_begin:\group_execute_after:N\calc_init_B: \group_begin:\group_execute_after:N\calc_init_B: \calc_pre_scan:N @@ -476,12 +572,12 @@ % \begin{macro}{\calc_numeric:} % \begin{macro}{\calc_close:} % \begin{macrocode} -\def_new:Npn\calc_init_B:{\l_calc_B_register\g_calc_A_register} -\def_new:Npn\calc_numeric:{ +\cs_new_nopar:Npn\calc_init_B:{\l_calc_B_register\g_calc_A_register} +\cs_new_nopar:Npn\calc_numeric:{ \tex_afterassignment:D\calc_post_scan:N \pref_global:D\g_calc_A_register } -\def_new:Npn\calc_close:{ +\cs_new_nopar:Npn\calc_close:{ \group_end:\pref_global:D\g_calc_A_register\l_calc_B_register \group_end:\pref_global:D\g_calc_A_register\l_calc_B_register \calc_post_scan:N} @@ -493,21 +589,21 @@ % \begin{macro}{\calc_post_scan:N} % Look at what token we have and decide where to go. % \begin{macrocode} -\def_new:Npn\calc_post_scan:N#1{ - \if_meaning:NN#1!\let:NN\calc_next:w\group_end: \else: - \if_meaning:NN#1+\let:NN\calc_next:w\calc_add: \else: - \if_meaning:NN#1-\let:NN\calc_next:w\calc_subtract: \else: - \if_meaning:NN#1*\let:NN\calc_next:w\calc_multiply:N \else: - \if_meaning:NN#1/\let:NN\calc_next:w\calc_divide:N \else: - \if_meaning:NN#1)\let:NN\calc_next:w\calc_close: \else: - \if_meaning:NN#1\scan_stop:\let:NN\calc_next:w\calc_post_scan:N +\cs_new_nopar:Npn\calc_post_scan:N#1{ + \if_meaning:w#1!\cs_set_eq:NN\calc_next:w\group_end: \else: + \if_meaning:w#1+\cs_set_eq:NN\calc_next:w\calc_add: \else: + \if_meaning:w#1-\cs_set_eq:NN\calc_next:w\calc_subtract: \else: + \if_meaning:w#1*\cs_set_eq:NN\calc_next:w\calc_multiply:N \else: + \if_meaning:w#1/\cs_set_eq:NN\calc_next:w\calc_divide:N \else: + \if_meaning:w#1)\cs_set_eq:NN\calc_next:w\calc_close: \else: + \if_meaning:w#1\scan_stop:\cs_set_eq:NN\calc_next:w\calc_post_scan:N \else: % \end{macrocode} % If we get here, there is an error but let's also disable % |\calc_next:w| since it is otherwise undefined. No need to give % extra errors just for that. % \begin{macrocode} - \let:NN \calc_next:w \use_noop: + \cs_set_eq:NN \calc_next:w \prg_do_nothing: \calc_error:N#1 \fi: \fi: @@ -524,33 +620,33 @@ % \begin{macro}{\calc_divide:N} % The switches for multiplication and division. % \begin{macrocode} -\def_new:Npn \calc_multiply:N #1{ - \if_meaning:NN \calc_maxmin_operation:Nnn #1 - \let:NN \calc_next:w \calc_maxmin_multiply: +\cs_new_nopar:Npn \calc_multiply:N #1{ + \if_meaning:w \calc_maxmin_operation:Nnn #1 + \cs_set_eq:NN \calc_next:w \calc_maxmin_multiply: \else: - \if_meaning:NN \calc_ratio_multiply:nn #1 - \let:NN \calc_next:w \calc_ratio_multiply:nn + \if_meaning:w \calc_ratio_multiply:nn #1 + \cs_set_eq:NN \calc_next:w \calc_ratio_multiply:nn \else: - \if_meaning:NN \calc_real_evaluate:nn #1 - \let:NN \calc_next:w \calc_real_multiply:n + \if_meaning:w \calc_real_evaluate:nn #1 + \cs_set_eq:NN \calc_next:w \calc_real_multiply:n \else: - \def:Npn \calc_next:w{\calc_multiply: #1} + \cs_set_nopar:Npn \calc_next:w{\calc_multiply: #1} \fi: \fi: \fi: \calc_next:w } -\def_new:Npn \calc_divide:N #1{ - \if_meaning:NN \calc_maxmin_operation:Nnn #1 - \let:NN \calc_next:w \calc_maxmin_divide: +\cs_new_nopar:Npn \calc_divide:N #1{ + \if_meaning:w \calc_maxmin_operation:Nnn #1 + \cs_set_eq:NN \calc_next:w \calc_maxmin_divide: \else: - \if_meaning:NN \calc_ratio_multiply:nn #1 - \let:NN \calc_next:w \calc_ratio_divide:nn + \if_meaning:w \calc_ratio_multiply:nn #1 + \cs_set_eq:NN \calc_next:w \calc_ratio_divide:nn \else: - \if_meaning:NN \calc_real_evaluate:nn #1 - \let:NN \calc_next:w \calc_real_divide:n + \if_meaning:w \calc_real_evaluate:nn #1 + \cs_set_eq:NN \calc_next:w \calc_real_divide:n \else: - \def:Npn \calc_next:w{\calc_divide: #1} + \cs_set_nopar:Npn \calc_next:w{\calc_divide: #1} \fi: \fi: \fi: @@ -560,26 +656,26 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\calc_generic_add:N} +% \begin{macro}{\calc_generic_add_or_subtract:N} % \begin{macro}{\calc_add:} % \begin{macro}{\calc_subtract:} % \begin{macro}{\calc_add_A_to_B:} % \begin{macro}{\calc_subtract_A_from_B:} % Here is how we add and subtract. % \begin{macrocode} -\def_new:Npn\calc_generic_add_or_subtract:N#1{ +\cs_new_nopar:Npn\calc_generic_add_or_subtract:N#1{ \group_end: \pref_global:D\g_calc_A_register\l_calc_B_register\group_end: \group_begin:\group_execute_after:N#1\group_begin: \group_execute_after:N\calc_init_B: \calc_pre_scan:N} -\def_new:Npn\calc_add:{\calc_generic_add_or_subtract:N\calc_add_A_to_B:} -\def_new:Npn\calc_subtract:{ +\cs_new_nopar:Npn\calc_add:{\calc_generic_add_or_subtract:N\calc_add_A_to_B:} +\cs_new_nopar:Npn\calc_subtract:{ \calc_generic_add_or_subtract:N\calc_subtract_A_from_B:} % \end{macrocode} % Don't use |\tex_advance:D| since it allows overflows. % \begin{macrocode} -\def_new:Npn\calc_add_A_to_B:{ +\cs_new_nopar:Npn\calc_add_A_to_B:{ \l_calc_B_register \if_case:w\l_calc_current_type_int \etex_numexpr:D\or: @@ -588,7 +684,7 @@ \etex_muexpr:D\fi: \l_calc_B_register + \g_calc_A_register\scan_stop: } -\def_new:Npn\calc_subtract_A_from_B:{ +\cs_new_nopar:Npn\calc_subtract_A_from_B:{ \l_calc_B_register \if_case:w\l_calc_current_type_int \etex_numexpr:D\or: @@ -613,15 +709,15 @@ % primitive \TeX{} operations but the expandable operations provided % by \eTeX. This means that all results are rounded not truncated! % \begin{macrocode} -\def_new:Npn\calc_generic_multiply_or_divide:N#1{ +\cs_new_nopar:Npn\calc_generic_multiply_or_divide:N#1{ \group_end: \group_begin: - \let:NN\g_calc_A_register\g_calc_A_int - \let:NN\l_calc_B_register\l_calc_B_int + \cs_set_eq:NN\g_calc_A_register\g_calc_A_int + \cs_set_eq:NN\l_calc_B_register\l_calc_B_int \int_zero:N \l_calc_current_type_int \group_execute_after:N#1\calc_pre_scan:N } -\def_new:Npn\calc_multiply_B_by_A:{ +\cs_new_nopar:Npn\calc_multiply_B_by_A:{ \l_calc_B_register \if_case:w\l_calc_current_type_int \etex_numexpr:D\or: @@ -630,7 +726,7 @@ \etex_muexpr:D\fi: \l_calc_B_register*\g_calc_A_int\scan_stop: } -\def_new:Npn\calc_divide_B_by_A:{ +\cs_new_nopar:Npn\calc_divide_B_by_A:{ \l_calc_B_register \if_case:w\l_calc_current_type_int \etex_numexpr:D\or: @@ -639,9 +735,9 @@ \etex_muexpr:D\fi: \l_calc_B_register/\g_calc_A_int\scan_stop: } -\def_new:Npn\calc_multiply:{ +\cs_new_nopar:Npn\calc_multiply:{ \calc_generic_multiply_or_divide:N\calc_multiply_B_by_A:} -\def_new:Npn\calc_divide:{ +\cs_new_nopar:Npn\calc_divide:{ \calc_generic_multiply_or_divide:N\calc_divide_B_by_A:} % \end{macrocode} % \end{macro} @@ -651,19 +747,19 @@ % \end{macro} % % \begin{macro}{\calc_calculate_box_size:nnn} -% \begin{macro}{\calc_calculate_box_size_aux:n} +% \begin{macro}[aux]{\calc_calculate_box_size_aux:n} % Put something in a box and measure it. |#1| is a list of % |\box_ht:N| etc., |#2| should be |\dim_set:Nn|\meta{dim register} % or |\dim_gset:Nn|\meta{dim register} and |#3| is the contents. % \begin{macrocode} -\def_long_new:Npn \calc_calculate_box_size:nnn #1#2#3{ +\cs_new:Npn \calc_calculate_box_size:nnn #1#2#3{ \hbox_set:Nn \l_tmpa_box {{#3}} - #2{\c_zero_dim \tlist_map_function:nN{#1}\calc_calculate_box_size_aux:n} + #2{\c_zero_dim \tl_map_function:nN{#1}\calc_calculate_box_size_aux:n} } % \end{macrocode} % Helper for calculating the final dimension. % \begin{macrocode} -\def:Npn \calc_calculate_box_size_aux:n#1{ + #1\l_tmpa_box} +\cs_set_nopar:Npn \calc_calculate_box_size_aux:n#1{ + #1\l_tmpa_box} % \end{macrocode} % \end{macro} % \end{macro} @@ -672,12 +768,12 @@ % \begin{macro}{\calc_textsize:Nn} % Now we can define |\calc_textsize:Nn|. % \begin{macrocode} -\def_protected_long:Npn \calc_textsize:Nn#1#2{ +\cs_set_protected:Npn \calc_textsize:Nn#1#2{ \group_begin: - \let:NN\calc_widthof_aux:n\box_wd:N - \let:NN\calc_heightof_aux:n\box_ht:N - \let:NN\calc_depthof_aux:n\box_dp:N - \def:Npn\calc_totalheightof_aux:n{\box_ht:N\box_dp:N} + \cs_set_eq:NN\calc_widthof_aux:n\box_wd:N + \cs_set_eq:NN\calc_heightof_aux:n\box_ht:N + \cs_set_eq:NN\calc_depthof_aux:n\box_dp:N + \cs_set_nopar:Npn\calc_totalheightof_aux:n{\box_ht:N\box_dp:N} \exp_args:No\calc_calculate_box_size:nnn{#1} {\dim_gset:Nn\g_calc_A_register} % \end{macrocode} @@ -685,10 +781,10 @@ % call. % \begin{macrocode} { - \let:NN \calc_depthof_aux:n \calc_depthof_auxi:n - \let:NN \calc_widthof_aux:n \calc_widthof_auxi:n - \let:NN \calc_heightof_aux:n \calc_heightof_auxi:n - \let:NN \calc_totalheightof_aux:n \calc_totalheightof_auxi:n + \cs_set_eq:NN \calc_depthof_aux:n \calc_depthof_auxi:n + \cs_set_eq:NN \calc_widthof_aux:n \calc_widthof_auxi:n + \cs_set_eq:NN \calc_heightof_aux:n \calc_heightof_auxi:n + \cs_set_eq:NN \calc_totalheightof_aux:n \calc_totalheightof_auxi:n #2 } \group_end: @@ -703,7 +799,7 @@ % register, the ratio is probably also done with this type and we'll % have to convert them to regular points. % \begin{macrocode} -\def_protected_long:Npn\calc_ratio_multiply:nn#1#2{ +\cs_set_protected:Npn\calc_ratio_multiply:nn#1#2{ \group_end:\group_begin: \if_num:w\l_calc_current_type_int < \c_three \calc_dim_set:Nn\l_calc_B_int{#1} @@ -715,7 +811,7 @@ % \end{macrocode} % Then store the ratio as a fraction, which we just pass on. % \begin{macrocode} - \gdef:Npx\calc_calculated_ratio:{ + \cs_gset_nopar:Npx\calc_calculated_ratio:{ \int_use:N\l_calc_B_int/\int_use:N\l_calc_C_int } \group_end: @@ -738,7 +834,7 @@ % \end{macrocode} % Division is just flipping the arguments around. % \begin{macrocode} -\def_long_new:Npn \calc_ratio_divide:nn#1#2{\calc_ratio_multiply:nn{#2}{#1}} +\cs_new:Npn \calc_ratio_divide:nn#1#2{\calc_ratio_multiply:nn{#2}{#1}} % \end{macrocode} % \end{macro} % \end{macro} @@ -750,7 +846,7 @@ % |\ratio|, this is horribly inefficient since we just want to convert % the decimal to a fraction. % \begin{macrocode} -\def_protected_new:Npn\calc_real_evaluate:nn #1#2{ +\cs_new_protected_nopar:Npn\calc_real_evaluate:nn #1#2{ \group_end: \l_calc_B_register \if_case:w\l_calc_current_type_int @@ -764,8 +860,8 @@ \scan_stop: \group_begin: \calc_post_scan:N} -\def_new:Npn \calc_real_multiply:n #1{\calc_real_evaluate:nn{#1}{1}} -\def_new:Npn \calc_real_divide:n {\calc_real_evaluate:nn{1}} +\cs_new_nopar:Npn \calc_real_multiply:n #1{\calc_real_evaluate:nn{#1}{1}} +\cs_new_nopar:Npn \calc_real_divide:n {\calc_real_evaluate:nn{1}} % \end{macrocode} % \end{macro} % \end{macro} @@ -778,7 +874,7 @@ % \begin{macro}{\calc_maxmin_multiply:} % The max and min functions. % \begin{macrocode} -\def_protected_long:Npn\calc_maxmin_operation:Nnn#1#2#3{ +\cs_set_protected:Npn\calc_maxmin_operation:Nnn#1#2#3{ \group_begin: \calc_maxmin_generic:Nnn#1{#2}{#3} \group_end: @@ -787,7 +883,7 @@ % \end{macrocode} % |#1| is either |>| or |<| and was expanded into this initially. % \begin{macrocode} -\def_protected_long_new:Npn \calc_maxmin_generic:Nnn#1#2#3{ +\cs_new_protected:Npn \calc_maxmin_generic:Nnn#1#2#3{ \group_begin: \if_case:w\l_calc_current_type_int \calc_int_set:Nn\l_calc_C_int{#2}% @@ -816,7 +912,7 @@ \fi: \group_end: } -\def_long_new:Npn\calc_maxmin_div_or_mul:NNnn#1#2#3#4{ +\cs_new:Npn\calc_maxmin_div_or_mul:NNnn#1#2#3#4{ \group_end: \group_begin: \int_zero:N\l_calc_current_type_int @@ -826,9 +922,9 @@ \group_begin: \calc_post_scan:N } -\def_new:Npn\calc_maxmin_multiply:{ +\cs_new_nopar:Npn\calc_maxmin_multiply:{ \calc_maxmin_div_or_mul:NNnn\calc_multiply_B_by_A:} -\def_new:Npn\calc_maxmin_divide: { +\cs_new_nopar:Npn\calc_maxmin_divide: { \calc_maxmin_div_or_mul:NNnn\calc_divide_B_by_A:} % \end{macrocode} % \end{macro} @@ -840,9 +936,9 @@ % \begin{macro}{\calc_error:N} % The error message. % \begin{macrocode} -\def_new:Npn\calc_error:N#1{ +\cs_new_nopar:Npn\calc_error:N#1{ \PackageError{calc} - {`\token_to_string:N#1'~ invalid~ at~ this~ point} + {`\token_to_str:N#1'~ invalid~ at~ this~ point} {I~ expected~ to~ see~ one~ of:~ +~ -~ *~ /~ )} } % \end{macrocode} @@ -858,14 +954,14 @@ % \begin{macro}{\minof} % Max and min operations % \begin{macrocode} -\def_long_new:Npn \calc_maxof:nn#1#2{ +\cs_new:Npn \calc_maxof:nn#1#2{ \calc_maxmin_operation:Nnn > \exp_not:n{{#1}{#2}} } -\def_long_new:Npn \calc_minof:nn#1#2{ +\cs_new:Npn \calc_minof:nn#1#2{ \calc_maxmin_operation:Nnn < \exp_not:n{{#1}{#2}} } -\let:NN \maxof \calc_maxof:nn -\let:NN \minof \calc_minof:nn +\cs_set_eq:NN \maxof \calc_maxof:nn +\cs_set_eq:NN \minof \calc_minof:nn % \end{macrocode} % \end{macro} % \end{macro} @@ -873,47 +969,47 @@ % \end{macro} % % \begin{macro}{\calc_widthof:n} -% \begin{macro}{\calc_widthof_aux:n} -% \begin{macro}{\calc_widthof_auxi:n} +% \begin{macro}[aux]{\calc_widthof_aux:n} +% \begin{macro}[aux]{\calc_widthof_auxi:n} % \begin{macro}{\calc_heightof:n} -% \begin{macro}{\calc_heightof_aux:n} -% \begin{macro}{\calc_heightof_auxi:n} +% \begin{macro}[aux]{\calc_heightof_aux:n} +% \begin{macro}[aux]{\calc_heightof_auxi:n} % \begin{macro}{\calc_depthof:n} -% \begin{macro}{\calc_depthof_aux:n} -% \begin{macro}{\calc_depthof_auxi:n} +% \begin{macro}[aux]{\calc_depthof_aux:n} +% \begin{macro}[aux]{\calc_depthof_auxi:n} % \begin{macro}{\calc_totalheightof:n} -% \begin{macro}{\calc_totalheightof_aux:n} -% \begin{macro}{\calc_totalheightof_auxi:n} +% \begin{macro}[aux]{\calc_totalheightof_aux:n} +% \begin{macro}[aux]{\calc_totalheightof_auxi:n} % Text dimension commands. % \begin{macrocode} -\def_long_new:Npn \calc_widthof:n#1{ +\cs_new:Npn \calc_widthof:n#1{ \calc_textsize:Nn \exp_not:N\calc_widthof_aux:n\exp_not:n{{#1}} } -\def_long_new:Npn \calc_heightof:n#1{ +\cs_new:Npn \calc_heightof:n#1{ \calc_textsize:Nn \exp_not:N\calc_heightof_aux:n\exp_not:n{{#1}} } -\def_long_new:Npn \calc_depthof:n#1{ +\cs_new:Npn \calc_depthof:n#1{ \calc_textsize:Nn \exp_not:N\calc_depthof_aux:n\exp_not:n{{#1}} } -\def_long_new:Npn \calc_totalheightof:n#1{ +\cs_new:Npn \calc_totalheightof:n#1{ \calc_textsize:Nn \exp_not:N\calc_totalheightof_aux:n \exp_not:n{{#1}} } -\def_long_new:Npn \calc_widthof_aux:n #1{ +\cs_new:Npn \calc_widthof_aux:n #1{ \exp_not:N\calc_widthof_aux:n\exp_not:n{{#1}} } -\let_new:NN \calc_widthof_auxi:n \calc_widthof_aux:n -\def_long_new:Npn \calc_depthof_aux:n #1{ +\cs_new_eq:NN \calc_widthof_auxi:n \calc_widthof_aux:n +\cs_new:Npn \calc_depthof_aux:n #1{ \exp_not:N\calc_depthof_aux:n\exp_not:n{{#1}} } -\let_new:NN \calc_depthof_auxi:n \calc_depthof_aux:n -\def_long_new:Npn \calc_heightof_aux:n #1{ +\cs_new_eq:NN \calc_depthof_auxi:n \calc_depthof_aux:n +\cs_new:Npn \calc_heightof_aux:n #1{ \exp_not:N\calc_heightof_aux:n\exp_not:n{{#1}} } -\let_new:NN \calc_heightof_auxi:n \calc_heightof_aux:n -\def_long_new:Npn \calc_totalheightof_aux:n #1{ +\cs_new_eq:NN \calc_heightof_auxi:n \calc_heightof_aux:n +\cs_new:Npn \calc_totalheightof_aux:n #1{ \exp_not:N\calc_totalheightof_aux:n\exp_not:n{{#1}} } -\let_new:NN \calc_totalheightof_auxi:n \calc_totalheightof_aux:n +\cs_new_eq:NN \calc_totalheightof_auxi:n \calc_totalheightof_aux:n % \end{macrocode} % \end{macro} % \end{macro} @@ -932,9 +1028,9 @@ % \begin{macro}{\calc_real:n} % Ratio and real. % \begin{macrocode} -\def_long_new:Npn \calc_ratio:nn#1#2{ +\cs_new:Npn \calc_ratio:nn#1#2{ \calc_ratio_multiply:nn\exp_not:n{{#1}{#2}}} -\def_new:Npn \calc_real:n {\calc_real_evaluate:nn} +\cs_new_nopar:Npn \calc_real:n {\calc_real_evaluate:nn} % \end{macrocode} % We can implement real and ratio without actually using these % names. We'll see. @@ -951,12 +1047,12 @@ % \begin{macro}{\real} % User commands. % \begin{macrocode} -\let:NN \depthof\calc_depthof:n -\let:NN \widthof\calc_widthof:n -\let:NN \heightof\calc_heightof:n -\let:NN \totalheightof\calc_totalheightof:n -%%\let:NN \ratio\calc_ratio:nn -%%\let:NN \real\calc_real:n +\cs_set_eq:NN \depthof\calc_depthof:n +\cs_set_eq:NN \widthof\calc_widthof:n +\cs_set_eq:NN \heightof\calc_heightof:n +\cs_set_eq:NN \totalheightof\calc_totalheightof:n +%%\cs_set_eq:NN \ratio\calc_ratio:nn +%%\cs_set_eq:NN \real\calc_real:n % \end{macrocode} % \end{macro} % \end{macro} @@ -970,10 +1066,10 @@ % \begin{macro}{\addtolength} % \begin{macro}{\gaddtolength} % \begin{macrocode} -\def_protected:Npn \setlength{\calc_skip_set:Nn} -\def_protected:Npn \gsetlength{\calc_skip_gset:Nn} -\def_protected:Npn \addtolength{\calc_skip_add:Nn} -\def_protected:Npn \gaddtolength{\calc_skip_gadd:Nn} +\cs_set_protected_nopar:Npn \setlength{\calc_skip_set:Nn} +\cs_set_protected_nopar:Npn \gsetlength{\calc_skip_gset:Nn} +\cs_set_protected_nopar:Npn \addtolength{\calc_skip_add:Nn} +\cs_set_protected_nopar:Npn \gaddtolength{\calc_skip_gadd:Nn} % \end{macrocode} % \end{macro} % \end{macro} @@ -992,44 +1088,67 @@ % |\mathchoice| will no longer need this switch as the argument is % only executed once. % \begin{macrocode} +% +%<*package> \newif\iffirstchoice@ \firstchoice@true -\def_protected:Npn \calc_setcounter:nn#1#2{ +% +%<*initex|package> +\cs_set_protected_nopar:Npn \calc_setcounter:nn#1#2{ \calc_chk_document_counter:nn{#1}{ \exp_args:Nc\calc_int_gset:Nn {c@#1}{#2} } } -\def_protected:Npn \calc_addtocounter:nn#1#2{ +\cs_set_protected_nopar:Npn \calc_addtocounter:nn#1#2{ +% +%<*package> \iffirstchoice@ +% +%<*initex|package> \calc_chk_document_counter:nn{#1}{ \exp_args:Nc\calc_int_gadd:Nn {c@#1}{#2} } +% +%<*package> \fi: +% +%<*initex|package> } -\def_protected:Npn \calc_stepcounter:n#1{ +\cs_set_protected_nopar:Npn \calc_stepcounter:n#1{ +% +%<*package> \iffirstchoice@ +% +%<*initex|package> \calc_chk_document_counter:nn{#1}{ \int_gincr:c {c@#1} \group_begin: - \let:NN \@elt\@stpelt \cs_use:c{cl@#1} + \cs_set_eq:NN \@elt\@stpelt \use:c{cl@#1} \group_end: } +% +%<*package> \fi: +% +%<*initex|package> } -\def_new:Npn \calc_chk_document_counter:nn#1{ +\cs_new_nopar:Npn \calc_chk_document_counter:nn#1{ \cs_if_free:cTF{c@#1}{\@nocounterr {#1}} } -\let:NN \setcounter \calc_setcounter:nn -\let:NN \addtocounter \calc_addtocounter:nn -\let:NN \stepcounter \calc_stepcounter:n +\cs_set_eq:NN \setcounter \calc_setcounter:nn +\cs_set_eq:NN \addtocounter \calc_addtocounter:nn +\cs_set_eq:NN \stepcounter \calc_stepcounter:n +% +%<*package> \AtBeginDocument{ - \let:NN \setcounter \calc_setcounter:nn - \let:NN \addtocounter \calc_addtocounter:nn - \let:NN \stepcounter \calc_stepcounter:n + \cs_set_eq:NN \setcounter \calc_setcounter:nn + \cs_set_eq:NN \addtocounter \calc_addtocounter:nn + \cs_set_eq:NN \stepcounter \calc_stepcounter:n } % \end{macrocode} % Prevent the usual \textsf{calc} from loading. % \begin{macrocode} -%\def:cpn{ver@calc.sty}{2005/08/06} +\cs_set_nopar:cpn{ver@calc.sty}{2005/08/06} +% % \end{macrocode} % \end{macro} % \end{macro} @@ -1038,22 +1157,14 @@ % \end{macro} % \end{macro} % \end{macro} -% -% +% % \begin{macrocode} -% %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.2 2006/01/27 23:11:47 morten -% Fixed bug in \calc_pre_scan:N and avoid using \advance in order to -% catch overflows. -% -% Revision 1.1 2006/01/27 07:51:13 morten -% Initial version of a calc module +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3chk.dtx b/Master/texmf-dist/source/latex/expl3/l3chk.dtx index 281ba7bc1cc..ad016f91c91 100644 --- a/Master/texmf-dist/source/latex/expl3/l3chk.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3chk.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3chk.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3chk.dtx Copyright (C) 1990-2006,2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3chk.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3chk.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental check module} %\iffalse %<*driver> @@ -44,7 +44,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -59,17 +59,27 @@ % \date{\filedate} % \maketitle % -% \section{The chk module} +% \begin{documentation} % % To ensure that functions and variables are properly used certain % checking functions are implemented that may or may not be compiled % into the final format. % -% \subsection{Functions} +% \section{Tracing} +% +% \begin{function}{\tracingall | +% \absolutelytracingall | +% \donotcheck | +% \tracingoff | +% \traceon | +% \traceoff } +% Commands to control the level of verbosity in the tracing output. +% \end{function} +% +% \section{Functions} % % \begin{function}{% % \chk_var_or_const:N | -% \chk_var_or_const:c | % } % \begin{syntax} % "\chk_var_or_const:N" @@ -80,9 +90,7 @@ % % \begin{function}{% % \chk_local:N | -% \chk_local:c | % \chk_global:N | -% \chk_global:c | % } % \begin{syntax} % "\chk_local:N" @@ -108,40 +116,26 @@ % "\chk_local_or_pref_global:N" inside some function "\foo_bar:n" we can % implement a global version "\foo_gbar:n" by defining % \begin{quote} -% "\def_new:Npn \foo_gbar:n {\pref_global_chk: \foo_bar:n }" +% "\cs_new_nopar:Npn \foo_gbar:n {\pref_global_chk: \foo_bar:n }" % \end{quote} % provided that "\foo_bar:n" is built in a way that prefixing it with % "\pref_global:D" turns its operation into a global one. See % implementation for details. % \end{function} % -% \subsection{Constants} -% -% \begin{variable}{\c_undefined} -% This constant is always undefined and therefore can be used to check -% for free function names. -% \end{variable} -% -% \subsection{Internal functions} -% -% \begin{function}{% -% \chk_global_aux:w | -% \chk_local_aux:w | -% \chk_var_or_const_aux:w | -% } -% Helper functions that implement the checking. -% \end{function} +% \end{documentation} % -% \StopEventually{} +% \begin{implementation} % -% \subsection{The Implementation} +% \section{\pkg{l3chk} implementation} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3basics} -%\RequirePackage{l3int,l3prg} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % @@ -150,10 +144,10 @@ % too badly. All these functions are of type `{\tt e}' since they % issue error messages if certain conditions are violated. % -% \subsubsection{Checking variable assignments} +% \subsection{Checking variable assignments} % % \begin{macro}{\chk_local:N} -% \begin{macro}{\chk_local_aux:w} +% \begin{macro}[aux]{\chk_local_aux:w} % This function checks that its argument is a proper local % variable, i.e.\ its name starts with |\l| or |\L|. % It is not allowed that the name starts with |\g| or |\G|, @@ -166,18 +160,18 @@ % during the implementation since it will find certain errors % involving wrong expansion in earlier stage. % \begin{macrocode} -\def_new:Npn \chk_local:N #1{ - \exp_after:NN \chk_local_aux:w \token_to_string:N#1\q_stop} +\cs_new_nopar:Npn \chk_local:N #1{ + \exp_after:wN \chk_local_aux:w \token_to_str:N#1\q_stop} -\def_new:Npn \chk_local_aux:w #1#2#3\q_stop{ +\cs_new_nopar:Npn \chk_local_aux:w #1#2#3\q_stop{ \if_num:w\tex_uccode:D`#2=`G\scan_stop: - \err_latex_bug:x{Local~mismatch:~local~function~called~with~ + \msg_kernel_bug:x {Local~mismatch:~local~function~called~with~ global~variable:^^J\text_put_four_sp: #1#2#3~ on~line~\tex_the:D\tex_inputlineno:D} \else: \if_num:w\tex_uccode:D`#2=`L\scan_stop: \else: - \err_latex_bug:x{Variable~mismatch:~function~not~called~with~ + \msg_kernel_bug:x {Variable~mismatch:~function~not~called~with~ proper~variable:^^J\text_put_four_sp: #1#2#3~ on~line~\tex_the:D\tex_inputlineno:D}\fi: \fi:} @@ -191,21 +185,21 @@ % \end{macro} % % \begin{macro}{\chk_global:N} -% \begin{macro}{\chk_global_aux:w} +% \begin{macro}[aux]{\chk_global_aux:w} % |\chk_global:N| is similar to |\chk_local:N| but looks only % for global variables. % \begin{macrocode} -\def_new:Npn \chk_global:N #1{\exp_after:NN - \chk_global_aux:w \token_to_string:N#1\q_stop} -\def_new:Npn \chk_global_aux:w #1#2#3\q_stop{ +\cs_new_nopar:Npn \chk_global:N #1{\exp_after:wN + \chk_global_aux:w \token_to_str:N#1\q_stop} +\cs_new_nopar:Npn \chk_global_aux:w #1#2#3\q_stop{ \if_num:w\tex_uccode:D`#2=`L\scan_stop: - \err_latex_bug:x{Global~mismatch:~global~function~called~with~ + \msg_kernel_bug:x {Global~mismatch:~global~function~called~with~ local~variable:~#1#2#3~ on~line~\tex_the:D\tex_inputlineno:D} \else: \if_num:w\tex_uccode:D`#2=`G\scan_stop: \else: - \err_latex_bug:x{Variable~mismatch:~function~not~called~with~ + \msg_kernel_bug:x {Variable~mismatch:~function~not~called~with~ proper~variable:~#1#2#3~ on~line~\tex_the:D\tex_inputlineno:D}\fi:\fi:} % \end{macrocode} @@ -218,7 +212,7 @@ % |\pref_global:D| without loosing the possibility to check for the % correct type of a variable, the following helper functions can be % used: |\chk_local_or_pref_global:N| \m{variable} is the variable -% check which is usually |\let:NN| to |\chk_local:N|, i.e.\ it will +% check which is usually |\cs_set_eq:NN| to |\chk_local:N|, i.e.\ it will % check for local variables. This behavior will be changed by % |\pref_global_chk:|. This function first changes % |\chk_local_or_pref_global:N| to check for global variables, then @@ -228,7 +222,7 @@ % inside some function |\foo_bar:n| we can implement a global % version |\foo_gbar:n| by defining % \begin{verbatim} -% \def_new:Npn \foo_gbar:n {\pref_global_chk: \foo_bar:n } +% \cs_new_nopar:Npn \foo_gbar:n {\pref_global_chk: \foo_bar:n } %\end{verbatim} % provided of course, that |\foo_bar:n| is defined in a way that a % |\pref_global:D| does work. Such a scheme has to be used @@ -237,25 +231,25 @@ % |\pref_global_chk:| into |\pref_global:D| and omit the % |\chk_local_or_pref_global:N| function in the body. % \begin{macrocode} -\def_new:Npn \pref_global_chk: { - \gdef:Npn \chk_local_or_pref_global:N ##1{ +\cs_new_nopar:Npn \pref_global_chk: { + \cs_gset_nopar:Npn \chk_local_or_pref_global:N ##1{ \chk_global:N ##1 - \glet:NN \chk_local_or_pref_global:N \chk_local:N} + \cs_gset_eq:NN \chk_local_or_pref_global:N \chk_local:N} \pref_global:D} -\let_new:NN \chk_local_or_pref_global:N \chk_local:N +\cs_new_eq:NN \chk_local_or_pref_global:N \chk_local:N % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\chk_var_or_const:N} -% \begin{macro}{\chk_var_or_const_aux:w} +% \begin{macro}[aux]{\chk_var_or_const_aux:w} % |\chk_var_or_const:N| is used in situations where we want to check % that we have a variable (or a constant) but do not care whether % or not it is global (for example, in allocation routines). % \begin{macrocode} -\def_new:Npn \chk_var_or_const:N #1{\exp_after:NN - \chk_var_or_const_aux:w \token_to_string:N#1\q_stop } -\def_new:Npn \chk_var_or_const_aux:w #1#2#3\q_stop { +\cs_new_nopar:Npn \chk_var_or_const:N #1{\exp_after:wN + \chk_var_or_const_aux:w \token_to_str:N#1\q_stop } +\cs_new_nopar:Npn \chk_var_or_const_aux:w #1#2#3\q_stop { \if_num:w\tex_uccode:D`#2=`L\scan_stop: \else: \if_num:w\tex_uccode:D`#2=`G\scan_stop: @@ -273,7 +267,7 @@ % could check this by testing that there is no |_|, but this is not % implemented so far. % \begin{macrocode} - \err_latex_bug:x{Variable~mismatch:~function~not~called~with~ + \msg_kernel_bug:x {Variable~mismatch:~function~not~called~with~ proper~variable:^^J\text_put_four_sp: #1#2#3~ on~line~\tex_the:D\tex_inputlineno:D}\fi:\fi:\fi: \fi:} @@ -282,7 +276,7 @@ % \end{macro} % % -% \subsubsection{Doing some tracing} +% \subsection{Doing some tracing} % % \begin{macro}{\tracingall} % \begin{macro}{\absolutelytracingall} @@ -292,20 +286,20 @@ % probably wrong. Therefore this definition of it turns the % functions of as far as possible. % \begin{macrocode} -\def_new:Npn\donotcheck{ - \let:NN \chk_global:N \use_none:n - \let:NN \chk_local:N \use_none:n - \let:NN \chk_local_or_pref_global:N \use_none:n - \let:NN \pref_global_chk: \pref_global:D - \let:NN \chk_new_cs:N \use_none:n - \let:NN \chk_exist_cs:N \use_none:n - \let:NN \chk_var_or_const:N \use_none:n - \let:NN \cs_record_name:N \use_none:n - \let:NN \cs_record_name:c \use_none:n - \let:NN \cs_record_meaning:N \use_none:n - \let:NN \register_record_name:N \use_none:n +\cs_new_nopar:Npn\donotcheck{ + \cs_set_eq:NN \chk_global:N \use_none:n + \cs_set_eq:NN \chk_local:N \use_none:n + \cs_set_eq:NN \chk_local_or_pref_global:N \use_none:n + \cs_set_eq:NN \pref_global_chk: \pref_global:D + \cs_set_eq:NN \chk_if_free_cs:N \use_none:n + \cs_set_eq:NN \chk_exist_cs:N \use_none:n + \cs_set_eq:NN \chk_var_or_const:N \use_none:n + \cs_set_eq:NN \cs_record_name:N \use_none:n + \cs_set_eq:NN \cs_record_name:c \use_none:n + \cs_set_eq:NN \cs_record_meaning:N \use_none:n + \cs_set_eq:NN \register_record_name:N \use_none:n } -\def_new:Npn\absolutelytracingall{ +\cs_new_nopar:Npn\absolutelytracingall{ % \end{macrocode} % \end{macro} % @@ -326,7 +320,7 @@ \tex_errorstopmode:D} % % Use LaTeX2e definition for now. -%\def_new:Npn\tracingall{ +%\cs_new_nopar:Npn\tracingall{ % \donotcheck % \absolutelytracingall %} @@ -337,7 +331,7 @@ % \begin{macro}{\tracingoff} % This macro turns off all tracing. % \begin{macrocode} -\def_new:Npn\tracingoff{ +\cs_new_nopar:Npn\tracingoff{ % \end{macrocode} % First we turn off |\g_trace_online_status| so that we get minimal % rubbish on the terminal. Of course, in the log file all @@ -358,28 +352,28 @@ % \end{macrocode} % \end{macro} % -% \subsubsection{Tracing modules} +% \subsection{Tracing modules} % % \begin{macro}{\traceon} % \begin{macro}{\traceoff} % Turning the tracing of modules on or off. (primitive version). % \begin{macrocode} %<*trace> -\def_new:Npn\traceon#1{ +\cs_new_nopar:Npn\traceon#1{ \clist_map_inline:nn {#1}{ - \cs_free:cF{g_trace_ ##1 _status} + \cs_if_free:cF{g_trace_ ##1 _status} {\int_gincr:c{g_trace_ ##1 _status}} } } -\def_new:Npn\traceoff#1{ +\cs_new_nopar:Npn\traceoff#1{ \clist_map_inline:nn {#1}{ - \cs_free:cF{g_trace_ ##1 _status} + \cs_if_free:cF{g_trace_ ##1 _status} {\int_gdecr:c{g_trace_ ##1 _status}} } } % -%<-trace>\let_new:NN\traceon\use_none:n -%<-trace>\let_new:NN\traceoff\use_none:n +%<-trace>\cs_new_eq:NN\traceon\use_none:n +%<-trace>\cs_new_eq:NN\traceoff\use_none:n % % \end{macrocode} % \end{macro} @@ -393,22 +387,7 @@ % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.14 2006/03/20 18:26:34 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.13 2005/12/27 09:58:01 morten -% Minor changes plus changed RCS information retrieval -% -% Revision 1.12 2005/04/12 12:07:53 morten -% Removed unnecessary functions -% -% Revision 1.11 2005/03/15 23:31:54 braams -% Some fiddling with docstrip guards for initex use -% -% Revision 1.10 2005/03/11 21:33:31 braams -% Fixed the use of RCS information +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3clist.dtx b/Master/texmf-dist/source/latex/expl3/l3clist.dtx index 0155c64f394..f875b7e0cbc 100644 --- a/Master/texmf-dist/source/latex/expl3/l3clist.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3clist.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3clist.dtx Copyright (C) 2005-2006 Frank Mittelbach, LaTeX3 project +%% File: l3clist.dtx Copyright (C) 2005-2008 Frank Mittelbach, LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3clist.dtx 745 2008-08-03 18:50:46Z morten $ +\GetIdInfo$Id: l3clist.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental comma separated lists} %\iffalse %<*driver> @@ -44,7 +44,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -61,9 +61,7 @@ % \date{\filedate} % \maketitle % -% -% -% \section{Comma lists} +% \begin{documentation} % % \LaTeX3 implements a data type called `clist (comma-lists)'. These % are special @@ -75,8 +73,8 @@ % part of the value). It is also possible to map functions on such % comma-lists so that they are executed for every item of the comma-list. % -% All functions that return items from a comma-list in some \m{tlp} assume -% that the \m{tlp} is local. See remarks below if you need a global +% All functions that return items from a comma-list in some \m{tl var.}~assume +% that the \m{tl var.}~is local. See remarks below if you need a global % returned value. % % The defined functions are not orthogonal in the sense that every @@ -89,7 +87,7 @@ % like "\clist_push:Nn" which has the same effect. Maybe one should % therefore remove the ``left'' functions totally. % -% \subsection{Functions} +% \section{Functions for creating/initialising comma-lists} % % \begin{function}{% % \clist_new:N | @@ -113,117 +111,153 @@ % These functions locally or globally clear . % \end{function} % +% \begin{function}{ \clist_clear_new:N | +% \clist_clear_new:c | +% \clist_gclear_new:N | +% \clist_gclear_new:c } +% \begin{syntax} +% "\clist_clear_new:N" +% \end{syntax} +% These functions locally or globally clear if it exists or +% otherwise allocates it. +% \end{function} +% +% \begin{function}{ \clist_set_eq:NN | +% \clist_set_eq:cN | +% \clist_set_eq:Nc | +% \clist_set_eq:cc } +% \begin{syntax} +% "\clist_set_eq:NN" +% \end{syntax} +% Function that locally makes identical to . +% \end{function} +% +% +% \begin{function}{ \clist_gset_eq:NN | +% \clist_gset_eq:cN | +% \clist_gset_eq:Nc | +% \clist_gset_eq:cc } +% \begin{syntax} +% "\clist_gset_eq:NN" +% \end{syntax} +% Function that globally makes identical to . +% \end{function} +% +% \section{Putting data in} +% % \begin{function}{% % \clist_put_left:Nn | +% \clist_put_left:NV | % \clist_put_left:No | % \clist_put_left:Nx | % \clist_put_left:cn | -% \clist_put_right:Nn | -% \clist_put_right:No | -% \clist_put_right:Nx | +% \clist_put_left:co | +% \clist_put_left:cV | % } % \begin{syntax} % "\clist_put_left:Nn" % \end{syntax} % Locally appends as a single item to the left -% or right of . might get expanded before -% appending. +% of . might get expanded before +% appending according to the variant used. % \end{function} % % \begin{function}{% -% \clist_gput_left:Nn | -% \clist_gput_right:Nn | -% \clist_gput_right:No | -% \clist_gput_right:cn | -% \clist_gput_right:co | -% \clist_gput_right:cc | +% \clist_put_right:Nn | +% \clist_put_right:No | +% \clist_put_right:NV | +% \clist_put_right:Nx | +% \clist_put_right:cn | +% \clist_put_right:co | +% \clist_put_right:cV | % } % \begin{syntax} -% "\clist_gput_left:Nn" +% "\clist_put_right:Nn" % \end{syntax} -% Globally appends as a single item to the left -% or right of . +% Locally appends as a single item to the right +% of . might get expanded before +% appending according to the variant used. % \end{function} % % \begin{function}{% -% \clist_get:NN | -% \clist_get:cN | +% \clist_gput_left:Nn | +% \clist_gput_left:NV | +% \clist_gput_left:No | +% \clist_gput_left:Nx | +% \clist_gput_left:cn | +% \clist_gput_left:cV | +% \clist_gput_left:co | % } % \begin{syntax} -% "\clist_get:NN" +% "\clist_gput_left:Nn" % \end{syntax} -% Functions that locally assign the left-most item of to the -% token list pointer . Item is not removed from ! If you -% need a global return value you need to code something like this: -% \begin{quote} -% "\clist_get:NN" "\l_tmpa_tlp" \\ -% "\tlp_gset_eq:NN" "\l_tmpa_tlp" -% \end{quote} -% But if this kind of construction is used often enough a separate -% function should be provided. +% Globally appends as a single item to the +% right of . % \end{function} % % \begin{function}{% -% \clist_set_eq:NN +% \clist_gput_right:Nn | +% \clist_gput_right:NV | +% \clist_gput_right:No | +% \clist_gput_right:Nx | +% \clist_gput_right:cn | +% \clist_gput_right:cV | +% \clist_gput_right:co | % } % \begin{syntax} -% "\clist_set_eq:NN" +% "\clist_gput_right:Nn" % \end{syntax} -% Function that locally makes identical to . +% Globally appends as a single item to the +% right of . % \end{function} % +% \section{Getting data out} % -% \begin{function}{% -% \clist_gset_eq:NN | -% \clist_gset_eq:cN | -% \clist_gset_eq:Nc | -% \clist_gset_eq:cc -% } +% \begin{function}{ \clist_use:N | +% \clist_use:c } % \begin{syntax} -% "\clist_gset_eq:NN" +% "\clist_use:N" % \end{syntax} -% Function that globally makes identical to . +% Function that inserts the into the processing stream. Mainly +% useful if one knows what the contains, e.g., for displaying +% the content of template parameters. % \end{function} % -% -% \begin{function}{% -% \clist_concat:NNN | -% \clist_gconcat:NNN | -% \clist_gconcat:NNc | -% \clist_gconcat:ccc | -% } +% \begin{function}{ \clist_show:N | +% \clist_show:c } % \begin{syntax} -% "\clist_gconcat:NNN" +% "\clist_show:N" % \end{syntax} -% Function that concatenates and and globally assigns the -% result to . +% Function that pauses the compilation and displays in the terminal +% output and in the log file. (Usually used for diagnostic purposes.) % \end{function} % -% -% \begin{function}{% -% \clist_remove_duplicates:N | -% \clist_gremove_duplicates:N | -% } +% \begin{function}{ \clist_display:N | +% \clist_display:c } % \begin{syntax} -% "\clist_gremove_duplicates:N" +% "\clist_display:N" % \end{syntax} -% Function that removes any duplicate entries in . +% As with "\clist_show:N" but pretty prints the output one line per element. % \end{function} % -% \begin{function}{% -% \clist_use:N | -% \clist_use:c -% } +% \begin{function}{ \clist_get:NN | +% \clist_get:cN } % \begin{syntax} -% "\clist_use:N" +% "\clist_get:NN" % \end{syntax} -% Function that inserts the into the processing stream. Mainly -% useful if one knows what the contains, e.g., for displaying -% the content of template parameters. +% Functions that locally assign the left-most item of to the +% token list variable . Item is not removed from ! If you +% need a global return value you need to code something like this: +% \begin{quote} +% "\clist_get:NN" "\l_tmpa_tl" \\ +% "\tl_gset_eq:NN" "\l_tmpa_tl" +% \end{quote} +% But if this kind of construction is used often enough a separate +% function should be provided. % \end{function} % % -% \subsection{Mapping functions} +% \section{Mapping functions} % % % We provide three types of mapping functions, each with their own @@ -253,7 +287,7 @@ % \clist_map_inline:nn | % } % \begin{syntax} -% "\clist_map_inline:Nn" "{" "}" +% "\clist_map_inline:Nn" \Arg{inline function} % \end{syntax} % Applies (which should be the direct coding for a % function with one argument (i.e.\ use "##1" as the placeholder for @@ -269,7 +303,7 @@ % \clist_map_variable:nNn | % } % \begin{syntax} -% "\clist_map_variable:NNn" "{" "}" +% "\clist_map_variable:NNn" \Arg{action} % \end{syntax} % Assigns to each element in and then executes % which should contain . As the @@ -281,16 +315,16 @@ % \end{function} % % \begin{function}{% -% \clist_map_break:w | +% \clist_map_break: | % } % \begin{syntax} -% "\clist_map_break:w" +% "\clist_map_break:" % \end{syntax} % For breaking out of a loop. To be used inside "TF" type functions as % in the example below. % \begin{verbatim} -% \def_new:Npn \test_function:n #1 { -% \int_compare:nNnTF {#1}> 3 {\clist_map_break:w}{``#1''} +% \cs_new_nopar:Npn \test_function:n #1 { +% \intexpr_compare:nTF {#1 > 3} {\clist_map_break:}{``#1''} % } % \clist_map_function:nN {1,2,3,4,5,6,7,8}\test_function:n % \end{verbatim} @@ -298,9 +332,10 @@ % \end{function} % % -% \subsection{Predicates and conditionals} +% \section{Predicates and conditionals} % -% \begin{function}{\clist_if_empty_p:N} +% \begin{function}{ \clist_if_empty_p:N | +% \clist_if_empty_p:c } % \begin{syntax} % "\clist_if_empty_p:N" % \end{syntax} @@ -308,99 +343,87 @@ % contain any tokens. % \end{function} % -% \begin{function}{% -% \clist_if_empty:NTF | -% \clist_if_empty:cTF | -% \clist_if_empty:NF | -% \clist_if_empty:cF | -% } +% \begin{function}{ \clist_if_empty:N / (TF)(EXP) | +% \clist_if_empty:c / (TF)(EXP)} % \begin{syntax} -% "\clist_if_empty:NTF" "{" "}{" "}" +% "\clist_if_empty:NTF" \Arg{true code} \Arg{false code} % \end{syntax} % Set of conditionals that test whether or not a particular % is empty and if so executes either or . % \end{function} % -% \begin{function}{% -% \clist_if_eq:NNTF | -% } +% \begin{function}{ \clist_if_eq_p:NN / (EXP) | +% \clist_if_eq_p:cN / (EXP) | +% \clist_if_eq_p:Nc / (EXP) | +% \clist_if_eq_p:cc / (EXP) } % \begin{syntax} -% "\clist_if_eq:NNTF" "{" -% "}{" "}" +% "\clist_if_eq_p:N" +% \end{syntax} +% This predicate returns `true' if the two comma lists are identical. +% \end{function} +% +% \begin{function}{ \clist_if_eq:NN / (TF)(EXP) | +% \clist_if_eq:cN / (TF)(EXP) | +% \clist_if_eq:Nc / (TF)(EXP) | +% \clist_if_eq:cc / (TF)(EXP) } +% \begin{syntax} +% "\clist_if_eq:NNTF" \Arg{true code} \Arg{false code} % \end{syntax} % Check if and are equal and execute % either or accordingly. % \end{function} % -% \begin{function}{% -% \clist_if_in:NnTF | -% \clist_if_in:NoTF | -% \clist_if_in:cnTF | -% \clist_if_in:coTF | -% } +% \begin{function}{ \clist_if_in:Nn / (TF) | +% \clist_if_in:NV / (TF) | +% \clist_if_in:No / (TF) | +% \clist_if_in:cn / (TF) | +% \clist_if_in:cV / (TF) | +% \clist_if_in:co / (TF) } % \begin{syntax} -% "\clist_if_in:NnTF" "{" "}{" "}{" -% "}" +% "\clist_if_in:NnTF" \Arg{item} \Arg{true code} \Arg{false code} % \end{syntax} % Function that tests if is in . Depending on the result % either or is executed. % \end{function} % -% \subsection{Internal functions} +% \section{Higher level functions} % -% \begin{function}{\clist_if_empty_err:N} +% \begin{function}{ \clist_concat:NNN | +% \clist_concat:ccc | +% \clist_gconcat:NNN | +% \clist_gconcat:ccc } % \begin{syntax} -% "\clist_if_empty_err:N" +% "\clist_gconcat:NNN" % \end{syntax} -% Signals an \LaTeX3 error if is empty. +% Function that concatenates and and locally or globally +% assigns the result to . % \end{function} % -% \begin{function}{\clist_pop_aux:nnNN} +% +% \begin{function}{ \clist_remove_duplicates:N | +% \clist_gremove_duplicates:N } % \begin{syntax} -% "\clist_pop_aux:nnNN" +% "\clist_gremove_duplicates:N" % \end{syntax} -% Function that assigns the left-most item of to using -% and assigns the tail to using . This -% function could be used to implement a global return function. +% Function that removes any duplicate entries in . % \end{function} -% -% \begin{function}{% -% \clist_get_aux:w | -% \clist_pop_aux:w | -% \clist_pop_auxi:w | -% \clist_put_aux:NNnnNn | -% } -% \begin{syntax}\end{syntax} -% Functions used to implement put and get operations. They are not for -% meant for direct use. +% +% \begin{function}{ +% \clist_remove_element:Nn | +% \clist_gremove_element:Nn +%} +% \begin{syntax} +% "\clist_gremove_element:Nn" +% \end{syntax} +% Function that removes from , if present. +% \begin{texnote} +% This is similar in concept to \cs{@removeelement}, except that the +% syntax is clearer and the initial and final lists have the same +% name automatically. +% \end{texnote} % \end{function} % -% -% -% \begin{function}{% -% \clist_map_function_aux:Nw | -% \clist_map_inline_aux:Nw | -% \clist_map_variable_aux:Nnw | -% } -% \begin{syntax}\end{syntax} -% Internal helper functions for the mapping functions. -% \end{function} -% -% -% \begin{function}{% -% \clist_concat_aux:NNNN | -% \clist_remove_duplicates_aux:NN | -% \clist_remove_duplicates_aux:n | -% \l_clist_remove_duplicates_clist | -% } -% \begin{syntax}\end{syntax} -% Functions that help concatenate s and remove duplicate -% elements from a . -% \end{function} -% -% -% -% \subsection{Comma list Stacks} +% \section{Functions for `comma-list stacks'} % % Special comma-lists in \LaTeX3 are `stacks' with their usual operations % of `push', `pop', and `top'. They are internally implemented as @@ -409,14 +432,16 @@ % % \begin{function}{% % \clist_push:Nn | +% \clist_push:NV | % \clist_push:No | % \clist_push:cn | % \clist_gpush:Nn | +% \clist_gpush:NV | % \clist_gpush:No | % \clist_gpush:cn | % } % \begin{syntax} -% "\clist_push:Nn" "{" "}" +% "\clist_push:Nn" \Arg{token list} % \end{syntax} % Locally or globally pushes as a single item onto the % . might get expanded before the operation. @@ -429,10 +454,10 @@ % \clist_gpop:cN | % } % \begin{syntax} -% "\clist_pop:NN" +% "\clist_pop:NN" % \end{syntax} % Functions that assign the top item of to the token -% list pointer and removes it from ! +% list variable and removes it from ! % \end{function} % % \begin{function}{% @@ -440,38 +465,65 @@ % \clist_top:cN | % } % \begin{syntax} -% "\clist_top:NN" +% "\clist_top:NN" % \end{syntax} % Functions that locally assign the top item of to the token -% list pointer . Item is not removed from ! +% list variable . Item is not removed from ! % \end{function} % -% \StopEventually{} +% \section{Internal functions} % -% Use "clist" functions. +% \begin{function}{\clist_if_empty_err:N} +% \begin{syntax} +% "\clist_if_empty_err:N" +% \end{syntax} +% Signals an \LaTeX3 error if is empty. +% \end{function} % +% \begin{function}{\clist_pop_aux:nnNN} +% \begin{syntax} +% "\clist_pop_aux:nnNN" +% \end{syntax} +% Function that assigns the left-most item of to using +% and assigns the tail to using . This +% function could be used to implement a global return function. +% \end{function} % -% \subsection {The Implementation} +% \begin{function}{% +% \clist_get_aux:w | +% \clist_pop_aux:w | +% \clist_pop_auxi:w | +% \clist_put_aux:NNnnNn | +% } +% \begin{syntax}\end{syntax} +% Functions used to implement put and get operations. They are not for +% meant for direct use. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3clist} implementation} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} %<*package> -\NeedsTeXFormat{LaTeX2e} -%\RequirePackage{l3prg,l3quark} -%\RequirePackage{l3chk} +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: % %<*initex|package> % \end{macrocode} % +% \subsection{Allocation and initialisation} % % \begin{macro}{\clist_new:N} % \begin{macro}{\clist_new:c} % Comma-Lists are implemented using token lists. % \begin{macrocode} -\def_new:Npn \clist_new:N #1{\tlp_new:Nn #1{}} -\def_new:Npn \clist_new:c {\exp_args:Nc \clist_new:N} +\cs_new_eq:NN \clist_new:N \tl_new:N +\cs_generate_variant:Nn \clist_new:N {c} % \end{macrocode} % \end{macro} % \end{macro} @@ -482,10 +534,10 @@ % \begin{macro}{\clist_gclear:c} % Clearing a comma-list is the same as clearing a token list. % \begin{macrocode} -\let_new:NN \clist_clear:N \tlp_clear:N -\let_new:NN \clist_clear:c \tlp_clear:c -\let_new:NN \clist_gclear:N \tlp_gclear:N -\let_new:NN \clist_gclear:c \tlp_gclear:c +\cs_new_eq:NN \clist_clear:N \tl_clear:N +\cs_generate_variant:Nn \clist_clear:N {c} +\cs_new_eq:NN \clist_gclear:N \tl_gclear:N +\cs_generate_variant:Nn \clist_gclear:N {c} % \end{macrocode} % \end{macro} % \end{macro} @@ -493,24 +545,32 @@ % \end{macro} % % -% \begin{macro}{\clist_set_eq:NN} -% We can set one \meta{clist} equal to another. +% \begin{macro}{\clist_clear_new:N} +% \begin{macro}{\clist_clear_new:c} +% \begin{macro}{\clist_gclear_new:N} +% \begin{macro}{\clist_gclear_new:c} +% Clearing a comma-list is the same as clearing a token list. % \begin{macrocode} -\let_new:NN \clist_set_eq:NN \let:NN +\cs_new_eq:NN \clist_clear_new:N \tl_clear_new:N +\cs_generate_variant:Nn \clist_clear_new:N {c} +\cs_new_eq:NN \clist_gclear_new:N \tl_gclear_new:N +\cs_generate_variant:Nn \clist_gclear_new:N {c} % \end{macrocode} % \end{macro} -% +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_set_eq:NN} % \begin{macro}{\clist_set_eq:cN} % \begin{macro}{\clist_set_eq:Nc} % \begin{macro}{\clist_set_eq:cc} -% An of course globally which seems to be needed far more often. +% We can set one \meta{clist} equal to another. % \begin{macrocode} -\let_new:NN \clist_gset_eq:NN \glet:NN -\def_new:Npn \clist_gset_eq:cN {\exp_args:Nc \clist_gset_eq:NN} -\def_new:Npn \clist_gset_eq:Nc {\exp_args:NNc \clist_gset_eq:NN} -\def_new:Npn \clist_gset_eq:cc {\exp_args:Ncc \clist_gset_eq:NN} +\cs_new_eq:NN \clist_set_eq:NN \cs_set_eq:NN +\cs_new_eq:NN \clist_set_eq:cN \cs_set_eq:cN +\cs_new_eq:NN \clist_set_eq:Nc \cs_set_eq:Nc +\cs_new_eq:NN \clist_set_eq:cc \cs_set_eq:cc % \end{macrocode} % \end{macro} % \end{macro} @@ -518,33 +578,30 @@ % \end{macro} % % -% \begin{macro}{\clist_if_empty_p:N} -% A predicate which evaluates to |\c_true| iff the comma-list is empty. -% \begin{macrocode} -\let_new:NN \clist_if_empty_p:N \tlp_if_empty_p:N -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\clist_if_empty:NTF} -% \begin{macro}{\clist_if_empty:NT} -% \begin{macro}{\clist_if_empty:NF} -% \begin{macro}{\clist_if_empty:cTF} -% \begin{macro}{\clist_if_empty:cT} -% \begin{macro}{\clist_if_empty:cF} -% |\clist_if_empty:NTF|\m{clist}\m{true~case}\m{false~case} will check -% whether the \m{clist} is empty and then select one of the other -% arguments. |\clist_if_empty:cTF| turns its first argument into a -% control comma-list to get the name of the comma-list. +% \begin{macro}{\clist_gset_eq:NN} +% \begin{macro}{\clist_gset_eq:cN} +% \begin{macro}{\clist_gset_eq:Nc} +% \begin{macro}{\clist_gset_eq:cc} +% An of course globally which seems to be needed far more often. % \begin{macrocode} -\def_test_function_new:npn {clist_if_empty:N}#1{\if_meaning:NN#1\c_empty_tlp} -\def_new:Npn \clist_if_empty:cTF {\exp_args:Nc\clist_if_empty:NTF} -\def_new:Npn \clist_if_empty:cT {\exp_args:Nc\clist_if_empty:NT} -\def_new:Npn \clist_if_empty:cF {\exp_args:Nc\clist_if_empty:NF} +\cs_new_eq:NN \clist_gset_eq:NN \cs_gset_eq:NN +\cs_new_eq:NN \clist_gset_eq:cN \cs_gset_eq:cN +\cs_new_eq:NN \clist_gset_eq:Nc \cs_gset_eq:Nc +\cs_new_eq:NN \clist_gset_eq:cc \cs_gset_eq:cc % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% +% \subsection{Predicates and conditionals} +% +% \begin{macro}{\clist_if_empty_p:N,\clist_if_empty_p:c} +% \begin{macro}[TF]{\clist_if_empty:N,\clist_if_empty:c} +% \begin{macrocode} +\prg_new_eq_conditional:NNn \clist_if_empty:N \tl_if_empty:N {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_empty:c \tl_if_empty:c {p,TF,T,F} +% \end{macrocode} % \end{macro} % \end{macro} % @@ -552,154 +609,257 @@ % \begin{macro}{\clist_if_empty_err:N} % Signals an error if the comma-list is empty. % \begin{macrocode} -\def_new:Npn \clist_if_empty_err:N #1{ - \if_meaning:NN#1\c_empty_tlp - \tlp_clear:N \l_testa_tlp % catch prefixes - \err_latex_bug:x{Empty~comma-list~`\token_to_string:N#1'} - \fi:} +\cs_new_nopar:Npn \clist_if_empty_err:N #1 { + \if_meaning:w #1 \c_empty_tl + \tl_clear:N \l_testa_tl % catch prefixes + \msg_kernel_bug:x {Empty~comma-list~`\token_to_str:N #1'} + \fi: +} % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_if_eq:NNTF} -% As comma lists are token list pointers internally this is just an -% alias. +% \begin{macro}{\clist_if_eq_p:NN,\clist_if_eq_p:Nc, +% \clist_if_eq_p:cN,\clist_if_eq_p:cc} +% \begin{macro}[TF]{\clist_if_eq:NN,\clist_if_eq:cN, +% \clist_if_eq:Nc,\clist_if_eq:cc} +% Returns |\c_true| iff the two comma-lists are equal. % \begin{macrocode} -\let_new:NN \clist_if_eq:NNTF \tlp_if_eq:NNTF +\prg_new_eq_conditional:NNn \clist_if_eq:NN \tl_if_eq:NN {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc {p,TF,T,F} +\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc {p,TF,T,F} % \end{macrocode} -% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[TF]{\clist_if_in:Nn} +% \begin{macro}[TF]{\clist_if_in:NV,\clist_if_in:No,\clist_if_in:cn, +% \clist_if_in:cV,\clist_if_in:co} +% |\clist_if_in:NnTF| \m{clist}\m{item} \m{true~case} \m{false~case} +% will check whether \m{item} is in \m{clist} and then either execute +% the \m{true~case} or the \m{false~case}. \m{true~case} and +% \m{false~case} may contain incomplete |\if_charcode:w| +% statements. +% \begin{macrocode} +\prg_new_conditional:Nnn \clist_if_in:Nn {TF,T,F} { + \cs_set:Npn \clist_tmp:w ##1,#2,##2##3 \q_stop { + \if_meaning:w \q_no_value ##2 + \prg_return_false: \else: \prg_return_true: \fi: + } + \exp_last_unbraced:NNo \clist_tmp:w , #1 , #2 , \q_no_value \q_stop +} +% \end{macrocode} +% \begin{macrocode} +\cs_generate_variant:Nn \clist_if_in:NnTF {NV,No,cn,cV,co} +\cs_generate_variant:Nn \clist_if_in:NnT {NV,No,cn,cV,co} +\cs_generate_variant:Nn \clist_if_in:NnF {NV,No,cn,cV,co} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Retrieving data} +% +% \begin{macro}{\clist_use:N} +% \begin{macro}{\clist_use:c} +% Using a \meta{clist} is just executing it but +% if \m{clist} equals |\scan_stop:| it is probably stemming +% from a |\cs:w ... \cs_end:| that was created by mistake somewhere. +% \begin{macrocode} +\cs_new_nopar:Npn \clist_use:N #1 { + \if_meaning:w #1 \scan_stop: + \msg_kernel_bug:x { + Comma~list~ `\token_to_str:N #1'~ has~ an~ erroneous~ structure!} + \else: + \exp_after:wN #1 + \fi: +} +\cs_generate_variant:Nn \clist_use:N {c} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_get:NN} % \begin{macro}{\clist_get:cN} -% |\clist_get:NN |\zz{comma-list}\zz{cmd} defines \zz{cmd} to be the -% left-most element of \zz{comma-list}. +% \begin{macro}{\clist_get_aux:w} +% |\clist_get:NN |\meta{comma-list}\meta{cmd} defines \meta{cmd} to be the +% left-most element of \meta{comma-list}. % \begin{macrocode} -\def_new:Npn \clist_get:NN #1{ +\cs_new_nopar:Npn \clist_get:NN #1 { \clist_if_empty_err:N #1 - \exp_after:NN\clist_get_aux:w #1,\q_stop} + \exp_after:wN \clist_get_aux:w #1,\q_stop +} % \end{macrocode} % \begin{macrocode} -\def_new:Npn \clist_get_aux:w #1,#2\q_stop #3{\tlp_set:Nn #3{#1}} +\cs_new:Npn \clist_get_aux:w #1,#2\q_stop #3 { \tl_set:Nn #3{#1} } % \end{macrocode} % \begin{macrocode} -\def_new:Npn \clist_get:cN {\exp_args:Nc \clist_get:NN} +\cs_generate_variant:Nn \clist_get:NN {cN} % \end{macrocode} % \end{macro} % \end{macro} +% \end{macro} % % \begin{macro}{\clist_pop_aux:nnNN} % \begin{macro}{\clist_pop_aux:w} % \begin{macro}{\clist_pop_auxi:w} -% |\clist_pop_aux:nnNN| \zz{def$\sb1$} \zz{def$\sb2$} \zz{comma-list} -% \zz{cmd} assigns the left-most element of \zz{comma-list} to -% \zz{cmd} using \zz{def$\sb2$}, and assigns the tail of -% \zz{comma-list} to \zz{comma-list} using \zz{def$\sb1$}. +% |\clist_pop_aux:nnNN| \meta{def$\sb1$} \meta{def$\sb2$} \meta{comma-list} +% \meta{cmd} assigns the left-most element of \meta{comma-list} to +% \meta{cmd} using \meta{def$\sb2$}, and assigns the tail of +% \meta{comma-list} to \meta{comma-list} using \meta{def$\sb1$}. % \begin{macrocode} -\def_new:Npn \clist_pop_aux:nnNN #1#2#3{ +\cs_new:Npn \clist_pop_aux:nnNN #1#2#3 { \clist_if_empty_err:N #3 - \exp_after:NN\clist_pop_aux:w #3,\q_nil\q_stop #1#2#3} + \exp_after:wN \clist_pop_aux:w #3,\q_nil\q_stop #1#2#3 +} % \end{macrocode} +% After the assignmnets below, if there was only one element in the original +% clist, it now contains only |\q_nil|. % \begin{macrocode} -\def_new:Npn \clist_pop_aux:w #1,#2\q_stop #3#4#5#6{ - #4#6{#1} - #3#5{#2} +\cs_new:Npn \clist_pop_aux:w #1,#2\q_stop #3#4#5#6 { + #4 #6 {#1} + #3 #5 {#2} + \quark_if_nil:NTF #5 { #3 #5 {} }{ \clist_pop_auxi:w #2 #3#5 } +} % \end{macrocode} -% If there was only one element in the original clist, it now contains -% only |\q_nil|. % \begin{macrocode} - \quark_if_nil:NTF #5 - { #3#5{} } - { \clist_pop_auxi:w #2 #3#5 } -} +\cs_new:Npn \clist_pop_auxi:w #1,\q_nil #2#3 { #2#3{#1} } % \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\clist_show:N} +% \begin{macro}{\clist_show:c} % \begin{macrocode} -\def_new:Npn\clist_pop_auxi:w #1,\q_nil #2#3 {#2#3{#1}} +\cs_new_eq:NN \clist_show:N \tl_show:N +\cs_new_eq:NN \clist_show:c \tl_show:c % \end{macrocode} % \end{macro} % \end{macro} +% +% \begin{macro}{\clist_display:N} +% \begin{macro}{\clist_display:c} +% \begin{macrocode} +\cs_new_nopar:Npn \clist_display:N #1 { + \iow_term:x { Comma-list~\token_to_str:N #1~contains~ + the~elements~(without~outer~braces): } + \toks_clear:N \l_tmpa_toks + \clist_map_inline:Nn #1 { + \toks_if_empty:NF \l_tmpa_toks { + \toks_put_right:Nx \l_tmpa_toks {^^J>~} + } + \toks_put_right:Nx \l_tmpa_toks { + \iow_space: \iow_char:N \{ \exp_not:n {##1} \iow_char:N \} + } + } + \toks_show:N \l_tmpa_toks +} +\cs_generate_variant:Nn \clist_display:N {c} +% \end{macrocode} +% \end{macro} % \end{macro} % +% \subsection{Storing data} +% % \begin{macro}{\clist_put_aux:NNnnNn} % The generic put function. -% \begin{macrocode} -\def_new:Npn \clist_put_aux:NNnnNn #1#2#3#4#5#6{ -% \end{macrocode} % When adding we have to distinguish between an empty \meta{clist} % and one that contains at least one item (otherwise we accumulate % commas). -% \begin{macrocode} - \clist_if_empty:NTF#5 {#1 #5{#6}} -% \end{macrocode} +% % MH says: Perhaps we should make sure that empty arguments don't get % on the stack as that is probably a mistake. That's what I've -% implemented here. Since |\tlist_if_empty:nF| is expandable prefixes +% implemented here. Since |\tl_if_empty:nF| is expandable prefixes % are still allowed. % \begin{macrocode} - { \tlist_if_empty:nF {#6}{ #2 #5{#3#6#4} } } +\cs_new:Npn \clist_put_aux:NNnnNn #1#2#3#4#5#6 { + \clist_if_empty:NTF #5 { #1 #5 {#6} } { + \tl_if_empty:nF {#6} { #2 #5{#3#6#4} } + } } % \end{macrocode} % \end{macro} +% % \begin{macro}{\clist_put_left:Nn} +% \begin{macro}{\clist_put_left:NV} % \begin{macro}{\clist_put_left:No} % \begin{macro}{\clist_put_left:Nx} % \begin{macro}{\clist_put_left:cn} +% \begin{macro}{\clist_put_left:cV} +% \begin{macro}{\clist_put_left:co} % The operations for adding to the left. % \begin{macrocode} -\def_new:Npn \clist_put_left:Nn { - \clist_put_aux:NNnnNn \tlp_set:Nn \tlp_put_left:Nn {} , +\cs_new_nopar:Npn \clist_put_left:Nn { + \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_left:Nn {} , } -\def_new:Npn \clist_put_left:cn {\exp_args:Nc \clist_put_left:Nn} -\def_new:Npn \clist_put_left:No {\exp_args:NNo\clist_put_left:Nn} -\def_new:Npn \clist_put_left:Nx {\exp_args:Nnx\clist_put_left:Nn} +\cs_generate_variant:Nn \clist_put_left:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{\clist_gput_left:Nn} +% \begin{macro}{\clist_gput_left:NV} +% \begin{macro}{\clist_gput_left:No} +% \begin{macro}{\clist_gput_left:Nx} +% \begin{macro}{\clist_gput_left:cn} +% \begin{macro}{\clist_gput_left:cV} +% \begin{macro}{\clist_gput_left:co} % Global versions. % \begin{macrocode} -\def_new:Npn \clist_gput_left:Nn { - \clist_put_aux:NNnnNn \tlp_gset:Nn \tlp_gput_left:Nn {} , +\cs_new_nopar:Npn \clist_gput_left:Nn { + \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_left:Nn {} , } +\cs_generate_variant:Nn \clist_gput_left:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_put_right:Nn} -% \begin{macro}{\clist_put_right:cn} +% \begin{macro}{\clist_put_right:NV} % \begin{macro}{\clist_put_right:No} % \begin{macro}{\clist_put_right:Nx} +% \begin{macro}{\clist_put_right:cn} +% \begin{macro}{\clist_put_right:cV} +% \begin{macro}{\clist_put_right:co} % Adding something to the right side is almost the same. % \begin{macrocode} -\def_new:Npn \clist_put_right:Nn { - \clist_put_aux:NNnnNn \tlp_set:Nn \tlp_put_right:Nn , {} +\cs_new_nopar:Npn \clist_put_right:Nn { + \clist_put_aux:NNnnNn \tl_set:Nn \tl_put_right:Nn , {} } -\def_new:Npn \clist_put_right:cn {\exp_args:Nc \clist_put_right:Nn} -\def_new:Npn \clist_put_right:No {\exp_args:Nno\clist_put_right:Nn} -\def_new:Npn \clist_put_right:Nx {\exp_args:Nnx\clist_put_right:Nn} +\cs_generate_variant:Nn \clist_put_right:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % \begin{macro}{\clist_gput_right:Nn} +% \begin{macro}{\clist_gput_right:NV} % \begin{macro}{\clist_gput_right:No} +% \begin{macro}{\clist_gput_right:Nx} % \begin{macro}{\clist_gput_right:cn} +% \begin{macro}{\clist_gput_right:cV} % \begin{macro}{\clist_gput_right:co} -% \begin{macro}{\clist_gput_right:cc} -% \begin{macro}{\clist_gput_right:NC} -% An here the global variants. +% And here the global variants. % \begin{macrocode} -\def_new:Npn \clist_gput_right:Nn { - \clist_put_aux:NNnnNn \tlp_gset:Nn \tlp_gput_right:Nn , {} +\cs_new_nopar:Npn \clist_gput_right:Nn { + \clist_put_aux:NNnnNn \tl_gset:Nn \tl_gput_right:Nn , {} } -\def_new:Npn \clist_gput_right:No {\exp_args:NNo \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:cn {\exp_args:Nc \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:co {\exp_args:Nco \clist_gput_right:Nn} -\def_new:Npn \clist_gput_right:cc {\exp_args:Ncc \clist_gput_right:Nn} -% \end{macrocode} -% \begin{macrocode} -\def_new:Npn \clist_gput_right:NC {\exp_args:NNC \clist_gput_right:Nn} +\cs_generate_variant:Nn \clist_gput_right:Nn {NV,No,Nx,cn,cV,co} % \end{macrocode} % \end{macro} % \end{macro} @@ -707,36 +867,42 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% +% +% \subsection{Mapping} % -% \begin{macro}{\clist_map_function:nN} -% \begin{macro}{\clist_map_function:cN} % \begin{macro}{\clist_map_function:NN} -% |\clist_map_function:NN| \zz{comma-list} \zz{cmd} applies \zz{cmd} to each -% element of \zz{comma-list}, from left to right. +% \begin{macro}{\clist_map_function:cN} +% \begin{macro}{\clist_map_function:nN} +% |\clist_map_function:NN| \meta{comma-list} \meta{cmd} applies \meta{cmd} to each +% element of \meta{comma-list}, from left to right. % \begin{macrocode} -\def_new:Npn \clist_map_function:NN #1#2{ - \clist_if_empty:NF #1 - { - \exp_after:NN \clist_map_function_aux:Nw - \exp_after:NN #2 #1 , \q_recursion_tail , \q_recursion_stop +\cs_new_nopar:Npn \clist_map_function:NN #1#2 { + \clist_if_empty:NF #1 { + \exp_after:wN \clist_map_function_aux:Nw + \exp_after:wN #2 #1 , \q_recursion_tail , \q_recursion_stop } } -\def_new:Npn \clist_map_function:cN{\exp_args:Nc\clist_map_function:NN} -\def_new:Npn \clist_map_function:nN #1#2{ - \tlist_if_blank:nF {#1} - { \clist_map_function_aux:Nw #2 #1 , \q_recursion_tail , \q_recursion_stop } +\cs_generate_variant:Nn \clist_map_function:NN {cN} +% \end{macrocode} +% \begin{macrocode} +\cs_new:Npn \clist_map_function:nN #1#2 { + \tl_if_blank:nF {#1} { + \clist_map_function_aux:Nw #2 #1 , \q_recursion_tail , \q_recursion_stop + } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\clist_map_function_aux:Nw} +% \begin{macro}[aux]{\clist_map_function_aux:Nw} % The general loop. Tests if we hit the first stop marker and exits if % we did. If we didn't, place the function "#1" in front of the % element "#2", which is surrounded by braces. % \begin{macrocode} -\def_long_new:Npn \clist_map_function_aux:Nw #1#2,{ +\cs_new:Npn \clist_map_function_aux:Nw #1#2,{ \quark_if_recursion_tail_stop:n{#2} #1{#2} \clist_map_function_aux:Nw #1 @@ -744,11 +910,11 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_map_break:w} +% \begin{macro}{\clist_map_break:} % The break statement is easy. Same as in other modules, gobble % everything up to the special recursion stop marker. % \begin{macrocode} -\let_new:NN \clist_map_break:w \use_none_delimit_by_q_recursion_stop:w +\cs_new_eq:NN \clist_map_break: \use_none_delimit_by_q_recursion_stop:w % \end{macrocode} % \end{macro} % @@ -769,31 +935,28 @@ % every operation globally. % \begin{macrocode} \int_new:N \g_clist_inline_level_int -\def_long_new:Npn \clist_map_inline:Nn #1#2{ - \clist_if_empty:NF #1 - { +\cs_new:Npn \clist_map_inline:Nn #1#2 { + \clist_if_empty:NF #1 { \int_gincr:N \g_clist_inline_level_int - \gdef_long:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} + \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} ##1{#2} % \end{macrocode} -% Recall that the |E| in |\exp_args:NcE| means `single token expanded -% once and no braces added'. It is a lot more efficient to carry over +% It is a lot more efficient to carry over % the special function rather than constructing the same csname over % and over again, so we just do it once. We reuse % |\clist_map_function_aux:Nw| for the actual loop. % \begin{macrocode} - \exp_args:NcE \clist_map_function_aux:Nw + \exp_last_unbraced:NcV \clist_map_function_aux:Nw {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} #1 , \q_recursion_tail , \q_recursion_stop \int_gdecr:N \g_clist_inline_level_int } } -\def_new:Npn \clist_map_inline:cn{\exp_args:Nc\clist_map_inline:Nn} -\def_long_new:Npn \clist_map_inline:nn #1#2{ - \tlist_if_empty:nF {#1} - { +\cs_generate_variant:Nn \clist_map_inline:Nn {c} +\cs_new:Npn \clist_map_inline:nn #1#2 { + \tl_if_empty:nF {#1} { \int_gincr:N \g_clist_inline_level_int - \gdef_long:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} + \cs_gset:cpn {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} ##1{#2} \exp_args:Nc \clist_map_function_aux:Nw {clist_map_inline_ \int_use:N \g_clist_inline_level_int :n} @@ -810,76 +973,78 @@ % \begin{macro}{\clist_map_variable:nNn} % \begin{macro}{\clist_map_variable:NNn} % \begin{macro}{\clist_map_variable:cNn} -% |\clist_map:NNn| \zz{comma-list} \zz{temp} \zz{action} assigns -% \zz{temp} to each element and executes \zz{action}. +% |\clist_map_variable:NNn| \meta{comma-list} \meta{temp} \meta{action} assigns +% \meta{temp} to each element and executes \meta{action}. % \begin{macrocode} -\def_new:Npn \clist_map_variable:nNn #1#2#3{ - \tlist_if_empty:nF{#1} - { +\cs_new:Npn \clist_map_variable:nNn #1#2#3 { + \tl_if_empty:nF {#1} { \clist_map_variable_aux:Nnw #2 {#3} #1 , \q_recursion_tail , \q_recursion_stop } } -\def_new:Npn \clist_map_variable:NNn {\exp_args:No \clist_map_variable:nNn} -\def_new:Npn \clist_map_variable:cNn {\exp_args:Nc \clist_map_variable:NNn} +% \end{macrocode} +% Something for v/V +% \begin{macrocode} +\cs_new_nopar:Npn \clist_map_variable:NNn {\exp_args:No \clist_map_variable:nNn} +\cs_generate_variant:Nn\clist_map_variable:NNn {cNn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}{\clist_map_variable_aux:Nnw} +% \begin{macro}[aux]{\clist_map_variable_aux:Nnw} % The general loop. Assign the temp variable |#1| to the current item % |#3| and then check if that's the stop marker. If it is, break the % loop. If not, execute the action |#2| and continue. % \begin{macrocode} -\def_new:Npn \clist_map_variable_aux:Nnw #1#2#3,{ - \def:Npn #1{#3} +\cs_new:Npn \clist_map_variable_aux:Nnw #1#2#3,{ + \cs_set_nopar:Npn #1{#3} \quark_if_recursion_tail_stop:N #1 #2 \clist_map_variable_aux:Nnw #1{#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}{\clist_concat_aux:NNNN} -% \begin{macro}{\clist_concat:NNN} -% \begin{macro}{\clist_gconcat:NNN} -% \begin{macro}{\clist_gconcat:NNc} -% \begin{macro}{\clist_gconcat:ccc} +% \subsection{Higher level functions} +% +% \begin{macro}[aux]{\clist_concat_aux:NNNN} +% \begin{macro}{\clist_concat:NNN,\clist_concat:ccc} +% \begin{macro}{\clist_gconcat:NNN,\clist_gconcat:ccc} % |\clist_gconcat:NNN| \m{clist~1} \m{clist~2} \m{clist~3} will globally % assign \m{clist~1} the concatenation of \m{clist~2} and % \m{clist~3}. +% +% Again the situation is a bit more complicated because of the use +% of commas between items, so if either list is empty we have to avoid +% adding a comma. % \begin{macrocode} -\def_new:Npn \clist_concat_aux:NNNN #1#2#3#4{ +\cs_new_nopar:Npn \clist_concat_aux:NNNN #1#2#3#4 { \toks_set:No \l_tmpa_toks {#3} \toks_set:No \l_tmpb_toks {#4} #1 #2 { \toks_use:N \l_tmpa_toks -% \end{macrocode} -% Again the situation is a bit more complicated because of the use -% of commas between items, so if either list is empty we have to avoid -% adding a comma. -% \begin{macrocode} - \toks_if_empty:NF \l_tmpa_toks {\toks_if_empty:NF \l_tmpb_toks ,} + \toks_if_empty:NF \l_tmpa_toks { \toks_if_empty:NF \l_tmpb_toks , } \toks_use:N \l_tmpb_toks } } -\def_new:Npn \clist_concat:NNN {\clist_concat_aux:NNNN \tlp_set:Nx} -\def_new:Npn \clist_gconcat:NNN {\clist_concat_aux:NNNN \tlp_gset:Nx} +\cs_new_nopar:Npn \clist_concat:NNN { \clist_concat_aux:NNNN \tl_set:Nx } +\cs_new_nopar:Npn \clist_gconcat:NNN { \clist_concat_aux:NNNN \tl_gset:Nx } +\cs_generate_variant:Nn \clist_concat:NNN {ccc} +\cs_generate_variant:Nn \clist_gconcat:NNN {ccc} % \end{macrocode} -% And the usual versions. -% \begin{macrocode} -\def_new:Npn \clist_gconcat:NNc{\exp_args:Nnnc\clist_gconcat:NNN} -\def_new:Npn \clist_gconcat:ccc{\exp_args:Nccc\clist_gconcat:NNN} -% \end{macrocode} -% \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% +% +% \begin{macro}[aux]{\l_clist_remove_clist} +% A common scratch space for the removal routines. +% \begin{macrocode} +\clist_new:N \l_clist_remove_clist +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\clist_remove_duplicates_aux:NN} -% \begin{macro}{\clist_remove_duplicates_aux:n} +% \begin{macro}[aux]{\clist_remove_duplicates_aux:NN} +% \begin{macro}[aux]{\clist_remove_duplicates_aux:n} % \begin{macro}{\clist_remove_duplicates:N} % \begin{macro}{\clist_gremove_duplicates:N} % Removing duplicate entries in a \meta{clist} is fairly straight @@ -887,23 +1052,24 @@ % from left to right. For each element check if the element is % already present in the list. % \begin{macrocode} -\def:Npn \clist_remove_duplicates_aux:NN #1#2 { - \clist_clear:N \l_clist_remove_duplicates_clist +\cs_new:Nn \clist_remove_duplicates_aux:NN { + \clist_clear:N \l_clist_remove_clist \clist_map_function:NN #2 \clist_remove_duplicates_aux:n - #1 #2 \l_clist_remove_duplicates_clist + #1 #2 \l_clist_remove_clist } -\def:Npn \clist_remove_duplicates_aux:n #1 { - \clist_if_in:NnTF \l_clist_remove_duplicates_clist {#1} {} - {\clist_put_right:Nn \l_clist_remove_duplicates_clist {#1}} +\cs_new:Nn \clist_remove_duplicates_aux:n { + \clist_if_in:NnF \l_clist_remove_clist {#1} { + \clist_put_right:Nn \l_clist_remove_clist {#1} + } } % \end{macrocode} % The high level functions are just for telling if it should be a % local or global setting. % \begin{macrocode} -\def_new:Npn \clist_remove_duplicates:N { +\cs_new_nopar:Npn \clist_remove_duplicates:N { \clist_remove_duplicates_aux:NN \clist_set_eq:NN } -\def_new:Npn \clist_gremove_duplicates:N { +\cs_new_nopar:Npn \clist_gremove_duplicates:N { \clist_remove_duplicates_aux:NN \clist_gset_eq:NN } % \end{macrocode} @@ -911,67 +1077,38 @@ % \end{macro} % \end{macro} % \end{macro} -% -% \begin{macro}{\l_clist_remove_duplicates_clist} -% \begin{macrocode} -\clist_new:N \l_clist_remove_duplicates_clist -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\clist_use:N} -% \begin{macro}{\clist_use:c} -% Using a \meta{clist} is just executing it but\dots -% \begin{macrocode} -\def_new:Npn \clist_use:N #1 { - \if_meaning:NN #1 \scan_stop: -% \end{macrocode} -% \dots\ if \m{clist} equals |\scan_stop:| it is probably stemming -% from a |\cs:w ... \cs_end:| that was created by mistake somewhere. +% +%\begin{macro}{\clist_remove_element:Nn} +%\begin{macro}{\clist_gremove_element:Nn} +%\begin{macro}[aux]{\clist_remove_element_aux:NNn} +%\begin{macro}[aux]{\clist_remove_element_aux:n} +% The same general idea is used for removing elements: the parent +% functions just set things up for the internal ones. % \begin{macrocode} - \err_latex_bug:x {Comma~list~ `\token_to_string:N #1'~ - has~ an~ erroneous~ structure!} - \else: - \exp_after:NN #1 - \fi: +\cs_new_nopar:Npn \clist_remove_element:Nn { + \clist_remove_element_aux:NNn \clist_set_eq:NN } -\def_new:Npn \clist_use:c {\exp_args:Nc \clist_use:N} -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\clist_if_in:NnTF} -% \begin{macro}{\clist_if_in:NoTF} -% \begin{macro}{\clist_if_in:cnTF} -% \begin{macro}{\clist_if_in:coTF} -% |\clist_if_in:NnTF| \m{clist}\m{item} \m{true~case} \m{false~case} -% will check whether \m{item} is in \m{clist} and then either execute -% the \m{true~case} or the \m{false~case}. \m{true~case} and -% \m{false~case} may contain incomplete |\if_charcode:w| -% statements. -% \begin{macrocode} -\def_new:Npn \clist_if_in:NnTF #1#2{ - \def:Npn \tmp:w ##1 ,#2, ##2##3\q_stop{ - \if_meaning:NN\q_no_value##2 - \exp_after:NN\use_arg_ii:nn - \else: - \exp_after:NN\use_arg_i:nn - \fi: +\cs_new_nopar:Npn \clist_gremove_element:Nn { + \clist_remove_element_aux:NNn \clist_gset_eq:NN +} +\cs_new:Nn \clist_remove_element_aux:NNn { + \clist_clear:N \l_clist_remove_clist + \cs_set:Nn \clist_remove_element_aux:n { + \tl_if_eq:nnF {#3} {##1} { + \clist_put_right:Nn \l_clist_remove_clist {##1} + } } - \exp_after:NN \tmp:w - \exp_after:NN , #1, #2, \q_no_value \q_stop + \clist_map_function:NN #2 \clist_remove_element_aux:n + #1 #2 \l_clist_remove_clist } -\def_new:Npn \clist_if_in:NoTF {\exp_args:NNo \clist_if_in:NnTF} -\def_new:Npn \clist_if_in:coTF {\exp_args:Nco \clist_if_in:NnTF} -\def_new:Npn \clist_if_in:cnTF {\exp_args:Nc \clist_if_in:NnTF} +\cs_new:Nn \clist_remove_element_aux:n { } % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} % -% -% \subsubsection{Stack operations} +% \subsection{Stack operations} % % We build stacks from comma-lists, but here we put the % specific functions together. @@ -979,6 +1116,7 @@ % % \begin{macro}{\clist_push:Nn} % \begin{macro}{\clist_push:No} +% \begin{macro}{\clist_push:NV} % \begin{macro}{\clist_push:cn} % \begin{macro}{\clist_pop:NN} % \begin{macro}{\clist_pop:cN} @@ -986,22 +1124,25 @@ % `push' and `pop'. In most cases they are nothing more then new % names for old functions. % \begin{macrocode} -\let_new:NN \clist_push:Nn \clist_put_left:Nn -\let_new:NN \clist_push:No \clist_put_left:No -\let_new:NN \clist_push:cn \clist_put_left:cn -\def_new:Npn \clist_pop:NN {\clist_pop_aux:nnNN \tlp_set:Nn \tlp_set:Nn} -\def_new:Npn \clist_pop:cN {\exp_args:Nc \clist_pop:NN} +\cs_new_eq:NN \clist_push:Nn \clist_put_left:Nn +\cs_new_eq:NN \clist_push:NV \clist_put_left:NV +\cs_new_eq:NN \clist_push:No \clist_put_left:No +\cs_new_eq:NN \clist_push:cn \clist_put_left:cn +\cs_new_nopar:Npn \clist_pop:NN {\clist_pop_aux:nnNN \tl_set:Nn \tl_set:Nn} +\cs_generate_variant:Nn \clist_pop:NN {cN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % % % \begin{macro}{\clist_gpush:Nn} % \begin{macro}{\clist_gpush:No} +% \begin{macro}{\clist_gpush:NV} % \begin{macro}{\clist_gpush:cn} % \begin{macro}{\clist_gpop:NN} % \begin{macro}{\clist_gpop:cN} @@ -1010,12 +1151,17 @@ % here more often. In case of |\clist_gpop:NN| the value is % nevertheless returned locally. % \begin{macrocode} -\let_new:NN \clist_gpush:Nn \clist_gput_left:Nn -\def_new:Npn \clist_gpush:No {\exp_args:NNo \clist_gpush:Nn} -\def_new:Npn \clist_gpush:cn {\exp_args:Nc \clist_gpush:Nn} -\def_new:Npn \clist_gpop:NN {\clist_pop_aux:nnNN \tlp_gset:Nn \tlp_set:Nn} -\def_new:Npn \clist_gpop:cN {\exp_args:Nc \clist_gpop:NN} +\cs_new_eq:NN \clist_gpush:Nn \clist_gput_left:Nn +\cs_new_eq:NN \clist_gpush:NV \clist_gput_left:NV +\cs_new_eq:NN \clist_gpush:No \clist_gput_left:No +\cs_generate_variant:Nn \clist_gpush:Nn {cn} % \end{macrocode} +% +% \begin{macrocode} +\cs_new_nopar:Npn \clist_gpop:NN {\clist_pop_aux:nnNN \tl_gset:Nn \tl_set:Nn} +\cs_generate_variant:Nn \clist_gpop:NN {cN} +% \end{macrocode} +% \end{macro} % \end{macro} % \end{macro} % \end{macro} @@ -1028,58 +1174,26 @@ % Looking at the top element of the stack without removing it is % done with this operation. % \begin{macrocode} -\let_new:NN \clist_top:NN \clist_get:NN -\let_new:NN \clist_top:cN \clist_get:cN +\cs_new_eq:NN \clist_top:NN \clist_get:NN +\cs_new_eq:NN \clist_top:cN \clist_get:cN % \end{macrocode} % \end{macro} % \end{macro} % -% -% Show token usage: % \begin{macrocode} % +% \end{macrocode} +% +% Show token usage: +% \begin{macrocode} %<*showmemory> %\showMemUsage % % \end{macrocode} % +% \end{implementation} +% \PrintIndex % % -% \endinput -% -% $Log$ -% Revision 1.16 2006/07/30 15:45:46 morten -% Made \clist_map_inline:Nn and variants nestable plus a little cleanup. -% -% Revision 1.15 2006/03/20 18:26:34 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.14 2006/01/04 01:32:09 morten -% Minor changes to code to reflect changes in l3tlp. -% -% Revision 1.13 2005/12/27 09:52:51 morten -% Minor changes plus changed RCS information retrieval -% -% Revision 1.12 2005/10/27 23:14:49 morten -% Improved loops. -% -% Revision 1.11 2005/04/12 16:45:22 morten -% Enabled put operations. Added function that removes duplicate entries (mostly for -% use after concatenating to clists) -% -% Revision 1.10 2005/04/12 13:22:13 morten -% Mostly cosmetic changes. \clist_gconcat:NNN reprogrammed using "proper" methods, \clist_put_right:Nn likewise. -% -% Revision 1.9 2005/03/22 23:26:54 morten -% Fix error message -% -% Revision 1.8 2005/03/16 22:36:43 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.7 2005/03/11 21:36:36 braams -% Fixed the use of RCS information; -% Fixed a few documentation typos; added \StopEventually -% Replaced \ifx by \if_meaning:NN, \c_if_empty_toks became \c_empty_toks -% but needs further work according to Morten % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3doc.dtx b/Master/texmf-dist/source/latex/expl3/l3doc.dtx new file mode 100644 index 00000000000..d9674ee724e --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3doc.dtx @@ -0,0 +1,1674 @@ +% \iffalse +%% File: l3doc.dtx Copyright (C) 1990-2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +%<*driver> +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +\input docstrip.tex +\askforoverwritefalse +\preamble + + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble +\generate{\file{l3doc.cls}{\from{l3doc.dtx}{class}}} +\generate{\file{l3doc.ist}{\from{l3doc.dtx}{docist}}} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +% +% +%<*driver|class> +\RequirePackage{l3names} +% +% +% Need to protect the file metadata for any modules that load l3doc. +% This is restored after "\ProvideExplClass" below. +% \begin{macrocode} +%\let \filenameOld \filename +%\let \filenameextOld \filenameext +%\let \filedateOld \filedate +%\let \fileversionOld \fileversion +%\let \filedescriptionOld \filedescription +% \end{macrocode} +% +%<*driver|class> +\GetIdInfo$Id: l3doc.dtx 1398 2009-06-08 15:53:26Z joseph $ + {L3 Experimental documentation class} +% +% +%<*driver> +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +\documentclass{l3doc} +\begin{document} +\DocInput{l3doc.dtx} +\end{document} +% +% +% This isn't included in the typeset documentation because it's a bit ugly: +%<*class> +\ProvidesExplClass + {\filename}{\filedate}{\fileversion}{\filedescription} +\RequirePackage{expl3} +\let \filename \filenameOld +\let \filenameext \filenameextOld +\let \filedate \filedateOld +\let \fileversion \fileversionOld +\let \filedescription \filedescriptionOld +% +% \fi +% +% \title{The \pkg{l3doc} class\thanks{This file +% has version number \fileversion, last +% revised \filedate.}} +% \author{\Team} +% \date{\filedate} +% \maketitle +% \tableofcontents +% +% \begin{documentation} +% +% \section{Introduction} +% +% This is an ad-hoc class for documenting the \pkg{expl3} bundle, +% a collection of modules or packages that make up \LaTeX3's programming +% environment. Eventually it will replace the "ltxdoc" class for \LaTeX3, +% but not before the good ideas in \pkg{hypdoc}, \cls{xdoc2}, \pkg{docmfp}, and +% \cls{gmdoc} are incorporated. +% +% \textbf{It is even less stable than the main \pkg{expl3} packages. Use at own risk!} +% +% It is written as a `self-contained' docstrip file: executing +% "latex l3doc.dtx" +% will generate the "l3doc.cls" file and typeset this +% documentation; execute "tex l3doc.dtx" to only generate the ".cls" file. +% +% \section{Features of other packages} +% +% This class builds on the \pkg{ltxdoc} class and the \pkg{doc} package, but +% in the time since they were originally written some +% improvements and replacements have appeared that we would like to use as +% inspiration. +% +% These packages or classes are \pkg{hypdoc}, \pkg{docmfp}, \pkg{gmdoc}, +% and \pkg{xdoc}. I have summarised them below in order to work out what +% sort of features we should aim at a minimum for \pkg{l3doc}. +% +% \subsection{The \pkg{hypdoc} package} +% +% This package provides hyperlink support for the \pkg{doc} package. I have +% included it in this list to remind me that cross-referencing between +% documentation and implementation of methods is not very good. (E.g., it +% would be nice to be able to automatically hyperlink the documentation for +% a function from its implementation and vice-versa.) +% +% \subsection{The \pkg{docmfp} package} +% +% \begin{itemize} +% \item Provides "\DescribeRoutine" and the "routine" environment (etc.) +% for MetaFont and MetaPost code. +% \item Provides "\DescribeVariable" and the "variable" environment (etc.) +% for more general code. +% \item Provides "\Describe" and the "Code" environment (etc.) as a +% generalisation of the above two instantiations. +% \item Small tweaks to the DocStrip system to aid non-\LaTeX\ use. +% \end{itemize} +% +% \subsection{The \pkg{xdoc2} package} +% +% \begin{itemize} +% \item Two-sided printing. +% \item "\NewMacroEnvironment", "\NewDescribeEnvironment"; similar idea +% to \pkg{docmfp} but more comprehensive. +% \item Tons of small improvements. +% \end{itemize} +% +% \subsection{The \pkg{gmdoc} package} +% +% Radical re-implementation of \pkg{doc} as a package or class. +% \begin{itemize} +% \item Requires no "\begin{macrocode}" blocks! +% \item Automatically inserts "\begin{macro}" blocks! +% \item And a whole bunch of other little things. +% \end{itemize} +% +% \section{Problems \& Todo} +% +% Problems at the moment: (1)~not flexible in the types of things that can be documented; (2)~very nonstandard markup (using `"|"' as a delimiter and the odd `"/ (...)"' tags; (3)~no obvious link to the "\begin{macro}" function that's used analogously in the implementation. +% +% The environments "function" and "macro" should probably +% be renamed to something like \env{funcdoc} and \env{funcimpl}, +% respectively. +% +% Furthermore, we need another `layer' of documentation commands to +% account for `user-macro' as opposed to `code-functions'; the \pkg{expl3} +% functions should be documented differently, probably, to the \pkg{xparse} +% user macros (at least in terms of indexing). +% +% In no particular order, a list of things to do: +% \begin{itemize} +% \item Rename \env{function}/\env{macro} environments to better describe +% their use. +% \item Generalise \env{function}/\env{macro} for documenting `other things', +% such as environment names, package options, even keyval options. +% \item Use \pkg{xparse}. +% \item New function like "\part" but for files (remove awkward `File' as "\partname"). +% \item Something better to replace "\StopEventually"; I'm thinking two +% environments \env{documentation} and \env{implementation} that can +% conditionally typeset/ignore their material. +% \item Hyperlink documentation and implementation of macros (also see +% the \textsc{dtx} file of \pkg{svn-multi} v2). +% \end{itemize} +% +% \section{Bugs} +% +% \begin{itemize} +% \item Spaces are ignored entirely within \env{function} and \env{macro} +% arguments. This is just waiting for a convenient space-trimming +% macro in \pkg{expl3}. +% \end{itemize} +% +% \section{Documentation} +% +% \subsection{Partitioning documentation and implementation} +% +% \pkg{doc} uses the "\OnlyDocumentation"/"\AlsoImplementation" macros +% to guide the use of "\StopEventually{}", which is intended to be placed +% to partition the documentation and implementation within a single DTX file. +% +% This isn't very flexible, since it assumes that we \emph{always} want +% to print the documentation. For the \pkg{expl3} sources, I wanted to be +% be able to input DTX files in two modes: only displaying the documentation, +% and only displaying the implementation. For example: +% +% \begin{verbatim} +% \DisableImplementation +% \DocInput{l3basics,l3prg,...} +% \EnableImplementation +% \DisableDocumentation +% \DocInputAgain +% \end{verbatim} +% +% The idea being that the entire \pkg{expl3} bundle can be documented, +% with the implementation included at the back. Now, this isn't perfect, +% but it's a start. +% +% Use "\begin{documentation}...\end{documentation}" around the documentation, +% and "\begin{implementation}...\end{implementation}" around the implementation. +% The "\EnableDocumentation"/"\EnableImplementation" will cause them to be typeset +% when the DTX file is "\DocInput"; use "\DisableDocumentation"/"\DisableImplementation" +% to omit the contents of those environments. +% +% Note that \cmd\DocInput\ now takes comma-separated arguments, and \cmd\DocInputAgain\ +% can be used to re-input all DTX files previously input in this way. +% +% \subsection{Describing functions in the documentation} +% +% \DescribeEnv{function} +% \DescribeEnv{syntax} +% Two heavily-used environments are defined to describe the syntax +% of \textsf{expl3} functions and variables. +% \begin{verbatim} +% \begin{function}{ list_of | functions } +% \begin{syntax} +% "\foo_bar:" \Arg{meta} +% \end{syntax} +% +% \end{function} +% \end{verbatim} +% +% \begin{function}{ list_of | functions } +% \begin{syntax} +% "\foo_bar:" \Arg{meta} +% \end{syntax} +% +% \end{function} +% +% Note that the list of functions use "|" as a separator. +% +% \bigskip +% \textbf{MAJOR PROPOSED CHANGE}\qquad +% I think we should probably discourage this sort of free-form markup in +% \LaTeX3 and change this to a plain ol' comma-separated list instead. +% +% Alternatively, we could provide programmatic means of looping through +% lists with arbitary separators and promote this kind of thing. +% +% \subsection{Describing functions in the implementation} +% +% \DescribeEnv{macro} +% The well-used environment from \LaTeXe\ for marking up the implementation +% of macros/functions remains the \env{macro} environment. +% One major change in \pkg{l3doc}: it now accepts comma-separated lists +% of functions, to avoid a very large number of consecutive "\end{macro}" +% statements. +% \begin{verbatim} +% % \begin{macro}{\foo:N,\foo:c} +% % \begin{macrocode} +% ... code for \foo:N and \foo:c ... +% % \end{macrocode} +% % \end{macro} +% \end{verbatim} +% +% \DescribeEnv{arguments} +% Within a \env{macro} environment, you may use the \env{arguments} environment +% to describe the arguments taken by the function(s). It behaves exactly +% like a list environment. +% \begin{verbatim} +% % \begin{macro}{\foo:nn,\foo:VV} +% % \begin{arguments} +% % \item Name of froozle to be frazzled +% % \item Name of muble to be jubled +% % \end{arguments} +% % \begin{macrocode} +% ... code for \foo:nn and \foo:VV ... +% % \end{macrocode} +% % \end{macro} +% \end{verbatim} +% +% \bigskip +% \textbf{OPTIONS FOR THE FUTURE}\qquad Any improvements to the markup +% for the \env{function} environment would be good to mirror in \env{macro}. +% +% Perhaps this would be a better syntax for describing arguments? +% \begin{verbatim} +% \begin{macro}{\foo:nn,foo:VV} +% \dArg{Name of froozle to be frazzled} +% \dArg{Name of mumble to be jumbled} +% ... +% \end{verbatim} +% I.e., get rid of the environment and do things like in, say, \pkg{fontspec}. +% +% \subsection{Keeping things consistent} +% +% Whenever a function is either documented or defined with \env{function} +% and \env{macro} respectively, its name is stored in a sequence for later +% processing. +% +% At the end of the document (i.e., after the \textsc{dtx} file has finished +% processing), the list of names is analysed to check whether all defined +% functions have been documented and vice versa. The results are printed +% in the console output. +% +% If you need to do more serious work with these lists of names, take a +% look at the implementation for the data structures and methods used to +% store and access them directly. +% +% \subsection{Documenting templates} +% +% The following macros are provided for documenting templates; might +% end up being something completely different but who knows. +% \begin{quote}\parskip=0pt\obeylines +% "\begin{TemplateInterfaceDescription}" \Arg{template type name} +% " \TemplateArgument{none}{---}" +% \textsc{or one or more of these:} +% " \TemplateArgument" \Arg{arg no} \Arg{meaning} +% \textsc{and} +% "\TemplateSemantics" +% " " \meta{text describing the template type semantics} +% "\end{TemplateInterfaceDescription}" +% \end{quote} +% +% \begin{quote}\parskip=0pt\obeylines +% "\begin{TemplateDescription}" \Arg{template type name} \Arg{name} +% \textsc{one or more of these:} +% " \TemplateKey" \marg{key name} \marg{type of key} +% " "\marg{textual description of meaning} +% " "\marg{default value if any} +% \textsc{and} +% "\TemplateSemantics" +% " " \meta{text describing special additional semantics of the template} +% "\end{TemplateDescription}" +% \end{quote} +% +% \begin{quote}\parskip=0pt\obeylines +% "\begin{InstanceDescription}" \oarg{text to specify key column width (optional)} +% \hfill\marg{template type name}\marg{instance name}\marg{template name} +% \textsc{one or more of these:} +% " \InstanceKey" \marg{key name} \marg{value} +% \textsc{and} +% "\InstanceSemantics" +% " " \meta{text describing the result of this instance} +% "\end{InstanceDescription}" +% \end{quote} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3doc} implementation} +% +% \begin{macrocode} +%<*class> +% \end{macrocode} +% +% The Guilty Parties. +% \begin{macrocode} +\cs_new_nopar:Npn\Team{% + The~\LaTeX3~Project\thanks{% + Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~ + Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~ + David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~ + Javier~Bezos,~Will~Robertson,~Joseph~Wright}} +% \end{macrocode} +% +% \subsection{Options} +% +% \begin{macrocode} +\DeclareOption{a5paper}{\@latexerr{Option not supported}{}} +% \end{macrocode} +% +% \begin{macrocode} +\bool_new:N \g_doc_full_bool +\bool_set_false:N \g_doc_full_bool +\DeclareOption{full}{ \bool_set_true:N \g_doc_full_bool } +\DeclareOption{onlydoc}{ \bool_set_false:N \g_doc_full_bool } +% \end{macrocode} +% +% \begin{macrocode} +\bool_new:N \g_doc_checkfunc_bool +\bool_set_true:N \g_doc_checkfunc_bool +\DeclareOption{check}{ \bool_set_true:N \g_doc_checkfunc_bool } +\DeclareOption{nocheck}{ \bool_set_false:N \g_doc_checkfunc_bool } +% \end{macrocode} +% +% \begin{macrocode} +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} +\ExecuteOptions{full} +\ProcessOptions +% \end{macrocode} +% +% +% \subsection{Class and package loading} +% +% \begin{macrocode} +\LoadClass[a4paper]{article} +\RequirePackage{doc} +\RequirePackage{array,alphalph,color,fixltx2e,enumitem,trace,underscore} +% \end{macrocode} +% +% \begin{macrocode} +\RequirePackage[T1]{fontenc} +\RequirePackage{lmodern,textcomp} +\RequirePackage{hypdoc} +% \end{macrocode} +% Just want the "comment" environment from \pkg{verbatim}: +% \begin{macrocode} +\let\doc@verbatim\verbatim +\let\enddoc@verbatim\endverbatim +\let\doc@@verbatim\@verbatim +\usepackage{verbatim} +\AtBeginDocument{% + \let\verbatim\doc@verbatim + \let\endverbatim\enddoc@verbatim + \let\@verbatim\doc@@verbatim +} +% \end{macrocode} +% +% \subsection{Configuration} +% +% \begin{macro}{\MakePrivateLetters} +% \begin{macrocode} +\cs_set_nopar:Npn \MakePrivateLetters { + \char_make_letter:N \@ + \char_make_letter:N \_ + \char_make_letter:N \: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\setcounter{StandardModuleDepth}{1} +\@addtoreset{CodelineNo}{part} +\cs_set_nopar:Npn \theCodelineNo { + \textcolor[gray]{0.5}{ \sffamily\tiny\arabic{CodelineNo} } +} +% \end{macrocode} +% +% +% +% \subsection{Design} +% +% Increase the text width slightly so that width the standard fonts +% 72 columns of code may appear in a |macrocode| environment. +% Increase the marginpar width slightly, for long command names. +% And increase the left margin by a similar amount. +% \begin{macrocode} +\setlength \textwidth { 385pt } +\addtolength \marginparwidth { 30pt } +\addtolength \oddsidemargin { 20pt } +\addtolength \evensidemargin { 20pt } +% \end{macrocode} +% (These were introduced when "article" was the documentclass, but +% I've left them here for now to remind me to do something about them +% later; we still have the problem of \emph{very long} command names.) +% +% Customise lists: +% \begin{macrocode} +\cs_set_eq:NN \@@oldlist\list +\cs_set_nopar:Npn \list#1#2{\@@oldlist{#1}{#2\listparindent\z@}} +\setlength \parindent { 0pt } +\setlength \itemindent { 0pt } +\setlength \parskip { \medskipamount } +% \end{macrocode} +% +% \subsection{Text markup} +% +% Make "|" and |"| be `short verb' characters, but not in +% the document preamble, where an active character may interfere +% with packages that are loaded. +% \begin{macrocode} +\AtBeginDocument { + \MakeShortVerb \" + \MakeShortVerb \| +} +% \end{macrocode} +% +% \begin{macrocode} +\providecommand*\eTeX{ + \if b\expandafter\@car\f@series\@nil\boldmath\fi + $\m@th\varepsilon$-\TeX +} +% \end{macrocode} +% +% \begin{macro}{\cmd,\cs} +% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving +% arguments. |\cs{foo}| also prints |\foo|, for those who prefer that +% syntax. +% \begin{macrocode} +\cs_set_nopar:Npn \cmd #1 { \cs{\expandafter\cmd@to@cs\string#1} } +\cs_set_nopar:Npn \cmd@to@cs #1#2 { \char\number`#2\relax } +\DeclareRobustCommand \cs [1] { \texttt { \char`\\ #1 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\marg,\oarg,\parg} +% |\marg{text}| prints \marg{text}, `mandatory argument'.\\ +% |\oarg{text}| prints \oarg{text}, `optional argument'.\\ +% |\parg{te,xt}| prints \parg{te,xt}, `picture mode argument'. +% \begin{macrocode} +\providecommand\marg[1]{ \texttt{\char`\{} \meta{#1} \texttt{\char`\}} } +\providecommand\oarg[1]{ \texttt[ \meta{#1} \texttt] } +\providecommand\parg[1]{ \texttt( \meta{#1} \texttt) } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\m,\file,\env,\pkg,\cls} +% This list may change\dots this is just my preference for markup. +% \begin{macrocode} +\cs_set_eq:NN \m \meta +\cs_set_eq:NN \file \nolinkurl +\DeclareRobustCommand \env {\texttt} +\DeclareRobustCommand \pkg {\textsf} +\DeclareRobustCommand \cls {\textsf} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{texnote} +% \begin{macrocode} +\newenvironment{texnote}{ + \endgraf + \vspace{3mm} + \small\textbf{\TeX~hackers~note:} +}{ + \vspace{3mm} +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\tn} +% \begin{macrocode} +\newcommand\tn[1]{ + \texttt{\bslash #1} + \index{TeX~and~LaTeX2e~commands\actualchar + \string\TeX{}~and~\string\LaTeXe{}~commands:\levelchar + #1\actualchar{\string\ttfamily\string\bslash{}#1}}} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{documentation} +% \begin{environment}{implementation} +% \begin{macro}{\EnableDocumentation,\EnableImplementation} +% \begin{macro}{\DisableDocumentation,\DisableImplementation} +% \begin{macrocode} +\newenvironment{documentation}{}{} +\newenvironment{implementation}{}{} +\newcommand\EnableDocumentation{% + \renewenvironment{documentation}{}{}% +} +\newcommand\EnableImplementation{% + \renewenvironment{implementation}{}{}% +} +\newcommand\DisableDocumentation{% + \cs_set_eq:NN \documentation \comment + \cs_set_eq:NN \enddocumentation \endcomment +} +\newcommand\DisableImplementation{% + \cs_set_eq:NN \implementation \comment + \cs_set_eq:NN \endimplementation \endcomment +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{environment} +% \end{environment} +% +% \begin{environment}{arguments} +% This environment is designed to be used within a \env{macro} environment +% to describe the arguments of the macro/function. +% \begin{macrocode} +\newenvironment{arguments}{ + \enumerate[ + nolistsep, + label=\texttt{\#\arabic*}~:, + labelsep=*, + ] +}{ + \endenumerate +} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{function} +% \begin{environment}{variable} +% Environment for documenting function(s). +% Stick the function names in a box. Use a "|" as delimiter and +% allow |<...>| to be used as markup for |\meta{...}|. +% Ignore spaces and sanitize with catcodes before reading argument. +% \begin{macrocode} +\group_begin: +\char_make_active:N \< +\cs_gnew_nopar:Npn \function { + \char_make_active:N \< + \cs_set_eq:NN < \doc_open_meta:n + \group_begin: + \MakePrivateLetters + \char_make_other:N \| + \char_make_other:N \^ + \char_make_other:N \\ + \char_make_space:N \~ + \char_make_ignore:N \ % space + \char_make_ignore:N \^^M + \char_make_ignore:N \^^I + \function_aux:n +} +\group_end: +% \end{macrocode} +% And the "variable" function is exactly the same for now: +% \begin{macrocode} +\cs_set_eq:NN \variable \function +% \end{macrocode} +% +% \begin{macro}{\function_aux:n} +% \begin{arguments} +% \item Vertical bar--separated list of functions with optional metadata; +% input has already been sanitised by catcode changes before reading +% the argument. +% \end{arguments} +% \begin{macrocode} +\cs_set_nopar:Npn \function_aux:n #1 { + \cs_set_nopar:Npn \nextnewline{\cs_gset_nopar:Npn\nextnewline{\\}} + \tl_gset_eq:NN \g_doc_macro_tl \c_empty_tl + \bigskip\endgraf\noindent\ttfamily + \tabular[b]{ | l @{} c | } + \hline + \doc_showmacro:w #1 | \q_stop \\ + \hline + \endtabular + \group_end: +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \end{environment} +% +% \begin{macro}{\doc_showmacro:w} +% This function reads in a "|"-separated list, passing each item to +% the auxiliary function "\doc_showmacro_aux:w". +% \begin{macrocode} +\cs_set_nopar:Npn \doc_showmacro:w #1 | { + \tl_if_blank:nTF {#1} { + \use_none:n + }{ + \doc_showmacro_aux:w #1 / \q_stop + \peek_meaning:NTF \q_stop { \use_none:n } { \doc_showmacro:w } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\bool_new:N \l_doc_meta_TF_bool +\bool_new:N \l_doc_meta_EXP_bool +% \end{macrocode} +% +% \begin{macro}{\doc_showmacro_aux:w} +% This macro is passed one of: +% \begin{quote} +% "\abc:cnx / (EXP) / \q_stop" \\ +% "\abc:cnx / \q_stop" \\ +% \end{quote} +% We also have some code here to print out every documented macro at the end +% of the document. +% \begin{arguments} +% \item Function/macro/variable name \item Metadata tags (if any) +% \end{arguments} +% \begin{macrocode} +\cs_new_nopar:Npn \doc_showmacro_aux:w #1 / #2 \q_stop { + + \tl_if_in:nnTF {#2} { (TF) } { + \bool_gset_true:N \l_doc_meta_TF_bool + }{ + \bool_gset_false:N \l_doc_meta_TF_bool + } + \tl_if_in:nnTF {#2} { (EXP) } { + \bool_gset_true:N \l_doc_meta_EXP_bool + }{ + \bool_gset_false:N \l_doc_meta_EXP_bool + } + + \bool_if:NTF \l_doc_meta_TF_bool { + \doc_special_main_index:o { #1 TF } + \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 TF } } + \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 T } } + \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 F } } + }{ + \doc_special_main_index:o { #1 } + \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n { #1 } } + } + + \doc_showmacro_aux_ii:w #1::\q_stop +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\doc_showmacro_aux_ii:w} +% This macro is passed one of: +% \begin{quote} +% "\showexplmacro "^^A +% \makebox[\widthof{\texttt{123456}}]{\meta{name}}^^A +% " ::\q_stop" \\ +% "\showexplmacro \foo ::\q_stop" \\ +% "\showexplmacro \foo: ::\q_stop" \\ +% "\showexplmacro \foo:Z ::\q_stop" \\ +% \end{quote} +% Notice that for "\foo", "#2" and "#3" are empty,\\ +% for "\foo:", "#2" is empty,\\ +% and for both "\foo:" and "\foo:Z", "#3" is `":"' . +% \begin{arguments} +% \item Function name \item Possible arg.\ spec. \item Possible colon +% \end{arguments} +% \begin{macrocode} +\cs_set_nopar:Npn \doc_showmacro_aux_ii:w #1:#2:#3 \q_stop { + \nextnewline + + \tl_if_eq:xxTF {#1} {\g_doc_macro_tl} { + \doc_typeset_aux:n + }{ + \tl_gset:Nn \g_doc_macro_tl {#1} + \use:n + } + { \g_doc_macro_tl } + #3 + #2 + \bool_if:NT \l_doc_meta_TF_bool { \doc_typeset_TF: } + & + \bool_if:NT \l_doc_meta_EXP_bool { + \hspace{\tabcolsep} + $\star$ + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{syntax} +% Syntax block placed next to the list of functions to illustrate their use. +% \begin{macrocode} +\newenvironment{syntax}{% + \minipage[b]{.7\textwidth}% + \cs_set_nopar:Npn \meta@font@select{\rmfamily\itshape} % (Will: I HATE italic cmtt!) + \small\ttfamily\raggedright + \obeyspaces\obeylines +}{% + \endminipage + \hfil\break + \global\@ignoretrue +} +% \end{macrocode} +% \end{environment} +% +% Perhaps these belong in \file{l3token}? +% \begin{macrocode} +\tl_map_inline:nn {0123456789} { \cs_gset_eq:cN {char_other_#1} #1 } +% \end{macrocode} +% +% \begin{macro}{\doc_open_meta:n,\doc_close_meta:n} +% This code turns all numbers within "<...>" markup to be set as subscripts. +% You can use escaped numbers to get the real thing (e.g., "\1" = `1'). +% \begin{macrocode} +\group_begin: + \tl_map_inline:nn {0123456789} { \char_make_active:N #1 } + \cs_gnew:Npn \doc_open_meta:n { + \group_begin: + \tl_map_function:nN {0123456789} \doc_assign_num:n + \doc_close_meta:w + } + \cs_gnew:Npn \Arg { + \texttt{ \char`\{ } + \group_begin: + \tl_map_function:nN {0123456789} \doc_assign_num:n + \doc_close_Arg:n + } +\group_end: +\cs_new_nopar:Npn \doc_close_meta:w #1> { \meta {#1} \group_end: } +\cs_new_nopar:Npn \doc_close_Arg:n #1 { + \meta {#1} + \group_end: + \texttt{ \char`\} } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\doc_assign_num:n} +% This function takes a numeral (`0'), defines its escaped self to be equal +% to itself ("\0" $\to$ `0'), makes it active, and turns itself into a subscript +% instead (`0' $\to$ `${}_0$'). +% \begin{macrocode} +\cs_new_nopar:Npn \doc_assign_num:n #1 { + \cs_set_eq:cc { \string #1 } { char_other_\string #1 } + \char_make_active:N #1 + \cs_set_nopar:Npn #1 { \unskip \, $ {} \sb { \use:c { char_other_\string #1 } } $ } +} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{macro} +% We want to extend the old definition to allow comma-separated lists of +% macros, rather than one at a time. keyval processing is very rudimentary; +% awaiting a more robust solution. +% \begin{macrocode} +\renewcommand \macro [1][] { + \bool_set_false:N \l_doc_macro_aux_bool + \bool_set_false:N \l_doc_macro_TF_bool + \cs_set_eq:NN \doc_macroname_prefix:n \use:n + \cs_set_eq:NN \doc_macroname_suffix: \c_empty_tl + + \cs_set_nopar:Npn \KV_key_no_value_elt:n ##1 { \use:c {doc_macro_opt_##1:} } + \KV_parse_space_removal_sanitize:n {#1} + + \group_begin: + \MakePrivateLetters + \char_make_letter:N \\ + \char_make_ignore:N \ % space + \char_make_ignore:N \^^M + \char_make_ignore:N \^^I + \doc_macro_aux:n +} +% \end{macrocode} +% After changing the catcodes, parse the arguments: +% \begin{macrocode} +\cs_new_nopar:Npn \doc_macro_aux:n #1 { + \group_end: + \clist_map_inline:nn {#1} { \doc_macro_single {##1} } +} +% \end{macrocode} +% +% \begin{macrocode} +\bool_new:N \l_doc_macro_aux_bool +\bool_new:N \l_doc_macro_TF_bool +\cs_set_nopar:Npn \doc_macro_opt_aux: { \bool_set_true:N \l_doc_macro_aux_bool } +\cs_set_nopar:Npn \doc_macro_opt_TF: { \bool_set_true:N \l_doc_macro_TF_bool } +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{doc_macro_single} +% Let's start to mess around with "doc"'s "macro" environment. See \file{doc.dtx} +% for a full explanation of the original environment. It's +% rather \emph{enthusiastically} commented. +% \begin{arguments} +% \item Macro/function/whatever name; input has already been sanitised. +% \end{arguments} +% \begin{macrocode} +\cs_set_nopar:Npn \doc_macro_single #1 { + + \topsep\MacroTopsep + \trivlist + \cs_set_nopar:Npn \makelabel ##1 { \llap{##1} } + \if@inlabel + \cs_set_eq:NN \@tempa \@empty + \count@ \macro@cnt + \loop \ifnum\count@>\z@ + \cs_set_nopar:Npx \@tempa{\@tempa\hbox{\strut}} + \advance\count@\m@ne + \repeat + \cs_set_nopar:Npx \makelabel ##1 { + \llap{\vtop to\baselineskip {\@tempa\hbox{##1}\vss}} + } + \advance \macro@cnt \@ne + \else + \macro@cnt \@ne + \fi + + \bool_if:NT \l_doc_macro_aux_bool { + \cs_set_eq:NN \doc_macroname_prefix:n \doc_typeset_aux:n + } + \bool_if:NT \l_doc_macro_TF_bool { + \cs_set_eq:NN \doc_macroname_suffix: \doc_typeset_TF: + } + + \cs_set_nopar:Npx \@tempa { + \exp_not:N \item [ \exp_not:N \doc_print_macroname:n { + \tl_to_str:n {#1} + }] + } \@tempa + \global\advance \c@CodelineNo \@ne + + \bool_if:NF \l_doc_macro_aux_bool { + \bool_if:NTF \l_doc_macro_TF_bool { + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 TF } } + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 T } } + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 F } } + }{ + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n {#1} } + } + } + \bool_if:NTF \l_doc_macro_TF_bool { + \SpecialMainIndex{#1 TF}\nobreak + \DoNotIndex{#1 TF} + }{ + \SpecialMainIndex{#1}\nobreak + \DoNotIndex{#1} + } + + \global\advance \c@CodelineNo \m@ne + \ignorespaces +} +% \end{macrocode} +% +% \begin{macro}{\doc_print_macroname:n} +% \begin{macrocode} +\cs_set_nopar:Npn \doc_print_macroname:n #1 { + \strut \MacroFont + \doc_macroname_prefix:n {#1} \doc_macroname_suffix: \ % space! +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \begin{macro}{\doc_typeset_TF:,\doc_typeset_aux:n} +% Used by \cs{doc_macro_single} and \cs{doc_showmacro_aux_ii:w} to typeset +% conditionals and auxiliary functions. +% \begin{macrocode} +\cs_set_nopar:Npn \doc_typeset_TF: { + \color[gray]{0.5} + \underline { \color{black} \itshape TF \kern-0.1em } +} +\cs_set_nopar:Npn \doc_typeset_aux:n #1 { + {\color[gray]{0.5} #1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DescribeOption} +% For describing package options. Due to Joseph Wright. +% Name/usage might change soon. +% \begin{macrocode} +\newcommand*{\DescribeOption}{ + \leavevmode + \@bsphack + \begingroup + \MakePrivateLetters + \Describe@Option +} +\newcommand*{\Describe@Option}[1]{ + \endgroup + \marginpar{ + \raggedleft + \PrintDescribeEnv{#1} + } + \SpecialOptionIndex{#1} + \@esphack + \ignorespaces +} +\newcommand*{\SpecialOptionIndex}[1]{ + \@bsphack + \begingroup + \HD@target + \let\HDorg@encapchar\encapchar + \edef\encapchar usage{ + \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage} + } + \index{ + #1\actualchar{\protect\ttfamily#1} (option) + \encapchar usage + } + \index{ + options:\levelchar#1\actualchar{\protect\ttfamily#1} + \encapchar usage + } + \endgroup + \@esphack +} +% \end{macrocode} +% \end{macro} +% +% Here are some definitions for additional markup that will help to +% structure your documentation. +% +% \begin{environment}{danger} +% \begin{environment}{ddanger} +% \begin{syntax} +% |\begin{[d]danger}|\\ +% dangerous code\\ +% |\end{[d]danger}| +% \end{syntax} +% +% \begin{danger} +% Provides a danger bend, as known from the \TeX{}book. +% \end{danger} +% The actual character from the font |manfnt|: +% \begin{macrocode} +\font\manual=manfnt +\cs_set_nopar:Npn \dbend { {\manual\char127} } +% \end{macrocode} +% +% Defines the single danger bend. Use it whenever there is a feature in your +% package that might be tricky to use. +% FIXME: Has to be fixed when in combination with a macro-definition. +% \begin{macrocode} +\newenvironment {danger} { + \begin{trivlist}\item[]\noindent + \begingroup\hangindent=2pc\hangafter=-2 + \cs_set_nopar:Npn \par{\endgraf\endgroup} + \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces +}{ + \par\end{trivlist} +} +% \end{macrocode} +% +% \begin{ddanger} +% Use the double danger bend if there is something which could cause serious +% problems when used in a wrong way. Better the normal user does not know +% about such things. +% \end{ddanger} +% \begin{macrocode} +\newenvironment {ddanger} { + \begin{trivlist}\item[]\noindent + \begingroup\hangindent=3.5pc\hangafter=-2 + \cs_set_nopar:Npn \par{\endgraf\endgroup} + \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\ignorespaces +}{ + \par\end{trivlist} +} +% \end{macrocode} +% \end{environment} +% \end{environment} +% +% \subsection{Documenting templates} +% +% \begin{macrocode} +\newenvironment{TemplateInterfaceDescription}[1] + {\subsection{The template type `#1'}% + \begingroup + \@beginparpenalty\@M + \description + \def\TemplateArgument##1##2{\item[Arg: ##1]##2\par}% + \def\TemplateSemantics{\enddescription\endgroup + \subsubsection*{Semantics:}}% + } + {\par\bigskip} +% \end{macrocode} +% +% \begin{macrocode} +\newenvironment{TemplateDescription}[2] + {\subsection{The template `#2' (type #1)}% + \subsubsection*{Attributes:}% + \begingroup + \@beginparpenalty\@M + \description + \def\TemplateKey##1##2##3##4{\item[##1 (##2)]##3% + \ifx\TemplateKey##4\TemplateKey\else +% \hskip0ptplus3em\penalty-500\hskip 0pt plus 1filll Default:~##4% + \hfill\penalty500\hbox{}\hfill Default:~##4% + \nobreak\hskip-\parfillskip\hskip0pt\relax + \fi + \par}% + \def\TemplateSemantics{\enddescription\endgroup + \subsubsection*{Semantics \& Comments:}}% + } + {\par\bigskip} +% \end{macrocode} +% +% \begin{macrocode} +\newenvironment{InstanceDescription}[4][xxxxxxxxxxxxxxx] + {\subsubsection{The instance `#3' (template #2/#4)}% + \subsubsection*{Attribute values:}% + \begingroup + \@beginparpenalty\@M + \def\InstanceKey##1##2{\>\textbf{##1}\>##2\\}% + \def\InstanceSemantics{\endtabbing\endgroup + \vskip-30pt\vskip0pt + \subsubsection*{Layout description \& Comments:}}% + \tabbing + xxxx\=#1\=\kill + } + {\par\bigskip} +% \end{macrocode} +% +% \subsection{Inheriting doc} +% +% Code here is taken from \pkg{doc}, stripped of comments and translated +% into \pkg{expl3} syntax. New features are added in various places. +% +% \begin{macro}{\StopEventually,\Finale,\AlsoImplementation,\OnlyDescription} +% \begin{macrocode} +\bool_new:N \g_doc_implementation_bool +\cs_set_nopar:Npn \AlsoImplementation { + \bool_set_true:N \g_doc_implementation_bool + \cs_set:Npn \StopEventually ##1 { + \@bsphack + \cs_gset_nopar:Npn \Finale { ##1 \check@checksum } + \init@checksum + \@esphack + } +} +\AlsoImplementation +\cs_set_nopar:Npn \OnlyDescription { + \@bsphack + \bool_set_false:N \g_doc_implementation_bool + \cs_set:Npn \StopEventually ##1 { ##1 \endinput } + \@esphack +} +\cs_set_eq:NN \Finale \relax +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\cs_set_nopar:Npn \partname{File} +% \end{macrocode} +% +% \begin{macro}{\DocInput} +% From \pkg{doc}. Now accepts comma-list input (who has commas in filenames?). +% \begin{macrocode} +\clist_new:N \g_docinput_clist +\cs_set:Npn \DocInput #1 { + \clist_map_inline:nn {#1} { + \clist_put_right:Nn \g_docinput_clist {##1} + \MakePercentIgnore + \input{##1} + \MakePercentComment + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DocInputAgain} +% Uses "\g_docinput_clist" to re-input whatever's already been "\DocInput"-ed until now. +% May be used multiple times. +% \begin{macrocode} +\cs_set:Npn \DocInputAgain { + \clist_map_inline:Nn \g_docinput_clist { + \MakePercentIgnore + \input{##1} + \MakePercentComment + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DocInclude} +% More or less exactly the same as |\include|, but uses |\DocInput| +% on a |dtx| file, not |\input| on a |tex| file. +% \begin{macrocode} +\cs_set_nopar:Npn \partname{File} +% \end{macrocode} +% +% \begin{macrocode} +\newcommand*{\DocInclude}[1]{% + \relax\clearpage + \docincludeaux + \IfFileExists{#1.fdd}{ + \cs_set_nopar:Npn \currentfile{#1.fdd} + }{ + \cs_set_nopar:Npn \currentfile{#1.dtx} + } + \ifnum\@auxout=\@partaux + \@latexerr{\string\include\space cannot~be~nested}\@eha + \else + \@docinclude #1 + \fi +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_nopar:Npn \@docinclude #1 { + \clearpage + \immediate\write\@mainaux{\string\@input{#1.aux}} + \@tempswatrue + \if@partsw + \@tempswafalse + \cs_set_nopar:Npx \@tempb{#1} + \@for\@tempa:=\@partlist\do{ + \ifx\@tempa\@tempb\@tempswatrue\fi + } + \fi + \if@tempswa + \cs_set_eq:NN \@auxout\@partaux + \immediate\openout\@partaux #1.aux + \immediate\write\@partaux{\relax} + \cs_set_eq:NN \@ltxdoc@PrintIndex\PrintIndex + \cs_set_eq:NN \PrintIndex\relax + \cs_set_eq:NN \@ltxdoc@PrintChanges\PrintChanges + \cs_set_eq:NN \PrintChanges\relax + \cs_set_eq:NN \@ltxdoc@theglossary\theglossary + \cs_set_eq:NN \@ltxdoc@endtheglossary\endtheglossary + \part{\currentfile} + { + \cs_set_eq:NN \ttfamily\relax + \cs_gset_nopar:Npx \filekey{\filekey, \thepart={\ttfamily\currentfile}} + } + \DocInput{\currentfile} + \cs_set_eq:NN \PrintIndex\@ltxdoc@PrintIndex + \cs_set_eq:NN \PrintChanges\@ltxdoc@PrintChanges + \cs_set_eq:NN \theglossary\@ltxdoc@theglossary + \cs_set_eq:NN \endtheglossary\@ltxdoc@endtheglossary + \clearpage + \@writeckpt{#1} + \immediate\closeout\@partaux + \else + \@nameuse{cp@#1} + \fi + \cs_set_eq:NN \@auxout\@mainaux +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_gset_nopar:Npn \codeline@wrindex #1 { + \immediate\write\@indexfile { + \string\indexentry{#1} + {\filesep\number\c@CodelineNo} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\cs_set_eq:NN \filesep \@empty +% \end{macrocode} +% +% \begin{macro}{\docincludeaux} +% \begin{macrocode} +\cs_set_nopar:Npn \docincludeaux { + \cs_set_nopar:Npn \thepart {\alphalph{part}} + \cs_set_nopar:Npn \filesep {\thepart-} + \cs_set_eq:NN \filekey\@gobble + \g@addto@macro\index@prologue{ + \cs_gset_nopar:Npn\@oddfoot{ + \parbox{\textwidth}{ + \strut\footnotesize + \raggedright{\bfseries File~Key:}~\filekey + } + } + \cs_set_eq:NN \@evenfoot\@oddfoot + } + \cs_gset_eq:NN \docincludeaux\relax + \cs_gset_nopar:Npn\@oddfoot{ + \expandafter\ifx\csname ver@\currentfile\endcsname\relax + File~\thepart :~{\ttfamily\currentfile}~ + \else + \GetFileInfo{\currentfile} + File~\thepart :~{\ttfamily\filename}~ + Date:~\filedate\ % space + Version~\fileversion + \fi + \hfill\thepage + } + \cs_set_eq:NN \@evenfoot \@oddfoot +} +% \end{macrocode} +% \end{macro} +% +% \subsection{At end document} +% +% Print all defined and documented macros/functions. +% +% \begin{macrocode} +\seq_new:N \g_doc_functions_seq +\seq_new:N \g_doc_macros_seq +% \end{macrocode} +% +% \begin{macrocode} +\iow_new:N \g_write_func_stream +\iow_open:Nn \g_write_func_stream { \jobname.cmds } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_nopar:Npn \doc_show_functions_defined: { + \bool_if:nT { \g_doc_implementation_bool && \g_doc_checkfunc_bool } { + \typeout{ ======================================== ^^J } + + \tl_clear:N \l_tmpa_tl + \seq_map_inline:Nn \g_doc_functions_seq { + \seq_if_in:NnT \g_doc_macros_seq {##1} { + \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J } + \iow_now:Nn \g_write_func_stream { ##1 } + } + } + \iow_close:N \g_write_func_stream + \doc_functions_typeout:n { + Functions~both~documented~and~defined:^^J (In~order~of~being~documented) + } + + \seq_map_inline:Nn \g_doc_functions_seq { + \seq_if_in:NnF \g_doc_macros_seq {##1} { + \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J } + } + } + \doc_functions_typeout:n { Functions~documented~but~not~defined: } + + \seq_map_inline:Nn \g_doc_macros_seq { + \seq_if_in:NnF \g_doc_functions_seq {##1} { + \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J } + } + } + \doc_functions_typeout:n { Functions~defined~but~not~documented: } + + \typeout{ ======================================== } + } +} +\AtEndDocument{ \doc_show_functions_defined: } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set_nopar:Npn \doc_functions_typeout:n #1 { + \tl_if_empty:NF \l_tmpa_tl { + \typeout{ + -------------------------------------- ^^J #1 ^^J + -------------------------------------- ^^J \l_tmpa_tl + } + \tl_clear:N \l_tmpa_tl + } +} +% \end{macrocode} +% +% \subsection{Indexing} +% +% Fix index (for now): +% \begin{macrocode} +\g@addto@macro\theindex{\MakePrivateLetters} +% \end{macrocode} +% +% \begin{macrocode} +\setcounter{IndexColumns}{2} +% \end{macrocode} +% +% Set up the Index to use "\part" +% \begin{macrocode} +\IndexPrologue{ + \part*{Index} + \markboth{Index}{Index} + \addcontentsline{toc}{part}{Index} + The~italic~numbers~denote~the~pages~where~the~ + corresponding~entry~is~described,~ + numbers~underlined~point~to~the~definition,~ + all~others~indicate~the~places~where~it~is~used. +} +% \end{macrocode} +% +% +% \begin{macro}{\doc_special_main_index:n,\doc_special_main_index:o,\hdpgindex} +% Heiko's replacement to play nicely with |hypdoc|: +% \begin{macrocode} +\cs_set_nopar:Npn \doc_special_main_index:n #1 { + \index{ + \@gobble#1 + \actualchar + \string\verb\quotechar*\verbatimchar#1\verbatimchar + \encapchar + hdpgindex{\thepage}{usage} + } +} +\cs_set_nopar:Npn \doc_special_main_index:o { \exp_args:No \doc_special_main_index:n } +% \end{macrocode} +% \begin{macrocode} +\cs_set_nopar:Npn \hdpgindex #1#2#3 { + \csname\ifx\\#2\\relax\else#2\fi\endcsname{ + \hyperlink{page.#1}{#3} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\g@addto@macro \PrintIndex { \AtEndDocument{ \typeout{^^J + ========================================^^J + Generate~the~index~by~executing^^J + \msg_four_spaces: makeindex~-s~l3doc.ist~-o~\jobname.ind~\jobname.idx^^J + ========================================^^J + }} +} +% \end{macrocode} +% +% \subsection{Change history} +% +% Set the change history to use "\part". +% Allow control names to be hyphenated in here... +% \begin{macrocode} +\GlossaryPrologue{ + \part*{Change~History} + {\GlossaryParms\ttfamily\hyphenchar\font=`\-} + \markboth{Change~History}{Change~History} + \addcontentsline{toc}{part}{Change~History} +} +% \end{macrocode} +% +% \begin{macrocode} +\g@addto@macro \PrintChanges { \AtEndDocument{ \typeout{^^J + ========================================^^J + Generate~the~change~list~by~executing^^J + \msg_four_spaces: makeindex~-s~gglo.ist~~-o~\jobname.gls~\jobname.glo^^J + ========================================^^J + }} +} +% \end{macrocode} +% +%^^A The standard \changes command modified slightly to better cope with +%^^A this multiple file document. +%^^A\def\changes@#1#2#3{% +%^^A \let\protect\@unexpandable@protect +%^^A \edef\@tempa{\noexpand\glossary{#2\space\currentfile\space#1\levelchar +%^^A \ifx\saved@macroname\@empty +%^^A \space +%^^A \actualchar +%^^A \generalname +%^^A \else +%^^A \expandafter\@gobble +%^^A \saved@macroname +%^^A \actualchar +%^^A \string\verb\quotechar*% +%^^A \verbatimchar\saved@macroname +%^^A \verbatimchar +%^^A \fi +%^^A :\levelchar #3}}% +%^^A \@tempa\endgroup\@esphack} +% +% \subsection{Patch file} +% +% Will: Do we still need this? +% +% \begin{macro}{\includeltpatch} +% This command will be used to input the patch file +% if that file exists. +% \begin{macrocode} +\cs_new_nopar:Npn \includeltpatch { + \cs_set_nopar:Npn \currentfile {l3patch.ltx} + \part{l3patch} + {\cs_set_eq:NN \ttfamily\relax + \cs_gset_nopar:Npx \filekey{\filekey, \thepart={\ttfamily\currentfile}}} + Things~we~did~wrong\ldots + \IndexInput{l3patch.ltx}} +% \end{macrocode} +% Get the date from ltvers.dtx +% \begin{macrocode} +\cs_set_nopar:Npn \patchdate{0} +\begingroup + %%\cs_set_nopar:Npn \ProvidesFile#1\fmtversion#2{\date{#2}\endinput} + \cs_set_nopar:Npn \ProvidesFile#1[#2#3]{\date{#2}\endinput} + \input{l3vers.dtx} + \cs_gset_nopar:Npx \@date{\@date} + \cs_gset_eq:NN \X@date \@date +% Add the patch version if available. + \cs_set:Npn \Xdef#1#2#3\def#4#5 { + \cs_gset_nopar:Npx \X@date{#2} + \cs_gset_nopar:Npx \patchdate{#5} + \endinput + } + \InputIfFileExists{l3patch.ltx}{ + \cs_set_eq:NN \cs_set_nopar:Npn \Xdef + }{ + \cs_gset_eq:NN \includeltpatch \relax + } +\endgroup +\ifx\@date\X@date + \cs_set_nopar:Npn \Xpatch{0} + \ifx\patchdate\Xpatch\else + \cs_set_nopar:Npx \@date {\@date\space Patch level \patchdate} + \fi +\else + \@warning{l3patch.ltx does not match l3vers.dtx!} + \cs_set_eq:NN \includeltpatch \relax +\fi +% \end{macrocode} +% \end{macro} +% +% \subsection{cfg} +% +% \begin{macrocode} +\bool_if:NTF \g_doc_full_bool { + \RecordChanges + \CodelineIndex + \EnableCrossrefs + \AlsoImplementation +}{ + \CodelineNumbered + \DisableCrossrefs + \OnlyDescription +} +% \end{macrocode} +% +% Input a local configuration file, if it exists. +% \begin{macrocode} +\InputIfFileExists{l3doc.cfg}{ + \typeout{*************************************^^J + *~Local~config~file~l3doc.cfg~used ^^J + *************************************} +}{} +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% \subsection{Makeindex configuration} +% +% The makeindex style "l3doc.ist" is used in place of the usual +% "gind.ist" to ensure that I is used in the sequence I J K +% not I II II, which would be the default makeindex behaviour. +% +% Will: Do we need this? +% +% \begin{macrocode} +%<*docist> +actual '=' +quote '!' +level '>' +preamble +"\n \\begin{theindex} \n \\makeatletter\\scan@allowedfalse\n" +postamble +"\n\n \\end{theindex}\n" +item_x1 "\\efill \n \\subitem " +item_x2 "\\efill \n \\subsubitem " +delim_0 "\\pfill " +delim_1 "\\pfill " +delim_2 "\\pfill " +% The next lines will produce some warnings when +% running Makeindex as they try to cover two different +% versions of the program: +lethead_prefix "{\\bfseries\\hfil " +lethead_suffix "\\hfil}\\nopagebreak\n" +lethead_flag 1 +heading_prefix "{\\bfseries\\hfil " +heading_suffix "\\hfil}\\nopagebreak\n" +headings_flag 1 + +% and just for source3: +% Remove R so I is treated in sequence I J K not I II III +page_precedence "rnaA" +% +% \end{macrocode} +% +% \section{Testing} +%\ExplSyntaxOn +%\cs_set_eq:NN\g_saved_doc_functions_seq\g_doc_functions_seq +%\cs_set_eq:NN\g_saved_doc_macros_seq\g_doc_macros_seq +%\ExplSyntaxOff +% +% \begin{function}{\example_foo:N|\example_foo:c} +% \begin{syntax} +% "\example_foo:N" +% \end{syntax} +% <0123456789> <\0\1\2\3\4\5\6\7\8\9> \Arg{arg1} ":(" +% \end{function} +% +% \begin{function}{ \foo | \foo: | \foo:x | \barrz: } +% \begin{syntax} +% "\example_foo:N" +% \end{syntax} +% <0123456789> <\0\1\2\3\4\5\6\7\8\9> +% \end{function} +% +% \begin{function}{\foo:N / (TF) | \foo_if:c / (TF) (EXP)} +% Test. +% \end{function} +% +% \begin{function}{ \bar / (EXP) | \bar: / (EXP) | \bar:x / (EXP) | } +% \begin{syntax} +% "\example_foo:N" +% \end{syntax} +% <0123456789> <\0\1\2\3\4\5\6\7\8\9> +% \end{function} +% +% \begin{macro}{ \foo , \foo: , \foo:x } +% Testing. +% \end{macro} +% +% \bigskip\bigskip +% +% \begin{macro}[aux]{ \foo_aux: } +% Testing. +% \end{macro} +% +% \bigskip\bigskip +% +% \begin{macro}[TF]{ \foo_if:c } +% Testing. +% \end{macro} +% +%\ExplSyntaxOn +%\cs_set_eq:NN\g_doc_functions_seq\g_saved_doc_functions_seq +%\cs_set_eq:NN\g_doc_macros_seq\g_saved_doc_macros_seq +%\ExplSyntaxOff +% +% \bigskip\bigskip +% +% \begin{macro}{\c_minus_one} +% \begin{macro}{\c_zero} +% \begin{macro}{\c_one} +% \begin{macro}{\c_two} +% \begin{macro}{\c_three} +% \begin{macro}{\c_four} +% \begin{macro}{\c_five} +% \begin{macro}{\c_six} +% \begin{macro}{\c_seven} +% \begin{macro}{\c_eight} +% \begin{macro}{\c_nine} +% \begin{macro}{\c_ten} +% \begin{macro}{\c_eleven} +% \begin{macro}{\c_sixteen} +% \begin{macro}{\c_thirty_two} +% \begin{macro}{\c_hundred_one} +% \begin{macro}{\c_twohundred_fifty_five} +% \begin{macro}{\c_twohundred_fifty_six} +% \begin{macro}{\c_thousand} +% \begin{macro}{\c_ten_thousand} +% \begin{macro}{\c_ten_thousand_one} +% \begin{arguments} +% \item name +% \item parameters +% \end{arguments} +% Another test. +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Macros} +% \raggedright +% \ExplSyntaxOn +% \seq_map_inline:Nn \g_doc_macros_seq { `\texttt{#1}' \quad } +% \ExplSyntaxOff +% +% \subsection{Functions} +% \ExplSyntaxOn +% \seq_map_inline:Nn \g_doc_functions_seq { `\texttt{#1}' \quad } +% \ExplSyntaxOff +% +% \end{implementation} +% +% \PrintIndex +% +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3expan.dtx b/Master/texmf-dist/source/latex/expl3/l3expan.dtx index 1efadb1dab3..7f2323b2e0c 100644 --- a/Master/texmf-dist/source/latex/expl3/l3expan.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3expan.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3expan.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3expan.dtx Copyright (C) 1990-2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3expan.dtx 735 2008-01-14 22:31:02Z morten $ +\GetIdInfo$Id: l3expan.dtx 1376 2009-06-01 17:01:30Z morten $ {L3 Experimental Argument Expansion module} %\iffalse %<*driver> @@ -44,153 +44,37 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3expan.dtx} \end{document} % % \fi % % -% \title{The \textsf{l3expan} package\thanks{This file +% \title{The \pkg{l3expan} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ -% Controlling Expansion of Command Arguments} +% Controlling Expansion of Function Arguments} % \author{\Team} % \date{\filedate} % \maketitle % +% \begin{documentation} % -% \section{\LaTeX3 functions} +% \section{Brief overview} % -% All \LaTeX3 functions contain a colon in their -% name. Characters following the colon are used to denote the number and -% the ``type'' of arguments that the function takes. An uppercase "N" is -% used to denote an argument that consists of a single token and a -% lowercase "n" is used when the argument can consist of several tokens -% surrounded by braces. In case of "n" arguments that consist of a -% single token the surrounding braces can be omitted in nearly all -% situations---functions that force the use of braces even for single -% token arguments are explicitly mentioned. For example, "\seq_gpush:Nn" -% is a function that takes two arguments, the first is a single token -% (the sequence) and the second may consist of several tokens surrounded -% by braces. +% The functions in this module all have prefix |exp|. % -% This concept of argument specification makes it easy to read the code -% and should be followed when defining new functions. -% -% \subsection{Expanding arguments of functions} -% -% Within code it is often necessary to expand or partially expand -% arguments before passing it on to some function. For example, if the -% token list pointer "\l_tmpa_tlp" contains the current file -% that should be pushed onto some stack, we can not write -% \begin{quote} -% "\seq_gpush:Nn" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} -% since this would put the token "\l_tmpa_tlp" and not its -% contents on the stack. Instead a suitable number of "\exp_after:NN" -% would be necessary (together with extra braces) to change the order of -% execution, i.e. -% \begin{quote} -% "\exp_after:NN" \\ -% " \seq_gpush:Nn" \\ -% "\exp_after:NN" \\ -% " \g_file_name_stack" \\ -% "\exp_after:NN" \\ -% " {\l_tmpa_tlp}" -% \end{quote} -% -% The above example is probably the simplest case but is already shows -% how the code changes to something difficult to understand. Therefore -% \LaTeX3 provides the programmer with a general scheme that keeps the -% code compact and easy to understand. -% To denote that some argument to a function needs special treatment one -% just uses different letters in the argument part of the function to -% mark the desired behavior. In the above example one would write -% \begin{quote} -% "\seq_gpush:No" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} -% to achieve the desired effect. Here the "o" stands for expand this -% (the second) argument once before passing it to the function. -% -% The following letters can be used to denote special treatment of -% arguments before passing it to the basic function: -% \begin{description} -% \item[o] One time expanded token or token-list. In the latter case, -% effectively only the first token in the list gets expanded. Since -% the expansion might result in more than one token, the result is -% surrounded for further processing with braces. -% -% \item[x] Fully expanded token or token-list. Like "o" but the -% argument is expanded using "\def:Npx" before it is passed on. This means -% that expansion takes place until only unexpandable tokens are left. -% -% \item[f] Almost the same as the |x| type except here the token list -% is expanded fully until the first unexpandable token is found and -% the rest is left unchanged. Note that if this function finds a -% space at the beginning of the argument it will gobble it and not -% expand the next argument. -% -% \item[N,O,X] Like "n", "o", "x" but the argument must be a single -% token without any braces around it. -% -% \item[c] A character string or a token-list that ultimately expands -% to characters. This string (after expansion) is used to construct a -% command name that is eventually passed on. -% -% \item[C] A character string or a token-list that ultimately expands -% to characters. From this string (after expansion) a command name is -% constructed and then this command name is expanded once (like "o"). -% The result of this is eventually passed on. In other words -% \begin{quote} -% "\seq_gpush:NC" \\ -% " \g_file_name_stack" \\ -% " {l_tmpa_tlp}" -% \end{quote} -% Has the same effect as the example above. -% -% -% \end{description} -% -% Here are three new expansion types that may be useful but I'm not -% sure yet. Only time will tell\dots{} Proper documentation of these -% functions is postponed until later. -% \begin{description} -% \item[d] This is pretty much like the |o| type except the token list -% get's expanded twice before being passed on. (|d| is for double.) -% It is often useful in conjunction with a forced expansion. -% -% \item[E] Sometimes you need to unpack a token list or something else -% but you don't want it to add the braces that the |o| type -% does. This is where you usually wind up with a lot of -% |\exp_after:NN|s and we would like to avoid that. This type works -% quite well with the other syntax but it won't work in certain -% circumstances: Since the generic expansion functions read their -% arguments when the expanded code is shuffled around, this type -% will have a problem if the last token you want to expand once is -% |\token_to_str:N| \emph{and} you're in an argument expansion -% process involving arguments in braces such as the |n| and |o| type -% arguments. If you stick to functions invloving only |N| and |E| -% everything will work just fine. (|E| is for expanded, single -% token.) -% -% \item[e] Same as above but the argument must be given in braces. -% \end{description} -% -% Due to memory constraints not all possible variations are implemented -% for every base function. Instead only those that are used within the -% \LaTeX3 kernel or otherwise seem to be of general interest are -% implemented. +% Not all possible variations are implemented for every base +% function. Instead only those that are used within the \LaTeX3 kernel +% or otherwise seem to be of general interest are implemented. % Consult the module description to find out which functions are % actually defined. The next section explains how to define missing % variants. +% % -% \subsection{Defining new variants} +% \section{Defining new variants} % % The definition of variant forms for base functions may be necessary % when writing new functions or when applying a kernel function in a @@ -202,11 +86,11 @@ % second are a single tokens the third argument gets % expanded once. If "\seq_gpush:No" wouldn't be defined the example % above could be coded in the following way: -% \begin{quote} -% "\exp_args:NNo\seq_gpush:Nn" \\ -% " \g_file_name_stack" \\ -% " \l_tmpa_tlp" -% \end{quote} +% \begin{verbatim} +% \exp_args:NNo\seq_gpush:Nn +% \g_file_name_stack +% \l_tmpa_tl +% \end{verbatim} % In other words, the first argument to "\exp_args:NNo" is the base % function and the other arguments are preprocessed and then passed to % this base function. In the example the first argument to the base @@ -215,85 +99,132 @@ % how the variants are defined. They just expand into the appropriate % "\exp_" function followed by the desired base function, e.g. % \begin{quote} -% "\def_new:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}" +% "\cs_new_nopar:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}" % \end{quote} % Providing variants in this way in style files is uncritical as the -% "\def_new:Npn" function will silently accept definitions whenever the +% "\cs_new_nopar:Npn" function will silently accept definitions whenever the % new definition is identical to an already given one. Therefore adding % such definition to later releases of the kernel will not make such % style files obsolete. % -% The |f| type is so special that it deserves an example. -% Let's pretend we want to set "\aaa" equal to the control sequence -% stemming from turning "b \l_tmpa_tlp b" into a control -% sequence. Furthermore we want to store the execution of it in a -% \m{toks} register. In this example we assume "\l_tmpa_tlp" contains -% the text string "lur". The straight forward approach is -% \begin{quote} -% "\toks_set:No \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" -% \end{quote} -% Unfortunately this only puts -% "\exp_args:NNc \let:NN \aaa {b \l_tmpa_tlp b}" into "\l_tmpa_toks" -% and not "\let:NwN \aaa = \blurb" as we probably wanted. Using -% "\toks_set:Nx" is not an option as that will die horribly. Instead -% we can do a -% \begin{quote} -% "\toks_set:Nf \l_tmpa_toks {\let:Nc \aaa {b \l_tmpa_tlp b}}" -% \end{quote} -% which puts the desired result in "\l_tmpa_toks". It requires -% "\toks_set:Nf" to be defined as -% \begin{quote} -% "\def:Npn \toks_set:Nf {\exp_args:NNf \toks_set:Nn}" -% \end{quote} -% If you use this type of expansion in conditional processing then -% you should stick to using "TF" type functions only as it does not -% try to finish any "\if... \fi:" itself! -% -% -% -% -% -% The available internal functions for argument expansion come in to +% The steps above may be automated by using the function +% "\cs_generate_variant:Nn", described next. +% +% \subsection{Methods for defining variants} +% +% \begin{function}{\cs_generate_variant:Nn} +% \begin{syntax} +% "\cs_generate_variant:Nn" +% "\cs_generate_variant:Nn " "\foo:Nn" "{c}" +% "\cs_generate_variant:Nn" "\foo:Nn" "{c,Nx,cx}" +% \end{syntax} +% This function greatly simplify the task of defining +% variantions on a base function with differing expansion control. +% The first example is equivalent to writing +% \begin{verbatim} +% \cs_set_nopar:Npn \foo:cn { \exp_args:Nc \foo:Nn } +% \end{verbatim} +% If used with a comma-separated list of variants, it does so for each +% variant form, i.e., the second example is equivalent to +% \begin{verbatim} +% \cs_set_nopar:Npn \foo:cn { \exp_args:Nc \foo:Nn } +% \cs_set_nopar:Npn \foo:Nx { \exp_args:NNx \foo:Nn } +% \cs_set_nopar:Npn \foo:cx { \exp_args:Ncx \foo:Nn } +% \end{verbatim} +% \end{function} +% +% \paragraph{Internal functions} \mbox{} +% +% \begin{function}{\cs_generate_internal_variant:n} +% \begin{syntax} +% "\cs_generate_internal_variant:n" \Arg{args} +% \end{syntax} +% Defines the appropriate "\exp_args:N" function, if necessary, +% to perform the expansion control specified by . +% \end{function} +% +% \section{Introducing the variants} +% +% The available internal functions for argument expansion come in two % flavours, some of them are faster then others. Therefore it is usually % best to follow the following guidelines when defining new functions % that are supposed to come with variant forms: % \begin{itemize} % \item % Arguments that might need expansion should come first in the list of -% arguments to make processing faster. +% arguments to make processing faster. % \item % Arguments that should consist of single tokens should come first. % \item % Arguments that need full expansion (i.e., are denoted with "x") -% should be avoided if possible as they can not be processed very fast. +% should be avoided if possible as they can not be processed very fast. % \item % In general "n", "x", and "o" (if not in the last position) will % need special processing which is not fast and not expandable, % i.e., functions of this type may not work correctly in arguments % that are itself subject to "x" expansion. Therefore it is best to % use the ``expandable'' functions (i.e., those that contain only -% "c", "N", "O", "o" or "f" in the last position) whenever possible. +% "c", "N", "o" or "f" in the last position) whenever possible. % \end{itemize} % +% The |V| type returns the value of a register, which can be one of +% |tl|, |num|, |int|, |skip|, |dim|, |toks|, or built-in \TeX\ +% registers. The |v| type is the same except it first creates a +% control sequence out of its argument before returning the +% value. This recent addition to the argument specifiers may shake +% things up a bit as most places where |o| is used will be replaced by +% |V|. The documentation you are currently reading will therefore +% require a fair bit of re-writing. +% +% In general, the programmer should not need to be concerned with +% expansion control. When simply using the content of a variable, +% functions with a "V" specifier should be used. For those referred to by +% (cs)name, the "v" specifier is available for the same purpose. Only when +% specific expansion steps are needed, such as when using delimited +% arguments, should the lower-level functions with "o" specifiers be employed. +% +% The |f| type is so special that it deserves an example. +% Let's pretend we want to set "\aaa" equal to the control sequence +% stemming from turning "b \l_tmpa_tl b" into a control +% sequence. Furthermore we want to store the execution of it in a +% \m{toks} register. In this example we assume "\l_tmpa_tl" contains +% the text string "lur". The straight forward approach is +% \begin{quote} +% "\toks_set:No \l_tmpa_toks {\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}}" +% \end{quote} +% Unfortunately this only puts +% "\exp_args:NNc \cs_set_eq:NN \aaa {b \l_tmpa_tl b}" into "\l_tmpa_toks" +% and not "\cs_set_eq:NwN \aaa = \blurb" as we probably wanted. Using +% "\toks_set:Nx" is not an option as that will die horribly. Instead +% we can do a +% \begin{quote} +% "\toks_set:Nf \l_tmpa_toks {\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}}" +% \end{quote} +% which puts the desired result in "\l_tmpa_toks". It requires +% "\toks_set:Nf" to be defined as +% \begin{quote} +% "\cs_set_nopar:Npn \toks_set:Nf {\exp_args:NNf \toks_set:Nn}" +% \end{quote} +% If you use this type of expansion in conditional processing then +% you should stick to using "TF" type functions only as it does not +% try to finish any "\if... \fi:" itself! +% % % When pdf\TeX\ 1.50 arrives, it will contain a primitive for % performing the equivalent of an "x" expansion after only one % expansion and most importantly: as an expandable operation. -% \begin{function}{% -% \exp_arg:x -% } +% \begin{function}{\exp_arg:x} % \begin{syntax} -% " \exp_arg:x" "{" "}" +% "\exp_arg:x" \Arg{arg} % \end{syntax} % is expanded fully using an "x" expansion. % \end{function} % % -% \subsection{Manipulating the first argument} % -% \begin{function}{% -% \exp_args:No -% } +% \section{Manipulating the first argument} +% +% \begin{function}{ \exp_args:No / (EXP) } % \begin{syntax} % " \exp_args:No" "..." % \end{syntax} @@ -302,9 +233,16 @@ % more than one argument---all others are passed unchanged. % \end{function} % -% \begin{function}{% -% \exp_args:Nc -% } +% \begin{function}{ \exp_args:Nd / (EXP) } +% \begin{syntax} +% " \exp_args:Nd" "..." +% \end{syntax} +% The first argument of (i.e., ) is expanded twice, the +% result is surrounded by braces and passed to . may have +% more than one argument---all others are passed unchanged. +% \end{function} +% +% \begin{function}{ \exp_args:Nc / (EXP) | \exp_args:cc / (EXP) } % \begin{syntax} % " \exp_args:Nc" "..." % \end{syntax} @@ -313,25 +251,32 @@ % result of this expansion.) Then the result is turned into a control % sequence and passed to as the first argument. may have % more than one argument---all others are passed unchanged. +% +% In the ":cc" variant, the control sequence itself is constructed +% (with the same process as described above) before is turned into a +% control sequence and passed as its argument. % \end{function} % -% \begin{function}{% -% \exp_args:NC -% } +% \begin{function}{ \exp_args:NV / (EXP) } % \begin{syntax} -% " \exp_args:Nc" "..." +% " \exp_args:NV" % \end{syntax} -% The first argument of (i.e., ) is expanded until only -% characters remain. (An internal error occurs if something else is the -% result of this expansion.) Then the result is turned into a control -% sequence which is then expanded once more. The result of this is then -% passed to as the first argument. may have more than -% one argument---all others are passed unchanged. +% The first argument of (i.e., ) is expanded to its +% value. By value we mean a number stored in an |int| or |num| +% register, the length value of a |dim|, |skip| or |muskip| register, the +% contents of a |toks| register or the unexpanded contents of a |tl var.| +% register. The value is passed onto in braces. % \end{function} % -% \begin{function}{% -% \exp_args:Nx -% } +% \begin{function}{ \exp_args:Nv / (EXP) } +% \begin{syntax} +% " \exp_args:Nv" \Arg{register} +% \end{syntax} +% Like the |V| type except the register is given by a list of +% characters from which a control sequence name is generated. +% \end{function} +% +% \begin{function}{ \exp_args:Nx } % \begin{syntax} % " \exp_args:Nx" "..." % \end{syntax} @@ -342,9 +287,7 @@ % As mentioned before, this type of function is relatively slow. % \end{function} % -% \begin{function}{% -% \exp_args:Nf -% } +% \begin{function}{ \exp_args:Nf / (EXP) } % \begin{syntax} % " \exp_args:Nf" "..." % \end{syntax} @@ -355,8 +298,7 @@ % Beware of its special behavior as explained above. % \end{function} % -% -% \subsection{Manipulating two arguments} +% \section{Manipulating two arguments} % % \begin{function}{% % \exp_args:NNx | @@ -374,16 +316,22 @@ % \end{function} % % \begin{function}{% -% \exp_args:NNo | -% \exp_args:NNf | -% \exp_args:Nno | -% \exp_args:NNc | -% \exp_args:Noo | -% \exp_args:NOo | -% \exp_args:NOc | -% \exp_args:Nco | -% \exp_args:Ncc | -% \exp_args:NNC | +% \exp_args:NNo / (EXP) | +% \exp_args:NNc / (EXP) | +% \exp_args:NNv / (EXP) | +% \exp_args:NNV / (EXP) | +% \exp_args:NNd / (EXP) | +% \exp_args:NNf / (EXP) | +% \exp_args:Nno / (EXP) | +% \exp_args:Nnf / (EXP) | +% \exp_args:Noo / (EXP) | +% \exp_args:Noc / (EXP) | +% \exp_args:Nco / (EXP) | +% \exp_args:Ncf / (EXP) | +% \exp_args:Ncc / (EXP) | +% \exp_args:Nff / (EXP) | +% \exp_args:Nfo / (EXP) | +% \exp_args:NVV / (EXP) | % } % \begin{syntax} % "\exp_args:NNo" "..." @@ -391,17 +339,20 @@ % These are the fast and expandable functions for the first two arguments. % \end{function} % -% \subsection{Manipulating three arguments} +% \section{Manipulating three arguments} % % So far not all possible functions are provided and even the selection % below may be reduced in the future as far as the non-expandable % functions are concerned. % % \begin{function}{% +% \exp_args:NNnx | +% \exp_args:NNox | % \exp_args:Nnnx | -% \exp_args:Noox | % \exp_args:Nnox | +% \exp_args:Noox | % \exp_args:Ncnx | +% \exp_args:Nccx | % } % \begin{syntax} % "\exp_args:Nnnx" "..." @@ -410,44 +361,32 @@ % \end{function} % % \begin{function}{% -% \exp_args:NnnN | -% \exp_args:Nnno | -% \exp_args:NNOo | -% \exp_args:NOOo | -% \exp_args:Nccc | -% \exp_args:NcNc | -% \exp_args:Nnnc | -% \exp_args:NcNo | -% \exp_args:Ncco | +% \exp_args:NNNo / (EXP) | +% \exp_args:NNoo / (EXP) | +% \exp_args:NNno / (EXP) | +% \exp_args:Nnno / (EXP) | +% \exp_args:Nnnc / (EXP) | +% \exp_args:Nooo / (EXP) | +% \exp_args:Nccc / (EXP) | +% \exp_args:NcNc / (EXP) | +% \exp_args:NcNo / (EXP) | +% \exp_args:Ncco / (EXP) | % } % \begin{syntax} -% "\exp_args:NNOo" "..." +% "\exp_args:NNoo" "..." % \end{syntax} % These are the fast and expandable functions for the first three % arguments. % \end{function} % -% \subsection{Internal functions and variables} -% -% \begin{function}{\exp_after:NN} -% \begin{syntax} -% "\exp_after:NN" -% \end{syntax} -% This will expand once before processing . This is -% similar to "\exp_args:No" except that no braces are put around the -% result of expanding . -% \begin{texnote} -% This is the primitive \tn{expandafter} which was renamed to fit into -% the naming conventions of \LaTeX3. -% \end{texnote} -% \end{function} +% \section{Preventing expansion} % % \begin{function}{\exp_not:N | % \exp_not:c | % \exp_not:n } % \begin{syntax} % "\exp_not:N" -% "\exp_not:n" "{" "}" +% "\exp_not:n" \Arg{token list} % \end{syntax} % This function will prohibit the expansion of in situation % where would otherwise be replaced by it definition, e.g., @@ -458,45 +397,40 @@ % \end{texnote} % \end{function} % -% % \begin{function}{\exp_not:o | % \exp_not:d | -% \exp_not:f} +% \exp_not:f } % \begin{syntax} -% "\exp_not:o" "{""}" +% "\exp_not:o" \Arg{token list} % \end{syntax} % Same as "\exp_not:n" except is expanded once for the % "o" type and twice for the "d" type and the result of this expansion -% is then prohibited from being expanded further. +% is then prohibited from being expanded further. % \end{function} -% -% \begin{function}{\exp_not:E} +% +% \begin{function}{\exp_not:V | +% \exp_not:v } % \begin{syntax} -% "\exp_not:E" +% "\exp_not:V" +% "\exp_not:v" \Arg{token list} % \end{syntax} -% The name of this command is a lie. Perhaps it should be called -% ``"exp_perhaps_once"''. What it actually does is, it expands -% and then issues an "\exp_not:N" to prohibit further expansion of the -% first token in the replacement text of . This means that if -% the replacement text of consists of more than one token all -% further tokens are still subject to full expansion. -% \begin{texnote} -% This command has no equivalent. -% \end{texnote} +% The value of is retrieved and then passed on to +% "\exp_not:n" which will prohibit further expansion. The |v| type +% first creates a control sequence from but is otherwise +% identical to |V|. % \end{function} -% % -% \begin{function}{\exp_stop_f: } +% \begin{function}{\exp_stop_f:} % \begin{syntax} % ... "\exp_stop_f:" % \end{syntax} % This function stops an "f" type expansion. An example use is one such as % \begin{verbatim} -% \tlp_set:Nf \l_tmpa_tlp { +% \tl_set:Nf \l_tmpa_tl { % \if_case:w \l_tmpa_int -% \or: \use_arg_i_after_orelse:nw{\exp_stop_f: \textbullet} -% \or: \use_arg_i_after_orelse:nw{\exp_stop_f: \textendash} -% \else: \use_arg_i_after_orelse:nw{\exp_stop_f: else-item} +% \or: \use_i_after_orelse:nw {\exp_stop_f: \textbullet} +% \or: \use_i_after_orelse:nw {\exp_stop_f: \textendash} +% \else: \use_i_after_fi:nw {\exp_stop_f: else-item} % \fi: % } % \end{verbatim} @@ -508,46 +442,122 @@ % writing code. % \end{texnote} % \end{function} +% +% \section{Unbraced expansion} +% +% \begin{function}{ +% \exp_last_unbraced:Nf| +% \exp_last_unbraced:NV| +% \exp_last_unbraced:Nv| +% \exp_last_unbraced:NcV| +% \exp_last_unbraced:NNo| +% \exp_last_unbraced:NNV| +% \exp_last_unbraced:NNNo| +% } +% \begin{syntax} +% "\exp_last_unbraced:NV" +% \end{syntax} +% There are a small number of occasions where the last argument +% in an expansion run must be expanded unbraced. These functions +% should only be used inside functions, \emph{not} for creating +% variants. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} % +% \section{\pkg{l3expan} implementation} % -% \begin{variable}{\l_exp_tlp | } +% \subsection{Internal functions and variables} +% +% \begin{function}{\exp_after:wN} +% \begin{syntax} +% "\exp_after:wN" +% \end{syntax} +% This will expand once before processing . This is +% similar to "\exp_args:No" except that no braces are put around the +% result of expanding . +% \begin{texnote} +% This is the primitive \tn{expandafter} which was renamed to fit into +% the naming conventions of \LaTeX3. +% \end{texnote} +% \end{function} +% +% \begin{variable}{\l_exp_tl} % \begin{syntax}\end{syntax} % The "\exp_" module has its private variables to temporarily store % results of the argument expansion. This is done to avoid interference % with other functions using temporary variables. % \end{variable} % -% \StopEventually{} +% \begin{function}{ \exp_eval_register:N / (EXP) | +% \exp_eval_register:c / (EXP) } +% \begin{syntax} +% "\exp_eval_register:N" +% \end{syntax} +% These functions evaluates a register as part of a "V" or "v" expansion +% (respectively). A register might exist as +% one of two things: A parameter-less non-long, non-protected macro +% or a built-in \TeX\ register such as |\count|. +% \end{function} +% +% \begin{function}{\::n|\::N|\::c|\::o|\::f|\::x|\::v|\::V|\::d|\:::} +% \begin{syntax} +% "\cs_set_nopar:Npn \exp_args:Ncof {\::c\::o\::f\:::}" +% \end{syntax} +% Internal forms for the base expansion types. +% \end{function} % -% \subsection {The Implementation} +% \subsection{Module code} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3tlp} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % -% \subsubsection{General expansion} +% \begin{macro}{\exp_after:wN} +% \begin{macro}{\exp_not:N} +% \begin{macro}{\exp_not:n} +% These are defined in \pkg{l3basics}. +% \begin{macrocode} +%<*bootstrap> +\cs_set_eq:NwN \exp_after:wN \tex_expandafter:D +\cs_set_eq:NwN \exp_not:N \tex_noexpand:D +\cs_set_eq:NwN \exp_not:n \etex_unexpanded:D +% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{General expansion} % % In this section a general mechanism for defining functions to handle % argument handling is defined. These general expansion functions are % expandable unless |x| is used. (Any version of |x| is going to have -% to use one of the \LaTeX3\ names for |\def:Npx| at some point, and +% to use one of the \LaTeX3\ names for |\cs_set_nopar:Npx| at some point, and % so is never going to be expandable.\footnote{However, some % primitives have certain characteristics that means that their % arguments undergo an \texttt{x} type expansion but the primitive % is in fact still expandable. We shall make it very clear when such % a function is expandable.}) % -% In a later section some common cases are coded by a more direct -% method, typically using calls to |\exp_after:NN|. +% The definition of expansion functions with this technique happens +% in section~\ref{sec:gendef}. +% In section~\ref{sec:handtune} some common cases are coded by a more direct +% method for efficiency, typically using calls to |\exp_after:wN|. % -% \begin{macro}{\l_exp_tlp} -% We need a scratch token list pointer. +% \begin{macro}{\l_exp_tl} +% We need a scratch token list variable. +% We don't use "tl" methods so that \pkg{l3expan} can be loaded earlier. % \begin{macrocode} -\tlp_new:Nn\l_exp_tlp{} +\cs_new_nopar:Npn \l_exp_tl {} % \end{macrocode} % \end{macro} % @@ -555,20 +565,47 @@ % to perform the expansions. All macros are |long| as this turned out % to be desirable since the tokens undergoing expansion may be % arbitrary user input. -% \begin{macro}{\exp_arg_next:nnn} -% This is basically the same function as |\Dexp_arg_next:nnn|. +% +% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3| +% where |#1| holds the remaining argument manipulations to be performed, +% |\:::| serves as an end marker for the list of manipulations, |#2| +% is the carried over result of the previous expansion steps and |#3| is +% the argument about to be processed. +% +% \begin{macro}[aux]{\exp_arg_next:nnn} +% \begin{macro}[aux]{\exp_arg_next_nobrace:nnn} +% |#1| is the result of an expansion step, |#2| is the remaining +% argument manipulations and |#3| is the current result of the +% expansion chain. This auxilliary function moves |#1| back after +% |#3| in the input stream and checks if any expansion is left to +% be done by calling |#2|. In by far the most cases we will require +% to add a set of braces to the result of an argument manipulation +% so it is more effective to do it directly here. Actually, so far +% only the |c| of the final argument manipulation variants does not +% require a set of braces. % \begin{macrocode} -\def_long_new:Npn\exp_arg_next:nnn#1#2#3{ +\cs_new:Npn\exp_arg_next:nnn#1#2#3{ + #2\:::{#3{#1}} +} +\cs_new:Npn\exp_arg_next_nobrace:nnn#1#2#3{ #2\:::{#3#1} } % \end{macrocode} % \end{macro} +% \end{macro} +% +% \begin{macro}{\:::} +% The end marker is just another name for the identity function. +% \begin{macrocode} +\cs_new:Npn\:::#1{#1} +% \end{macrocode} +% \end{macro} % % \begin{macro}{\::n} % This function is used to skip an argument that doesn't need to % be expanded. % \begin{macrocode} -\def_long_new:Npn\::n#1\:::#2#3{ +\cs_new:Npn\::n#1\:::#2#3{ #1\:::{#2{#3}} } % \end{macrocode} @@ -577,9 +614,8 @@ % \begin{macro}{\::N} % This function is used to skip an argument that consists of a % single token and doesn't need to be expanded. -%^^A was \let_new:NN\::N\::n (changed to match \;N above. % \begin{macrocode} -\def_long_new:Npn\::N#1\:::#2#3{ +\cs_new:Npn\::N#1\:::#2#3{ #1\:::{#2#3} } % \end{macrocode} @@ -589,8 +625,8 @@ % This function is used to skip an argument that is turned into % as control sequence without expansion. % \begin{macrocode} -\def_long_new:Npn\::c#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn\cs:w #3\cs_end:{#1}{#2} +\cs_new:Npn\::c#1\:::#2#3{ + \exp_after:wN\exp_arg_next_nobrace:nnn\cs:w #3\cs_end:{#1}{#2} } % \end{macrocode} % \end{macro} @@ -598,8 +634,8 @@ % \begin{macro}{\::o} % This function is used to expand an argument once. % \begin{macrocode} -\def_long_new:Npn\::o#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn\exp_after:NN{\exp_after:NN{#3}}{#1}{#2} +\cs_new:Npn\::o#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn\exp_after:wN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} @@ -608,7 +644,7 @@ % \begin{macro}{\::f} % \begin{macro}{\exp_stop_f:} % This function is used to expand a token list until the first -% unexpandable token is found. The underlying "\int_to_roman:w -`0" +% unexpandable token is found. The underlying "\tex_romannumeral:D -`0" % expands everything in its way to find something terminating the % number and thereby expands the function in front of it. This % scanning procedure is terminated once the expansion hits @@ -616,459 +652,541 @@ % to mark such an end of expansion marker; in case the scanner hits % a number, this number also terminates the scanning and is left % untouched. In the example shown earlier the scanning was stopped -% once \TeX{} had fully expanded "\let:Nc \aaa {b \l_tmpa_tlp b}" -% into "\let:NwN \aaa = \blurb" which then turned out to contain -% the non-expandable token "\let:NwN". Since the expansion of -% "\int_to_roman:w -`0" is \m{null}, we wind up with a fully +% once \TeX{} had fully expanded "\cs_set_eq:Nc \aaa {b \l_tmpa_tl b}" +% into "\cs_set_eq:NwN \aaa = \blurb" which then turned out to contain +% the non-expandable token "\cs_set_eq:NwN". Since the expansion of +% "\tex_romannumeral:D -`0" is \m{null}, we wind up with a fully % expanded list, only \TeX{} has not tried to execute any of the % non-expandable tokens. This is what differentiates this function % from the "x" argument type. % \begin{macrocode} -\def_long_new:Npn\::f#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn - \exp_after:NN{\exp_after:NN{\int_to_roman:w -`0 #3}} +\cs_new:Npn\::f#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{\tex_romannumeral:D -`0 #3} {#1}{#2} } -\def_new:Npn \exp_stop_f: {~} +\cs_new_nopar:Npn \exp_stop_f: {~} % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\::x} +% \begin{macro}{\::x,\exp_arg:x} % This function is used to expand an argument fully. If the % pdf\TeX\ primitive "\expanded" is present, we use it. % \begin{macrocode} -\let_new:NN \exp_arg:x \expanded % Move eventually. +\cs_new_eq:NN \exp_arg:x \expanded % Move eventually. \cs_if_free:NTF\exp_arg:x{ - \def_long_new:Npn\::x#1\:::#2#3{ - % \tlp_set:Nx\l_exp_tlp{{{#3}}} - \def:Npx \l_exp_tlp{{{#3}}} - \exp_after:NN\exp_arg_next:nnn\l_exp_tlp{#1}{#2}} + \cs_new:Npn\::x#1\:::#2#3{ + \cs_set_nopar:Npx \l_exp_tl{{#3}} + \exp_after:wN\exp_arg_next:nnn\l_exp_tl{#1}{#2}} } { - \def_long_new:Npn\::x#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn - \exp_after:NN{\exp_arg:x{{#3}}}{#1}{#2} + \cs_new:Npn\::x#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{\exp_arg:x{{#3}}}{#1}{#2} } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\:::} -% Just another name for the identity function. +% +% \begin{macro}{\::v} +% \begin{macro}{\::V} +% These functions return the value of a register, i.e., one of +% |tl|, |num|, |int|, |skip|, |dim| and |muskip|. The |V| version +% expects a single token whereas |v| like |c| creates a csname from +% its argument given in braces and then evaluates it as if it was a +% |V|. The sequence |\tex_romannumeral:D -`0| sets off an |f| type +% expansion. The argument is returned in braces. % \begin{macrocode} -\def_long_new:Npn\:::#1{#1} +\cs_new:Npn \::V#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{ + \tex_romannumeral:D -`0 + \exp_eval_register:N #3 + } + {#1}{#2} +} +\cs_new:Npn \::v#1\:::#2#3{ + \exp_after:wN\exp_arg_next:nnn + \exp_after:wN{ + \tex_romannumeral:D -`0 + \exp_eval_register:c {#3} + } + {#1}{#2} +} % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\::C} -% This function creates a control sequence out of |#3| and expands -% that once before passing it on to |\exp_arg_next:nnn|. +% \begin{macro}{\exp_eval_register:N,\exp_eval_register:c} +% \begin{macro}{\exp_eval_error_msg:w} +% This function evaluates a register. Now a register might exist as +% one of two things: A parameter-less macro or a built-in \TeX\ +% register such as |\count|. For the \TeX\ registers we have to +% utilize a |\tex_the:D| whereas for the macros we merely have to +% expand them once. The trick is to find out when to use +% |\tex_the:D| and when not to. What we do here is try to find out +% whether the token will expand to something else when hit with +% |\exp_after:wN|. The technique is to compare the meaning of the +% register in question when it has been prefixed with |\exp_not:N| +% and the register itself. If it is a macro, the prefixed +% |\exp_not:N| will temporarily turn it into the primitive +% |\tex_relax:D|. % \begin{macrocode} -\def_long_new:Npn\::C#1\:::#2#3{ - \exp_after:NN\exp_C_aux:nnn\cs:w #3\cs_end:{#1}{#2}} +\cs_set_nopar:Npn \exp_eval_register:N #1{ + \exp_after:wN \if_meaning:w \exp_not:N #1#1 % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\exp_C_aux:nnn} -% A helper function for |\::C| wich expands its argument before -% passing it on to |\exp_arg_next:nnn|. +% If the token was not a macro it may be a malformed variable from a +% |c| expansion in which case it is equal to the primitive +% |\tex_relax:D|. In that case we throw an error. We could let \TeX\ +% do it for us but that would result in the rather obscure +% \begin{quote} +% |! You can't use `\relax' after \the.| +% \end{quote} +% which while quite true doesn't give many hints as to what actually +% went wrong. We provide something more sensible. +% \begin{macrocode} + \if_meaning:w \tex_relax:D #1 + \exp_eval_error_msg:w + \fi: +% \end{macrocode} +% The next bit requires some explanation. The function must be +% initiated by the sequence |\tex_romannumeral:D -`0| and we want to +% terminate this expansion chain by inserting an |\exp_stop_f:| +% token. However, we have to expand the register |#1| before we do +% that. If it is a \TeX\ register, we need to execute the sequence +% |\exp_after:wN\exp_stop_f:\tex_the:D #1| and if it is a macro we +% need to execute |\exp_after:wN\exp_stop_f: #1|. We therefore issue +% the longer of the two sequences and if the register is a macro, we +% remove the |\tex_the:D|. % \begin{macrocode} -\def_long_new:Npn\exp_C_aux:nnn #1{ - \exp_after:NN - \exp_arg_next:nnn - \exp_after:NN - { - \exp_after:NN - {#1} - } + \else: + \exp_after:wN \use_i_ii:nnn + \fi: + \exp_after:wN \exp_stop_f: \tex_the:D #1 +} +\cs_set_nopar:Npn \exp_eval_register:c #1{ + \exp_after:wN\exp_eval_register:N\cs:w #1\cs_end: } % \end{macrocode} -% \end{macro} +% Clean up nicely, then call the undefined control sequence. The +% result is an error message looking like this: +% \begin{verbatim} +% ! Undefined control sequence. +% \exp_eval_error_msg:w ...erroneous variable used! +% +% l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl} +% \end{verbatim} +% \begin{macrocode} +\group_begin:% +\tex_catcode:D`\!=11\tex_relax:D% +\tex_catcode:D`\ =11\tex_relax:D% +\cs_gset:Npn\exp_eval_error_msg:w#1\tex_the:D#2{% +\fi:\fi:\erroneous variable used!}% +\group_end:% +% \end{macrocode} +% \end{macro} +% \end{macro} +% % % Here are some that might not stay but let's see. -% \begin{macro}{\::E} -% This function is used to expand an argument once and return it -% \emph{without} braces. Use this only when you feel pretty -% comfortable about your input! Actually this is pretty much just -% generic wrapper for |\exp_after:NN|. +% +% \begin{macro}{\::d} +% This function is used to expand an argument twice. Mostly useful +% for |toks| type things. This is likely to vanish with |V| around. % \begin{macrocode} -\def_long_new:Npn\::E#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} +\cs_new:Npn\::d#1\:::#2#3{ + \exp_after:wN\exp_after:wN\exp_after:wN\exp_arg_next:nnn + \exp_after:wN\exp_after:wN\exp_after:wN{#3}{#1}{#2} } % \end{macrocode} % \end{macro} % -% \begin{macro}{\::e} -% Same as |\::E| really but conceptually they are different. +% \subsection{Hand-tuned definitions} +% \label{sec:handtune} +% +% One of the most important features of these functions is that they +% are fully expandable and therefore allow to prefix them with +% |\pref_global:D| for example. This together with the fact that the +% `general' concept above is slower means that we should convert +% whenever possible and perhaps remove all remaining occurences by +% hand-encoding in the end. +% +% \begin{macro}{\exp_args:No} +% \begin{macro}{\exp_args:NNo} +% \begin{macro}{\exp_args:NNNo} % \begin{macrocode} -\def_long_new:Npn\::e#1\:::#2#3{ - \exp_after:NN\exp_arg_next:nnn \exp_after:NN{#3}{#1}{#2} -} +\cs_new:Npn \exp_args:No #1#2{\exp_after:wN#1\exp_after:wN{#2}} +\cs_new:Npn \exp_args:NNo #1#2#3{\exp_after:wN#1\exp_after:wN#2 + \exp_after:wN{#3}} +\cs_new:Npn \exp_args:NNNo #1#2#3#4{\exp_after:wN#1\exp_after:wN#2 + \exp_after:wN#3\exp_after:wN{#4}} % \end{macrocode} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\::d} -% This function is used to expand an argument twice. Mostly useful -% for |toks| type things. +% +% \begin{macro}{\exp_args:Nc,\exp_args:cc,\exp_args:NNc,\exp_args:Ncc,\exp_args:Nccc} +% Here are the functions that turn their argument into csnames but +% are expandable. % \begin{macrocode} -\def_long_new:Npn\::d#1\:::#2#3{ - \exp_after:NN\exp_after:NN\exp_after:NN\exp_arg_next:nnn - \exp_after:NN\exp_after:NN\exp_after:NN{ - \exp_after:NN\exp_after:NN\exp_after:NN{#3}}{#1}{#2} -} +\cs_set:Npn \exp_args:Nc #1#2{\exp_after:wN#1\cs:w#2\cs_end:} +\cs_new:Npn \exp_args:cc #1#2{\cs:w #1\exp_after:wN\cs_end:\cs:w #2\cs_end:} +\cs_new:Npn \exp_args:NNc #1#2#3{\exp_after:wN#1\exp_after:wN#2 + \cs:w#3\cs_end:} +\cs_new:Npn \exp_args:Ncc #1#2#3{\exp_after:wN#1 + \cs:w#2\exp_after:wN\cs_end:\cs:w#3\cs_end:} +\cs_new:Npn \exp_args:Nccc #1#2#3#4{\exp_after:wN#1 + \cs:w#2\exp_after:wN\cs_end:\cs:w#3\exp_after:wN + \cs_end:\cs:w #4\cs_end:} % \end{macrocode} % \end{macro} % -% We do most of them by hand here. This also means that we get a name -% for |\exp_after:NN| that fits with the rest of the code. +% \begin{macro}{\exp_args:Nco} +% If we force that the third argument +% always has braces, we could implement this function +% with less tokens and only two arguments. % \begin{macrocode} -\let:NN \exp_args:NE \exp_after:NN -\def:Npn \exp_args:NNE #1{\exp_args:NE#1\exp_args:NE} -\def:Npn \exp_args:NNNE #1#2{\exp_args:NE#1\exp_args:NE#2\exp_args:NE} -\def:Npn \exp_args:NEE #1{\exp_args:NE\exp_args:NE\exp_args:NE#1\exp_args:NE} -\def:Npn \exp_args:NcE #1#2{\exp_after:NN #1\cs:w #2\exp_after:NN\cs_end:} -\def:Npn \exp_args:Nd {\::d\:::} -\def:Npn \exp_args:NNd {\::N\::d\:::} +\cs_new:Npn \exp_args:Nco #1#2#3{\exp_after:wN#1\cs:w#2\exp_after:wN + \cs_end:\exp_after:wN{#3}} % \end{macrocode} +% \end{macro} +% +% \subsection{Definitions with the `general' technique} +% \label{sec:gendef} +% +% \begin{macro}{\exp_args:Nd,\exp_args:Nf,\exp_args:NV,\exp_args:Nv,\exp_args:Nx} +% \begin{macrocode} +\cs_set_nopar:Npn \exp_args:Nd {\::d\:::} +\cs_set_nopar:Npn \exp_args:Nf {\::f\:::} +\cs_set_nopar:Npn \exp_args:Nv {\::v\:::} +\cs_set_nopar:Npn \exp_args:NV {\::V\:::} +\cs_set_nopar:Npn \exp_args:Nx {\::x\:::} +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\exp_args:NC} -% \begin{macro}{\exp_args:Ncx} -% \begin{macro}{\exp_args:Ncco} -% \begin{macro}{\exp_args:Nccx} -% \begin{macro}{\exp_args:Ncnx} -% \begin{macro}{\exp_args:NcNc} -% \begin{macro}{\exp_args:Nf} -% \begin{macro}{\exp_args:NNf} -% \begin{macro}{\exp_args:Nfo} -% \begin{macro}{\exp_args:Nnf} -% \begin{macro}{\exp_args:NNno} -% \begin{macro}{\exp_args:NnnN} -% \begin{macro}{\exp_args:Nnno} -% \begin{macro}{\exp_args:Nnnx} -% \begin{macro}{\exp_args:Nno} -% \begin{macro}{\exp_args:Nnox} -% \begin{macro}{\exp_args:NNx} -% \begin{macro}{\exp_args:Nnx} -% \begin{macro}{\exp_args:Noo} -% \begin{macro}{\exp_args:Noox} -% \begin{macro}{\exp_args:Nox} -% \begin{macro}{\exp_args:Nx} -% \begin{macro}{\exp_args:Nxx} -% \begin{macro}{\exp_args:Nxx} -% \begin{macro}{\exp_args:NNC} -% \begin{macro}{\exp_args:Nnnc} -% \begin{macro}{\exp_args:NNnx} -% \begin{macro}{\exp_args:NNoo} -% \begin{macro}{\exp_args:NNox} +% \begin{macro}{\exp_args:NNV,\exp_args:NNv,\exp_args:NNd,\exp_args:NNf,\exp_args:NNx, +% \exp_args:NVV, +% \exp_args:Ncx, +% \exp_args:Nfo,\exp_args:Nff, +% \exp_args:Ncf,\exp_args:Nco, +% \exp_args:Nnf,\exp_args:Nno,\exp_args:Nnx, +% \exp_args:Noo,\exp_args:Noc,\exp_args:Nox, +% \exp_args:Nxo,\exp_args:Nxx} % Here are the actual function definitions, using the helper functions % above. % \begin{macrocode} -%\def:Npn \exp_args:NNNo {\::N\::N\::o\:::} -%\def:Npn \exp_args:NNOo {\::N\::O\::o\:::} -%\def:Npn \exp_args:NNc {\::N\::c\:::} -%\def:Npn \exp_args:NNo {\::N\::o\::\:::} -%\def:Npn \exp_args:NOOo {\::O\::O\::o\:::} -%\def:Npn \exp_args:NOc {\::O\::c\:::} -%\def:Npn \exp_args:NOo {\::O\::o\:::} -%\def:Npn \exp_args:Nc {\::c\:::} -%\def:Npn \exp_args:Ncc {\::c\::c\:::} -%\def:Npn \exp_args:Nccc {\::c\::c\::c\:::} -%\def:Npn \exp_args:Nco {\::c\::o\:::} -%\def:Npn \exp_args:No {\::o\:::} +\cs_set_nopar:Npn \exp_args:NNd {\::N\::d\:::} +\cs_set_nopar:Npn \exp_args:NNf {\::N\::f\:::} +\cs_set_nopar:Npn \exp_args:NNv {\::N\::v\:::} +\cs_set_nopar:Npn \exp_args:NNV {\::N\::V\:::} +\cs_set_nopar:Npn \exp_args:NNx {\::N\::x\:::} + +\cs_set_nopar:Npn \exp_args:Ncx {\::c\::x\:::} +\cs_set_nopar:Npn \exp_args:Nfo {\::f\::o\:::} +\cs_set_nopar:Npn \exp_args:Nff {\::f\::f\:::} +\cs_set_nopar:Npn \exp_args:Ncf {\::c\::f\:::} +\cs_set_nopar:Npn \exp_args:Nnf {\::n\::f\:::} +\cs_set_nopar:Npn \exp_args:Nno {\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:Nnx {\::n\::x\:::} + +\cs_set_nopar:Npn \exp_args:Noc {\::o\::c\:::} +\cs_set_nopar:Npn \exp_args:Noo {\::o\::o\:::} +\cs_set_nopar:Npn \exp_args:Nox {\::o\::x\:::} -\def:Npn \exp_args:NC {\::C\:::} -\def:Npn \exp_args:NNC {\::N\::C\:::} -\def:Npn \exp_args:NNf {\::N\::f\:::} -\def:Npn \exp_args:NNno {\::N\::n\::o\:::} -\def:Npn \exp_args:NNnx {\::N\::n\::x\:::} % new -\def:Npn \exp_args:NNoo {\::N\::o\::o\:::} % new -\def:Npn \exp_args:NNox {\::N\::o\::x\:::} % new -\def:Npn \exp_args:NNx {\::N\::x\:::} -\def:Npn \exp_args:NcNc {\::c\::N\::c\:::} -\def:Npn \exp_args:NcNo {\::c\::N\::o\:::} -\def:Npn \exp_args:Ncco {\::c\::c\::o\:::} -\def:Npn \exp_args:Ncco {\::c\::c\::o\:::} -\def:Npn \exp_args:Nccx {\::c\::c\::x\:::} -\def:Npn \exp_args:Ncnx {\::c\::n\::x\:::} -\def:Npn \exp_args:Ncx {\::c\::x\:::} -\def:Npn \exp_args:Nf {\::f\:::} -\def:Npn \exp_args:Nfo{\::f\::o\:::} -\def:Npn \exp_args:Nnf {\::n\::f\:::} -\def:Npn \exp_args:NnnN {\::n\::n\::N\:::} %% Strange one this one... -\def:Npn \exp_args:Nnnc {\::n\::n\::c\:::} -\def:Npn \exp_args:Nnno {\::n\::n\::o\:::} -\def:Npn \exp_args:Nnnx {\::n\::n\::x\:::} -\def:Npn \exp_args:Nno {\::n\::o\:::} -\def:Npn \exp_args:Nnox {\::n\::o\::x\:::} -\def:Npn \exp_args:Nnx {\::n\::x\:::} -\def:Npn \exp_args:Noo {\::o\::o\:::} -\def:Npn \exp_args:Noox {\::o\::o\::x\:::} -\def:Npn \exp_args:Nox {\::o\::x\:::} -\def:Npn \exp_args:Nx {\::x\:::} -\def:Npn \exp_args:Nxo {\::x\::o\:::} -\def:Npn \exp_args:Nxx {\::x\::x\:::} +\cs_set_nopar:Npn \exp_args:NVV {\::V\::V\:::} + +\cs_set_nopar:Npn \exp_args:Nxo {\::x\::o\:::} +\cs_set_nopar:Npn \exp_args:Nxx {\::x\::x\:::} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} +% +% \begin{macro}{\exp_args:Ncco, +% \exp_args:Nccx, +% \exp_args:Ncnx, +% \exp_args:NcNc, +% \exp_args:NcNo, +% \exp_args:NNno, +% \exp_args:Nnno, +% \exp_args:Nnnx, +% \exp_args:Nnox, +% \exp_args:Nooo, +% \exp_args:Noox, +% \exp_args:Nnnc, +% \exp_args:NNnx, +% \exp_args:NNoo, +% \exp_args:NNox} +% \begin{macrocode} +\cs_set_nopar:Npn \exp_args:NNno {\::N\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:NNnx {\::N\::n\::x\:::} +\cs_set_nopar:Npn \exp_args:NNoo {\::N\::o\::o\:::} +\cs_set_nopar:Npn \exp_args:NNox {\::N\::o\::x\:::} + +\cs_set_nopar:Npn \exp_args:Nnnc {\::n\::n\::c\:::} +\cs_set_nopar:Npn \exp_args:Nnno {\::n\::n\::o\:::} +\cs_set_nopar:Npn \exp_args:Nnnx {\::n\::n\::x\:::} +\cs_set_nopar:Npn \exp_args:Nnox {\::n\::o\::x\:::} + +\cs_set_nopar:Npn \exp_args:NcNc {\::c\::N\::c\:::} +\cs_set_nopar:Npn \exp_args:NcNo {\::c\::N\::o\:::} +\cs_set_nopar:Npn \exp_args:Ncco {\::c\::c\::o\:::} +\cs_set_nopar:Npn \exp_args:Ncco {\::c\::c\::o\:::} +\cs_set_nopar:Npn \exp_args:Nccx {\::c\::c\::x\:::} +\cs_set_nopar:Npn \exp_args:Ncnx {\::c\::n\::x\:::} + +\cs_set_nopar:Npn \exp_args:Noox {\::o\::o\::x\:::} +\cs_set_nopar:Npn \exp_args:Nooo {\::o\::o\::o\:::} +% \end{macrocode} % \end{macro} % % -% \subsubsection{Preventing expansion} +% \subsection{Preventing expansion} % % % \begin{macro}{\exp_not:o} % \begin{macro}{\exp_not:d} % \begin{macro}{\exp_not:f} +% \begin{macro}{\exp_not:v} +% \begin{macro}{\exp_not:V} % \begin{macrocode} -\def_long_new:Npn\exp_not:o#1{\exp_not:n\exp_after:NN{#1}} -\def_long_new:Npn\exp_not:d#1{ - \exp_not:n\exp_after:NN\exp_after:NN\exp_after:NN{#1} +\cs_new:Npn\exp_not:o#1{\exp_not:n\exp_after:wN{#1}} +\cs_new:Npn\exp_not:d#1{ + \exp_not:n\exp_after:wN\exp_after:wN\exp_after:wN{#1} +} +\cs_new:Npn\exp_not:f#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 #1} +} +\cs_new:Npn\exp_not:v#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 \exp_eval_register:c {#1}} } -\def_long_new:Npn\exp_not:f#1{ - \exp_not:n\exp_after:NN{\int_to_roman:w -`0 #1} +\cs_new:Npn\exp_not:V#1{ + \exp_not:n\exp_after:wN{\tex_romannumeral:D -`0 \exp_eval_register:N #1} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % -% \begin{macro}{\exp_not:E} % \begin{macro}{\exp_not:c} -% Two helper functions, which we can probably live without it. +% A helper function. % \begin{macrocode} -\def_new:Npn\exp_not:E{\exp_after:NN\exp_not:N} -\def_long_new:Npn\exp_not:c#1{\exp_after:NN\exp_not:N\cs:w#1\cs_end:} +\cs_new:Npn\exp_not:c#1{\exp_after:wN\exp_not:N\cs:w#1\cs_end:} % \end{macrocode} % \end{macro} -% \end{macro} -% -% -% \subsubsection{Single token expansion} % -% Expansion for arguments that are single tokens is done with the -% functions below. I first thought of using a different module name -% but then I saw that this wouldn't do since I could then never -% determine for, say, |\seq_put:no| whether this means single, or -% general expansion. Therefore I decided to use uppercase `O' for -% single expansion. -% -% One of the most important features of these functions is that they -% are fully expandable and therefore allow to prefix them with -% |\pref_global:D| for example. This together with the fact that the -% above concept is much slower in general means that we should convert -% whenever possible and perhaps remove all remaining occurences by -% hand-encoding in the end. % -% \begin{macro}{\exp_args:No} -% \begin{macro}{\exp_args:NOo} -% \begin{macro}{\exp_args:NNo} -% \begin{macro}{\exp_args:NNO} -% \begin{macro}{\exp_args:NOOo} -% \begin{macro}{\exp_args:NNOo} -% \begin{macro}{\exp_args:NNNo} -% This looks somewhat horrible but it runs well with the other -% syntax. It is important to see that these functions really need -% single tokens as arguments whenever capital letters are used. +% \subsection{Defining function variants} +% +% +% \begin{macro}{\cs_generate_variant:Nn} +% \begin{macro}[aux]{\cs_generate_variant_aux:nnNn} +% \begin{macro}[aux]{\cs_generate_variant_aux:nnw} +% \begin{macro}[aux]{\cs_generate_variant_aux:N} +% \begin{arguments} +% \item Base form of a function; e.g., "\tl_set:Nn" +% \item One or more variant argument specifiers; e.g., "{Nx,c,cx}" +% \end{arguments} +% Split up the original base function to grab its name and signature +% consisting of $k$ letters. Then we wish to iterate through the list +% of variant argument specifiers, and for each one construct a new +% function name using the original base name, the variant signature +% consisting of $l$ letters and the last $k-l$ letters of the base +% signature. For example, for a base function "\tl_set:Nn" which +% needs a "c" variant form, we want the new signature to be "cn". % \begin{macrocode} -\def_long_new:Npn \exp_args:No #1#2{\exp_after:NN#1\exp_after:NN{#2}} -\def_long_new:Npn \exp_args:NOo #1#2#3{\exp_after:NN\exp_args:No \exp_after:NN#1 - \exp_after:NN#2\exp_after:NN{#3}} -\def_long_new:Npn \exp_args:NOOo #1#2#3#4{\exp_after:NN\exp_args:NOo - \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} -\def_long_new:Npn \exp_args:NNo #1#2#3{\exp_after:NN#1\exp_after:NN#2 - \exp_after:NN{#3}} -\def_long_new:Npn \exp_args:NNO #1#2#3 {\exp_after:NN#1 - \exp_after:NN#2 #3} -\def_long_new:Npn \exp_args:NNOo #1#2#3#4{\exp_after:NN\exp_args:NNo - \exp_after:NN#1\exp_after:NN#2\exp_after:NN#3\exp_after:NN{#4}} -\def_long_new:Npn \exp_args:NNNo #1#2#3#4{\exp_after:NN#1\exp_after:NN#2 - \exp_after:NN#3\exp_after:NN{#4}} +\cs_new:Npn \cs_generate_variant:Nn #1 { + \chk_if_exist_cs:N #1 + \cs_split_function:NN #1 \cs_generate_variant_aux:nnNn +} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\exp_args:Nc} -% \begin{macro}{\exp_args:NNc} -% \begin{macro}{\exp_args:NOc} -% \begin{macro}{\exp_args:Ncc} -% \begin{macro}{\exp_args:Nccc} -% Here are the functions that turn their argument into csnames but -% are expandable. +% We discard the boolean and then set off a loop through the desired +% variant forms. % \begin{macrocode} -\def_long_new:Npn \exp_args:Nc #1#2{\exp_after:NN#1\cs:w#2\cs_end:} -\def_long_new:Npn \exp_args:NNc #1#2#3{\exp_after:NN#1\exp_after:NN#2 - \cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:NOc#1#2#3{\exp_after:NN\exp_args:No\exp_after:NN - #1\exp_after:NN#2\cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:Ncc #1#2#3{\exp_after:NN#1 - \cs:w#2\exp_after:NN\cs_end:\cs:w#3\cs_end:} -\def_long_new:Npn \exp_args:Nccc #1#2#3#4{\exp_after:NN#1 - \cs:w#2\exp_after:NN\cs_end:\cs:w#3\exp_after:NN - \cs_end:\cs:w #4\cs_end:} +\cs_set:Npn \cs_generate_variant_aux:nnNn #1#2#3#4{ + \cs_generate_variant_aux:nnw {#1}{#2} #4,?,\q_recursion_stop +} +% \end{macrocode} +% Next is the real work to be done. We now have 1: base name, 2: base +% signature, 3: beginning of variant signature. To construct the new +% csname and the "\exp_args:Ncc" form, we need the variant signature. +% In our example, we wanted to discard the first two letters of the +% base signature because the variant form started with "cc". This is +% the same as putting first "cc" in the signature and then +% "\use_none:nn" followed by the base signature "NNn". We therefore +% call a small loop that outputs an "n" for each letter in the variant +% signature and use this to call the correct "\use_none:" variant. +% Firstly though, we check whether to terminate the loop. +% \begin{macrocode} +\cs_set:Npn \cs_generate_variant_aux:nnw #1 #2 #3, { + \if:w ? #3 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: +% \end{macrocode} +% Then check if the variant form has already been defined. +% \begin{macrocode} + \cs_if_free:cTF { + #1:#3\use:c {use_none:\cs_generate_variant_aux:N #3 ?}#2 + } + { +% \end{macrocode} +% If not, then define it and then additionally check if +% the |\exp_args:N| form needed is defined. +% \begin{macrocode} + \cs_new_nopar:cpx { + #1:#3 \use:c{use_none:\cs_generate_variant_aux:N #3 ?}#2 + } + { + \exp_not:c { exp_args:N #3} \exp_not:c {#1:#2} + } + \cs_generate_internal_variant:n {#3} + } +% \end{macrocode} +% Otherwise tell that it was already defined. +% \begin{macrocode} + { + \iow_log:x{ + Variant~\token_to_str:c { + #1:#3\use:c {use_none:\cs_generate_variant_aux:N #3 ?}#2 + }~already~defined;~ not~ changing~ it~on~line~ + \tex_the:D \tex_inputlineno:D + } + } +% \end{macrocode} +% Recurse. +% \begin{macrocode} + \cs_generate_variant_aux:nnw{#1}{#2} +} +% \end{macrocode} +% The small loop for defining the required number of "n"s. Break when +% seeing a "?". +% \begin{macrocode} +\cs_set:Npn \cs_generate_variant_aux:N #1{ + \if:w ?#1 \exp_after:wN\use_none:nn \fi: n \cs_generate_variant_aux:N +} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% -% -% \begin{macro}{\exp_args:Nco} -% If we force that the third argument -% always has braces, we could implement this function -% with less tokens and only two arguments. -% \begin{macrocode} -\def_long_new:Npn \exp_args:Nco #1#2#3{\exp_after:NN#1\cs:w#2\exp_after:NN - \cs_end:\exp_after:NN{#3}} -% \end{macrocode} -% \end{macro} % % -% \begin{macro}{\exp_def_form:nnn} -% This command is a recent addition which was actually added -% when we wrote the article for TUGboat (while most of the other -% code goes way back to 1993). +% \begin{macro}{\cs_generate_internal_variant:n} +% Test if |exp_args:N #1| is already defined +% and if not define it via the +% |\::| commands using the chars in |#1| % \begin{macrocode} -\def:Npn\exp_def_form:nnn#1#2#3{ - \exp_after:NN - \def:Npn - \cs:w - #1:#3 - \exp_after:NN - \cs_end: - \exp_after:NN - { - \cs:w - exp_args:N#3 - \exp_after:NN - \cs_end: - \cs:w - #1:#2 - \cs_end: - } +\cs_new:Npn \cs_generate_internal_variant:n #1 { + \cs_if_free:cT { exp_args:N #1 }{ % \end{macrocode} -% We also have to test if |exp_args:N#3| is already defined -% and if not define it via the -% |\::| commands using the chars in |#3| +% We use "new" to log the definition if we have to make one. % \begin{macrocode} - \cs_if_free:cT - {exp_args:N#3} - {\def:cpx {exp_args:N#3} - {\exp_args_form_x:w #3 :} - } + \cs_new:cpx { exp_args:N #1 } + { \cs_generate_internal_variant_aux:n #1 : } + } } % \end{macrocode} % \end{macro} % -% -% \begin{macro}{\exp_args_form_x:w} +% \begin{macro}[aux]{\cs_generate_internal_variant_aux:n} % This command grabs char by char outputting |\::#1| (not expanded % further) until we see a |:|. That colon is in fact also turned into % |\:::| so that the required structure for |\exp_args...| commands % is correctly terminated. % \begin{macrocode} -\def_new:Npn\exp_args_form_x:w #1 { +\cs_new:Npn \cs_generate_internal_variant_aux:n #1 { \exp_not:c{::#1} - \if_meaning:NN #1 : - \else: - \exp_after:NN\exp_args_form_x:w - \fi:} + \if_meaning:w #1 : + \exp_after:wN \use_none:n + \fi: + \cs_generate_internal_variant_aux:n +} % \end{macrocode} % \end{macro} % -% Show token usage: +% \subsection{Last-unbraced versions} +% +%\begin{macro}[aux]{\exp_arg_last_unbraced:nn} +%\begin{macro}[aux]{\::f_unbraced} +%\begin{macro}[aux]{\::o_unbraced} +%\begin{macro}[aux]{\::V_unbraced} +%\begin{macro}[aux]{\::v_unbraced} +% There are a few places where the last argument needs to be available +% unbraced. First some helper macros. +% \begin{macrocode} +\cs_new:Npn \exp_arg_last_unbraced:nn #1#2 { #2#1 } +\cs_new:Npn \::f_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { \tex_romannumeral:D -`0 #2 } {#1} +} +\cs_new:Npn \::o_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn \exp_after:wN {#2 }{#1} +} +\cs_new:Npn \::V_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { \tex_romannumeral:D -`0 \exp_eval_register:N #2 } {#1} +} +\cs_new:Npn \::v_unbraced \:::#1#2 { + \exp_after:wN \exp_arg_last_unbraced:nn + \exp_after:wN { + \tex_romannumeral:D -`0 \exp_eval_register:c {#2} + } {#1} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\exp_last_unbraced:NV} +%\begin{macro}{\exp_last_unbraced:Nv} +%\begin{macro}{\exp_last_unbraced:Nf} +%\begin{macro}{\exp_last_unbraced:NcV} +%\begin{macro}{\exp_last_unbraced:NNo} +%\begin{macro}{\exp_last_unbraced:NNV} +%\begin{macro}{\exp_last_unbraced:NNNo} +% Now the business end. +% \begin{macrocode} +\cs_new_nopar:Npn \exp_last_unbraced:Nf { \::f_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:NV { \::V_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:Nv { \::v_unbraced \::: } +\cs_new_nopar:Npn \exp_last_unbraced:NcV { + \::c \::V_unbraced \::: +} +\cs_new:Npn \exp_last_unbraced:NNo #1#2#3 { + \exp_after:wN #1 \exp_after:wN #2 #3 +} +\cs_new_nopar:Npn \exp_last_unbraced:NNV { + \::N \::V_unbraced \::: +} +\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4 { + \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4 +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% % \begin{macrocode} % +% \end{macrocode} +% +% Show token usage: +% \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.29 2006/07/30 15:43:38 morten -% Minor touch-up plus added functions needed by clist module -% -% Revision 1.28 2006/06/03 18:56:31 morten -% A few more functions -% -% Revision 1.27 2006/03/20 18:26:35 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.26 2006/02/17 23:01:47 braams -% Imported \exp_args:NNO from l3messages -% -% Revision 1.25 2005/12/27 10:00:45 morten -% Changed RCS information retrieval -% -% Revision 1.24 2005/12/22 13:56:03 morten -% Fixed error in \exp_args:NNd -% -% Revision 1.23 2005/12/21 20:44:30 morten -% Corrected typo. -% -% Revision 1.22 2005/12/06 15:34:46 morten -% Made \exp_not:o do what you'd expect -% -% Revision 1.21 2005/11/23 07:37:29 morten -% A few new expansion types, we shall see if they will be useful. -% -% Revision 1.20 2005/04/12 16:44:06 morten -% Fix to make it run as a package -% -% Revision 1.19 2005/04/12 13:24:07 morten -% Minor updates -% -% Revision 1.18 2005/04/09 21:06:46 morten -% Added yet another function. -% -% Revision 1.17 2005/04/06 21:38:10 morten -% Added more functions. -% -% Revision 1.16 2005/03/26 21:09:44 morten -% Added f argument type for "force expansion" -% -% Revision 1.15 2005/03/22 23:24:40 morten -% Fixed documentation error. -% -% Revision 1.14 2005/03/16 22:36:37 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.13 2005/03/11 21:37:37 braams -% Fixed the use of RCS information +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3file.dtx b/Master/texmf-dist/source/latex/expl3/l3file.dtx new file mode 100644 index 00000000000..e5e3a5e159c --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3file.dtx @@ -0,0 +1,412 @@ +% \iffalse +%% File: l3file.dtx Copyright (C) 2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +%% +% +%<*driver|package> +\RequirePackage{l3names} +% +%\fi +\GetIdInfo$Id: l3file.dtx 1352 2009-05-28 11:50:39Z morten $ + {L3 Experimental file loading} +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass[full]{l3doc} +\begin{document} + \DocInput{l3file.dtx} +\end{document} +% +% \fi +% +% \title{The \textsf{l3file} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% File Loading} +% \author{\Team} +% \date{\filedate} +% \maketitle +% +% \begin{documentation} +% +%\section{Loading files} +% +% The need to test if a file is available and to load a file if found is +% covered at a low level here. +% +%\begin{function}{ +% \file_if_exist_p:n| +% \file_if_exist:n / (TF) +%} +% \begin{syntax} +% "\file_if_exist:nTF" +% \end{syntax} +% Tests if exists. +% \begin{texnote} +% This is \LaTeXe's \cs{IfFileExists}, although it does not return +% name of the file (\emph{cf.}~\cs{@filef@und}). +% \end{texnote} +%\end{function} +% +%\begin{function}{\file_add_path:nN} +% \begin{syntax} +% "\file_add_path:nN" +% \end{syntax} +% Searches for on the \TeX\ path and using +% \cs{l_file_search_path_clist}. If is found, is set +% to the file name plus any path information needed. If is not +% found, will be blank. +% \begin{texnote} +% This is similar to obtaining \cs{@filef@und} from \LaTeXe's +% \cs{IfFileExists}. +% \end{texnote} +%\end{function} +% +%\begin{function}{\file_input:n} +% \begin{syntax} +% "\file_input:n" +% \end{syntax} +% Inputs if it found (according to the same rule as for +% \cs{file_if_exist:n}. +% \begin{texnote} +% This acts in a similar way to \LaTeXe's \cs{input}, as it will not +% lead to a \TeX\ loop if the file is not found. +% \end{texnote} +%\end{function} +% +%\begin{function}{\file_input_no_record:n} +% \begin{syntax} +% "\file_input_no_record:n" +% \end{syntax} +% Inputs if it found (according to the same rule as for +% \cs{file_if_exist:n}, but does not add it to +% \cs{g_file_record_clist}. The file is still added to +% \cs{g_file_record_full_clist}. +% \begin{texnote} +% This is similar to \LaTeXe's \cs{@input@}. +% \end{texnote} +%\end{function} +% +%\begin{function}{ +% \file_input_no_check:n| +% \file_input_no_check_no_record:n| +%} +% \begin{syntax} +% "\file_input_no_check:n" +% \end{syntax} +% Inputs directly without checking if it exists. The +% \texttt{no_record} version does not record the input in +% \begin{texnote}\cs{g_file_record_clist}. +% These are simple wrappers around the \TeX\ \cs{input} primitive +% \end{texnote} +%\end{function} +% +%\begin{function}{ +% \file_list:| +% \file_list_full:| +%} +% \begin{syntax} +% "\file_list:" +% \end{syntax} +% Lists files loaded in current \LaTeX\ run: the \texttt{full} version +% lists all files. +%\end{function} +% +%\section{Variables and constants} +% +%\begin{variable}{ +% \g_file_record_clist| +% \g_file_record_full_clist +%} +% Used to track the files that have been loaded. +%\end{variable} +% +%\begin{variable}{\l_file_search_path_clist} +% List of paths to search for a file in addition to those searched by +% \TeX. +% \begin{texnote} +% This is \cs{input@path} in \LaTeXe. +% \end{texnote} +%\end{variable} +% +%\begin{variable}{\l_file_test_read_stream} +% Input stream used to carry out file tests. +%\end{variable} +% +%\begin{variable}{\l_file_tmp_bool} +% Internal scratch switch. +%\end{variable} +% +%\begin{variable}{\l_file_tmp_tl} +% Internal scratch token list variable. +%\end{variable} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3file} implementation} +% +% The usual lead-off. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% +%<*initex|package> +% \end{macrocode} +% +%\begin{macro}{\g_file_record_clist} +%\begin{macro}{\g_file_record_full_clist} +% When files are read with logging, the names are added here. There are +% two lists, one for everything and one for only those items which might +% later be listed (as in \LaTeXe's \cs{listfiles}). +% \begin{macrocode} +\clist_new:N \g_file_record_clist +\clist_new:N \g_file_record_full_clist +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_file_search_path_clist} +% Checking input needs a stream to work with +% \begin{macrocode} +\clist_new:N \l_file_search_path_clist +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_file_test_read_stream} +% Checking input needs a stream to work with +% \begin{macrocode} +\ior_new:N \l_file_test_read_stream +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_file_tmp_bool} +% A flag is needed for internal purposes. +% \begin{macrocode} +\bool_new:N \l_file_tmp_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_file_tmp_tl} +% A scratch token list variable. +% \begin{macrocode} +\tl_new:N \l_file_tmp_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\file_if_exist_p:n} +%\begin{macro}[TF]{\file_if_exist:n} +%\begin{macro}[aux]{\file_if_exist_path:n} +%\begin{macro}[aux]{\file_if_exist_aux:n} +% Checking if a file exists takes place in two parts. First, there is +% a simple check ``here''. If that fails, then there is a loop over +% the current search path. +% \begin{macrocode} +\prg_new_conditional:Nnn \file_if_exist:n {p,TF,T,F} { + \ior_open:Nn \l_file_test_read_stream {#1} + \ior_if_eof:NTF \l_file_test_read_stream { + \file_if_exist_path:n {#1} + }{ + \ior_close:N \l_file_test_read_stream + \prg_return_true: + } +} +\cs_new_nopar:Nn \file_if_exist_path:n { + \bool_set_false:N \l_file_tmp_bool + \cs_set_nopar:Nn \file_if_exist_aux:n { + \ior_open:Nn \l_file_test_read_stream { #1 ##1 } + \ior_if_eof:NF \l_file_test_read_stream { + \bool_set_true:N \l_file_tmp_bool + \clist_map_break: + } + } +% +%<*package> + \cs_if_exist:NT \input@path { + \cs_set_eq:NN \l_file_search_path_clist \input@path + } +% +%<*initex|package> + \clist_map_function:NN \l_file_search_path_clist \file_if_exist_aux:n + \ior_close:N \l_file_test_read_stream + \bool_if:NTF \l_file_tmp_bool { + \prg_return_true: + }{ + \prg_return_false: + } +} +\cs_new_nopar:Nn \file_if_exist_aux:n { } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\file_add_path:nN} +%\begin{macro}[aux]{\file_add_path_search:n} +%\begin{macro}[aux]{\file_add_path_aux:n} +% Checking if a file exists takes place in two parts. First, there is +% a simple check ``here''. If that fails, then there is a loop over +% the current search path. +% \begin{macrocode} +\cs_new_nopar:Nn \file_add_path:nN { + \tl_clear:N #2 + \ior_open:Nn \l_file_test_read_stream {#1} + \ior_if_eof:NTF \l_file_test_read_stream { + \file_add_path_search:nN {#1} #2 + }{ + \tl_set:Nn #2 {#1} + } + \ior_close:N \l_file_test_read_stream +} +\cs_new_nopar:Nn \file_add_path_search:nN { + \cs_set_nopar:Nn \file_add_path_aux:n { + \ior_open:Nn \l_file_test_read_stream { ##1 #1 } + \ior_if_eof:NF \l_file_test_read_stream { + \tl_set:Nn #2 { ##1 #1 } + \clist_map_break: + } + } +% +%<*package> + \cs_if_exist:NT \input@path { + \cs_set_eq:NN \l_file_search_path_clist \input@path + } +% +%<*initex|package> + \clist_map_function:NN \l_file_search_path_clist \file_add_path_aux:n +} +\cs_new_nopar:Nn \file_add_path_aux:n { } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\file_input:n} +%\begin{macro}{\file_input_no_record:n} +% \cs{file_add_path:nN} will return an empty token list variable if the +% file is not found. This is used rather than \cs{file_if_exist:nT} here +% as it saves running the same loop twice. +% \begin{macrocode} +\cs_new:Nn \file_input:n { + \file_add_path:nN {#1} \l_file_tmp_tl + \tl_if_empty:NF \l_file_tmp_tl { + \file_input_no_check:n \l_file_tmp_tl + } +} +\cs_new:Nn \file_input_no_record:n { + \file_add_path:nN {#1} \l_file_tmp_tl + \tl_if_empty:NF \l_file_tmp_tl { + \file_input_no_check_no_record:n \l_file_tmp_tl + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\file_input_no_check:n} +% File input records what is going on before setting to work. +% \begin{macrocode} +\cs_new_nopar:Nn \file_input_no_check:n { + \clist_gput_right:Nx \g_file_record_clist {#1} + \wlog{ADDING: #1} +% +%<*package> + \@addtofilelist {#1} +% +%<*initex|package> + \clist_gput_right:Nx \g_file_record_full_clist {#1} + \tex_input:D #1 ~ +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\file_input_no_check_no_record:n} +% Inputting a file without adding to the main record is basically the +% same: even in this case the file goes on the full log. +% \begin{macrocode} +\cs_new_nopar:Nn \file_input_no_check_no_record:n { + \clist_gput_right:Nx \g_file_record_full_clist {#1} + \tex_input:D #1 ~ +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\file_list:} +%\begin{macro}{\file_list_full:} +%\begin{macro}[aux]{\file_list:N} +% Two functions to list all files used to the log: the \texttt{full} +% version includes everything whereas the standard version uses the +% shorter record. +% \begin{macrocode} +\cs_new_nopar:Nn \file_list: { + \file_list:N \g_file_record_clist +} +\cs_new_nopar:Nn \file_list_full: { + \file_list:N \g_file_record_full_clist +} +\cs_new_nopar:Nn \file_list:N { + \clist_remove_duplicates:N #1 + \iow_log:x { *~File~List~* } + \clist_map_function:NN #1 \file_list_aux:n + \iow_log:x { ************* } +} +\cs_new_nopar:Nn \file_list_aux:n { + \iow_log:x { #1 } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +% When used as a package, there is a need to hold onto the standard +% file list as well as the new one here. +% \begin{macrocode} +% +%<*package> +% \begin{macrocode} +\AtBeginDocument{ + \clist_put_right:NV \g_file_record_clist \@filelist + \clist_put_right:NV \g_file_record_full_clist \@filelist +} +% +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/expl3/l3final.dtx b/Master/texmf-dist/source/latex/expl3/l3final.dtx index f23db756876..65da64c7f7f 100644 --- a/Master/texmf-dist/source/latex/expl3/l3final.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3final.dtx @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -37,7 +37,7 @@ % %<*-ini> %\fi -\GetIdInfo$Id: l3final.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3final.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental final module} %\iffalse % @@ -46,7 +46,7 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} \DocInput{\filename.\filenameext} \end{document} @@ -63,15 +63,9 @@ % Some of the macros needed in creating the format are no longer % needed and will either be removed are modified to generate error % messages. -%<*initex> -% -% \subsection{Closing the error file} % -% Earlier on in the format a file was opened to collect all the -% error messages. This file needs to be closed before the format is -% dumped. % \begin{macrocode} -\err_file_close:N\c_kernel_err_tlp +%<*initex> % \end{macrocode} % % \subsection{Dumping the format} @@ -80,45 +74,7 @@ % \begin{macrocode} \tex_dump:D % \end{macrocode} -% -% \subsection{Creating the format} % -% There is one more thing needed for creating the format; a file -% called \file{lbase.ini}. For now this is included here. -%<*ini> % \begin{macrocode} -%% Derived from a file by Thomas Esser - -\ifx\pdfoutput\undefined \else - \ifx\pdfoutput\relax \else - % We're building the latex format with the pdfetex engine (started 2004). - % See this file for details. - \input pdftex-dvi.tex - \fi -\fi - -%% the usual format initialization. -%%\scrollmode -\input lbase.ltx -\endinput +% % \end{macrocode} -% -% \endinput -% -% $Log$ -% Revision 1.5 2006/03/19 15:03:22 braams -% Added code to close the kernel error file -% -% Revision 1.4 2006/01/13 23:20:07 braams -% Added lbase.ini to be generated from this file -% -% Revision 1.3 2005/12/27 16:01:48 morten -% Changed RCS information retrieval -% -% Revision 1.2 2005/04/12 22:48:24 braams -% Corrected a slight mistake -% -% Revision 1.1 2005/04/12 22:41:38 braams -% This file will contain al the last minute things needed in the format. -% For starters it just dumps the format. -% diff --git a/Master/texmf-dist/source/latex/expl3/l3format.ins b/Master/texmf-dist/source/latex/expl3/l3format.ins index cc3d0d984b8..f42ea71724d 100644 --- a/Master/texmf-dist/source/latex/expl3/l3format.ins +++ b/Master/texmf-dist/source/latex/expl3/l3format.ins @@ -1,72 +1,75 @@ - -\input docstrip.tex -\askforoverwritefalse - -\preamble - - -EXPERIMENTAL CODE - -Do not distribute this file without also distributing the -source files specified above. - -Do not distribute a modified version of this file. - - -\endpreamble -% stop docstrip adding \endinput -\postamble -\endpostamble - -\keepsilent - -% generate the format file -\generate{% - \file{lbase.ltx}{% - \from{l3names.dtx}{initex} % The naming conventions - \from{l3basics.dtx}{initex} % Initialisations - \from{l3chk.dtx}{initex} % Checking functions - \from{l3tlp.dtx}{initex} % token list pointers - \from{l3expan.dtx}{initex} % Controlling expansion of arguments - \from{l3quark.dtx}{initex} % quarks - \from{l3num.dtx}{initex} % Storing integers in macros - \from{l3seq.dtx}{initex} % Sequences and Stacks - \from{l3alloc.dtx}{initex} % Register allocations - \from{l3io.dtx}{initex} % dealing with I/O - \from{l3int.dtx}{initex} % dealing with integer registers - \from{l3clist.dtx}{initex} % Comma separated lists - \from{l3prop.dtx}{initex} % property lists - \from{l3token.dtx}{initex} % token investigation -% - \from{l3vers.dtx}{initex} % Version information -% - \from{l3skip.dtx}{initex} % dealing with skip registers - \from{l3toks.dtx}{initex} % dealing with token registers - \from{l3messages.dtx}{initex} % seting up for user communication - \from{l3box.dtx}{initex} % dealing with box registers - \from{l3precom.dtx}{initex,precompile} % - \from{l3prg.dtx}{initex} % Program control structures - \from{l3xref.dtx}{initex} % Cross references -% - \from{l3final.dtx}{initex} % Final wrap-up - } -} -% generate the format initialisation file -\generate{% - \file{lbase.ini}{% - \from{l3final.dtx}{ini} - } -} - -\Msg{} -\Msg{*************************************} -\Msg{*} -\Msg{* Now run (PDF)EINITEX on *lbase.ini} -\Msg{*} -\Msg{* On an up to date system, run } -\Msg{* pdfetex -ini "*lbase.ini" } -\Msg{*} -\Msg{*************************************} -\Msg{} - -\endbatchfile + +\input docstrip.tex +\askforoverwritefalse + +\preamble + + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble + +\keepsilent + +% generate the format file +\generate{% + \file{lbase.ltx}{% + \from{l3names.dtx}{initex} % The naming conventions + \from{l3basics.dtx}{initex} % Initialisations + \from{l3expan.dtx}{initex} % Controlling expansion of arguments + \from{l3tl.dtx}{initex} % token list variables + \from{l3num.dtx}{initex} % Storing integers in macros + \from{l3intexpr.dtx}{initex} % + \from{l3quark.dtx}{initex} % quarks + \from{l3seq.dtx}{initex} % Sequences and stacks +% + \from{l3alloc.dtx}{initex} % Register allocations +% + \from{l3toks.dtx}{initex} % dealing with token registers + \from{l3int.dtx}{initex} % dealing with integer registers + \from{l3prg.dtx}{initex} % Program control structures + \from{l3clist.dtx}{initex} % Comma separated lists + \from{l3token.dtx}{initex} % token investigation + \from{l3io.dtx}{initex} % dealing with I/O + \from{l3prop.dtx}{initex} % property lists + \from{l3msg.dtx}{initex} % setting up for user communication + \from{l3skip.dtx}{initex} % dealing with skip registers + \from{l3box.dtx}{initex} % dealing with box registers + \from{l3keyval.dtx}{initex} % +% +% \from{l3precom.dtx}{initex,precompile} % +% + \from{l3calc.dtx}{initex} % + \from{l3xref.dtx}{initex} % Cross references + \from{l3file.dtx}{initex} % file loading +% + \from{l3vers.dtx}{initex} % Version information +% +% +% \from{l3chk.dtx}{initex} % Checking functions +% + \from{l3final.dtx}{initex} % Final wrap-up + } +} + +\Msg{} +\Msg{*************************************} +\Msg{*} +\Msg{* Now run (PDF)INITEX on lbase.ltx} +\Msg{*} +\Msg{* On an up to date system, run } +\Msg{* pdftex -ini *lbase.ltx } +\Msg{*} +\Msg{*************************************} +\Msg{} + +\endbatchfile diff --git a/Master/texmf-dist/source/latex/expl3/l3int.dtx b/Master/texmf-dist/source/latex/expl3/l3int.dtx index 5b13df9cec4..815f7610e9c 100644 --- a/Master/texmf-dist/source/latex/expl3/l3int.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3int.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3int.dtx Copyright (C) 1990-2008 LaTeX3 project +%% File: l3int.dtx Copyright (C) 1990-2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3int.dtx 738 2008-08-01 13:21:42Z morten $ +\GetIdInfo$Id: l3int.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental Integer module} %\iffalse %<*driver> @@ -44,9 +44,9 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3int.dtx} \end{document} % % \fi @@ -55,12 +55,12 @@ % \title{The \textsf{l3int} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ -% Counters} +% Integers/counters} % \author{\Team} % \date{\filedate} % \maketitle % -% \section{Integers} +% \begin{documentation} % % \LaTeX3 maintains two type of integer registers for internal use. % One (associated with the name "num") for low level uses in the @@ -72,12 +72,12 @@ % preferred in all cases as there is little chance we should ever run % out of registers when being based on at least \eTeX. % -% \subsection{Functions} +% \section{Functions} % % \begin{function}{% % \int_new:N | % \int_new:c | -% \int_new_l:N | +%^^A \int_new_l:N | % } % \begin{syntax} % "\int_new:N" @@ -85,7 +85,7 @@ % Globally defines to be a new variable of type "int" although % you can still choose if it should be a an "\l_" or "\g_" type. % There is no way to define constant counters with these functions. -% The function "\int_new_l:N" defines locally only. +%^^A The function "\int_new_l:N" defines locally only. % \begin{texnote} % "\int_new:N" is the equivalent to plain \TeX{}'s \tn{newcount}. % However, the internal register allocation is done differently. @@ -125,7 +125,7 @@ % \int_gset:cn | % } % \begin{syntax} -% "\int_set:Nn" "{" "}" +% "\int_set:Nn" \Arg{integer expr} % \end{syntax} % These functions will set the register to the % value. This value can contain simple calc-like expressions as @@ -154,7 +154,7 @@ % \int_gadd:cn | % } % \begin{syntax} -% "\int_add:Nn" "{" "}" +% "\int_add:Nn" \Arg{integer expr} % \end{syntax} % These functions will add to the register the value . If the second argument is a register too, the @@ -168,7 +168,7 @@ % \int_gsub:cn | % } % \begin{syntax} -% "\int_gsub:Nn" "{" "}" +% "\int_gsub:Nn" \Arg{integer expr} % \end{syntax} % These functions will subtract from the register the value % . If the second argument is a register too, the @@ -193,18 +193,34 @@ % \end{texnote} % \end{function} % -% \subsection{Formatting a counter value} +% \begin{function}{ \int_show:N | +% \int_show:c } +% \begin{syntax} +% "\int_show:N" +% \end{syntax} +% This function pauses the compilation and displays the integer value kept +% in in the console output and log file. +% \begin{texnote} +% The function "\int_show:N" could be implemented directly as the \TeX{} +% primitive "\tex_showthe:D" which is also responsible to produce the values for +% other internal quantities. We have chosen to use individual functions +% for counters, dimensions etc.\ to allow checks and to make the code +% more self-explaining. +% \end{texnote} +% \end{function} +% +% \section{Formatting a counter value} % % \begin{function}{ -% \int_to_arabic:n | -% \int_to_alph:n | -% \int_to_Alph:n | -% \int_to_roman:n | -% \int_to_Roman:n | -% \int_to_symbol:n | +% \int_to_arabic:n / (EXP) | +% \int_to_alph:n / (EXP) | +% \int_to_Alph:n / (EXP) | +% \int_to_roman:n / (EXP) | +% \int_to_Roman:n / (EXP) | +% \int_to_symbol:n / (EXP) | % } % \begin{syntax} -% "\int_to_alph:n" "{" "}" +% "\int_to_alph:n" \Arg{integer} % "\int_to_alph:n" % \end{syntax} % If some or the the current value of a should be @@ -228,9 +244,9 @@ % \end{texnote} % \end{function} % -% \subsubsection{Internal functions} +% \subsection{Internal functions} % -% \begin{function}{\int_to_roman:w} +% \begin{function}{\int_to_roman:w / (EXP)} % \begin{syntax} % "\int_to_roman:w" \textit{or} % \end{syntax} @@ -240,12 +256,24 @@ % This is the \TeX{} primitive \tn{romannumeral} renamed. % \end{texnote} % \end{function} +% +% \begin{function}{\int_to_number:w / (EXP)} +% \begin{syntax} +% "\int_to_number:w" +% \end{syntax} +% Converts to its numerical string. Note that +% it produces a string of letters with catcode 12. +% \begin{texnote} +% This is the \TeX{} primitive \tn{number} renamed. +% \end{texnote} +% \end{function} +% % \begin{function}{ % \int_roman_lcuc_mapping:Nnn | % \int_to_roman_lcuc:NN | % } % \begin{syntax} -% "\int_roman_lcuc_mapping:Nnn" "{""}" "{""}" +% "\int_roman_lcuc_mapping:Nnn" \Arg{licr} \Arg{LICR} % "\int_to_roman_lcuc:NN" % \end{syntax} % "\int_roman_lcuc_mapping:Nnn" specifies how the roman @@ -264,8 +292,8 @@ % \int_symbol_text_conversion_rule:n | % } % \begin{syntax} -% "\int_convert_number_with_rule:nnN" "{""}" "{""}" -% "\int_alph_default_conversion_rule:n" "{""}" +% "\int_convert_number_with_rule:nnN" \Arg{int1} \Arg{int2} +% "\int_alph_default_conversion_rule:n" \Arg{int} % \end{syntax} % "\int_convert_number_with_rule:nnN" converts into letters, % symbols, whatever as defined by . denotes the base @@ -277,7 +305,34 @@ % % % -% \subsection{Variable and constants} +% \section{Variable and constants} +% +% \begin{function}{% +% \int_const:Nn | +% } +% \begin{syntax} +% "\int_const:Nn" "\c_" \Arg{value} +% \end{syntax} +% Defines an integer constant of a certain . If the constant is negative +% or very large it internally uses an register. +% \end{function} +% +% \begin{variable}{ \c_minus_one | \c_zero | \c_one | \c_two | \c_three | +% \c_four | \c_five | \c_six | \c_seven | \c_eight | +% \c_nine | \c_ten | \c_eleven | \c_twelve | \c_thirteen | +% \c_fourteen | \c_fifteen | \c_sixteen | \c_thirty_two | +% \c_hundred_one | +% \c_twohundred_fifty_five | \c_twohundred_fifty_six | +% \c_thousand | +% \c_ten_thousand | \c_ten_thousand_one | +% \c_ten_thousand_two | \c_ten_thousand_three | +% \c_ten_thousand_four | \c_twenty_thousand } +% Set of constants denoting useful values. +% \begin{texnote} +% Some of these constants have been available under \LaTeX2 under names +% like \tn{m@ne}, \tn{z@}, \tn{@ne},\tn{tw@}, \tn{thr@@}, etc. +% \end{texnote} +% \end{variable} % % \begin{variable}{% % \c_max_int | @@ -299,149 +354,87 @@ % \end{variable} % % -% \subsection{Testing and evaluating integer expressions} % -% \begin{function}{% -% \int_eval:n | -% \int_div_truncate:nn | -% \int_div_round:nn | -% \int_mod:nn | -% } -% \begin{syntax} -% "\int_eval:n" "{""}" \\ -% "\int_div_truncate:n" "{""}" "{""}" \\ -% "\int_mod:nn" "{""}" "{""}" -% \end{syntax} -% Evaluates the value of a integer expression so that -% "\int_eval:n {3*5/4}" puts "4" back into the input stream. Note that -% the results of divisions are rounded by the primitive operations. If -% you want the result of a division to be truncated use -% "\int_div_truncate:nn". "\int_div_round:nn" is added for -% completeness. "\int_mod:nn" returns the remainder of a division. All -% of these functions are expandable. -% \begin{texnote} -% "\int_eval:n" is the \eTeX primitive \tn{numexpr} turned into a function -% taking an argument. -% \end{texnote} -% \end{function} % -% \begin{function}{% -% \int_compare:nNnTF | -% \int_compare:nNnT | -% \int_compare:nNnF | -% } -% \begin{syntax} -% "\int_compare:nNnTF" "{""}" "{""}" -% "{""}" "{""}" -% \end{syntax} -% These functions test two integer expressions against each other. They -% are both evaluated by "\int_eval:n". Note that if both expressions -% are normal integer variables as in -% \begin{quote} -% "\int_compare:nNnTF \l_temp_int < \c_zero {negative}{non-negative}" -% \end{quote} -% you can safely omit the braces. -% \begin{texnote} -% This is the \TeX{} primitive \tn{ifnum} turned into a function. -% \end{texnote} -% \end{function} +% \section{Conversion} % % \begin{function}{% -% \int_compare_p:nNn | +% \int_convert_from_base_ten:nn | % } % \begin{syntax} -% "\int_compare_p:nNn" "{""}" "{""}" +% "\int_convert_from_base_ten:nn" \Arg{number} \Arg{base} % \end{syntax} -% A predicate version of the above mentioned functions. +% Converts the base~10 number into its equivalent +% representation written in base~. Expandable. % \end{function} % -% \begin{function}{% -% \int_max_of:nn | -% \int_min_of:nn | -% } -% \begin{syntax} -% "\int_max_of:nn" "{""}" "{""}" -% \end{syntax} -% Return the largest or smallest of two integer expressions. -% \end{function} % % \begin{function}{% -% \int_abs:n | +% \int_convert_to_base_ten:nn | % } % \begin{syntax} -% "\int_abs:n" "{""}" +% "\int_convert_to_base_ten:nn" \Arg{number} \Arg{base} % \end{syntax} -% Return the numerical value of an integer expression. +% Converts the base~ number into its equivalent +% representation written in base~10. can consist of digits +% and ascii letters. Expandable. % \end{function} % -% \begin{function}{% -% \int_if_odd:nTF | -% \int_if_odd_p:n | -% } +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3int} implementation} +% +% \subsection{Internal functions and variables} +% +% \begin{function}{\int_advance:w} % \begin{syntax} -% "\int_if_odd:nTF" "{""}" "{""}" "{""}" +% "\int_advance:w" % \end{syntax} -% These functions test if an integer expression is even or odd. We -% also define a predicate version of it. +% Increments the count register by the specified amount. % \begin{texnote} -% This is the \TeX{} primitive \tn{ifodd} turned into a function. +% This is \TeX's \tn{advance}. % \end{texnote} % \end{function} % -% \begin{function}{% -% \int_whiledo:nNnT | -% \int_whiledo:nNnF | -% \int_dowhile:nNnT | -% \int_dowhile:nNnF | -% } +% +% \begin{function}{\int_convert_number_to_letter:n / (EXP)} % \begin{syntax} -% "\int_whiledo:nNnT" "{""}" +% "\int_convert_number_to_letter:n" \Arg{integer expression} % \end{syntax} -% "\int_whiledo:nNnT" tests the integer expressions and if true performs -% the body "T" until the test fails. "\int_dowhile:nNnT" is similar -% but executes the body first and then performs the check, thus -% ensuring that the body is executed at least once. The "F" versions -% are similar but continue the loop as long as the test is false. They -% could be omitted as it is just a matter of switching the arguments -% in the test. +% Internal function for turning a number for a different base into a letter or digit. % \end{function} % - -% \subsection{Conversion} -% -% \begin{function}{% -% \int_convert_from_base_ten:nn | -% } +% \begin{function}{\int_pre_eval_one_arg:Nn | \int_pre_eval_two_args:Nnn} % \begin{syntax} -% "\int_convert_from_base_ten:nn" "{""}""{""}" +% "\int_pre_eval_one_arg:Nn" \Arg{integer expression} +% "\int_pre_eval_one_arg:Nnn" \Arg{int~expr~1} \Arg{int~expr~2} % \end{syntax} -% Converts the base~10 number into its equivalent -% representation written in base~. Expandable. +% These are expansion helpers; they evaluate their integer expressions +% before handing them off to the specified . % \end{function} % -% -% \begin{function}{% -% \int_convert_to_base_ten:nn | -% } +% \begin{function}{ \int_get_sign_and_digits:n / (EXP) | +% \int_get_sign:n / (EXP ) | +% \int_get_digits:n / (EXP) } % \begin{syntax} -% "\int_convert_to_base_ten:nn" "{""}""{""}" +% "\int_get_sign_and_digits:n" \Arg{number} % \end{syntax} -% Converts the base~ number into its equivalent -% representation written in base~10. can consist of digits -% and ascii letters. Expandable. +% From an argument that may or may not include a "+" or "-" sign, these +% functions expand to the respective components of the number. % \end{function} % -% -% \StopEventually{} -% \subsection{The Implementation} -% +% \subsection{Module loading and primitives definitions} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3num} -%\RequirePackage{l3chk} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % @@ -450,9 +443,9 @@ % \begin{macro}{\int_advance:w} % A new name for the primitives. % \begin{macrocode} -\let_new:NN \int_to_roman:w \tex_romannumeral:D -\let_new:NN \int_to_number:w \tex_number:D -\let_new:NN \int_advance:w \tex_advance:D +\cs_new_eq:NN \int_to_roman:w \tex_romannumeral:D +\cs_new_eq:NN \int_to_number:w \tex_number:D +\cs_new_eq:NN \int_advance:w \tex_advance:D % \end{macrocode} % \end{macro} % \end{macro} @@ -460,6 +453,63 @@ % Functions that support \LaTeX's user accessible counters should be % added here, too. But first the internal counters. % +% \subsection{Allocation and setting} +% +% \begin{macro}{\int_new:N,\int_new:c} +%^^A \begin{macro}{\int_new_l:N} +% Allocation of a new internal counter is already done above. Here we define +% the next likely variant. +% +% For the \LaTeX3 format: +% \begin{macrocode} +%<*initex> +\alloc_setup_type:nnn {int} {11} \c_max_register_num +\cs_new_nopar:Npn \int_new:N #1 {\alloc_reg:NnNN g {int} \tex_countdef:D#1} +\cs_new_nopar:Npn \int_new_l:N #1 {\alloc_reg:NnNN l {int} \tex_countdef:D#1} +% +% \end{macrocode} +% For `l3in2e': +% \begin{macrocode} +%<*package> +\cs_new_nopar:Npn \int_new:N #1 { + \chk_if_free_cs:N #1 + \newcount #1 +} +% +% \end{macrocode} +% \begin{macrocode} +\cs_generate_variant:Nn \int_new:N {c} +% \end{macrocode} +% \end{macro} +%^^A \end{macro} +% +% +% \begin{macro}{\int_set:Nn} +% \begin{macro}{\int_set:cn} +% \begin{macro}{\int_gset:Nn} +% \begin{macro}{\int_gset:cn} +% Setting counters is again something that I would like to make +% uniform at the moment to get a better overview. +% \begin{macrocode} +\cs_new_nopar:Npn \int_set:Nn #1#2{#1 \intexpr_eval:w #2\intexpr_eval_end: +%<*check> +\chk_local_or_pref_global:N #1 +% +} +\cs_new_nopar:Npn \int_gset:Nn { +%<*check> + \pref_global_chk: +% +%<-check> \pref_global:D + \int_set:Nn } +\cs_generate_variant:Nn\int_set:Nn {cn} +\cs_generate_variant:Nn\int_gset:Nn {cn} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macro}{\int_incr:N} % \begin{macro}{\int_decr:N} % \begin{macro}{\int_gincr:N} @@ -471,17 +521,17 @@ % Incrementing and decrementing of integer registers is done with % the following functions. % \begin{macrocode} -\def_new:Npn \int_incr:N #1{\int_advance:w#1\c_one +\cs_new_nopar:Npn \int_incr:N #1{\int_advance:w#1\c_one %<*check> \chk_local_or_pref_global:N #1 % } -\def_new:Npn \int_decr:N #1{\int_advance:w#1\c_minus_one +\cs_new_nopar:Npn \int_decr:N #1{\int_advance:w#1\c_minus_one %<*check> \chk_local_or_pref_global:N #1 % } -\def_new:Npn \int_gincr:N { +\cs_new_nopar:Npn \int_gincr:N { % \end{macrocode} % We make sure that a local variable is not updated globally by % changing the internal test (i.e.\ |\chk_local_or_pref_global:N|) before @@ -496,7 +546,7 @@ % %<-check> \pref_global:D \int_incr:N} -\def_new:Npn \int_gdecr:N { +\cs_new_nopar:Npn \int_gdecr:N { %<*check> \pref_global_chk: % @@ -506,80 +556,41 @@ % With the |\int_add:Nn| functions we can shorten the above code. % If this makes it too slow \ldots % \begin{macrocode} -\def:Npn \int_incr:N #1{\int_add:Nn#1\c_one} -\def:Npn \int_decr:N #1{\int_add:Nn#1\c_minus_one} -\def:Npn \int_gincr:N #1{\int_gadd:Nn#1\c_one} -\def:Npn \int_gdecr:N #1{\int_gadd:Nn#1\c_minus_one} -\def:Npn \int_incr:c {\exp_args:Nc\int_incr:N} -\def:Npn \int_decr:c {\exp_args:Nc\int_decr:N} -\def:Npn \int_gincr:c {\exp_args:Nc\int_gincr:N} -\def:Npn \int_gdecr:c {\exp_args:Nc\int_gdecr:N} +\cs_set_nopar:Npn \int_incr:N #1{\int_add:Nn#1\c_one} +\cs_set_nopar:Npn \int_decr:N #1{\int_add:Nn#1\c_minus_one} +\cs_set_nopar:Npn \int_gincr:N #1{\int_gadd:Nn#1\c_one} +\cs_set_nopar:Npn \int_gdecr:N #1{\int_gadd:Nn#1\c_minus_one} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% -% \begin{macro}{\int_new:N} -% \begin{macro}{\int_new_l:N} -% \begin{macro}{\int_new:c} -% Allocation of a new internal counter is already done above. Here we define -% the next likely variant. +% % \begin{macrocode} -%<*initex> -\alloc_setup_type:nnn {int} \c_eleven \c_max_register_num -\def_new:Npn \int_new:N #1 {\alloc_reg:NnNN g {int} \tex_countdef:D#1} -\def_new:Npn \int_new_l:N #1 {\alloc_reg:NnNN l {int} \tex_countdef:D#1} -% -%\let:NN \int_new:N \newcount% allocation better nick the LaTeX one... -\def_new:Npn \int_new:c {\exp_args:Nc \int_new:N} +\cs_generate_variant:Nn \int_incr:N {c} +\cs_generate_variant:Nn \int_decr:N {c} +\cs_generate_variant:Nn \int_gincr:N {c} +\cs_generate_variant:Nn \int_gdecr:N {c} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% -% -% \begin{macro}{\int_set:Nn} -% \begin{macro}{\int_set:cn} -% \begin{macro}{\int_gset:Nn} -% \begin{macro}{\int_gset:cn} -% Setting counters is again something that I would like to make -% uniform at the moment to get a better overview. -% \begin{macrocode} -\def_new:Npn \int_set:Nn #1#2{#1 \int_eval:w #2\int_eval_end: -%<*check> -\chk_local_or_pref_global:N #1 -% -} -\def_new:Npn \int_gset:Nn { -%<*check> - \pref_global_chk: -% -%<-check> \pref_global:D - \int_set:Nn } -\def_new:Npn \int_set:cn {\exp_args:Nc \int_set:Nn } -\def_new:Npn \int_gset:cn {\exp_args:Nc \int_gset:Nn } -% \end{macrocode} +% \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % +% % \begin{macro}{\int_zero:N} % \begin{macro}{\int_zero:c} % \begin{macro}{\int_gzero:N} % \begin{macro}{\int_gzero:c} % Functions that reset an \m{int} register to zero. % \begin{macrocode} -\def_new:Npn \int_zero:N #1 {#1=\c_zero} -\def_new:Npn \int_zero:c #1 {\exp_args:Nc \int_zero:N} -\def_new:Npn \int_gzero:N #1 {\pref_global:D #1=\c_zero} -\def_new:Npn \int_gzero:c {\exp_args:Nc \int_gzero:N} +\cs_new_nopar:Npn \int_zero:N #1 {#1=\c_zero} +\cs_generate_variant:Nn \int_zero:N {c} +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_nopar:Npn \int_gzero:N #1 {\pref_global:D #1=\c_zero} +\cs_generate_variant:Nn \int_gzero:N {c} % \end{macrocode} % \end{macro} % \end{macro} @@ -597,39 +608,39 @@ % Adding and substracting to and from a counter \ldots % We should think of using these functions % \begin{macrocode} -\def_new:Npn \int_add:Nn #1#2{ +\cs_new_nopar:Npn \int_add:Nn #1#2{ % \end{macrocode} % We need to say |by| in case the first argument is a register % accessed by its number, e.g., |\count23|. Not that it should % ever happen but\dots % \begin{macrocode} - \int_advance:w #1 by \int_eval:w #2\int_eval_end: + \int_advance:w #1 by \intexpr_eval:w #2\intexpr_eval_end: %<*check> \chk_local_or_pref_global:N #1 % } -\def_new:Npn\int_add:cn{\exp_args:Nc\int_add:Nn} -\def_new:Npn \int_sub:Nn #1#2{ - \int_advance:w #1-\int_eval:w #2\int_eval_end: +\cs_new_nopar:Npn \int_sub:Nn #1#2{ + \int_advance:w #1-\intexpr_eval:w #2\intexpr_eval_end: %<*check> \chk_local_or_pref_global:N #1 % } -\def_new:Npn \int_gadd:Nn { +\cs_new_nopar:Npn \int_gadd:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \int_add:Nn } -\def_new:Npn \int_gsub:Nn { +\cs_new_nopar:Npn \int_gsub:Nn { %<*check> \pref_global_chk: % %<-check> \pref_global:D \int_sub:Nn } -\def_new:Npn \int_gadd:cn{\exp_args:Nc\int_gadd:Nn} -\def_new:Npn \int_sub:cn{\exp_args:Nc\int_sub:Nn} -\def_new:Npn \int_gsub:cn{\exp_args:Nc\int_gsub:Nn} +\cs_generate_variant:Nn \int_add:Nn {cn} +\cs_generate_variant:Nn \int_gadd:Nn {cn} +\cs_generate_variant:Nn \int_sub:Nn {cn} +\cs_generate_variant:Nn \int_gsub:Nn {cn} % \end{macrocode} % \end{macro} % \end{macro} @@ -645,8 +656,18 @@ % \begin{macro}{\int_use:c} % Here is how counters are accessed: % \begin{macrocode} -\let_new:NN \int_use:N \tex_the:D -\def_new:Npn \int_use:c #1{\int_use:N \cs:w#1\cs_end:} +\cs_new_eq:NN \int_use:N \tex_the:D +\cs_new_nopar:Npn \int_use:c #1{\int_use:N \cs:w#1\cs_end:} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\int_show:N} +% \begin{macro}{\int_show:c} +% Diagnostics. +% \begin{macrocode} +\cs_new_eq:NN \int_show:N \tex_showthe:D +\cs_new_nopar:Npn \int_show:c {\exp_args:Nc \int_show:N } % \end{macrocode} % \end{macro} % \end{macro} @@ -657,7 +678,7 @@ % \begin{macro}{\int_to_arabic:n} % Nothing exciting here. % \begin{macrocode} -\def_new:Npn \int_to_arabic:n #1{\int_to_number:w \int_eval:n{#1}} +\cs_new_nopar:Npn \int_to_arabic:n #1{ \intexpr_eval:n{#1}} % \end{macrocode} % \end{macro} % @@ -671,9 +692,9 @@ % character \TeX{} produces to the character we actually want which % will give us letters with category code~11.% % \begin{macrocode} -\def_new:Npn \int_roman_lcuc_mapping:Nnn #1#2#3{ - \def:cpn {int_to_lc_roman_#1:}{#2} - \def:cpn {int_to_uc_roman_#1:}{#3} +\cs_new_nopar:Npn \int_roman_lcuc_mapping:Nnn #1#2#3{ + \cs_set_nopar:cpn {int_to_lc_roman_#1:}{#2} + \cs_set_nopar:cpn {int_to_uc_roman_#1:}{#3} } % \end{macrocode} % \end{macro} @@ -701,18 +722,18 @@ % The commands for producing the lower and upper case roman numerals % run a loop on one character at a time and also carries some % information for upper or lower case with it. We put it through -% |\int_eval:n| first which is safer and more flexible. +% |\intexpr_eval:n| first which is safer and more flexible. % \begin{macrocode} -\def_new:Npn \int_to_roman:n #1 { - \exp_after:NN \int_to_roman_lcuc:NN \exp_after:NN l - \int_to_roman:w \int_eval:n {#1} Q +\cs_new_nopar:Npn \int_to_roman:n #1 { + \exp_after:wN \int_to_roman_lcuc:NN \exp_after:wN l + \int_to_roman:w \intexpr_eval:n {#1} Q } -\def_new:Npn \int_to_Roman:n #1 { - \exp_after:NN \int_to_roman_lcuc:NN \exp_after:NN u - \int_to_roman:w \int_eval:n {#1} Q +\cs_new_nopar:Npn \int_to_Roman:n #1 { + \exp_after:wN \int_to_roman_lcuc:NN \exp_after:wN u + \int_to_roman:w \intexpr_eval:n {#1} Q } -\def_new:Npn \int_to_roman_lcuc:NN #1#2{ - \cs_use:c {int_to_#1c_roman_#2:} +\cs_new_nopar:Npn \int_to_roman_lcuc:NN #1#2{ + \use:c {int_to_#1c_roman_#2:} \int_to_roman_lcuc:NN #1 } % \end{macrocode} @@ -743,20 +764,20 @@ % We do a little pre-expansion of the arguments below as they % otherwise have a tendency to grow quite large. % \begin{macrocode} -\def:Npn \int_convert_number_with_rule:nnN #1#2#3{ - \int_compare:nNnTF {#1}>{#2} +\cs_set_nopar:Npn \int_convert_number_with_rule:nnN #1#2#3{ + \intexpr_compare:nNnTF {#1}>{#2} { - \exp_args:No \int_convert_number_with_rule:nnN - { \int_use:N\int_div_truncate:nn {#1-1}{#2} }{#2} + \exp_args:Nf \int_convert_number_with_rule:nnN + { \intexpr_div_truncate:nn {#1-1}{#2} }{#2} #3 % \end{macrocode} % Note that we have to nudge our modulus function so it won't % return~$0$ as that wouldn't work with |\if_case:w| when that % expects a positive number to produce a letter. % \begin{macrocode} - \exp_args:No #3 { \int_use:N\int_eval:n{1+\int_mod:nn {#1-1}{#2}} } + \exp_args:Nf #3 { \intexpr_eval:n{1+\intexpr_mod:nn {#1-1}{#2}} } } - { \exp_args:No #3{ \int_use:N\int_eval:n{#1} } } + { \exp_args:Nf #3{ \intexpr_eval:n{#1} } } } % \end{macrocode} % As can be seen it is even simpler to convert to number systems @@ -770,7 +791,7 @@ % should have one such rule, as say in Danish there are 29 letters in % the alphabet. % \begin{macrocode} -\def_new:Npn \int_alph_default_conversion_rule:n #1{ +\cs_new_nopar:Npn \int_alph_default_conversion_rule:n #1{ \if_case:w #1 \or: a\or: b\or: c\or: d\or: e\or: f \or: g\or: h\or: i\or: j\or: k\or: l @@ -779,7 +800,7 @@ \or: y\or: z \fi: } -\def_new:Npn \int_Alph_default_conversion_rule:n #1{ +\cs_new_nopar:Npn \int_Alph_default_conversion_rule:n #1{ \if_case:w #1 \or: A\or: B\or: C\or: D\or: E\or: F \or: G\or: H\or: I\or: J\or: K\or: L @@ -799,11 +820,11 @@ % second argument of |\int_convert_number_with_rule:nnN| should of % course match the number of |\or:|s in the conversion rule. % \begin{macrocode} -\def_new:Npn \int_to_alph:n #1{ +\cs_new_nopar:Npn \int_to_alph:n #1{ \int_convert_number_with_rule:nnN {#1}{26} \int_alph_default_conversion_rule:n } -\def_new:Npn \int_to_Alph:n #1{ +\cs_new_nopar:Npn \int_to_Alph:n #1{ \int_convert_number_with_rule:nnN {#1}{26} \int_Alph_default_conversion_rule:n } @@ -814,7 +835,7 @@ % \begin{macro}{\int_to_symbol:n} % Turning a number into a symbol is also easy enough. % \begin{macrocode} -\def_new:Npn \int_to_symbol:n #1{ +\cs_new_nopar:Npn \int_to_symbol:n #1{ \mode_if_math:TF { \int_convert_number_with_rule:nnN {#1}{9} @@ -831,7 +852,7 @@ % \begin{macro}{\int_symbol_text_conversion_rule:n} % Nothing spectacular here. % \begin{macrocode} -\def_new:Npn \int_symbol_math_conversion_rule:n #1 { +\cs_new_nopar:Npn \int_symbol_math_conversion_rule:n #1 { \if_case:w #1 \or: * \or: \dagger @@ -844,7 +865,7 @@ \or: \ddagger\ddagger \fi: } -\def_new:Npn \int_symbol_text_conversion_rule:n #1 { +\cs_new_nopar:Npn \int_symbol_text_conversion_rule:n #1 { \if_case:w #1 \or: \textasteriskcentered \or: \textdagger @@ -866,7 +887,6 @@ % \begin{macro}{\l_tmpc_int} % \begin{macro}{\g_tmpa_int} % \begin{macro}{\g_tmpb_int} -% \begin{macro}{\l_loop_int} % We provide four local and two global scratch counters, maybe we % need more or less. % \begin{macrocode} @@ -875,202 +895,116 @@ \int_new:N \l_tmpc_int \int_new:N \g_tmpa_int \int_new:N \g_tmpb_int -\int_new:N \l_loop_int % a variable for use in loops (whilenum etc) % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % -% \begin{macro}{\int_eval:n} -% \begin{macro}{\int_eval:w} -% \begin{macro}{\int_eval_end:} -% Evaluating a calc expression using normal operators. Many of these -% are exactly the same as the ones in the \textsf{num} module so we -% just use them. -% \begin{macrocode} -\let_new:NN \int_eval:n \num_eval:n -\let_new:NN \int_eval:w \num_eval:w -\let_new:NN \int_eval_end: \num_eval_end: -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\c_max_int} -% The largest number allowed is $2^{31}-1$ -% \begin{macrocode} -\const_new:Nn \c_max_int {2147483647} -% \end{macrocode} -% \end{macro} % % \begin{macro}{\int_pre_eval_one_arg:Nn} % \begin{macro}{\int_pre_eval_two_args:Nnn} -% These might be handy when handing down values to other +% These are handy when handing down values to other % functions. All they do is evaluate the number in advance. % \begin{macrocode} -\def:Npn \int_pre_eval_one_arg:Nnn #1#2{\exp_args:No#1{\int_eval:w#2}} -\def:Npn \int_pre_eval_two_args:Nnn #1#2#3{ - \exp_args:Noo#1{\int_use:N\int_eval:w#2}{\int_use:N\int_eval:w#3} +\cs_set_nopar:Npn \int_pre_eval_one_arg:Nn #1#2{ + \exp_args:Nf#1{\intexpr_eval:n{#2}}} +\cs_set_nopar:Npn \int_pre_eval_two_args:Nnn #1#2#3{ + \exp_args:Nff#1{\intexpr_eval:n{#2}}{\intexpr_eval:n{#3}} } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\int_div_truncate:nn} -% \begin{macro}{\int_div_round:nn} -% \begin{macro}{\int_mod:nn} -% \begin{macro}{\int_div_truncate_raw:nn} -% \begin{macro}{\int_div_round_raw:nn} -% \begin{macro}{\int_mod_raw:nn} -% As "\num_eval:w" rounds the result of a division we also -% provide a version that truncates the result. -% \begin{macrocode} -\def_new:Npn \int_div_truncate:nn { - \int_pre_eval_two_args:Nnn\int_div_truncate_raw:nn -} -% \end{macrocode} -% Initial version didn't work correctly with e\TeX's implementation. -% \begin{macrocode} -%\def_new:Npn \int_div_truncate_raw:nn #1#2 { -% \int_eval:n{ (2*#1 - #2) / (2* #2) } -%} -% \end{macrocode} -% New version by Heiko: -% \begin{macrocode} -\def_new:Npn \int_div_truncate_raw:nn #1#2 { - \int_eval:w - \if_num:w \int_eval:w#1 = \c_zero - 0 - \else: - (#1 - \if_num:w \int_eval:w #1 < \c_zero - \if_num:w \int_eval:w#2 < \c_zero - -( #2 + - \else: - +( #2 - - \fi: - \else: - \if_num:w \int_eval:w #2 < \c_zero - +( #2 + - \else: - -( #2 - - \fi: - \fi: - 1)/2) - \fi: - /(#2) - \int_eval_end: -} -% \end{macrocode} -% For the sake of completeness: -% \begin{macrocode} -\def_new:Npn \int_div_round:nn { - \int_pre_eval_two_args:Nnn\int_div_round_raw:nn -} -\def_new:Npn \int_div_round_raw:nn #1#2 {\int_eval:n{#1/#2}} -% \end{macrocode} -% Finally there's the modulus operation. -% \begin{macrocode} -\def_new:Npn \int_mod:nn {\int_pre_eval_two_args:Nnn\int_mod_raw:nn} -\def_new:Npn \int_mod_raw:nn #1#2 { - \int_eval:n{ #1 - \int_div_truncate_raw:nn {#1}{#2} * #2 } -} -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \begin{macro}{\int_compare:nNnTF} -% \begin{macro}{\int_compare:nNnT} -% \begin{macro}{\int_compare:nNnF} -% Simple comparison tests. -% \begin{macrocode} -\let_new:NN \int_compare:nNnTF \num_compare:nNnTF -\let_new:NN \int_compare:nNnT \num_compare:nNnT -\let_new:NN \int_compare:nNnF \num_compare:nNnF -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\int_max_of:nn} -% \begin{macro}{\int_min_of:nn} -% \begin{macro}{\int_abs:n} -% Simple comparison tests. +% \subsection{Defining constants} +% \begin{macro}{\int_const:Nn} +% As stated, most constants can be defined as |\tex_chardef:D| or +% |\tex_mathchardef:D| but that's engine dependent. % \begin{macrocode} -\let_new:NN \int_max_of:nn \num_max_of:nn -\let_new:NN \int_min_of:nn \num_min_of:nn -\let_new:NN \int_abs:nn \num_abs:nn +\cs_new_nopar:Npn \int_const:Nn #1#2 { + \intexpr_compare:nNnTF {#2} > \c_minus_one { + \intexpr_compare:nNnTF {#2} > \c_max_register_num { + \int_new:N #1 \int_set:Nn #1{#2} + } { + \chk_if_free_cs:N #1 \tex_mathchardef:D #1 = \intexpr_eval:n{#2} + } + } { + \int_new:N #1 \int_set:Nn #1{#2} + } +} % \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% +% \end{macro} % -% \begin{macro}{\int_compare_p:nNn} -% A predicate function. +% \begin{macro}{\c_minus_one, +% \c_zero, \c_one, \c_two, \c_three, \c_four, \c_five, \c_six, +% \c_seven, \c_eight, \c_nine, \c_ten, +% \c_eleven, \c_twelve, \c_thirteen, \c_fourteen, \c_fifteen, +% \c_sixteen, \c_thirty_two, +% \c_hundred_one, +% \c_twohundred_fifty_five, \c_twohundred_fifty_six, +% \c_thousand, +% \c_ten_thousand, +% \c_ten_thousand_one, \c_ten_thousand_two, +% \c_ten_thousand_three, \c_ten_thousand_four, +% \c_twenty_thousand} +% And the usual constants, others are still missing. Please, make +% every constant a real constant at least for the moment. We can +% easily convert things in the end when we have found what +% constants are used in critical places and what not. % \begin{macrocode} -\let_new:NN \int_compare_p:nNn \num_compare_p:nNn + %% \tex_countdef:D \c_minus_one = 10 \scan_stop: + %% \c_minus_one = -1 \scan_stop: %% in l3basics +%\int_const:Nn \c_zero {0} +\int_const:Nn \c_one {1} +\int_const:Nn \c_two {2} +\int_const:Nn \c_three {3} +\int_const:Nn \c_four {4} +\int_const:Nn \c_five {5} +\int_const:Nn \c_six {6} +\int_const:Nn \c_seven {7} +\int_const:Nn \c_eight {8} +\int_const:Nn \c_nine {9} +\int_const:Nn \c_ten {10} +\int_const:Nn \c_eleven {11} +\int_const:Nn \c_twelve {12} +\int_const:Nn \c_thirteen {13} +\int_const:Nn \c_fourteen {14} +\int_const:Nn \c_fifteen {15} + %% \tex_chardef:D \c_sixteen = 16\scan_stop: %% in l3basics +\int_const:Nn \c_thirty_two {32} % \end{macrocode} -% \end{macro} -% -% \begin{macro}{\int_if_odd_p:n} -% \begin{macro}{\int_if_odd:nTF} -% \begin{macro}{\int_if_odd:nT} -% \begin{macro}{\int_if_odd:nF} -% A predicate function. +% The next one may seem a little odd (obviously!) but is useful when +% dealing with logical operators. % \begin{macrocode} -\def_new:Npn \int_if_odd_p:n #1 { - \if_num_odd:w \int_eval:n{#1} - \c_true - \else: - \c_false - \fi: -} -\def_test_function_new:npn {int_if_odd:n}#1{\if_num_odd:w \int_eval:n{#1}} +\int_const:Nn \c_hundred_one {101} +\int_const:Nn \c_twohundred_fifty_five{255} +\int_const:Nn \c_twohundred_fifty_six {256} +\int_const:Nn \c_thousand {1000} +\int_const:Nn \c_ten_thousand {10000} +\int_const:Nn \c_ten_thousand_one {10001} +\int_const:Nn \c_ten_thousand_two {10002} +\int_const:Nn \c_ten_thousand_three {10003} +\int_const:Nn \c_ten_thousand_four {10004} +\int_const:Nn \c_twenty_thousand {20000} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\int_whiledo:nNnT} -% \begin{macro}{\int_whiledo:nNnF} -% \begin{macro}{\int_dowhile:nNnT} -% \begin{macro}{\int_dowhile:nNnF} -% These are quite easy given the above functions. The "while" versions -% test first and then execute the body. The "dowhile" does it the -% other way round. The have to be defined as ``long'' since the "T" argument -% might contain "\par" tokens. +% \begin{macro}{\c_max_int} +% The largest number allowed is $2^{31}-1$ % \begin{macrocode} -\def_long_new:Npn \int_whiledo:nNnT #1#2#3#4{ - \int_compare:nNnT {#1}#2{#3}{#4 \int_whiledo:nNnT {#1}#2{#3}{#4}} -} -\def_long_new:Npn \int_whiledo:nNnF #1#2#3#4{ - \int_compare:nNnF {#1}#2{#3}{#4 \int_whiledo:nNnF {#1}#2{#3}{#4}} -} -\def_long_new:Npn \int_dowhile:nNnT #1#2#3#4{ - #4 \int_compare:nNnT {#1}#2{#3}{\int_dowhile:nNnT {#1}#2{#3}{#4}} -} -\def_long_new:Npn \int_dowhile:nNnF #1#2#3#4{ - #4 \int_compare:nNnF {#1}#2{#3}{\int_dowhile:nNnF {#1}#2{#3}{#4}} -} +\int_const:Nn \c_max_int {2147483647} % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % -% \subsubsection{Scanning and conversion} +% +% \subsection{Scanning and conversion} % % % Conversion between different numbering schemes requires meticulous @@ -1081,54 +1015,50 @@ % \begin{macro}{\int_get_sign_and_digits:n} % \begin{macro}{\int_get_sign:n} % \begin{macro}{\int_get_digits:n} -% \begin{macro}{\int_get_sign_and_digits_aux:nNNN} -% \begin{macro}{\int_get_sign_and_digits_aux:oNNN} +% \begin{macro}[aux]{\int_get_sign_and_digits_aux:nNNN} +% \begin{macro}[aux]{\int_get_sign_and_digits_aux:oNNN} % A number may be preceeded by any number of |+|s and |-|s. Start out % by assuming we have a positive number. % \begin{macrocode} -\def_new:Npn \int_get_sign_and_digits:n #1{ - \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_true \c_true +\cs_new_nopar:Npn \int_get_sign_and_digits:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_true_bool \c_true_bool } -\def_new:Npn \int_get_sign:n #1{ - \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_true \c_false +\cs_new_nopar:Npn \int_get_sign:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_true_bool \c_false_bool } -\def_new:Npn \int_get_digits:n #1{ - \int_get_sign_and_digits_aux:nNNN {#1} \c_true \c_false \c_true +\cs_new_nopar:Npn \int_get_digits:n #1{ + \int_get_sign_and_digits_aux:nNNN {#1} \c_true_bool \c_false_bool \c_true_bool } % \end{macrocode} % Now check the first character in the string. Only a |-| can change % if a number is positive or negative, hence we reverse the boolean % governing this. Then gobble the |-| and start over. % \begin{macrocode} -\def_new:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4{ - \tlist_if_head_eq_charcode:fNTF {#1} - +\cs_new_nopar:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4{ + \tl_if_head_eq_charcode:fNTF {#1} - { \bool_if:NTF #2 - { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_false #3#4 } - { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_true #3#4 } + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_false_bool #3#4 } + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} \c_true_bool #3#4 } } % \end{macrocode} % The other cases are much simpler since we either just have to gobble % the |+| or exit immediately and insert the correct sign. % \begin{macrocode} { - \tlist_if_head_eq_charcode:fNTF {#1} + + \tl_if_head_eq_charcode:fNTF {#1} + { \int_get_sign_and_digits_aux:oNNN {\use_none:n #1} #2#3#4} { % \end{macrocode} % The boolean |#3| is for printing the sign while |#4| is for printing % the digits. % \begin{macrocode} - \bool_double_if:NNnnnn #3#4 - { \bool_if:NF #2 - #1 } - { \bool_if:NF #2 - } - { #1 } { } + \bool_if:NT #3 { \bool_if:NF #2 - } + \bool_if:NT #4 {#1} } } } -\def_new:Npn \int_get_sign_and_digits_aux:oNNN{ - \exp_args:No\int_get_sign_and_digits_aux:nNNN -} +\cs_generate_variant:Nn \int_get_sign_and_digits_aux:nNNN {oNNN} % \end{macrocode} % \end{macro} % \end{macro} @@ -1138,23 +1068,23 @@ % % % \begin{macro}{\int_convert_from_base_ten:nn} -% \begin{macro}{\int_convert_from_base_ten_aux:nnn} -% \begin{macro}{\int_convert_from_base_ten_aux:non} -% \begin{macro}{\int_convert_from_base_ten_aux:fon} +% \begin{macro}[aux]{\int_convert_from_base_ten_aux:nnn} +% \begin{macro}[aux]{\int_convert_from_base_ten_aux:non} +% \begin{macro}[aux]{\int_convert_from_base_ten_aux:fon} % |#1| is the base 10 number to be converted to base |#2|. We split % off the sign first, print if if there and then convert only the % number. Since this is supposedly a base~10 number we can let \TeX\ % do the reading of |+| and |-|. % \begin{macrocode} -\def:Npn \int_convert_from_base_ten:nn#1#2{ - \num_compare:nNnTF {#1}<\c_zero +\cs_set_nopar:Npn \int_convert_from_base_ten:nn#1#2{ + \intexpr_compare:nNnTF {#1}<\c_zero { - - \int_convert_from_base_ten_aux:non {} - { \int_use:N \int_eval:n {-#1} } + - \int_convert_from_base_ten_aux:nfn {} + { \intexpr_eval:n {-#1} } } { - \int_convert_from_base_ten_aux:non {} - { \int_use:N \int_eval:n {#1} } + \int_convert_from_base_ten_aux:nfn {} + { \intexpr_eval:n {#1} } } {#2} } @@ -1173,44 +1103,42 @@ % |#1| is the carried over result, |#2| the remainder and |#3| the % base number. % \begin{macrocode} -\def_new:Npn \int_convert_from_base_ten_aux:nnn#1#2#3{ - \num_compare:nNnTF {#2}<{#3} +\cs_new_nopar:Npn \int_convert_from_base_ten_aux:nnn#1#2#3{ + \intexpr_compare:nNnTF {#2}<{#3} { \int_convert_number_to_letter:n{#2} #1 } { - \int_convert_from_base_ten_aux:fon + \int_convert_from_base_ten_aux:ffn { - \int_convert_number_to_letter:n {\int_use:N\int_mod_raw:nn {#2}{#3}} + \int_convert_number_to_letter:n {\intexpr_mod:nn {#2}{#3}} #1 } - {\int_use:N \int_div_truncate_raw:nn{#2}{#3}} + { \intexpr_div_truncate:nn{#2}{#3}} {#3} } } -\def:Npn \int_convert_from_base_ten_aux:non{ - \exp_args:Nno\int_convert_from_base_ten_aux:nnn -} -\def:Npn \int_convert_from_base_ten_aux:fon{ - \exp_args:Nfo\int_convert_from_base_ten_aux:nnn -} +\cs_generate_variant:Nn \int_convert_from_base_ten_aux:nnn {nfn} +\cs_generate_variant:Nn \int_convert_from_base_ten_aux:nnn {ffn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} +% % \begin{macro}{\int_convert_number_to_letter:n} % Turning a number for a different base into a letter or digit. % \begin{macrocode} -\def:Npn \int_convert_number_to_letter:n #1{ \if_case:w \int_eval:w - #1-10\scan_stop: \exp_after:NN A \or: \exp_after:NN B \or: - \exp_after:NN C \or: \exp_after:NN D \or: \exp_after:NN E \or: - \exp_after:NN F \or: \exp_after:NN G \or: \exp_after:NN H \or: - \exp_after:NN I \or: \exp_after:NN J \or: \exp_after:NN K \or: - \exp_after:NN L \or: \exp_after:NN M \or: \exp_after:NN N \or: - \exp_after:NN O \or: \exp_after:NN P \or: \exp_after:NN Q \or: - \exp_after:NN R \or: \exp_after:NN S \or: \exp_after:NN T \or: - \exp_after:NN U \or: \exp_after:NN V \or: \exp_after:NN W \or: - \exp_after:NN X \or: \exp_after:NN Y \or: \exp_after:NN Z \else: - \use_arg_i_after_fi:nw{ #1 }\fi: } +\cs_set_nopar:Npn \int_convert_number_to_letter:n #1{ + \if_case:w \intexpr_eval:w #1-10\intexpr_eval_end: + \exp_after:wN A \or: \exp_after:wN B \or: + \exp_after:wN C \or: \exp_after:wN D \or: \exp_after:wN E \or: + \exp_after:wN F \or: \exp_after:wN G \or: \exp_after:wN H \or: + \exp_after:wN I \or: \exp_after:wN J \or: \exp_after:wN K \or: + \exp_after:wN L \or: \exp_after:wN M \or: \exp_after:wN N \or: + \exp_after:wN O \or: \exp_after:wN P \or: \exp_after:wN Q \or: + \exp_after:wN R \or: \exp_after:wN S \or: \exp_after:wN T \or: + \exp_after:wN U \or: \exp_after:wN V \or: \exp_after:wN W \or: + \exp_after:wN X \or: \exp_after:wN Y \or: \exp_after:wN Z \else: + \use_i_after_fi:nw{ #1 }\fi: } % \end{macrocode} % \end{macro} % @@ -1219,8 +1147,8 @@ % use only the digits/letters from it and pass that onto a new % function. % \begin{macrocode} -\def:Npn \int_convert_to_base_ten:nn #1#2 { - \int_use:N\int_eval:n{ +\cs_set_nopar:Npn \int_convert_to_base_ten:nn #1#2 { + \intexpr_eval:n{ \int_get_sign:n{#1} \exp_args:Nf\int_convert_to_base_ten_aux:nn {\int_get_digits:n{#1}}{#2} } @@ -1228,7 +1156,7 @@ % \end{macrocode} % This is an intermediate function to get things started. % \begin{macrocode} -\def_new:Npn \int_convert_to_base_ten_aux:nn #1#2{ +\cs_new_nopar:Npn \int_convert_to_base_ten_aux:nn #1#2{ \int_convert_to_base_ten_auxi:nnN {0}{#2} #1 \q_nil } % \end{macrocode} @@ -1236,11 +1164,11 @@ % is the previously calculated result (to be multiplied by the base), % |#2| is the base and |#3| is the next letter/digit to be added. % \begin{macrocode} -\def_new:Npn \int_convert_to_base_ten_auxi:nnN#1#2#3{ +\cs_new_nopar:Npn \int_convert_to_base_ten_auxi:nnN#1#2#3{ \quark_if_nil:NTF #3 {#1} - {\exp_args:No\int_convert_to_base_ten_auxi:nnN - {\int_use:N \int_eval:n{ #1*#2+\int_convert_letter_to_number:N #3} } + {\exp_args:Nf\int_convert_to_base_ten_auxi:nnN + {\intexpr_eval:n{ #1*#2+\int_convert_letter_to_number:N #3} } {#2} } } @@ -1249,80 +1177,30 @@ % also takes care of handling lowercase and uppercase letters. Hence % |a| is turned into |11| and so is |A|. % \begin{macrocode} -\def:Npn \int_convert_letter_to_number:N #1{ - \int_compare:nNnTF{`#1}<{58}{#1} +\cs_set_nopar:Npn \int_convert_letter_to_number:N #1{ + \intexpr_compare:nNnTF{`#1}<{58}{#1} { - \int_eval:n{ `#1 - - \if:w\int_compare_p:nNn{`#1}<{91} - 55 - \else: - 87 - \fi: + \intexpr_eval:n{ `#1 - + \intexpr_compare:nNnTF{`#1}<{91}{ 55 }{ 87 } } } } % \end{macrocode} % \end{macro} % -% -% -% -% -% +% \begin{macrocode} +% +% \end{macrocode} % % Show token usage: % \begin{macrocode} -% %<*showmemory> \showMemUsage % % \end{macrocode} % +% \end{implementation} +% \PrintIndex % -% \endinput -% -% $Log$ -% Revision 1.26 2006/06/03 17:17:08 morten -% Functions for converting between number bases -% -% Revision 1.25 2006/03/20 18:26:35 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.24 2006/01/17 22:47:43 morten -% Changed \int_while:nNnT to \int_whiledo:nNnT to avoid confusion with -% the dowhile versions. -% -% Revision 1.23 2005/12/27 10:02:37 morten -% Minor changes plus changed RCS information retrieval -% -% Revision 1.22 2005/12/21 20:43:32 morten -% Fixed silly bugs! -% -% Revision 1.21 2005/12/06 17:31:23 morten -% fixed \int_convert_number_with_rule:nnN -% -% Revision 1.20 2005/12/06 14:49:36 morten -% Fixed primitive names plus a few minor touch-ups -% -% Revision 1.19 2005/04/25 15:02:47 morten -% Added ifodd functions -% -% Revision 1.18 2005/04/09 21:07:39 morten -% Added (extensible) implementations of \int_to_roman:n etc. -% -% Revision 1.17 2005/04/06 22:35:43 braams -% Now we have register allocation fitted -% -% Revision 1.16 2005/03/25 23:48:47 braams -% Added a missing \end{macro} -% -% Revision 1.15 2005/03/22 23:22:09 morten -% Moved definitions of constants to l3num -% -% Revision 1.14 2005/03/16 22:36:30 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.13 2005/03/11 21:38:31 braams -% Fixed the use of RCS information; added \StopEventually % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx b/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx new file mode 100644 index 00000000000..6b454a8ab80 --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx @@ -0,0 +1,642 @@ +% \iffalse +%% File: l3intexpr.dtx Copyright (C) 2009 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/svnroot/experimental/trunk/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +% +%<*driver|package> +\RequirePackage{l3names} +% +%\fi +\GetIdInfo$Id: l3intexpr.dtx 1086 2009-03-20 19:29:35Z morten $ + {L3 Integer Expressions} +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass[full]{l3doc} +\begin{document} +\DocInput{\filename.\filenameext} +\end{document} +% +% \fi +% +% +% \title{The \textsf{l3intexpr} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% Integer expressions} +% \author{\Team} +% \date{\filedate} +% \maketitle +% +% \begin{documentation} +% +% This module sets up evaluation of integer expressions and allows +% mixing |int| and |num| registers. +% +% An integer expression is one that contains integers in the form of +% numbers, registers containg numbers, i.e., |int| and |num| registers +% plus constants like |\c_one|, standard operators "+", "-", "/" and +% "*" and parentheses to group sub-expressions. +% +% \section{Functions} +% +% \begin{function}{% +% \intexpr_eval:n / (EXP) +% } +% \begin{syntax} +% "\intexpr_eval:n" \Arg{int~expr} +% \end{syntax} +% The result of this expansion is a properly terminated , +% i.e., one that can be used with "\if_case:w" and others. For example, +% \begin{quote} +% |\intexpr_eval:n{ 5 + 4*3 - (3+4*5) }| +% \end{quote} +% evaluates to $-6$. The result is returned after two expansions so +% if you find that you need to pass on the result to another function +% using the expansion engine, the recommendation is to use an "f" type +% expansion if in an expandable context or "x" otherwise. +% \end{function} +% +% +% \begin{function}{% +% \intexpr_compare_p:n / (EXP) | +% \intexpr_compare:n / (TF)(EXP) +% } +% \begin{syntax} +% "\intexpr_compare_p:n" \Arg{ } +% \end{syntax} +% Compares with using C-like relational +% operators, i.e. +% \begin{center} +% \begin{tabular}{ll@{\hspace{2cm}}ll} +% Less than & "<" & Less than or equal & "<=" \\ +% Greater than & "<" & Greater than or equal & ">=" \\ +% Equal & "==" or "=" & Not equal & "!=" +% \end{tabular} +% \end{center} +% Both integer expressions are evaluated fully in the process. Note +% the syntax, which allows natural input in the style of +% \begin{quote} +% |\intexpr_compare_p:n {5+3 != \l_tmpb_int}| +% \end{quote} +% "=" is added for the sake of \TeX\ users accustomed to using a +% single equal sign. +% \end{function} +% +% +% \begin{function}{% +% \intexpr_compare_p:nNn / (EXP) | +% \intexpr_compare:nNn / (TF)(EXP) +% } +% \begin{syntax} +% "\intexpr_compare_p:nNn" \Arg{int~expr1}\Arg{int~expr2} +% \end{syntax} +% Compares with using one of the relations +% "=", ">" or "<". This is faster than the variant above but at the +% cost of requiring a little more typing and not supporting the +% extended set of relational operators. Note that if both expressions +% are normal integer variables as in +% \begin{quote} +% "\intexpr_compare:nNnTF \l_temp_int < \c_zero {negative}{non-negative}" +% \end{quote} +% you can safely omit the braces. +% \end{function} +% +% +% \begin{function}{% +% \intexpr_max:nn / (EXP)| +% \intexpr_min:nn / (EXP)| +% } +% \begin{syntax} +% "\intexpr_max:nn" \Arg{int~expr1} \Arg{int~expr2} +% \end{syntax} +% Return the largest or smallest of two integer expressions. +% \end{function} +% +% \begin{function}{% +% \intexpr_abs:n / (EXP)| +% } +% \begin{syntax} +% "\intexpr_abs:n" \Arg{int~expr} +% \end{syntax} +% Return the numerical value of an integer expression. +% \end{function} +% +% \begin{function}{% +% \intexpr_if_odd:n / (EXP)(TF) | +% \intexpr_if_odd_p:n / (EXP) | +% \intexpr_if_even:n / (EXP)(TF) | +% \intexpr_if_even_p:n / (EXP) | +% } +% \begin{syntax} +% "\intexpr_if_odd:nTF" \Arg{int~expr} \Arg{true} \Arg{false} +% \end{syntax} +% These functions test if an integer expression is even or odd. +% \end{function} +% +% +% +% +% +% +% \begin{function}{% +% \intexpr_div_truncate:nn / (EXP) | +% \intexpr_div_round:nn / (EXP) | +% \intexpr_mod:nn / (EXP) | +% } +% \begin{syntax} +% "\intexpr_div_truncate:n" \Arg{int~expr} \Arg{int~expr} \\ +% "\intexpr_mod:nn" \Arg{int~expr} \Arg{int~expr} +% \end{syntax} +% If +% you want the result of a division to be truncated use +% "\intexpr_div_truncate:nn". "\intexpr_div_round:nn" is added for +% completeness. "\intexpr_mod:nn" returns the remainder of a division. +% \end{function} +% +% +% +% +% +% +% +% +% +% +% +% \section{Primitive functions} +% +% +% \begin{function}{% +% \intexpr_value:w | +% } +% \begin{syntax} +% "\intexpr_value:w" \\ +% "\intexpr_value:w" +% \end{syntax} +% Expands until an is formed. One space may be +% gobbled in the process. +% \begin{texnote} +% This is the \TeX{} primitive \tn{number}. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \intexpr_eval:w | +% \intexpr_eval_end: | +% } +% \begin{syntax} +% "\intexpr_eval:w" "\intexpr_eval_end:" +% \end{syntax} +% Evaluates . The evaluation stops when an +% unexpandable token of catcode other than 12 is reached or +% "\intexpr_end:" is read. The latter is gobbled by the scanner +% mechanism. +% \begin{texnote} +% This is the \eTeX{} primitive \tn{numexpr}. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \if_intexpr_compare:w | +% } +% \begin{syntax} +% "\if_intexpr_compare:w" "\else:" "\fi:" +% \end{syntax} +% Compare two numbers. It is recommended to use "\intexpr_eval:n" to +% correctly evaluate and terminate these numbers. is one of +% "<", "=" or ">" with catcode 12. +% \begin{texnote} +% This is the \TeX{} primitive \tn{ifnum}. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \if_intexpr_odd:w | +% } +% \begin{syntax} +% "\if_intexpr_odd:w" "\else:" "\fi:" +% \end{syntax} +% Execute if is odd, otherwise. +% \begin{texnote} +% This is the \TeX{} primitive \tn{ifodd}. +% \end{texnote} +% \end{function} +% +% \begin{function}{% +% \if_intexpr_case:w | +% \or: | +% } +% \begin{syntax} +% "\if_intexpr_case:w" "\or:" "\or:" "..." "\else:" +% "\fi:" +% \end{syntax} +% Chooses case . If you wish to use negative numbers as well, +% you can offset them with "\intexpr_eval:n". +% \begin{texnote} +% These are the \TeX{} primitives \tn{ifcase} and \tn{or}. +% \end{texnote} +% \end{function} +% +% +% +% \begin{function}{% +% \intexpr_while_do:nn | +% \intexpr_until_do:nn | +% \intexpr_do_while:nn | +% \intexpr_do_until:nn | +% } +% \begin{syntax} +% "\intexpr_while_do:nn" \Arg{ } \Arg{code} +% \end{syntax} +% "\intexpr_while_do:nn" tests the integer expressions against each +% other using a C-like as in "\intexpr_compare_p:n" and if true +% performs the until the test fails. "\intexpr_do_while:nn" is +% similar but executes the first and then performs the check, +% thus ensuring that the body is executed at least once. The `until' +% versions are similar but continue the loop as long as the test is +% false. They could be omitted as it is just a matter of switching the +% arguments in the test. +% \end{function} +% +% \begin{function}{% +% \intexpr_while_do:nNnn | +% \intexpr_until_do:nNnn | +% \intexpr_do_while:nNnn | +% \intexpr_do_until:nNnn | +% } +% \begin{syntax} +% "\intexpr_while_do:nNnn" \Arg{code} +% \end{syntax} +% Exactly as above but instead using the syntax of +% "\intexpr_compare_p:nNn". +% \end{function} +% +% +% +% +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3intexpr} implementation} +% +% +% We start by ensuring that the required packages are loaded. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% +%<*initex|package> +% \end{macrocode} +% +% \begin{macro}{\intexpr_value:w} +% \begin{macro}{\intexpr_eval:n,\intexpr_eval:w,\intexpr_eval_end:} +% \begin{macro}{\if_intexpr_compare:w} +% \begin{macro}{\if_intexpr_odd:w} +% \begin{macro}{\if_intexpr_case:w} +% Here are the remaining primitives for number comparisons and +% expressions. +% \begin{macrocode} +\cs_set_eq:NN \intexpr_value:w \tex_number:D +\cs_set_eq:NN \intexpr_eval:w \etex_numexpr:D +\cs_set_protected:Npn \intexpr_eval_end: {\tex_relax:D} +\cs_set_eq:NN \if_intexpr_compare:w \tex_ifnum:D +\cs_set_eq:NN \if_intexpr_odd:w \tex_ifodd:D +\cs_set_eq:NN \if_intexpr_case:w \tex_ifcase:D +\cs_set:Npn \intexpr_eval:n #1{ + \intexpr_value:w \intexpr_eval:w #1\intexpr_eval_end: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% +% +% +% \begin{macro}{\intexpr_compare_p:n} +% \begin{macro}[TF]{\intexpr_compare:n} +% Comparison tests using a simple syntax where only one set of braces +% is required and additional operators such as "!=" and ">=" are +% supported. First some notes on the idea behind this. We wish to +% support writing code like +% \begin{verbatim} +% \intexpr_compare_p:n { 5 + \l_tmpa_int != 4 - \l_tmpb_int } +% \end{verbatim} +% In other words, we want to somehow add the missing "\intexpr_eval:w" +% where required. We can start evaluating from the left using +% "\intexpr:w", and we know that since the relation symbols "<", ">", +% "=" and "!" are not allowed in such expressions, they will terminate +% the expression. Therefore, we first let \TeX\ evaluate this left +% hand side of the (in)equality. +% \begin{macrocode} +\prg_set_conditional:Npnn \intexpr_compare:n #1{p,TF,T,F}{ + \exp_after:wN \intexpr_compare_auxi:w \intexpr_value:w + \intexpr_eval:w #1\q_stop +} +% \end{macrocode} +% Then the next step is to figure out which relation we should use, so +% we have to somehow get rid of the first evaluation so that we can +% see what stopped it. "\tex_romannumeral:D" is handy here since its +% expansion given a non-positive number is \m{null}. We therefore +% simply check if the first token of the left hand side evaluation is +% a minus. If not, we insert it and issue "\tex_romannumeral:D", +% thereby ridding us of the left hand side evaluation. We do however +% save it for later. +% \begin{macrocode} +\cs_set:Npn \intexpr_compare_auxi:w #1#2\q_stop{ + \exp_after:wN \intexpr_compare_auxii:w \tex_romannumeral:D + \if:w #1- \else: -\fi: #1#2 \q_stop #1#2 \q_nil +} +% \end{macrocode} +% This leaves the first relation symbol in front and assuming the +% right hand side has been input, at least one other token as well. We +% support the following forms: |=|, |<|, |>| and the extended |!=|, +% |==|, |<=| and |>=|. All the extended forms have an extra |=| so we +% check if that is present as well. Then use specific function to +% perform the test. +% \begin{macrocode} +\cs_set:Npn \intexpr_compare_auxii:w #1#2#3\q_stop{ + \use:c{ + intexpr_compare_ + #1 \if_meaning:w =#2 = \fi: + :w} +} +% \end{macrocode} +% The actual comparisons are then simple function calls, using the +% relation as delimiter for a delimited argument. +% Equality is easy: +% \begin{macrocode} +\cs_set:cpn {intexpr_compare_=:w} #1=#2\q_nil{ + \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% So is the one using |==| -- we just have to use |==| in the +% parameter text. +% \begin{macrocode} +\cs_set:cpn {intexpr_compare_==:w} #1==#2\q_nil{ + \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% Not equal is just about reversing the truth value. +% \begin{macrocode} +\cs_set:cpn {intexpr_compare_!=:w} #1!=#2\q_nil{ + \if_intexpr_compare:w #1=\intexpr_eval:w #2 \intexpr_eval_end: + \prg_return_false: \else: \prg_return_true: \fi: +} +% \end{macrocode} +% Less than and greater than are also straight forward. +% \begin{macrocode} +\cs_set:cpn {intexpr_compare_<:w} #1<#2\q_nil{ + \if_intexpr_compare:w #1<\intexpr_eval:w #2 \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_set:cpn {intexpr_compare_>:w} #1>#2\q_nil{ + \if_intexpr_compare:w #1>\intexpr_eval:w #2 \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% For the less than or equal operation, we simply add $1$ to the right +% hand side and then use a less than test. A similar trick for the +% greater than or equal test except there we subtract $1$. +% \begin{macrocode} +\cs_set:cpn {intexpr_compare_<=:w} #1<=#2\q_nil{ + \if_intexpr_compare:w #1<\intexpr_eval:w #2 +\c_one \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +\cs_set:cpn {intexpr_compare_>=:w} #1>=#2\q_nil{ + \if_intexpr_compare:w #1>\intexpr_eval:w #2 - \c_one \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\intexpr_compare_p:nNn} +% \begin{macro}[TF]{\intexpr_compare:nNn} +% More efficient but less natural in typing. +% \begin{macrocode} +\prg_set_conditional:Npnn \intexpr_compare:nNn #1#2#3{p,TF,T,F}{ + \if_intexpr_compare:w \intexpr_eval:w #1 #2 \intexpr_eval:w #3 \intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\intexpr_max:nn} +% \begin{macro}{\intexpr_min:nn} +% \begin{macro}{\intexpr_abs:n} +% Functions for $\min$, $\max$, and absolute value. +% \begin{macrocode} +\cs_set:Npn \intexpr_abs:n #1{ + \intexpr_value:w + \if_intexpr_compare:w \intexpr_eval:w #1<\c_zero + - + \fi: + \intexpr_eval:w #1\intexpr_eval_end: +} +\cs_set:Npn \intexpr_max:nn #1#2{ + \intexpr_value:w \intexpr_eval:w + \if_intexpr_compare:w + \intexpr_eval:w #1>\intexpr_eval:w #2\intexpr_eval_end: + #1 + \else: + #2 + \fi: + \intexpr_eval_end: +} +\cs_set:Npn \intexpr_min:nn #1#2{ + \intexpr_value:w \intexpr_eval:w + \if_intexpr_compare:w + \intexpr_eval:w #1<\intexpr_eval:w #2\intexpr_eval_end: + #1 + \else: + #2 + \fi: + \intexpr_eval_end: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\intexpr_div_truncate:nn} +% \begin{macro}{\intexpr_div_round:nn} +% \begin{macro}{\intexpr_mod:nn} +% As "\intexpr_eval:w" rounds the result of a division we also +% provide a version that truncates the result. +% \begin{macrocode} +% \end{macrocode} +% Initial version didn't work correctly with e\TeX's implementation. +% \begin{macrocode} +%\cs_set:Npn \intexpr_div_truncate_raw:nn #1#2 { +% \intexpr_eval:n{ (2*#1 - #2) / (2* #2) } +%} +% \end{macrocode} +% New version by Heiko: +% \begin{macrocode} +\cs_set:Npn \intexpr_div_truncate:nn #1#2 { + \intexpr_value:w \intexpr_eval:w + \if_intexpr_compare:w \intexpr_eval:w #1 = \c_zero + 0 + \else: + (#1 + \if_intexpr_compare:w \intexpr_eval:w #1 < \c_zero + \if_intexpr_compare:w \intexpr_eval:w #2 < \c_zero + -( #2 + + \else: + +( #2 - + \fi: + \else: + \if_intexpr_compare:w \intexpr_eval:w #2 < \c_zero + +( #2 + + \else: + -( #2 - + \fi: + \fi: + 1)/2) + \fi: + /(#2) + \intexpr_eval_end: +} +% \end{macrocode} +% For the sake of completeness: +% \begin{macrocode} +\cs_set:Npn \intexpr_div_round:nn #1#2 {\intexpr_eval:n{(#1)/(#2)}} +% \end{macrocode} +% Finally there's the modulus operation. +% \begin{macrocode} +\cs_set:Npn \intexpr_mod:nn #1#2 { + \intexpr_value:w + \intexpr_eval:w + #1 - \intexpr_div_truncate:nn {#1}{#2} * (#2) + \intexpr_eval_end: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\intexpr_if_odd_p:n} +% \begin{macro}[TF]{\intexpr_if_odd:n} +% \begin{macro}{\intexpr_if_even_p:n} +% \begin{macro}[TF]{\intexpr_if_even:n} +% A predicate function. +% \begin{macrocode} +\prg_set_conditional:Npnn \intexpr_if_odd:n #1 {p,TF,T,F} { + \if_intexpr_odd:w \intexpr_eval:w #1\intexpr_eval_end: + \prg_return_true: \else: \prg_return_false: \fi: +} +\prg_set_conditional:Npnn \intexpr_if_even:n #1 {p,TF,T,F} { + \if_intexpr_odd:w \intexpr_eval:w #1\intexpr_eval_end: + \prg_return_false: \else: \prg_return_true: \fi: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\intexpr_while_do:nn} +% \begin{macro}{\intexpr_until_do:nn} +% \begin{macro}{\intexpr_do_while:nn} +% \begin{macro}{\intexpr_do_until:nn} +% These are quite easy given the above functions. The "while" versions +% test first and then execute the body. The "do_while" does it the +% other way round. +% \begin{macrocode} +\cs_set:Npn \intexpr_while_do:nn #1#2{ + \intexpr_compare:nT {#1}{#2 \intexpr_while_do:nn {#1}{#2}} +} +\cs_set:Npn \intexpr_until_do:nn #1#2{ + \intexpr_compare:nF {#1}{#2 \intexpr_until_do:nn {#1}{#2}} +} +\cs_set:Npn \intexpr_do_while:nn #1#2{ + #2 \intexpr_compare:nT {#1}{\intexpr_do_while:nNnn {#1}{#2}} +} +\cs_set:Npn \intexpr_do_until:nn #1#2{ + #2 \intexpr_compare:nF {#1}{\intexpr_do_until:nn {#1}{#2}} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\intexpr_while_do:nNnn} +% \begin{macro}{\intexpr_until_do:nNnn} +% \begin{macro}{\intexpr_do_while:nNnn} +% \begin{macro}{\intexpr_do_until:nNnn} +% As above but not using the more natural syntax. +% \begin{macrocode} +\cs_set:Npn \intexpr_while_do:nNnn #1#2#3#4{ + \intexpr_compare:nNnT {#1}#2{#3}{#4 \intexpr_while_do:nNnn {#1}#2{#3}{#4}} +} +\cs_set:Npn \intexpr_until_do:nNnn #1#2#3#4{ + \intexpr_compare:nNnF {#1}#2{#3}{#4 \intexpr_until_do:nNnn {#1}#2{#3}{#4}} +} +\cs_set:Npn \intexpr_do_while:nNnn #1#2#3#4{ + #4 \intexpr_compare:nNnT {#1}#2{#3}{\intexpr_do_while:nNnn {#1}#2{#3}{#4}} +} +\cs_set:Npn \intexpr_do_until:nNnn #1#2#3#4{ + #4 \intexpr_compare:nNnF {#1}#2{#3}{\intexpr_do_until:nNnn {#1}#2{#3}{#4}} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% \end{implementation} +% \PrintIndex +% +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3io.dtx b/Master/texmf-dist/source/latex/expl3/l3io.dtx index b382744776b..6473c2dca8b 100644 --- a/Master/texmf-dist/source/latex/expl3/l3io.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3io.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3io.dtx Copyright (C) 1990-2006 LaTeX3 project +%% File: l3io.dtx Copyright (C) 1990-2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -36,7 +36,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3io.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3io.dtx 1369 2009-05-31 21:36:35Z joseph $ {L3 Experimental i/o module} %\iffalse %<*driver> @@ -44,14 +44,22 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3io.dtx} \end{document} % % \fi % -% \section{Low-level file i/o} +% \title{The \textsf{l3io} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% Low-level file i/o} +% \author{\Team} +% \date{\filedate} +% \maketitle +% +% \begin{documentation} % % \TeX{} is capable of reading from and writing up to 16 individual % streams. These i/o operations are accessable in \LaTeX3 with functions @@ -60,25 +68,24 @@ % auxiliary file module, but here are the necessary functions for % manipulating private streams. % -% Sometimes it is not know beforehand how much text is going to be +% Sometimes it is not known beforehand how much text is going to be % written with a single call. As a result some internal \TeX{} buffer % may overflow. To avoid this kind of problem, \LaTeX3 maintains beside -% direct write operations like "\iow_expanded:Nn" also so called ``long'' +% direct write operations like "\iow_now:Nx" also so called ``long'' % writes where the output is broken into individual lines on every blank % in the text to be written. The resulting files are difficult to read % for humans but since they usually serve only as internal storage this % poses no problem. % -% Beside the functions that immediately act (e.g., "\iow_expanded:Nn", +% Beside the functions that immediately act (e.g., "\iow_now:Nx", % etc.) we also have deferred operations that are saved away until the % next page is finished. This allow to expand the at the right % time to get correct page numbers etc. % -% \subsection{Functions for output streams} +% \section{Functions for output streams} % -% \begin{function}{\iow_new:N | -% \iow_new:c -% } +% \begin{function}{ \iow_new:N | +% \iow_new:c } % \begin{syntax} % "\iow_new:N" % \end{syntax} @@ -90,11 +97,10 @@ % \end{texnote} % \end{function} % -% \begin{function}{\iow_open:Nn | -% \iow_open:cn -% } +% \begin{function}{ \iow_open:Nn | +% \iow_open:cn } % \begin{syntax} -% "\iow_open:Nn" "{" "}" +% "\iow_open:Nn" \Arg{file name} % \end{syntax} % Opens output stream to write to . The output % stream is immediately available for use. If the was already @@ -105,65 +111,93 @@ % still open at the end of the \TeX{} run will be automatically closed. % \end{function} % -% \begin{function}{\iow_expanded:Nn | -% \iow_unexpanded:Nn -% } +% \begin{function}{ \iow_close:N } +% \begin{syntax} +% "\iow_open:Nn" +% \end{syntax} +% Closes output stream . +% \end{function} +% +% \subsection{Immediate writing} +% +% \begin{function}{ \iow_now:Nx | +% \iow_now:Nn } % \begin{syntax} -% "\iow_expanded:Nn" "{" "}" +% "\iow_now:Nx" \Arg{tokens} % \end{syntax} -% This function immediately writes the expansion of to the +% "\iow_now:Nx" immediately writes the expansion of to the % output stream . If is not open output goes to the -% terminal. The variant "\iow_unexpanded:Nn" writes out without any -% further expansion (verbatim). +% terminal. The variant "\iow_now:Nn" writes out without any +% further expansion. +% \begin{texnote} +% These are the equivalent of \TeX's "\immediate\write" with and without +% expansion control. +% \end{texnote} +% \end{function} +% +% \begin{function}{ \iow_log:n | \iow_log:x | +% \iow_term:x | \iow_term:n } +% \begin{syntax} +% "\iow_log:x" \Arg{tokens} +% \end{syntax} +% These functions write to the log file (also known as the transcript file) or +% to the terminal respectively. They are equivalent to "\iow_now:Nx" where +% is the transcript file ("\c_iow_log_stream") or the terminal +% ("\c_iow_term_stream"). % \end{function} % -% \begin{function}{\iow_expanded_log:n | -% \iow_expanded_term:n | -% \iow_unexpanded_term:n -% } +% \begin{function}{ \iow_now_buffer_safe:Nn | +% \iow_now_buffer_safe:Nx } % \begin{syntax} -% "\iow_expanded_log:n" "{" "}" +% "\iow_now_buffer_safe:Nn" \Arg{tokens} % \end{syntax} -% These functions write to the transcript or to the terminal -% respectively. So they are equivalent to "\iow_expanded:Nn" where -% is the transcript file ("\c_iow_log_stream") or the terminal -% ("\c_io_term_stream"). +% Like "\iow_now:Nx" but splits at every blank into separate +% lines. When potentially (very) long token lists are being written, this +% avoids the problem of +% buffer overflow when reading back the file. % \end{function} % -% \begin{function}{\iow_long_expanded:Nx | -% \iow_long_unexpanded:Nn -% } +% \begin{function}{ \iow_now_when_avail:Nn | +% \iow_now_when_avail:cn } % \begin{syntax} -% "\iow_long_expanded:Nn" "{" "}" +% "\iow_now_when_avail:Nn" \Arg{tokens} % \end{syntax} -% Like "\iow_expanded:Nn" but splits at every blank into separate -% lines. +% This special function first checks if the is open for writing. +% If not it does nothing otherwise it behaves like "\iow_now:Nn". % \end{function} % -% \begin{function}{\iow_unexpanded_if_avail:Nn| -% \iow_unexpanded_if_avail:cn|} +% \subsection{Deferred writing} +% +% \begin{function}{ \iow_shipout:Nn | \iow_shipout:Nx } % \begin{syntax} -% "\iow_unexpanded_if_avail:Nn" "{" "}" +% "\iow_shipout_x:Nn" \Arg{tokens} % \end{syntax} -% This special function first checks if the is open of writing. -% If not it does nothing otherwise it behaves like "\iow_unexpanded:Nn". +% These functions write to the specified , but unlike with +% "\iow_now:Nn" which write the material immediately, "\iow_shipout:Nn" waits +% until the processing of the current page has finished. % \end{function} % -% \begin{function}{\iow_deferred_expanded:Nn | -% \iow_deferred_unexpanded:Nn} +% \begin{function}{ \iow_shipout_x:Nn | \iow_shipout_x:Nx } % \begin{syntax} -% "\iow_deferred_expanded:Nn" "{" "}" +% "\iow_shipout_x:Nn" \Arg{tokens} % \end{syntax} -% These functions save away until the next page is ready to be -% shipped out. Then, in case of "\iow_deferred_expanded:Nn" get -% expanded and afterwards written to . "\iow_deferred_expanded:Nn" -% also always needs "{}" around the second argument. The use of -% "\iow_deferred_unexpanded:Nn" is probably seldom necessary. +% More useful than the "\iow_shipout:Nn" functions, these functions also write +% to at the end of the processing of the current page; +% however, before are written they are subjected to a further +% "x" expansion stage. +% +% This is useful for writing messages that depend +% on counters (such as the page number) that are not known until the page has +% been completed. +% +% "\iow_shipout_x:Nn" always needs "{}" around the second argument. % \begin{texnote} -% "\iow_deferred_expanded:Nn" was known as \tn{write}. +% "\iow_shipout_x:Nn" is equivalent to \TeX's \tn{write}. % \end{texnote} % \end{function} % +% \subsection{Special characters for writing} +% % \begin{function}{\iow_newline:} % \begin{syntax} % "\iow_newline:" @@ -172,10 +206,26 @@ % that gets written some output stream in non-verbatim mode. % \end{function} % -% \subsection{Functions for input streams} +% \begin{function}{\iow_space:} +% \begin{syntax} +% "\iow_space:" +% \end{syntax} +% Function that produces a space when used within the +% that gets written to some output stream in an expanding mode. +% \end{function} +% +% \begin{function}{\iow_char:N} +% \begin{syntax} +% "\iow_space:N" "\" +% "\iow_space:N" "\%" +% \end{syntax} +% Inserts into the output stream. Useful when trying to write difficult +% characters such as "%", "{", "}", etc., in messages. +% \end{function} +% +% \section{Functions for input streams} % -% \begin{function}{\ior_new:N -% } +% \begin{function}{\ior_new:N} % \begin{syntax} % "\ior_new:N" % \end{syntax} @@ -188,12 +238,12 @@ % % \begin{function}{\ior_open:Nn} % \begin{syntax} -% "\ior_open:Nn" "{" "}" +% "\ior_open:Nn" \Arg{file name} % \end{syntax} % This function opens as an input stream for the external file % . If doesn't exist or is an empty file the % stream is considered to be fully read, a condition which can be tested -% with "\ior_eof:NTF" etc. If was already used to read from some +% with "\ior_if_eof:NTF" etc. If was already used to read from some % other file this file will be closed first. The input stream is ready % for immediate use. % \end{function} @@ -209,10 +259,9 @@ % \end{texnote} % \end{function} % -% \begin{function}{\ior_eof:NTF | -% \ior_eof:NF} +% \begin{function}{ \ior_if_eof_p:N / (EXP) | \ior_if_eof:N / (TF)(EXP) } % \begin{syntax} -% "\ior_eof:NTF" "{" "}{" "}" +% "\ior_if_eof:NTF" \Arg{true code} \Arg{false code} % \end{syntax} % Conditional that tests if some input stream is fully read. The % condition is also true if the input stream is not open. @@ -228,18 +277,18 @@ % \end{texnote} % \end{function} % -% \begin{function}{\ior_to:NN | -% \ior_gto:NN} +% \begin{function}{ \ior_to:NN | +% \ior_gto:NN } % \begin{syntax} -% "\ior_to:NN" +% "\ior_to:NN" % \end{syntax} % Functions that reads one or more lines (until an equal number of left % and right braces are found) from the input stream and places -% the result locally or globally into . If is not open -% input is requested from the terminal. +% the result locally or globally into the token list variable. +% If is not open, input is requested from the terminal. % \end{function} % -% \subsection{Constants} +% \section{Constants} % % \begin{variable}{\c_iow_comment_char | % \c_iow_lbrace_char | @@ -248,55 +297,36 @@ % right brace in token lists that should be written to a file. % \end{variable} % -% \begin{variable}{\c_io_term_stream} +% \begin{variable}{ \c_iow_term_stream | \c_ior_term_stream } % Input or output stream denoting the terminal. If used as an input -% stream the user is prompted with the name of the (that is used +% stream the user is prompted with the name of the token list variable +% (that is used % in the call "\ior_to:NN" or "\ior_gto:NN") followed by an equal sign. % If you don't want an automatic prompt of this sort ``misuse'' % "\c_iow_log_stream" as an input stream. % \end{variable} % -% \begin{variable}{\c_iow_log_stream} +% \begin{variable}{ \c_iow_log_stream | \c_ior_log_stream } % Output stream that writes only to the transcript file (e.g., the -% {\tt.log} file on most systems). You may ``misuse'' this stream as an +% ".log" file on most systems). You may ``misuse'' this stream as an % input stream. In this case it acts as a terminal stream without user % prompting. % \end{variable} % % -% \subsection{Internal functions} +% \end{documentation} % -% \begin{function}{\iow_long_expanded_aux:w} -% Function used to implement immediate writing where a new line is -% started at every blank. -% \end{function} -% -% \begin{function}{% -% \tex_read:D | -% \tex_immediate:D | -% \tex_closeout:D | -% \tex_openin:D | -% \tex_openout:D | -% } -% These are the functions of the primitive interface to \TeX. -% \begin{texnote} -% The \TeX{} primitives \tn{read}, \tn{immediate}, \tn{closeout}, -% \tn{openin}, and \tn{openout} are all renamed and should not be used -% by a programmer since the functionality is covered by the \LaTeX3 -% functions above. -% \end{texnote} -% \end{function} -% -% \StopEventually{} +% \begin{implementation} % -% \subsection{The Implementation} +% \section{\pkg{l3io} implementation} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} -%\ProvidesExplPackage -% {\filename}{\filedate}{\fileversion}{\filedescription} -%\RequirePackage{l3chk}\par -%\RequirePackage{l3toks}\par +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +% %<*initex|package> % \end{macrocode} % @@ -305,27 +335,25 @@ % (for write) as module names. e.g.\ |\c_ior_test_stream| is an input stream % variable called `test'. % -% \subsubsection{Output streams} +% \subsection{Output streams} % -% \begin{macro}{\iow_new:N} -% \begin{macro}{\iow_new:c} +% \begin{macro}{\iow_new:N,\iow_new:c} % Allocation of new output streams is done by these functions. % As we currently do not distribute a new allocation module we nick % the |\newwrite| function. % \begin{macrocode} %<*initex> \alloc_setup_type:nnn {iow} \c_zero \c_sixteen -\def_new:Npn \iow_new:N #1 {\alloc_reg:NnNN g {iow} \tex_chardef:D #1} +\cs_new_nopar:Npn \iow_new:N #1 {\alloc_reg:NnNN g {iow} \tex_chardef:D #1} % -%\let:NN \iow_new:N \newwrite -\def_new:Npn \iow_new:c {\exp_args:Nc \iow_new:N} +%<*package> +\cs_set_eq:NN \iow_new:N \newwrite +% +\cs_generate_variant:Nn \iow_new:N {c} % \end{macrocode} % \end{macro} -% \end{macro} -% % -% \begin{macro}{\iow_open:Nn} -% \begin{macro}{\iow_open:cn} +% \begin{macro}{\iow_open:Nn,\iow_open:cn} % To open streams for reading or writing the following two functions % are provided. The streams are opened immediately. % @@ -334,110 +362,99 @@ % We have to check whether this is also necessary in case of % |\tex_openin:D|. % \begin{macrocode} -\def_new:Npn \iow_open:Nn #1#2{\iow_close:N #1 - \tex_immediate:D\tex_openout:D#1#2\scan_stop:} -\def_new:Npn \iow_open:cn {\exp_args:Nc \iow_open:Nn} +\cs_new_nopar:Npn \iow_open:Nn #1#2 { + \iow_close:N #1 + \tex_immediate:D \tex_openout:D #1#2 \scan_stop: +} +\cs_generate_variant:Nn \iow_open:Nn {c} % \end{macrocode} % \end{macro} -% \end{macro} -% % % \begin{macro}{\iow_close:N} % Since we close output streams prior to opening, a separate closing % operation is probably not necessary. But here it is, just in % case\ldots. Actually you will need this if you intend to write -% and then read in the same pass from some stream. +% and then read in the same pass from a stream. % \begin{macrocode} -\def_new:Npn \iow_close:N {\tex_immediate:D\tex_closeout:D} +\cs_new_nopar:Npn \iow_close:N { \tex_immediate:D \tex_closeout:D } % \end{macrocode} % \end{macro} % % -% \begin{macro}{\c_io_term_stream} -% \begin{macro}{\c_iow_log_stream} +% \begin{macro}{\c_iow_term_stream,\c_ior_term_stream} +% \begin{macro}{\c_iow_log_stream,\c_ior_log_stream} % Here we allocate two output streams for writing to the transcript % file only (|\c_iow_log_stream|) and to both the terminal and transcript -% file (|\c_io_term_stream|). The latter can also be used to read -% from therefore it is called |..io_..|. +% file (|\c_iow_term_stream|). Both can be used to read from and have +% equivalent "\c_ior" versions. % \begin{macrocode} -\let_new:NN \c_io_term_stream \c_sixteen -\let_new:NN \c_iow_log_stream \c_minus_one +\cs_new_eq:NN \c_iow_term_stream \c_sixteen +\cs_new_eq:NN \c_ior_term_stream \c_sixteen +\cs_new_eq:NN \c_iow_log_stream \c_minus_one +\cs_new_eq:NN \c_ior_log_stream \c_minus_one % \end{macrocode} % \end{macro} % \end{macro} % % \paragraph{Immediate writing} % -% \begin{macro}{\iow_expanded:Nn} +% \begin{macro}{\iow_now:Nx} % An abbreviation for an often used operation, which immediately -% writes its second argument to the output stream. +% writes its second argument expanded to the output stream. % \begin{macrocode} -\def_new:Npn \iow_expanded:Nn {\tex_immediate:D\iow_deferred_expanded:Nn} +\cs_new_nopar:Npn \iow_now:Nx { \tex_immediate:D \iow_shipout_x:Nn } % \end{macrocode} % \end{macro} % -% \begin{macro}{\iow_unexpanded:Nn} -% This routine writes the second argument verbatim onto the output -% stream. If this stream isn't open, the output goes to the terminal. +% \begin{macro}{\iow_now:Nn} +% This routine writes the second argument onto the output +% stream without expansion. If this stream isn't open, the output goes to +% the terminal instead. % If the first argument is no output stream at all, we get an % internal error. % \begin{macrocode} -\def_new:Npn \iow_unexpanded:Nn #1#2{ - \iow_expanded:Nn #1{\exp_not:n{#2}}} +\cs_new_nopar:Npn \iow_now:Nn #1#2 { + \iow_now:Nx #1 { \exp_not:n {#2} } +} % \end{macrocode} % \end{macro} % % -% \begin{macro}{\iow_expanded_log:n} -% \begin{macro}{\iow_expanded_term:n} +% \begin{macro}{\iow_log:n,\iow_log:x,\iow_term:n,\iow_term:x} % Now we redefine two functions for which we needed a definition -% very early on. They both write their second argument fully -% expanded to the output stream. +% very early on. % \begin{macrocode} -\def:Npn \iow_expanded_log:n {\iow_expanded:Nn \c_iow_log_stream} -\def:Npn \iow_expanded_term:n{\iow_expanded:Nn \c_io_term_stream} +\cs_set_nopar:Npn \iow_log:x { \iow_now:Nx \c_iow_log_stream } +\cs_new_nopar:Npn \iow_log:n { \iow_now:Nn \c_iow_log_stream } +\cs_set_nopar:Npn \iow_term:x { \iow_now:Nx \c_iow_term_stream } +\cs_new_nopar:Npn \iow_term:n { \iow_now:Nn \c_iow_term_stream } % \end{macrocode} -% The second one isn't exactly equivalent to the old |\typeout| since +% "\iow_term:x" isn't exactly equivalent to the old |\typeout| since % we need to control expansion in the function we provide for the user. % \end{macro} -% \end{macro} - -% \begin{macro}{\iow_unexpanded_term:n} -% This function writes its argument verbatim to the the terminal. -% \begin{macrocode} -\def_new:Npn \iow_unexpanded_term:n {\iow_unexpanded:Nn \c_io_term_stream} -% \end{macrocode} -% \end{macro} % % -% \begin{macro}{\iow_unexpanded_if_avail:Nn} -% \begin{macro}{\iow_unexpanded_if_avail:cn} -% |\iow_unexpanded_if_avail:Nn | \m{stream} \m{code}. This routine writes +% \begin{macro}{\iow_now_when_avail:Nn,\iow_now_when_avail:cn} +% |\iow_now_when_avail:Nn | \m{stream} \m{code}. This routine writes % its second argument unexpanded to the stream given by the first % argument, provided that this stream was opened for writing. Note, % that |#| characters get doubled within \m{code}. -% \begin{macrocode} -\def_new:Npn \iow_unexpanded_if_avail:Nn #1{ -% \end{macrocode} +% % In this routine we have to check whether or not the output stream % that was requested is defined at all. % So we check if the name is still free. +% % \begin{macrocode} - \cs_free:NTF #1\use_none:n {\iow_unexpanded:Nn #1}} -% \end{macrocode} -% Note: the next function could be streamlined for speed if we use -% the faster |\cs_free:cTF|. (space viz time). -% \begin{macrocode} -\def_new:Npn \iow_unexpanded_if_avail:cn { - \exp_args:Nc \iow_unexpanded_if_avail:Nn } +\cs_new_nopar:Npn \iow_now_when_avail:Nn #1 { + \cs_if_free:NTF #1 {\use_none:n} {\iow_now:Nn #1} +} +\cs_generate_variant:Nn \iow_now_when_avail:Nn {c} % \end{macrocode} % \end{macro} -% \end{macro} % % -% \begin{macro}{\iow_long_expanded:Nn} -% \begin{macro}{\iow_long_unexpanded:Nn} -% \begin{macro}{\iow_long_expanded_aux:w} +% \begin{macro}{\iow_now_buffer_safe:Nn,\iow_now_buffer_safe:Nx} +% \begin{macro}[aux]{\iow_now_buffer_safe_expanded_aux:w} % Another type of writing onto an output stream is used for % potentially long token sequences. We break the output lines at % every blank in the second argument. This avoids the problem of @@ -448,61 +465,42 @@ % But this can happen only if things like % two spaces find their way into the second argument. % Usually, multiple spaces are removed by \TeX's scanner. -% % \begin{macrocode} -\def_new:Npn \iow_long_expanded_aux:w #1#2#3{ - \group_begin:\tex_newlinechar:D`\ #1#2{#3}\group_end:} -\def_new:Npn \iow_long_expanded:Nn {\iow_long_expanded_aux:w - \iow_expanded:Nn} -\def_new:Npn \iow_long_unexpanded:Nn {\iow_long_expanded_aux:w - \iow_unexpanded:Nn} +\cs_new_nopar:Npn \iow_now_buffer_safe_aux:w #1#2#3 { + \group_begin: \tex_newlinechar:D`\ #1#2{#3} \group_end: +} +\cs_new_nopar:Npn \iow_now_buffer_safe:Nx { + \iow_now_buffer_safe_aux:w \iow_now:Nx +} +\cs_new_nopar:Npn \iow_now_buffer_safe:Nn { + \iow_now_buffer_safe_aux:w \iow_now:Nn +} % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % % % \paragraph{Deferred writing} -% -% With \eTeX\ available deferred writing is easy. The comments below -% are old. % -% Deferred writing to output streams is a bit more complicated because -% there seems to be no nice hack for writing unexpanded. The only -% relatively sure bet is to use |\token_to_meaning:N| expansion of some token -% list. That's the way the following functions are implemented. -% -% Another possibility would be to reserve a certain number of scratch -% token registers that could be used to hold the tokens until after the -% next |\tex_shipout:D|. But such an approach would probably fail because of -% the limited number of available token registers that would need to -% be reserved for this special application. -% -% -% \begin{macro}{\iow_deferred_expanded:Nn} -% First the easy part, this is the primitive. +% \begin{macro}{\iow_shipout_x:Nn,\iow_shipout_x:Nx} +% First the easy part, this is the primitive. % \begin{macrocode} -\let:NN \iow_deferred_expanded:Nn \tex_write:D +\cs_set_eq:NN \iow_shipout_x:Nn \tex_write:D +\cs_generate_variant:Nn \iow_shipout_x:Nn {Nx} % \end{macrocode} % \end{macro} % -% -% \begin{macro}{\iow_deferred_unexpanded:Nn} -% Now the harder part: +% \begin{macro}{\iow_shipout:Nn,\iow_shipout:Nx} +% With \eTeX\ available deferred writing is easy. % \begin{macrocode} -\def_new:Npn \iow_deferred_unexpanded:Nn #1#2{ - \iow_deferred_expanded:Nn{\exp_not:n{#2}} +\cs_new_nopar:Npn \iow_shipout:Nn #1#2{ + \iow_shipout_x:Nn #1 { \exp_not:n {#2} } } -%% Old implementation: -%\def_new:Npn \iow_deferred_unexpanded:Nn #1#2{ -% \tlp_set:Nn \l_tmpa_tlp {#2} -% \tlp_set:Nx \l_tmpb_tlp -% {\iow_deferred_expanded:Nn #1{\tlp_to_str:N \l_tmpa_tlp}} -% \l_tmpb_tlp} +\cs_generate_variant:Nn \iow_shipout:Nn {Nx} % \end{macrocode} % \end{macro} % -% Long forms of these functions are not possible since the deferred +% `Buffer safe' forms of these functions are not possible since the deferred % writing will restore the value of |\tex_newlinechar:D| before it will have % a chance to act. But on the other hand it is nevertheless possible % to make all deferred writes long by setting the |\tex_newlinechar:D| @@ -515,33 +513,52 @@ % % \begin{macro}{\iow_newline:} % Global variable holding the character that forces a new line when -% something is written to an output stream. +% something is written to an output stream. +% \begin{macrocode} +\cs_new_nopar:Npn \iow_newline: {^^J} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\iow_space:} +% Global variable holding the character that inserts a space char when +% writing to an output stream. +% \begin{macrocode} +\cs_new_nopar:Npn \iow_space: {~} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\iow_char:N} +% Function to write any escaped char to an output stream. % \begin{macrocode} -\def_new:Npn \iow_newline: {^^J} +\cs_new:Nn \iow_char:N { \cs_to_str:N #1 } % \end{macrocode} % \end{macro} % +% % \begin{macro}{\c_iow_comment_char} % \begin{macro}{\c_iow_lbrace_char} % \begin{macro}{\c_iow_rbrace_char} +% TODO: remove these in favour of "\iow_char:N" (Will, Apr 2009) +% % We also need to be able to write braces and the comment character. We % achieve this by defining global constants to expand into a version of % these characters with |\tex_catcode:D|${}=12$. % \begin{macrocode} -\tlp_new:Nx \c_iow_comment_char {\cs_to_str:N\%} +\tl_new:Nx \c_iow_comment_char {\cs_to_str:N\%} % \end{macrocode} % To avoid another allocation function which is probably only -% necessary here we use the |\def:Npx| command directly. +% necessary here we use the |\cs_set_nopar:Npx| command directly. % \begin{macrocode} -\tlp_new:Nx \c_iow_lbrace_char{\cs_to_str:N\{} -\tlp_new:Nx \c_iow_rbrace_char{\cs_to_str:N\}} +\tl_new:Nx \c_iow_lbrace_char{\cs_to_str:N\{} +\tl_new:Nx \c_iow_rbrace_char{\cs_to_str:N\}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % -% \subsubsection{Input streams} +% \subsection{Input streams} % % \begin{macro}{\ior_new:N} % Allocation of new input streams is done by this function. @@ -550,100 +567,79 @@ % \begin{macrocode} %<*initex> \alloc_setup_type:nnn {ior} \c_zero \c_sixteen -\def_new:Npn \ior_new:N #1 {\alloc_reg:NnNN g {ior} \tex_chardef:D #1} +\cs_new_nopar:Npn \ior_new:N #1 {\alloc_reg:NnNN g {ior} \tex_chardef:D #1} % -%\let:NN \ior_new:N \newread +%\cs_set_eq:NN \ior_new:N \newread % \end{macrocode} % \end{macro} % % \begin{macro}{\ior_open:Nn} -% \begin{macro}{\ior_close:Nn} +% \begin{macro}{\ior_close:N} % Processing of input-streams (via |\tex_openin:D| and |closein|) is % always `immediate' as far as \TeX{} is concerned. An extra % |\tex_immediate:D| is silently ignored. % \begin{macrocode} -\let:NN \ior_close:N \tex_closein:D -\def_new:Npn \ior_open:Nn #1#2{\ior_close:N #1\scan_stop: - \tex_openin:D#1#2\scan_stop:} +\cs_set_eq:NN \ior_close:N \tex_closein:D +\cs_new_nopar:Npn \ior_open:Nn #1#2 { + \ior_close:N #1 \scan_stop: + \tex_openin:D #1#2 \scan_stop: +} % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\ior_eof:NTF} -% |\ior_eof:NTF | \m{stream} \m{true case} \m{false case}. To -% test if some particular input stream is exhausted the following -% conditional is provided: +% +% \begin{macro}{\if_eof:w} % \begin{macrocode} -\def_new:Npn \ior_eof:NTF #1{\if_eof:w#1 - \exp_after:NN\use_arg_i:nn \else: - \exp_after:NN\use_arg_ii:nn \fi:} +\cs_new_eq:NN \if_eof:w \tex_ifeof:D % \end{macrocode} % \end{macro} % -% \begin{macro}{\ior_eof:NF} -% \begin{macro}{\if_eof:w} -% |\ior_eof:NF | \m{stream} \m{false case}. Do something if -% if there is still something to read from this file: +% +% \begin{macro}{\ior_if_eof_p:N} +% \begin{macro}[TF]{\ior_if_eof:N} +% |\ior_if_eof:NTF | \m{stream} \m{true case} \m{false case}. To +% test if some particular input stream is exhausted the following +% conditional is provided: % \begin{macrocode} -\let:NN \if_eof:w \tex_ifeof:D -\def_new:Npn \ior_eof:NF #1{\if_eof:w#1 - \exp_after:NN \use_none:nn \fi: \use_arg_i:n} +\prg_new_conditional:Nnn \ior_if_eof:N {p,TF,T,F} { + \tex_ifeof:D #1 \prg_return_true: \else: \prg_return_false: \fi: +} % \end{macrocode} % \end{macro} % \end{macro} % % +% % \begin{macro}{\ior_to:NN} % \begin{macro}{\ior_gto:NN} % And here we read from files. % \begin{macrocode} -%<*check> -\def_new:Npn \ior_to:NN #1#2{\tex_read:D#1to#2 - \chk_local_or_pref_global:N #2} -% -%<-check> \def_new:Npn \ior_to:NN #1{\tex_read:D#1to} -\def_new:Npn \ior_gto:NN { -%<*check> - \pref_global_chk: -% -%<-check> \pref_global:D - \ior_to:NN} +\cs_new_nopar:Npn \ior_to:NN #1#2 { + \tex_read:D #1 to #2 +% \chk_local_or_pref_global:N #2 +} +\cs_new_nopar:Npn \ior_gto:NN { +%<+check> \pref_global_chk: +%<-check> \pref_global:D + \ior_to:NN +} % \end{macrocode} % \end{macro} % \end{macro} % +% \begin{macrocode} +% +% \end{macrocode} % % Show token usage: % \begin{macrocode} -% %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.16 2006/03/20 18:26:36 braams -% Updated the copyright notice (2006) and demoted all implementation -% sections to subsections and so on to clean up the toc for source3.tex -% -% Revision 1.15 2005/12/27 09:51:27 morten -% Changed the use of RCS information -% -% Revision 1.14 2005/11/07 17:59:48 morten -% Fixed definition of \iow_newline: (moved it to the right place) -% -% Revision 1.13 2005/04/29 22:29:23 braams -% Replaced the undefined \g_iow_newline_code with \tex_newlinechar:D -% and added the definition for \iow_newline: -% -% Revision 1.12 2005/04/06 22:35:37 braams -% Now we have register allocation fitted -% -% Revision 1.11 2005/03/16 22:36:24 braams -% Added the tweaks necessary to be able to load with initex -% -% Revision 1.10 2005/03/11 21:39:10 braams -% Fixed the use of RCS information; added \StopEventually +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3keyval.dtx b/Master/texmf-dist/source/latex/expl3/l3keyval.dtx index 4134b0fef51..8ac747e5d0a 100644 --- a/Master/texmf-dist/source/latex/expl3/l3keyval.dtx +++ b/Master/texmf-dist/source/latex/expl3/l3keyval.dtx @@ -1,5 +1,5 @@ % \iffalse -%% File: l3keyval.dtx Copyright (C) 2006 LaTeX3 project +%% File: l3keyval.dtx Copyright (C) 2006-2009 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -17,7 +17,7 @@ %% %% The development version of the bundle can be found at %% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% @@ -35,7 +35,7 @@ \RequirePackage{l3names} % %\fi -\GetIdInfo$Id: l3keyval.dtx 621 2007-09-01 20:14:19Z morten $ +\GetIdInfo$Id: l3keyval.dtx 1362 2009-05-28 20:19:21Z joseph $ {L3 Experimental keyval processing} %\iffalse %<*driver> @@ -43,9 +43,9 @@ \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse -\documentclass{l3doc} +\documentclass[full]{l3doc} \begin{document} -\DocInput{\filename.\filenameext} +\DocInput{l3keyval.dtx} \end{document} % % \fi @@ -59,6 +59,8 @@ % \date{\filedate} % \maketitle % +% \begin{documentation} +% % \section{Introduction} % % Currently, this module only provides functions for extracting keys @@ -109,16 +111,13 @@ % two functions before starting the parsing process. % % -% \subsection{Functions} -% -% -% +% \section{Functions} % % \begin{function}{ % \KV_parse_no_space_removal_no_sanitize:n | % } % \begin{syntax} -% "\KV_parse_no_space_removal_no_sanitize:n" "{""}" +% "\KV_parse_no_space_removal_no_sanitize:n" \Arg{keyval list} % \end{syntax} % Parses the keys and values literally. For use when spaces are % ignored and |=| and |,| have normal catcodes. @@ -128,7 +127,7 @@ % \KV_parse_space_removal_no_sanitize:n | % } % \begin{syntax} -% "\KV_parse_space_removal_no_sanitize:n" "{""}" +% "\KV_parse_space_removal_no_sanitize:n" \Arg{keyval list} % \end{syntax} % As above but also removes spaces around keys and values. For use % when spaces are not ignored. @@ -138,7 +137,7 @@ % \KV_parse_space_removal_sanitize:n | % } % \begin{syntax} -% "\KV_parse_space_removal_sanitize:n" "{""}" +% "\KV_parse_space_removal_sanitize:n" \Arg{keyval list} % \end{syntax} % As above but additionally also replaces top-level active |=| and % |,| with harmless versions. @@ -166,43 +165,91 @@ % \KV_key_value_elt:nn | % } % \begin{syntax} -% "\KV_key_no_value_elt:n" "{""}" \\ -% "\KV_key_value_elt:n" "{""}" "{""}" +% "\KV_key_no_value_elt:n" \Arg{key} \\ +% "\KV_key_value_elt:n" \Arg{key} \Arg{value} % \end{syntax} % Functions returned by the |\KV_parse_| functions. The default % definition of these two functions is an error message! % \end{function} % +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3keyval} implementation} +% +% \subsection{Internal functions and variables} +% +% \begin{variable}{ \l_KV_tmpa_tl | \l_KV_tmpb_tl | +% \c_KV_single_equal_sign_tl | +% \l_KV_parse_toks | \l_KV_currkey_toks | +% \l_KV_currval_toks } +% Token list variables and token registers used internally. +% \end{variable} +% +% \begin{function}{ \KV_sanitize_outerlevel_active_equals:N | +% \KV_sanitize_outerlevel_active_commas:N } +% \begin{syntax} +% "\KV_sanitize_outerlevel_active_equals:N" +% \end{syntax} +% Replaces catcode other "=" and "," within a with active characters. +% \end{function} +% +% \begin{function}{ \KV_remove_surrounding_spaces:nw | +% \KV_remove_surrounding_spaces_auxi:w / (EXP) } +% \begin{syntax} +% +% "\KV_remove_surrounding_spaces:nw" "\q_nil" +% "\KV_remove_surrounding_spaces_auxi:w" \verb*" Q"$\sb3$ +% \end{syntax} +% Removes a possible +% leading space plus a possible ending space from a . +% The first version (which is not used in the code) stores it in . +% \end{function} % -% \StopEventually{} +% \begin{function}{ \KV_add_value_element:w | \KV_set_key_element:w } +% \begin{syntax} +% "\KV_set_key_element:w" "\q_nil" +% "\KV_add_value_element:w" "\q_stop" "\q_nil" +% \end{syntax} +% Specialised functions to strip spaces from their input and set the +% token registers "\l_KV_currkey_toks" or "\l_KV_currval_toks" +% respectively. +% \end{function} % -% \section{Implementation} +% \begin{function}{ \KV_split_key_value_current:w | +% \KV_split_key_value_space_removal:w | +% \KV_split_key_value_space_removal_detect_error:wTF | +% \KV_split_key_value_no_space_removal:w } +% \begin{syntax} +% "\KV_split_key_value_current:w" \dots +% \end{syntax} +% These functions split keyval lists into chunks depending which +% sanitising method is being used. "\KV_split_key_value_current:w" is "\cs_set_eq:NN" +% to whichever is appropriate. +% \end{function} % +% \subsection{Module code} % % We start by ensuring that the required packages are loaded. % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} -\RequirePackage{l3quark} -\RequirePackage{l3toks} -\RequirePackage{l3int} -\RequirePackage{l3token} +\package_check_loaded_expl: % %<*initex|package> % \end{macrocode} % % -% -% -% \begin{macro}{\l_KV_tmpa_tlp} -% \begin{macro}{\l_KV_tmpb_tlp} -% \begin{macro}{\c_KV_single_equal_sign_tlp} +% \begin{macro}{\l_KV_tmpa_tl} +% \begin{macro}{\l_KV_tmpb_tl} +% \begin{macro}{\c_KV_single_equal_sign_tl} % Various useful things. % \begin{macrocode} -\tlp_new:Nn\l_KV_tmpa_tlp{} -\tlp_new:Nn\l_KV_tmpb_tlp{} -\tlp_new:Nn \c_KV_single_equal_sign_tlp{=} +\tl_new:N \l_KV_tmpa_tl +\tl_new:N \l_KV_tmpb_tl +\tl_new:Nn \c_KV_single_equal_sign_tl{=} % \end{macrocode} % \end{macro} % \end{macro} @@ -240,12 +287,12 @@ \char_set_catcode:nn{`\,}{13} \char_set_lccode:nn{`\8}{`\=} \char_set_lccode:nn{`\9}{`\,} -\tlist_to_lowercase:n{\group_end: -\def_new:Npn \KV_sanitize_outerlevel_active_equals:N #1{ - \tlp_replace_all_in:Nnn #1 = 8 +\tl_to_lowercase:n{\group_end: +\cs_new_nopar:Npn \KV_sanitize_outerlevel_active_equals:N #1{ + \tl_replace_all_in:Nnn #1 = 8 } -\def_new:Npn \KV_sanitize_outerlevel_active_commas:N #1{ - \tlp_replace_all_in:Nnn #1 , 9 +\cs_new_nopar:Npn \KV_sanitize_outerlevel_active_commas:N #1{ + \tl_replace_all_in:Nnn #1 , 9 } } % \end{macrocode} @@ -258,10 +305,10 @@ % % \begin{macro}{\KV_remove_surrounding_spaces:nw} % \begin{macro}{\KV_remove_surrounding_spaces_auxi:w} -% \begin{macro}{\KV_remove_surrounding_spaces_auxii:w} +% \begin{macro}[aux]{\KV_remove_surrounding_spaces_auxii:w} % \begin{macro}{\KV_set_key_element:w} -% \begin{macro}{\KV_set_value_element:w} -% The macro |\KV_remove_surrounding_spaces:Nw| removes a possible +% \begin{macro}{\KV_add_value_element:w} +% The macro |\KV_remove_surrounding_spaces:nw| removes a possible % leading space plus a possible ending space from its second % argument and stores it in the token register |#1|. % @@ -274,7 +321,7 @@ \char_set_catcode:nn{`\Q}{3} % \end{macrocode} % \begin{macrocode} -\gdef_long_new:Npn\KV_remove_surrounding_spaces:nw#1#2\q_nil{ +\cs_gnew:Npn\KV_remove_surrounding_spaces:nw#1#2\q_nil{ % \end{macrocode} % The idea in this processing is to use a Q with strange catcode to % remove a trailing space. But first, how to get this expansion going? @@ -312,7 +359,7 @@ % |\KV_remove_surrounding_spaces_auxii:w| to work properly we need to % put back a Q first. % \begin{macrocode} -\gdef_long_new:Npn\KV_remove_surrounding_spaces_auxi:w#1~Q{ +\cs_gnew:Npn\KV_remove_surrounding_spaces_auxi:w#1~Q{ \KV_remove_surrounding_spaces_auxii:w #1 Q } % \end{macrocode} @@ -320,39 +367,41 @@ % taken care of by the function used to initiate the expansion. Simply % return the argument before the funny Q. % \begin{macrocode} -\gdef_long_new:Npn\KV_remove_surrounding_spaces_auxii:w#1Q#2{#1} +\cs_gnew:Npn\KV_remove_surrounding_spaces_auxii:w#1Q#2{#1} % \end{macrocode} +% % Here are some specialized versions of the above. They do exactly % what we want in one go. First trim spaces from the value and then % put the result surrounded in braces onto |\l_KV_parse_toks|. % \begin{macrocode} -\gdef_long_new:Npn\KV_add_value_element:w\q_stop#1\q_nil{ +\cs_gnew:Npn\KV_add_value_element:w\q_stop#1\q_nil{ \toks_set:Nf\l_KV_currval_toks { \KV_remove_surrounding_spaces_auxi:w \exp_not:N#1Q~Q } \toks_put_right:No\l_KV_parse_toks{ - \exp_after:NN {\toks_use:N \l_KV_currval_toks} + \exp_after:wN {\toks_use:N \l_KV_currval_toks} } } % \end{macrocode} % When storing the key we firstly remove spaces plus the prepended % |\q_no_value|. % \begin{macrocode} -\gdef_long_new:Npn\KV_set_key_element:w#1\q_nil{ +\cs_gnew:Npn\KV_set_key_element:w#1\q_nil{ \toks_set:Nf\l_KV_currkey_toks { - \exp_after:NN\KV_remove_surrounding_spaces_auxi:w - \exp_after:NN\exp_not:N\use_none:n #1Q~Q + \exp_last_unbraced:NNo \KV_remove_surrounding_spaces_auxi:w + \exp_not:N \use_none:n #1Q~Q } % \end{macrocode} % Afterwards we gobble an extra level of braces if that's what we are -% asked to do. +% asked to do. The next part can be done using \cs{toks_set:Nd}, but +% this might not be around for long. % \begin{macrocode} \bool_if:NT \l_KV_remove_one_level_of_braces_bool { - \toks_set:Nd \l_KV_currkey_toks{ - \exp_after:NN \KV_add_element_aux:w - \toks_use:N \l_KV_currkey_toks \q_nil + \exp_args:NNo \toks_set:No \l_KV_currkey_toks { + \exp_after:wN \KV_add_element_aux:w + \toks_use:N \l_KV_currkey_toks \q_nil } } } @@ -364,10 +413,10 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\KV_add_element_aux:w} +% \begin{macro}[aux]{\KV_add_element_aux:w} % A helper function for fixing braces around keys and values. % \begin{macrocode} -\def_long_new:Npn \KV_add_element_aux:w#1\q_nil{#1} +\cs_new:Npn \KV_add_element_aux:w#1\q_nil{#1} % \end{macrocode} % \end{macro} % @@ -375,57 +424,58 @@ % Parse a list of keyvals, put them into list form with entries like % |\KV_key_no_value_elt:n{key1}| and |\KV_key_value_elt:nn{key2}{val2}|. % -% \begin{macro}{\KV_parse_sanitize_aux:n} +% \begin{macro}[aux]{\KV_parse_sanitize_aux:n} % The slow parsing algorithm sanitizes active commas and equal signs % at the top level first. Then uses |#1| as inspector of each % element in the comma list. % \begin{macrocode} -\def_long_new:Npn \KV_parse_sanitize_aux:n #1{ +\cs_new:Npn \KV_parse_sanitize_aux:n #1 { \group_begin: - \toks_clear:N \l_KV_parse_toks - \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:n{#1}} - \KV_sanitize_outerlevel_active_equals:N\l_KV_tmpa_tlp - \KV_sanitize_outerlevel_active_commas:N\l_KV_tmpa_tlp - \exp_after:NN \KV_parse_elt:w \exp_after:NN\q_no_value \l_KV_tmpa_tlp,\q_nil, + \toks_clear:N \l_KV_parse_toks + \tl_set:Nx \l_KV_tmpa_tl { \exp_not:n {#1} } + \KV_sanitize_outerlevel_active_equals:N \l_KV_tmpa_tl + \KV_sanitize_outerlevel_active_commas:N \l_KV_tmpa_tl + \exp_last_unbraced:NNV \KV_parse_elt:w \q_no_value + \l_KV_tmpa_tl , \q_nil , % \end{macrocode} % We evaluate the parsed keys and values outside the group so the % token register is restored to its previous value. % \begin{macrocode} - \exp_after:NN\group_end: - \toks_use:N \l_KV_parse_toks + \exp_last_unbraced:NV \group_end: + \l_KV_parse_toks } % \end{macrocode} % \end{macro} % % -% \begin{macro}{\KV_parse_no_sanitize_aux:n} +% \begin{macro}[aux]{\KV_parse_no_sanitize_aux:n} % Like above but we don't waste time sanitizing. This is probably % the one we will use for preamble parsing where catcodes of |=| and % |,| are as expected! % \begin{macrocode} -\def_long_new:Npn \KV_parse_no_sanitize_aux:n #1{ +\cs_new:Npn \KV_parse_no_sanitize_aux:n #1{ \group_begin: - \toks_clear:N \l_KV_parse_toks - \KV_parse_elt:w \q_no_value #1,\q_nil, - \exp_after:NN\group_end: - \toks_use:N \l_KV_parse_toks + \toks_clear:N \l_KV_parse_toks + \KV_parse_elt:w \q_no_value #1 , \q_nil , + \exp_last_unbraced:NV \group_end: + \l_KV_parse_toks } % \end{macrocode} % \end{macro} % % -% \begin{macro}{\KV_parse_elt:w} +% \begin{macro}[aux]{\KV_parse_elt:w} % This function will always have a |\q_no_value| stuffed in as the % rightmost token in |#1|. In case there was a blank entry in the % comma separated list we just run it again. The |\use_none:n| makes % sure to gobble the quark |\q_no_value|. A similar test is made to % check if we hit the end of the recursion. % \begin{macrocode} -\def_long:Npn \KV_parse_elt:w #1,{ - \tlist_if_blank:oTF{\use_none:n #1} +\cs_set:Npn \KV_parse_elt:w #1,{ + \tl_if_blank:oTF{\use_none:n #1} { \KV_parse_elt:w \q_no_value } { - \quark_if_nil:oF {\use_arg_ii:nn #1 } + \quark_if_nil:oF {\use_ii:nn #1 } % \end{macrocode} % If we made it to here we can start parsing the key and value. When % done try, try again. @@ -443,7 +493,7 @@ % \begin{macro}{\KV_split_key_value_current:w} % The function called to split the keys and values. % \begin{macrocode} -\let_new:NN \KV_split_key_value_current:w \ERROR +\cs_new:Npn \KV_split_key_value_current:w {\ERROR} % \end{macrocode} % \end{macro} % @@ -462,7 +512,7 @@ % % \begin{macro}{\KV_split_key_value_space_removal:w} % \begin{macro}{\KV_split_key_value_space_removal_detect_error:wTF} -% \begin{macro}{\KV_split_key_value_space_removal_aux:w} +% \begin{macro}[aux]{\KV_split_key_value_space_removal_aux:w} % The code below removes extraneous spaces around the keys and % values plus one set of braces around the entire value. % @@ -474,7 +524,7 @@ % this is slightly more tedious (but only slightly) but at least it % always removes only one level of braces. % \begin{macrocode} -\def_long_new:Npn \KV_split_key_value_space_removal:w #1 = #2\q_nil{ +\cs_new:Npn \KV_split_key_value_space_removal:w #1 = #2\q_nil{ % \end{macrocode} % First grab the key. % \begin{macrocode} @@ -483,15 +533,15 @@ % Then we start checking. If only a key was entered, |#2| contains % |=| and nothing else, so we test for that first. % \begin{macrocode} - \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:n{#2}} - \tlp_if_eq:NNTF\l_KV_tmpa_tlp\c_KV_single_equal_sign_tlp + \tl_set:Nx\l_KV_tmpa_tl{\exp_not:n{#2}} + \tl_if_eq:NNTF\l_KV_tmpa_tl\c_KV_single_equal_sign_tl % \end{macrocode} % Then we just insert the default key. % \begin{macrocode} { \toks_put_right:No\l_KV_parse_toks{ - \exp_after:NN \KV_key_no_value_elt:n - \exp_after:NN {\toks_use:N\l_KV_currkey_toks} + \exp_after:wN \KV_key_no_value_elt:n + \exp_after:wN {\toks_use:N\l_KV_currkey_toks} } } % \end{macrocode} @@ -510,9 +560,9 @@ % \end{macrocode} % The error test. % \begin{macrocode} -\def_long_new:Npn +\cs_new:Npn \KV_split_key_value_space_removal_detect_error:wTF#1=#2#3\q_nil{ - \tlist_if_head_eq_meaning:nNTF{#3}\q_no_value + \tl_if_head_eq_meaning:nNTF{#3}\q_no_value } % \end{macrocode} % Now we can start extracting the value. Recall that |#1| here starts @@ -521,18 +571,18 @@ % is empty or blank, all three quarks are gobbled. If |#1| consists of % exactly one token or brace group, only the latter quark is left. % \begin{macrocode} -\def_long_new:Npn \KV_val_preserve_braces:NnN #1#2#3{{#2}} -\def_long_new:Npn\KV_split_key_value_space_removal_aux:w #1=={ - \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:o{\use_none:nnn#1\q_nil\q_nil}} +\cs_new:Npn \KV_val_preserve_braces:NnN #1#2#3{{#2}} +\cs_new:Npn\KV_split_key_value_space_removal_aux:w #1=={ + \tl_set:Nx\l_KV_tmpa_tl{\exp_not:o{\use_none:nnn#1\q_nil\q_nil}} \toks_put_right:No\l_KV_parse_toks{ - \exp_after:NN \KV_key_value_elt:nn - \exp_after:NN {\toks_use:N\l_KV_currkey_toks} + \exp_after:wN \KV_key_value_elt:nn + \exp_after:wN {\toks_use:N\l_KV_currkey_toks} } % \end{macrocode} -% If there a blank space or nothing at all, |\l_KV_tmpa_tlp| is now +% If there a blank space or nothing at all, |\l_KV_tmpa_tl| is now % completely empty. % \begin{macrocode} - \tlp_if_empty:NTF\l_KV_tmpa_tlp + \tl_if_empty:NTF\l_KV_tmpa_tl % \end{macrocode} % We just put an empty value on the stack. % \begin{macrocode} @@ -540,21 +590,21 @@ { % \end{macrocode} % If there was exactly one brace group or token in |#1|, -% |\l_KV_tmpa_tlp| is now equal to |\q_nil|. Then we can just pick it +% |\l_KV_tmpa_tl| is now equal to |\q_nil|. Then we can just pick it % up as the second argument of |#1|. This will also take care of any % spaces which might surround it. % \begin{macrocode} - \quark_if_nil:NTF\l_KV_tmpa_tlp + \quark_if_nil:NTF\l_KV_tmpa_tl { \bool_if:NTF \l_KV_remove_one_level_of_braces_bool { \toks_put_right:No\l_KV_parse_toks{ - \exp_after:NN{\use_arg_ii:nnn #1\q_nil} + \exp_after:wN{\use_ii:nnn #1\q_nil} } } { \toks_put_right:No\l_KV_parse_toks{ - \exp_after:NN{\KV_val_preserve_braces:NnN #1\q_nil} + \exp_after:wN{\KV_val_preserve_braces:NnN #1\q_nil} } } } @@ -575,14 +625,14 @@ % however fun they may be. Since there are no spaces, a set of % braces around a value is automatically stripped by \TeX. % \begin{macrocode} -\def_long_new:Npn \KV_split_key_value_no_space_removal:w #1#2=#3=#4\q_nil{ - \tlp_set:Nn\l_KV_tmpa_tlp{#4} - \tlp_if_empty:NTF \l_KV_tmpa_tlp +\cs_new:Npn \KV_split_key_value_no_space_removal:w #1#2=#3=#4\q_nil{ + \tl_set:Nn\l_KV_tmpa_tl{#4} + \tl_if_empty:NTF \l_KV_tmpa_tl { \toks_put_right:Nn\l_KV_parse_toks{\KV_key_no_value_elt:n{#2}} } { - \tlp_if_eq:NNTF\c_KV_single_equal_sign_tlp\l_KV_tmpa_tlp + \tl_if_eq:NNTF\c_KV_single_equal_sign_tl\l_KV_tmpa_tl { \toks_put_right:Nn\l_KV_parse_toks{\KV_key_value_elt:nn{#2}{#3}} } @@ -597,8 +647,8 @@ % \begin{macro}{\KV_key_no_value_elt:n} % \begin{macro}{\KV_key_value_elt:nn} % \begin{macrocode} -\def_long_new:Npn \KV_key_no_value_elt:n #1{\ERROR} -\def_long_new:Npn \KV_key_value_elt:nn #1#2{\ERROR} +\cs_new:Npn \KV_key_no_value_elt:n #1{\ERROR} +\cs_new:Npn \KV_key_value_elt:nn #1#2{\ERROR} % \end{macrocode} % \end{macro} % \end{macro} @@ -612,8 +662,8 @@ % version that disallows unmatched conditional and does no space % removal. % \begin{macrocode} -\def_new:Npn \KV_parse_no_space_removal_no_sanitize:n { - \let:NN \KV_split_key_value_current:w \KV_split_key_value_no_space_removal:w +\cs_new_nopar:Npn \KV_parse_no_space_removal_no_sanitize:n { + \cs_set_eq:NN \KV_split_key_value_current:w \KV_split_key_value_no_space_removal:w \KV_parse_no_sanitize_aux:n } % \end{macrocode} @@ -624,15 +674,15 @@ % The other varieties can be defined in a similar manner. For the % version needed at the document level, we can use this one. % \begin{macrocode} -\def_new:Npn \KV_parse_space_removal_sanitize:n { - \let:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w +\cs_new_nopar:Npn \KV_parse_space_removal_sanitize:n { + \cs_set_eq:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w \KV_parse_sanitize_aux:n } % \end{macrocode} % For preamble use by the non-programmer this is probably best. % \begin{macrocode} -\def_new:Npn \KV_parse_space_removal_no_sanitize:n { - \let:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w +\cs_new_nopar:Npn \KV_parse_space_removal_no_sanitize:n { + \cs_set_eq:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w \KV_parse_no_sanitize_aux:n } % \end{macrocode} @@ -642,24 +692,15 @@ % % \begin{macrocode} % +% \end{macrocode} +% +% \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % -% \endinput -% -% $Log$ -% Revision 1.4 2006/07/25 22:38:58 morten -% Removed spurious \exp_after:NN in \KV_add_value_element:w. Sigh. -% -% Revision 1.3 2006/07/25 22:34:03 morten -% Fixed silly bug in \KV_set_key_element:w plus clean-up of code -% -% Revision 1.2 2006/07/25 16:21:30 morten -% Allow values to contain unmatched conditionals such as `val -% \fi:'. Provide option to not strip any braces at all. -% -% Revision 1.1 2006/01/27 10:14:24 morten -% Initial version of keyval parser +% \end{implementation} +% \PrintIndex % +% \endinput diff --git a/Master/texmf-dist/source/latex/expl3/l3messages.dtx b/Master/texmf-dist/source/latex/expl3/l3messages.dtx deleted file mode 100644 index b5ae9e6025f..00000000000 --- a/Master/texmf-dist/source/latex/expl3/l3messages.dtx +++ /dev/null @@ -1,966 +0,0 @@ -% \iffalse -%% File: l3messages.dtx Copyright (C) 1990-2007 LaTeX3 project -%% -%% It may be distributed and/or modified under the conditions of the -%% LaTeX Project Public License (LPPL), either version 1.3c of this -%% license or (at your option) any later version. The latest version -%% of this license is in the file -%% -%% http://www.latex-project.org/lppl.txt -%% -%% This file is part of the ``expl3 bundle'' (The Work in LPPL) -%% and all files in that bundle must be distributed together. -%% -%% The released version of this bundle is available from CTAN. -%% -%% ----------------------------------------------------------------------- -%% -%% The development version of the bundle can be found at -%% -%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ -%% -%% for those people who are interested. -%% -%%%%%%%%%%% -%% NOTE: %% -%%%%%%%%%%% -%% -%% Snapshots taken from the repository represent work in progress and may -%% not work or may contain conflicting material! We therefore ask -%% people _not_ to put them into distributions, archives, etc. without -%% prior consultation with the LaTeX Project Team. -%% -%% ----------------------------------------------------------------------- -% -%<*driver|package> -\RequirePackage{l3names} -% -%\fi -\GetIdInfo$Id: l3messages.dtx 673 2007-09-28 20:50:33Z mittelba $ - {L3 Experimental LaTeX Messages module} -%\iffalse -%<*driver> -%\fi -\ProvidesFile{\filename.\filenameext} - [\filedate\space v\fileversion\space\filedescription] -%\iffalse -\documentclass{l3doc} -\begin{document} -\DocInput{\filename.\filenameext} -\end{document} -% -% \fi -% -% -% \section{Communicating with the user} -% -% Sometimes it is necesary to pass information back to the user -% about what is going on. The information can be just that, -% information, or it can be a warning that something might not -% happen to his expectation. It could also be that something has -% gone awry and that processing can't reliably continue without -% some help from the user. In such a case an error is signalled. -% When things are really bad, processing may have to stop as there -% is no way to enter additional commands that put things right -% again. In such a case we have a fatal error and the \LaTeX\ run -% will be aborted. -% -% \subsection{Displaying the information} -% -% First of all we need a couple of fairly low level functions that -% deal with the job of passing the information to the user. -% -% Real information is usually only written to the log file, while -% warnings are displayed on the screen as well. -% \begin{function}{% -% \err_info:nn | -% \err_warn:nn -% } -% \begin{syntax} -% "\err_info:nn" "{" "}" "{""}" -% \end{syntax} -% The will be written to the log file. When it contains -% the command "\err_newline:" a line break will occur and the new -% line will start with the . The function -% "\err_warn:nn" writes the message to the terminal as well. -% \end{function} -% When an erroneous situation is encountered, a message is -% displayed and the user is given the opportunity to enter some -% additional code in an attempt to put things right. He may first -% ask for some help, in which case some extra text will be -% displayed to him. -% \begin{function}{\err_interrupt:NNw} -% \begin{syntax} -% "\err_interrupt:NNw"