% \iffalse %% 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 %% 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: l3basics.dtx 1700 2009-11-04 21:15:58Z joseph $ {L3 Experimental basic definitions} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \begin{document} \DocInput{l3basics.dtx} \end{document} % % \fi % % % \title{The \textsf{l3basics} package\thanks{This file % has version number \fileversion, last % revised \filedate.}\\ % Basic Definitions} % \author{\Team} % \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. % % 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. % % \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} % % 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 % |\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: / (EXP) | % \if_false: / (EXP) | % \or: / (EXP) | % \else: / (EXP) | % \fi: / (EXP) | % \reverse_if:N / (EXP) } % \begin{syntax} % "\if_true:" "\else:" "\fi:" \\ % "\if_false:" "\else:" "\fi:" \\ % "\reverse_if:N" % \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. "\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:w / (EXP) } % \begin{syntax} % "\if_meaning:w" "\else:" "\fi:" % \end{syntax} % "\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 / (EXP) | % \if_charcode:w / (EXP) | % \if_catcode:w / (EXP) } % \begin{syntax} % "\if:w" "\else:" "\fi:" \\ % "\if_catcode:w" "\else:" "\fi:" % \end{syntax} % These conditionals will expand any following tokens until two % unexpandable tokens are left. If you wish to prevent this expansion, % prefix the token in question with "\exp_not:N". "\if_catcode:w" % tests if the category codes of the two tokens are the same whereas % "\if:w" tests if the character codes are % identical. "\if_charcode:w" is an alternative name for "\if:w". % \end{function} % % % \begin{function}{\if_predicate:w / (EXP)} % \begin{syntax} % "\if_predicate:w" "\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:" "\fi:" % \end{syntax} % Check if appears in the hash table or if the control sequence % that can be formed from appears in the hash table. The % latter function does not turn the control sequence in question into % "\scan_stop:"! This can be useful when dealing with control % sequences which cannot be entered as a single token. % \end{function} % % \begin{function}{ % \if_mode_horizontal: / (EXP) | % \if_mode_vertical: / (EXP) | % \if_mode_math: / (EXP) | % \if_mode_inner: / (EXP) } % \begin{syntax} % "\if_mode_horizontal:" "\else:" "\fi:" % \end{syntax} % Execute if currently in horizontal mode, otherwise % execute . Similar for the other functions. % \end{function} % % \subsection{Non-primitive conditionals} % % \begin{function}{ \cs_if_eq_name_p:NN } % \begin{syntax} % "\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_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_p:NNTF" % "\cs_if_eq:NNTF" \Arg{true code} \Arg{false code} % \end{syntax} % These functions check if and have same meaning. % \end{function} % % % \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 % "\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_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_exist_p:N" % "\cs_if_exist:NTF" \Arg{true code} \Arg{false code} % \end{syntax} % 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_do_not_use_p:N / (EXP) } % \begin{syntax} % "\cs_if_do_not_use_p:N" % \end{syntax} % 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}{ % \chk_if_free_cs:N| % \chk_if_free_cs:c % } % \begin{syntax} % "\chk_if_free_cs:N" % \end{syntax} % 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}{ \chk_if_exist_cs:N | % \chk_if_exist_cs:c } % \begin{syntax} % "\chk_if_exist_cs:N" % \end{syntax} % This function checks that is defined. If it is not an error % is generated. % \end{function} % % \begin{variable}{ \c_true_bool | \c_false_bool } % \begin{syntax} % \end{syntax} % Constants that represent `true' or `false', respectively. Used to % implement predicates. % \end{variable} % % \subsection{Applications} % % \begin{function}{ \str_if_eq_p:nn / (EXP) } % \begin{syntax} % "\str_if_eq_p:nn" \Arg{string1} \Arg{string2} % \end{syntax} % Expands to `true' if is the same as , % otherwise `false'. Ignores spaces within the strings. % \end{function} % % \begin{function}{ \str_if_eq_var_p:nf / (EXP) } % \begin{syntax} % "\str_if_eq_var_p:nf" \Arg{string1} \Arg{string2} % \end{syntax} % A variant of "\str_if_eq_p:nn" which has the advantage of % obeying spaces in at least the second argument. % \end{function} % % % \section{Control sequences} % % \begin{function}{ \cs:w / (EXP) | \cs_end: / (EXP) } % \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}{ \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} % % \section{Selecting and discarding tokens from the input stream} % % The conditional processing cannot be implemented without % being able to gobble and select which tokens to use from the input % stream. % % % \begin{function}{ \use:n / (EXP) | % \use:nn / (EXP) | % \use:nnn / (EXP) | % \use:nnnn / (EXP) } % \begin{syntax} % "\use:n" \Arg{arg} % \end{syntax} % 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_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_none:n" \Arg{arg1}\\ % "\use_none:nn" \Arg{arg1} \Arg{arg2} % \end{syntax} % 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_i:nn / (EXP) | % \use_ii:nn / (EXP) } % \begin{syntax} % "\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_i:nnn / (EXP) | % \use_ii:nnn / (EXP) | % \use_iii:nnn / (EXP) } % \begin{syntax} % "\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. % \begin{texnote} % \LaTeXe\ has only "\@thirdofthree". % \end{texnote} % \end{function} % % \begin{function}{ \use_i:nnnn / (EXP) | % \use_ii:nnnn / (EXP) | % \use_iii:nnnn / (EXP) | % \use_iv:nnnn / (EXP) } % \begin{syntax} % "\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} % % \subsection{Extending the interface} % % \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 or terminating recursion. % \end{function} % % \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_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_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_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_i_after_orelse:nw" can be used anywhere where % "\use_i_after_else:nw" or "\use_i_after_or:nw" are used. % \end{function} % % % \section{That which belongs in other modules but needs to be defined earlier} % % \begin{function}{ \exp_after:wN / (EXP) } % \begin{syntax} % "\exp_after:wN" % \end{syntax} % Expands once and then continues processing from . % \begin{texnote} % This is \TeX's \tn{expandafter}. % \end{texnote} % \end{function} % % \begin{function}{ \exp_not:N / (EXP) | \exp_not:n / (EXP) } % \begin{syntax} % "\exp_not:N" % "\exp_not:n" \Arg{tokens} % \end{syntax} % In an expanding context, this function prevents or from % expanding. % \begin{texnote} % 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}{ \iow_log:x | % \iow_term:x | % \iow_shipout_x:Nn } % \begin{syntax} % "\iow_log:x" \Arg{message} % "\iow_shipout_x:Nn" \Arg{message} % \end{syntax} % Writes to either to log or the terminal. % \end{function} % % \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 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. 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 % 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{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} % % 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} % "\cs_new: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. % \end{function} % % \begin{function}{\cs_gnew:Npn | % \cs_gnew:Npx | % \cs_gnew:cpn | % \cs_gnew:cpx % } % \begin{syntax} % "\cs_gnew:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_new_nopar:Npn | % \cs_new_nopar:Npx | % \cs_new_nopar:cpn | % \cs_new_nopar:cpx % } % \begin{syntax} % "\cs_new_nopar:Npn" \Arg{code} % \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}{\cs_gnew_nopar:Npn | % \cs_gnew_nopar:Npx | % \cs_gnew_nopar:cpn | % \cs_gnew_nopar:cpx % } % \begin{syntax} % "\cs_gnew_nopar:Npn" \Arg{code} % \end{syntax} % Like "\cs_new_nopar:Npn" but defines the new function globally. See % comments above. % \end{function} % % \begin{function}{\cs_new_protected:Npn | % \cs_new_protected:Npx | % \cs_new_protected:cpn | % \cs_new_protected:cpx % } % \begin{syntax} % "\cs_new_protected:Npn" \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}{ \cs_gnew_protected:Npn | % \cs_gnew_protected:Npx | % \cs_gnew_protected:cpn | % \cs_gnew_protected:cpx } % \begin{syntax} % "\cs_gnew_protected:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_new_protected_nopar:Npn | % \cs_new_protected_nopar:Npx | % \cs_new_protected_nopar:cpn | % \cs_new_protected_nopar:cpx % } % \begin{syntax} % "\cs_new_protected_nopar:Npn" \Arg{code} % \end{syntax} % Defines a function that does not expand when inside an |x| type % expansion. % \end{function} % % \begin{function}{\cs_gnew_protected_nopar:Npn | % \cs_gnew_protected_nopar:Npx | % \cs_gnew_protected_nopar:cpn | % \cs_gnew_protected_nopar:cpx % } % \begin{syntax} % "\cs_gnew_protected_nopar:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % % % % % % % % \subsection{Defining new functions using the signature} % % % \begin{function}{\cs_new:Nn | % \cs_new:Nx | % \cs_new:cn | % \cs_new:cx % } % \begin{syntax} % "\cs_new:Nn" \Arg{code} % \end{syntax} % 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}{\cs_gnew:Nn | % \cs_gnew:Nx | % \cs_gnew:cn | % \cs_gnew:cx % } % \begin{syntax} % "\cs_gnew:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_new_nopar:Nn | % \cs_new_nopar:Nx | % \cs_new_nopar:cn | % \cs_new_nopar:cx % } % \begin{syntax} % "\cs_new_nopar:Nn" \Arg{code} % \end{syntax} % Version of the above in which "\par" is not allowed to appear within the % argument(s) of the defined functions. % \end{function} % % \begin{function}{\cs_gnew_nopar:Nn | % \cs_gnew_nopar:Nx | % \cs_gnew_nopar:cn | % \cs_gnew_nopar:cx % } % \begin{syntax} % "\cs_gnew_nopar:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_new_protected:Nn | % \cs_new_protected:Nx | % \cs_new_protected:cn | % \cs_new_protected:cx % } % \begin{syntax} % "\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}{\cs_gnew_protected:Nn | % \cs_gnew_protected:Nx | % \cs_gnew_protected:cn | % \cs_gnew_protected:cx % } % \begin{syntax} % "\cs_gnew_protected:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_new_protected_nopar:Nn | % \cs_new_protected_nopar:Nx | % \cs_new_protected_nopar:cn | % \cs_new_protected_nopar:cx % } % \begin{syntax} % "\cs_new_protected_nopar:Nn" \Arg{code} % \end{syntax} % 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} % % \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_gnew_protected_nopar:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % % \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. % % \begin{function}{\cs_set:Npn | % \cs_set:Npx | % \cs_set:cpn | % \cs_set:cpx | % } % \begin{syntax} % "\cs_set:Npn" \Arg{code} % \end{syntax} % 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}{\cs_gset:Npn | % \cs_gset:Npx | % \cs_gset:cpn | % \cs_gset:cpx | % } % \begin{syntax} % "\cs_gset:Npn" \Arg{code} % \end{syntax} % Global variant of "\cs_set:Npn". % \end{function} % % \begin{function}{\cs_set_nopar:Npn | % \cs_set_nopar:Npx | % \cs_set_nopar:cpn | % \cs_set_nopar:cpx | % } % \begin{syntax} % "\cs_set_nopar:Npn" \Arg{code} % \end{syntax} % 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}{\cs_gset_nopar:Npn | % \cs_gset_nopar:Npx | % \cs_gset_nopar:cpn | % \cs_gset_nopar:cpx | % } % \begin{syntax} % "\cs_gset_nopar:Npn" \Arg{code} % \end{syntax} % 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}{\cs_set_protected:Npn | % \cs_set_protected:Npx | % \cs_set_protected:cpn | % \cs_set_protected:cpx | % } % \begin{syntax} % "\cs_set_protected:Npn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. % These varieties allow |\par| tokens in the arguments of the % function being defined. % \end{function} % % \begin{function}{\cs_gset_protected:Npn | % \cs_gset_protected:Npx | % \cs_gset_protected:cpn | % \cs_gset_protected:cpx | % } % \begin{syntax} % "\cs_gset_protected:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_set_protected_nopar:Npn | % \cs_set_protected_nopar:Npx | % \cs_set_protected_nopar:cpn | % \cs_set_protected_nopar:cpx | % } % \begin{syntax} % "\cs_set_protected_nopar:Npn" \Arg{code} % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. % 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}{\cs_gset_protected_nopar:Npn | % \cs_gset_protected_nopar:Npx | % \cs_gset_protected_nopar:cpn | % \cs_gset_protected_nopar:cpx | % } % \begin{syntax} % "\cs_gset_protected_nopar:Npn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % \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} % "\cs_set:Nn" \Arg{code} % \end{syntax} % Like "\cs_set_nopar:Nn" but allows "\par" tokens in the arguments of the % function being defined. % \end{function} % % \begin{function}{\cs_gset:Nn | % \cs_gset:Nx | % \cs_gset:cn | % \cs_gset:cx | % } % \begin{syntax} % "\cs_gset:Nn" \Arg{code} % \end{syntax} % Global variant of "\cs_set:Nn". % \end{function} % % \begin{function}{\cs_set_nopar:Nn | % \cs_set_nopar:Nx | % \cs_set_nopar:cn | % \cs_set_nopar:cx | % } % \begin{syntax} % "\cs_set_nopar:Nn" \Arg{code} % \end{syntax} % Like "\cs_new_nopar:Nn" etc.\ but does not check the name. % \end{function} % % \begin{function}{\cs_gset_nopar:Nn | % \cs_gset_nopar:Nx | % \cs_gset_nopar:cn | % \cs_gset_nopar:cx | % } % \begin{syntax} % "\cs_gset_nopar:Nn" \Arg{code} % \end{syntax} % Like "\cs_set_nopar:Nn" but defines the globally. % \end{function} % % \begin{function}{\cs_set_protected:Nn | % \cs_set_protected:cn | % \cs_set_protected:Nx | % \cs_set_protected:cx | % } % \begin{syntax} % "\cs_set_protected: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. % \end{function} % % \begin{function}{\cs_gset_protected:Nn | % \cs_gset_protected:cn | % \cs_gset_protected:Nx | % \cs_gset_protected:cx | % } % \begin{syntax} % "\cs_gset_protected:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\cs_set_protected_nopar:Nn | % \cs_set_protected_nopar:cn | % \cs_set_protected_nopar:Nx | % \cs_set_protected_nopar:cx | % } % \begin{syntax} % "\cs_set_protected_nopar: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:wN \prg_do_nothing:|. % \end{function} % % \begin{function}{\cs_gset_protected_nopar:Nn | % \cs_gset_protected_nopar:cn | % \cs_gset_protected_nopar:Nx | % \cs_gset_protected_nopar:cx | % } % \begin{syntax} % "\cs_gset_protected_nopar:Nn" \Arg{code} % \end{syntax} % Global versions of the above functions. % \end{function} % % % % \subsection{Undefining functions} % % \begin{function}{ % \cs_gundefine:N | % \cs_gundefine:c % } % \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} % "\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}{\cs_set_eq:NwN} % \begin{syntax} % "\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 % 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} % "\cs_set_eq:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. % \end{texnote} % \end{function} % % \subsection{Internal 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. % % 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} % % \begin{function}{\cs_to_str:N / (EXP)} % \begin{syntax} % "\cs_to_str:N" % \end{syntax} % This function returns the name of as a sequence of letters with % the escape character removed. % \end{function} % % \begin{function}{\token_to_str:N / (EXP) | \token_to_str:c / (EXP)} % \begin{syntax} % "\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 / (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. % % \section{Grouping and scanning} % % \begin{function}{\scan_stop:} % \begin{syntax} % "\scan_stop:" % \end{syntax} % This function stops \TeX's scanning ahead when ending a number. % \begin{texnote} % This is the \TeX{} primitive \tn{relax} renamed. % \end{texnote} % \end{function} % % % \begin{function}{\group_begin:| % \group_end:} % \begin{syntax} % "\group_begin:" <...> "\group_end:" % \end{syntax} % Encloses <...> inside a group. % \begin{texnote} % These are the \TeX{} primitives \tn{begingroup} and \tn{endgroup} % renamed. % \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} % % % \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}{\luatex_if_engine: / (TF)(EXP)} % \begin{syntax} % "\luatex_if_engine:TF" \Arg{true code} \Arg{false code} % \end{syntax} % 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} % % \begin{implementation} % % \section{\pkg{l3basics} implementation} % % 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. % % \subsection{Renaming some \TeX{} primitives (again)} % % \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 % 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> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} \package_check_loaded_expl: % %<*initex|package> \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} \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \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} \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} % \end{macro} % \end{macro} % \begin{macro}{\if_cs_exist:N} % \begin{macro}{\if_cs_exist:w} % \begin{macrocode} \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: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} \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}{\iow_shipout_x:Nn} % \begin{macro}{\token_to_meaning: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} % \begin{macro}{\cs_meaning:c} % \begin{macro}{\cs_show:N} % \begin{macro}{\cs_show:c} % \begin{macrocode} \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\scan_stop:} % \begin{macro}{\group_begin:} % \begin{macro}{\group_end:} % The next three are basic functions for which there also exist % versions that are safe inside alignments. These safe versions are % defined in the \textsf{l3prg} module. % \begin{macrocode} \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} \cs_set_eq:NwN \group_execute_after:N \tex_aftergroup:D % \end{macrocode} % \end{macro} % \begin{macro}{\pref_global:D} % \begin{macro}{\pref_long:D} % \begin{macro}{\pref_protected:D} % \begin{macrocode} \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} % % % % \subsection {Defining functions} % % % We start by providing functions for the typical definition % functions. First the local ones. % % \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} \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 } \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \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} \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 } \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \subsection{Selecting tokens} % % \begin{macro}{\use:c} % This macro grabs its argument and returns a csname from it. % \begin{macrocode} \cs_set:Npn \use:c #1 { \cs:w#1\cs_end: } % \end{macrocode} % \end{macro} % % \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} \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} % % \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} % % % % \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} \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}{\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} \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}{\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} \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} % % % \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} \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} % % \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} % \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} \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} % % \subsection{Expansion control from l3expan} % %\ExplSyntaxOn % \cs_set_eq:NN \g_saved_doc_macros_seq \g_doc_macros_seq %\ExplSyntaxOff % \begin{macro}{\exp_args:Nc} % Moved here for now as it is going to be used right away. % \begin{macrocode} \cs_set:Npn \exp_args:Nc #1#2{\exp_after:wN#1\cs:w#2\cs_end:} % \end{macrocode} % \end{macro} %\ExplSyntaxOn % \cs_set_eq:NN \g_doc_macros_seq \g_saved_doc_macros_seq %\ExplSyntaxOff % % \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. % %\ExplSyntaxOn % \cs_set_eq:NN \g_saved_doc_macros_seq \g_doc_macros_seq %\ExplSyntaxOff % % \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}{\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} \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} } % \end{macrocode} % \end{macro} % % \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn} % The obvious setting-equal functions. % \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} % \end{macro} % %\ExplSyntaxOn % \cs_set_eq:NN \g_doc_macros_seq \g_saved_doc_macros_seq %\ExplSyntaxOff % % \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} \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} % \begin{macro}[aux]{\prg_generate_conditional_parm_aux:nnNNnnnn, % \prg_generate_conditional_parm_aux:nw} % % 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} \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}[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} \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: } } \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: } } \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} % % \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} % % 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} % % \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". % % 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} % % \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} % % \subsection{Exist or free} % % 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. % % \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} \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} % % \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}{\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} %<*!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} % % 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} \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} % % \begin{macro}{\msg_kernel_bug:x} % This will show internal errors. % \begin{macrocode} \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} % % \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> \cs_set:Npn \cs_record_meaning:N #1{} % % \end{macrocode} % \end{macro} % % \begin{macro}{\chk_if_free_cs:N} % \begin{macro}{\chk_if_free_cs:c} % 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 } } %<*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} % } \cs_set_nopar:Npn \chk_if_free_cs:c { \exp_args:Nc \chk_if_free_cs:N } % \end{macrocode} % \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. % \begin{macrocode} \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} % % % \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} \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} % % \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} \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} % % % \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} \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} % % % % % \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} % \end{macro} % \end{macro} % \end{macro} % \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \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} \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} % \end{macro} % \end{macro} % \end{macro} % \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \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} \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \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} \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \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} \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \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'. % % The |c| variants are not protected in order for their arguments to % be constructed in the correct context. % % \begin{macrocode} \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_new_eq:NN} % \begin{macro}{\cs_new_eq:cN} % \begin{macro}{\cs_new_eq:Nc} % \begin{macro}{\cs_new_eq:cc} % \begin{macrocode} \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_gset_eq:NN} % \begin{macro}{\cs_gset_eq:cN} % \begin{macro}{\cs_gset_eq:Nc} % \begin{macro}{\cs_gset_eq:cc} % \begin{macrocode} \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_gnew_eq:NN} % \begin{macro}{\cs_gnew_eq:cN} % \begin{macro}{\cs_gnew_eq:Nc} % \begin{macro}{\cs_gnew_eq:cc} % \begin{macrocode} \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} % % % \subsection{Undefining functions} % % \begin{macro}{\cs_gundefine:N } % \begin{macro}{\cs_gundefine:c } % 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} \cs_new_nopar:Npn \cs_gundefine:N #1{\cs_gset_eq:NN #1\c_undefined:D} \cs_new_nopar:Npn \cs_gundefine:c #1{ \cs_gset_eq:cN {#1} \c_undefined:D } % \end{macrocode} % \end{macro} % \end{macro} % % % \subsection{Engine specific definitions} % % \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} \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} % % % % % \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} \cs_new_nopar:Npn \prg_do_nothing: {} % \end{macrocode} % \end{macro} % % % \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} \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} % A variant form we need right away. % \begin{macrocode} \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}[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} \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} % % % % % \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} \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} % \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_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} \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} % \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} % % 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} \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} % \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} \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_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} \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} % \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_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} % % \begin{macrocode} % % \end{macrocode} % % \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % % \end{implementation} % % \PrintIndex % % \endinput