% \iffalse meta-comment
%
%% regulatory-sources.dtx
%% Copyright 2024-2026 E. Nijenhuis
%
% 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 2005/12/01 or later.
%
% This work has the LPPL maintenance status ‘maintained’.
%
% The Current Maintainer of this work is E. Nijenhuis.
%
% This work consists of the files listed in the meta-comment of
% regulatory-struct.dtx.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{regulatory-sources.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{regulatory-sources}
%<package>    [2026/09/10 1.0.0 Xerdi's Regulatory Package (External sources)]
%
%<*driver>
\documentclass[10pt,english]{ltxdoc}
%! suppress = InclusionLoop
\usepackage{regulatory}
\usepackage{tabularx}
\usepackage[english,dutch]{babel}
\input{regulatory-preamble}
\newcommand\translation[2]{#1}
\begin{document}
    \selectlanguage{english}
    \DocInput{regulatory-sources.dtx}
\end{document}
%</driver>
% \fi
%
% \subsection{\texorpdfstring{\package{regulatory-sources}}{regulatory-sources}}
% \setcounter{CodelineNo}{0}
%
% A regulatory document cites instruments that are not this document: a statute, a regulation of the
% Union. This module holds the ones a document cites, so that the wording of a citation is a property of
% the document rather than of the sentence it happens to stand in. What it does \emph{not} do is decide the
% wording; that is the next module. This one reads and holds.
%
% \subsubsection{\translation{Prerequisites}{Vereisten}}
%
% \iffalse
%<*package>
% \fi
%    \begin{macrocode}
\RequirePackage{regulatory-struct}
%    \end{macrocode}
%
% \subsubsection{\translation{Sources of a source}{Bronnen van een bron}}
%
% Sources are declared in a \file{bib} file, which is the format such records are already kept in, and
% read by this module rather than by \package{biblatex} or \package{bib2gls}. Neither would be wrong; both
% would put an external program between a document and a handful of records. The test suite of this bundle
% promises a \TeX{} installation and nothing else, the conversion to HTML runs the same documents, and a
% document rarely cites more than a few instruments. So the reading is done here, and the price of that is
% that this module owns a parser.
%
% A parser that is owned has to say what it accepts. This one accepts the shape a \file{bib} file is
% written in when a person writes it, and nothing further:
%
% \begin{labeling}{\quad}
%     \item[] an entry opens with \texttt{@}\meta{type}\texttt{\{}\meta{key}\texttt{,} on a line of its own;
%     \item[] a field is \meta{name}~\texttt{= \{}\meta{value}\texttt{\},} on a line of its own;
%     \item[] the entry closes with \texttt{\}} on a line of its own;
%     \item[] a line that is empty, or that starts with \texttt{\%}, is a comment.
% \end{labeling}
%
% A line that is none of these is an error naming the file and the line, rather than a line that is
% skipped. That is the whole reason a parser may be owned at all: the failure of a reader has to be loud,
% since a record that was not read is a citation that comes out empty and a document that looks finished.
%    \begin{macrocode}
\ExplSyntaxOn
\prop_new:N \g__regulatory_src_required_prop
\prop_new:N \g__regulatory_src_type_prop
\prop_new:N \g__regulatory_src_register_prop
\prop_new:N \g__regulatory_src_typealias_prop
\prop_new:N \g__regulatory_src_fieldalias_prop
\seq_new:N \g__regulatory_src_keys_seq

\ior_new:N \g__regulatory_src_ior
\str_new:N \l__regulatory_src_key_str
\str_new:N \l__regulatory_src_type_str
\str_new:N \l__regulatory_src_file_str
\str_new:N \l__regulatory_src_query_str
\int_new:N \l__regulatory_src_line_int
\bool_new:N \l__regulatory_src_open_bool
\seq_new:N \l__regulatory_src_parts_seq
\tl_new:N \l__regulatory_src_required_tl
\clist_new:N \l__regulatory_src_required_clist
\tl_new:N \l__regulatory_src_one_tl
\tl_new:N \l__regulatory_src_two_tl
%    \end{macrocode}
%
% \begin{macro}{\newsourcetype}
% Declares an entry type, the fields an entry of it cannot do without, and the register its citations are
% worded in. The required fields are what the wording needs in every register: a Dutch regulation is named
% by its citeertitel, an act of the Union by what kind of act it is and by its number.
%
% The register belongs to the type and not to the document, because it is the legal order of the instrument
% that decides how a citation of it reads. A Dutch contract that cites the \textsc{gdpr} words that
% citation the way the regulation itself does. An entry may override it with a \texttt{register} field.
%    \begin{macrocode}
\NewDocumentCommand \newsourcetype { m m m }
  {
    \prop_gput:Nnn \g__regulatory_src_required_prop { #1 } { #2 }
    \prop_gput:Nnn \g__regulatory_src_register_prop { #1 } { #3 }
  }

\NewDocumentCommand \newsourcetypealias { m m }
  { \prop_gput:Nnn \g__regulatory_src_typealias_prop { #1 } { #2 } }

\NewDocumentCommand \newsourcefieldalias { m m }
  { \prop_gput:Nnn \g__regulatory_src_fieldalias_prop { #1 } { #2 } }

\cs_new:Npn \__regulatory_src_alias:Nn #1#2
  {
    \tl_if_blank:eTF { \prop_item:Nn #1 { #2 } }
      { #2 } { \prop_item:Nn #1 { #2 } }
  }
\cs_generate_variant:Nn \__regulatory_src_alias:Nn { Ne }

\cs_new:Npn \regulatory@src@type@of #1
  { \__regulatory_src_alias:Ne \g__regulatory_src_typealias_prop { #1 } }
\cs_new:Npn \regulatory@src@field@of #1
  { \__regulatory_src_alias:Ne \g__regulatory_src_fieldalias_prop { #1 } }
\ExplSyntaxOff

\newsourcetype{regulation}{citetitle}{dutch}
\newsourcetype{euact}{kind,number}{dutch_eu}
%    \end{macrocode}
%
% The names above are English, as the rest of this bundle is, and every one of them answers to a Dutch name
% as well. A bib file is written by the person who keeps the records, and that person writes
% \texttt{citetitle} because that is what the field is called in the law that defines it. Neither name is
% a translation of the other in the reader: the Dutch one resolves to the English one before anything is
% stored, so a file may use either and a document may read back either.
%    \begin{macrocode}
\newsourcetypealias{regeling}{regulation}
\newsourcetypealias{euhandeling}{euact}

\newsourcefieldalias{citeertitel}{citetitle}
\newsourcefieldalias{afkorting}{abbreviation}
\newsourcefieldalias{boek}{book}
\newsourcefieldalias{geldig}{valid}
\newsourcefieldalias{soort}{kind}
\newsourcefieldalias{nummer}{number}
\newsourcefieldalias{roepnaam}{shortname}
\newsourcefieldalias{titel}{title}
\newsourcefieldalias{pb}{oj}
\newsourcefieldalias{lidwoord}{determiner}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newsource}
% Declares one source in the document itself, which is the route that needs no file at all. It ends in the
% same store as a line read from a \file{bib} file, so nothing downstream can tell the two apart.
%    \begin{macrocode}
\ExplSyntaxOn
\NewDocumentCommand \newsource { m m m }
  {
    \__regulatory_src_begin:nn { #2 } { #1 }
    \keyval_parse:nnn
      { \__regulatory_src_novalue:n } { \__regulatory_src_field:nn } { #3 }
    \__regulatory_src_end:
  }

\cs_new_protected:Npn \__regulatory_src_novalue:n #1
  {
    \msg_error:nnn { regulatory-sources } { no-value } { #1 }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection*{Opening an entry}
%
% \verb|\__regulatory_src_begin:nn|
% Opens an entry of \meta{type} under \meta{key}. An undeclared type and a key that is already taken are
% both errors: the first is a record nothing can word, the second is a record that would quietly replace
% one the document already relies on.
%    \begin{macrocode}
\cs_new_protected:Npn \__regulatory_src_begin:nn #1#2
  {
    \str_set:Nx \l__regulatory_src_type_str { \regulatory@src@type@of { #1 } }
    \str_set:Nn \l__regulatory_src_key_str { #2 }
    \prop_if_in:NVF \g__regulatory_src_required_prop \l__regulatory_src_type_str
      {
        \msg_error:nnxx { regulatory-sources } { unknown-type }
          { \l__regulatory_src_type_str } { \l__regulatory_src_key_str }
      }
    \seq_if_in:NVT \g__regulatory_src_keys_seq \l__regulatory_src_key_str
      {
        \msg_error:nnx { regulatory-sources } { duplicate-key }
          { \l__regulatory_src_key_str }
      }
    \prop_new:c { g__regulatory_src_e_ \l__regulatory_src_key_str _prop }
    \bool_set_true:N \l__regulatory_src_open_bool
  }
%    \end{macrocode}
%
% \subsubsection*{Storing a field}
%
% \verb|\__regulatory_src_field:nn|
% Stores one field of the entry that is open. The name of the field is lowered and expanded into the key
% it is stored under, while the value is not expanded at all: a value is data, and a document that writes
% a macro in a bib file gets that macro back rather than what it produced at reading time.
%    \begin{macrocode}
\cs_new_protected:Npn \__regulatory_src_field:nn #1#2
  {
    \bool_if:NTF \l__regulatory_src_open_bool
      {
        \use:x
          {
            \prop_gput:cnn
              { g__regulatory_src_e_ \l__regulatory_src_key_str _prop }
              { \regulatory@src@field@of { \str_lowercase:n { #1 } } }
              { \exp_not:n { #2 } }
          }
      }
      { \msg_error:nnn { regulatory-sources } { stray-field } { #1 } }
  }
%    \end{macrocode}
%
% \subsubsection*{Closing an entry}
%
% \verb|\__regulatory_src_end:|
% Closes the entry and holds it against the fields its type requires. This is the moment the guarantee is
% made: from here on a source may be read without asking whether it is complete, which is what lets the
% commands that word a citation be expandable and silent.
%    \begin{macrocode}
\cs_new_protected:Npn \__regulatory_src_end:
  {
    \prop_get:NVN \g__regulatory_src_required_prop \l__regulatory_src_type_str
      \l__regulatory_src_required_tl
    \quark_if_no_value:NF \l__regulatory_src_required_tl
      {
        \clist_set:NV \l__regulatory_src_required_clist
          \l__regulatory_src_required_tl
        \clist_map_inline:Nn \l__regulatory_src_required_clist
          {
            \prop_if_in:cnF
              { g__regulatory_src_e_ \l__regulatory_src_key_str _prop } { ##1 }
              {
                \msg_error:nnxxx { regulatory-sources } { missing-field }
                  { ##1 } { \l__regulatory_src_key_str }
                  { \l__regulatory_src_type_str }
              }
          }
      }
    \__regulatory_src_checkvalid:
    \prop_gput:NVV \g__regulatory_src_type_prop
      \l__regulatory_src_key_str \l__regulatory_src_type_str
    \seq_gput_right:NV \g__regulatory_src_keys_seq \l__regulatory_src_key_str
    \bool_set_false:N \l__regulatory_src_open_bool
  }
%    \end{macrocode}
%
% \verb|\__regulatory_src_checkvalid:|
% Every entry says when it was last held against the text it describes. The date it gives is what
% \cmd{\sourcedate} is compared with, so an entry without one is never reported stale: \enquote{not looked
% at yet} and \enquote{looked at and current} would come out as the same silence. A guard whose off switch
% is an absent field is switched off by accident rather than by decision, so the absence is said out loud
% and the decision is given a word of its own\,---\,\texttt{valid = unverified}, which is silent, because
% the author has then said it. Anything else that is not a date is said as well, since a date in another
% shape compares wrongly rather than not at all.
%
% Asked for by the sibling session that keeps the sources this reader is written for, on the argument this
% whole bundle is built on.
%
% There is deliberately no fourth state for \enquote{checked and known to have changed}. Such an entry
% already warns: it keeps its last good date, the document speaks later, and the source is named. A word in
% place of that date would fire the same warning while throwing the date away, and the date is the one thing
% that says how far behind the entry is and whether the citation in front of the reader predates the change.
% A note that an entry is known to be wrong is for a person reading the file, not a state this guard reads.
%    \begin{macrocode}
\cs_new_protected:Npn \__regulatory_src_checkvalid:
  {
    \prop_get:cnNTF { g__regulatory_src_e_ \l__regulatory_src_key_str _prop }
      { valid } \l__regulatory_src_valid_tl
      {
        \str_if_eq:VnF \l__regulatory_src_valid_tl { unverified }
          {
            \regex_match:NVF \c__regulatory_src_date_regex \l__regulatory_src_valid_tl
              {
                \msg_warning:nnxx { regulatory-sources } { valid-not-iso }
                  { \l__regulatory_src_key_str } { \l__regulatory_src_valid_tl }
              }
          }
      }
      {
        \msg_warning:nnx { regulatory-sources } { no-valid }
          { \l__regulatory_src_key_str }
      }
  }
\cs_generate_variant:Nn \regex_match:NnF { NVF }

\msg_new:nnn { regulatory-sources } { no-valid }
  {
    The~source~`#1'~does~not~say~when~it~was~last~held~against~the~text~it~
    describes,~\\
    so~it~can~never~be~reported~out~of~date.~Give~it~valid~=~YYYY-MM-DD,~or~
    valid~=~unverified~to~say~so~on~purpose.~Reported
  }

\msg_new:nnn { regulatory-sources } { valid-not-iso }
  {
    The~source~`#1'~gives~valid~=~`#2',~which~is~neither~YYYY-MM-DD~nor~
    unverified.~\\
    Dates~are~compared~as~they~are~written,~so~this~one~compares~wrongly~rather~
    than~not~at~all.~Reported
  }
%    \end{macrocode}
%
% \begin{macro}{\loadsources}
% Reads \meta{file}\texttt{.bib}. The file is looked up the way \TeX{} looks up a file it is given, so it
% is found next to the document or anywhere on the input path; a file that is not there is an error and
% not an empty list of sources.
%    \begin{macrocode}
\NewDocumentCommand \loadsources { m }
  {
    \file_get_full_name:nNTF { #1 .bib } \l__regulatory_src_file_str
      { \__regulatory_src_read:V \l__regulatory_src_file_str }
      { \msg_error:nnn { regulatory-sources } { file-not-found } { #1 .bib } }
  }

\cs_new_protected:Npn \__regulatory_src_read:n #1
  {
    \int_zero:N \l__regulatory_src_line_int
    \bool_set_false:N \l__regulatory_src_open_bool
    \ior_open:Nn \g__regulatory_src_ior { #1 }
    \ior_str_map_inline:Nn \g__regulatory_src_ior
      { \__regulatory_src_line:nn { #1 } { ##1 } }
    \ior_close:N \g__regulatory_src_ior
    \bool_if:NT \l__regulatory_src_open_bool
      {
        \msg_error:nnxx { regulatory-sources } { unclosed }
          { \l__regulatory_src_key_str } { #1 }
      }
  }
\cs_generate_variant:Nn \__regulatory_src_read:n { V }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection*{Reading one line}
%
% \verb|\__regulatory_src_line:nn|
% One line of the file, tried against the four shapes the subset knows. The order is the order they occur
% in: a comment or a blank line first, since a file holds more of those than anything else.
%    \begin{macrocode}
\regex_const:Nn \c__regulatory_src_blank_regex { \A \s* (\%.*)? \Z }
\regex_const:Nn \c__regulatory_src_open_regex
  { \A \s* \@ (\w+) \s* \{ \s* ([^,\s\{\}]+) \s* ,? \s* \Z }
\regex_const:Nn \c__regulatory_src_field_regex
  { \A \s* (\w+) \s* = \s* \{ (.*) \} \s* ,? \s* \Z }
\regex_const:Nn \c__regulatory_src_close_regex { \A \s* \} \s* ,? \s* \Z }

\cs_new_protected:Npn \__regulatory_src_pair:N #1
  {
    \tl_set:Nx \l__regulatory_src_one_tl
      { \seq_item:Nn \l__regulatory_src_parts_seq { 2 } }
    \tl_set:Nx \l__regulatory_src_two_tl
      { \seq_item:Nn \l__regulatory_src_parts_seq { 3 } }
    \exp_args:NVV #1 \l__regulatory_src_one_tl \l__regulatory_src_two_tl
  }

\cs_new_protected:Npn \__regulatory_src_line:nn #1#2
  {
    \int_incr:N \l__regulatory_src_line_int
    \regex_match:NnTF \c__regulatory_src_blank_regex { #2 }
      { }
      {
        \regex_extract_once:NnNTF \c__regulatory_src_open_regex { #2 }
          \l__regulatory_src_parts_seq
          { \__regulatory_src_pair:N \__regulatory_src_begin:nn }
          {
            \regex_extract_once:NnNTF \c__regulatory_src_field_regex { #2 }
              \l__regulatory_src_parts_seq
              { \__regulatory_src_pair:N \__regulatory_src_field:nn }
              {
                \regex_match:NnTF \c__regulatory_src_close_regex { #2 }
                  { \__regulatory_src_end: }
                  {
                    \msg_error:nnxxx { regulatory-sources } { unreadable }
                      { \int_use:N \l__regulatory_src_line_int } { #1 } { #2 }
                  }
              }
          }
      }
  }
%    \end{macrocode}
%
% \begin{macro}{\srcfield}
% \begin{macro}{\srctype}
% Reads one field of a source. Both are expandable and both give nothing for a field that is not there,
% which is safe precisely because a source cannot be declared without the fields its type requires: what
% is absent here is optional by construction.
%    \begin{macrocode}
\cs_new:Npn \__regulatory_src_read:nn #1#2
  { \prop_item:cn { g__regulatory_src_e_ #1 _prop } { #2 } }
\cs_generate_variant:Nn \__regulatory_src_read:nn { ee }

\cs_new:Npn \srcfield #1#2
  { \__regulatory_src_read:ee { #1 } { \regulatory@src@field@of { #2 } } }
\cs_new:Npn \srctype #1
  {
    \prop_item:Nn \g__regulatory_src_type_prop { #1 }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\srcregister}
% The register a source is worded in: the one its type declares, unless the entry says otherwise.
%    \begin{macrocode}
\cs_new:Npn \srcregister #1
  {
    \tl_if_blank:eTF { \srcfield { #1 } { register } }
      {
        \prop_item:Ne \g__regulatory_src_register_prop
          { \prop_item:Nn \g__regulatory_src_type_prop { #1 } }
      }
      { \srcfield { #1 } { register } }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifsourceexists}
% Whether \meta{key} was declared at all. The key is made into a string before it is looked for: the keys
% of a file were read as text, and a sequence compares what it holds character by character, category code
% and all\,---\,so a key typed in the document would never equal the same key read from a file.
%    \begin{macrocode}
\NewDocumentCommand \ifsourceexists { m m m }
  {
    \str_set:Nn \l__regulatory_src_query_str { #1 }
    \seq_if_in:NVTF \g__regulatory_src_keys_seq \l__regulatory_src_query_str
      { #2 } { #3 }
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{\translation{Registers}{Registers}}
%
% A citation is worded in the register of the instrument it points at, and every register has two systems:
% one written out in full and one shortened. Which of the two applies is a property of the place the
% citation stands in\,---\,the Leidraad has it in full in the running text and shortened in a footnote, and
% shortened as well when it stands between brackets in the running text\,---\,so the call decides and the
% document sets the default.
%
% Seven keys are enough to word a citation. Five of them are macros, and each of them is handed the macro
% to put its result in rather than expanding to it: writing an ordinal in words is work that
% \package{fmtcount} does with a command that cannot be expanded, and a citation is assembled before it is
% typeset so that it can be read back.
%
% \begin{labeling}{\texttt{separator}}
%     \item[\texttt{article}] the word before the number of an article.
%     \item[\texttt{number}] the number itself, which is where the colon notation of the civil code lives.
%     \item[\texttt{paragraph}] the paragraph, which Dutch calls a lid.
%     \item[\texttt{point}] the lettered point, which Dutch calls an onderdeel.
%     \item[\texttt{subpoint}] the level below that, which the standards call a subonderdeel.
%     \item[\texttt{separator}] what stands between the parts: a comma in full, a space when shortened.
%     \item[\texttt{determiner}] the article a name takes when neither the entry nor the kind of the
%         instrument says, which is a genitive in the registers of the Union: \enquote{der Verordnung},
%         \enquote{du règlement}.
%     \item[\texttt{connective}] what stands between the last part and the instrument: \enquote{connective} when written
%         out in full, nothing when shortened.
%     \item[\texttt{assemble}] how the parts are arranged: from the outside in, which is what a register
%         that leaves this out gets, or the other way round, which is what English does.
%     \item[\texttt{attachnum}] the shape the number of a paragraph takes when it hangs on its article
%         rather than standing on its own. Brackets in English, and around each of them where there is more
%         than one: \enquote{Article 6(1), (2) and (3)}, measured, against \enquote{paragraphs 1 and 2}
%         where the same paragraphs stand by themselves.
%     \item[\texttt{attach}] how that number is bound to the article, which in English is simply against
%         it. Only a register arranged the other way round needs either of these two.
%     \item[\texttt{source}] the instrument itself, named from the fields of its entry.
% \end{labeling}
%    \begin{macrocode}
\ExplSyntaxOff
\newcommand\regulatory@src@ordinal[1]{\ordinalstringnum{#1}}

\ExplSyntaxOn
\prop_new:N \g__regulatory_src_register_store_prop
\cs_generate_variant:Nn \prop_item:Nn { Ne }
%    \end{macrocode}
% Which registers were declared, in the order they were, so that the set of them can be read back. The
% store above is keyed by register, system and key at once, so it answers what a register says and not
% which registers there are, and the manual names them one by one. This is what lets the suite hold that
% list against the code rather than against the last time somebody looked.
%    \begin{macrocode}
\seq_new:N \g__regulatory_src_registers_seq

\cs_new_protected:Npn \__regulatory_src_register_put:nnnn #1#2#3#4
  { \prop_gput:Nnn \g__regulatory_src_register_store_prop { #1 / #2 / #3 } { #4 } }

\cs_new_protected:Npn \__regulatory_src_register_bare:nnn #1#2#3
  { \msg_error:nnnnn { regulatory-sources } { register-key-without-value } { #1 } { #2 } { #3 } }

\msg_new:nnn { regulatory-sources } { register-key-without-value }
  {
    The~key~`#3'~of~register~`#1'~(#2)~was~given~no~value.~\\
    Every~key~of~a~register~carries~one:~a~word,~a~number~format~or~an~arrangement.
  }

\NewDocumentCommand \newsourceregister { m m m }
  {
    \seq_if_in:NnF \g__regulatory_src_registers_seq { #1 }
      { \seq_gput_right:Nn \g__regulatory_src_registers_seq { #1 } }
    \keyval_parse:nnn
      { \__regulatory_src_register_bare:nnn { #1 } { full } }
      { \__regulatory_src_register_put:nnnn { #1 } { full } }
      { #2 }
    \keyval_parse:nnn
      { \__regulatory_src_register_bare:nnn { #1 } { short } }
      { \__regulatory_src_register_put:nnnn { #1 } { short } }
      { #3 }
  }

\cs_new:Npn \regsrc@get #1#2#3
  { \prop_item:Ne \g__regulatory_src_register_store_prop { #1 / #2 / #3 } }

\cs_new_protected:Npn \regsrc@set #1#2#3#4
  {
    \prop_get:NeNF \g__regulatory_src_register_store_prop { #1 / #2 / #3 } #4
      { \cs_set_eq:NN #4 \relax }
  }
\cs_generate_variant:Nn \prop_get:NnNF { NeNF }
\ExplSyntaxOff
%    \end{macrocode}
%
% The register of the Dutch legislator, which is also the one a Dutch author writes in. In full it is the
% form the Aanwijzingen voor de regelgeving prescribe for regulations themselves\,---\,a model rather than
% a rule for a document that is not a regulation, since those instructions bind ministries and not
% contracts. Shortened it is the form of the Leidraad: no commas, the designation before the number, and
% the colon notation for the civil code.
%    \begin{macrocode}



% Where the designation stands: before its numbers in nearly every register, after
% them where a paragraph is written as an ordinal.
\newcommand\regulatory@src@before[3]{\def#1{#3~#2}}
\newcommand\regulatory@src@after[3]{\def#1{#2\space#3}}

% One number, in the shape its level takes.
\newcommand\regulatory@src@num@plain[2]{\def#1{#2}}
\newcommand\regulatory@src@num@paren[2]{\def#1{#2)}}
\newcommand\regulatory@src@num@degree[2]{\def#1{#2\textdegree}}
\newcommand\regulatory@src@num@parens[2]{\def#1{(#2)}}

% A paragraph written into the article it belongs to, which is the English form.
\newcommand\regulatory@src@attach@plain[3]{\def#1{#2#3}}
\newcommand\regulatory@src@num@ordinal[2]{%
    \storeordinalstringnum{regsrc}{#2}%
    \expandafter\let\expandafter\regulatory@src@ord\csname @fcs@regsrc\endcsname
    \let#1\regulatory@src@ord
}
\newcommand\regulatory@src@num@unmeasured[2]{%
    \PackageWarning{regulatory-sources}{%
        This register has no measured form for the level below a point,\MessageBreak
        so the number is written on its own. Reported}%
    \def#1{#2}%
}

\newcommand\regulatory@src@paragraph@absatz[2]{\def#1{Absatz~#2}}
\newcommand\regulatory@src@paragraph@paragraphe[2]{\def#1{paragraphe~#2}}
\newcommand\regulatory@src@point@buchstabe[2]{\def#1{Buchstabe~#2}}
\newcommand\regulatory@src@point@point[2]{\def#1{point~#2)}}
%    \end{macrocode}
%
% Which article a name takes is not a property of the register but of the instrument, and the entry
% already says which instrument it is. Counted in the same regulation: \enquote{de la directive} sixteen
% times against \enquote{du règlement} seven, so a single default for French is wrong more often than it
% is right, and \enquote{du directive} is not a matter of style but of grammar. German is the same story
% one step further: \enquote{der} carries Verordnung and Richtlinie but not Beschluss or Vertrag, which
% take \enquote{des}.
%
% So the determiner is looked up by the kind of the instrument, and the \texttt{determiner} field of an
% entry overrides that for the case no table can know.
%    \begin{macrocode}
%    \end{macrocode}
%
% The pieces the registers above are built from. A number carries the book of the civil code in the
% shortened form and leaves it to the name of the instrument in the full one, which is what
% \enquote{artikel 96 \dots{} van Boek 6 van het Burgerlijk Wetboek} against \enquote{art. 6:96 BW} comes
% down to.
%    \begin{macrocode}
\newcommand\regulatory@src@number@plain[3]{\def#1{#3}}
\newcommand\regulatory@src@number@colon[3]{%
    \ifthenelse{\equal{#2}{}}{\def#1{#3}}{\def#1{#2:#3}}%
}
%    \end{macrocode}
%
% The ordinal keeps an ordinary space between the number and the word it belongs to. The regulation binds
% a label to its number with a space that does not break, but it writes its numbers after the label,
% \texttt{lid 6}, and never as an ordinal: \emph{zesde lid} does not occur in it once. What binds
% \emph{zesde} to \emph{lid} in the national register is therefore not measured, and this bundle does not
% decide it.
%    \begin{macrocode}
\newcommand\regulatory@src@source@full@store[2]{%
    \protected@edef#1{\regulatory@src@source@full{#2}}%
}
\newcommand\regulatory@src@source@short@store[2]{%
    \protected@edef#1{\regulatory@src@source@short{#2}}%
}

\ExplSyntaxOn
\prop_new:N \g__regulatory_src_determiner_prop
\tl_new:N \l__regulatory_src_det_tl
\tl_new:N \l__regulatory_src_kind_tl
\cs_generate_variant:Nn \str_lowercase:n { V }

\NewDocumentCommand \newsourcedeterminer { m m m }
  {
    \tl_set:Nx \l__regulatory_src_kind_tl { #1 / \str_lowercase:n { #2 } }
    \prop_gput:NVn \g__regulatory_src_determiner_prop \l__regulatory_src_kind_tl { #3 }
  }
%    \end{macrocode}
%
% Worked out before the citation is built rather than while it is: the entry decides first, then the kind
% of the instrument, then the default of the register. Doing it here rather than in an expandable macro
% keeps the lookup a plain lookup.
%    \begin{macrocode}
\cs_new_protected:Npn \regulatory@src@setdet #1
  {
    \tl_set:Nx \l__regulatory_src_det_tl { \srcfield { #1 } { determiner } }
    \tl_if_blank:VT \l__regulatory_src_det_tl
      {
        \tl_set:Nx \l__regulatory_src_kind_tl { \srcfield { #1 } { kind } }
        \tl_set:Nx \l__regulatory_src_kind_tl
          {
            \regulatory@src@reg /
            \str_lowercase:V \l__regulatory_src_kind_tl
          }
        \tl_set:Nx \l__regulatory_src_det_tl
          {
            \exp_args:NNV \prop_item:Nn
              \g__regulatory_src_determiner_prop \l__regulatory_src_kind_tl
          }
      }
    \tl_if_blank:VT \l__regulatory_src_det_tl
      { \tl_set:Nx \l__regulatory_src_det_tl { \regulatory@src@defdet } }
    \tl_set_eq:NN \regulatory@src@thisdet \l__regulatory_src_det_tl
  }

\cs_new:Npn \regulatory@src@determiner #1 { \regulatory@src@thisdet }
\ExplSyntaxOff
\ExplSyntaxOn

\cs_new:Npn \regulatory@src@naam #1
  {
    \tl_if_blank:eTF { \srcfield { #1 } { shortname } }
      { \srcfield { #1 } { citetitle } } { \srcfield { #1 } { shortname } }
  }
\cs_new:Npn \regulatory@src@source@full #1
  {
    \tl_if_blank:eF { \srcfield { #1 } { book } }
      { Boek~ \srcfield { #1 } { book } \c_space_tl van~ }
    \tl_if_blank:eF { \regulatory@src@determiner { #1 } }
      { \regulatory@src@determiner { #1 } ~ }
    \regulatory@src@naam { #1 }
  }
\cs_new:Npn \regulatory@src@source@short #1
  {
    \tl_if_blank:eTF { \srcfield { #1 } { abbreviation } }
      { \regulatory@src@naam { #1 } } { \srcfield { #1 } { abbreviation } }
  }
\ExplSyntaxOff
\ExplSyntaxOn
%    \end{macrocode}
%
% \subsubsection{\translation{Where a register lives}{Waar een register staat}}
%
% Not here. A register is written in the language definition file of its language,
% \file{regulatory-\meta{language}.def}, next to the words that language calls a provision by. Those two
% are one measurement: what says that German writes \enquote{Artikel 6 Absatz 1 Buchstabe a} in a citation
% is the same reading of the same text that says it calls a paragraph an \emph{Absatz}. Keeping them apart
% would mean one measurement landing in two files, where it can drift.
%
% It also spares whoever writes one a second set of names. The language is \texttt{dutch} to
% \package{babel} and the register is \texttt{dutch} here, and \texttt{dutch\_eu} is that same language
% writing in the legal order of the Union.
%
% Those files are read for every language this bundle ships, whatever language the document is in, because
% a register belongs to the source and not to the document: a Dutch contract cites a German regulation in
% German. \zcref{sec:lang} has the loading rule.
%
% \subsubsection{\translation{Naming more than one}{Meer dan één noemen}}
%
% A citation may name a list of provisions or a run of them, which the source writes as
% \enquote{artikelen 101 en 102} and \enquote{artikelen 12 tot en met 15}. Both are written by the author
% rather than worked out here: \texttt{point=\{c,d\}} is a list and \texttt{point=\{a--c\}} is a
% run, and the register decides how either reads.
%
% The far end of a range does not always read like the near one: the civil code is cited as
% \enquote{art. 6:162-164}, where the book is named once and the second number stands on its own. A run
% therefore formats its two ends separately, and every other level hands the same format twice.
%
% Three things are counted apart because the register words them apart: the numbers, which each go through
% the format of their level; the words that join them; and the designation, which takes its plural as soon
% as there is more than one. Measured in the same regulation, with the non-breaking space where the source
% puts it: \enquote{artikelen~101 en~102}, \enquote{artikelen~12 tot en met~15}, \enquote{punten~c) en~e)},
% \enquote{Buchstaben~c und e}, \enquote{Absätze~1, 2 und~3}, \enquote{paragraphes~1 et 4}.
%    \begin{macrocode}
\ExplSyntaxOn
\seq_new:N \l__regulatory_src_items_seq
\tl_new:N \l__regulatory_src_joined_tl
\int_new:N \l__regulatory_src_count_int

\cs_new_protected:Npn \regulatory@src@join #1#2#3#4#5#6
  {
    \tl_clear:N \l__regulatory_src_joined_tl
    \tl_if_in:nnTF { #2 } { -- }
      { \__regulatory_src_range:nnnn { #2 } { #3 } { #6 } { #5 } }
      { \__regulatory_src_list:nnn { #2 } { #3 } { #4 } }
    \tl_set_eq:NN #1 \l__regulatory_src_joined_tl
  }

\cs_new_protected:Npn \__regulatory_src_range:nnnn #1#2#3#4
  {
    \seq_set_split:Nnn \l__regulatory_src_items_seq { -- } { #1 }
    \int_set:Nn \l__regulatory_src_count_int { 2 }
    \seq_pop_left:NN \l__regulatory_src_items_seq \l_tmpa_tl
    \exp_args:NNV #2 \l__regulatory_src_piece_tl \l_tmpa_tl
    \tl_put_right:NV \l__regulatory_src_joined_tl \l__regulatory_src_piece_tl
    \tl_put_right:Nn \l__regulatory_src_joined_tl { #4 }
    \seq_pop_left:NN \l__regulatory_src_items_seq \l_tmpa_tl
    \exp_args:NNV #3 \l__regulatory_src_piece_tl \l_tmpa_tl
    \tl_put_right:NV \l__regulatory_src_joined_tl \l__regulatory_src_piece_tl
  }

\cs_new_protected:Npn \__regulatory_src_list:nnn #1#2#3
  {
    \seq_set_split:Nnn \l__regulatory_src_items_seq { , } { #1 }
    \seq_set_map_x:NNn \l__regulatory_src_items_seq \l__regulatory_src_items_seq
      { \tl_trim_spaces:n { ##1 } }
    \int_set:Nn \l__regulatory_src_count_int
      { \seq_count:N \l__regulatory_src_items_seq }
    \int_step_inline:nnn { 1 } { \l__regulatory_src_count_int }
      {
        \int_compare:nNnT { ##1 } > { 1 }
          {
            \int_compare:nNnTF { ##1 } = { \l__regulatory_src_count_int }
              { \tl_put_right:Nn \l__regulatory_src_joined_tl { #3 } }
              { \tl_put_right:Nn \l__regulatory_src_joined_tl { ,~ } }
          }
        \tl_set:Nx \l_tmpa_tl { \seq_item:Nn \l__regulatory_src_items_seq { ##1 } }
        \exp_args:NNV #2 \l__regulatory_src_piece_tl \l_tmpa_tl
        \tl_put_right:NV \l__regulatory_src_joined_tl \l__regulatory_src_piece_tl
      }
  }

\tl_new:N \l__regulatory_src_piece_tl
\cs_new:Npn \regulatory@src@items { \int_use:N \l__regulatory_src_count_int }
\ExplSyntaxOff
%    \end{macrocode}
%
% \subsubsection{\translation{Citing a source}{Een bron aanhalen}}
%
% \begin{macro}{\srcref}
% Cites \meta{key}, either as a whole or down to one of its provisions. The optional argument holds the
% provision\,---\,\texttt{article}, \texttt{paragraph}, \texttt{point} and \texttt{subpoint}\,---\,and stands
% before the key, as it does in \cmd{\cite}, so that a bracket in the sentence after the citation is not
% mistaken for it.
%
% The star asks for the system that is not the default of the document, which is what a citation between
% brackets or in a footnote wants. It may also be named outright with \texttt{system}. The default of the
% document is the \option{sourcestyle} option, and it is \texttt{full}, since that is what the running text
% of a document is.
%
% What it comes to is built up in \cmd{\regulatory@src@last} before it is typeset, so that the wording of a
% citation can be read back rather than only looked at. That is what the test suite asserts on: a citation
% in the wrong register fails nowhere, it simply stands there wrong.
%    \begin{macrocode}
\ExplSyntaxOff
\newcommand\regulatory@src@system{\regulatory@sourcestyle}

%    \end{macrocode}
% The Dutch names are meta keys, and the value of a meta key is braced on the way through: a meta key sets
% its target by running the key parser again, so \texttt{onderdeel=\{c,d\}} would arrive as two keys, of
% which the second is a key named \texttt{d} that does not exist. Measured: without the braces the list and
% range citations lost their second item and \LaTeX{} said only that a key was unknown, naming a letter.
%    \begin{macrocode}
\ExplSyntaxOn
\keys_define:nn { regulatory / srcref }
  {
    article   .code:n = \def \regulatory@src@article    { #1 } ,
    paragraph .code:n = \def \regulatory@src@paragraph  { #1 } ,
    point     .code:n = \def \regulatory@src@point      { #1 } ,
    subpoint  .code:n = \def \regulatory@src@subpoint   { #1 } ,
    system    .code:n = \def \regulatory@src@thissystem { #1 } ,
    date      .code:n = \tl_set:Nn \l__regulatory_src_thisdate_tl { #1 } ,
    datum     .meta:n = { date      = {#1} } ,
    artikel   .meta:n = { article   = {#1} } ,
    lid       .meta:n = { paragraph = {#1} } ,
    onderdeel .meta:n = { point     = {#1} } ,
    onder     .meta:n = { subpoint  = {#1} } ,
  }
\cs_new_protected:Npn \regulatory@src@setkeys #1
  { \keys_set:nn { regulatory / srcref } { #1 } }
\ExplSyntaxOff

%    \end{macrocode}
%
% \begin{macro}{\sourcedate}
% The date a citation speaks as of. A reference to legislation is a reference to a \emph{version} of it:
% the same article read a year apart is not necessarily the same article, and the Juriconnect standard says
% so by carrying the date in the reference itself. This bundle does not print the date and does not build
% the link yet, but it refuses to let a document leave it unsaid, because the alternative is a citation
% that silently means \enquote{whenever this was last typeset}.
%
% It is a warning and not an error on purpose: a document that cites without a date is defective, but it is
% not broken, and a package that cannot be added to an existing document without stopping it is a package
% that does not get added. The warning is said once, and names the command that answers it.
%
% An entry may carry a \texttt{valid} field, which is the date the data of that entry was last checked.
% When the document speaks as of a later date than that, the entry cannot vouch for itself and says so,
% once per source. That is what makes a shared file of sources safe to use at all, wherever it is kept: the
% identifiers in it never age, the dates do, and a document that outruns the data it was handed is told
% rather than quietly given whatever the last update to that file happened to contain. This bundle ships
% no legislation itself and is not the place for it\,---\,a citeertitel changes on its own clock and a
% package on CTAN does not\,---\,but it is the place for the machinery that says when the two have come
% apart.
%    \begin{macrocode}
\ExplSyntaxOn
\tl_new:N \g__regulatory_src_date_tl
\tl_new:N \l__regulatory_src_thisdate_tl
\seq_new:N \g__regulatory_src_dated_seq
\bool_new:N \g__regulatory_src_nodate_bool

\regex_const:Nn \c__regulatory_src_date_regex { \A \d{4}-\d{2}-\d{2} \Z }

\msg_new:nnn { regulatory-sources } { date-not-iso }
  {
    The~date~`#1'~is~not~of~the~form~YYYY-MM-DD.~\\
    Dates~are~compared~as~they~are~written,~so~another~form~would~compare~wrongly~
    rather~than~not~at~all.
  }

\NewDocumentCommand \sourcedate { m }
  {
    \regex_match:NnTF \c__regulatory_src_date_regex { #1 }
      { \tl_gset:Nn \g__regulatory_src_date_tl { #1 } }
      { \msg_error:nnn { regulatory-sources } { date-not-iso } { #1 } }
  }

\cs_new_protected:Npn \__regulatory_src_checkdate:n #1
  {
    \tl_if_empty:NT \l__regulatory_src_thisdate_tl
      { \tl_set_eq:NN \l__regulatory_src_thisdate_tl \g__regulatory_src_date_tl }
    \tl_if_empty:NTF \l__regulatory_src_thisdate_tl
      {
        \bool_if:NF \g__regulatory_src_nodate_bool
          {
            \bool_gset_true:N \g__regulatory_src_nodate_bool
            \msg_warning:nn { regulatory-sources } { no-date }
          }
      }
      { \__regulatory_src_checkstale:n { #1 } }
  }

\cs_new_protected:Npn \__regulatory_src_checkstale:n #1
  {
    \tl_set:Nx \l__regulatory_src_valid_tl { \srcfield { #1 } { valid } }
    \tl_if_empty:NF \l__regulatory_src_valid_tl
      {
        \str_compare:eNeT \l__regulatory_src_thisdate_tl > \l__regulatory_src_valid_tl
          {
            \seq_if_in:NnF \g__regulatory_src_dated_seq { #1 }
              {
                \seq_gput_right:Nn \g__regulatory_src_dated_seq { #1 }
                \msg_warning:nnxxx { regulatory-sources } { stale-source }
                  { #1 } { \l__regulatory_src_valid_tl } { \l__regulatory_src_thisdate_tl }
              }
          }
      }
  }
\cs_generate_variant:Nn \str_compare:nNnT { eNeT }

\msg_new:nnn { regulatory-sources } { no-date }
  {
    This~document~cites~legislation~without~saying~as~of~when.~\\
    Put~\iow_char:N\\sourcedate\{YYYY-MM-DD\}~in~the~preamble,~or~give~one~
    citation~its~own~with~date=YYYY-MM-DD.~Reported
  }

\msg_new:nnn { regulatory-sources } { stale-source }
  {
    The~source~`#1'~was~last~checked~on~#2,~and~this~document~speaks~as~of~#3.~\\
    Whatever~changed~in~between~is~not~in~this~citation.~Reported
  }
\cs_new_protected:Npn \regulatory@src@checkdate #1
  { \__regulatory_src_checkdate:n { #1 } }
\cs_new_protected:Npn \regulatory@src@cleardate
  { \tl_clear:N \l__regulatory_src_thisdate_tl }
\ExplSyntaxOff
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
\newcommand\regulatory@src@thislabel{}
\newcommand\regulatory@src@label[2]{%
    \ifnum\regulatory@src@items>1
        \edef\regulatory@src@thislabel{%
            \regsrc@get{\regulatory@src@reg}{\regulatory@src@thissystem}{#2}}%
    \else
        \edef\regulatory@src@thislabel{%
            \regsrc@get{\regulatory@src@reg}{\regulatory@src@thissystem}{#1}}%
    \fi
}

\newcommand\regulatory@src@last{}
\newcommand\regulatory@src@part[1]{%
    \ifx\regulatory@src@parts\@empty\else
        \protected@xdef\regulatory@src@last{\regulatory@src@last\regulatory@src@sep}%
    \fi
    \protected@xdef\regulatory@src@last{\regulatory@src@last#1}%
    \let\regulatory@src@parts\relax
}
%    \end{macrocode}
%
% Every level puts what it comes to in a macro of its own, worked out to the last token there and then,
% rather than straight into the citation. Worked out, because the designation of a level lives in one macro
% that every level writes to in turn, and a part that kept the macro rather than its text would read the
% word of whatever level came after it. Its own macro, because
% where the parts stand with respect to one another is a decision of the register and not of this module.
% Nearly every register names them from the outside in\,---\,the article, then the paragraph, then the
% point\,---\,and joins them with its separator. English does the reverse, and measured in the English text
% of the same regulation it is not close: \enquote{point (a) of Article 6(1)} twenty-eight times against
% nothing at all for either of the two arrangements the other registers use. So the deepest level comes
% first, each level is joined to the next with \enquote{of}, and the paragraph is not named but written
% into the article between brackets.
%
% Two arrangements are therefore offered and the \texttt{assemble} key of a register picks one. A register
% that says nothing is arranged from the outside in, which is what all four of the others do.
%    \begin{macrocode}
\newcommand\regulatory@src@p@article{}
\newcommand\regulatory@src@p@paragraph{}
\newcommand\regulatory@src@p@paragraphnum{}
\newcommand\regulatory@src@p@point{}
\newcommand\regulatory@src@p@subpoint{}
\newcommand\regulatory@src@p@source{}

\newcommand\regulatory@src@add[1]{%
    \ifx#1\@empty\else\expandafter\regulatory@src@part\expandafter{#1}\fi
}

\newcommand\regulatory@src@assemble@forward{%
    \regulatory@src@add\regulatory@src@p@article
    \regulatory@src@add\regulatory@src@p@paragraph
    \regulatory@src@add\regulatory@src@p@point
    \regulatory@src@add\regulatory@src@p@subpoint
    \ifx\regulatory@src@parts\@empty\else
        \protected@edef\regulatory@src@p@source{%
            \regulatory@src@connective\regulatory@src@p@source}%
    \fi
    \regulatory@src@add\regulatory@src@p@source
}
%    \end{macrocode}
%
% The other way round, with one thing more to do than turning the order about: a paragraph that hangs on an
% article is written \texttt{(1)} and takes no word, while one that stands on its own keeps its word,
% \enquote{point (a) of paragraph 1}. Both occur in the same regulation, so the register hands over the
% shape of the attached one in \texttt{attach} and the level keeps its own wording for the other case.
%    \begin{macrocode}
\newcommand\regulatory@src@assemble@backward{%
    \ifx\regulatory@src@p@article\@empty\else
        \ifx\regulatory@src@p@paragraphnum\@empty\else
            \ifx\regulatory@src@attach\relax\else
                \protected@edef\@@attachnow{%
                    \noexpand\regulatory@src@attach
                        \noexpand\regulatory@src@p@article
                        {\regulatory@src@p@article}{\regulatory@src@p@paragraphnum}}%
                \@@attachnow
                \let\regulatory@src@p@paragraph\@empty
            \fi
        \fi
    \fi
    \regulatory@src@add\regulatory@src@p@subpoint
    \regulatory@src@add\regulatory@src@p@point
    \regulatory@src@add\regulatory@src@p@paragraph
    \regulatory@src@add\regulatory@src@p@article
    \regulatory@src@add\regulatory@src@p@source
}

\NewDocumentCommand \srcref { s O{} m }{%
    \begingroup
        \def\regulatory@src@article{}%
        \def\regulatory@src@paragraph{}%
        \def\regulatory@src@point{}%
        \def\regulatory@src@subpoint{}%
        \IfBooleanTF{#1}{%
            \ifthenelse{\equal{\regulatory@sourcestyle}{full}}{%
                \def\regulatory@src@thissystem{short}%
            }{%
                \def\regulatory@src@thissystem{full}%
            }%
        }{%
            \edef\regulatory@src@thissystem{\regulatory@sourcestyle}%
        }%
        \regulatory@src@cleardate
        \regulatory@src@setkeys{#2}%
        \regulatory@src@checkdate{#3}%
        \edef\regulatory@src@reg{\srcregister{#3}}%
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{separator}%
            {\regulatory@src@sep}%
        \edef\regulatory@src@defdet{%
            \regsrc@get{\regulatory@src@reg}{\regulatory@src@thissystem}{determiner}}%
        \regulatory@src@setdet{#3}%
        \let\regulatory@src@parts\@empty
        \gdef\regulatory@src@last{}%
        \let\regulatory@src@p@article\@empty
        \let\regulatory@src@p@paragraph\@empty
        \let\regulatory@src@p@paragraphnum\@empty
        \let\regulatory@src@p@point\@empty
        \let\regulatory@src@p@subpoint\@empty
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{and}%
            {\regulatory@src@and}%
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{to}%
            {\regulatory@src@to}%
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{connective}%
            {\regulatory@src@connective}%
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{attach}%
            {\regulatory@src@attach}%
        \ifx\regulatory@src@article\@empty\else
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{articlenum}{\@@fmt}%
            \def\@@numfmt##1##2{\@@fmt##1{\srcfield{#3}{book}}{##2}}%
            \def\@@numrest##1##2{\@@fmt##1{}{##2}}%
            \expandafter\regulatory@src@join\expandafter\regulatory@src@piece
                \expandafter{\regulatory@src@article}{\@@numfmt}%
                {\regulatory@src@and}{\regulatory@src@to}{\@@numrest}%
            \regulatory@src@label{articleone}{articlemany}%
            \protected@edef\regulatory@src@p@article{%
                \regulatory@src@thislabel~\regulatory@src@piece}%
        \fi
        \ifx\regulatory@src@paragraph\@empty\else
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{paragraphnum}{\@@fmt}%
            \expandafter\regulatory@src@join\expandafter\regulatory@src@piece
                \expandafter{\regulatory@src@paragraph}{\@@fmt}%
                {\regulatory@src@and}{\regulatory@src@to}{\@@fmt}%
            \regulatory@src@label{paragraphone}{paragraphmany}%
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{paragraph}{\@@compose}%
            \expandafter\@@compose\expandafter\regulatory@src@p@paragraph
                \expandafter{\regulatory@src@piece}{\regulatory@src@thislabel}%
            \protected@edef\regulatory@src@p@paragraph{\regulatory@src@p@paragraph}%
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{attachnum}{\@@afmt}%
            \ifx\@@afmt\relax
                \let\regulatory@src@p@paragraphnum\regulatory@src@piece
            \else
                \expandafter\regulatory@src@join\expandafter\regulatory@src@p@paragraphnum
                    \expandafter{\regulatory@src@paragraph}{\@@afmt}%
                    {\regulatory@src@and}{\regulatory@src@to}{\@@afmt}%
            \fi
        \fi
        \ifx\regulatory@src@point\@empty\else
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{pointnum}{\@@fmt}%
            \expandafter\regulatory@src@join\expandafter\regulatory@src@piece
                \expandafter{\regulatory@src@point}{\@@fmt}%
                {\regulatory@src@and}{\regulatory@src@to}{\@@fmt}%
            \regulatory@src@label{pointone}{pointmany}%
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{point}{\@@compose}%
            \expandafter\@@compose\expandafter\regulatory@src@p@point
                \expandafter{\regulatory@src@piece}{\regulatory@src@thislabel}%
            \protected@edef\regulatory@src@p@point{\regulatory@src@p@point}%
        \fi
        \ifx\regulatory@src@subpoint\@empty\else
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{subpointnum}{\@@fmt}%
            \expandafter\regulatory@src@join\expandafter\regulatory@src@piece
                \expandafter{\regulatory@src@subpoint}{\@@fmt}%
                {\regulatory@src@and}{\regulatory@src@to}{\@@fmt}%
            \regulatory@src@label{subpointone}{subpointmany}%
            \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{subpoint}{\@@compose}%
            \expandafter\@@compose\expandafter\regulatory@src@p@subpoint
                \expandafter{\regulatory@src@piece}{\regulatory@src@thislabel}%
            \protected@edef\regulatory@src@p@subpoint{\regulatory@src@p@subpoint}%
        \fi
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{source}{\@@fmt}%
        \@@fmt\regulatory@src@p@source{#3}%
        \regsrc@set{\regulatory@src@reg}{\regulatory@src@thissystem}{assemble}%
            {\regulatory@src@assembler}%
        \ifx\regulatory@src@assembler\relax
            \let\regulatory@src@assembler\regulatory@src@assemble@forward
        \fi
        \regulatory@src@assembler
    \endgroup
    \regulatory@src@last
}
\ExplSyntaxOn
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\regulatory@src@messages}
% What the module says when it stops. Every one of these names the record it was reading, since a bib file
% that is wrong is wrong in one entry and the rest of it is fine.
%    \begin{macrocode}
\msg_new:nnn { regulatory-sources } { unknown-type }
  {
    Source~'#2'~is~of~type~'#1',~which~no~one~declared.~Declare~it~with~
    \iow_char:N\\newsourcetype,~or~use~one~of:~
    \prop_map_function:NN \g__regulatory_src_required_prop
      \__regulatory_src_type_name:nn
  }
\cs_new:Npn \__regulatory_src_type_name:nn #1#2 { ~#1 }

\msg_new:nnn { regulatory-sources } { missing-field }
  {
    Source~'#2'~of~type~'#3'~has~no~'#1'.~A~source~of~that~type~cannot~be~
    written~out~without~it.
  }
\msg_new:nnn { regulatory-sources } { duplicate-key }
  { Source~'#1'~was~already~declared.~The~second~one~would~replace~it. }
\msg_new:nnn { regulatory-sources } { stray-field }
  { Field~'#1'~stands~outside~any~entry. }
\msg_new:nnn { regulatory-sources } { no-value }
  { Field~'#1'~was~given~no~value. }
\msg_new:nnn { regulatory-sources } { file-not-found }
  { There~is~no~file~'#1'~to~read~sources~from. }
\msg_new:nnn { regulatory-sources } { unclosed }
  { Source~'#1'~is~still~open~at~the~end~of~'#2'.~A~closing~brace~is~missing. }
\msg_new:nnn { regulatory-sources } { unreadable }
  {
    Line~#1~of~'#2'~is~none~of~the~four~shapes~this~reader~knows:\\
    ~~#3\\
    An~entry~opens~with~an~at~sign,~the~type~and~the~key;~a~field~reads~
    name~=~{value};~an~entry~closes~with~a~brace~of~its~own.~Each~of~the~three~
    stands~on~a~line~of~its~own,~and~a~value~is~in~braces~and~not~in~quotes:~
    this~is~a~restricted~syntax~and~not~a~BibTeX~parser.
  }
\ExplSyntaxOff
%    \end{macrocode}
% \end{macro}
% \iffalse
%</package>
% \fi
%
% \Finale
%
