% \iffalse %% File: l3basics.dtx Copyright (C) 1990-1998 LaTeX3 project % %<*dtx> \ProvidesFile{l3basics.dtx} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{l3basics} % \ProvidesFile{l3basics.drv} % \fi % \ProvidesFile{l3basics.dtx} [1998/05/04 v1.0i L3 Experimental basic definitions] % % \iffalse %<*driver> \documentclass{l3doc} \begin{document} \DocInput{l3basics.dtx} \end{document} % % \fi % % \GetFileInfo{l3basics.dtx} % \title{The \textsf{l3basics} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Basic Definitions} % \author{\Team} % \date{\filedate} % \maketitle % % % We start by ensuring that the required packages are loaded. In % this case there is a boot-strapping problem since, to use much of % the code in this file, the `l3expan' package needs to be loaded; % but this file must be loaded first. % \begin{macrocode} %\RequirePackage{l3names}\par % \end{macrocode} % % 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. % % \subsection{Functions} % % \begin{function}{\cs_to_str:N} % \begin{syntax} % "\cs_to_str:N" % \end{syntax} % This function return the name of as a sequence of letters with % the escape character removed. % \end{function} % % \begin{function}{\cs_gen_sym:N | % \cs_ggen_sym:N} % \begin{syntax} % "\cs_gen_sym:N" % \end{syntax} % These functions will generate a new control sequence name for use as a % pointer, e.g.\ some tree structure like the LDB. The new unique name % is returned locally in for further use. The names are generated % using the roman numeral representation of some special counters % together with a prefix of "\l*" (local) or "\g*"( global). % \end{function} % % % \subsection{Predicates and conditionals} % % \begin{function}{% % \if_meaning:NN | % } % \begin{syntax} % "\if_meaning:NN" "\else:" "\fi:" % \end{syntax} % This conditional executes when the replacement text, i.e., % the expansion of and are the same, otherwise it executes % . % \begin{texnote} % This is the primitive \tn{ifx}. % \end{texnote} % \end{function} % \begin{function}{% % \cs_eq_p:NN | % } % \begin{syntax} % "\cs_eq_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_free_p:N | % } % \begin{syntax} % "\cs_free_p:N" % \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:". % \end{function} % % \begin{function}{% % \cs_free:NTF | % \cs_free:NF | % \cs_free:NT | % \cs_free:cF | % \cs_free:cTF | % } % \begin{syntax} % "\cs_free:NTF" "{""}{""}" % \end{syntax} % These functions check if is free and then execute either or . % \begin{texnote} % The conditional "\cs_free:cTF" is the \LaTeX3 implementation of the % \LaTeX2 function \tn{@ifundefined}. The other functions haven't been % around before. % \end{texnote} % \end{function} % % \begin{function}{% % \cs_exist_p:N | % } % \begin{syntax} % "\cs_exist_p:N" % \end{syntax} % This function does the opposite of "\cs_free_p:N". % \end{function} % % \begin{function}{% % \chk_new_cs:N | % } % \begin{syntax} % "\chk_new_cs:N" % \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). % \end{function} % % \begin{function}{% % \chk_exist_cs:N | % } % \begin{syntax} % "\chk_exist_cs:N" % \end{syntax} % This function checks that is defined. If it is not an error % is generated. % \end{function} % % % \subsection{Internal functions} % % \begin{function}{% % \cs:w | % \cs_end: | % } % \begin{syntax} % "\cs:w" "\cs_end:" % \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. % \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}{\pref_global:D | % \pref_long:D | % } % \begin{syntax} % "\pref_global:D" "\def: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. % % 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_long:Npn". % \begin{texnote} % These prefixes are the primitives \tn{global}, \tn{long}. % The \tn{outer} isn't used at all within \LaTeX3 % because \ldots % \end{texnote} % \end{function} % % \subsection{Choice functions} % % \begin{function}{% % \use_choice_i:nn | % \use_choice_ii:nn | % } % \begin{syntax} % "\use_choice_i:nn" "{" "}{" "}" % \end{syntax} % Functions that execute the first or second argument respectively, % after removing the surrounding braces. Used to implement conditionals. % \end{function} % % \begin{function}{% % \use_choice_i:nnn | % \use_choice_ii:nnn | % \use_choice_iii:nnn | % } % \begin{syntax} % "\use_choice_i:nnn" "{" "}{" "}{" "}" % \end{syntax} % Functions that pick up one of three arguments and execute them after % removing the surrounding braces. Should be described somewhere else. % \end{function} % % \begin{function}{\use:n} % \begin{syntax} % "\use:n" "{" "}" % \end{syntax} % Function that executes the next argument after removing the % surrounding braces. Used to implement conditionals. % \end{function} % % \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 % functions that get new meanings all over the place. % % (Parts of this module are a mess, as far as naming conventions are % concerned.) % % \begin{texnote} % While \TeX{} makes all definition functions directly available to the % user \LaTeX3 hides them very carefully to avoid the problems with % definitions that are overwritten accidentally. Many functions that are in % \TeX{} a combination of prefixes and definition functions are provided % as individual functions. % \end{texnote} % % \subsection{Defining new functions} % % A definition of a new function can be done locally and globally. Currently % nearly all function definitions are done locally on top level, in % other words they are global but don't show it. Therefore I think it may % be better to remove the local variants in the future and declare all % checked function definitions global. % % \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 % } % \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 | % } % \begin{syntax} % "\def_long_new:Npn" "{" "}" % \end{syntax} % 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}{\let_new:NN | % \glet_new:NN} % \begin{syntax} % "\let_new:NN" % \end{syntax} % Gives the function the current meaning of . Again, we may % do this alway globally. % \end{function} % % \subsection{Defining internal functions (no checks)} % % 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. % % \begin{function}{\def:Npn | % \def:Npx | % \def:cpn | % \def:cpx | % } % \begin{syntax} % "\def:Npn" "{" "}" % \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} % \end{function} % % \begin{function}{\gdef:Npn | % \gdef:Npx | % \gdef:cpn | % \gdef:cpx | % } % \begin{syntax} % "\gdef:Npn" "{" "}" % \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} % \end{function} % % \begin{function}{\def:No | % \gdef:No % } % \begin{syntax} % "\def:No" "{" "}" % \end{syntax} % Local and global variant that expands code once before defining . % The function may not take as the others do. Perhaps this % should be changed. % \end{function} % % \begin{function}{\def_long:Npn | % \def_long:Npx | % \def_long:cpn | % } % \begin{syntax} % "\def_long:Npn" "{" "}" % \end{syntax} % Like "\def:Npn" but allows "\par" tokens in the arguments of the % function being defined. % \end{function} % % \begin{function}{\gdef_long:Npn | % \gdef_long:Npx | % } % \begin{syntax} % "\gdef_long:Npn" "{" "}" % \end{syntax} % Global variant of "\def_long:Npn". % \end{function} % % \begin{function}{\let:NN | % \glet:NN | % \let:cN | % \let:Nc | % \let:cc % } % \begin{syntax} % "\let:cN" % \end{syntax} % Gives the function the current meaning of . Again, we may % always do this globally. % \end{function} % % \begin{function}{\let:NwN} % \begin{syntax} % "\let:NwN" % "\let:NwN" "=" % \end{syntax} % These functions assign the meaning of locally or globally to the % function . Because the \TeX{} primitive operation is being used % which may have an equal sign and (a certain number of) spaces between % and the name contains a "w". (Not happy about this % convention!). % \begin{texnote} % "\let:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. % \end{texnote} % \end{function} % % % \StopEventually{} % % \section{Renaming some \TeX{} primitives (again)} % % 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 apropriate modules, but % do a few now, just to get started.\footnote{This renaming gets expensive % 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} %<*package> \tex_let:D \let:NwN \tex_let:D \let:NwN \def:Npn \tex_def:D \let:NwN \gdef:Npn \tex_gdef:D \let:NwN \def:Npx \tex_edef:D \let:NwN \gdef:Npx \tex_xdef:D \let:NwN \if:w \tex_if:D \let:NwN \if_num:w \tex_ifnum:D \let:NwN \if_meaning:NN \tex_ifx:D \let:NwN \if_false: \tex_iffalse:D \let:NwN \else: \tex_else:D \let:NwN \fi: \tex_fi:D \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 \exp_after:NN \tex_expandafter:D \let:NwN \scan_stop: \tex_relax:D \let:NwN \exp_not:N \tex_noexpand:D \let:NwN \group_begin: \tex_begingroup:D \let:NwN \group_end: \tex_endgroup:D % \end{macrocode} % % 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} % % % \section {Defining and checking (new) functions} % % We need some constants now, that should actually all be defined % together. We try to avoid using count registers for constants as % much as possible. % % \begin{macrocode} \let:NwN\c_minus_one\m@ne \tex_chardef:D \c_one = 1\scan_stop: \tex_chardef:D \c_sixteen = 16\scan_stop: \tex_mathchardef:D \c_two_hundred_fifty_six = 256\scan_stop: % \end{macrocode} % % 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}{\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{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 } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\err_latex_bug:n} % This will show internal errors. % \begin{macrocode} \def:Npn\err_latex_bug:n#1{ \io_put_term:x{This~is~a~LaTeX~bug!~Check~coding!}\tex_errmessage:D{#1}} % \end{macrocode} % \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{macrocode} %<*trace> \def:Npn \cs_record_meaning:N#1{} % % \end{macrocode} % \end{macro} % % \subsection{Checking new definitions} % % \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. % \begin {macrocode} \def:Npn \chk_new_cs:N #1{ \if_meaning:NN #1\c_undefined \else: \if_meaning:NN #1\scan_stop: \else: \err_latex_bug:n {Command~name~`\token_to_string:N #1'~ already~defined!~ Current~meaning:~\token_to_meaning:N #1 } \fi: \fi: %<*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} % } % \end{macrocode} % \end {macro} % % \begin{macro}{\cs_exist_p:N} % Expands into |\c_true| if the control sequence given as its % argument {\em is} in use. % % \begin{macrocode} \def:Npn \cs_exist_p:N #1{ \if:w \cs_free_p:N #1 \c_false \else: \c_true \fi:} % \end{macrocode} % \end{macro} % % \begin{macro}{\chk_exist_cs:N } % This function issues a warning message when the control sequence % in its argument does not exist. % \begin{macrocode} \def:Npn \chk_exist_cs:N #1 { \if:w \cs_exist_p:N #1 \else: \err_latex_bug:n{Command~ `\token_to_string:N #1'~ not~ yet~ defined!} \fi:} % \end{macrocode} % \end{macro} % % \begin{macro}{\cs_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{macrocode} \def:Npn \cs_free_p:N #1{ \if_meaning:NN#1\c_undefined \if:w\cs_eq_p:NN #1\c_undefined \c_false \else: \c_true \fi: \else: \if_meaning:NN#1\scan_stop: \if:w\cs_eq_p:NN #1\scan_stop: \c_false \else: \c_true \fi: \else: \c_false \fi:\fi:} % \end{macrocode} % \end{macro} % % \subsection{More new definitions} % % \begin{macro}{\let:NN} % \begin{macro}{\let:cN} % \begin{macro}{\let:Nc} % \begin{macro}{\let:cc} % These macros allow us to copy the definition of a control sequence % to another control sequence. Maybe we should implement a few more % of these. % % \begin{macrocode} \tex_long:D\def: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{macrocode} \let:NwN #1=~} \def:Npn\let:cN #1 {\exp_after:NN\let:NwN\cs:w#1\cs_end:=~} \def:Npn\let:Nc{\exp_args:NNc\let:NN} \def:Npn\let:cc{\exp_args:Ncc\let:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin {macro}{\def_new:Npn} % \begin {macro}{\def_new:Npx} % \begin {macro}{\let_new:NN} % These are like |\def:Npn| and |\let:NN|, but they first check that % the argument command is not already in use. You may use % |\tex_global:D|, |\tex_long:D|, and |\tex_outer:D| as % prefixes. % \begin {macrocode} \def:Npn \def_new:Npn #1{\chk_new_cs:N #1 \def:Npn #1} \def:Npn \def_new:Npx #1{\chk_new_cs:N #1 \def:Npx #1} \def_new:Npn \let_new:NN #1{\chk_new_cs:N #1 \let:NN #1} % \end{macrocode} % \end {macro} % \end {macro} % \end {macro} % % \begin {macro}{\def:cpn} % \begin {macro}{\def:cpx} % \begin {macro}{\def_new:cpn} % \begin {macro}{\def_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.). % % |\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 {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 \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:} % \end{macrocode} % \end {macro} % \end {macro} % \end {macro} % \end {macro} % % % \begin{macro}{\def: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} % \end{macrocode} % \end{macro} % % \begin {macro}{\def_long:Npn} % \begin {macro}{\def_long_new:Npn} % \begin {macro}{\def_long:cpn} % \begin {macro}{\def_long:Npx} % |\def_long:Npn| stands for |\tex_long:D| |\def:Npn|. % |\def_long:Npx| expands its second argument. % \begin {macrocode} \def_new:Npn \def_long:Npn {\tex_long:D\def:Npn} \def_new:Npn \def_long_new:Npn #1{\chk_new_cs:N #1 \def_long:Npn #1} \def_new:Npn \def_long:cpn #1{\exp_after:NN \def_long:Npn \cs:w #1\cs_end:} \def_new:Npn \def_long:Npx {\tex_long:D\def:Npx} % \end{macrocode} % \end {macro} % \end {macro} % \end {macro} % \end {macro} % % \begin {macro}{\glet:NN} % \begin {macro}{\glet_new:NN} % \begin {macro}{\gdef_new:Npn} % \begin {macro}{\gdef:cpn} % \begin {macro}{\gdef:cpx} % \begin {macro}{\gdef:No} % These are global versions of some of the previosly defined functions. % \begin {macrocode} \def_new:Npn \glet:NN {\tex_global:D \let:NN} \def_new:Npn \glet_new:NN #1{\chk_new_cs:N #1 \tex_global:D\let:NN #1} \def_new:Npn \gdef_new:Npn #1{\chk_new_cs:N #1 \gdef:Npn #1} \def_new:Npn \gdef:cpn {\tex_global:D \def:cpn} \def_new:Npn \gdef:cpx {\tex_global:D \def:cpx} \def_new:Npn \gdef:No {\exp_args:NNo\gdef:Npn} % \end{macrocode} % \end {macro} % \end {macro} % \end {macro} % \end {macro} % \end {macro} % \end {macro} % \begin {macro}{\gdef_long:Npn} % \begin {macro}{\gdef_long:Npx} % |\gdef_long:Npn| stands for |\tex_long:D| |\tex_global:D| |\def:Npn|. % |\gdef_long:Npx| expands its second argument. % \begin {macrocode} \def_new:Npn \gdef_long:Npn {\tex_long:D\gdef:Npn} \def_new:Npn \gdef_long:Npx {\tex_long:D\gdef:Npx} % \end{macrocode} % \end {macro} % \end {macro} % % \begin {macro}{\gfuturelet:NNN} % This is a global version of |\let_peek_after:NNN| % \begin {macrocode} \def_new:Npn \gfuturelet:NNN{\tex_global:D \let_peek_after:NNN} % \end{macrocode} % \end {macro} % % \subsection{Further checking} % % \begin{macro}{\cs_free:NTF} % \begin{macro}{\cs_free:NT} % \begin{macro}{\cs_free:NF} % The old |\@ifundefined| of \LaTeX{} 2.09 is reimplemented 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_new:Npn \cs_free:NTF #1{\if:w\cs_free_p:N #1 \exp_after:NN \use_choice_i:nn \else: \exp_after:NN \use_choice_ii:nn \fi:} \def_long_new:Npn \cs_free:NT #1{\if:w\cs_free_p:N #1 \exp_after:NN \use:n \else: \exp_after:NN \use_none:n \fi:} \def_long_new:Npn \cs_free:NF #1{\if:w\cs_free_p:N #1 \exp_after:NN \use_none:n \else: \exp_after:NN \use:n \fi:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\cs_free:cTF} % \begin{macro}{\cs_free:cT} % \begin{macro}{\cs_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{macrocode} \def_long_new:Npn \cs_free:cTF #1{ \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop: \exp_after:NN \use_choice_i:nn \else: \exp_after:NN \use_choice_ii:nn \fi:} \def_long_new:Npn \cs_free:cF #1{\exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop: \exp_after:NN \use_none:nn \fi: \use:n} \def_long_new:Npn \cs_free:cT #1{\exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop: \else: \exp_after:NN \use_none:nn \fi: \use:n} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \subsection{Freeing memory} % % \begin{macro}{\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 \gundefine:N #1{\glet:NN #1\c_undefined} % \end{macrocode} % \end{macro} % % \subsection{Gobbling tokens from input} % % \begin{macro}{\use_none:n} % \begin{macro}{\use_none:nn} % \begin{macro}{\use_none:nnn} % \begin{macro}{\use_none:nnnn} % 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. % \begin{macrocode} \def_long_new:Npn \use_none:n #1{} \def_long_new:Npn \use_none:nn #1#2{} \def_long_new:Npn \use_none:nnn #1{\use_none:nn} \def_long_new:Npn \use_none:nnnn {\exp_after:NN\use_none:nn \use_none:nn} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsection{Selecting tokens} % % \begin{macro}{\use:n} % This macro grabs its argument and returns it back to the input % (with outer braces removed). % \begin{macrocode} \def_long_new:Npn \use:n #1{#1} % \end{macrocode} % \end{macro} % % \begin{macro}{\use:c} % \begin{macro}{\use:cc} % This macro grabs its argument and returns a csname from it. % \begin{macrocode} \def_new:Npn \use:c #1{\cs:w #1\cs_end:} % \end{macrocode} % THE NAME IS COMPLETELY WRONG!!!!! % \begin{macrocode} \def_new:Npn \use:cc #1#2 {\cs:w #1\exp_after:NN\cs_end:\cs:w #2\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\use_choice_i:nn} % \begin{macro}{\use_choice_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_choice_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{macrocode} \def_long_new:Npn \use_choice_i:nn #1#2{#1} \def_long_new:Npn \use_choice_ii:nn #1#2{#2} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\use_choice_i:nnn} % \begin{macro}{\use_choice_ii:nnn} % \begin{macro}{\use_choice_iii:nnn} % We also need something for picking up arguments from a longer % list. % \begin{macrocode} \def_long_new:Npn\use_choice_i:nnn#1#2#3{#1} \def_long_new:Npn\use_choice_ii:nnn#1#2#3{#2} \def_long_new:Npn\use_choice_iii:nnn#1#2#3{#3} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \subsection{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} % % \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'. % \begin{macrocode} \def_new:Npn \use_noop: {} % \end{macrocode} % \end{macro} % % \section{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{macrocode} \def_new:Npn \cs_to_str:N {\exp_after:NN\use_none:n \token_to_string:N} % \end{macrocode} % \end{macro} % % \begin{macro}{\tlist_eq:nnTF} % \begin{macro}{\tlist_eq:onTF} % |\tlist_eq:nnTF| tests whether the first two arguments are equal and % executes either its third or fourth argument. % |\tlist_eq:onTF| expands its first argument once. % \begin{macrocode} \def_new:Npn \tlist_eq:nnTF #1#2{ \tlp_gset:Nn \g_testa_tlp {#1} \tlp_gset:Nn \g_testb_tlp {#2} \if_meaning:NN\g_testa_tlp \g_testb_tlp \exp_after:NN\use_choice_i:nn \else: \exp_after:NN\use_choice_ii:nn \fi:} \def_new:Npn \tlist_eq:onTF {\exp_args:No \tlist_eq:nnTF} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\tlist_empty:nTF} % \begin{macro}{\tlist_empty:nF} % These test whether a token list is empty and act accordingly. % \begin{macrocode} \def_new:Npn \tlist_empty:nTF #1{\tlp_gset:Nn \g_testa_tlp {#1} \if_meaning:NN\g_testa_tlp \c_empty_tlp \exp_after:NN \use_choice_i:nn \else: \exp_after:NN \use_choice_ii:nn \fi:} \def_new:Npn \tlist_empty:nF #1{\tlp_gset:Nn \g_testa_tlp {#1} \if_meaning:NN\g_testa_tlp \c_empty_tlp \exp_after:NN \use_none:nn \fi: \use:n} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\str_eq_p:nn} % Takes 2 lists of characters as arguments and expands into % |\c_true| if they are equal, and |\c_false| otherwise. I'm % pretty sure that the non expandable version above is faster, but % it's not expandable so we also include this one. % \begin{macrocode} \def_new:Npn \str_eq_p:nn #1#2{\str_eq_p_aux:w #1\scan_stop:\\#2\scan_stop:\\} \def_new:Npn \str_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_eq_p_aux:w #2\\#4\\\fi:\fi: \else:\c_false \fi:} % \end{macrocode} % \end{macro} % % \begin{macro}{\cs_eq_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. % \begin{macrocode} \def:Npn \cs_eq_p:NN #1#2{ \exp_after:NN\exp_after:NN \exp_after:NN\str_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:\\} % \end{macrocode} % \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}} % \end{macrocode} % % % \section{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 or the . 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 and/or 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. % % \subsection{Variables} % % \begin{variable}{% % \c_true | \c_false | % } % Constants that represend `true' or `false', respectively. Used to % implement predicates. % \end{variable} % % \begin{variable}{\l_testa_tlp | % \l_testb_tlp | % \g_testa_tlp | % \g_testb_tlp | % } % All conditionals and predicates never use tmp variables. Instead they % use the following reserved variables. % \end{variable} % % \subsection{Predicate implementation} % % I think Michael originated the idea of expandable boolean tests. % They must expand into either \texttt{TT} or \texttt{TF} and are % tested using |\if:w|. % % % \begin{macro}{\c_true} % \begin{macro}{\c_false} % Here are the canonical boolean values. % \begin{macrocode} \def_new:Npn \c_true {TT} \def_new:Npn \c_false {TF} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} % %<*showmemory> \showMemUsage % % \end{macrocode} %