% \iffalse %% File: l3basics.dtx Copyright (C) 1990-2006 LaTeX3 project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the ``expl3 bundle'' (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX Project Team. %% %% ----------------------------------------------------------------------- %<*driver|package> \RequirePackage{l3names} % %\fi \GetIdInfo$Id: l3basics.dtx 702 2007-11-27 14:21:49Z morten $ {L3 Experimental basic definitions} %\iffalse %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass{l3doc} \begin{document} \DocInput{\filename.\filenameext} \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 % % % As the name suggest this package holds some basic definitions which % are needed by most or all other packages in this set. % % \section{Basics} % % Here we describe those functions that used all over the place. With % that we mean functions dealing with the construction and testing of % control sequences. Furthermore the basic parts of conditional % processing are covered; conditional processing dealing with specific % data types is described in the modules specific for the respective % data types. % % \subsection{Predicates and conditionals} % % \subsubsection{Primitive conditionals} % % The \eTeX\ engine itself provides many different conditionals. Some % expand whatever comes after them and others don't. Hence the names % for these underlying functions will often contain a |:w| part but % higher level functions are often available. See for instance % |\int_compare_p:nNn| which is a wrapper for |\if_num:w|. % % Certain conditionals deal with specific data types like boxes and % fonts and are described there. The ones described below are either % the universal conditionals or deal with control sequences. We will % prefix primitive conditionals with |\if_|. % % \begin{function}{% % \if_true: | % \if_false: | % \else: | % \fi: | % \reverse_if:N | % } % \begin{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. % \end{function} % % \begin{function}{% % \if_meaning:NN | % \if_cs_meaning_eq:NN | % \if_token_eq:NN | % } % \begin{syntax} % "\if_meaning:NN" "\else:" % "\fi:" \\ % "\if_cs_meaning_eq:NN" "\else:" % "\fi:" \\ % "\if_token_eq:NN" "\else:" "\fi:" % \end{syntax} % "\if_meaning:NN" executes when the replacement text, % i.e., the expansion of and are the same, otherwise it % executes . However this name isn't really that % good. What the \TeX\ primitive does is compare two tokens to see if % they are equal. Hence this is actually a "token" functions. A % similar argument applies to the situation where it is used to % compare control sequences, where it is the meaning being compared. % Something to be cleaned up at some point. % \end{function} % % \begin{function}{% % \if:w | % \if_charcode:w | % \if_catcode:w % } % \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_cs_exist:N | % \if_cs_exist:w % } % \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: | % \if_mode_vertical: | % \if_mode_math: | % \if_mode_inner: % } % \begin{syntax} % "\if_horizontal_mode:" "\else:" "\fi:" % \end{syntax} % Execute if currently in horizontal mode, otherwise % execute . Similar for the other functions. % \end{function} % % \subsubsection{Non-primitive conditionals} % % \begin{function}{% % \cs_if_eq_p:NN % } % \begin{syntax} % "\cs_if_eq_p:NN" % \end{syntax} % Returns `true' if and are textually the same, i.e.\ have % the same name, otherwise it returns `false'. % \end{function} % % \begin{function}{% % \cs_if_eq:NNTF | % \cs_if_eq:NNT | % \cs_if_eq:NNF | % \cs_if_eq:cNTF | % \cs_if_eq:cNT | % \cs_if_eq:cNF | % \cs_if_eq:NcTF | % \cs_if_eq:NcT | % \cs_if_eq:NcF | % \cs_if_eq:ccTF | % \cs_if_eq:ccT | % \cs_if_eq:ccF % } % \begin{syntax} % "\cs_if_eq:NNTF" "{""}{""}" % \end{syntax} % These functions check if and have same meaning and then % execute either or . % \end{function} % % % \begin{function}{% % \cs_if_free_p:N % } % \begin{syntax} % "\cs_if_free_p:N" % \end{syntax} % Returns `true' if is either undefined or equal to "\scan_stop:". % However, it returns `false' if is textually "\c_undefined" (the % constantly undefined function), or textually "\scan_stop:". % \end{function} % % \begin{function}{% % \cs_if_free:NTF | % \cs_if_free:NT | % \cs_if_free:NF | % \cs_if_free:cTF | % \cs_if_free:cT | % \cs_if_free:cF % } % \begin{syntax} % "\cs_if_free:NTF" "{""}{""}" % \end{syntax} % These functions check if is free and then execute either or . % \begin{texnote} % The conditional "\cs_if_free:cTF" is the \LaTeX3 implementation of % the \LaTeX2 function \tn{@ifundefined}. The other functions % haven't been around before. % \end{texnote} % \end{function} % % \begin{function}{% % \cs_if_really_free:cTF | % \cs_if_really_free:cF | % \cs_if_really_free:cT % } % \begin{syntax} % "\cs_if_really_free:cTF" "{""}" "{""} {""}" % \end{syntax} % Similar to "\cs_if_free:cTF" but does not put anything previously % undefined into the hash table. Useful for special control sequences % like "\foo/bar" which cannot be entered as one token. % \end{function} % % \begin{function}{% % \cs_if_exist_p:N % } % \begin{syntax} % "\cs_if_exist_p:N" % \end{syntax} % This function does the opposite of "\cs_if_free_p:N". % \end{function} % % \begin{function}{% % \cs_if_exist:NTF | % \cs_if_exist:NT | % \cs_if_exist:NF | % \cs_if_exist:cTF | % \cs_if_exist:cT | % \cs_if_exist:cF % } % \begin{syntax} % "\cs_if_exist:NTF" "{""}{""}" % \end{syntax} % These functions check if exists and then execute either or . Exactly the opposite of "\cs_if_free:NTF". % \end{function} % % \begin{function}{% % \cs_if_really_exist:cTF | % \cs_if_really_exist:cF | % \cs_if_really_exist:cT % } % \begin{syntax} % "\cs_if_really_exist:cTF" "{""}" "{""} {""}" % \end{syntax} % The opposite of "\cs_if_really_free:cTF". % \end{function} % % % \begin{function}{% % \chk_new_cs:N | % } % \begin{syntax} % "\chk_new_cs:N" % \end{syntax} % This function checks that is so far either undefined or equals % "\scan_stop:" (the function that is assigned to newly created % control sequences by \TeX{} when "\cs:w" "..." "\cs_end:" is % used). % \end{function} % % \begin{function}{% % \chk_exist_cs:N | % \chk_exist_cs:c % } % \begin{syntax} % "\chk_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 | % \c_false % } % \begin{syntax} % \end{syntax} % Constants that represent `true' or `false', respectively. Used to % implement predicates. % \end{variable} % % % % \subsection{Selecting and discarding tokens from the input stream} % % The conditional processing could not have been implemented without % being able to gobble and select which tokens to use from the input % stream. % % \begin{function}{% % \use_none:n | % \use_none:nn | % \use_none:nnn | % \use_none:nnnn | % \use_none:nnnnn | % \use_none:nnnnnn | % \use_none:nnnnnnn | % \use_none:nnnnnnnn | % \use_none:nnnnnnnnn | % } % \begin{syntax} % "\use_none:n" "{""}"\\ % "\use_none:nn" "{""}{""}" % \end{syntax} % These functions gobble the tokens or brace groups from the input % stream. % \end{function} % % % \begin{function}{\use_arg_i:n} % \begin{syntax} % "\use_arg_i:n" "{" "}" % \end{syntax} % Function that executes the next argument after removing the % surrounding braces. Used to implement conditionals. % \end{function} % % \begin{function}{% % \use_arg_i:nn | % \use_arg_ii:nn | % } % \begin{syntax} % "\use_arg_i:nn" "{" "}{" "}" % \end{syntax} % Functions that execute the first or second argument respectively, % after removing the surrounding braces. Primarily used to implement % conditionals. % \end{function} % % \begin{function}{% % \use_arg_i:nnn | % \use_arg_ii:nnn | % \use_arg_iii:nnn | % } % \begin{syntax} % "\use_arg_i:nnn" "{" "}{" "}{" "}" % \end{syntax} % Functions that pick up one of three arguments and execute them after % removing the surrounding braces. Should be described somewhere else. % \end{function} % % \begin{function}{% % \use_arg_i:nnnn | % \use_arg_ii:nnnn | % \use_arg_iii:nnnn | % \use_arg_iv:nnnn | % } % \begin{syntax} % "\use_arg_i:nnnn" "{" "}{" "}{" "}{" "}" % \end{syntax} % Functions that pick up one of four arguments and execute them after % removing the surrounding braces. % \end{function} % % A different kind of functions for selecting tokens from the token % stream are those that use delimited arguments. % % \begin{function}{% % \use_none_delimit_by_q_nil:w | % \use_none_delimit_by_q_stop:w | % } % \begin{syntax} % "\use_none_delimit_by_q_nil:w" "\q_nil" % \end{syntax} % Gobbles . Useful in gobbling the remainder in a list % structure. % \end{function} % % \begin{function}{% % \use_arg_i_delimit_by_q_nil:nw | % \use_arg_i_delimit_by_q_stop:nw | % } % \begin{syntax} % "\use_arg_i_delimit_by_q_nil:nw" "{""}" "\q_nil" % \end{syntax} % Gobbles and executes afterwards. This can also % be used to get the first item in a token list. % \end{function} % % % \begin{function}{% % \use_arg_i_after_fi:nw | % \use_arg_i_after_else:nw | % \use_arg_i_after_or:nw | % \use_arg_i_after_orelse:nw % } % \begin{syntax} % "\use_arg_i_after_fi:nw" "{""}" "\fi:" % "\use_arg_i_after_else:nw" "{""}" "\else:" "\fi:" % "\use_arg_i_after_or:nw" "{""}" "\or:" "\fi:" % "\use_arg_i_after_orelse:nw" "{""}" "\or:/\else:" "\fi:" % \end{syntax} % Executes after executing closing out % "\fi:". "\use_arg_i_after_orelse:nw" can be used anywhere where % "\use_arg_i_after_else:nw" or "\use_arg_i_after_or:nw" are used. % \end{function} % % \subsection{Internal functions} % % \begin{function}{% % \cs:w | % \cs_end: % } % \begin{syntax} % "\cs:w" "\cs_end:" % \end{syntax} % This is the \TeX{} internal way of generating a control sequence from % some token list. get expanded and must ultimately result in a % sequence of characters. % \begin{texnote} % These functions are the primitives \tn{csname} and \tn{endcsname}. % "\cs:w" is considered weird because it expands tokens until it reaches % "\cs_end:". % \end{texnote} % \end{function} % % \begin{function}{\pref_global:D | % \pref_long:D | % \pref_protected:D | % } % \begin{syntax} % "\pref_global:D" "\def:Npn" % \end{syntax} % Prefix functions that can be used in front of some definition % functions (namely \ldots). The result of prefixing a function % definition with "\pref_global:D" makes the definition global, % "\pref_long:D" change the argument scanning mechanism so that it % allows "\par" tokens in the argument of the prefixed function, % and "\pref_protected:D" makes the definition robust in "\write"s etc. % % % None of these internal functions should be used by a programmer since % the necessary combinations are all available as separate function, % e.g., "\def_long:Npn" is internally implemented as "\pref_long:D" % "\def:Npn". % \begin{texnote} % These prefixes are the primitives \tn{global}, \tn{long}, and % \tn{protected}. The \tn{outer} isn't used at all within \LaTeX3 % because \ldots % \end{texnote} % \end{function} % % % % \begin{function}{\io_put_log:x | % \io_put_term:x | % \io_put_deferred:Nx | % } % \begin{syntax} % "\io_put_log:x" "{""}" % "\io_put_deferred:Nx" "{""}" % \end{syntax} % Writes to either to log or the terminal. % \end{function} % % \subsection{Defining functions} % % % There are two types of function definitions in \LaTeX3: versions % that check if the function name is still unused, and versions that % simply make the definition. The later are used for internal scratch % functions that get new meanings all over the place. % % For each type there is an additional choice to be made: Does the % function to be defined contain delimited arguments? The answer in % 99\% of the cases is no, so in most cases the programmer just want % to input the number of arguments, which is basically how % \cs{newcommand} in \LaTeXe{} works. Therefore we provide functions % that expect a number as the primary type and later on in this module % you can find the ones with the more primitive syntax. % % 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} % % % \subsubsection{Defining new functions} % % Firstly comes to variants most used namely those taking a number to % denote the number of arguments. % % \begin{function}{\def_new:NNn | % \def_new:NNx | % \def_new:cNn | % \def_new:cNx % } % \begin{syntax} % "\def_new:NNn" "{" "}" % \end{syntax} % Defines a new function, making sure that is unused so far. % is the number of arguments which is in the interval $[0,9]$ % otherwise an error is raised. It is under the responsibility of the % programmer to name the new function according to the rules laid out % in the previous section. is either passed literally or may % be subject to expansion (under the "x" variants). % \end{function} % % \begin{function}{\gdef_new:NNn | % \gdef_new:cNn | % \gdef_new:NNx | % \gdef_new:cNx % } % \begin{syntax} % "\gdef_new:NNn" "{" "}" % \end{syntax} % Like "\def_new:NNn" but defines the new function globally. % \end{function} % % \begin{function}{\def_long_new:NNn | % \def_long_new:NNx | % \def_long_new:cNn | % \def_long_new:cNx % } % \begin{syntax} % "\def_long_new:NNn" "{" "}" % \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}{\gdef_long_new:NNn | % \gdef_long_new:NNx | % \gdef_long_new:cNn | % \gdef_long_new:cNx % } % \begin{syntax} % "\gdef_long_new:NNn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_new:NNn | % \def_protected_new:NNx | % \def_protected_new:cNn | % \def_protected_new:cNx % } % \begin{syntax} % "\def_protected_new:NNn" "{" "}" % \end{syntax} % Defines a function that does not expand when inside an |x| type % expansion. % \end{function} % % \begin{function}{\gdef_protected_new:NNn | % \gdef_protected_new:NNx | % \gdef_protected_new:cNn | % \gdef_protected_new:cNx % } % \begin{syntax} % "\gdef_protected_new:NNn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_long_new:NNn | % \def_protected_long_new:NNx | % \def_protected_long_new:cNn | % \def_protected_long_new:cNx % } % \begin{syntax} % "\def_protected_long_new:NNn" "{" "}" % \end{syntax} % Defines a function that is both robust and may contain "\par" tokens % in the argument(s) when called. % \end{function} % % \begin{function}{\gdef_protected_long_new:NNn | % \gdef_protected_long_new:NNx | % \gdef_protected_long_new:cNn | % \gdef_protected_long_new:cNx % } % \begin{syntax} % "\gdef_protected_long_new:NNn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % % % % % Secondly comes the ones where the programmer can use delimited % arguments. Rarely needed outside the kernel. % % % \begin{function}{\def_new:Npn | % \def_new:Npx | % \def_new:cpn | % \def_new:cpx % } % \begin{syntax} % "\def_new:Npn" "{" "}" % \end{syntax} % Defines a new function, making sure that is unused so far. % may consist of arbitrary parameter specification in \TeX{} % syntax. It is under the responsibility of the programmer to name the % new function according to the rules laid out in the previous section. % is either passed literally or may be subject to expansion % (under the "x" variants). % \end{function} % % \begin{function}{\gdef_new:Npn | % \gdef_new:cpn | % \gdef_new:Npx | % \gdef_new:cpx % } % \begin{syntax} % "\gdef_new:Npn" "{" "}" % \end{syntax} % Like "\def_new:Npn" but defines the new function globally. See % comments above. % \end{function} % % \begin{function}{\def_long_new:Npn | % \def_long_new:Npx | % \def_long_new:cpn | % \def_long_new:cpx % } % \begin{syntax} % "\def_long_new:Npn" "{" "}" % \end{syntax} % Defines a function that may contain "\par" tokens in the argument(s) % when called. This is not allowed for normal functions. % \end{function} % % \begin{function}{\gdef_long_new:Npn | % \gdef_long_new:Npx | % \gdef_long_new:cpn | % \gdef_long_new:cpx % } % \begin{syntax} % "\gdef_long_new:Npn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_new:Npn | % \def_protected_new:Npx | % \def_protected_new:cpn | % \def_protected_new:cpx % } % \begin{syntax} % "\def_protected_new:Npn" "{" "}" % \end{syntax} % Defines a function that does not expand when inside an |x| type % expansion. % \end{function} % % \begin{function}{\gdef_protected_new:Npn | % \gdef_protected_new:Npx | % \gdef_protected_new:cpn | % \gdef_protected_new:cpx % } % \begin{syntax} % "\gdef_protected_new:Npn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_long_new:Npn | % \def_protected_long_new:Npx | % \def_protected_long_new:cpn | % \def_protected_long_new:cpx % } % \begin{syntax} % "\def_protected_long_new:Npn" "{" "}" % \end{syntax} % Defines a function that is both robust and may contain "\par" tokens % in the argument(s) when called. % \end{function} % % \begin{function}{\gdef_protected_long_new:Npn | % \gdef_protected_long_new:Npx | % \gdef_protected_long_new:cpn | % \gdef_protected_long_new:cpx % } % \begin{syntax} % "\gdef_protected_long_new:Npn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\let_new:NN | % \let_new:cN | % \let_new:Nc | % \let_new:cc | % \glet_new:NN| % \glet_new:cN| % \glet_new:Nc| % \glet_new:cc } % \begin{syntax} % "\let_new:NN" % \end{syntax} % Gives the function the current meaning of . Again, we may % do this always globally. % \end{function} % % % % \subsubsection{Undefining functions} % % \begin{function}{ \cs_gundefine:N % } % \begin{syntax} % "\cs_gundefine:N" % \end{syntax} % Undefines the control sequence. % \end{function} % % \subsubsection{Defining internal functions (no checks)} % % Besides the function definitions that check whether or not their % argument is an unused function we need function definitions that % overwrite currently used definitions. The following functions are % provided for this purpose. % % First comes the versions expecting a number to denote the number of % arguments. % % \begin{function}{\def:NNn | % \def:NNx | % \def:cNn | % \def:cNx | % } % \begin{syntax} % "\def:NNn" "{" "}" % \end{syntax} % Like "\def_new:NNn" etc.\ but does not check the name. % \end{function} % % \begin{function}{\gdef:NNn | % \gdef:NNx | % \gdef:cNn | % \gdef:cNx | % } % \begin{syntax} % "\gdef:NNn" "{" "}" % \end{syntax} % Like "\def:NNn" but defines the globally. % \end{function} % % % \begin{function}{\def_long:NNn | % \def_long:NNx | % \def_long:cNn | % \def_long:cNx | % } % \begin{syntax} % "\def_long:NNn" "{" "}" % \end{syntax} % Like "\def:NNn" but allows "\par" tokens in the arguments of the % function being defined. % \end{function} % % \begin{function}{\gdef_long:NNn | % \gdef_long:NNx | % \gdef_long:cNn | % \gdef_long:cNx | % } % \begin{syntax} % "\gdef_long:NNn" "{" "}" % \end{syntax} % Global variant of "\def_long:NNn". % \end{function} % % \begin{function}{\def_protected:NNn | % \def_protected:cNn | % \def_protected:NNx | % \def_protected:cNx | % } % \begin{syntax} % "\def_protected:NNn" "{" "}" % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. % This also comes as a |long| version. If you for some reason want to % expand it inside an |x| type expansion, prefix it with % |\exp_after:NN \use_noop:|. % \end{function} % % \begin{function}{\gdef_protected:NNn | % \gdef_protected:cNn | % \gdef_protected:NNx | % \gdef_protected:cNx | % } % \begin{syntax} % "\gdef_protected:NNn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_long:NNn | % \def_protected_long:cNn | % \def_protected_long:NNx | % \def_protected_long:cNx | % } % \begin{syntax} % "\def_protected_long:NNn" "{" "}" % \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}{\gdef_protected_long:NNn | % \gdef_protected_long:cNn | % \gdef_protected_long:NNx | % \gdef_protected_long:cNx | % } % \begin{syntax} % "\gdef_protected_long:NNn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % Secondly the ones that use the primitive parameter build-up: % % \begin{function}{\def:Npn | % \def:Npx | % \def:cpn | % \def:cpx | % } % \begin{syntax} % "\def:Npn" "{" "}" % \end{syntax} % Like "\def_new:Npn" etc.\ but does not check the name. % \begin{texnote} % "\def:Npn" is the \LaTeX3 name for \TeX{}'s \tn{def} and "\def:Npx" % corresponds to the primitive \tn{edef}. The "\def:cpn" function was % known in \LaTeX2 as \tn{@namedef}. "\def:cpx" has no equivalent. % \end{texnote} % \end{function} % % \begin{function}{\gdef:Npn | % \gdef:Npx | % \gdef:cpn | % \gdef:cpx | % } % \begin{syntax} % "\gdef:Npn" "{" "}" % \end{syntax} % Like "\def:Npn" but defines the globally. % \begin{texnote} % "\gdef:Npn" and "\gdef:Npx" are known to \TeX{}hackers as \tn{gdef} % and \tn{xdef}. % \end{texnote} % \end{function} % % % \begin{function}{\def_long:Npn | % \def_long:Npx | % \def_long:cpn | % \def_long:cpx | % } % \begin{syntax} % "\def_long:Npn" "{" "}" % \end{syntax} % Like "\def:Npn" but allows "\par" tokens in the arguments of the % function being defined. % \end{function} % % \begin{function}{\gdef_long:Npn | % \gdef_long:Npx | % \gdef_long:cpn | % \gdef_long:cpx | % } % \begin{syntax} % "\gdef_long:Npn" "{" "}" % \end{syntax} % Global variant of "\def_long:Npn". % \end{function} % % \begin{function}{\def_protected:Npn | % \def_protected:cpn | % \def_protected:Npx | % \def_protected:cpx | % } % \begin{syntax} % "\def_protected:Npn" "{" "}" % \end{syntax} % Naturally robust macro that won't expand in an |x| type argument. % This also comes as a |long| version. If you for some reason want to % expand it inside an |x| type expansion, prefix it with % |\exp_after:NN \use_noop:|. % \end{function} % % \begin{function}{\gdef_protected:Npn | % \gdef_protected:cpn | % \gdef_protected:Npx | % \gdef_protected:cpx | % } % \begin{syntax} % "\gdef_protected:Npn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % \begin{function}{\def_protected_long:Npn | % \def_protected_long:cpn | % \def_protected_long:Npx | % \def_protected_long:cpx | % } % \begin{syntax} % "\def_protected_long:Npn" "{" "}" % \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}{\gdef_protected_long:Npn | % \gdef_protected_long:cpn | % \gdef_protected_long:Npx | % \gdef_protected_long:cpx | % } % \begin{syntax} % "\gdef_protected_long:Npn" "{" "}" % \end{syntax} % Global versions of the above functions. % \end{function} % % % % \begin{function}{\let:NN | % \let:cN | % \let:Nc | % \let:cc | % \glet:NN | % \glet:cN | % \glet:Nc | % \glet:cc % } % \begin{syntax} % "\let:cN" % \end{syntax} % Gives the function the current meaning of . Again, we may % always do this globally. % \end{function} % % \begin{function}{\let:NwN} % \begin{syntax} % "\let:NwN" % "\let:NwN" "=" % \end{syntax} % These functions assign the meaning of locally or globally to the % function . Because the \TeX{} primitive operation is being used % which may have an equal sign and (a certain number of) spaces between % and the name contains a "w". (Not happy about this % convention!). % \begin{texnote} % "\let:NwN" is the \LaTeX3 name for \TeX{}'s \tn{let}. % \end{texnote} % \end{function} % % % \subsection{Defining test functions} % % % \begin{function}{ % \def_test_function:npn | % \def_long_test_function:npn | % \def_test_function_new:npn | % \def_long_test_function_new:npn | % } % \begin{syntax} % "\def_test_function_new:npn" "{"name"}" "{""}" % \end{syntax} % Define all the common test cases for a simple test to reduce the % risk of typos. As an example here's how we defined the functions % "\cs_free:cTF", "\cs_free:cT" and "\cs_free:cF". You just have to % fill in the test. % \begin{verbatim} % \def_test_function:npn{cs_free:c} #1 { % \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} % \end{verbatim} % Be careful not to use this function inside some primitive % conditional as \TeX\ will most likely get confused because of the % unmatched conditionals. % \end{function} % % % \subsection{The innards of a function} % % \begin{function}{\cs_to_str:N} % \begin{syntax} % "\cs_to_str:N" % \end{syntax} % This function return the name of as a sequence of letters with % the escape character removed. % \end{function} % % \begin{function}{\token_to_string:N} % \begin{syntax} % "\token_to_string:N" % \end{syntax} % This function return the name of as a sequence of letters % including the escape character. % \end{function} % % \begin{function}{\token_to_meaning:N} % \begin{syntax} % "\token_to_meaning:N" % \end{syntax} % This function returns the type and definition of as a sequence % of letters. % \end{function} % % Other functions regarding arbitrary tokens can be found in the % \textsf{l3token} module. % % \subsection{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} % % % \subsection{Engine specific definitions} % % \begin{function}{\engine_if_aleph:TF} % \begin{syntax} % "\engine_if_aleph:TF" "{""}" "{""}" % \end{syntax} % This function detects if we're running an Aleph based format. This % is particularly useful when allocating registers. % \end{function} % % % % \StopEventually{} % % % \subsection{The Implementation} % We start by ensuring that the required packages are loaded. We need % \textsf{l3names} to get things going but we actually need it very % early on, so it is loaded at the very top of this file. Also, most % of the code below won't run until \textsf{l3expan} has been % loaded. % % \subsubsection{Renaming some \TeX{} primitives (again)} % % \begin{macro}{\let: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} %\ProvidesExplPackage % {\filename}{\filedate}{\fileversion}{\filedescription} %<*initex|package> \tex_let:D \let:NwN \tex_let:D % \end{macrocode} % \end{macro} % \begin{macro}{\if_true:} % \begin{macro}{\if_false:} % \begin{macro}{\else:} % \begin{macro}{\fi:} % \begin{macro}{\reverse_if:N} % \begin{macro}{\if:w} % \begin{macro}{\if_charcode:w} % \begin{macro}{\if_catcode:w} % Then some conditionals. % \begin{macrocode} \let:NwN \if_true: \tex_iftrue:D \let:NwN \if_false: \tex_iffalse:D \let:NwN \else: \tex_else:D \let:NwN \fi: \tex_fi:D \let:NwN \reverse_if:N \etex_unless:D \let:NwN \if:w \tex_if:D \let:NwN \if_charcode:w \tex_if:D \let:NwN \if_catcode:w \tex_ifcat:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\if_meaning:NN} % \begin{macro}{\if_token_eq:NN} % \begin{macro}{\if_cs_meaning_eq:NN} % Some different names for |\ifx|.\footnote{MH: Clean up at some point} % \begin{macrocode} \let:NwN \if_meaning:NN \tex_ifx:D \let:NwN \if_token_eq:NN \tex_ifx:D \let:NwN \if_cs_meaning_eq:NN\tex_ifx:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\if_mode_math:} % \begin{macro}{\if_mode_horizontal:} % \begin{macro}{\if_mode_vertical:} % \begin{macro}{\if_mode_inner:} % \TeX{} lets us detect some if its modes. % \begin{macrocode} \let:NwN \if_mode_math: \tex_ifmmode:D \let:NwN \if_mode_horizontal:\tex_ifhmode:D \let:NwN \if_mode_vertical: \tex_ifvmode:D \let:NwN \if_mode_inner: \tex_ifinner:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\if_cs_exist:N} % \begin{macro}{\if_cs_exist:w} % \begin{macrocode} \let:NwN \if_cs_exist:N \etex_ifdefined:D \let:NwN \if_cs_exist:w \etex_ifcsname:D % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\exp_after:NN} % \begin{macro}{\exp_not:N} % \begin{macro}{\exp_not:n} % The three |\exp_| functions are used in the \textsf{l3expan} module % where they are described. % \begin{macrocode} \let:NwN \exp_after:NN \tex_expandafter:D \let:NwN \exp_not:N \tex_noexpand:D \let:NwN \exp_not:n \etex_unexpanded:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\io_put_deferred:Nx} % \begin{macro}{\token_to_meaning:N} % \begin{macro}{\token_to_string:N} % \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} \let:NwN \io_put_deferred:Nx \tex_write:D \let:NwN \token_to_meaning:N \tex_meaning:D \let:NwN \token_to_string:N \tex_string:D \let:NwN \cs:w \tex_csname:D \let:NwN \cs_end: \tex_endcsname:D \let:NwN \cs_meaning:N \tex_meaning:D \tex_def:D \cs_meaning:c #1{\exp_after:NN\cs_meaning:N\cs:w #1\cs_end:} \let:NwN \cs_show:N \tex_show:D \tex_def:D \cs_show:c #1{\exp_after:NN\cs_show:N\cs:w #1\cs_end:} % \end{macrocode} % \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} \let:NwN \scan_stop: \tex_relax:D \let:NwN \group_begin: \tex_begingroup:D \let:NwN \group_end: \tex_endgroup:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macro}{\group_execute_after:N} % \begin{macrocode} \let:NwN \group_execute_after:N \tex_aftergroup:D % \end{macrocode} % \end{macro} % \begin{macro}{\the_internal:D} % \begin{macro}{\pref_global:D} % \begin{macro}{\pref_long:D} % \begin{macro}{\pref_protected:D} % These following names are temporary and should be removed as soon % as possible (April 1998). % \begin{macrocode} \let:NwN \the_internal:D \tex_the:D \let:NwN \pref_global:D \tex_global:D % \end{macrocode} % "\pref_long:D" has been documented for years but didn't exist\dots{} % Added it and the robustness prefix. % \begin{macrocode} \let:NwN \pref_long:D \tex_long:D \let:NwN \pref_protected:D \etex_protected:D % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \subsubsection {Defining functions} % % % We start by providing functions for the typical definition % functions. First the local ones. % % \begin{macro}{\def:Npn} % \begin{macro}{\def:Npx} % \begin{macro}{\def_long:Npn} % \begin{macro}{\def_long:Npx} % \begin{macro}{\def_protected:Npn} % \begin{macro}{\def_protected:Npx} % \begin{macro}{\def_protected_long:Npn} % \begin{macro}{\def_protected_long:Npx} % All assignment functions in \LaTeX3 should be naturally robust; % after all, the \TeX\ primitives for assignments are and it can be % a cause of problems if others aren't. % \begin{macrocode} \let:NwN \def:Npn \tex_def:D \let:NwN \def:Npx \tex_edef:D \pref_protected:D \def:Npn \def_long:Npn {\pref_long:D \def:Npn} \pref_protected:D \def:Npn \def_long:Npx {\pref_long:D \def:Npx} \pref_protected:D \def:Npn \def_protected:Npn {\pref_protected:D \def:Npn} \pref_protected:D \def:Npn \def_protected:Npx {\pref_protected:D \def:Npx} \def_protected:Npn \def_protected_long:Npn { \pref_protected:D \pref_long:D \def:Npn } \def_protected:Npn \def_protected_long:Npx { \pref_protected:D \pref_long:D \def:Npx } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\gdef:Npn} % \begin{macro}{\gdef:Npx} % \begin{macro}{\gdef_long:Npn} % \begin{macro}{\gdef_long:Npx} % \begin{macro}{\gdef_protected:Npn} % \begin{macro}{\gdef_protected:Npx} % \begin{macro}{\gdef_protected_long:Npn} % \begin{macro}{\gdef_protected_long:Npx} % Global versions of the above functions. % \begin{macrocode} \let:NwN \gdef:Npn \tex_gdef:D \let:NwN \gdef:Npx \tex_xdef:D \def_protected:Npn \gdef_long:Npn {\pref_long:D \gdef:Npn} \def_protected:Npn \gdef_long:Npx {\pref_long:D \gdef:Npx} \def_protected:Npn \gdef_protected:Npn {\pref_protected:D \gdef:Npn} \def_protected:Npn \gdef_protected:Npx {\pref_protected:D \gdef:Npx} \def_protected:Npn \gdef_protected_long:Npn { \pref_protected:D \pref_long:D \gdef:Npn } \def_protected:Npn \gdef_protected_long:Npx { \pref_protected:D \pref_long:D \gdef:Npx } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Predicate implementation} % % I think Michael originated the idea of expandable boolean tests. At % first these were supposed to expand into either \texttt{TT} or % \texttt{TF} to be tested using |\if:w| but this was later changed to % \texttt{00} and \texttt{01}, so they can be used in logical % operations (see the \textsf{l3prg} module). We need this from the % get-go. % % \begin{macro}{\c_true} % \begin{macro}{\c_false} % Here are the canonical boolean values. % \begin{macrocode} \def:Npn \c_true {00} \def:Npn \c_false {01} % \end{macrocode} % \end{macro} % \end{macro} % % \subsubsection {Defining and checking (new) functions} % % \begin{macro}{\c_minus_one} % \begin{macro}{\c_sixteen} % We need the constants |\c_minus_one| and |\c_sixteen| now for % writing information to the log and the terminal but the % rest are defined in the \textsf{l3num} module -- at least for the % ones that can be defined with |\tex_chardef:D| or % |\tex_mathchardef:D|. Otherwise the \textsf{l3int} module is % required but it can't be used until the allocation has been set % up properly! The actual allocation mechanism is in % \textsf{l3alloc} and as \TeX{} wants to reserve count registers % 0--9, the first available one is~10 so we use that for % |\c_minus_one|. % \begin{macrocode} %<*!initex> \let:NwN \c_minus_one\m@ne % %<*!package> \tex_countdef:D \c_minus_one = 10 \scan_stop: \c_minus_one = -1 \scan_stop: % \tex_chardef:D \c_sixteen = 16\scan_stop: % \end{macrocode} % \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}{\io_put_log:x} % \begin{macro}{\io_put_term:x} % We define a routine to write only to the log file. And a % similar one for writing to both the log file and the terminal. % % \begin{macrocode} \def:Npn \io_put_log:x{ \tex_immediate:D\io_put_deferred:Nx \c_minus_one } \def:Npn \io_put_term:x{ \tex_immediate:D\io_put_deferred:Nx \c_sixteen } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\err_latex_bug:x} % This will show internal errors. % \begin{macrocode} \def:Npn\err_latex_bug:x#1{ \io_put_term:x{This~is~a~LaTeX~bug!~Check~coding!}\tex_errmessage:D{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\cs_record_meaning:N} % This macro will be used later on for tracing purposes. But we % need some more modules to define it, so we just give some dummy % definition here. % \begin{macrocode} %<*trace> \def:Npn \cs_record_meaning:N#1{} % % \end{macrocode} % \end{macro} % % We need these two to make |\chk_new_cs:N| bulletproof. % \begin{macrocode} \def_long:Npn \use_none:n #1{} \def_long:Npn \use_arg_i:n #1{#1} % \end{macrocode} % \begin{macro}{\chk_new_cs:N} % This command is called by |\def_new:Npn| and |\let_new:NN| etc.\ % to make sure that the argument sequence is not already in use. If % it is, an error is signalled. It checks if \m{csname} is % undefined or |\scan_stop:|. Otherwise an error message is % issued. We have to make sure we don't put the argument into the % conditional processing since it may be an |\if...| type function! % \begin {macrocode} \def:Npn \chk_new_cs:N #1{ \if:w \cs_if_free_p:N #1 \exp_after:NN \use_none:n \else: \exp_after:NN \use_arg_i:n \fi: { \err_latex_bug:x {Command~name~`\token_to_string:N #1'~ already~defined!~ Current~meaning:~\token_to_meaning:N #1 } } %<*trace> \cs_record_meaning:N#1 % \io_put_term:x{Defining~\token_to_string:N #1~on~%} \io_put_log:x{Defining~\token_to_string:N #1~on~ line~\tex_the:D \tex_inputlineno:D} % } % \end{macrocode} % \end{macro} % % On 2005/11/20 Morten said: I think names for testing if a certain % condition is true or false should always contain |if| to avoid % confusion. This is what we do for lots of other types of test % functions. For now I have defined both names for the functions % checking names of control sequences. % % \begin{macro}{\cs_if_exist_p:N} % Expands into |\c_true| if the control sequence given as its % argument \emph{is} in use. % \begin{macrocode} \def:Npn \cs_if_exist_p:N #1{ \if:w \cs_if_free_p:N #1 \c_false \else: \c_true \fi:} % \end{macrocode} % \end{macro} % % \begin{macro}{\chk_if_exist_cs:N } % \begin{macro}{\chk_if_exist_cs:c } % This function issues a warning message when the control sequence % in its argument does not exist. % \begin{macrocode} \def:Npn \chk_if_exist_cs:N #1 { \if:w \cs_if_exist_p:N #1 \else: \err_latex_bug:x{Command~ `\token_to_string:N #1'~ not~ yet~ defined!} \fi:} \def:Npn \chk_if_exist_cs:c #1 { \exp_after:NN \chk_if_exist_cs:N \cs:w #1\cs_end: } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\cs_if_free_p:N} % Expands into |\c_true| if the control sequence given as its % argument is not yet in use. Note that we make sure to expand % into |\c_false| if the control sequence is textually % |\c_undefined| or |\scan_stop:|, so that we don't end up % (re)defining them. % \begin{macrocode} \def:Npn \cs_if_free_p:N #1{ \if_cs_exist:N #1 \if_meaning:NN#1\scan_stop: \if:w\cs_if_eq_name_p:NN #1\scan_stop: \c_false \else: \c_true \fi: \else: \c_false \fi: \else: \if:w \cs_if_eq_name_p:NN #1\c_undefined \c_false \else: \c_true \fi: \fi: } \let:NwN \cs_free_p:N \cs_if_free_p:N % \end{macrocode} % \end{macro} % % % \begin{macro}{\str_if_eq_p:nn} % \begin{macro}{\str_if_eq_p_aux:w} % Takes 2 lists of characters as arguments and expands into % |\c_true| if they are equal, and |\c_false| otherwise. Note that % in the current implementation spaces in these strings are % ignored.\footnote{This is a function which could use % \cs{tlist_compare:xx}.} % \begin{macrocode} \def:Npn \str_if_eq_p:nn #1#2{ \str_if_eq_p_aux:w #1\scan_stop:\\#2\scan_stop:\\ } \def:Npn \str_if_eq_p_aux:w #1#2\\#3#4\\{ \if_meaning:NN#1#3 \if_meaning:NN#1\scan_stop:\c_true \else: \if_meaning:NN#3\scan_stop:\c_false \else: \str_if_eq_p_aux:w #2\\#4\\\fi:\fi: \else:\c_false \fi:} % \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} \def_long:Npn \cs_if_eq_name_p:NN #1#2{ \exp_after:NN\exp_after:NN \exp_after:NN\str_if_eq_p_aux:w \exp_after:NN\token_to_string:N \exp_after:NN#1 \exp_after:NN\scan_stop: \exp_after:NN\\ \token_to_string:N#2\scan_stop:\\} % \end{macrocode} % \end{macro} % % % \begin{macro}{\str_if_eq_var_p:nf} % \begin{macro}{\str_if_eq_var_start:nnN} % \begin{macro}{\str_if_eq_var_stop:w} % A variant of |\str_if_eq_p:nn| which has the advantage of obeying % spaces in at least the second argument. See \textsf{l3quark} for % an application. From the hand of David Kastrup with slight % modifications to make it fit with the remainder of the expl3 % language. % % The macro builds a string of |\if:w \fi:| pairs from the first % argument. The idea is to turn the comparison of |ab| and |cde| % into % \begin{verbatim} % \tex_number:D % \if:w \scan_stop: \if:w b\if:w a cde\scan_stop: '\fi: \fi: \fi: % 13 % \end{verbatim} % The |'| is important here. If all tests are true, the |'| is read % as part of the number in which case the returned number is |13| in % octal notation so |\tex_number:D| returns |11|. If one test % returns false the |'| is never seen and then we get just |13|. We % wrap the whole process in an external |\if:w| in order to make it % return either |\c_true| or |\c_false| since some parts of % \textsf{l3prg} expect a predicate to return one of these two % tokens. % \begin{macrocode} \def:Npn \str_if_eq_var_p:nf#1{ \if:w \tex_number:D\str_if_eq_var_start:nnN{}{}#1\scan_stop: } \def:Npn\str_if_eq_var_start:nnN#1#2#3{ \if:w#3\scan_stop:\exp_after:NN\str_if_eq_var_stop:w\fi: \str_if_eq_var_start:nnN{\if:w#3#1}{#2\fi:} } \def:Npn\str_if_eq_var_stop:w\str_if_eq_var_start:nnN#1#2#3{ #1#3\scan_stop:'#213~\c_true\else:\c_false\fi: } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % % % \subsubsection{More new definitions} % % % % \begin{macro}{\def_new:Npn} % \begin{macro}{\def_new:Npx} % \begin{macro}{\def_long_new:Npn} % \begin{macro}{\def_long_new:Npx} % \begin{macro}{\def_protected_new:Npn} % \begin{macro}{\def_protected_new:Npx} % \begin{macro}{\def_protected_long_new:Npn} % \begin{macro}{\def_protected_long_new:Npx} % These are like |\def:Npn| and |\let:NN|, but they first check that % the argument command is not already in use. You may use % |\pref_global:D|, |\pref_long:D|, |\pref_protected:D|, and % |\tex_outer:D| as prefixes. % \begin {macrocode} \def_protected:Npn \def_new:Npn #1{\chk_new_cs:N #1 \def:Npn #1} \def_protected:Npn \def_new:Npx #1{\chk_new_cs:N #1 \def:Npx #1} \def_protected:Npn \def_long_new:Npn #1{\chk_new_cs:N #1 \def_long:Npn #1} \def_protected:Npn \def_long_new:Npx #1{\chk_new_cs:N #1 \def_long:Npx #1} \def_protected:Npn \def_protected_new:Npn #1{\chk_new_cs:N #1 \def_protected:Npn #1} \def_protected:Npn \def_protected_new:Npx #1{\chk_new_cs:N #1 \def_protected:Npx #1} \def_protected:Npn \def_protected_long_new:Npn #1{\chk_new_cs:N #1 \def_protected_long:Npn #1} \def_protected:Npn \def_protected_long_new:Npx #1{\chk_new_cs:N #1 \def_protected_long:Npx #1} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\gdef_new:Npn} % \begin{macro}{\gdef_new:Npx} % \begin{macro}{\gdef_long_new:Npn} % \begin{macro}{\gdef_long_new:Npx} % \begin{macro}{\gdef_protected_new:Npn} % \begin{macro}{\gdef_protected_new:Npx} % \begin{macro}{\gdef_protected_long_new:Npn} % \begin{macro}{\gdef_protected_long_new:Npx} % Global versions of the above functions. % \begin {macrocode} \def_protected_new:Npn \gdef_new:Npn #1{\chk_new_cs:N #1 \gdef:Npn #1} \def_protected_new:Npn \gdef_new:Npx #1{\chk_new_cs:N #1 \gdef:Npx #1} \def_protected_new:Npn \gdef_long_new:Npn #1{\chk_new_cs:N #1 \gdef_long:Npn #1} \def_protected_new:Npn \gdef_long_new:Npx #1{\chk_new_cs:N #1 \gdef_long:Npx #1} \def_protected_new:Npn \gdef_protected_new:Npn #1{\chk_new_cs:N #1 \gdef_protected:Npn #1} \def_protected_new:Npn \gdef_protected_new:Npx #1{\chk_new_cs:N #1 \gdef_protected:Npx #1} \def_protected_new:Npn \gdef_protected_long_new:Npn #1{\chk_new_cs:N #1 \gdef_protected_long:Npn #1} \def_protected_new:Npn \gdef_protected_long_new:Npx #1{\chk_new_cs:N #1 \gdef_protected_long:Npx #1} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\def:cpn} % \begin{macro}{\def:cpx} % \begin{macro}{\gdef:cpn} % \begin{macro}{\gdef:cpx} % \begin{macro}{\def_new:cpn} % \begin{macro}{\def_new:cpx} % \begin{macro}{\gdef_new:cpn} % \begin{macro}{\gdef_new:cpx} % Like |\def:Npn| and |\def_new:Npn|, except that the first argument % consists of the sequence of characters that should be used to form % the name of the desired control sequence (the |c| stands for % csname argument, see the expansion module.). Global versions are % also provided. % % |\def:cpn|\m{string}\m{rep-text} will turn \m{string} into a % csname and then assign \m {rep-text} to it by using |\def:Npn|. % This means that there might be a parameter string between the two % arguments. % \begin{macrocode} \def_new:Npn \def:cpn #1{\exp_after:NN \def:Npn \cs:w #1\cs_end:} \def_new:Npn \def:cpx #1{\exp_after:NN \def:Npx \cs:w #1\cs_end:} \def_new:Npn \gdef:cpn #1{\exp_after:NN \gdef:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef:cpx #1{\exp_after:NN \gdef:Npx \cs:w #1\cs_end:} \def_new:Npn \def_new:cpn #1{\exp_after:NN \def_new:Npn \cs:w #1\cs_end:} \def_new:Npn \def_new:cpx #1{\exp_after:NN \def_new:Npx \cs:w #1\cs_end:} \def_new:Npn \gdef_new:cpn #1{\exp_after:NN \gdef_new:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_new:cpx #1{\exp_after:NN \gdef_new:Npx \cs:w #1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macro}{\def_long:cpn} % \begin{macro}{\def_long:cpx} % \begin{macro}{\gdef_long:cpn} % \begin{macro}{\gdef_long:cpx} % \begin{macro}{\def_long_new:cpn} % \begin{macro}{\def_long_new:cpx} % \begin{macro}{\gdef_long_new:cpn} % \begin{macro}{\gdef_long_new:cpx} % Variants of the |\def_long:Npn| versions which make a csname out % of the first arguments. We may also do this globally. % \begin{macrocode} \def_new:Npn \def_long:cpn #1{\exp_after:NN \def_long:Npn \cs:w #1\cs_end:} \def_new:Npn \def_long:cpx #1{ \exp_after:NN\def_long:Npx\cs:w #1\cs_end:} \def_new:Npn \gdef_long:cpn #1{ \exp_after:NN \gdef_long:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_long:cpx #1{ \exp_after:NN\gdef_long:Npx\cs:w #1\cs_end:} \def_new:Npn \def_long_new:cpn #1{ \exp_after:NN \def_long_new:Npn \cs:w #1\cs_end:} \def_new:Npn \def_long_new:cpx #1{ \exp_after:NN \def_long_new:Npx \cs:w #1\cs_end:} \def_new:Npn \gdef_long_new:cpn #1{ \exp_after:NN \gdef_long_new:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_long_new:cpx #1{ \exp_after:NN \gdef_long_new:Npx \cs:w #1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def_protected:cpn} % \begin{macro}{\def_protected:cpx} % \begin{macro}{\gdef_protected:cpn} % \begin{macro}{\gdef_protected:cpx} % \begin{macro}{\def_protected_new:cpn} % \begin{macro}{\def_protected_new:cpx} % \begin{macro}{\gdef_protected_new:cpn} % \begin{macro}{\gdef_protected_new:cpx} % Variants of the |\def_protected:Npn| versions which make a csname % out of the first arguments. We may also do this globally. % \begin{macrocode} \def_new:Npn \def_protected:cpn #1{ \exp_after:NN \def_protected:Npn \cs:w #1\cs_end:} \def_new:Npn \def_protected:cpx #1{ \exp_after:NN\def_protected:Npx\cs:w #1\cs_end:} \def_new:Npn \gdef_protected:cpn #1{ \exp_after:NN \gdef_protected:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_protected:cpx #1{ \exp_after:NN\gdef_protected:Npx\cs:w #1\cs_end:} \def_new:Npn \def_protected_new:cpn #1{ \exp_after:NN \def_protected_new:Npn \cs:w #1\cs_end:} \def_new:Npn \def_protected_new:cpx #1{ \exp_after:NN \def_protected_new:Npx \cs:w #1\cs_end:} \def_new:Npn \gdef_protected_new:cpn #1{ \exp_after:NN \gdef_protected_new:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_protected_new:cpx #1{ \exp_after:NN \gdef_protected_new:Npx \cs:w #1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def_protected_long:cpn} % \begin{macro}{\def_protected_long:cpx} % \begin{macro}{\gdef_protected_long:cpn} % \begin{macro}{\gdef_protected_long:cpx} % \begin{macro}{\def_protected_long_new:cpn} % \begin{macro}{\def_protected_long_new:cpx} % \begin{macro}{\gdef_protected_long_new:cpn} % \begin{macro}{\gdef_protected_long_new:cpx} % Variants of the |\def_protected_long:Npn| versions which make a csname % out of the first arguments. We may also do this globally. % \begin{macrocode} \def_new:Npn \def_protected_long:cpn #1{ \exp_after:NN \def_protected_long:Npn \cs:w #1\cs_end:} \def_new:Npn \def_protected_long:cpx #1{ \exp_after:NN\def_protected_long:Npx\cs:w #1\cs_end:} \def_new:Npn \gdef_protected_long:cpn #1{ \exp_after:NN \gdef_protected_long:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_protected_long:cpx #1{ \exp_after:NN\gdef_protected_long:Npx\cs:w #1\cs_end:} \def_new:Npn \def_protected_long_new:cpn #1{ \exp_after:NN \def_protected_long_new:Npn \cs:w #1\cs_end:} \def_new:Npn \def_protected_long_new:cpx #1{ \exp_after:NN \def_protected_long_new:Npx \cs:w #1\cs_end:} \def_new:Npn \gdef_protected_long_new:cpn #1{ \exp_after:NN \gdef_protected_long_new:Npn \cs:w #1\cs_end:} \def_new:Npn \gdef_protected_long_new:cpx #1{ \exp_after:NN \gdef_protected_long_new:Npx \cs:w #1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\def_aux_0:NNn} % \begin{macro}{\def_aux_1:NNn} % \begin{macro}{\def_aux_2:NNn} % \begin{macro}{\def_aux_3:NNn} % \begin{macro}{\def_aux_4:NNn} % \begin{macro}{\def_aux_5:NNn} % \begin{macro}{\def_aux_6:NNn} % \begin{macro}{\def_aux_7:NNn} % \begin{macro}{\def_aux_8:NNn} % \begin{macro}{\def_aux_9:NNn} % \begin{macro}{\def_aux:NNnn} % \begin{macro}{\def_aux:Ncnn} % \begin{macro}{\def_arg_number_error_msg:Nn} % Defining a function with $n$ arguments. First some helper functions. % \begin{macrocode} \def_new:cpn {def_aux_0:NNn} #1#2 {#1 #2 } \def_new:cpn {def_aux_1:NNn} #1#2 {#1 #2 ##1 } \def_new:cpn {def_aux_2:NNn} #1#2 {#1 #2 ##1##2 } \def_new:cpn {def_aux_3:NNn} #1#2 {#1 #2 ##1##2##3 } \def_new:cpn {def_aux_4:NNn} #1#2 {#1 #2 ##1##2##3##4 } \def_new:cpn {def_aux_5:NNn} #1#2 {#1 #2 ##1##2##3##4##5 } \def_new:cpn {def_aux_6:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6 } \def_new:cpn {def_aux_7:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7 } \def_new:cpn {def_aux_8:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8 } \def_new:cpn {def_aux_9:NNn} #1#2 {#1 #2 ##1##2##3##4##5##6##7##8##9 } % \end{macrocode} % Then the function itself which checks for the existance of such a % helper function. If it doesn't exist, return an error. Otherwise % call it to define \verb|#2| with the correct number of arguments. % \begin{macrocode} \def_protected_long_new:Npn \def_aux:NNnn #1#2#3#4 { \cs_if_really_exist:cTF {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} { \cs_use:c {def_aux_\tex_the:D\etex_numexpr:D #3 :NNn} #1 #2 {#4} } { \def_arg_number_error_msg:Nn #2{#3} } } \def_new:Npn \def_aux:Ncnn #1#2{ \exp_after:NN \def_aux:NNnn \exp_after:NN #1 \cs:w #2\cs_end:} % \end{macrocode} % The error message. % \begin{macrocode} \def_new:Npn \def_arg_number_error_msg:Nn #1#2 { \err_latex_bug:x{ You're~ trying~ to~ define~ the~ command~ `\token_to_string:N #1'~ with~ \use_arg_i:n{\tex_the:D\etex_numexpr:D #2\scan_stop:} ~ arguments~ but~ I~ only~ allow~ 0-9~ arguments.~ I~ can~ probably~ not~ help~ you~ here } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def_aux_use_0_parameter:} % \begin{macro}{\def_aux_use_1_parameter:} % \begin{macro}{\def_aux_use_2_parameter:} % \begin{macro}{\def_aux_use_3_parameter:} % \begin{macro}{\def_aux_use_4_parameter:} % \begin{macro}{\def_aux_use_5_parameter:} % \begin{macro}{\def_aux_use_6_parameter:} % \begin{macro}{\def_aux_use_7_parameter:} % \begin{macro}{\def_aux_use_8_parameter:} % \begin{macro}{\def_aux_use_9_parameter:} % Something similar to |\def_aux_9:NNn| but for using the % parameters. % \begin{macrocode} \def:cpn{def_aux_use_0_parameter:}{} \def:cpn{def_aux_use_1_parameter:}{{##1}} \def:cpn{def_aux_use_2_parameter:}{{##1}{##2}} \def:cpn{def_aux_use_3_parameter:}{{##1}{##2}{##3}} \def:cpn{def_aux_use_4_parameter:}{{##1}{##2}{##3}{##4}} \def:cpn{def_aux_use_5_parameter:}{{##1}{##2}{##3}{##4}{##5}} \def:cpn{def_aux_use_6_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}} \def:cpn{def_aux_use_7_parameter:}{{##1}{##2}{##3}{##4}{##5}{##6}{##7}} \def:cpn{def_aux_use_8_parameter:}{ {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}} \def:cpn{def_aux_use_9_parameter:}{ {##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}{##9}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def:NNn} % \begin{macro}{\def:NNx} % \begin{macro}{\def:cNn} % \begin{macro}{\def:cNx} % \begin{macro}{\gdef:NNn} % \begin{macro}{\gdef:NNx} % \begin{macro}{\gdef:cNn} % \begin{macro}{\gdef:cNx} % \begin{macro}{\def_new:NNn} % \begin{macro}{\def_new:NNx} % \begin{macro}{\def_new:cNn} % \begin{macro}{\def_new:cNx} % \begin{macro}{\gdef_new:NNn} % \begin{macro}{\gdef_new:NNx} % \begin{macro}{\gdef_new:cNn} % \begin{macro}{\gdef_new:cNx} % Defining macros without delimited arguments is now relatively % easy. First local and global versions of the usual |\def:Npn| % operation. % \begin{macrocode} \def_new:Npn \def:NNn { \def_aux:NNnn \def:Npn } \def_new:Npn \def:NNx { \def_aux:NNnn \def:Npx } \def_new:Npn \def:cNn { \def_aux:Ncnn \def:Npn } \def_new:Npn \def:cNx { \def_aux:Ncnn \def:Npx } \def_new:Npn \gdef:NNn { \def_aux:NNnn \gdef:Npn } \def_new:Npn \gdef:NNx { \def_aux:NNnn \gdef:Npx } \def_new:Npn \gdef:cNn { \def_aux:Ncnn \gdef:Npn } \def_new:Npn \gdef:cNx { \def_aux:Ncnn \gdef:Npx } \def_new:Npn \def_new:NNn { \def_aux:NNnn \def_new:Npn } \def_new:Npn \def_new:NNx { \def_aux:NNnn \def_new:Npx } \def_new:Npn \def_new:cNn { \def_aux:Ncnn \def_new:Npn } \def_new:Npn \def_new:cNx { \def_aux:Ncnn \def_new:Npx } \def_new:Npn \gdef_new:NNn { \def_aux:NNnn \gdef_new:Npn } \def_new:Npn \gdef_new:NNx { \def_aux:NNnn \gdef_new:Npx } \def_new:Npn \gdef_new:cNn { \def_aux:Ncnn \gdef_new:Npn } \def_new:Npn \gdef_new:cNx { \def_aux:Ncnn \gdef_new:Npx } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def_long:NNn} % \begin{macro}{\def_long:NNx} % \begin{macro}{\def_long:cNn} % \begin{macro}{\def_long:cNx} % \begin{macro}{\gdef_long:NNn} % \begin{macro}{\gdef_long:NNx} % \begin{macro}{\gdef_long:cNn} % \begin{macro}{\gdef_long:cNx} % \begin{macro}{\def_long_new:NNn} % \begin{macro}{\def_long_new:NNx} % \begin{macro}{\def_long_new:cNn} % \begin{macro}{\def_long_new:cNx} % \begin{macro}{\gdef_long_new:NNn} % \begin{macro}{\gdef_long_new:NNx} % \begin{macro}{\gdef_long_new:cNn} % \begin{macro}{\gdef_long_new:cNx} % Long versions of the above. % \begin{macrocode} \def_new:Npn \def_long:NNn { \def_aux:NNnn \def_long:Npn } \def_new:Npn \def_long:NNx { \def_aux:NNnn \def_long:Npx } \def_new:Npn \def_long:cNn { \def_aux:Ncnn \def_long:Npn } \def_new:Npn \def_long:cNx { \def_aux:Ncnn \def_long:Npx } \def_new:Npn \gdef_long:NNn { \def_aux:NNnn \gdef_long:Npn } \def_new:Npn \gdef_long:NNx { \def_aux:NNnn \gdef_long:Npx } \def_new:Npn \gdef_long:cNn { \def_aux:Ncnn \gdef_long:Npn } \def_new:Npn \gdef_long:cNx { \def_aux:Ncnn \gdef_long:Npx } \def_new:Npn \def_long_new:NNn { \def_aux:NNnn \def_long_new:Npn } \def_new:Npn \def_long_new:NNx { \def_aux:NNnn \def_long_new:Npx } \def_new:Npn \def_long_new:cNn { \def_aux:Ncnn \def_long_new:Npn } \def_new:Npn \def_long_new:cNx { \def_aux:Ncnn \def_long_new:Npx } \def_new:Npn \gdef_long_new:NNn { \def_aux:NNnn \gdef_long_new:Npn } \def_new:Npn \gdef_long_new:NNx { \def_aux:NNnn \gdef_long_new:Npx } \def_new:Npn \gdef_long_new:cNn { \def_aux:Ncnn \gdef_long_new:Npn } \def_new:Npn \gdef_long_new:cNx { \def_aux:Ncnn \gdef_long_new:Npx } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\def_protected:NNn} % \begin{macro}{\def_protected:NNx} % \begin{macro}{\def_protected:cNn} % \begin{macro}{\def_protected:cNx} % \begin{macro}{\gdef_protected:NNn} % \begin{macro}{\gdef_protected:NNx} % \begin{macro}{\gdef_protected:cNn} % \begin{macro}{\gdef_protected:cNx} % \begin{macro}{\def_protected_new:NNn} % \begin{macro}{\def_protected_new:NNx} % \begin{macro}{\def_protected_new:cNn} % \begin{macro}{\def_protected_new:cNx} % \begin{macro}{\gdef_protected_new:NNn} % \begin{macro}{\gdef_protected_new:NNx} % \begin{macro}{\gdef_protected_new:cNn} % \begin{macro}{\gdef_protected_new:cNx} % Protected versions of the above. % \begin{macrocode} \def_new:Npn \def_protected:NNn { \def_aux:NNnn \def_protected:Npn } \def_new:Npn \def_protected:NNx { \def_aux:NNnn \def_protected:Npx } \def_new:Npn \def_protected:cNn { \def_aux:Ncnn \def_protected:Npn } \def_new:Npn \def_protected:cNx { \def_aux:Ncnn \def_protected:Npx } \def_new:Npn \gdef_protected:NNn { \def_aux:NNnn \gdef_protected:Npn } \def_new:Npn \gdef_protected:NNx { \def_aux:NNnn \gdef_protected:Npx } \def_new:Npn \gdef_protected:cNn { \def_aux:Ncnn \gdef_protected:Npn } \def_new:Npn \gdef_protected:cNx { \def_aux:Ncnn \gdef_protected:Npx } \def_new:Npn \def_protected_new:NNn { \def_aux:NNnn \def_protected_new:Npn } \def_new:Npn \def_protected_new:NNx { \def_aux:NNnn \def_protected_new:Npx } \def_new:Npn \def_protected_new:cNn { \def_aux:Ncnn \def_protected_new:Npn } \def_new:Npn \def_protected_new:cNx { \def_aux:Ncnn \def_protected_new:Npx } \def_new:Npn \gdef_protected_new:NNn { \def_aux:NNnn \gdef_protected_new:Npn } \def_new:Npn \gdef_protected_new:NNx { \def_aux:NNnn \gdef_protected_new:Npx } \def_new:Npn \gdef_protected_new:cNn { \def_aux:Ncnn \gdef_protected_new:Npn } \def_new:Npn \gdef_protected_new:cNx { \def_aux:Ncnn \gdef_protected_new:Npx } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\def_protected_long:NNn} % \begin{macro}{\def_protected_long:NNx} % \begin{macro}{\def_protected_long:cNn} % \begin{macro}{\def_protected_long:cNx} % \begin{macro}{\gdef_protected_long:NNn} % \begin{macro}{\gdef_protected_long:NNx} % \begin{macro}{\gdef_protected_long:cNn} % \begin{macro}{\gdef_protected_long:cNx} % \begin{macro}{\def_protected_long_new:NNn} % \begin{macro}{\def_protected_long_new:NNx} % \begin{macro}{\def_protected_long_new:cNn} % \begin{macro}{\def_protected_long_new:cNx} % \begin{macro}{\gdef_protected_long_new:NNn} % \begin{macro}{\gdef_protected_long_new:NNx} % \begin{macro}{\gdef_protected_long_new:cNn} % \begin{macro}{\gdef_protected_long_new:cNx} % And finally both long and protected. % \begin{macrocode} \def_new:Npn \def_protected_long:NNn { \def_aux:NNnn \def_protected_long:Npn } \def_new:Npn \def_protected_long:NNx { \def_aux:NNnn \def_protected_long:Npx } \def_new:Npn \def_protected_long:cNn { \def_aux:Ncnn \def_protected_long:Npn } \def_new:Npn \def_protected_long:cNx { \def_aux:Ncnn \def_protected_long:Npx } \def_new:Npn \gdef_protected_long:NNn { \def_aux:NNnn \gdef_protected_long:Npn } \def_new:Npn \gdef_protected_long:NNx { \def_aux:NNnn \gdef_protected_long:Npx } \def_new:Npn \gdef_protected_long:cNn { \def_aux:Ncnn \gdef_protected_long:Npn } \def_new:Npn \gdef_protected_long:cNx { \def_aux:Ncnn \gdef_protected_long:Npx } \def_new:Npn \def_protected_long_new:NNn { \def_aux:NNnn \def_protected_long_new:Npn } \def_new:Npn \def_protected_long_new:NNx { \def_aux:NNnn \def_protected_long_new:Npx } \def_new:Npn \def_protected_long_new:cNn { \def_aux:Ncnn \def_protected_long_new:Npn } \def_new:Npn \def_protected_long_new:cNx { \def_aux:Ncnn \def_protected_long_new:Npx } \def_new:Npn \gdef_protected_long_new:NNn { \def_aux:NNnn \gdef_protected_long_new:Npn } \def_new:Npn \gdef_protected_long_new:NNx { \def_aux:NNnn \gdef_protected_long_new:Npx } \def_new:Npn \gdef_protected_long_new:cNn { \def_aux:Ncnn \gdef_protected_long_new:Npn } \def_new:Npn \gdef_protected_long_new:cNx { \def_aux:Ncnn \gdef_protected_long_new:Npx } % \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}{\let:NN} % \begin{macro}{\let:cN} % \begin{macro}{\let:Nc} % \begin{macro}{\let:cc} % \begin{macro}{\let_new:NN} % \begin{macro}{\let_new:cN} % \begin{macro}{\let_new:Nc} % \begin{macro}{\let_new:cc} % These macros allow us to copy the definition of a control sequence % to another control sequence. % \begin{macrocode} \def_protected_long_new:Npn \let:NN #1{ % \end{macrocode} % The |=| sign allows us to define funny char tokens like .|=| % itself or \verb*= = with this function. For the definition of % |\c_space_chartok{~}| to work we need the |~| after the |=| % \begin{macrocode} \let:NwN #1=~} \def_new:Npn\let:cN #1 {\exp_after:NN\let:NN\cs:w#1\cs_end:} \def_new:Npn\let:Nc{\exp_args:NNc\let:NN} \def_new:Npn\let:cc{\exp_args:Ncc\let:NN} \def_new:Npn \let_new:NN #1{\chk_new_cs:N #1 \let:NN #1} \def_new:Npn \let_new:cN {\exp_args:Nc \let_new:NN} \def_new:Npn \let_new:Nc {\exp_args:NNc \let_new:NN} \def_new:Npn \let_new:cc {\exp_args:Ncc \let_new:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\glet:NN} % \begin{macro}{\glet:cN} % \begin{macro}{\glet:Nc} % \begin{macro}{\glet:cc} % \begin{macro}{\glet_new:NN} % \begin{macro}{\glet_new:cN} % \begin{macro}{\glet_new:Nc} % \begin{macro}{\glet_new:cc} % These are global versions of some of the previously defined functions. % \begin{macrocode} \def_protected_new:Npn \glet:NN {\pref_global:D \let:NN} \def_protected_new:Npn \glet:Nc {\exp_args:NNc \glet:NN} \def_protected_new:Npn \glet:cN {\exp_args:Nc \glet:NN} \def_new:Npn \glet:cc {\exp_args:Ncc \glet:NN} \def_new:Npn \glet_new:NN #1{\chk_new_cs:N #1 \tex_global:D\let:NN #1} \def_new:Npn \glet_new:cN {\exp_args:Nc \glet_new:NN} \def_new:Npn \glet_new:Nc {\exp_args:NNc \glet_new:NN} \def_new:Npn \glet_new:cc {\exp_args:Ncc \glet_new:NN} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\def:No} % \begin{macro}{\gdef:No} % |\def:No| expands its second argument one time before making % the definition. % \begin{macrocode} \def_new:Npn \def:No{\exp_args:NNo\def:Npn} \def_new:Npn \gdef:No {\exp_args:NNo\gdef:Npn} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\def_test_function_aux:Nnnn} % \begin{macro}{\def_test_function_aux:Nnnx} % \begin{macro}{\def_test_function:npn} % \begin{macro}{\def_test_function:npx} % \begin{macro}{\def_long_test_function:npn} % \begin{macro}{\def_long_test_function:npx} % \begin{macro}{\def_test_function_new:npn} % \begin{macro}{\def_test_function_new:npx} % \begin{macro}{\def_long_test_function_new:npn} % \begin{macro}{\def_long_test_function_new:npx} % We will often be defining several almost identical TF, T and F % type functions so it makes sense for us to define a small function % that will do this for us so that we are less likely to introduce % typos (it does tend to happen). By doing it in two steps as below % we can still retain a simple interface where you write the \TeX\ % parameters as usual. Just don't do it when you're already within a % conditional! % % I think the ways of exiting conditionals below are as fast as they % get. Using |\reverse_if:N| instead of |\else:| didn't give any % difference I could measure. % \begin{macrocode} \def_long_new:Npn \def_test_function_aux:Nnnn #1#2#3#4{ #1 {#2TF} #3 {#4 \exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:} #1 {#2FT} #3 {#4 \exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:} #1 {#2T} #3 {#4 \else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n} #1 {#2F} #3 {#4 \exp_after:NN\use_none:nn\fi:\use_arg_i:n}} \def_long_new:Npn \def_test_function_aux:Nnnx #1#2#3#4{ #1 {#2TF} #3 {#4 \exp_not:n{\exp_after:NN\use_arg_i:nn\else:\exp_after:NN\use_arg_ii:nn\fi:}} #1 {#2FT} #3 {#4 \exp_not:n{\exp_after:NN\use_arg_ii:nn\else:\exp_after:NN\use_arg_i:nn\fi:}} #1 {#2T} #3 {#4 \exp_not:n{\else:\exp_after:NN\use_none:nn\fi:\use_arg_i:n}} #1 {#2F} #3 {#4 \exp_not:n{\exp_after:NN\use_none:nn\fi:\use_arg_i:n}}} \def_long_new:Npn \def_test_function:npn #1#2#{ \def_test_function_aux:Nnnn \def:cpn {#1}{#2} } \def_long_new:Npn \def_test_function:npx #1#2#{ \def_test_function_aux:Nnnx \def:cpx {#1}{#2} } \def_long_new:Npn \def_long_test_function:npn #1#2#{ \def_test_function_aux:Nnnn \def_long:cpn {#1}{#2} } \def_long_new:Npn \def_long_test_function:npx #1#2#{ \def_test_function_aux:Nnnx \def_long:cpx {#1}{#2} } \def_long_new:Npn \def_test_function_new:npn #1#2#{ \def_test_function_aux:Nnnn \def_new:cpn {#1}{#2} } \def_long_new:Npn \def_long_test_function_new:npn #1#2#{ \def_test_function_aux:Nnnn \def_long_new:cpn {#1}{#2} } \def_long_new:Npn \def_test_function_new:npx #1#2#{ \def_test_function_aux:Nnnx \def_new:cpx {#1}{#2} } \def_long_new:Npn \def_long_test_function_new:npx #1#2#{ \def_test_function_aux:Nnnx \def_long_new:cpx {#1}{#2} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsubsection{Further checking} % % \begin{macro}{\cs_if_free:NTF} % \begin{macro}{\cs_if_free:NT} % \begin{macro}{\cs_if_free:NF} % The old |\@ifundefined| of \LaTeX{} 2.09 is re-implemented in the % function |\cs_free:cTF|, again in a way that |\else:| and |\fi:| % are removed. In this implementation this is absolutely % necessary because functions inside the conditional parts expect % to read further input from outside the conditional. Actually, % the first part of the code below is more general, since it checks % \m{csnames} directly and therefore allows both |\scan_stop:| and % |\c_undefined|. % \begin{macrocode} \def_long_test_function_new:npn {cs_if_free:N}#1{\if:w\cs_if_free_p:N #1} \let:NN \cs_free:NTF \cs_if_free:NTF \let:NN \cs_free:NT \cs_if_free:NT \let:NN \cs_free:NF \cs_if_free:NF % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\cs_if_free:cTF} % \begin{macro}{\cs_if_free:cT} % \begin{macro}{\cs_if_free:cF} % We have to implement the |c| variants `by hand' because a different % test is necessary and I don't want the overhead for the test with % |\if:w|. What a mistake Don made by making this a % feature of |\cs:w|. If I'm not totally mistaken this % feature alone has cost him more than 600\$ for bug-checks. % \begin{macrocode} \def_long_test_function_new:npn {cs_if_free:c}#1{ \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} \let:NN \cs_free:cTF \cs_if_free:cTF \let:NN \cs_free:cT \cs_if_free:cT \let:NN \cs_free:cF \cs_if_free:cF % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\cs_if_really_free:cTF} % \begin{macro}{\cs_if_really_free:cT} % \begin{macro}{\cs_if_really_free:cF} % These versions are for special control sequences that can only be % formed through |\cs:w ... \cs_end:|. They do not turn the control % sequence formed into |\scan_stop:|. % \begin{macrocode} \def_long_test_function_new:npn {cs_if_really_free:c}#1{ \reverse_if:N\if_cs_exist:w #1\cs_end:} \let:NN \cs_really_free:cTF \cs_if_really_free:cTF \let:NN \cs_really_free:cT \cs_if_really_free:cT \let:NN \cs_really_free:cF \cs_if_really_free:cF % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\cs_if_exist:NTF} % \begin{macro}{\cs_if_exist:NT} % \begin{macro}{\cs_if_exist:NF} % \begin{macro}{\cs_if_exist:cTF} % \begin{macro}{\cs_if_exist:cT} % \begin{macro}{\cs_if_exist:cF} % \begin{macro}{\cs_if_really_exist:cTF} % \begin{macro}{\cs_if_really_exist:cT} % \begin{macro}{\cs_if_really_exist:cF} % Now the same functions but with reverse logic: test if the control % sequence exists. % \begin{macrocode} \def_long_test_function_new:npn {cs_if_exist:N}#1{\if:w\cs_if_exist_p:N #1} \def_long_test_function_new:npn {cs_if_exist:c}#1{ \exp_after:NN\reverse_if:N \exp_after:NN \if_meaning:NN \cs:w#1\cs_end: \scan_stop:} \def_long_test_function_new:npn {cs_if_really_exist:c}#1{ \if_cs_exist:w #1\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsubsection{Freeing memory} % % \begin{macro}{\cs_gundefine:N } % The following function is used to free the main memory from the % definition of some function that isn't in use any longer. % \begin{macrocode} \def_new:Npn \cs_gundefine:N #1{\glet:NN #1\c_undefined} % \end{macrocode} % \end{macro} % % % \subsubsection{Engine specific definitions} % % \begin{macro}{\engine_if_aleph:TF} % In some cases it will be useful to know which engine we're running. % \begin{macrocode} \def_test_function_new:npn {engine_if_aleph:}{\if_cs_exist:N \aleph_textdir:D} % \end{macrocode} % \end{macro} % % % % \subsubsection{Selecting tokens} % % \begin{macro}{\use_arg_i:n} % This macro grabs its argument and returns it back to the input % (with outer braces removed). % \begin{macrocode} %\def_long_new:Npn \use_arg_i:n #1{#1}% moved earlier % \end{macrocode} % \end{macro} % % \begin{macro}{\use:c} % \begin{macro}{\cs_use:c} % \begin{macro}{\use:cc} % This macro grabs its argument and returns a csname from it. % \begin{macrocode} \def_new:Npn \use:c #1{\cs:w #1\cs_end:} \def_new:Npn \cs_use:c #1 { \cs:w#1\cs_end: } % \end{macrocode} % THE NAME IS COMPLETELY WRONG!!!!! % Morten says: Perhaps this is really |\exp_args:cc| instead? % \begin{macrocode} \def_new:Npn \use:cc #1#2 {\cs:w #1\exp_after:NN\cs_end:\cs:w #2\cs_end:} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\use_arg_i:nn} % \begin{macro}{\use_arg_ii:nn} % These macros are needed to provide functions with true and false % cases, as introduced by Michael some time ago. By using % |\exp_after:NN| |\use_arg_i:nn | |\else:| constructions it % is possible to write code where the true or false case is able to % access the following tokens from the input stream, which is not % possible if the |\c_true| syntax is used. % \begin{macrocode} \def_long_new:Npn \use_arg_i:nn #1#2{#1} \def_long_new:Npn \use_arg_ii:nn #1#2{#2} % \end{macrocode} % \end{macro} % \end{macro} % % % % \begin{macro}{\use_arg_i:nnn} % \begin{macro}{\use_arg_ii:nnn} % \begin{macro}{\use_arg_iii:nnn} % \begin{macro}{\use_arg_i:nnnn} % \begin{macro}{\use_arg_ii:nnnn} % \begin{macro}{\use_arg_iii:nnnn} % \begin{macro}{\use_arg_iv:nnnn} % We also need something for picking up arguments from a longer % list. % \begin{macrocode} \def_long_new:NNn \use_arg_i:nnn 3{#1} \def_long_new:NNn \use_arg_ii:nnn 3{#2} \def_long_new:NNn \use_arg_iii:nnn 3{#3} \def_long_new:NNn \use_arg_i:nnnn 4{#1} \def_long_new:NNn \use_arg_ii:nnnn 4{#2} \def_long_new:NNn \use_arg_iii:nnnn 4{#3} \def_long_new:NNn \use_arg_iv:nnnn 4{#4} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\use_arg_i_ii:nn} % And a function for grabbing two arguments and returning them % again. % \begin{macrocode} \def_long_new:NNn\use_arg_i_ii:nn 2{#1#2} % \end{macrocode} % \end{macro} % % \begin{macro}{\use_none_delimit_by_q_nil:w} % \begin{macro}{\use_none_delimit_by_q_stop:w} % Functions that gobble everything until they see either |\q_nil| or % |\q_stop| resp. % \begin{macrocode} \def_long_new:Npn \use_none_delimit_by_q_nil:w #1\q_nil{} \def_long_new:Npn \use_none_delimit_by_q_stop:w #1\q_stop{} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\use_arg_i_delimit_by_q_nil:nw} % \begin{macro}{\use_arg_i_delimit_by_q_stop:nw} % Same as above but execute first argument after gobbling. Very % useful when you need to skip the rest of a mapping sequence but % want an easy way to control what should be expanded next. % \begin{macrocode} \def_long_new:Npn \use_arg_i_delimit_by_q_nil:nw #1#2\q_nil{#1} \def_long_new:Npn \use_arg_i_delimit_by_q_stop:nw #1#2\q_stop{#1} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\use_arg_i_after_fi:nw} % \begin{macro}{\use_arg_i_after_else:nw} % \begin{macro}{\use_arg_i_after_or:nw} % \begin{macro}{\use_arg_i_after_or:nw} % Returns the first argument after ending the conditional. % \begin{macrocode} \def_long_new:Npn \use_arg_i_after_fi:nw #1\fi:{\fi: #1} \def_long_new:Npn \use_arg_i_after_else:nw #1\else:#2\fi:{\fi: #1} \def_long_new:Npn \use_arg_i_after_or:nw #1\or: #2\fi: {\fi:#1} \def_long_new:Npn \use_arg_i_after_orelse:nw #1 #2#3\fi: {\fi:#1} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \subsubsection{Gobbling tokens from input} % % \begin{macro}{\use_none:n} % \begin{macro}{\use_none:nn} % \begin{macro}{\use_none:nnn} % \begin{macro}{\use_none:nnnn} % \begin{macro}{\use_none:nnnnn} % \begin{macro}{\use_none:nnnnnn} % \begin{macro}{\use_none:nnnnnnn} % \begin{macro}{\use_none:nnnnnnnn} % \begin{macro}{\use_none:nnnnnnnnn} % To gobble tokens from the input we use a standard naming % convention: the number of tokens gobbled is given by the number of % |n|'s following the |:| in the name. Although defining % |\use_none:nnn| and above as separate calls of |\use_none:n| and % |\use_none:nn| is slightly faster, this is very non-intuitive to % the programmer who will assume that expanding such a function once % will take care of gobbling all the tokens in one go. % \begin{macrocode} %\def_long_new:NNn \use_none:n 1{}% moved earlier \def_long_new:NNn \use_none:nn 2{} \def_long_new:NNn \use_none:nnn 3{} \def_long_new:NNn \use_none:nnnn 4{} \def_long_new:NNn \use_none:nnnnn 5{} \def_long_new:NNn \use_none:nnnnnn 6{} \def_long_new:NNn \use_none:nnnnnnn 7{} \def_long_new:NNn \use_none:nnnnnnnn 8{} \def_long_new:NNn \use_none:nnnnnnnnn 9{} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \subsubsection{Scratch functions} % % \begin{macro}{\gtmp:w} % This function is for global scratch definitions that are used % immediately afterwards. It should be used when we need a function % that operates on input, i.e.\ has arguments. If we want to save % only some tokens for later use, token-list scratch variables % should be used. % \begin{macrocode} \def_new:Npn \gtmp:w {} % \end{macrocode} % \end{macro} % % \begin{macro}{\tmp:w} % This is a local version of the previous function. % \begin{macrocode} \def_new:Npn \tmp:w {} % \end{macrocode} % \end{macro} % % \begin{macro}{\use_noop:} % I don't think this function belongs here, but one place is as % good as any other. I want to use this function when I want to % express `no operation'. % \begin{macrocode} \def_new:Npn \use_noop: {} % \end{macrocode} % \end{macro} % % \subsubsection{Strings and input stream token lists} % % \begin{macro}{\cs_to_str:N} % This converts a control sequence into the character string of its % name, removing the leading escape character. % \begin{macrocode} \def_new:Npn \cs_to_str:N {\exp_after:NN\use_none:n \token_to_string:N} % \end{macrocode} % \end{macro} % % % % % % \begin{macro}{\cs_if_eq:NNTF} % \begin{macro}{\cs_if_eq:NNT} % \begin{macro}{\cs_if_eq:NNF} % \begin{macro}{\cs_if_eq:cNTF} % \begin{macro}{\cs_if_eq:cNT} % \begin{macro}{\cs_if_eq:cNF} % \begin{macro}{\cs_if_eq:NcTF} % \begin{macro}{\cs_if_eq:NcT} % \begin{macro}{\cs_if_eq:NcF} % \begin{macro}{\cs_if_eq:ccTF} % \begin{macro}{\cs_if_eq:ccT} % \begin{macro}{\cs_if_eq:ccF} % Check if two control sequences are identical. % \begin{macrocode} \def_test_function_new:npn {cs_if_eq:NN} #1#2{\if_meaning:NN #1#2} \def_new:Npn \cs_if_eq:cNTF {\exp_args:Nc \cs_if_eq:NNTF} \def_new:Npn \cs_if_eq:cNT {\exp_args:Nc \cs_if_eq:NNT} \def_new:Npn \cs_if_eq:cNF {\exp_args:Nc \cs_if_eq:NNF} \def_new:Npn \cs_if_eq:NcTF {\exp_args:NNc \cs_if_eq:NNTF} \def_new:Npn \cs_if_eq:NcT {\exp_args:NNc \cs_if_eq:NNT} \def_new:Npn \cs_if_eq:NcF {\exp_args:NNc \cs_if_eq:NNF} \def_new:Npn \cs_if_eq:ccTF {\exp_args:Ncc \cs_if_eq:NNTF} \def_new:Npn \cs_if_eq:ccT {\exp_args:Ncc \cs_if_eq:NNT} \def_new:Npn \cs_if_eq:ccF {\exp_args:Ncc \cs_if_eq:NNF} % \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} % % Finally some code that is needed as we do not distribute the file % module at the moment (so we simply define the needed function via an % existing \LaTeX{} command) and some other stuff which was set up % elsewhere, in undistributed modules. % \begin{macrocode} \def_new:Npn\file_not_found:nTF #1#2#3{\IfFileExists{#1}{#3}{#2}} % \end{macrocode} % % % \subsubsection{Predicates and conditionals} % \label{sec:predicates} % % \LaTeX3 has three concepts for conditional flow processing: % \begin{enumerate} % % \item % Functions that carry out a test an then execute, depending on its % result, either the code supplied in the \m{true arg} or the \m{false % arg}. These arguments are denoted with "T" and "F" repectively. An % example would be % \begin{quote} % "\cs_free:cTF{abc}{...}{...}" % \end{quote} % a function that will turn the first argument into a control sequence % (since its marked as "c") then checks whether this control sequence is % still free and then depending on the result carry out the code in the % second argument (true case) or in the third argument (false case). % % \item % Functions that return a special type of boolean value which can be % tested by the function "\if:w". All functions of this type % have names that end with "_p" in the description part. For example % \begin{quote} % "\cs_free_p:N" % \end{quote} % would be a predicate function for the same type of test as the % function above. It would return `true' if its argument (a single token % denoted by "N") is still free for definition. It would be used in % constructions like % \begin{quote} % "\if:w \cs_free_p:N \l_foo_bar ... \else: ... \fi:" % \end{quote} % % \item % Actually there is a third one, namely the original concept used in % plain \TeX{}. This belongs to the second form but needs further % thoughts. % \end{enumerate} % % Important to note is that conditionals with \m{true code} and/or % \m{false code} are always defined in a way that the code of the chosen % alternative can operate on following tokens in the input stream while % the predicate implementations always have an "\else:" or "\fi:" % interfering. This can be important in scanner implementations. % % % \begin{macrocode} % %<*showmemory> \showMemUsage % % \end{macrocode} % % \endinput % % $Log$ % Revision 1.38 2006/08/06 17:05:25 morten % Make \chk_new_cs:N bulletproof % % Revision 1.37 2006/07/30 14:37:47 morten % Added \str_if_eq_var_p:nf % % Revision 1.36 2006/07/23 13:43:21 morten % Removed extra occurrence of \str_if_eq_p:nn % % Revision 1.35 2006/07/17 22:25:31 morten % Fix logic of \chk_new_cs:N and rename \cs_if_eq_p:NN to % \cs_if_eq_name_p:NN because it is not their meaning but their names % which are compared. % % Revision 1.34 2006/07/08 22:46:17 morten % Rearranged some code and added complete set of \use_none: % functions. % % Revision 1.33 2006/07/06 14:53:56 morten % Added \def:NNn functions, reorganized code and much much more. % % Revision 1.32 2006/06/03 17:14:43 morten % Added more \use_arg_... functions. % % Revision 1.31 2006/03/20 18:26:33 braams % Updated the copyright notice (2006) and demoted all implementation % sections to subsections and so on to clean up the toc for source3.tex % % Revision 1.30 2006/01/22 19:35:46 morten % Changed \use_none:nnn to gobble all tokens in one go and added % \use_arg_i_ii:nn for l3keyval. % % Revision 1.29 2006/01/16 09:47:49 morten % Fixed deleted brace % % Revision 1.28 2006/01/15 19:08:28 morten % Fixed typos in some \if names % % Revision 1.27 2006/01/04 01:29:36 morten % Changed "robust" to "protected". % % Revision 1.26 2005/12/27 09:53:55 morten % Fixed some names, added a few more \use_... functions, changed RCS % information retrieval % % Revision 1.25 2005/12/23 11:16:15 morten % *** empty log message *** % % Revision 1.24 2005/12/02 15:21:55 morten % Fixed minor typo % % Revision 1.23 2005/11/20 07:10:03 morten % Added a few missing functions. New function type % \def_test_function:npn to help define TF-type functions. % % Revision 1.22 2005/11/08 04:16:17 morten % Fixed typo. % % Revision 1.21 2005/10/27 22:35:13 morten % Cleaned up a bit and moved some code to l3num. % % Revision 1.20 2005/07/12 16:10:24 morten % Allow \cs_if_eq_p:NN to accept \par. (Yes, real life experience) % % Revision 1.19 2005/04/06 21:34:55 morten % Added more functions. Moved \engine_aleph:TF from l3prg % % Revision 1.18 2005/03/25 23:52:24 braams % The definition of \next needs to be seen at initex time, % not at typesetting time % % Revision 1.17 2005/03/22 23:28:46 morten % Moved some code to l3prg, removed obsolete code, cleaned up documentation. % % Revision 1.16 2005/03/16 22:31:44 braams % Changed definition of \c_zero and \c_minus_one % % Revision 1.15 2005/03/15 23:16:27 braams % Some tweaking with the docstrip guards to get the documentation to % come out right. % % Revision 1.14 2005/03/15 22:50:00 braams % Made loadable by initex as the second file % % Revision 1.13 2005/03/11 21:32:21 braams % Fixed the use of RCS information; % moved \RequirePackage after \StopEventually %