From da237d93d205989f6e955beb7ac7ec52c092aecd Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Tue, 9 Sep 2014 21:48:38 +0000
Subject: zhnumber (8sep14)

git-svn-id: svn://tug.org/texlive/trunk@35138 c570f23f-e606-0410-a88d-b1316a301751
---
 Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty | 880 ++++++++++++++--------
 1 file changed, 557 insertions(+), 323 deletions(-)

(limited to 'Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty')

diff --git a/Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty b/Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty
index 64d6ecab90c..3ff77026369 100644
--- a/Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty
+++ b/Master/texmf-dist/tex/latex/zhnumber/zhnumber.sty
@@ -6,7 +6,7 @@
 %%
 %% zhnumber.dtx  (with options: `package')
 %% 
-%%    Copyright (C) 2012 by Qing Lee <sobenlee@gmail.com>
+%%    Copyright (C) 2012, 2014 by Qing Lee <sobenlee@gmail.com>
 %% --------------------------------------------------------------------------
 %%    This work may be distributed and/or modified under the
 %%    conditions of the LaTeX Project Public License, either version 1.3
@@ -21,9 +21,11 @@
 %% 
 \NeedsTeXFormat{LaTeX2e}
 \RequirePackage{expl3}
-\GetIdInfo$Id: zhnumber.dtx 367 2012-11-23 04:45:50Z sobenlee $
+\GetIdInfo$Id: zhnumber.dtx 715 2014-09-09 14:11:20Z sobenlee $
   {Typesetting numbers with Chinese glyphs}
-\ProvidesExplPackage{\ExplFileName}{\ExplFileDate}{1.6}{\ExplFileDescription}
+\ProvidesExplPackage
+  {\ExplFileName}
+  {\ExplFileDate}{2.0}{\ExplFileDescription}
 \msg_new:nnn { zhnumber } { l3-too-old }
   {
     Support~package~'expl3'~too~old. \\\\
@@ -31,172 +33,250 @@
     'l3kernel'~and~'l3packages'\\\\
     using~your~TeX~package~manager~or~from~CTAN.
   }
-\@ifpackagelater { expl3 } { 2012/07/16 } { }
+\@ifpackagelater { expl3 } { 2014/08/25 } { }
   { \msg_error:nn  { zhnumber }  { l3-too-old } }
-\RequirePackage{xparse}
-\RequirePackage{l3keys2e}
-\DeclareExpandableDocumentCommand \zhnumber { o m }
-  { \zhnum_number_aux:nNn {#1} \zhnum_number:n {#2} }
-\cs_new_nopar:Nn \zhnum_number:n { \zhnum_number:w #1 . \q_nil . \q_stop }
-\cs_new_nopar:Nn \zhnum_number_aux:nNn
+\RequirePackage { xparse , l3keys2e }
+\DeclareExpandableDocumentCommand \zhnumber { +o +m }
   {
-    \IfNoValueTF {#1} { #2 {#3} }
-      { \group_begin: \zhnumsetup {#1} #2 {#3} \group_end: }
+    \IfNoValueTF {#1}
+      { \zhnum_number:n {#2} }
+      { \zhnumberwithoptions {#1} {#2} }
   }
-\cs_new_nopar:Npn \zhnum_number:w #1.#2.#3 \q_stop
+ \NewDocumentCommand \zhnumberwithoptions { +m +m }
+  {
+    \group_begin:
+      \keys_set:nn { zhnum / options } {#1}
+      \zhnum_number:n {#2}
+    \group_end:
+  }
+\cs_new:Npn \zhnum_number:n #1
+  { \__zhnum_number:www #1 . \q_nil . \q_stop }
+\cs_new:Npn \__zhnum_number:www #1 . #2 . #3 \q_stop
   {
     \quark_if_nil:nTF {#2}
-      { \zhnum_integer_or_fraction:w #1 / \q_nil / \q_stop }
+      { \__zhnum_integer_or_fraction:www #1 / \q_nil / \q_stop }
       { \zhnum_decimal:nn {#1} {#2} }
   }
-\cs_new_nopar:Npn \zhnum_integer_or_fraction:w #1/#2/#3 \q_stop
+\cs_new:Npn \__zhnum_integer_or_fraction:www #1 / #2 / #3 \q_stop
   {
     \quark_if_nil:nTF {#2}
-      { \zhnum_integer:f {#1} }
-      { \zhnum_fraction:w #2 \q_mark #1 ; \q_nil ; \q_stop }
+      { \zhnum_integer:n {#1} }
+      { \__zhnum_fraction:wwww #2 \q_mark #1 ; \q_nil ; \q_stop }
   }
-\cs_new_nopar:Npn \zhnum_fraction:w #1 \q_mark #2;#3;#4 \q_stop
+\cs_new:Npn \__zhnum_fraction:wwww #1 \q_mark #2 ; #3 ; #4 \q_stop
   {
     \quark_if_nil:nTF {#3}
       {
-        \zhnum_blank_to_zero:f {#1} \c_zhnum_parts_tl
+        \zhnum_blank_to_zero:f {#1}
+        \c__zhnum_parts_tl
         \zhnum_blank_to_zero:f {#2}
       }
       {
-        \tl_if_blank:fF {#2} { \zhnumber {#2} \c_zhnum_and_tl }
-        \zhnum_blank_to_zero:f {#1} \c_zhnum_parts_tl
+        \tl_if_blank:fF {#2}
+          {
+            \zhnum_number:n {#2}
+            \c__zhnum_and_tl
+          }
+        \zhnum_blank_to_zero:f {#1}
+        \c__zhnum_parts_tl
         \zhnum_blank_to_zero:f {#3}
       }
   }
 \cs_generate_variant:Nn \tl_if_blank:nF { f }
-\cs_new_nopar:Nn \zhnum_decimal:nn
+\cs_new:Npn \zhnum_decimal:nn #1#2
   {
-    \zhnum_blank_to_zero:f {#1} \c_zhnum_dot_tl
-    \tl_if_blank:fTF {#2} { \c_zhnum_zero_tl } { \zhdigits * {#2} }
+    \zhnum_blank_to_zero:f {#1} \c__zhnum_dot_tl
+    \tl_if_blank:fTF {#2}
+      { \c__zhnum_zero_tl }
+      { \zhnum_digits_zero:n {#2} }
   }
 \cs_generate_variant:Nn \tl_if_blank:nTF { f }
-\cs_new_nopar:Nn \zhnum_blank_to_zero:n
-  { \tl_if_blank:nTF {#1} { \zhnum_digit_map:n \c_zero } { \zhnumber {#1} } }
+\cs_new:Npn \zhnum_blank_to_zero:n #1
+  {
+    \tl_if_blank:nTF {#1}
+      { \c__zhnum_zero_tl }
+      { \zhnum_number:n {#1} }
+  }
 \cs_generate_variant:Nn \zhnum_blank_to_zero:n { f }
 \DeclareExpandableDocumentCommand \zhnum { o m }
-  { \zhnum_number_aux:nNn {#1} \zhnum_counter:n {#2} }
-\cs_new_nopar:Nn \zhnum_counter:n
   {
-    \exp_args:Nc \token_if_int_register:NTF { c@#1 }
-      { \zhnum_integer:v { c@#1 } }
-      { \@nocounterr {#1} }
+    \IfNoValueTF {#1}
+      { \zhnum_counter:n {#2} }
+      { \zhnumwithoptions {#1} {#2} }
   }
-\cs_new_nopar:Nn \zhnum_integer:n
+\NewDocumentCommand \zhnumwithoptions { m m }
   {
-    \int_compare:nNnT { \__int_get_sign:n {#1} \c_one } < \c_zero { \c_zhnum_minus_tl }
-    \zhnum_parse_number:f { \zhnum_trim_zeros:f { \zhnum_erase_separator:n {#1} } }
+    \group_begin:
+      \keys_set:nn { zhnum / options } {#1}
+      \zhnum_counter:n {#2}
+    \group_end:
+  }
+\cs_new_nopar:Npn \zhnum_counter:n #1
+  { \exp_args:Nc \zhnum_counter:Nn  { c@#1 } {#1} }
+\cs_new:Npn \zhnum_counter:Nn #1#2
+  {
+    \token_if_int_register:NTF #1
+      { \zhnum_int:n {#1} }
+      { \__msg_expandable_error:n { `#2' is not a LaTeX counter. } }
   }
