% --------------------------------------------------------------------------
% the CHEMNUM package
%
%   a comprehensive approach for the numbering of chemical compounds
%
% --------------------------------------------------------------------------
% Clemens Niederberger
% --------------------------------------------------------------------------
% https://github.org/cgnieder/chemnum/
% contact@mychemistry.eu
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
% Copyright 2011--2021 Clemens Niederberger
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008/05/04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
\RequirePackage{expl3,xparse,l3keys2e}

\ExplSyntaxOn
\tl_const:Nn \c_chemnum_date_tl {2021/01/21}
\tl_const:Nn \c_chemnum_version_number_tl {1.3}
\tl_const:Nn \c_chemnum_version_suffix_tl {a}
\tl_const:Nx \c_chemnum_version_tl
  { \c_chemnum_version_number_tl \c_chemnum_version_suffix_tl }
\tl_const:Nn \c_chemnum_info_tl
  {a~ comprehensive~ approach~ for~ the~ numbering~ of~ chemical~ compounds}

% ----------------------------------------------------------------------------
% provide the package:
\ProvidesExplPackage
  {chemnum}
  {\c_chemnum_date_tl}
  {\c_chemnum_version_tl}
  {\c_chemnum_info_tl \c_space_tl (CN)}

% ----------------------------------------------------------------------------
% required packages:
% language support:
\RequirePackage{translations}

% greek alphabet for the labels matching to chemmacros' selection:
\RequirePackage{chemgreek}
\RequirePackage{psfrag}

% ----------------------------------------------------------------------------
% messages:
\msg_new:nnn {chemnum} {missing-label}
  {
    The~ key~ `#1' \tl_if_blank:nF {#2} {~ of~`#2'} ~ has~ no~ label~
    associated~ \msg_line_context:
  }

\msg_new:nnn {chemnum} {erroneous-argument-combination}
  {
    Apparently~ you've~ used~ both~ the~ `*'~ and~ the~ `+'~
    argument.~ This~ does~ not~ make~ sense.~ I'm~ doing~
    nothing~ \msg_line_context:
  }

\msg_new:nnn {chemnum} {unknown-counter-format}
  {
    I~ do~ not~ know~ the~ counter~ format~ `#1'.~ I'll~ use~ `arabic'~
    instead~ \msg_line_context:
  }

\msg_new:nnn {chemnum} {compound-not-initiated}
  { The~ compound~ `#1'~ has~ not~ been~ initiated~ \msg_line_context: }

\msg_new:nnn {chemnum} {subcompound-not-initiated}
  {
    The~ compound~ `#1\l_chemnum_compound_separator_tl #2'~ has~ not~ been~
    initiated~ \msg_line_context:
  }

