%%%============================================================================== %% Copyright 2026-present by Alceu Frigeri %% %% This work may be distributed and/or modified under the conditions of %% %% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt), %% version 1.3c (or later), and/or %% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html), %% version 3 (or later) %% %% This work has the LPPL maintenance status *maintained*. %% %% The Current Maintainer of this work is Alceu Frigeri %% %% This is version {1.0} {2026/02/18} %% %% The list of files that compose this work can be found in the README.md file at %% https://ctan.org/pkg/xstacks %% %%%============================================================================== \NeedsTeXFormat{LaTeX2e}[2025/06/01] %%%%%%% %%% %%% Just an attempt at having my package's info in a regular way %%% \pkginfograb_set:nn {} { props} sets package info %%% %%% \pkginfograbProvidesExplPackage {} { props} sets package's info %%% and calls \ProvidesExplPackage %%% %%%%%%% \RequirePackage{pkginfograb} \pkginfograbProvidesExplPackage {tokglobalstack} { name = {tokglobalstack} , prefix = {globalstack} , date = {2026/02/18}, version = {1.0} , description = {tokglobalstack - (multiple) global stack(s)} } %%%%%%% %%% End of cut-n-paste %%%%%%% \msg_new:nnnn { tokglobalstack } {defined} { (#1)~#2~already~defined. } { #2~ is ~ already~ defined, ~and~ will~ not~ be~ redefined. ~Error~Code~ ID:<#1>. } %%%%%%% %%% 'cs' generate case. %%%%%%% \cs_new_protected:Npn \globalstack_csnew:n #1 { \cs_if_exist:cTF {#1_gpush:n} { \msg_error:nnnn { tokglobalstack } {defined} {new01} {#1} } { \int_new:c {g__globalstack_ #1 _int} \cs_new:cpe {#1_gpush:n} % ##1 { \exp_not:N \int_gincr:N \exp_not:c {g__globalstack_ #1 _int} \exp_not:N \exp_args:NNc \exp_not:N \tl_gset:Nn \exp_not:c {g__globalstack_ #1 _ref_tl} {g__globalstack_ #1 _ \exp_not:N \int_use:N \exp_not:c {g__globalstack_ #1 _int} _tl} \exp_not:N \exp_args:No \exp_not:N \tl_gset:Nn \exp_not:c {g__globalstack_ #1 _ref_tl} % {##1} } \cs_new:cpe {#1_gput_right:n} %##1 { \exp_not:N \exp_args:No \exp_not:N \tl_gput_right:Nn \exp_not:c {g__globalstack_ #1 _ref_tl} % {##1} } \cs_new:cpe {#1_gput_left:n} %##1 { \exp_not:N \exp_args:No \exp_not:N \tl_gput_left:Nn \exp_not:c {g__globalstack_ #1 _ref_tl} % {##1} } \cs_new:cpe {#1_gpop:} { \exp_not:N \if_int_compare:w \exp_not:c {g__globalstack_ #1 _int} = \c_zero_int \exp_not:N \else: \exp_not:c {g__globalstack_ #1 _ref_tl} \exp_not:N \int_gdecr:N \exp_not:c {g__globalstack_ #1 _int} \exp_not:N \exp_args:NNc \exp_not:N \tl_gset:Nn \exp_not:c {g__globalstack_ #1 _ref_tl} {g__globalstack_ #1 _ \exp_not:N \int_use:N \exp_not:c {g__globalstack_ #1 _int} _tl} \exp_not:N \fi: } } } %%%%%%% %%% Note: %%% \__globalstack:wn absorbs 5 tokens, %%% 4 'internal' (including a quark marker) + 1 given by the user %%% except in two cases: (whereas only the 4 internal tokens will be consumed) %%% the 'default' cmd (...\use_none:nnnn so the variable expands to nothing) %%% and the \...pop: case %%% %%% a local group is created (except in the pop case) %%% so there is no need to reset \__globalstack:wn %%%%%%% \cs_set_eq:NN \__globalstack:wn \use_none:nnnn \tl_new:N \l__globalstack_tmpA_tl \cs_new_protected:Npn \globalstack_new:N #1 { \tl_if_exist:NTF #1 { \msg_error:nnnn { tokglobalstack } {defined} {new02} {#1} } { \tl_set:Ne \l__globalstack_tmpA_tl {\cs_to_str:N #1} \exp_args:Ncc \tl_gset:Nn {g__globalstack_ \l__globalstack_tmpA_tl _ref_tl} {g__globalstack_ \l__globalstack_tmpA_tl _tl} \tl_gset:cn {g__globalstack_ \l__globalstack_tmpA_tl _tl} {} \int_new:c {g__globalstack_ \l__globalstack_tmpA_tl _int} \tl_gset:Ne #1 { \exp_not:N \__globalstack:wn \exp_not:c {g__globalstack_ \l__globalstack_tmpA_tl _ref_tl} \exp_not:c {g__globalstack_ \l__globalstack_tmpA_tl _int} {\l__globalstack_tmpA_tl} \exp_not:N \q_stop } } } \cs_new_protected:Npn \__globalstack_gpush:wn #1#2#3 \q_stop % #4 { \int_gincr:N #2 \exp_args:NNc \tl_gset:Nn #1 {g__globalstack_ #3 _ \int_use:N #2 _tl} \exp_args:No \tl_gset:Nn #1 % {#4} } \cs_new_protected:Npn \globalstack_gpush:Nn #1#2 { { \cs_set_eq:NN \__globalstack:wn \__globalstack_gpush:wn #1 {#2} } } \cs_new_protected:Npn \globalstack_gput_right:Nn #1#2 { { \cs_set_eq:NN \__globalstack:wn \__globalstack_gput_right:wn #1 {#2} } } \cs_new_protected:Npn \__globalstack_gput_right:wn #1#2#3 \q_stop % #4 { \exp_args:No \tl_gput_right:Nn #1 % {#4} } \cs_new_protected:Npn \globalstack_gput_left:Nn #1#2 { { \cs_set_eq:NN \__globalstack:wn \__globalstack_gput_left:wn #1 {#2} } } \cs_new_protected:Npn \__globalstack_gput_left:wn #1#2#3 \q_stop % #4 { \exp_args:No \tl_gput_left:Nn #1 % {#4} } \cs_new_protected:Npn \__globalstack_gpop:w #1#2#3 \q_stop { \cs_set_eq:NN \__globalstack:wn \use_none:nnnn \if_int_compare:w #2 = \c_zero_int \else: \int_gdecr:N #2 #1 \exp_args:NNc \tl_gset:Nn #1 {g__globalstack_ #3 _ \int_use:N #2 _tl} \fi: } \cs_new_protected:Npn \globalstack_gpop:N % #1 { \cs_set_eq:NN \__globalstack:wn \__globalstack_gpop:w % #1 }