diff options
Diffstat (limited to 'macros/latex/contrib/bxcalc/bxcalcux.sty')
-rw-r--r-- | macros/latex/contrib/bxcalc/bxcalcux.sty | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/macros/latex/contrib/bxcalc/bxcalcux.sty b/macros/latex/contrib/bxcalc/bxcalcux.sty new file mode 100644 index 0000000000..90e222643a --- /dev/null +++ b/macros/latex/contrib/bxcalc/bxcalcux.sty @@ -0,0 +1,303 @@ +%% +%% This is file 'bxcalcux.sty'. +%% +%% Copyright (c) 2018-2020 Takayuki YATO (aka. "ZR") +%% GitHub: https://github.com/zr-tex8r +%% Twitter: @zr_tex8r +%% +%% This package is distributed under the MIT License. +%% + +%% package declaration +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{bxcalcux}[2020/09/25 v1.1] +\def\bxcx@pkgname{bxcalcux} + +%% code guards +\edef\bxcx@restore@codes{% +\catcode33=\the\catcode33% +\catcode34=\the\catcode34% +\catcode63=\the\catcode63% +\endlinechar=\the\endlinechar% +\relax} +\catcode33=12 %<!> +\catcode34=12 %<"> +\catcode63=12 %<?> +\endlinechar\m@ne +\AtEndOfPackage{ +\bxcx@restore@codes +\let\bxcx@restore@codes\@undefined} + +%--------------------------------------- general + +%% packages +\RequirePackage{calc}[] +\RequirePackage{etoolbox}[] +\ifx\numdef\@undefined\endinput\fi + +%% unique tokens +\def\bxcx@end{\noexpand\bxcx@end@} +\def\bxcx@mark{\noexpand\bxcx@mark@} +\def\bxcx@mt{\noexpand\bxcx@mt@} + +%% variables +\let\bxcx@parsed\@empty % parsed token list +\let\bxcx@unit\@empty % unit string now holding +\let\bxcx@unitlc\@empty % unit string now holding, lowercased +\newcount\bxcx@arg@count % # of arguments remaining +\let\bxcx@mode\relax % current mode (N/L/U) +\let\bxcx@g@tempa\@empty % global temp +% \bxcx@arity\CS % arity of functions of which the + % argument should be also parsed +% \bxcx@lc/<char> % lowercase letter of an alphabet letter +% \bxcx@tl/<str> % tl that relates to unit <str> +% \bxcx@mluf/<str> % is there a multichar unit <char>... ? + +%% Makes the array \bxcx@arity*. +\csdef{bxcx@arity\string\minof}{2} +\csdef{bxcx@arity\string\maxof}{2} +\csdef{bxcx@arity\string\ratio}{2} + +%% Makes the array \bxcx@lc/*. +\@tempcnta=65 +\@tempcntb=97 +\@whilenum\@tempcnta<91 \do{ + \lccode`!=\@tempcnta \lccode`?=\@tempcntb + \lowercase{ + \csdef{bxcx@lc/!}{?} + \csdef{bxcx@lc/?}{?} + } + \advance\@tempcnta\@ne + \advance\@tempcntb\@ne +} + +%% \bxcx@cond\ifXXX...\fi{<true>}{<false>} +\@gobbletwo\if\if \def\bxcx@cond#1\fi{ + #1\expandafter\@firstoftwo + \else \expandafter\@secondoftwo + \fi +} + +%--------------------------------------- unit registration + +%%<*> \newcalcunit{<unit>}{<length>} +\newcommand*\newcalcunit[2]{ + \DeclareCalcUnit{#1}{\dimexpr#2\relax} +} + +%%<+> \DeclareCalcUnit{<unit>}{<unit-of-dimen>} +\newcommand*\DeclareCalcUnit[2]{ + \edef\bxcx@tempa{#1} + \expandafter\bxcx@check@unit@name\meaning\bxcx@tempa\bxcx@end + \bxcx@cond\ifx\bxcx@tempa\@empty\fi{}{%else + \expandafter\bxcx@decl@calc@unit@a\meaning\bxcx@tempa\bxcx@end{#2} + } +} +\def\bxcx@decl@calc@unit@a#1>#2#3\bxcx@end#4{ + \ifstrempty{#3}{ + \csdef{bxcx@tl/#2}{#4} + }{%else + \csdef{bxcx@mluf/\@nameuse{bxcx@lc/#2}}{t} + \let\bxcx@unitlc\@empty + \@tfor\bxcx@tempa:=#2#3\do{ + \eappto\bxcx@unitlc{\@nameuse{bxcx@lc/\bxcx@tempa}} + } + \csdef{bxcx@tl/\bxcx@unitlc}{#4} + } +} +\def\bxcx@check@unit@name#1>#2\bxcx@end{ + \@tfor\bxcx@tempb:=#2\do{ + \ifcsdef{bxcx@lc/\bxcx@tempb}{}{%else + \let\bxcx@tempa\@empty + } + } + \ifx\bxcx@tempa\@empty + \PackageError\bxcx@pkgname + {Illegal unit name '#2'} + \fi +} + +%--------------------------------------- parser + +%%<+> \CUXParseExpr\CS{<expr>} +\newcommand*\CUXParseExpr[2]{ + \bxcx@parse{#2} + \let#1=\bxcx@parsed +} + +%% \bxcx@parse +\def\bxcx@parse#1{ + \let\bxcx@parsed\@empty + \bxcx@clear@unit + \let\bxcx@mode=N\relax + \bxcx@parse@a#1@\bxcx@end +} +\def\bxcx@the#1{\expandafter\bxcx@thee\meaning#1} +{\lccode`?=`r \lowercase{\gdef\bxcx@thee#1? #2{#2}}} +\def\bxcx@parse@a{ +%\typeout{[\bxcx@the\bxcx@mode:\the\bxcx@arg@count:\bxcx@unitlc]\expandonce{\bxcx@parsed}} + \futurelet\bxcx@tok\bxcx@parse@b +} +\def\bxcx@parse@b{ +%\typeout{<token:\meaning\bxcx@tok>} + \bxcx@cond\ifx\bxcx@tok\@sptoken\fi{ + \bxcx@parse@space + }{\bxcx@cond\ifx\bxcx@tok\bgroup\fi{ + \bxcx@parse@group + }{\bxcx@cond\ifcat\relax\noexpand\bxcx@tok\fi{ + \bxcx@arg@count=\z@ + \bxcx@parse@cs + }{%else + \bxcx@arg@count=\z@ + \bxcx@parse@char + }}} +} +\expandafter\def\expandafter\bxcx@parse@space\space{ + \bxcx@parse@char{ } +} +\def\bxcx@parse@char#1{ + \bxcx@cond\if N\bxcx@mode\fi{ + \ifcsdef{bxcx@lc/#1}{ + \ifcsdef{bxcx@tl/#1}{ + \bxcx@add@unit{#1} + \let\bxcx@mode=L\relax + }{\ifcsdef{bxcx@mluf/\@nameuse{bxcx@lc/#1}}{ + \bxcx@addto@unit{#1} + \let\bxcx@mode=U\relax + }{%else + \appto\bxcx@parsed{#1} + \let\bxcx@mode=L\relax + }} + }{%else + \appto\bxcx@parsed{#1} + } + }{\bxcx@cond\if U\bxcx@mode\fi{ + \ifcsdef{bxcx@lc/#1}{ + \bxcx@addto@unit{#1} + \ifcsdef{bxcx@tl/\bxcx@unitlc}{ + \bxcx@add@unit{\bxcx@unitlc} + \bxcx@clear@unit + \let\bxcx@mode=L\relax + }{} + }{%else + \eappto\bxcx@parsed{\bxcx@unit} + \bxcx@clear@unit + \appto\bxcx@parsed{#1} + \let\bxcx@mode=N\relax + } + }{%else(L\bxcx@mode) + \appto\bxcx@parsed{#1} + \ifcsdef{bxcx@lc/#1}{}{%else + \let\bxcx@mode=N\relax + } + }} + \bxcx@parse@a +} +\def\bxcx@parse@cs#1{ +%\typeout{<cs:\string#1>} + \bxcx@cond{\ifx#1\bxcx@end}\fi{% NB. #1 can be \fi + \bxcx@parse@fin + }{%else + \ifcsdef{bxcx@arity\string#1}{ + \bxcx@arg@count=\@nameuse{bxcx@arity\string#1}\relax + }{} + \bxcx@cond\if U\bxcx@mode\fi{ + \eappto\bxcx@parsed{\bxcx@unit} + \bxcx@clear@unit + }{} + \appto\bxcx@parsed{#1} + \let\bxcx@mode=N\relax + \bxcx@parse@a + } +} +\def\bxcx@parse@group#1{ + \bxcx@cond\if U\bxcx@mode\fi{ + \eappto\bxcx@parsed{\bxcx@unit} + \bxcx@clear@unit + }{} + \bxcx@cond\ifnum\bxcx@arg@count>\z@\fi{ +%\typeout{<group:parse>} + \begingroup + \bxcx@parse{#1} + \global\let\bxcx@gtempa\bxcx@parsed + \endgroup + \expandafter\bxcx@parse@group@a\bxcx@gtempa\bxcx@end + \advance\bxcx@arg@count\m@ne + }{%else +%\typeout{<group:pass>} + \appto\bxcx@parsed{{#1}} + } + \let\bxcx@mode=N\relax + \bxcx@parse@a +} +\def\bxcx@parse@group@a#1\bxcx@end{ + \appto\bxcx@parsed{{#1}} +} +\def\bxcx@parse@fin{ + \expandafter\bxcx@parse@fin@a\bxcx@parsed\bxcx@end +} +\def\bxcx@parse@fin@a#1@\bxcx@end{ + \def\bxcx@parsed{#1} +} + +%% \bxcx@add@unit +\def\bxcx@add@unit#1{ +%\typeout{<unit:#1>} + \expandafter\bxcx@add@unit@a\csname bxcx@tl/#1 + \endcsname\bxcx@end +} +\def\bxcx@add@unit@a#1\bxcx@end{ + \appto\bxcx@parsed{#1} +} + +%% \bxcx@clear@unit +\def\bxcx@clear@unit{ + \let\bxcx@unit\@empty + \let\bxcx@unitlc\@empty +} + +%% \bxcx@addto@unit +\def\bxcx@addto@unit#1{ + \appto\bxcx@unit{#1} + \eappto\bxcx@unitlc{\@nameuse{bxcx@lc/#1}} +} + +%--------------------------------------- apply the patch + +%% \bxcx@decl@patch\xxx{<body>} +% Here xxx is setlength or addtolength; and gives a new +% definition to that command. The <body> knows two macro +% arguments (#1 & #2) and \CUXxxx is the original definition +% of \xxx. +\def\bxcx@decl@patch#1{ + \expandafter\bxcx@decl@patch@a\csname + \expandafter\@gobble\string#1\space\expandafter\endcsname + \csname CUX\expandafter\@gobble\string#1\endcsname + #1 +} +\def\bxcx@decl@patch@a#1#2#3{ + \def\bxcx@tempa{\protect#1} + \bxcx@cond\ifx\bxcx@tempa#3\fi{ + \let#2=#1 + \def#1##1##2 + }{%else + \let#2=#3 + \DeclareRobustCommand*#3[2] + } +} + +%% Patch to \setlength. +\bxcx@decl@patch\setlength{ + \bxcx@parse{#2} + \CUXsetlength{#1}{\bxcx@parsed} +} + +%% Patch to \addtolength. +\bxcx@decl@patch\addtolength{ + \bxcx@parse{#2} + \CUXaddtolength{#1}{\bxcx@parsed} +} + +%--------------------------------------- all done +\endinput +%% EOF |