\msg_new:nnn {chemnum} {log-compound-silent}
  {
    ................................................. \\
    . ~ \msg_info_text:n {chemnum}: ~
      defined~ new~ compound~ `#1'~with~output~
      `\chemnum_expandable_get_compound_property:nn {#1}
        {counter-representation}' . \\
    .................................................
  }

\msg_new:nnn {chemnum} {log-compound-verbose}
  {
    ................................................. \\
    . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ compound: \\
    . \c_space_tl \c_space_tl \c_space_tl
    ID ~=~ #1 \\
    . \c_space_tl \c_space_tl \c_space_tl
    internal~ number ~=~
    \chemnum_expandable_get_compound_property:nn {#1} {number} \\
    . \c_space_tl \c_space_tl \c_space_tl
    label ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {counter-representation} \\
    . \c_space_tl \c_space_tl \c_space_tl
    pre~ label~ code ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {pre-label-code} \\
    . \c_space_tl \c_space_tl \c_space_tl
    post~ label~ code ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {post-label-code} \\
    . \c_space_tl \c_space_tl \c_space_tl
    pre~ main~ label~ code ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {pre-main-label-code} \\
    . \c_space_tl \c_space_tl \c_space_tl
    post~ main~ label~ code ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {post-main-label-code} \\
    . \c_space_tl \c_space_tl \c_space_tl
    format ~=~
    \chemnum_expandable_get_compound_property:nn {#1}
      {label-format} \\
    .................................................
  }

\msg_new:nnn {chemnum} {log-subcompound-silent}
  {
    ................................................. \\
    . ~ \msg_info_text:n {chemnum}: ~
      defined~ new~ subcompound~ `#2'~ with~ output~
      \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
        {counter-representation} \\
    . ~ belonging~ to~ the~ main~ compound~ `#1'. \\
    .................................................
  }

\msg_new:nnn {chemnum} {log-subcompound-verbose}
  {
    ................................................. \\
    . ~ \msg_info_text:n {chemnum}: ~ defined~ new~ subcompound: \\
    . \c_space_tl \c_space_tl \c_space_tl
    ID ~=~ #2 \\
    . \c_space_tl \c_space_tl \c_space_tl
    main~ compound~ ID ~=~
    \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
      {main-compound} \\
    . \c_space_tl \c_space_tl \c_space_tl
    internal~ number ~=~
    \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {number} \\
    . \c_space_tl \c_space_tl \c_space_tl
    label ~=~
    \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
      {counter-representation} \\
    .................................................
  }

\msg_new:nnn {chemnum} {deprecated-command}
  {
    The~ command~ `\token_to_str:N #1'~ \msg_line_context: \c_space_tl is~
    deprecated.~ Use~ `\token_to_str:N #2'~ instead.~ `\token_to_str:N #1'~
    may~ be~ removed~ in~ future~ versions.
  }

\msg_new:nnn {chemnum} {property-undefined}
  {
    The~ property~ `#2'~ for~ compound~ `#1'~ is~ undefined~ and~ thus~
    cannot~ be~ set~ \msg_line_context:
  }

% ----------------------------------------------------------------------------
% deprecated command names:
% #1: old name
% #2: new name
\cs_new_protected:Npn \chemnum_deprecated_command:NN #1#2
  {
    \cs_new_protected:Npn #1
      {
        \msg_warning:nnnn {chemnum} {deprecated-command} {#1} {#2}
        #2
      }
  }

\chemnum_deprecated_command:NN \cmpdsetup \setchemnum
\chemnum_deprecated_command:NN \cmpdinit \initcmpd
\chemnum_deprecated_command:NN \cmpdref \replacecmpd
\chemnum_deprecated_command:NN \cmpdreset \resetcmpd

% ----------------------------------------------------------------------------
% variants of kernel functions:
\cs_generate_variant:Nn \prop_gput:Nnn {Nnx,cnx,cnV}
\cs_generate_variant:Nn \prop_put:Nnn {NV,NVV,NVx}
\cs_generate_variant:Nn \prop_if_in:NnTF {NV}
\cs_generate_variant:Nn \quark_if_no_value:nTF {V}
\cs_generate_variant:Nn \quark_if_no_value:nF {V}
\cs_generate_variant:Nn \seq_set_split:Nnn {NV,NVV}
\cs_generate_variant:Nn \seq_use:Nnnn {NVVV}
\cs_generate_variant:Nn \tl_if_eq:nnF {Vx}
\cs_generate_variant:Nn \tl_if_in:nnTF {VV}

% ----------------------------------------------------------------------------
% temporary variables:
\tl_new:N \l__chemnum_tmpa_tl
\tl_new:N \l__chemnum_tmpb_tl

\seq_new:N \l__chemnum_tmpa_seq
\seq_new:N \l__chemnum_tmpb_seq
\seq_new:N \l__chemnum_tmpc_seq
\seq_new:N \l__chemnum_tmpd_seq
\seq_new:N \l__chemnum_tmpe_seq

\int_new:N \l__chemnum_tmpa_int
\int_new:N \l__chemnum_tmpb_int
\int_new:N \l__chemnum_tmpc_int

\str_new:N \l__chemnum_tmpa_str

% ----------------------------------------------------------------------------
% variables:
\prop_new:N \l__chemnum_label_formats_prop

% the main label counter:
% not very expl3 like but allows `cmpdmain' to be added to the \cl@<ounter>
% list, i.e., it can e.g. be reset for every chapter:
\newcounter{cmpdmain}
% counter for internal reference if needed. Will be a unique number in order
% of declaration:
\int_new:N \g__chemnum_main_int
\int_new:N \l__chemnum_compound_replace_int

\seq_new:N \g_chemnum_initiated_compounds_seq
\seq_new:N \g__chemnum_defined_compounds_seq
\seq_new:N \g__chemnum_compound_defined_subcompounds_seq

\tl_const:Nn \c_chemnum_nothing_here_tl {??}
\tl_new:N  \l__chemnum_label_format_tl
\tl_set:Nn \l__chemnum_label_format_tl {\bfseries}
\tl_new:N  \l__chemnum_local_label_format_tl
\tl_set_eq:NN \l__chemnum_local_label_format_tl \l__chemnum_label_format_tl
\tl_new:N  \l__chemnum_default_counter_representation_tl
\tl_set:Nn \l__chemnum_default_counter_representation_tl {arabic}
\tl_new:N  \l__chemnum_default_subcounter_representation_tl
\tl_set:Nn \l__chemnum_default_subcounter_representation_tl {alph}
\tl_new:N  \l__chemnum_pre_counter_default_tl
\tl_new:N  \l__chemnum_post_counter_default_tl
\tl_new:N  \l__chemnum_pre_label_default_tl
\tl_new:N  \l__chemnum_post_label_default_tl
\tl_new:N  \l__chemnum_pre_main_label_default_tl
\tl_new:N  \l__chemnum_post_main_label_default_tl
\tl_new:N  \l__chemnum_main_separator_tl
\tl_set:Nn \l__chemnum_main_separator_tl {,}
\tl_new:N  \l__chemnum_sub_separator_tl
\tl_set:Nn \l__chemnum_sub_separator_tl {,}
\tl_new:N  \l_chemnum_compound_separator_tl
\tl_set:Nn \l_chemnum_compound_separator_tl {.}

\tl_new:N  \l__chemnum_sep_list_two_tl
\tl_set:Nn \l__chemnum_sep_list_two_tl { \GetTranslation {chemnum-sep-two} }
\tl_new:N  \l__chemnum_sep_list_more_tl
\tl_set:Nn \l__chemnum_sep_list_more_tl {,~}
\tl_new:N  \l__chemnum_sep_list_last_two_tl
\tl_set:Nn \l__chemnum_sep_list_last_two_tl { \GetTranslation {chemnum-sep-last-two} }

\tl_new:N  \l__chemnum_sep_sublist_two_tl
\tl_set:Nn \l__chemnum_sep_sublist_two_tl {,}
\tl_new:N  \l__chemnum_sep_sublist_more_tl
\tl_set:Nn \l__chemnum_sep_sublist_more_tl {,}
\tl_new:N  \l__chemnum_sep_sublist_last_two_tl
\tl_set:Nn \l__chemnum_sep_sublist_last_two_tl {,}
\tl_new:N  \l__chemnum_sep_sublist_range_tl
\tl_set:Nn \l__chemnum_sep_sublist_range_tl {--}

\tl_new:N  \l__chemnum_compound_replace_tl
\tl_new:N  \l__chemnum_compound_replace_format_tl
\tl_new:N  \l__chemnum_compound_replace_local_format_tl
\tl_set:Nn \l__chemnum_compound_replace_format_tl {\sffamily}
\tl_new:N  \l__chemnum_compound_replace_tag_tl
\tl_set:Nn \l__chemnum_compound_replace_tag_tl {TMP}
\tl_new:N  \l__chemnum_psfrag_texpos_tl
\tl_new:N  \l__chemnum_psfrag_local_texpos_tl
\tl_set:Nn \l__chemnum_psfrag_texpos_tl {b}
\tl_new:N  \l__chemnum_psfrag_pspos_tl
\tl_new:N  \l__chemnum_psfrag_local_pspos_tl
\tl_set:Nn \l__chemnum_psfrag_pspos_tl {b}

\bool_new:N \l__chemnum_compound_local_bool
\bool_new:N \g__chemnum_initiate_bool
\bool_new:N \g__chemnum_initiate_strict_bool
\bool_new:N \g__chemnum_initiate_sub_bool
\bool_new:N \l__chemnum_log_bool
\bool_set_true:N \l__chemnum_log_bool
\bool_new:N \l__chemnum_log_verbose_bool
\bool_new:N \l__chemnum_compress_subcompounds_bool
\bool_set_true:N \l__chemnum_compress_subcompounds_bool
\bool_new:N \l__chemnum_merge_list_bool
\bool_new:N \l__chemnum_sub_only_bool
\bool_new:N \l__chemnum_sub_all_bool
\bool_new:N \l__chemnum_show_def_bool
\bool_new:N \l__chemnum_show_ref_bool
\bool_new:N \l__chemnum_compound_replace_auto_bool
\bool_set_true:N \l__chemnum_compound_replace_auto_bool
\bool_new:N \l__chemnum_compound_replace_auto_this_bool
\bool_set_true:N \l__chemnum_compound_replace_auto_this_bool
\bool_new:N \l__chemnum_replace_local_bool
\bool_new:N \l__chemnum_hyperlinks_bool

% ----------------------------------------------------------------------------
% label formats:

% #1: name
% #2: function with 1 n-type argument that takes an integer
\cs_new_protected:Npn \chemnum_add_label_format:nn #1#2
  {
    \cs_if_exist:cTF { __chemnum_#1_label_format:n }
      { \cs_set:cpn { __chemnum_#1_label_format:n } ##1 { #2 {##1} } }
      { \cs_new:cpn { __chemnum_#1_label_format:n } ##1 { #2 {##1} } }
    \prop_put:Nnx \l__chemnum_label_formats_prop {#1}
      { \exp_not:c { __chemnum_#1_label_format:n } }
  }

% a user level command to add new formats
\NewDocumentCommand \newcmpdcounterformat {mm}
  { \chemnum_add_label_format:nn {#1} {#2} }

\newcmpdcounterformat {arabic} { \int_to_arabic:n }
\newcmpdcounterformat {alph}   { \int_to_alph:n }
\newcmpdcounterformat {Alph}   { \int_to_Alph:n }
\newcmpdcounterformat {roman}  { \int_to_roman:n }
\newcmpdcounterformat {Roman}  { \int_to_Roman:n }
\newcmpdcounterformat {greek}  { \chemgreek_int_to_greek:n }
\newcmpdcounterformat {Greek}  { \chemgreek_int_to_Greek:n }

% ----------------------------------------------------------------------------
%%% options
% options assigned to group `compound' are only setable with the \cmpd command
% except they're _also_ asigned to the `general' group; likewise options that
% are assigned to the group `general' can only be set with \setchemnum except
% they're also assigned to the `compound' group.
\keys_define:nn {chemnum}
  {
    local .bool_set:N = \l__chemnum_compound_local_bool ,
    local .groups:n = {compound} ,
    % counter:
    counter-within .code:n = \@addtoreset{cmpdmain}{#1} ,
    counter-within .groups:n = {general} ,
    counter-format .code:n =
      \prop_if_in:NnTF \l__chemnum_label_formats_prop {#1}
        {
          \tl_set:Nn
            \l__chemnum_default_counter_representation_tl
            {#1}
        }
        {
          \msg_warning:nnn {chemnum} {unknown-counter-format} {#1}
          \tl_set:Nn
            \l__chemnum_default_counter_representation_tl
            {arabic}
        } ,
    counter-format .groups:n = {compound,general} ,
    sub-counter-format .code:n =
      \prop_if_in:NnTF \l__chemnum_label_formats_prop {#1}
        {
          \tl_set:Nn
            \l__chemnum_default_subcounter_representation_tl
            {#1}
        }
        {
          \msg_warning:nnn {chemnum} {unknown-counter-format} {#1}
          \tl_set:Nn
            \l__chemnum_default_subcounter_representation_tl
            {arabic}
        } ,
    sub-counter-format .groups:n = {compound,general} ,
    % label:
    pre-label-code .tl_set:N = \l__chemnum_pre_label_default_tl ,
    pre-label-code .groups:n = {compound,general} ,
    post-label-code .tl_set:N = \l__chemnum_post_label_default_tl ,
    post-label-code .groups:n = {compound,general} ,
    pre-main-label-code .tl_set:N = \l__chemnum_pre_main_label_default_tl ,
    pre-main-label-code .groups:n = {compound,general} ,
    post-main-label-code .tl_set:N = \l__chemnum_post_main_label_default_tl ,
    post-main-label-code .groups:n = {compound,general} ,
    main-sub-sep .tl_set:N = \l_chemnum_compound_separator_tl ,
    main-sub-sep .groups:n = {general,list} ,
    list-label-sep .tl_set:N = \l__chemnum_main_separator_tl ,
    list-label-sep .groups:n = {general,list} ,
    sub-list-label-sep .tl_set:N = \l__chemnum_sub_separator_tl ,
    sub-list-label-sep .groups:n = {general,list} ,
    format .code:n =
      \tl_set:Nn \l__chemnum_local_label_format_tl {#1}
      \bool_if:NF \l__chemnum_compound_local_bool
        { \tl_set:Nn \l__chemnum_label_format_tl {#1} } ,
    format .groups:n = {compound,general} ,
    sub-only .bool_set:N = \l__chemnum_sub_only_bool ,
    sub-only .groups:n = {compound,sub-only} ,
    sub-all .bool_set:N = \l__chemnum_sub_all_bool ,
    sub-all .groups:n = {compound} ,
    compress .bool_set:N =
      \l__chemnum_compress_subcompounds_bool ,
    compress .groups:n = {compound,general} ,
    merge .bool_set:N =
      \l__chemnum_merge_list_bool ,
    merge .groups:n = {general,list} ,
    % initiation:
    init .choice: ,
    init / true .code:n =
      \bool_set_true:N \g__chemnum_initiate_bool
      \bool_set_true:N \g__chemnum_initiate_sub_bool
      \bool_set_false:N \g__chemnum_initiate_strict_bool ,
    init / main .code:n =
      \bool_set_true:N \g__chemnum_initiate_bool
      \bool_set_false:N \g__chemnum_initiate_sub_bool
      \bool_set_false:N \g__chemnum_initiate_strict_bool ,
    init / false .code:n =
      \bool_set_false:N \g__chemnum_initiate_bool
      \bool_set_false:N \g__chemnum_initiate_sub_bool
      \bool_set_false:N \g__chemnum_initiate_strict_bool ,
    init / strict .code:n =
      \bool_set_true:N \g__chemnum_initiate_bool
      \bool_set_true:N \g__chemnum_initiate_sub_bool
      \bool_set_true:N \g__chemnum_initiate_strict_bool ,
    init / main-strict .code:n =
      \bool_set_true:N \g__chemnum_initiate_bool
      \bool_set_false:N \g__chemnum_initiate_sub_bool
      \bool_set_true:N \g__chemnum_initiate_strict_bool ,
    init .default:n = true ,
    init .groups:n = {general} ,
    % list processing:
    list-sep-two .tl_set:N = \l__chemnum_sep_list_two_tl ,
    list-sep-two .groups:n = {general,list} ,
    list-sep-more .tl_set:N = \l__chemnum_sep_list_more_tl ,
    list-sep-more .groups:n = {general,list} ,
    list-sep-last-two .tl_set:N = \l__chemnum_sep_list_last_two_tl ,
    list-sep-last-two .groups:n = {general,list} ,
    sub-list-sep-two .tl_set:N = \l__chemnum_sep_sublist_two_tl ,
    sub-list-sep-two .groups:n = {compound,general} ,
    sub-list-sep-more .tl_set:N = \l__chemnum_sep_sublist_more_tl ,
    sub-list-sep-more .groups:n = {compound,general} ,
    sub-list-sep-last-two .tl_set:N = \l__chemnum_sep_sublist_last_two_tl ,
    sub-list-sep-last-two .groups:n = {compound,general} ,
    sub-list-sep-range .tl_set:N = \l__chemnum_sep_sublist_range_tl ,
    sub-list-sep-range .groups:n = {compound,general} ,
    % logging and other information:
    log .choice: ,
    log / true .code:n =
      \bool_set_true:N \l__chemnum_log_bool
      \bool_set_false:N \l__chemnum_log_verbose_bool ,
    log / silent .code:n =
      \bool_set_true:N \l__chemnum_log_bool
      \bool_set_false:N \l__chemnum_log_verbose_bool ,
    log / false .code:n =
      \bool_set_false:N \l__chemnum_log_bool
      \bool_set_false:N \l__chemnum_log_verbose_bool ,
    log / verbose .code:n =
      \bool_set_true:N \l__chemnum_log_bool
      \bool_set_true:N \l__chemnum_log_verbose_bool ,
    log .default:n = true ,
    log .groups:n = {general} ,
    show-keys .choice: ,
    show-keys / true .code:n =
      \bool_set_true:N \l__chemnum_show_def_bool
      \bool_set_true:N \l__chemnum_show_ref_bool ,
    show-keys / false .code:n =
      \bool_set_false:N \l__chemnum_show_def_bool
      \bool_set_false:N \l__chemnum_show_ref_bool ,
    show-keys / def .code:n =
      \bool_set_true:N \l__chemnum_show_def_bool
      \bool_set_false:N \l__chemnum_show_ref_bool ,
    show-keys / ref .code:n =
      \bool_set_false:N \l__chemnum_show_def_bool
      \bool_set_true:N \l__chemnum_show_ref_bool ,
    show-keys .default:n = true ,
    show-keys .groups:n = {general} ,
    replace .bool_set:N = \l__chemnum_replace_local_bool ,
    replace .groups:n = {replace} ,
    replace-auto .bool_set:N = \l__chemnum_compound_replace_auto_bool ,
    replace-tag .tl_set:N = \l__chemnum_compound_replace_tag_tl ,
    replace-tag .groups:n = {general} ,
    tag .code:n =
      \tl_set:Nn \l__chemnum_compound_replace_tag_tl {#1}
      \bool_set_false:N \l__chemnum_compound_replace_auto_this_bool ,
    tag .groups:n = {replace} ,
    replace-tag-nr .code:n   =
      \int_set:Nn \l__chemnum_compound_replace_int { (#1) - 1 } ,
    replace-tag-nr .groups:n = {general} ,
    replace-tag-nr .initial:n = {1} ,
    replace-style .tl_set:N = \l__chemnum_compound_replace_format_tl ,
    replace-style .groups:n = {general} ,
    style .code:n =
      \tl_set:Nn \l__chemnum_compound_replace_local_format_tl {#1}
      \bool_set_true:N \l__chemnum_replace_local_bool ,
    style .groups:n = {replace} ,
    replace-pos .code:n = \__chemnum_set_psfrag_pos:nn #1 ,
    replace-pos .groups:n = {general} ,
    pos .code:n =
      \bool_set_true:N \l__chemnum_replace_local_bool
      \__chemnum_set_psfrag_local_pos:nn #1 ,
    pos .groups:n = {replace} ,
    hyperlinks .bool_set:N = \l__chemnum_hyperlinks_bool ,
    hyperlinks .groups:n = {general} ,
  }

% ----------------------------------------------------------------------------
% #1: int variable that holds the value
% #2: the chosen format
% this command is expandable
\cs_new:Npn \__chemnum_label_format:Nn #1#2
  {
    \prop_if_in:NnTF \l__chemnum_label_formats_prop {#2}
      { \use:c { __chemnum_#2_label_format:n } {#1} }
      { \__chemnum_arabic_label_format:n {#1} }
  }
\cs_generate_variant:Nn \__chemnum_label_format:Nn {NV,cV}

% ----------------------------------------------------------------------------
% auxiliary file -- we'll use the .aux file
% first let's add dummy definitions so we can hopefully avoid error messages
% if the `chemnum' package is removed from the preamble
\hook_gput_code:nnn {begindocument} {chemnum}
  {
    \legacy_if:nT {@filesw}
      {
        \iow_now:Nn \@auxout
          {
            \providecommand\chemnum@cmpd[8]{} ^^J
            \providecommand\chemnum@subcmpd[4]{} ^^J
            \providecommand\chemnum@check{}
          }
      }
  }

% we use this one to trigger a LaTeX rerun warning -- to be precise the
% ``Label(s) may have changed'' warning:
\cs_new_protected:Npn \__chemnum_rerun:
  {
    \hook_gput_code:nnn {enddocument} {code}
      { \def \chemnum@check { \@tempswatrue } }
  }

% add the rerun check at the end:
\hook_gput_code:nnn {enddocument} {code}
  {
    \legacy_if:nT {@filesw}
      { \iow_now:Nn \@auxout { \chemnum@check } }
  }

% ----------------------------------------------------------------------------
% initiating new compounds
% - property list that holds
% - ID
% - counter value
% - counter represetation
% - pre-counter-code
% - post-counter-code
% - pre-label-code
% - post-label-code
% - formatting code
% - add to list of initiated compounds

\cs_new_protected:Npn \chemnum_initiate_compound:n #1
  {
    \chemnum_compound_if_initiated:nF {#1}
      { \seq_gput_right:Nn \g_chemnum_initiated_compounds_seq {#1} }
  }

% #1: ID
\cs_new_protected:Npn \chemnum_define_compound:n #1
  {
    \chemnum_initialize_compound:n {#1}
    \chemnum_compound_declare_properties:nn {#1}
      {
        ID ,
        number ,
        counter-representation ,
        pre-label-code ,
        post-label-code ,
        pre-main-label-code ,
        post-main-label-code ,
        label-format
      }
    \chemnum_compound_set_property:nnn {#1} {ID} {#1}
    \chemnum_compound_set_property:nnx {#1} {number}
      { \int_use:N \c@cmpdmain }
    \chemnum_compound_set_property:nnx {#1} {counter-representation}
      {
        \exp_not:V \l__chemnum_pre_counter_default_tl
        \__chemnum_label_format:NV
          \c@cmpdmain % \g__chemnum_main_int
          \l__chemnum_default_counter_representation_tl
        \exp_not:V \l__chemnum_post_counter_default_tl
      }
    \chemnum_compound_set_property:nnV {#1} {pre-label-code}
      \l__chemnum_pre_label_default_tl
    \chemnum_compound_set_property:nnV {#1} {post-label-code}
      \l__chemnum_post_label_default_tl
    \chemnum_compound_set_property:nnV {#1} {pre-main-label-code}
      \l__chemnum_pre_main_label_default_tl
    \chemnum_compound_set_property:nnV {#1} {post-main-label-code}
      \l__chemnum_post_main_label_default_tl
    \chemnum_compound_set_property:nnV {#1} {label-format}
      \l__chemnum_label_format_tl
  }

\cs_new_protected:Npn \chemnum_finalize_compound:n #1
  {
    \chemnum_compound_update_properties:n {#1}
    \chemnum_save_compound_to_auxfile:n {#1}
    \chemnum_log_main:n {#1}
  }

% TODO: keep? and if: what should it set?
\cs_new_protected:Npn \chemnum_set_compound:n #1
  {
    % those should be done: however, they overwrite existing options in any
    % case... this would overwrite options that really should stay set.
    
    % \chemnum_compound_set_property:nnV {#1} {pre-label-code}
    %   \l__chemnum_pre_label_default_tl
    % \chemnum_compound_set_property:nnV {#1} {post-label-code}
    %   \l__chemnum_post_label_default_tl
    % \chemnum_compound_set_property:nnV {#1} {post-main-label-code}
    %   \l__chemnum_post_main_label_default_tl
    % \chemnum_compound_set_property:nnV {#1} {label-format}
    %   \l__chemnum_label_format_tl
    % \chemnum_save_compound_to_auxfile:n {#1}
    % \chemnum_compound_update_properties:n {#1}
  }

% we can use this command as a hook through redefinition:
\cs_new_protected:Npn \chemnum_initialize_compound:n #1
  { \chemnum_init_raw_compound:n {#1} }

\cs_new_protected:Npn \chemnum_init_raw_compound:n #1
  {
    \seq_if_in:NnF \g__chemnum_defined_compounds_seq {#1}
      {
        \seq_gput_right:Nn \g__chemnum_defined_compounds_seq {#1}
        \int_gincr:N \g__chemnum_main_int
        \stepcounter{cmpdmain}
      }
    \seq_if_exist:cF {g__chemnum_#1_initiated_subcompounds_seq}
      { \seq_new:c {g__chemnum_#1_initiated_subcompounds_seq} }
  }

% #1: main ID
% #2: sub ID
\cs_new_protected:Npn \chemnum_define_subcompound:nn #1#2
  {
    \chemnum_initialize_subcompound:nn {#1} {#2}
    \chemnum_subcompound_declare_properties:nnn {#1} {#2}
      {
        ID ,
        main-compound ,
        number ,
        counter-representation
      }
    \chemnum_subcompound_set_property:nnnn {#1} {#2} {ID} {#2}
    \chemnum_subcompound_set_property:nnnn {#1} {#2} {main-compound} {#1}
    \chemnum_subcompound_set_property:nnnx {#1} {#2} {number}
      { \int_use:c {g__chemnum_compound_#1_subcompound_int} }
    \chemnum_subcompound_set_property:nnnx {#1} {#2} {counter-representation}
      {
        \__chemnum_label_format:cV
          {g__chemnum_compound_#1_subcompound_int}
          \l__chemnum_default_subcounter_representation_tl
      }
  }

\cs_new_protected:Npn \chemnum_finalize_subcompound:nn #1#2
  {
    \chemnum_save_subcompound_to_auxfile:nn {#1} {#2}
    \chemnum_subcompound_update_properties:nn {#1} {#2}
    \chemnum_log_sub:nn {#1} {#2}
  }

\cs_new_protected:Npn \chemnum_initialize_subcompound:nn #1#2
  {
    \int_if_exist:cF {g__chemnum_compound_#1_subcompound_int}
      { \int_new:c {g__chemnum_compound_#1_subcompound_int} }
    \int_gincr:c {g__chemnum_compound_#1_subcompound_int}
    \seq_if_exist:cF {g__chemnum_compound_#1_subcompounds_seq}
      { \seq_new:c {g__chemnum_compound_#1_subcompounds_seq} }
    \prop_if_exist:cF {g__chemnum_compound_#1_subcompounds_prop}
      { \prop_new:c {g__chemnum_compound_#1_subcompounds_prop} }
    \seq_if_in:cnF {g__chemnum_compound_#1_subcompounds_seq} {#2}
      { \seq_gput_right:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} }
    \seq_gput_right:Nn \g__chemnum_compound_defined_subcompounds_seq {#1#2}
    \prop_gput:cnx {g__chemnum_compound_#1_subcompounds_prop} {#2}
      {
        \int_use:c {g__chemnum_compound_#1_subcompound_int} :
        \__chemnum_label_format:cV
          {g__chemnum_compound_#1_subcompound_int}
          \l__chemnum_default_subcounter_representation_tl
      }
  }

% #1: main ID
\prg_new_conditional:Npnn \chemnum_if_subcompounds:n #1 {T,F,TF}
  {
    \seq_if_exist:cTF {g__chemnum_compound_#1_subcompounds_seq}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1: main ID
\cs_new:Npn \chemnum_count_subcompounds:n #1
  { \int_use:c {g__chemnum_compound_#1_subcompound_int} }

% #1: main ID
% #2: index
\cs_new:Npn \chemnum_get_subcompound:nn #1#2
  { \seq_item:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} }

% ----------------------------------------------------------------------------

\cs_new:Npn \__chemnum_nothing_here:n #1
  {
    \c_chemnum_nothing_here_tl
    \msg_warning:nnn {chemnum} {missing-label} {#1}
  }

\cs_new:Npn \__chemnum_nothing_here:nn #1#2
  {
    \c_chemnum_nothing_here_tl
    \msg_warning:nnnn {chemnum} {missing-label} {#1} {#2}
  }
\cs_generate_variant:Nn \__chemnum_nothing_here:nn {x}
  
% ----------------------------------------------------------------------------
\cs_new_protected:Npn \chemnum_log_main:n #1
  {
    \bool_if:NT \l__chemnum_log_bool
      {
        \bool_if:NTF \l__chemnum_log_verbose_bool
          { \msg_log:nnn {chemnum} {log-compound-verbose} {#1} }
          { \msg_log:nnn {chemnum} {log-compound-silent} {#1} }
      }
  }

\cs_new_protected:Npn \chemnum_log_sub:nn #1#2
  {
    \bool_if:NT \l__chemnum_log_bool
      {
        \bool_if:NTF \l__chemnum_log_verbose_bool
          { \msg_log:nnnn {chemnum} {log-subcompound-verbose} {#1} {#2} }
          { \msg_log:nnnn {chemnum} {log-subcompound-silent} {#1} {#2} }
      }
  }

% ----------------------------------------------------------------------------
% #1: ID
\prg_new_protected_conditional:Npnn \chemnum_compound_if_initiated:n #1
  { T,F,TF }
  {
    \seq_if_in:NnTF \g_chemnum_initiated_compounds_seq {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1: main ID
% #2: sub ID
\prg_new_protected_conditional:Npnn \chemnum_subcompound_if_initiated:nn #1#2
  { T,F,TF }
  {
    \seq_if_in:cnTF {g__chemnum_#1_initiated_subcompounds_seq} {#2}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1: ID
\prg_new_protected_conditional:Npnn \chemnum_compound_if_defined:n #1
  { T,F,TF }
  {
    \seq_if_in:NnTF \g__chemnum_defined_compounds_seq {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1: main ID
% #2: sub ID
\prg_new_protected_conditional:Npnn \chemnum_subcompound_if_defined:nn #1#2
  { T,F,TF }
  {
    \seq_if_in:NnTF \g__chemnum_compound_defined_subcompounds_seq {#1#2}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% ----------------------------------------------------------------------------
% #1: ID
% #2: property to be defined
\cs_new_protected:Npn \chemnum_compound_declare_property:nn #1#2
  {
    \seq_if_exist:cF {g__chemnum_compound_#1_properties_seq }
      { \seq_new:c {g__chemnum_compound_#1_properties_seq} }
    \prop_if_exist:cF {g__chemnum_compound_#1_prop}
      { \prop_new:c {g__chemnum_compound_#1_prop} }
    \seq_if_in:cnF {g__chemnum_compound_#1_properties_seq} {#2}
      { \seq_gput_right:cn {g__chemnum_compound_#1_properties_seq} {#2} }
  }

% #1: ID
% #2: properties to be defined
\cs_new_protected:Npn \chemnum_compound_declare_properties:nn #1#2
  {
    \clist_map_inline:nn {#2}
      { \chemnum_compound_declare_property:nn {#1} {##1} }
  }

% #1: ID
% #2: property to be set
% #3: value of property
\cs_new_protected:Npn \chemnum_compound_set_property:nnn #1#2#3
  {
    \seq_if_in:cnTF {g__chemnum_compound_#1_properties_seq} {#2}
      { \prop_gput:cnn {g__chemnum_compound_#1_prop} {#2} {#3} }
      { \msg_error:nnn {chemnum} {property-undefined} {#1} {#2} }
  }
\cs_generate_variant:Nn \chemnum_compound_set_property:nnn {nnV,nnx}

% #1: ID
% #2: property to be updated
\cs_new_protected:Npn \chemnum_compound_update_property:nn #1#2
  {
    \seq_if_in:cnTF {g__chemnum_compound_#1_properties_seq} {#2}
      {
        \prop_get:cnN {g__chemnum_compound_#1_prop} {previous-#2}
          \l__chemnum_tmpa_tl
        \prop_get:cnN {g__chemnum_compound_#1_prop} {#2}
          \l__chemnum_tmpb_tl
        \tl_if_eq:NNF \l__chemnum_tmpb_tl \l__chemnum_tmpa_tl
          {
            \prop_gput:cnV {g__chemnum_compound_#1_prop}
              {previous-#2}
              \l__chemnum_tmpb_tl
          }
      }
      { \msg_error:nnn {chemnum} {property-undefined} {#1} {#2} }
  }

% #1: ID
\cs_new_protected:Npn \chemnum_compound_update_properties:n #1
  {
    \seq_map_inline:cn {g__chemnum_compound_#1_properties_seq}
      { \chemnum_compound_update_property:nn {#1} {##1} }
  }

% #1: main ID
% #2. sub ID
% #3: property to be defined
\cs_new_protected:Npn \chemnum_subcompound_declare_property:nnn #1#2#3
  {
    \seq_if_in:cnF {g__chemnum_compound_#1_#2_properties_seq} {#3}
      { \seq_gput_right:cn {g__chemnum_compound_#1_#2_properties_seq} {#3} }
  }

% #1: main ID
% #2. sub ID
% #3: properties to be defined
\cs_new_protected:Npn \chemnum_subcompound_declare_properties:nnn #1#2#3
  {
    \seq_if_exist:cF {g__chemnum_compound_#1_#2_properties_seq}
      { \seq_new:c {g__chemnum_compound_#1_#2_properties_seq} }
    \prop_if_exist:cF {g__chemnum_compound_#1_#2_properties_prop}
      { \prop_new:c {g__chemnum_compound_#1_#2_properties_prop} }
    \clist_map_inline:nn {#3}
      { \chemnum_subcompound_declare_property:nnn {#1} {#2} {##1} }
  }

% #1: main ID
% #2: sub ID
% #3: property to be set
% #4: value of property
\cs_new_protected:Npn \chemnum_subcompound_set_property:nnnn #1#2#3#4
  {
    \seq_if_in:cnTF {g__chemnum_compound_#1_#2_properties_seq} {#3}
      { \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop} {#3} {#4} }
      { \msg_error:nnn {chemnum} {property-undefined} {#1.#2} {#3} }
  }
\cs_generate_variant:Nn \chemnum_subcompound_set_property:nnnn {nnnV,nnnx}

% #1: main ID
% #2. sub ID
% #3: property to be updated
\cs_new_protected:Npn \chemnum_subcompound_update_property:nnn #1#2#3
  {
    \seq_if_in:cnTF {g__chemnum_compound_#1_#2_properties_seq}
      {
        \prop_get:cnN {g__chemnum_compound_#1_#2_properties_prop} {previous-#3}
          \l__chemnum_tmpa_tl
        \prop_get:cnN {g__chemnum_compound_#1_#2_properties_prop} {#3}
          \l__chemnum_tmpb_tl
        \tl_if_eq:NNF \l__chemnum_tmpb_tl \l__chemnum_tmpa_tl
          {
            \prop_gput:cnV {g__chemnum_compound_#1_#2_properties_prop}
              {previous-#3}
              \l__chemnum_tmpb_tl
          }
      }
      { \msg_error:nnn {chemnum} {property-undefined} {#1.#2} {#3} }
  }

% #1: main ID
% #2: sub ID
\cs_new_protected:Npn \chemnum_subcompound_update_properties:nn #1#2
  {
    \seq_map_inline:cn {g__chemnum_compound_#1_#2_properties_seq}
      { \chemnum_subcompound_update_property:nnn {#1} {#2} {##1} }
  }

% #1: ID
% #2: property
\cs_new_protected:Npn \chemnum_get_compound_property:nn #1#2
  { \chemnum_get_compound_property_or:nnn {#1} {#2} { } }

\cs_new_protected:Npn \chemnum_get_compound_property_or:nnn #1#2#3
  {
    \prop_get:cnNTF {g__chemnum_compound_#1_prop} {#2}
      \l__chemnum_tmpa_tl
      { \tl_use:N \l__chemnum_tmpa_tl }
      {#3}
  }

\cs_new:Npn \chemnum_expandable_get_compound_property:nn #1#2
  { \prop_item:cn {g__chemnum_compound_#1_prop} {#2} }
\cs_generate_variant:Nn \chemnum_expandable_get_compound_property:nn {V}

% #1: main ID
% #2: sub ID
% #3: property
\cs_new_protected:Npn \chemnum_get_subcompound_property:nnn #1#2#3
  { \chemnum_get_subcompound_property_or:nnnn {#1} {#2} {#3} { } }

\cs_new_protected:Npn \chemnum_get_subcompound_property_or:nnnn #1#2#3#4
  {
    \prop_get:cnNTF {g__chemnum_compound_#1_#2_properties_prop} {#3}
      \l__chemnum_tmpa_tl
      { \tl_use:N \l__chemnum_tmpa_tl }
      {#4}
  }

\cs_new:Npn \chemnum_expandable_get_subcompound_property:nnn #1#2#3
  { \prop_item:cn {g__chemnum_compound_#1_#2_properties_prop} {#3} }

% ----------------------------------------------------------------------------
\DeclareExpandableDocumentCommand \cmpdproperty { mm }
  { \chemnum_expandable_get_compound_property:nn {#1} {#2} }

\DeclareExpandableDocumentCommand \subcmpdproperty { mmm }
  { \chemnum_expandable_get_subcompound_property:nnn {#1} {#2} {#3} }

% #1: property
% #2: ID
% #3: value
\NewDocumentCommand \setcmpdproperty {mmm}
  {
    \chemnum_compound_set_property:nnn {#2} {#1} {#3}
    \chemnum_finalize_compound:n {#1}
  }

\NewDocumentCommand \setcmpdlabel {mm}
  { \setcmpdproperty {counter-representation} {#1} {#2} }

% ----------------------------------------------------------------------------
% initiating subcompounds:

% #1: main ID
% #2: sub ID
\cs_new_protected:Npn \chemnum_initiate_subcompound:nn #1#2
  {
    \chemnum_subcompound_if_initiated:nnF {#1} {#2}
      { \seq_gput_right:cn {g__chemnum_#1_initiated_subcompounds_seq} {#2} }
  }

% ----------------------------------------------------------------------------

% saving compounds to the auxilliary file:
% #1: ID
% #2: counter value
% #3: counter representation
% #4: pre label
% #5: post label
% #6: pre main label
% #7: post main label
% #8: label format
\cs_new_protected:Npn \__chemnum_write_compound_to_auxfile_x:nnnnnnnn #1#2#3#4#5#6#7#8
  {
    \hook_gput_code:nnn {begindocument} {chemnum}
      {
        \legacy_if:nT {@filesw}
          {
            \iow_now:Nx \@auxout
              { \exp_not:N \chemnum@cmpd {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} }
          }
      }
  }
\cs_generate_variant:Nn \__chemnum_write_compound_to_auxfile_x:nnnnnnnn {nnnVVVVV}

\cs_new_protected:Npn \chemnum_save_compound_to_auxfile:n #1
  {
    \__chemnum_write_compound_to_auxfile_x:nnnnnnnn {#1}
      { \chemnum_expandable_get_compound_property:nn {#1} {number} }
      { \chemnum_expandable_get_compound_property:nn {#1} {counter-representation} }
      { \chemnum_expandable_get_compound_property:nn {#1} {pre-label-code} }
      { \chemnum_expandable_get_compound_property:nn {#1} {post-label-code} }
      { \chemnum_expandable_get_compound_property:nn {#1} {pre-main-label-code} }
      { \chemnum_expandable_get_compound_property:nn {#1} {post-main-label-code}  }
      { \chemnum_expandable_get_compound_property:nn {#1} {label-format} }
  }

% #1: main ID
% #2: sub ID
% #2: counter value
% #3: counter representation
\cs_new_protected:Npn \__chemnum_write_subcompound_to_auxfile_x:nnnn #1#2#3#4
  {
    \legacy_if:nT {@filesw}
      {
        \iow_now:Nx \@auxout
          { \exp_not:N \chemnum@subcmpd {#1}{#2}{#3}{#4} }
      }
  }

\cs_new_protected:Npn \chemnum_save_subcompound_to_auxfile:nn #1#2
  {
    \__chemnum_write_subcompound_to_auxfile_x:nnnn {#1} {#2}
      {
        \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
          {number}
      }
      {
        \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
          {counter-representation}
      }
  }

% ----------------------------------------------------------------------------
% #1: ID
% #2: counter value
% #3: counter representation
% #4: pre label
% #5: post label
% #6: pre main label
% #7: post main label
% #8: label format
\cs_new_protected:Npn \chemnum@cmpd #1#2#3#4#5#6#7#8
  {
    % \chemnum_initialize_compound:n {#1} 
    \prop_if_exist:cF {g__chemnum_compound_#1_prop}
      { \prop_new:c {g__chemnum_compound_#1_prop} }
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-number} {#2}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-counter-representation} {#3}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-pre-label-code} {#4}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-post-label-code} {#5}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-pre-main-label-code} {#6}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-post-main-label-code} {#7}
    \prop_gput:cnn {g__chemnum_compound_#1_prop}
      {previous-label-format} {#8}
  }

% #1: main ID
% #2: sub ID
% #3: counter value
% #4: counter representation
\cs_new_protected:Npn \chemnum@subcmpd #1#2#3#4
  {
    \prop_if_exist:cF {g__chemnum_compound_#1_#2_properties_prop}
      { \prop_new:c {g__chemnum_compound_#1_#2_properties_prop} }
    \seq_if_exist:cF {g__chemnum_compound_#1_subcompounds_seq}
      { \seq_new:c {g__chemnum_compound_#1_subcompounds_seq} }
    \seq_if_in:cnF {g__chemnum_compound_#1_subcompounds_seq} {#2}
      { \seq_gput_right:cn {g__chemnum_compound_#1_subcompounds_seq} {#2} }
    \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop}
      {previous-number} {#3}
    \prop_gput:cnn {g__chemnum_compound_#1_#2_properties_prop}
      {previous-counter-representation} {#4}
  }

% ----------------------------------------------------------------------------
% declaring and writing compounds:

% #1: options
% #2: ID
\cs_new_protected:Npn \chemnum_declare_compound:nn #1#2
  {
    \tl_if_blank:nF {#1}
      { \keys_set_groups:nnn {chemnum} {compound} { local=true , #1 } }
    \chemnum_compound_if_initiated:nF {#2}
      {
        \bool_if:NT \g__chemnum_initiate_bool
          {
            \bool_if:NTF \g__chemnum_initiate_strict_bool
              { \msg_error:nnn {chemnum} {compound-not-initiated} {#2} }
              { \msg_warning:nnn {chemnum} {compound-not-initiated} {#2} }
          }
        \bool_if:NT \l__chemnum_show_def_bool
          { \cmpdshowdef {#2} }
        \bool_set_false:N \l__chemnum_show_ref_bool
        \chemnum_initiate_compound:n {#2}
      }
    \chemnum_compound_if_defined:nTF {#2}
      { \chemnum_set_compound:n {#2} }
      {
        \chemnum_define_compound:n {#2}
        \chemnum_finalize_compound:n {#2}
      }
  }

% #1: options
% #2: main ID
% #3: sub ID
\cs_new_protected:Npn \chemnum_declare_subcompound:nnn #1#2#3
  {
    \chemnum_subcompound_if_initiated:nnF {#2} {#3}
      {
        \bool_if:NT \g__chemnum_initiate_sub_bool
          {
            \bool_if:NTF \g__chemnum_initiate_strict_bool
              {
                \msg_error:nnnn {chemnum} {subcompound-not-initiated}
                  {#2} {#3}
              }
              {
                \msg_warning:nnnn {chemnum} {subcompound-not-initiated}
                  {#2} {#3}
              }
          }
        \bool_if:NT \l__chemnum_show_def_bool
          { \subcmpdshowdef {#2} {#3} }
        \bool_set_false:N \l__chemnum_show_ref_bool
        \chemnum_initiate_subcompound:nn {#2} {#3}
      }
    \chemnum_subcompound_if_defined:nnF {#2} {#3}
      {
        \chemnum_define_subcompound:nn {#2} {#3}
        \chemnum_finalize_subcompound:nn {#2} {#3}
      }
  }

\cs_new_protected:Npn \chemnum_compound_start:n #1
  {
    \bool_if:NF \l__chemnum_sub_only_bool
      { \chemnum_get_compound_property:nn {#1} {pre-label-code} }
  }

\cs_new:Npn \chemnum_expandable_compound_start:n #1
  {
    \bool_if:NF \l__chemnum_sub_only_bool
      {
        \chemnum_expandable_get_compound_property:nn {#1}
          {previous-pre-label-code}
      }
  }

\cs_new_protected:Npn \chemnum_compound_finish:n #1
  {
    \bool_if:NF \l__chemnum_sub_only_bool
      { \chemnum_get_compound_property:nn {#1} {post-label-code} }
  }

\cs_new:Npn \chemnum_expandable_compound_finish:n #1
  {
    \bool_if:NF \l__chemnum_sub_only_bool
      {
        \chemnum_expandable_get_compound_property:nn {#1}
          {previous-post-label-code}
      }
  }

% actively write a compound:
% #1: ID
\cs_new_protected:Npn \chemnum_compound_write:n #1
  {
    \chemnum_get_compound_property:nn {#1} {pre-main-label-code}
    \group_begin:
      \bool_if:NTF \l__chemnum_compound_local_bool
        { \l__chemnum_local_label_format_tl }
        { \chemnum_get_compound_property:nn {#1} {label-format} }
      { \chemnum_get_compound_property:nn {#1} {counter-representation} }
    \group_end:
    \chemnum_get_compound_property:nn {#1} {post-main-label-code}
  }

% actively write a subcompound:
% #1: main ID
% #2: sub ID
\cs_new_protected:Npn \chemnum_subcompound_write:nn #1#2
  {
    \group_begin:
      \bool_if:NTF \l__chemnum_compound_local_bool
        { \l__chemnum_local_label_format_tl }
        { \chemnum_get_compound_property:nn {#1} {label-format} }
      {
        \chemnum_get_subcompound_property:nnn {#1} {#2}
          {counter-representation}
      }
    \group_end:
  }

% this is only provided for use in PDF strings:
\cs_new:Npn \chemnum_expandable_compound_write:n #1
  {
    \chemnum_expandable_get_compound_property:nn {#1} {pre-main-label-code}
    \chemnum_expandable_get_compound_property:nn {#1} {counter-representation}
    \chemnum_expandable_get_compound_property:nn {#1} {post-main-label-code}
  }

\cs_new:Npn \chemnum_expandable_subcompound_write:nn #1#2
  {
    \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
      {counter-representation}
  }

% read and write saved values:
% #1: ID
\cs_new_protected:Npn \chemnum_compound_read:n #1
  {
    \chemnum_get_compound_property:nn {#1} {previous-pre-main-label-code}
    \group_begin:
      \chemnum_get_compound_property:nn {#1} {previous-label-format}
      {
        \chemnum_get_compound_property_or:nnn {#1}
          {previous-counter-representation}
          {
            \__chemnum_nothing_here:n {#1}
            \__chemnum_rerun:
          }
      }
    \group_end:
    \chemnum_get_compound_property:nn {#1} {previous-post-main-label-code}
    
  }

% #1: main ID
% #2: sub ID
\cs_new_protected:Npn \chemnum_subcompound_read:nn #1#2
  {
    \group_begin:
      \bool_if:NTF \l__chemnum_compound_local_bool
        { \l__chemnum_local_label_format_tl }
        { \chemnum_get_compound_property:nn {#1} {previous-label-format} }
      {
        \chemnum_get_subcompound_property_or:nnnn {#1} {#2}
          {previous-counter-representation}
          {
            \__chemnum_nothing_here:nn {#2} {#1}
            \__chemnum_rerun:
          }
      }
    \group_end:
  }

% this is only provided for use in PDF strings:
\cs_new:Npn \chemnum_expandable_compound_read:n #1
  {
    \chemnum_expandable_get_compound_property:nn {#1} {previous-pre-main-label-code}
    \chemnum_expandable_get_compound_property:nn {#1} {previous-counter-representation}
    \chemnum_expandable_get_compound_property:nn {#1} {previous-post-main-label-code}
  }

\cs_new:Npn \chemnum_expandable_subcompound_read:nn #1#2
  {
    \chemnum_expandable_get_subcompound_property:nnn {#1} {#2}
      {previous-counter-representation}
  }

% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: write == true and read == false
% #4: write == true and read == true
\cs_new:Npn \chemnum_if_write_and_or_read:NNTF #1#2
  {
    \bool_if:NTF #1
      { \use_none:nn }
      {
        \bool_if:NTF #2
          { \use_ii:nn }
          { \use_i:nn }
      }
  }

% write a label from the entries of \cmpd:
% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: options
% #4: label specifications
\cs_new_protected:Npn \chemnum_single_compound:NNnn #1#2#3#4
  {
    \bool_if:NT #1 { \@bsphack }
    \group_begin:
      \chemnum_split_sub_from_main:VNNnn
        \l_chemnum_compound_separator_tl
        #1 #2 {#3} {#4}
    \group_end:
    \bool_if:NT {#1} { \@esphack }
  }

% #1: label separator
% #2: boolean: if true register compound but don't write the label
% #3: boolean: if true only read compound
% #4: options
% #5: label spec
\cs_new_protected:Npn \chemnum_split_sub_from_main:nNNnn #1#2#3#4#5
  {
    \cs_set:Npn \__chemnum_split_sub_from_main_aux:nnnw ##1##2##3##4#1##5#1##6 \q_stop
      {
        \bool_if:NF ##2 { \chemnum_declare_compound:nn {##3} {##4} }
        \keys_set_groups:nnn {chemnum} {sub-only} {#4}
        \chemnum_if_write_and_or_read:NNTF #2 #3
          { \chemnum_compound_start:n {##4} }
          { \chemnum_expandable_compound_start:n {##4} }
        \chemnum_write_main:nnnn {##1} {##2} {##3} {##4}
        \bool_lazy_and:nnT
          { !\l__chemnum_sub_all_bool }
          { !\tl_if_blank_p:n {##5} }
          { \chemnum_write_sublist:NNnnn ##1 ##2 {##3} {##4} {##5} }
        \bool_if:NT \l__chemnum_sub_all_bool
          {
            \tl_clear:N \l__chemnum_tmpa_tl
            \tl_set:Nx \l__chemnum_tmpa_tl
              { \seq_use:cn {g__chemnum_compound_##4_subcompounds_seq} {,} }
            \tl_if_blank:VF \l__chemnum_tmpa_tl
              {
                \chemnum_write_sublist:NNnnV ##1 ##2 {##3} {##4}
                  \l__chemnum_tmpa_tl
              }
          }
        \chemnum_if_write_and_or_read:NNTF #2 #3
          { \chemnum_compound_finish:n {##4} }
          { \chemnum_expandable_compound_finish:n {##4} }
      }
    \__chemnum_split_sub_from_main_aux:nnnw {#2} {#3} {#4} #5#1#1 \q_stop
  }
\cs_generate_variant:Nn \chemnum_split_sub_from_main:nNNnn {V}

\cs_new:Npn \__chemnum_split_sub_from_main_aux:nnnw #1#2#3#4.#5.#6 \q_stop {}

% \chemnum_write_main:nnnn will write the main label, either with saved
% values (+ variant, boolean #2=true), or only register it (* variant, boolean
% #1=true)
%
% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: options
% #4: label spec
\cs_new_protected:Npn \chemnum_write_main:nnnn #1#2#3#4
  {
    \bool_if:NTF #2
      {
        \bool_if:NF \l__chemnum_sub_only_bool
          { \chemnum_hyper_link:nn {#4} { \chemnum_compound_read:n {#4} } }
        \bool_if:NT #1
          { \msg_error:nn {chemnum} {erroneous-argument-combination} }
      }
      {
        \bool_if:NT \l__chemnum_show_ref_bool
          { \cmpdshowref {#4} }
        \bool_lazy_or:nnF
          { \l__chemnum_sub_only_bool } {#1}
          {
            \chemnum_if_compound_used:nTF {#4}
              { \chemnum_hyper_link:nn {#4} }
              {
                \chemnum_use_compound:n {#4}
                \chemnum_hyper_target:nn {#4}
              }
            { \chemnum_compound_write:n {#4} }
          }
      }
  }

% ----------------------------------------------------------------------------
% use this for determining wether we need a hyperlink or hypertarget:
\seq_new:N \g__chemnum_used_compounds_seq

\prg_new_conditional:Npnn \chemnum_if_compound_used:n #1 {p,T,F,TF}
  {
    \seq_if_in:NnTF \g__chemnum_used_compounds_seq {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }

\cs_new_protected:Npn \chemnum_use_compound:n #1
  { \seq_gput_right:Nn \g__chemnum_used_compounds_seq {#1} }

% ----------------------------------------------------------------------------
% hyperlinks:

\cs_new_eq:NN \chemnum_hyper_target:nn \use_ii:nn
\cs_new_eq:NN \chemnum_hyper_link:nn   \use_ii:nn

\AtBeginDocument
  {
    % TODO: add boolean which allows en- and disabling the mechanism; disable
    % it per default
    \@ifpackageloaded {hyperref}
      {
        \bool_if:NT \l__chemnum_hyperlinks_bool
          {
            \cs_set_eq:NN \chemnum_hyper_link:nn \hyperlink
            \cs_set:Npn   \chemnum_hyper_target:nn #1#2
              { \raisebox {3ex} [0pt] { \hypertarget {#1} {} } #2 }
          }
      }
      {}
  }

% ----------------------------------------------------------------------------
\cs_new_protected:Npn \chemnum_print_label_id:n #1
  {
    \group_begin:
      \str_set:Nn \l__chemnum_tmpa_str {#1}
      \str_use:N \l__chemnum_tmpa_str
    \group_end:
  }

\cs_new_protected:Npn \chemnum_show_label_margin:n #1
  { \marginpar { \fbox {#1} } }

\cs_new_protected:Npn \chemnum_show_label_inline:n #1
  {
    \group_begin:
      \hbox_unpack:N \c_empty_box % this is \leavevmode
      \vbox_to_zero:n
        {
          \tex_vss:D
          \hbox_overlap_right:n
            {
              \tex_vrule:D \tex_raise:D .75em
              \hbox:n { \underbar {#1} }
            }
        }
    \group_end:
  }

\NewDocumentCommand \cmpdprintlabelid {m}
  { \chemnum_print_label_id:n {#1} }

\NewDocumentCommand \cmpdshowlabelmargin {m}
  { \chemnum_show_label_margin:n {#1} }
  
\NewDocumentCommand \cmpdshowlabelinline {m}
  { \chemnum_show_label_inline:n {#1} }

\NewDocumentCommand \chemnumshowdef {m}
  {
    \cmpdshowlabelmargin
      {
        \normalfont \ttfamily
        \cmpdprintlabelid {#1}
      }
  }
  
\NewDocumentCommand \chemnumshowref {m}
  {
    \cmpdshowlabelinline
      {
        \normalfont \ttfamily \footnotesize
        \cmpdprintlabelid {#1}
      }
  }

\NewDocumentCommand \cmpdshowdef {m} { \chemnumshowdef {#1} }
\NewDocumentCommand \cmpdshowref {m} { \chemnumshowref {#1} }
\NewDocumentCommand \subcmpdshowdef {mm} { \chemnumshowdef {#2~(#1)} }
\NewDocumentCommand \subcmpdshowref {mm} { \chemnumshowref {#2} }

% ----------------------------------------------------------------------------
% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: options
% #4: main label id
% #5: sublabel list
\cs_new_protected:Npn \chemnum_write_sublist:NNnnn #1#2#3#4#5
  {
    \seq_set_split:NVn
      \l__chemnum_tmpc_seq
      \l__chemnum_sub_separator_tl
      {#5}
    \seq_remove_duplicates:N \l__chemnum_tmpc_seq  
    \seq_map_inline:Nn \l__chemnum_tmpc_seq
      {
        \bool_if:NF #2
          { \chemnum_declare_subcompound:nnn {#3} {#4} {##1} }
      }
    \seq_clear:N \l__chemnum_tmpd_seq
    % puts the subcompounds ready to be printed in \l__chemnum_tmpd_seq :
    \chemnum_sort_subcompounds:NNNnnNN #1#2
      \l__chemnum_tmpc_seq
      {#3}
      {#4}
      \l__chemnum_tmpd_seq % to write the uncompressed list
      \l__chemnum_tmpe_seq % for compressing the list, holds the numbers
    \bool_lazy_and:nnTF
      { \l__chemnum_compress_subcompounds_bool }
      { \int_compare_p:n { \seq_count:N \l__chemnum_tmpe_seq > 2 } }
      {
        % needs a seq with the associated /numbers/!
        \chemnum_compress_subcompounds:NNN
          \l__chemnum_tmpd_seq % holds the IDs
          \l__chemnum_tmpe_seq % holds the numbers
          \l__chemnum_tmpc_seq % the new sequence
        \seq_use:Nn \l__chemnum_tmpc_seq {}
      }
      {
        \seq_use:NVVV \l__chemnum_tmpd_seq
          \l__chemnum_sep_sublist_two_tl
          \l__chemnum_sep_sublist_more_tl
          \l__chemnum_sep_sublist_last_two_tl
      }
  }
\cs_generate_variant:Nn \chemnum_write_sublist:NNnnn {NNnnV}

% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: options
% #4: main ID
% #5: sub ID
\cs_new_protected:Npn \chemnum_write_subcompound:NNnnn #1#2#3#4#5
  {
    \bool_if:NTF #2
      { \chemnum_subcompound_read:nn {#4} {#5} }
      {
        \chemnum_declare_subcompound:nnn {#3} {#4} {#5}
        \bool_if:NT \l__chemnum_show_ref_bool
          { \subcmpdshowref {#4} {#5} }
        \bool_if:NF #1
          { \chemnum_subcompound_write:nn {#4} {#5} }
      }
  }
\cs_generate_variant:Nn \chemnum_write_subcompound:NNnnn {NNnnV}

%%% The following command sorts the sequence according to the order in which
%%% they've been declared
% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: sub ID sequence
% #4: options
% #5: main ID
% #6: seq variable
% #7: seq variable
\cs_new_protected:Npn \chemnum_sort_subcompounds:NNNnnNN #1#2#3#4#5#6#7
  {
    \seq_clear:N #6
    \seq_clear:N #7
    \bool_if:NF #1
      {
        \seq_if_exist:cTF {g__chemnum_compound_#5_subcompounds_seq}
          {
            \seq_map_inline:Nn #3
              {
                \seq_if_in:cnTF {g__chemnum_compound_#5_subcompounds_seq} {##1}
                  {
                    \seq_put_right:Nn #6
                      { \chemnum_write_subcompound:NNnnn #1 #2 {#4} {#5} {##1} }
                    \bool_if:NTF #2
                      {
                        \seq_put_right:Nx #7
                          {
                            \chemnum_expandable_get_subcompound_property:nnn
                              {#5} {##1} {previous-number}
                          }
                      }
                      {
                        \seq_put_right:Nx #7
                          {
                            \chemnum_expandable_get_subcompound_property:nnn
                              {#5} {##1} {number}
                          }
                      }
                  }
                  { \__chemnum_nothing_here:nn {##1} {#5} }
              }
          }
          { \__chemnum_nothing_here:xn { \seq_use:Nnnn #3 {,~} {,~} {,~} } {#5} }
        }
      \seq_remove_all:Nn #7 {}
  }

% #1: sub ID sequence
% #2: sub ID sequence that holds the numbers rather than the IDs
% #3: seq variable
\cs_new_protected:Npn \chemnum_compress_subcompounds:NNN #1#2#3
  {
    \int_zero:N \l__chemnum_tmpa_int
    \int_zero:N \l__chemnum_tmpb_int
    \seq_clear:N \l__chemnum_tmpa_seq
    \seq_clear:N #3
    \seq_map_inline:Nn #2
      {
        \int_incr:N \l__chemnum_tmpa_int
        \int_compare:nTF { \l__chemnum_tmpa_int = 1 }
          { \seq_put_right:Nn \l__chemnum_tmpa_seq {1} }
          {
            \seq_put_right:Nx \l__chemnum_tmpa_seq
              { \int_eval:n { ##1 - \l__chemnum_tmpb_int } }
          }
        \int_set:Nn \l__chemnum_tmpb_int {##1}
      }
    \int_zero:N \l__chemnum_tmpa_int
    \int_set:Nn \l__chemnum_tmpb_int { \seq_count:N #2 }
    \int_zero:N \l__chemnum_tmpc_int
    \seq_map_inline:Nn \l__chemnum_tmpa_seq
      {
        \int_incr:N \l__chemnum_tmpa_int
        \int_compare:nTF { \l__chemnum_tmpa_int = 1 }
          {
            \int_add:Nn \l__chemnum_tmpc_int {##1}
            \seq_put_right:Nx #3 { \seq_item:Nn #1 {1} }
          }
          {
            \int_compare:nTF { ##1 = 1 }
              { \int_add:Nn \l__chemnum_tmpc_int {##1} }
              {
                \int_compare:nTF { \l__chemnum_tmpc_int > 2 }
                  {
                    \seq_put_right:NV #3 \l__chemnum_sep_sublist_range_tl
                    \seq_put_right:Nx #3
                      { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } }
                    \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl
                    \seq_put_right:Nx #3
                      { \seq_item:Nn #1 { \l__chemnum_tmpa_int } }
                  }
                  {
                    \seq_get_right:NN #3 \l__chemnum_tmpa_tl
                    \tl_if_eq:VxF
                      \l__chemnum_tmpa_tl
                      { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } }
                      {
                        \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl
                        \seq_put_right:Nx #3
                          { \seq_item:Nn #1 { \l__chemnum_tmpa_int - 1 } }
                      }
                    \seq_put_right:NV #3 \l__chemnum_sep_sublist_two_tl
                    \seq_put_right:Nx #3
                      { \seq_item:Nn #1 { \l__chemnum_tmpa_int } }
                  }
                \int_set:Nn \l__chemnum_tmpc_int { 1 }
              }
            \int_compare:nT { \l__chemnum_tmpa_int = \l__chemnum_tmpb_int }
              {
                \seq_get_right:NN #3 \l__chemnum_tmpa_tl
                \tl_if_eq:VxF
                  \l__chemnum_tmpa_tl
                  { \seq_item:Nn #1 { \l__chemnum_tmpa_int } }
                  {
                    \int_compare:nTF { \l__chemnum_tmpc_int > 2 }
                      { \seq_put_right:NV #3 \l__chemnum_sep_sublist_range_tl }
                      { \seq_put_right:NV #3 \l__chemnum_sep_sublist_last_two_tl }
                    \seq_put_right:Nx #3
                      { \seq_item:Nn #1 { \l__chemnum_tmpa_int } }
                  }
              }
          }
      }
  }

% ----------------------------------------------------------------------------
% the code level version of the main command:
% #1: boolean: if true register compound but don't write the label
% #2: boolean: if true only read compound
% #3: options
% #4: list of IDs
\cs_new_protected:Npn \chemnum_cmpd:nnnn #1#2#3#4
  {
    \group_begin:
      \keys_set_groups:nnn {chemnum} {list} {#3}
      \seq_set_split:NVn
        \l__chemnum_tmpa_seq
        \l__chemnum_main_separator_tl
        {#4}
      \seq_remove_duplicates:N \l__chemnum_tmpa_seq
      \chemnum_sort_main_labels:N \l__chemnum_tmpa_seq
      \seq_clear:N \l__chemnum_tmpb_seq
      \seq_map_inline:Nn \l__chemnum_tmpa_seq
        {
          \seq_put_right:Nn \l__chemnum_tmpb_seq
            { \chemnum_single_compound:NNnn #1 #2 {#3} {##1} }
        }
      \bool_if:NTF #1 % starred call of \cmpd
        { \seq_use:Nn \l__chemnum_tmpb_seq {} }
        {
          \seq_use:NVVV \l__chemnum_tmpb_seq
            \l__chemnum_sep_list_two_tl
            \l__chemnum_sep_list_more_tl
            \l__chemnum_sep_list_last_two_tl
        }
    \group_end:
  }

% #1: first variable
% #2: second variable
% #3: main/sub separator
% #4: complete label
\cs_new_protected:Npn \chemnum_separate_main_sub:NNnn #1#2#3#4
  {
    \cs_set:Npn \__chemnum_remove_sub:w ##1#3##2 \q_stop
      { \exp_not:n {##1} }
    \cs_set:Npn \__chemnum_get_sub:w ##1#3##2#3##3 \q_stop
      {
        \tl_if_blank:nF {##2} { \exp_not:n {##2} }
      }
    \tl_set:Nx #1 { \__chemnum_remove_sub:w #4#3 \q_stop }
    \tl_set:Nx #2 { \__chemnum_get_sub:w #4#3#3 \q_stop }
  }
\cs_generate_variant:Nn \chemnum_separate_main_sub:NNnn {NNV}

% sorting and merging of the main label list:
% #1: seq that holds the label list
\cs_new_protected:Npn \chemnum_sort_main_labels:N #1
  {
    \prop_clear:N \l__chemnum_tmpa_prop
    \seq_clear:N \l__chemnum_tmpb_seq
    \seq_clear:N \l__chemnum_tmpc_seq
    % build property list that holds entries of #1:
    \seq_map_inline:Nn #1
      {
        \chemnum_separate_main_sub:NNVn
          \l__chemnum_tmpa_tl % main part
          \l__chemnum_tmpb_tl % sub part
          \l_chemnum_compound_separator_tl
          {##1}
        \bool_if:NTF \l__chemnum_merge_list_bool
          {
            \prop_get:NVNTF \l__chemnum_tmpa_prop
              \l__chemnum_tmpa_tl
              \l__chemnum_tmpc_tl
              {
                \prop_put:NVx \l__chemnum_tmpa_prop
                  \l__chemnum_tmpa_tl
                  {
                    \exp_not:V \l__chemnum_tmpc_tl
                    \exp_not:V \l__chemnum_sub_separator_tl
                    \exp_not:V \l__chemnum_tmpb_tl
                  }
              }
              {
                \prop_put:NVV \l__chemnum_tmpa_prop
                  \l__chemnum_tmpa_tl
                  \l__chemnum_tmpb_tl
              }
          }
          {
            \prop_get:NVNTF \l__chemnum_tmpa_prop
              \l__chemnum_tmpa_tl
              \l__chemnum_tmpc_tl
              {
                \prop_put:NVx \l__chemnum_tmpa_prop
                  \l__chemnum_tmpa_tl
                  {
                    \exp_not:V \l__chemnum_tmpc_tl
                    \exp_not:V \l__chemnum_main_separator_tl
                    \exp_not:n {##1}
                  }
              }
              {
                \prop_put:NVn \l__chemnum_tmpa_prop
                  \l__chemnum_tmpa_tl
                  {##1}
              }
          }
      }
    % merge = true:
    % \l__chemnum_tmpa_prop now holds all main labels with possible sublabel
    % lists
    % merge = false
    % \l__chemnum_tmpa_prop now holds all main labels with all occurences of
    % the respective main label as property
    %
    % build sequence that holds entries of #1 in order of already defined
    % labels:
    \seq_map_inline:Nn \g__chemnum_defined_compounds_seq
      {
        \bool_if:NTF \l__chemnum_merge_list_bool
          {
            \prop_get:NnNT \l__chemnum_tmpa_prop {##1} \l__chemnum_tmpa_tl
              {
                \tl_if_in:VVTF
                  \l__chemnum_tmpa_tl
                  \l__chemnum_sub_separator_tl
                  {
                    \seq_put_right:Nx \l__chemnum_tmpb_seq
                      {
                        \exp_not:n {##1}
                        \tl_if_blank:VF \l__chemnum_tmpa_tl
                          {
                            \exp_not:V \l_chemnum_compound_separator_tl
                            { \exp_not:V \l__chemnum_tmpa_tl }
                          }
                      }
                  }
                  {
                    \seq_put_right:Nx \l__chemnum_tmpb_seq
                      {
                        \exp_not:n {##1}
                        \tl_if_blank:VF \l__chemnum_tmpa_tl
                          {
                            \exp_not:V \l_chemnum_compound_separator_tl
                            \exp_not:V \l__chemnum_tmpa_tl
                          }
                      }
                  }
                \seq_if_in:NnF \l__chemnum_tmpc_seq {##1}
                  { \seq_put_right:Nn \l__chemnum_tmpc_seq {##1} }
              }
          }
          {
            \prop_get:NnNT \l__chemnum_tmpa_prop {##1} \l__chemnum_tmpa_tl
              {
                \tl_if_in:VVTF
                  \l__chemnum_tmpa_tl
                  \l__chemnum_main_separator_tl
                  {
                    \seq_set_split:NVV \l__chemnum_tmpc_seq
                      \l__chemnum_main_separator_tl
                      \l__chemnum_tmpa_tl
                    \seq_map_inline:Nn \l__chemnum_tmpc_seq
                      { \seq_put_right:Nn \l__chemnum_tmpb_seq {####1} }
                  }
                  { \seq_put_right:NV \l__chemnum_tmpb_seq \l__chemnum_tmpa_tl }
              }
          }
      }
    % \l__chemnum_tmpb_seq now holds all labels that are already defined
    % merge = true :
    % the same \l__chemnum_tmpc_seq which only holds the /main/ labels
    \bool_if:NTF \l__chemnum_merge_list_bool
      {
        \seq_map_inline:Nn #1
          {
            \chemnum_separate_main_sub:NNVn
              \l__chemnum_tmpa_tl % main part
              \l__chemnum_tmpb_tl % sub part
              \l_chemnum_compound_separator_tl
              {##1}
            % check if existing main label is present, otherwise add entry
            \seq_if_in:NVF \l__chemnum_tmpc_seq \l__chemnum_tmpa_tl
              {
                \prop_get:NVNT \l__chemnum_tmpa_prop
                  \l__chemnum_tmpa_tl
                  \l__chemnum_tmpc_tl
                  {
                    \seq_put_right:Nx \l__chemnum_tmpb_seq
                      {
                        \exp_not:V \l__chemnum_tmpa_tl
                        \tl_if_blank:VF \l__chemnum_tmpc_tl
                          {
                            \exp_not:V \l_chemnum_compound_separator_tl
                            \exp_not:V \l__chemnum_tmpc_tl
                          }
                      }
                    \seq_put_right:NV \l__chemnum_tmpc_seq \l__chemnum_tmpa_tl
                  }
              }
          }
      }
      {
        \seq_map_inline:Nn #1
          {
            \seq_if_in:NnF \l__chemnum_tmpb_seq {##1}
              { \seq_put_right:Nn \l__chemnum_tmpb_seq {##1} }
          }
      }
    \seq_set_eq:NN #1 \l__chemnum_tmpb_seq
  }

% %-----------------------------------------------------------------------------%
% % REPLACE TAG IN EPS PICTURE WITH LABEL
% % works similar to \schemeref command of the chemscheme package
% % \cmpdref-[<keyval>][<tag>]{<label name>}

\cs_new_protected:Npn \__chemnum_set_psfrag_pos:nn #1#2
  {
    \tl_set:Nn \l__chemnum_psfrag_texpos_tl {#1}
    \tl_set:Nn \l__chemnum_psfrag_pspos_tl {#2}
  }

\cs_new_protected:Npn \__chemnum_set_psfrag_local_pos:nn #1#2
  {
    \tl_set:Nn \l__chemnum_psfrag_local_texpos_tl {#1}
    \tl_set:Nn \l__chemnum_psfrag_local_pspos_tl {#2}
  }
\cs_generate_variant:Nn \__chemnum_set_psfrag_local_pos:nn {VV}

\cs_new_protected:Npn \__chemnum_psfrag:nnnn #1#2#3#4
  { \psfrag {#1} [#2] [#3] {#4} }
\cs_generate_variant:Nn \__chemnum_psfrag:nnnn {VVVx}

% #1: boolean: if true only read label
% #2: options
% #3: label spec
\cs_new_protected:Npn \chemnum_cmpd_replace:nnn #1#2#3
  {
    % place the label
    % just in case it hasn't been declared:
    \bool_if:nF {#1} {
      \chemnum_cmpd:nnnn { \c_true_bool } { \c_false_bool } {#2} {#3}
    }
    \tl_set_eq:NN
      \l__chemnum_compound_replace_local_format_tl
      \l__chemnum_compound_replace_format_tl
    % set specific replacement options
    \keys_set_groups:nnn {chemnum} {replace} { replace=false, #2 }
    \bool_lazy_and:nnTF
      { \l__chemnum_compound_replace_auto_bool }
      { \l__chemnum_compound_replace_auto_this_bool }
      {
        \int_incr:N \l__chemnum_compound_replace_int
        \tl_set:Nx \l__chemnum_compound_replace_tl
          {
            \exp_not:V \l__chemnum_compound_replace_tag_tl
            \exp_not:V \l__chemnum_compound_replace_int
          }
      }
      {
        \tl_set_eq:NN
          \l__chemnum_compound_replace_tl
          \l__chemnum_compound_replace_tag_tl
        \bool_set_true:N \l__chemnum_compound_replace_auto_this_bool
      }
    % replace in EPS, this must not be in a group:
    \bool_if:NTF \l__chemnum_replace_local_bool
      {
        \__chemnum_psfrag:VVVx
          \l__chemnum_compound_replace_tl
          \l__chemnum_psfrag_local_texpos_tl
          \l__chemnum_psfrag_local_pspos_tl
          {
            \group_begin:
              \exp_not:V \l__chemnum_compound_replace_local_format_tl
              \exp_not:n
                { \chemnum_cmpd:nnnn { \c_false_bool } {#1} {#2} {#3} }
            \group_end:
          }
      }
      {
        \__chemnum_psfrag:VVVx
          \l__chemnum_compound_replace_tl
          \l__chemnum_psfrag_texpos_tl
          \l__chemnum_psfrag_pspos_tl
          {
            \group_begin:
              \exp_not:V \l__chemnum_compound_replace_format_tl
              \exp_not:n
                { \chemnum_cmpd:nnnn { \c_false_bool } {#1} {#2} {#3} }
            \group_end:
          }
      }
    % clean up local options:
    \keys_set_groups:nnn {chemnum} {replace} { replace=false }
    \__chemnum_set_psfrag_local_pos:VV
      \l__chemnum_psfrag_texpos_tl
      \l__chemnum_psfrag_pspos_tl
    \tl_set_eq:NN
      \l__chemnum_compound_replace_local_format_tl
      \l__chemnum_compound_replace_format_tl
  }

\NewDocumentCommand \replacecmpd {t+om}
  { \chemnum_cmpd_replace:nnn {#1} {#2} {#3} }

% ----------------------------------------------------------------------------
% the user level version of the main command:
\NewDocumentCommand \cmpd {st+O{}m}
  { \chemnum_cmpd:nnnn {#1} {#2} {#3} {#4} }

\NewDocumentCommand \refcmpd {O{}m}
  { \chemnum_cmpd:nnnn { \c_false_bool } { \c_true_bool } {#1} {#2} }

\NewDocumentCommand \labelcmpd {O{}m}
  { \chemnum_cmpd:nnnn { \c_true_bool } { \c_false_bool } {#1} {#2} }

\DeclareExpandableDocumentCommand \cmpdplain {m}
  {
    \chemnum_expandable_compound_start:n {#1}
    \chemnum_expandable_compound_read:n {#1}
    \chemnum_expandable_compound_finish:n {#1}
  }

\DeclareExpandableDocumentCommand \subcmpdplain {mm}
  { \chemnum_expandable_subcompound_read:nn {#1} {#2} }

\DeclareExpandableDocumentCommand \submaincmpdplain {mm}
  {
    \chemnum_expandable_compound_start:n {#1}
    \chemnum_expandable_compound_read:n {#1}
    \chemnum_expandable_subcompound_read:nn {#1} {#2}
    \chemnum_expandable_compound_finish:n {#1}
  }

% ----------------------------------------------------------------------------
\cs_new_protected:Npn \chemnum_init:nn #1#2
  {
    \group_begin:
      % this is semantically wrong! The conflict: either I allow initiation
      % to be set locally (which does not make sense, really) or I use wrong
      % semantics at this very point in the package code...
      \bool_set_false:N \g__chemnum_initiate_bool
      \bool_set_false:N \g__chemnum_initiate_sub_bool
      \chemnum_cmpd:nnnn { \c_true_bool } { \c_false_bool } {#1} {#2}
    \group_end:
  }

\NewDocumentCommand \initcmpd {O{}m}
  { \AtBeginDocument { \chemnum_init:nn {#1} {#2} } }
\@onlypreamble\initcmpd

% ----------------------------------------------------------------------------
% resetting compound numbering
\cs_new_protected:Npn \chemnum_reset_compounds:n #1
  { \setcounter {cmpdmain} { \int_eval:n { #1 - 1 } } }

\NewDocumentCommand \resetcmpd {O{1}}
  { \chemnum_reset_compounds:n {#1} }

% ----------------------------------------------------------------------------
% language support:
\DeclareTranslationFallback {chemnum-sep-two} {~and~}
\DeclareTranslation {English} {chemnum-sep-two} {~and~}
\DeclareTranslation {German} {chemnum-sep-two} {~und~}
\DeclareTranslation {French} {chemnum-sep-two} {~et~}
\DeclareTranslation {Spanish} {chemnum-sep-two} {~y~}
\DeclareTranslation {Italian} {chemnum-sep-two} {~e~}
\DeclareTranslation {Catalan} {chemnum-sep-two} {~i~}
\DeclareTranslation {Portuguese} {chemnum-sep-two} {~e~}
\DeclareTranslation {Dutch} {chemnum-sep-two} {~en~}
\DeclareTranslation {Danish} {chemnum-sep-two} {~og~}
\DeclareTranslation {Swedish} {chemnum-sep-two} {~och~}
\DeclareTranslation {Finnish} {chemnum-sep-two} {~ja~}
\DeclareTranslation {Norwegian} {chemnum-sep-two} {~og~}

\DeclareTranslationFallback {chemnum-sep-last-two} {~and~}
\DeclareTranslation {English} {chemnum-sep-last-two} {~and~}
\DeclareTranslation {American} {chemnum-sep-last-two} {,~and~}
\DeclareTranslation {British} {chemnum-sep-last-two} {~and~}
\DeclareTranslation {German} {chemnum-sep-last-two} {~und~}
\DeclareTranslation {French} {chemnum-sep-last-two} {~et~}
\DeclareTranslation {Spanish} {chemnum-sep-last-two} {~y~}
\DeclareTranslation {Italian} {chemnum-sep-last-two} {~e~}
\DeclareTranslation {Catalan} {chemnum-sep-last-two} {~i~}
\DeclareTranslation {Portuguese} {chemnum-sep-last-two} {~e~}
\DeclareTranslation {Dutch} {chemnum-sep-last-two} {~en~}
\DeclareTranslation {Danish} {chemnum-sep-last-two} {~og~}
\DeclareTranslation {Swedish} {chemnum-sep-last-two} {~och~}
\DeclareTranslation {Finnish} {chemnum-sep-last-two} {~ja~}
\DeclareTranslation {Norwegian} {chemnum-sep-last-two} {~og~}

% ----------------------------------------------------------------------------
% TODO: add a warning for those options that can't be set with the setup
% command, i.e., those belonging to the `compound' group
\cs_new_protected:Npn \chemnum_setup:n #1
  {
    \keys_set_filter:nnn {chemnum} {compound,general} {#1}
    \keys_set_groups:nnn {chemnum} {general} {#1}
  }

\NewDocumentCommand \setchemnum {m}
  { \chemnum_setup:n {#1} }

\file_input_stop:

% ----------------------------------------------------------------------------
HISTORY:
2014/03/12 v1.0  - first published
2014/05/30 v1.0a - bug fix: subcompounds can now be correctly referenced
                   before they're defined
2014/06/02 v1.0b - bug fix: list of sublabels can now correctly be sorted and
                   compressed if referenced before they're defined
2014/08/08 v1.1  - new option `replace-tag-nr'
2015/05/13 v1.1a - fix bug in \replacecmpd
2015/11/23 v1.1b - small adjustments in the property defining mechanism
                 - more meaningful error messages when unknown properties are
                   set
2016/01/30 v1.1c - adapt to deprecation of expl3's \prop_get:Nn (=>
                   \prop_item:Nn)
2016/04/14 v1.2  - changes to how compounds are saved to auxfile
                 - hyperref support: backlinks to first appearance of label
2016/05/11 v1.2a - pre- and post-label options now belong both to the
                   `compound' and the `general' groups
2016/10/22 v1.2b - enable label keys to be printed (with `show-keys') if they
                   contain underscores or similar tokens
                 - easier customization possibilities of the `show-keys'
                   functions
2019/10/02 v1.2c - fix issues #5, #7
2020/12/06 v1.3  - add \setcmpdproperty and \setcmpdlabel
                 - prefer lazy boolean evaluation
                 - fix issues #14, #15, #16
                 - make some variables public
                 - \chemnum_if_subcompounds:nTF
                 - \chemnum_count_subcompounds:n
                 - \chemnum_get_subcompound:nn
2021/01/21 v1.3a - fix issue #17