\input ptb-utils \_checkloaded{key-value} \def\novalue{\novalue} \def\_update_lastkeys#1#2#3{% \_xp\_xp\_xp\def\_xp\_xp\_xp#1\_xp\_xp\_xp{\_xp#1\_xp{\_xp{\_id#2}{#3}}}% } % #1: lastkeys, #2: key name, #3: key value \def\_vanilla_mapkey#1#2#3{% \_xp\def\csname key@\_id#2\endcsname{#3}% \_update_lastkeys{#1}{#2}{#3}% } \def\__mapkeys#1#2#3=#4=#5,{% \def\_temp{#3}% \ifx\_nul\_temp% \else% \_xp#1\_xp{\_xp#2\_xp}\_xp{\_id#3}{#4}% \_afterfi{\_mapkeys{#1}{#2}}% \fi% } \def\_mapkeys#1#2#3,{% \__mapkeys{#1}{#2}#3==,% } % #1: setter, #2: lastkeys, #3: map \def\_mapkeys_with_setter#1#2#3{% \def#2{}% \def\_temp{#3}% \ifx\_temp\empty% \else% \_afterfi{\_mapkeys{#1}{#2}#3,\_nul=,}% \fi% } \def\getvalue#1{% \csname key@#1\endcsname% } \def\__keyexists#1#2#3#4{% \bgroup% \def\_regA{#1}\def\_regB{#3}% \ifx\_regA\_regB% \egroup\def#2{#4}% \else% \egroup% \fi% } \def\_keyexists#1#2#3{% \ifx\_nul#3% \else% \__keyexists{#1}{#2}#3% \_afterfi{\_keyexists{#1}{#2}}% \fi% } \def\keyexists#1#2#3{% \let#2=\_nul% \def\_temp{\_keyexists{#1}{#2}}% \_xp\_temp#3\_nul% } \def\ifkeyexists#1{% \unless\ifx\_nul#1% } \def\_letnamedmacro#1#2{% \_xp\let\csname #1\endcsname=#2% } \def\___setdefault#1#2{% \def\_temp{#2}% \unless\ifx\_temp\empty% \_mapkeys_with_setter\_vanilla_mapkey\_settings{#2}% \keyexists{default}\_keydefault\_settings% \unless\ifx\_nul\_keydefault% \def\_temp{\_xp\def\csname key@#1\endcsname}% \_xp\_temp\_xp{\_keydefault}% \keyexists{name}\_keyname\_settings% \unless\ifx\_nul\_keyname% \_xp\_xp\_xp\_letnamedmacro\_xp\_xp\_xp{\_xp\_keyname\_xp}\_xp{\csname key@#1\endcsname}% %\_xp\_xp\_xp\let\_xp\_keyname\csname key@#1\endcsname% \fi% \else% \keyexists{required}\_keyrequired\_settings% \unless\ifx\_nul\_keyrequired% \_xp\def\_xp\_requiredkeys\_xp{\_requiredkeys{#1}}% \_xp\let\csname required@#1\endcsname=\_nul% \fi% \fi% \fi% } \def\__setdefault#1{% \ifx\_nul#1% \else% \___setdefault#1% \_xp\__setdefault% \fi% } \def\_setdefaults#1{% \def\_requiredkeys{}% \__setdefault#1\_nul% } \def\_vardef_mapkey#1#2#3{% \def\_tempdef{\_xp\_vardef\csname key@\_id#2\endcsname}% \_xp\_tempdef\_xp{\_varmap{#3}}% \_update_lastkeys{#1}{#2}{#3}% } \def\_protected_mapkey#1#2#3{% \keyexists{#2}\_keysettings\_keymappings% \unless\ifx\_nul\_keysettings% \let\_varmap=\_id% \def\_vardef{\def}% \let\_keyname=\_nul% \unless\ifx\_keysettings\empty% \_xp\_mapkeys_with_setter\_xp\_vanilla_mapkey\_xp\_settings\_xp{\_keysettings}% \keyexists{mapping}\_varmap\_settings% \ifx\_nul\_varmap% \let\_varmap=\_id% \fi% \keyexists{definition}\_vardef\_settings% \ifx\_nul\_vardef% \def\_vardef{\def}% \fi% \keyexists{name}\_keyname\_settings% \fi% \_vardef_mapkey{#1}{#2}{#3}% \_xp\let\csname required@#2\endcsname=\undefined% \unless\ifx\_nul\_keyname% %\_xp\_xp\_xp\let\_xp\_keyname\_xp=\csname key@#2\endcsname% \_xp\_xp\_xp\_letnamedmacro\_xp\_xp\_xp{\_xp\_keyname\_xp}\_xp{\csname key@#2\endcsname}% \fi% \else% \errhelp={Key `#2' supplied, but not present in key list}% \errmessage{Invalid key supplied}% \fi% } \def\_check_required#1{% \def\_temp{#1}% \unless\ifx\_nul\_temp% \ifcsname required@#1\endcsname% \errhelp={Key `#1' was required by the key list, but not supplied}% \errmessage{Required key not defined}% \fi% \_xp\_check_required% \fi% } \def\_check_required_supplied{% \_xp\_check_required\_requiredkeys\_nul% } \def\mapkeys#1#2{% \_mapkeys_with_setter\_vanilla_mapkey\_keymappings{#1}% \_xp\_setdefaults\_xp{\_keymappings}% \_mapkeys_with_setter\_protected_mapkey\lastkeys{#2}% \_check_required_supplied% }