-\cs_generate_variant:Nn \zhnum_integer:n { f , v , V }
-\cs_new_nopar:Nn \zhnum_erase_separator:n
-  { \cs_to_str:c { \tl_map_function:nN {#1} \zhnum_erase_separator_aux:N } }
-\cs_new_nopar:Nn \zhnum_erase_separator_aux:N { \zhnum_if_number:NT {#1} {#1} }
-\cs_new_nopar:Nn \zhnum_trim_zeros:n
+\cs_new:Npn \zhnum_int:n #1
   {
-    \tl_if_empty:nTF {#1} \c_zero
+    \int_compare:nNnTF {#1} > \c_zero
+      { \zhnum_parse_number:f { \int_eval:n {#1} } }
       {
-        \int_compare:nNnTF { \tl_head:n {#1} } = \c_zero
-          { \zhnum_trim_zeros:o { \use_none:n #1 } } {#1}
+        \int_compare:nNnTF {#1} < \c_zero
+          {
+            \c__zhnum_minus_tl
+            \zhnum_parse_number:f { \int_eval:n { - #1 } }
+          }
+          { \c__zhnum_zero_tl }
       }
   }
-\prg_new_conditional:Nnn \zhnum_if_number:N { p , T , F , TF }
+\cs_new:Npn \zhnum_integer:n #1
+  {
+    \exp_after:wN \__zhnum_read_integer:www
+    \tex_number:D
+      \exp_after:wN \__zhnum_read_sign_loop:N
+      \tex_romannumeral:D -`0 \use:n
+      #1 \exp_stop_f: \q_recursion_tail \q_recursion_stop
+         \__zhnum_result:nn { \c_zero } { } ;
+  }
+\cs_new:Npn \__zhnum_read_sign_loop:N #1
   {
-    \if_int_compare:w \c_one < 1 #1 \exp_stop_f:
-      \prg_return_true: \else: \prg_return_false: \fi:
+    \if:w + \if:w - \exp_not:N #1 + \fi: \exp_not:N #1
+      \exp_after:wN \__zhnum_read_sign_loop:N
+      \tex_romannumeral:D -`0 \exp_after:wN \use:n
+    \else:
+      1 \exp_after:wN ;
+      \tex_romannumeral:D -`0
+        \exp_after:wN \__zhnum_read_zeros_loop:N
+        \exp_after:wN #1
+    \fi:
+  }
+\cs_new:Npn \__zhnum_read_zeros_loop:N #1
+  {
+    \if:w 0 \exp_not:N #1
+      \exp_after:wN \__zhnum_read_zeros_loop:N
+      \tex_romannumeral:D -`0 \exp_after:wN \use:n
+    \else:
+      \exp_after:wN \__zhnum_read_abs_loop:Nw
+      \exp_after:wN #1
+    \fi:
+  }
+\cs_new:Npn \__zhnum_read_abs_loop:Nw #1#2 \q_recursion_stop
+  {
+    \zhnum_if_digit:NTF #1
+      { \__zhnum_output:nnwnn { + \c_one } #1 }
+      { \quark_if_recursion_tail_stop_do:Nn #1 { \__zhnum_loop_end:wnn } }
+    \exp_after:wN \__zhnum_read_abs_loop:Nw
+      \tex_romannumeral:D -`0 \use:n #2 \q_recursion_stop
+  }
+\cs_new:Npn \__zhnum_output:nnwnn #1#2#3 \__zhnum_result:nn #4#5
+  { #3 \__zhnum_result:nn { #4#1 } { #5#2 } }
+\cs_new:Npn \__zhnum_loop_end:wnn #1 \__zhnum_result:nn #2#3
+  { \int_eval:n {#2} ; #3 }
+\cs_new:Npn \__zhnum_read_integer:www #1 ; #2 ; #3 ;
+  {
+    \int_compare:nNnTF {#2} = \c_zero
+      { \c__zhnum_zero_tl }
+      {
+        \int_compare:nNnF {#1} = \c_one
+          { \c__zhnum_minus_tl }
+        \zhnum_parse_number:nn {#2} {#3}
+      }
   }
-\cs_generate_variant:Nn \zhnum_trim_zeros:n { f , o }
-\cs_generate_variant:Nn \cs_to_str:N        { c }
-\cs_new_nopar:Nn \zhnum_parse_number:n
+\cs_new:Npn \zhnum_if_digit:NTF #1
   {
-    \zhnum_parse_number:nff {#1}
-      { \tl_count:n {#1} }
-      { \int_mod:nn { \tl_count:n {#1} } \c_four }
+    \if_int_compare:w \c_nine < 1 \exp_not:N #1 \exp_stop_f:
+      \exp_after:wN \use_i:nn
+    \else:
+      \exp_after:wN \use_ii:nn
+    \fi:
   }
-\cs_new_nopar:Nn \zhnum_parse_number:nnn
+\cs_new_nopar:Npn \zhnum_parse_number:n #1
+  { \exp_args:Nf \zhnum_parse_number:nn { \tl_count:n {#1} } {#1} }
+\cs_new_nopar:Npn \zhnum_parse_number:nn #1#2
+  { \exp_args:Nf \__zhnum_parse_number:nnn { \int_mod:nn {#1} \c_four } {#1} {#2} }
+\cs_new_nopar:Npn \__zhnum_parse_number:nnn #1#2#3
   {
     \int_compare:nNnTF {#2} < \c_two
-      { \zhnum_digit_map:n {#1} }
+      { \zhnum_digit_map:n {#3} }
       {
-        \zhnum_split_number:fNNfn { \zhnum_insert_zeros:n {#3} #1 }
+        \zhnum_split_number:fNNfn { \zhnum_insert_zeros:n {#1} #3 }
           \c_true_bool \c_true_bool
           {
-            \int_compare:nNnTF {#3} = \c_zero
+            \int_compare:nNnTF {#1} = \c_zero
               { \int_eval:n { (#2) / \c_four - \c_one } }
               { \int_div_truncate:nn {#2} \c_four }
           }
           { \c_zero }
       }
   }
-\cs_generate_variant:Nn \zhnum_parse_number:n   {   f }
-\cs_generate_variant:Nn \zhnum_parse_number:nnn { nff }
-\cs_new_nopar:Nn \zhnum_insert_zeros:n
+\cs_generate_variant:Nn \zhnum_parse_number:n { f }
+\cs_new_nopar:Npn \zhnum_insert_zeros:n #1
   {
-    \if_case:w \int_eval:n { #1 - \c_one } \exp_stop_f:
+    \if_case:w \etex_numexpr:D #1 - \c_one \scan_stop:
       \or: \exp_after:wN \use_none:n
       \or: \exp_after:wN \use_none:nn
     \else: \exp_after:wN \use_none:nnn
     \fi:
-    000
+    0 0 0
   }
-\cs_new_nopar:Nn \zhnum_split_number:nNNnn
+\cs_new_nopar:Npn \zhnum_split_number:nNNnn #1#2#3#4#5
   {
-    \zhnum_split_number_aux:fnNNnn { \zhnum_number_item:nn {#1} {#5} }
+    \__zhnum_split_number:fnNNnn { \zhnum_number_item:nn {#1} {#5} }
       {#1} #2#3 {#4} {#5}
   }
-\cs_new_nopar:Nn \zhnum_split_number_aux:nnNNnn
+\cs_new_nopar:Npn \__zhnum_split_number:nnNNnn #1#2#3#4#5#6
   {
-    \int_compare:nNnTF {#1} = \c_zero { \use_i_ii:nnn }
+    \int_compare:nNnTF {#1} = \c_zero
+      { \__zhnum_split_number_aux:NNfnnn \c_false_bool \c_true_bool }
       {
-        \bool_if:NF #3 { \c_zhnum_zero_tl }
+        \bool_if:NF #3 { \c__zhnum_zero_tl }
         \zhnum_process_number:NNn #3#4 {#1}
-        \zhnum_scale_map:n { #5 - #6 }
+        \exp_args:Nf \zhnum_scale_map:n { \int_eval:n { #5 - #6 } }
         \int_compare:nNnTF { \int_mod:nn {#1} \c_ten } = \c_zero
-          { \use_i_ii:nnn } { \zhnum_use_i_iii:nnn }
+          { \__zhnum_split_number_aux:NNfnnn \c_false_bool \c_true_bool }
+          { \__zhnum_split_number_aux:NNfnnn \c_true_bool \c_false_bool }
       }
-    { \int_compare:nNnF {#5} = {#6} }
-    { {
-        \zhnum_split_number:nNNnf
-          {#2} \c_false_bool \c_true_bool {#5} { \int_eval:n { #6 + \c_one } }
-    } }
-    { {
-        \zhnum_split_number:nNNnf
-          {#2} \c_true_bool \c_false_bool {#5} { \int_eval:n { #6 + \c_one } }
-    } }
-  }
-\cs_new_nopar:Nn \zhnum_use_i_iii:nnn {#1#3}
-\cs_generate_variant:Nn \zhnum_split_number:nNNnn { fNNf , nNNnf }
-\cs_generate_variant:Nn \zhnum_split_number_aux:nnNNnn { f }
-\cs_new_nopar:Nn \zhnum_number_item:nn
-  { \zhnum_number_item_aux:nNNNN {#2} #1 \q_recursion_stop }
-\cs_new_nopar:Nn \zhnum_number_item_aux:nNNNN
+    { \int_eval:n { #6 + \c_one } } {#2} {#5} {#6}
+  }
+\cs_new_nopar:Npn \__zhnum_split_number_aux:NNnnnn #1#2#3#4#5#6
+  {
+    \int_compare:nNnF {#5} = {#6}
+      { \zhnum_split_number:nNNnn {#4} #1#2 {#5} {#3} }
+  }
+\cs_generate_variant:Nn \zhnum_split_number:nNNnn { fNNf }
+\cs_generate_variant:Nn \__zhnum_split_number:nnNNnn { f }
+\cs_generate_variant:Nn \__zhnum_split_number_aux:NNnnnn { NNf }
+\cs_new_nopar:Npn \zhnum_number_item:nn #1#2
+  { \__zhnum_number_item:nNNNN {#2} #1 \q_recursion_stop }
+\cs_new_nopar:Npn \__zhnum_number_item:nNNNN #1#2#3#4#5
   {
     \int_compare:nNnTF {#1} = \c_zero
-      { \zhnum_recursion_stop:NNNNw #2#3#4#5 }
-      { \zhnum_number_item_aux:fNNNN { \int_eval:n { #1 - \c_one } } }
+      { \__zhnum_recursion_stop:NNNNw #2#3#4#5 }
+      { \__zhnum_number_item:fNNNN { \int_eval:n { #1 - \c_one } } }
   }
-\cs_generate_variant:Nn \zhnum_number_item_aux:nNNNN { f }
-\cs_new_nopar:Npn \zhnum_recursion_stop:NNNNw #1#2#3#4#5 \q_recursion_stop {#1#2#3#4}
-\cs_new_nopar:Nn \zhnum_process_number:NNn
+\cs_generate_variant:Nn \__zhnum_number_item:nNNNN { f }
+\cs_new_nopar:Npn \__zhnum_recursion_stop:NNNNw #1#2#3#4#5 \q_recursion_stop
+  { #1#2#3#4 }
+\cs_new_nopar:Npn \zhnum_process_number:NNn #1#2#3
   { \zhnum_process_number:NNNNNN #3#1#2 }
-\cs_new_nopar:Nn \zhnum_process_number:NNNNNN
+\cs_new_nopar:Npn \zhnum_process_number:NNNNNN #1#2#3#4#5#6
   {
     \int_compare:nNnTF {#1} = \c_zero
-      { \bool_if:NF #6 { \c_zhnum_zero_tl } }
-      { \zhnum_digit_map:n {#1} \c_zhnum_thousand_tl }
+      { \bool_if:NF #6 { \c__zhnum_zero_tl } }
+      { \zhnum_digit_map:n {#1} \c__zhnum_thousand_tl }
     \int_compare:nNnTF {#2} = \c_zero
-      { \int_compare:nNnT { #1 * (#3#4) } > \c_zero { \c_zhnum_zero_tl } }
+      { \int_compare:nNnT { #1 * (#3#4) } > \c_zero { \c__zhnum_zero_tl } }
       {
         \bool_if:nTF
-          { \l_zhnum_ancient_bool && \int_compare_p:nNn {#2} = \c_two }
+          { \l__zhnum_ancient_bool && \int_compare_p:nNn {#2} = \c_two }
           { \zhnum_digit_map:n { #2 00 } }
-          { \zhnum_digit_map:n {#2} \c_zhnum_hundred_tl }
+          { \zhnum_digit_map:n {#2} \c__zhnum_hundred_tl }
       }
     \int_compare:nNnTF {#3} = \c_zero
-      { \int_compare:nNnT { #2 * #4 } > \c_zero { \c_zhnum_zero_tl } }
+      { \int_compare:nNnT { #2 * #4 } > \c_zero { \c__zhnum_zero_tl } }
       {
         \bool_if:nF
           {
@@ -206,7 +286,7 @@
           {
             \bool_if:nTF
               {
-                \l_zhnum_ancient_bool                   &&
+                \l__zhnum_ancient_bool                   &&
                 ( \int_compare_p:nNn {#3} = \c_two   ||
                   \int_compare_p:nNn {#3} = \c_three ||
                   \int_compare_p:nNn {#3} = \c_four )
@@ -214,364 +294,525 @@
               { \zhnum_digit_map:n { #3 0 } \use_none:n }
               { \zhnum_digit_map:n {#3} }
           }
-        \c_zhnum_ten_tl
+        \c__zhnum_ten_tl
       }
     \int_compare:nNnF {#4} = \c_zero { \zhnum_digit_map:n {#4} }
   }
 \DeclareExpandableDocumentCommand \zhdigits { s o m }
   {
-    \IfBooleanTF {#1}
-      { \zhnum_digits_aux:nnN {#2} {#3} \zhnum_digits_zero_aux:N }
-      { \zhnum_digits_aux:nnN {#2} {#3} \zhnum_digits_null_aux:N }
+    \IfNoValueTF {#2}
+      { \zhnum_digits:Nn #1 {#3} }
+      {
+        \IfBooleanTF #1
+          { \zhdigitswithoptions * }
+          { \zhdigitswithoptions }
+        {#2} {#3}
+      }
   }
-\cs_new_nopar:Nn \zhnum_digits_aux:nnN
+\NewDocumentCommand \zhdigitswithoptions { s m m }
   {
-    \IfNoValueTF {#1} { \tl_map_function:fN {#2} #3 }
-      { \group_begin: \zhnumsetup {#1} \tl_map_function:fN {#2} #3 \group_end: }
+    \group_begin:
+      \keys_set:nn { zhnum / options } {#2}
+      \zhnum_digits:Nn #1 {#3}
+    \group_end:
   }
-\cs_new_nopar:Nn \zhnum_digits_null:n { \tl_map_function:fN {#1} \zhnum_digits_null_aux:N }
+\cs_new_nopar:Npn \zhnum_digits_zero:n
+  { \zhnum_digits:Nn \BooleanTrue }
+\cs_new_nopar:Npn \zhnum_digits_null:n
+  { \zhnum_digits:Nn \BooleanFalse }
 \cs_generate_variant:Nn \zhnum_digits_null:n { V }
-\cs_generate_variant:Nn \tl_map_function:nN  { f }
-\cs_new_nopar:Nn \zhnum_digits_null_aux:N { \zhnum_digits_aux:NN \c_true_bool  #1 }
-\cs_new_nopar:Nn \zhnum_digits_zero_aux:N { \zhnum_digits_aux:NN \c_false_bool #1 }
-\cs_new_nopar:Nn \zhnum_digits_aux:NN
+\cs_new:Npn \zhnum_digits:Nn #1#2
+  {
+    \exp_after:wN \__zhnum_read_digits:w
+    \tex_number:D
+      \exp_after:wN \__zhnum_read_sign_loop:NN \exp_after:wN #1
+      \tex_romannumeral:D -`0 \use:n
+      #2 \exp_stop_f: \q_recursion_tail \q_recursion_stop
+  }
+\cs_new:Npn \__zhnum_read_sign_loop:NN #1#2
+  {
+    \if:w + \if:w - \exp_not:N #2 + \fi: \exp_not:N #2
+      \exp_after:wN \__zhnum_read_sign_loop:NN \exp_after:wN #1
+      \tex_romannumeral:D -`0 \exp_after:wN \use:n
+    \else:
+      1 \exp_after:wN ;
+        \exp_after:wN \__zhnum_read_digits_loop:NN
+        \exp_after:wN #1
+        \exp_after:wN #2
+    \fi:
+  }
+\cs_new:Npn \__zhnum_read_digits_loop:NN #1#2
   {
-    \str_if_eq_x:nnTF {#2} . \c_zhnum_dot_tl
+    \zhnum_if_digit:NTF #2
+      { \__zhnum_output_digits:NN #1#2 }
       {
-        \str_if_eq_x:nnTF {#2} -
-          { \c_zhnum_minus_tl }
-          {
-            \zhnum_if_number:NT {#2}
-              {
-                \bool_if:nTF { \int_compare_p:nNn {#2} = \c_zero }
-                  { \bool_if:NTF #1 \c_zhnum_null_tl \c_zhnum_zero_tl }
-                  { \zhnum_digit_map:n {#2} }
-              }
-          }
+        \quark_if_recursion_tail_stop:N #2
+        \if:w .\exp_not:N #2 \exp_after:wN \c__zhnum_dot_tl \fi:
       }
+    \exp_after:wN \__zhnum_read_digits_loop:NN \exp_after:wN #1
+        \tex_romannumeral:D -`0 \use:n
+  }
+\cs_new:Npn \__zhnum_read_digits:w #1 ;
+  {
+    \int_compare:nNnF {#1} = \c_one
+      { \c__zhnum_minus_tl }
+  }
+\cs_new:Npn \__zhnum_output_digits:NN #1#2
+  {
+    \cs:w
+      c__zhnum_
+        \if_int_compare:w #2 = \c_zero
+          \IfBooleanTF #1 { zero } { null }
+        \else:
+          #2
+        \fi:
+      _tl
+    \cs_end:
   }
 \DeclareExpandableDocumentCommand \zhdate { s m }
   {
-    \zhnum_date:w #2 \q_stop
-    \IfBooleanT {#1} { \zhweekday {#2} }
+    \__zhnum_date:www #2 \q_stop
+    \IfBooleanT {#1}
+      {  \__zhnum_week_day:www #2 \q_stop }
   }
-\cs_new_nopar:Npn \zhnum_date:w #1/#2/#3 \q_stop
+\cs_new_nopar:Npn \__zhnum_date:www #1/#2/#3 \q_stop
   {
-    \zhnum_check_time:Nn \zhnum_digits_null:n {#1} \c_zhnum_year_tl
-    \zhnum_check_time:Nn \zhnum_integer:f {#2} \c_zhnum_month_tl
-    \zhnum_check_time:Nn \zhnum_integer:f {#3} \c_zhnum_day_tl
+    \zhnum_check_time:Nn \zhnum_digits_null:n {#1} \c__zhnum_year_tl
+    \zhnum_check_time:Nn \zhnum_integer:n {#2} \c__zhnum_month_tl
+    \zhnum_check_time:Nn \zhnum_integer:n {#3} \c__zhnum_day_tl
   }
 \cs_new_nopar:Npn \zhtoday
   {
-    \zhnum_check_time:Nn \zhnum_digits_null:V \tex_year:D \c_zhnum_year_tl
-    \zhnum_check_time:Nn \zhnum_integer:V \tex_month:D \c_zhnum_month_tl
-    \zhnum_check_time:Nn \zhnum_integer:V \tex_day:D   \c_zhnum_day_tl
+    \zhnum_check_time:Nn \zhnum_digits_null:V \tex_year:D \c__zhnum_year_tl
+    \zhnum_check_time:Nn \zhnum_int:n \tex_month:D \c__zhnum_month_tl
+    \zhnum_check_time:Nn \zhnum_int:n \tex_day:D   \c__zhnum_day_tl
+  }
+\cs_new_nopar:Npn \zhnum_check_time:Nn #1
+  { \bool_if:NTF \l__zhnum_time_bool {#1} { \int_eval:n } }
+\cs_new_nopar:Npn \zhweekday #1
+  { \__zhnum_week_day:www #1 \q_stop }
+\cs_new_nopar:Npn \__zhnum_week_day:www #1/#2/#3 \q_stop
+  {
+    \if_case:w \etex_numexpr:D \zhnum_Zeller:nnn {#1} {#2} {#3} \scan_stop:
+           \c__zhnum_sat_tl
+      \or: \c__zhnum_sun_tl
+      \or: \c__zhnum_mon_tl
+      \or: \c__zhnum_tue_tl
+      \or: \c__zhnum_wed_tl
+      \or: \c__zhnum_thu_tl
+      \or: \c__zhnum_fri_tl
+    \fi:
   }
-\cs_new_nopar:Nn \zhnum_check_time:Nn
-  { \bool_if:NTF \l_zhnum_time_bool {#1} { \int_eval:n } {#2} }
-\cs_new_nopar:Npn \zhweekday #1 { \zhnum_week_day:w #1 \q_stop }
-\cs_new_nopar:Nn \zhnum_Zeller:nnn
+\cs_new_nopar:Npn \zhnum_Zeller:nnn #1#2#3
   {
     \int_compare:nNnTF
       { #1 \zhnum_two_digits:n {#2} \zhnum_two_digits:n {#3} } > { 1582 10 04 }
-      { \zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Gregorian:nnn }
-      { \zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Julian:nnn }
+      { \__zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Gregorian:nnn }
+      { \__zhnum_Zeller_aux:Nnnn \zhnum_Zeller_Julian:nnn }
     {#1} {#2} {#3}
   }
-\cs_new_nopar:Nn \zhnum_Zeller_aux:Nnnn
+\cs_new_nopar:Npn \__zhnum_Zeller_aux:Nnnn  #1#2#3#4
   {
     \int_compare:nNnTF {#3} < \c_three
       { #1 { #2 - \c_one } { #3 + \c_twelve } {#4} }
       { #1 {#2} {#3} {#4} }
   }
-\cs_new_nopar:Nn \zhnum_two_digits:n
+\cs_new_nopar:Npn \zhnum_two_digits:n #1
   {
     \int_compare:nNnT {#1} < \c_ten { 0 }
     \int_eval:n {#1}
   }
-\cs_new_nopar:Nn \zhnum_Zeller_Gregorian:nnn
+\cs_new_nopar:Npn \zhnum_Zeller_Gregorian:nnn #1#2#3
   {
     \int_mod:nn
       {
-          \int_eval:n {#3}
-        + \int_div_truncate:nn { 26 * ( \int_eval:n {#2} + \c_one ) } \c_ten
-        + \int_eval:n {#1}
+          (#3)
+        + \int_div_truncate:nn { 26 * ( #2 + \c_one ) } \c_ten
+        + (#1)
         + \int_div_truncate:nn {#1} \c_four
         + \c_six * \int_div_truncate:nn {#1} \c_one_hundred
         + \int_div_truncate:nn {#1} { 400 }
       }
       { \c_seven }
   }
-\cs_new_nopar:Nn \zhnum_Zeller_Julian:nnn
+\cs_new_nopar:Npn \zhnum_Zeller_Julian:nnn #1#2#3
   {
     \int_mod:nn
       {
-          \int_eval:n {#3}
-        + \int_div_truncate:nn { 26 * ( \int_eval:n {#2} + \c_one ) } \c_ten
-        + \int_eval:n {#1}
+          (#3)
+        + \int_div_truncate:nn { 26 * ( #2 + \c_one ) } \c_ten
+        + (#1)
         + \int_div_truncate:nn {#1} \c_four
         + \c_five
       }
       { \c_seven }
   }
-\cs_new_nopar:Npn \zhnum_week_day:w #1/#2/#3 \q_stop
-  {
-    \if_case:w \int_eval:n { \zhnum_Zeller:nnn {#1} {#2} {#3} } \exp_stop_f:
-           \c_zhnum_sat_tl
-      \or: \c_zhnum_sun_tl
-      \or: \c_zhnum_mon_tl
-      \or: \c_zhnum_tue_tl
-      \or: \c_zhnum_wed_tl
-      \or: \c_zhnum_thu_tl
-      \or: \c_zhnum_fri_tl
-    \fi:
-  }
-\cs_new_nopar:Npn \zhtime #1 { \zhnum_time:w #1 \q_stop }
+\cs_new_nopar:Npn \zhtime #1
+  { \__zhnum_time:ww #1 \q_stop }
 \group_begin:
 \char_set_lccode:nn { `\; } { `\: }
 \tl_to_lowercase:n
   {
     \group_end:
-    \cs_new_nopar:Npn \zhnum_time:w #1 ; #2 \q_stop
+    \cs_new_nopar:Npn \__zhnum_time:ww #1 ; #2 \q_stop
       {
-        \zhnum_check_time:Nn \zhnum_integer:f {#1} \c_zhnum_hour_tl
-        \zhnum_check_time:Nn \zhnum_integer:f {#2} \c_zhnum_minute_tl
+        \zhnum_check_time:Nn \zhnum_integer:n {#1} \c__zhnum_hour_tl
+        \zhnum_check_time:Nn \zhnum_integer:n {#2} \c__zhnum_minute_tl
       }
   }
 \cs_new_nopar:Npn \zhcurrtime
   {
-    \zhnum_check_time:Nn \zhnum_integer:f
-      { \int_div_truncate:nn \tex_time:D { 60 } } \c_zhnum_hour_tl
-    \zhnum_check_time:Nn \zhnum_integer:f
-      { \int_mod:nn \tex_time:D { 60 } } \c_zhnum_minute_tl
+    \zhnum_check_time:Nn \zhnum_int:n
+      { \int_div_truncate:nn \tex_time:D { 60 } } \c__zhnum_hour_tl
+    \zhnum_check_time:Nn \zhnum_int:n
+      { \int_mod:nn \tex_time:D { 60 } } \c__zhnum_minute_tl
   }
-\cs_new_nopar:Nn \zhnum_digit_map:n
-  { \tl_use:c { c_zhnum_ \zhnum_int_to_word:n {#1} _tl } }
-\cs_new_nopar:Nn \zhnum_scale_map:n
+\cs_new_nopar:Npn \zhnum_digit_map:n #1
+  { \use:c { c__zhnum_ #1 _tl } }
+\cs_new_nopar:Npn \zhnum_scale_map:n #1
   {
-    \cs_if_exist_use:cF { c_zhnum_scale_ \zhnum_int_to_word:n {#1} _tl }
+    \cs_if_exist_use:cF { c__zhnum_s #1 _tl }
       { \zhnum_scale_map_hook:n {#1} }
   }
-\cs_new_nopar:Nn \zhnum_scale_map_loop:n
-  { \zhnum_scale_map:n { \int_mod:nn {#1} \g_zhnum_scale_int } }
-\int_new:N \g_zhnum_scale_int
-\int_set_eq:NN \g_zhnum_scale_int \c_eleven
+\cs_new_nopar:Npn \zhnum_scale_map_loop:n #1
+  { \zhnum_scale_map:n { \int_mod:nn {#1} \g__zhnum_scale_int } }
+\int_new:N \g__zhnum_scale_int
+\int_set_eq:NN \g__zhnum_scale_int \c_eleven
 \cs_new_eq:NN \zhnum_scale_map_hook:n \zhnum_scale_map_loop:n
 \NewDocumentCommand \zhnumExtendScaleMap { > { \TrimSpaces } o m }
   {
-   \int_zero:N \l_tmpa_int
+    \int_zero:N \l_tmpa_int
     \clist_map_inline:nn {#2}
       {
         \int_incr:N \l_tmpa_int
         \tl_set:Nx \l_tmpa_tl
-          { c_zhnum_scale_ \zhnum_int_to_word:n { \l_tmpa_int + \c_eleven } _tl }
-        \tl_if_exist:cF \l_tmpa_tl { \int_incr:N \g_zhnum_scale_int }
+          { c__zhnum_s \int_eval:n { \l_tmpa_int + \c_eleven } _tl }
+        \tl_if_exist:cF { \l_tmpa_tl }
+          { \int_incr:N \g__zhnum_scale_int }
         \tl_set:cn { \l_tmpa_tl } {##1}
       }
-    \IfValueT {#1} { \cs_set:Nn \zhnum_scale_map_hook:n {#1} }
-  }
-\cs_new_nopar:Nn \zhnum_int_to_word:n
-  {
-    \if_case:w \int_eval:n {#1} \exp_stop_f:
-           zero
-      \or: one
-      \or: two
-      \or: three
-      \or: four
-      \or: five
-      \or: six
-      \or: seven
-      \or: eight
-      \or: nine
-      \or: ten
-      \or: eleven
-    \else:
-      \int_case:nnn {#1}
-        {
-          { 20 } { twenty }  { 30  } { thirty }
-          { 40 } { forty }   { 200 } { two_hundred }
-        }
-        { \int_to_roman:n {#1} }
-    \fi:
+    \IfNoValueF {#1}
+      { \cs_set:Npn \zhnum_scale_map_hook:n ##1 {#1} }
   }
 
-\keys_define:nn { zhnum / options }
-  {
-    -   .tl_set:N = \l_zhnum_minus_tl        ,
-    -0  .tl_set:N = \l_zhnum_null_tl         ,
-    E2  .tl_set:N = \l_zhnum_hundred_tl      ,
-    E3  .tl_set:N = \l_zhnum_thousand_tl     ,
-    FE2 .tl_set:N = \l_zhnum_financial_hundred_tl ,
-    FE3 .tl_set:N = \l_zhnum_financial_thousand_tl ,
-  }
-\clist_map_inline:nn
-  { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 20 , 30 , 40 , 200 }
+\group_begin:
+  \tl_set:Nn \l_tmpa_tl
+    {
+      -   .tl_set:N = \l__zhnum_minus_tl ,
+      -0  .tl_set:N = \l__zhnum_null_tl ,
+    }
+  \tl_put_right:Nx \l_tmpa_tl
+    {
+      E2  .tl_set:N = \exp_not:c { l__zhnum_ 100 _tl } ,
+      E3  .tl_set:N = \exp_not:c { l__zhnum_ 1000 _tl } ,
+      FE2 .tl_set:N = \exp_not:c { l__zhnum_financial_ 100 _tl } ,
+      FE3 .tl_set:N = \exp_not:c { l__zhnum_financial_ 1000 _tl } ,
+    }
+  \clist_map_inline:nn
+    { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 100 , 1000 }
+    {
+      \tl_put_right:Nx \l_tmpa_tl
+        {
+           #1 .tl_set:N = \exp_not:c { l__zhnum_ #1 _tl } ,
+          F#1 .tl_set:N = \exp_not:c { l__zhnum_financial_ #1 _tl } ,
+        }
+    }
+  \clist_map_inline:nn
+    { 20 , 30 , 40 , 200 }
+    {
+      \tl_put_right:Nx \l_tmpa_tl
+        { #1 .tl_set:N = \exp_not:c { l__zhnum_ #1 _tl } , }
+    }
+  \clist_map_inline:nn
+    { 4 , 8 , 12 , 16 , 20 , 24 , 28 , 32 , 36 , 40 , 44 }
+    {
+      \tl_put_right:Nx \l_tmpa_tl
+        { E#1 .tl_set:N = \exp_not:c { l__zhnum_ s \int_eval:n { #1 / 4 } _tl } , }
+    }
+  \clist_map_inline:nn
+    {
+      dot , and , parts , year , month , day , weekday , hour , minute
+      mon , tue , wed , thu , fri , sat , sun
+    }
+    {
+      \tl_put_right:Nx \l_tmpa_tl
+        { #1 .tl_set:N = \exp_not:c { l__zhnum_ #1 _tl } , }
+    }
+\use:x
   {
-    \keys_define:nn { zhnum / options }
-      { #1 .tl_set:c = { l_zhnum_ \zhnum_int_to_word:n {#1} _tl } }
-    \int_compare:nNnF {#1} > \c_ten
-      {
-        \keys_define:nn { zhnum / options }
-          { F#1 .tl_set:c = { l_zhnum_financial_ \zhnum_int_to_word:n {#1} _tl } }
-      }
+    \group_end:
+    \keys_define:nn { zhnum / options } { \exp_not:o \l_tmpa_tl }
   }
-\clist_map_inline:nn
-  { 4 , 8 , 12 , 16 , 20 , 24 , 28 , 32 , 36 , 40 , 44 }
+\cs_new_protected_nopar:Npn \zhnum_set_digits_map:nn #1#2
+  { \prop_put:Nnn \l__zhnum_cfg_map_prop {#1} {#2} }
+\cs_new_protected_nopar:Npn \zhnum_set_digits_map:nnn #1#2#3
   {
-    \keys_define:nn { zhnum / options }
-      { E#1 .tl_set:c = { l_zhnum_scale_ \zhnum_int_to_word:n { #1 / 4 } _tl } }
+    \prop_put_if_new:Nnn \l__zhnum_cfg_map_prop {#1} {#3}
+    \prop_put:Nnn \l__zhnum_cfg_map_var_prop {#1_#2} {#3}
   }
-\clist_map_inline:nn
+\cs_new_protected_nopar:Npn \zhnum_set_financial_map:nn #1#2
+  { \prop_put:Nnn \l__zhnum_cfg_map_finan_prop {#1} {#2} }
+\cs_new_protected_nopar:Npn \zhnum_set_financial_map:nnn #1#2#3
   {
-    dot , and , parts , year , month , day , weekday , hour , minute
-    mon , tue , wed , thu , fri , sat , sun
+    \prop_put_if_new:Nnn \l__zhnum_cfg_map_finan_prop {#1} {#3}
+    \prop_put:Nnn \l__zhnum_cfg_map_var_prop { financial_#1_#2 } {#3}
   }
-  { \keys_define:nn { zhnum / options } { #1 .tl_set:c = { l_zhnum_ #1 _tl } } }
-\cs_new_nopar:Nn \zhnum_parse_config:
+\prop_new:N \l__zhnum_cfg_map_prop
+\prop_new:N \l__zhnum_cfg_map_var_prop
+\prop_new:N \l__zhnum_cfg_map_finan_prop
+\cs_new_protected_nopar:Npn \zhnum_parse_config:
   {
-    \prop_map_function:NN \g_zhnum_cfg_map_prop \zhnum_check_simp:nn
-    \prop_map_function:NN \g_zhnum_cfg_map_prop \zhnum_check_financial:nn
+    \prop_map_function:NN \l__zhnum_cfg_map_prop \zhnum_check_simp:nn
+    \bool_if:NF \l__zhnum_reset_bool
+      { \prop_map_function:NN \l__zhnum_cfg_map_prop \zhnum_check_financial:nn }
     \zhnum_set_zero:
     \zhnum_set_week_day:
   }
-\cs_new_nopar:Nn \zhnum_check_simp:nn
+\cs_new_protected_nopar:Npn \zhnum_check_simp:nn #1#2
   {
-    \zhnum_check_simp_aux:nn {#1} {#2}
-    \prop_get:NnNT \g_zhnum_cfg_map_finan_prop {#1} \l_tmpa_tl
-      { \exp_args:NnV \zhnum_check_simp_aux:nn { financial_ #1 } \l_tmpa_tl }
+    \__zhnum_check_simp_aux:nn {#1} {#2}
+    \prop_get:NnNT \l__zhnum_cfg_map_finan_prop {#1} \l_tmpa_tl
+      { \exp_args:Nno \__zhnum_check_simp_aux:nn { financial_ #1 } \l_tmpa_tl }
   }
-\cs_new_nopar:Nn \zhnum_check_simp_aux:nn
+\cs_new_protected_nopar:Npn \__zhnum_check_simp_aux:nn #1#2
   {
-    \prop_get:NnNTF \g_zhnum_cfg_map_var_prop { #1 _trad } \l_tmpa_tl
+    \prop_get:NnNTF \l__zhnum_cfg_map_var_prop { #1 _trad } \l_tmpa_tl
       {
-        \prop_get:NnNTF \g_zhnum_cfg_map_var_prop { #1 _simp } \l_tmpb_tl
+        \prop_get:NnNTF \l__zhnum_cfg_map_var_prop { #1 _simp } \l_tmpb_tl
           {
-            \tl_set:cx { l_zhnum_ #1 _tl }
+            \tl_set:cx { l__zhnum_ #1 _tl }
               {
-                \exp_not:n { \bool_if:NTF \l_zhnum_simp_bool }
-                  { \exp_not:V \l_tmpb_tl } { \exp_not:V \l_tmpa_tl }
+                \exp_not:n { \bool_if:NTF \l__zhnum_simp_bool }
+                  { \exp_not:o \l_tmpb_tl } { \exp_not:o \l_tmpa_tl }
               }
           }
           {
-            \tl_set:cx { l_zhnum_ #1 _tl }
+            \tl_set:cx { l__zhnum_ #1 _tl }
               {
-                \exp_not:n { \bool_if:NTF \l_zhnum_simp_bool }
-                  { \exp_not:n {#2} } { \exp_not:V \l_tmpa_tl }
+                \exp_not:n { \bool_if:NTF \l__zhnum_simp_bool }
+                  { \exp_not:n {#2} } { \exp_not:o \l_tmpa_tl }
               }
           }
       }
-      { \tl_set:cn { l_zhnum_ #1 _tl } {#2} }
+      { \tl_set:cn { l__zhnum_ #1 _tl } {#2} }
   }
-\cs_new_nopar:Nn \zhnum_check_financial:nn
+\cs_new_protected_nopar:Npn \zhnum_check_financial:nn #1#2
   {
-    \prop_get:NnNTF \g_zhnum_cfg_map_finan_prop {#1} \l_tmpa_tl
+    \prop_get:NnNTF \l__zhnum_cfg_map_finan_prop {#1} \l_tmpa_tl
       {
-        \tl_set:cx { c_zhnum_ #1 _tl }
+        \zhnum_assgin_const_tl:cx { c__zhnum_ #1 _tl }
           {
-            \exp_not:n { \bool_if:NTF \l_zhnum_normal_bool }
-              { \exp_not:c { l_zhnum_ #1 _tl } }
-              { \exp_not:c { l_zhnum_financial_ #1 _tl } }
+            \exp_not:n { \bool_if:NTF \l__zhnum_normal_bool }
+              { \exp_not:c { l__zhnum_ #1 _tl } }
+              { \exp_not:c { l__zhnum_financial_ #1 _tl } }
           }
       }
-      { \tl_set:cx { c_zhnum_ #1 _tl } { \exp_not:c { l_zhnum_ #1 _tl } } }
+      {
+        \zhnum_assgin_const_tl:cx
+          { c__zhnum_ #1 _tl } { \exp_not:c { l__zhnum_ #1 _tl } }
+      }
   }
-\cs_new_nopar:Nn \zhnum_set_zero:
+\cs_new_protected_nopar:Npn \zhnum_set_zero:
   {
-    \tl_set:Nx \l_zhnum_zero_tl
+    \tl_set:cx { l__zhnum_0_tl }
       {
-        \exp_not:n { \bool_if:nTF \l_zhnum_null_bool }
-          { \exp_not:V \l_zhnum_null_tl } { \exp_not:V \l_zhnum_zero_tl }
+        \exp_not:n { \bool_if:nTF \l__zhnum_null_bool }
+          { \exp_not:o \l__zhnum_null_tl } { \exp_not:v { l__zhnum_0_tl } }
       }
   }
-\cs_new_nopar:Nn \zhnum_set_week_day:
+\cs_new_protected_nopar:Npn \zhnum_set_week_day:
+  {
+    \tl_set:Nx \l__zhnum_mon_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_1_tl } }
+    \tl_set:Nx \l__zhnum_tue_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_2_tl } }
+    \tl_set:Nx \l__zhnum_wed_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_3_tl } }
+    \tl_set:Nx \l__zhnum_thu_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_4_tl } }
+    \tl_set:Nx \l__zhnum_fri_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_5_tl } }
+    \tl_set:Nx \l__zhnum_sat_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:v { l__zhnum_6_tl } }
+    \tl_set:Nx \l__zhnum_sun_tl
+      { \exp_not:N \c__zhnum_weekday_tl \exp_not:o \l__zhnum_day_tl }
+    \bool_if:NF \l__zhnum_reset_bool
+      {
+        \clist_map_inline:nn { mon , tue , wed , thu , fri , sat , sun }
+          {
+            \zhnum_assgin_const_tl:cx
+              { c__zhnum_ ##1 _tl } { \exp_not:c { l__zhnum_ ##1 _tl } }
+          }
+        \bool_set_true:N \l__zhnum_reset_bool
+      }
+  }
+\cs_new_eq:NN \zhnum_assgin_const_tl:cx \tl_const:cx
+\AtEndOfPackage
+  { \cs_set_eq:NN \zhnum_assgin_const_tl:cx \tl_set:cx }
+\cs_new_protected_nopar:Npn \zhnum_set_alias:
+  {
+    \tl_const:Nx \c__zhnum_zero_tl     { \exp_not:c { c__zhnum_ 0 _tl } }
+    \tl_const:Nx \c__zhnum_ten_tl      { \exp_not:c { c__zhnum_ 10 _tl } }
+    \tl_const:Nx \c__zhnum_hundred_tl  { \exp_not:c { c__zhnum_ 100 _tl } }
+    \tl_const:Nx \c__zhnum_thousand_tl { \exp_not:c { c__zhnum_ 1000 _tl } }
+  }
+\AtEndOfPackage { \zhnum_set_alias: }
+\cs_new_protected_nopar:Npn \zhnum_load_cfg:n #1
   {
-    \tl_set:Nx \l_zhnum_mon_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_one_tl   }
-    \tl_set:Nx \l_zhnum_tue_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_two_tl   }
-    \tl_set:Nx \l_zhnum_wed_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_three_tl }
-    \tl_set:Nx \l_zhnum_thu_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_four_tl  }
-    \tl_set:Nx \l_zhnum_fri_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_five_tl  }
-    \tl_set:Nx \l_zhnum_sat_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_six_tl   }
-    \tl_set:Nx \l_zhnum_sun_tl { \exp_not:N \c_zhnum_weekday_tl \exp_not:V \l_zhnum_day_tl   }
-    \clist_map_inline:nn { mon , tue , wed , thu , fri , sat , sun }
-      { \tl_set:cx { c_zhnum_ ##1 _tl } { \exp_not:c { l_zhnum_ ##1 _tl } } }
+    \zhnum_set_cfg_name:Nn \l__zhnum_cfg_tl {#1}
+    \tl_if_eq:NNF \l__zhnum_cfg_tl \l__zhnum_last_cfg_tl
+      { \zhnum_update_cfg:n {#1} }
+    \zhnum_parse_config:
   }
-\cs_new:Nn \zhnum_load_cfg:n
+\cs_generate_variant:Nn \zhnum_load_cfg:n { o }
+\cs_new_protected_nopar:Npn \zhnum_update_cfg:n #1
   {
-    \cs_if_exist:NT \CJK@makeActive
+    \prop_if_exist:cTF { g__zhnum_cfg_ \l__zhnum_cfg_tl _prop }
+      { \tl_set_eq:NN \l__zhnum_last_cfg_tl \l__zhnum_cfg_tl }
+      { \zhnum_input_cfg:n  {#1} }
+    \__zhnum_update_cfg_prop:N \prop_set_eq:Nc
+  }
+\cs_new_protected_nopar:Npn \zhnum_input_cfg:n #1
+  {
+    \file_if_exist_input:nTF { zhnumber - #1 .cfg }
       {
-        \int_compare:nNnTF { \char_value_catcode:n {"080} } = \active
-          { \bool_set_false:N \l_zhnum_set_CJK_active_bool }
-          { \bool_set_true:N \l_zhnum_set_CJK_active_bool \CJK@makeActive }
+        \bool_set_false:N \l__zhnum_reset_bool
+        \__zhnum_update_cfg_prop:N \__zhnum_prop_initial:Nn
+        \group_begin:
+          \zhnum_set_catcode:
       }
-    \prop_clear:N \g_zhnum_cfg_map_prop
-    \prop_clear:N \g_zhnum_cfg_map_var_prop
-    \prop_clear:N \g_zhnum_cfg_map_finan_prop
-    \file_input:n { zhnumber - #1 .cfg }
-    \zhnum_parse_config:
-    \bool_if:nT { \cs_if_exist_p:N \CJK@makeInactive && \l_zhnum_set_CJK_active_bool }
-      { \CJK@makeInactive }
+      {
+        \msg_error:nnx { zhnumber } { file-not-found } {#1}
+        \use_none:nnn
+      }
+    \__zhnum_update_cfg_prop:N \__zhnum_prop_gset_eq:Nn
+    \group_end:
+  }
+\cs_new_protected_nopar:Npn \__zhnum_update_cfg_prop:N #1
+  {
+    #1 \l__zhnum_cfg_map_prop       { g__zhnum_cfg_ \l__zhnum_cfg_tl _prop }
+    #1 \l__zhnum_cfg_map_var_prop   { g__zhnum_cfg_var_ \l__zhnum_cfg_tl _prop }
+    #1 \l__zhnum_cfg_map_finan_prop { g__zhnum_cfg_finan_ \l__zhnum_cfg_tl _prop }
+  }
+\cs_new_protected:Npn \__zhnum_prop_initial:Nn #1#2
+  {
+    \prop_clear:N #1
+    \prop_new:c {#2}
+  }
+\cs_new_protected:Npn \__zhnum_prop_gset_eq:Nn #1#2
+  { \prop_gset_eq:cN {#2} #1 }
+\tl_new:N \l__zhnum_cfg_tl
+\tl_new:N \l__zhnum_last_cfg_tl
+\bool_new:N \l__zhnum_reset_bool
+\msg_new:nnnn  { zhnumber } { file-not-found }
+  { File~`#1'~not~found. }
+  {
+    The~requested~file~could~not~be~found~in~the~current~directory,~
+    in~the~TeX~search~path~or~in~the~LaTeX~search~path.
+  }
+\pdftex_if_engine:TF
+  {
+    \str_if_eq_x:nnTF
+      { \token_to_str:N \kchar }
+      { \token_to_meaning:N \kchar }
   }
-\cs_new_protected_nopar:Nn \zhnum_set_digits_map:nn
-  { \prop_put:Nnn \g_zhnum_cfg_map_prop {#1} {#2} }
-\cs_new_protected_nopar:Nn \zhnum_set_digits_map:nnn
+  { \use_i:nn }
   {
-    \prop_put_if_new:Nnn \g_zhnum_cfg_map_prop {#1} {#3}
-    \prop_put:Nnn \g_zhnum_cfg_map_var_prop {#1_#2} {#3}
+    \cs_new_eq:NN \zhnum_if_unicode_engine_p: \c_true_bool
+    \cs_new_eq:NN \zhnum_if_unicode_engine:TF \use_i:nn
   }
-\cs_new_protected_nopar:Nn \zhnum_set_financial_map:nn
-  { \prop_put:Nnn \g_zhnum_cfg_map_finan_prop {#1} {#2} }
-\cs_new_protected_nopar:Nn \zhnum_set_financial_map:nnn
   {
-    \prop_put_if_new:Nnn \g_zhnum_cfg_map_finan_prop {#1} {#3}
-    \prop_put:Nnn \g_zhnum_cfg_map_var_prop { financial_#1_#2 } {#3}
+    \cs_new_eq:NN \zhnum_if_unicode_engine_p: \c_false_bool
+    \cs_new_eq:NN \zhnum_if_unicode_engine:TF \use_ii:nn
   }
-\prop_new:N \g_zhnum_cfg_map_prop
-\prop_new:N \g_zhnum_cfg_map_var_prop
-\prop_new:N \g_zhnum_cfg_map_finan_prop
+\if_predicate:w \zhnum_if_unicode_engine_p:
+  \cs_new_eq:NN \zhnum_set_catcode: \prg_do_nothing:
+  \cs_new_protected_nopar:Npn \zhnum_set_cfg_name:Nn #1#2
+    {
+      \tl_set:Nx \l__zhnum_encoding_tl {#2}
+      \tl_set:Nx #1 { \tl_to_str:N \l__zhnum_encoding_tl }
+    }
+  \cs_new_eq:NN \zhnum_reset_config: \zhnum_parse_config:
+\else:
+  \cs_new_protected_nopar:Npn \zhnum_set_catcode:
+    { \bool_if:NT \l__zhnum_active_char_bool { \zhnum_set_active: } }
+  \cs_new_protected_nopar:Npn \zhnum_set_active:
+    {
+      \str_case:onTF { \l__zhnum_encoding_tl }
+        {
+          { gbk }  { \int_set:Nn \l__zhnum_byte_min_int { "81 } }
+          { big5 } { \int_set:Nn \l__zhnum_byte_min_int { "A1 } }
+        }
+        { \int_set:Nn \l__zhnum_byte_max_int { "FE } }
+        {
+          \int_set:Nn \l__zhnum_byte_min_int { "E0 }
+          \int_set:Nn \l__zhnum_byte_max_int { "EF }
+        }
+      \int_step_function:nnnN
+        { \l__zhnum_byte_min_int } { \c_one }
+        { \l__zhnum_byte_max_int } \char_set_catcode_active:n
+    }
+  \int_new:N \l__zhnum_byte_min_int
+  \int_new:N \l__zhnum_byte_max_int
+  \cs_new_protected_nopar:Npn \zhnum_set_cfg_name:Nn #1#2
+    {
+      \tl_set:Nx \l__zhnum_encoding_tl {#2}
+      \tl_set:Nx #1
+        {
+          \tl_to_str:N \l__zhnum_encoding_tl
+          \bool_if:NT \l__zhnum_active_char_bool
+            { \tl_to_str:n { _active } }
+        }
+    }
+  \cs_new_protected_nopar:Npn \zhnum_reset_config:
+    { \zhnum_load_cfg:o { \l__zhnum_encoding_tl } }
+  \bool_new:N \l__zhnum_active_char_bool
+  \bool_set_true:N \l__zhnum_active_char_bool
+\fi:
 \keys_define:nn { zhnum / options }
   {
-    encoding      .choice_code:n =
+    encoding         .choices:nn =
+      { UTF8 , GBK , Big5 }
       {
-        \tl_gset:Nx \c_zhnum_encoding_tl
-          { \exp_args:NV \tl_expandable_lowercase:n \l_keys_choice_tl }
-        \zhnum_load_cfg:n { \c_zhnum_encoding_tl }
+        \tl_set:Nx \l__zhnum_encoding_tl
+          { \exp_args:No \tl_expandable_lowercase:n { \l_keys_choice_tl } }
+        \zhnum_load_cfg:o { \l__zhnum_encoding_tl }
       } ,
-    encoding .generate_choices:n = { UTF8 , GBK , Big5 } ,
     encoding          .default:n = { GBK } ,
     encoding / Bg5       .meta:n = { encoding = Big5 } ,
     encoding / unknown   .code:n =
-      { \msg_error:nnx { zhnumber } { encoding-invalid } { \l_keys_value_tl } } ,
+      { \msg_error:nnn { zhnumber } { encoding-invalid } {#1} } ,
     style .multichoice: ,
     style / Normal       .code:n =
       {
-        \bool_set_false:N \l_zhnum_ancient_bool
-        \bool_set_true:N  \l_zhnum_normal_bool
+        \bool_set_false:N \l__zhnum_ancient_bool
+        \bool_set_true:N  \l__zhnum_normal_bool
       } ,
     style / Financial    .code:n =
       {
-        \bool_set_false:N \l_zhnum_ancient_bool
-        \bool_set_false:N \l_zhnum_normal_bool
+        \bool_set_false:N \l__zhnum_ancient_bool
+        \bool_set_false:N \l__zhnum_normal_bool
       } ,
     style / Ancient      .code:n =
       {
-        \bool_set_true:N \l_zhnum_ancient_bool
-        \bool_set_true:N \l_zhnum_normal_bool
+        \bool_set_true:N \l__zhnum_ancient_bool
+        \bool_set_true:N \l__zhnum_normal_bool
       } ,
-    style / Simplified   .code:n = { \bool_set_true:N  \l_zhnum_simp_bool } ,
-    style / Traditional  .code:n = { \bool_set_false:N \l_zhnum_simp_bool } ,
+    style / Simplified   .code:n = { \bool_set_true:N  \l__zhnum_simp_bool } ,
+    style / Traditional  .code:n = { \bool_set_false:N \l__zhnum_simp_bool } ,
     style             .default:n = { Normal , Simplified } ,
-    null             .bool_set:N = \l_zhnum_null_bool ,
+    null             .bool_set:N = \l__zhnum_null_bool ,
     time .choice: ,
-    time / Chinese       .code:n = { \bool_set_true:N \l_zhnum_time_bool } ,
-    time / Arabic        .code:n = { \bool_set_false:N  \l_zhnum_time_bool } ,
+    time / Chinese       .code:n = { \bool_set_true:N \l__zhnum_time_bool } ,
+    time / Arabic        .code:n = { \bool_set_false:N  \l__zhnum_time_bool } ,
     time              .default:n = { Arabic } ,
-    reset                .code:n = { \zhnum_load_cfg:n { \c_zhnum_encoding_tl } } ,
-  }
-\msg_new:nnn { zhnumber } { encoding-invalid }
-  {
-    The~encoding~'#1'~is~invalid,~please~check~it~over.\\\\
-    Available~encoding~are~'UTF8',~'GBK'~and~'Big5'.\\
+    reset                .code:n = { \zhnum_reset_config: } ,
+    activechar       .bool_set:N = \l__zhnum_active_char_bool ,
   }
+\tl_new:N \l__zhnum_encoding_tl
+\msg_new:nnnn { zhnumber } { encoding-invalid }
+  { The~encoding~`#1'~is~invalid. }
+  { Available~encoding~are~`UTF8',~`GBK'~and~`Big5'. }
 \NewDocumentCommand \zhnumsetup { m }
   {
     \keys_set:nn { zhnum / options } {#1}
@@ -579,19 +820,12 @@
   }
 \keys_set:nn { zhnum / options } { style , time }
 \ProcessKeysOptions { zhnum / options }
-\ExplSyntaxOn
-\tl_if_exist:NF \c_zhnum_encoding_tl
+\tl_if_empty:NT \l__zhnum_encoding_tl
   {
-    \exp_args:Nnx \keys_set:nn { zhnum / options }
-      {
-        encoding =
-          {
-            \bool_if:nTF { \xetex_if_engine_p: || \luatex_if_engine_p: }
-              { UTF8 } { GBK }
-          }
-      }
+    \zhnum_if_unicode_engine:TF
+      { \keys_set:nn { zhnum / options } { encoding = UTF8 } }
+      { \keys_set:nn { zhnum / options } { encoding = GBK } }
   }
-\ExplSyntaxOff
 %% 
 %%    This package consists of the file  zhnumber.dtx,
 %%                 and the derived files zhnumber.pdf,
-- 
cgit v1.2.3

