%%  Copyright 2013-2022 Christian Dietrich
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% 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.3 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 Christian Dietrich
%%
%% This work consists of the files dataref.dtx and dataref.ins
%% and the derived file dataref.sty.
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{dataref}[2022/03/25 v0.7 dataref]

\ifx\drefloaded\undefined
  \let\drefloaded=\relax
\else
  \expandafter\endinput
\fi

\def\drefutil@packageerror#1#2#3{\errhelp{#3}\errmessage{Package #1 Error: #2}}
\def\drefutil@packagewarning#1#2{\immediate\write17{Package #1: Warning! #2.}}
\def\dref@error#1{\drefutil@packageerror{dref}{#1}{}}
\def\dref@warning#1{\drefutil@packagewarning{dref}{#1}}

\RequirePackage{pgf}
\usepgflibrary{fpu}
\RequirePackage{iftex}
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
\RequirePackage{import}



\SetupKeyvalOptions{
  family=dref,
  prefix=dref@
}
\DeclareStringOption[/data]{datapath}
\DeclareStringOption[1]{defaultvalue}
\DeclareStringOption[none]{annotate}
\DeclareBoolOption{usagereport}
\DeclareBoolOption{refall}
\DeclareBoolOption{ignoremissing}
\DeclareBoolOption{noassert}
\ProcessKeyvalOptions*

% Load & Store Layer

% \dref@xdef is only used in \dref@set
\let\dref@xdef=\xdef % \dref@xdef is overridden in case of listadd

\def\dref@set#1#2#3{%
  \edef\dref@set@path{#3}%
  \edef\dref@set@value{#2}%
  \expandafter\pgfkeys@temptoks\expandafter{\dref@set@value}%
  \expandafter\dref@xdef%
      \csname pgfk@\dref@datapath\dref@set@path\endcsname%
  {\the\pgfkeys@temptoks}%
  % Setting the Unit is a little bit more tricky
  %% Unit Path Assembly
  \expandafter\def%
  \expandafter\dref@set@unitpath%
  \expandafter{%
  \csname pgfk@\dref@datapath\dref@set@path @unit\endcsname}%
  \expandafter\gdef\dref@set@unitpath{#1}%
  \ifdref@refall%
     \expandafter\dref@found\expandafter{\dref@set@path}{0}
     \expandafter\dref@referenced\expandafter{\dref@set@path}{0}%
  \fi%
  \dref@debug{\dref@set@path = \dref@set@value (\detokenize{#1})}%
}

\def\dref@load#1#2#3{%
  \edef\dref@load@path{#1}%
  \pgfkeysifdefined{\dref@datapath\dref@load@path}{%
    \pgfkeysgetvalue{\dref@datapath\dref@load@path}{#2}%
    \pgfkeysifdefined{\dref@datapath\dref@load@path @unit}{%
      \pgfkeysgetvalue{\dref@datapath\dref@load@path @unit}{#3}%
    }{%
      \def#3{}%
    }%
  }{%
    \edef#2{\dref@defaultvalue}%
    \def#3{}%
  }%
}

% List Looping. We define this upfront, as we have to build a pgfk@
% name here. The @loop@do macro is a helper to invoke list/do with the
% list element. dref@loop uses the etoolbox for looping feature.
\def\dref@loop@do#1{\drefkeys{list/do={#1}}}
\def\dref@loop#1{%
  \forlistcsloop{\dref@loop@do}{%
      pgfk@\dref@datapath #1%
  }%
}

\def\drefifdefined#1{%
  \pgfkeysifdefined{\dref@datapath\drefprefix #1}%{then}{else}
}

\def\dref@set@fromaux#1#2#3{%
  \drefifdefined{#2}{%
    \dref@warning{"\drefprefix #2" set before beginning of document, \string\drefsave{} is ignore}%
  }{%
    \dref@set{#1}{#2}{#3}%
  }%
}

\def\drefkeys#1{\pgfkeys{/dref/.cd,#1}}
\def\drefprefix{\pgfkeysvalueof{/dref/prefix}}
\newif\ifdref@debug
\def\dref@debug#1{\ifdref@debug \immediate\write17{Package dref: Debug: #1.}\fi}

\drefkeys{
  .is family,
  .search also={/pgf/number format},
  % The @init action is used to initialize all other actions
  @[/.code={\begingroup%
    % /pgf/fpu: \pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}% No more dimensions too large
    \def\drefunit{}% At first we are unitless
    \aftergroup\edef%
    \aftergroup\drefresult%
    \aftergroup{%
      \aftergroup\drefresult@smuggle%
      \aftergroup}%
    \aftergroup\expandafter%
    \aftergroup\def%
    \aftergroup\expandafter%
    \aftergroup\drefunit%
    \aftergroup\expandafter%
    \aftergroup{%
      \aftergroup\drefunit@smuggle%
      \aftergroup}
  },
  @]/.code={% We smuggle \drefresult after the current group
    \xdef\drefresult@smuggle{\drefresult}%
    \xdef\drefunit@smuggle{\expandonce\drefunit}%
    \endgroup%
  },
  @init/.style={},
  % The \drefresult macro holds the current value,
  % it can be set by value=
  prefix/.initial={},
  value/.code={\edef\drefresult{#1}\def\drefunit{}},
  value=0,
  path/.estore in={\drefcurrentpath},
  @init/.append style={},
  % \drefresult can be set by the @load action
  @load key to/.code n args={3}{%
    \dref@load{\drefprefix #1}{#2}{#3}%
  },
  @get key to/.style n args={3}{
    @check key={#1},
    @reference key={#1},
    @load key to={#1}{#2}{#3},
  },
  @get/.style={%
    @get key to={\drefcurrentpath}{\drefresult}{\drefunit},
    unit/@format enable,
  },
  % For most commands, we want to check whether a key exists.
  @check key/.code={%
    \drefifdefined{#1}{}{%
      \ifdref@ignoremissing%
        \dref@warning{undefined key `\drefprefix #1'}%
      \else%
        \dref@error{undefined key `\drefprefix #1'}%
      \fi%
    }%
  },
  % The @set action is used to pipe out \drefresult, before we can
  % print it. For example, we can use it to save the result to a new
  % key.
  @init/.append style={
    @set/.code={},
  },
  set/.style={
    @set/.append code={%
      \expandafter\dref@set\expandafter{\drefunit}{\drefresult}{\drefprefix #1}%
    }
  },
  save/.style={
    set={#1},
    @set/.append code={%
      \immediate\write\@auxout{%
        \noexpand\dref@set@fromaux{\expandonce\drefunit}{\drefresult}{\drefprefix #1}%
      }%
    }
  },
  to macro/.style={
    @set/.append code={%
      \aftergroup\edef%
      \aftergroup#1%
      \aftergroup{%
        \aftergroup\drefresult%
        \aftergroup}}
  },
  % List Keys
  list/append/.code={\let\dref@xdef=\listxadd},
  % Apply loop/do for every item
  list/loop/.code={%
    \dref@loop{\drefprefix #1}
  },
  % Various Keys
  debug/.is if=dref@debug,
  ignoremissing/.is if=dref@ignoremissing,
  defaultvalue/.store in=\dref@defaultvalue,
}

\csdef{dref@ifnum@0}{}
\csdef{dref@ifnum@1}{}
\csdef{dref@ifnum@2}{}
\csdef{dref@ifnum@3}{}
\csdef{dref@ifnum@4}{}
\csdef{dref@ifnum@5}{}
\csdef{dref@ifnum@6}{}
\csdef{dref@ifnum@7}{}
\csdef{dref@ifnum@8}{}
\csdef{dref@ifnum@9}{}
\csdef{dref@ifnum@-}{}
\csdef{dref@ifnum@.}{}
\def\dref@load@ifkey@firstchar#1#2\@nnil{#1}
\drefkeys{%
  @get key or value to/.code n args={3}{%
    \edef\dref@load@path{#1}%
    \edef\dref@firstchar{\expandafter\dref@load@ifkey@firstchar \dref@load@path\@nnil}%
    \ifcsdef{dref@ifnum@\dref@firstchar}{%
      \edef#2{\dref@load@path}%
    }{%
      \drefkeys{@get key to={#1}{#2}{#3}}%
    }%
  },
  @get key or value/.style={
    @get key or value to={\drefcurrentpath}{\drefresult}{\drefunit},
    unit/@format enable,
  },
}


% Print layer
\drefkeys{
  @init/.append style={
    @print result/.code={},
    @print unit/.code={}
  },
  @print/.style={@print result, @print unit},
  print default/.initial={pgf},
  print/.is choice,
  print/no/.style={
    @print result/.code={},
    @print unit/.code={}
  },
  print/default/.style={%
    print default/.get=\dref@print@format,%
    print/.expand once=\dref@print@format,
  },
  print/raw/.style={
    @print result/.code={\drefresult}
  },
  print/typeout/.style={
    @print result/.code={\typeout{#1\drefresult}},
    @print unit/.code={\typeout{\expandonce\drefunit}},
  },
  print/show/.style={
    @print result/.append code={\show\drefresult},
  },
  print/pgf/.style={
    @print result/.code={%
      \pgfmathprintnumber{\drefresult}%
    }
  },
  print/siunitx/.style={
    @print result/.code={%
      \num{\drefresult}%
    }
  },
}

% Compatibility with underscore package
\def\dref@normalunderscore{_}
\edef\dref@catcode@underscore{\the\catcode`_}
\catcode`_=13
\def\dref@catcode@setup{%
  \edef _{\dref@normalunderscore}%
}
\catcode`_=\dref@catcode@underscore


\AtBeginDocument{%
  \ifdim 13pt = \the\catcode`_pt%
    % _ is an active character
    \drefkeys{@[/.append code={%
        \dref@catcode@setup%
     }%
   }%
  \fi%
}

\newcommand{\drefset}[3][]{%
  % I put this version here, since it
  % provides a sped up mass setting of keys
  \begingroup%
    \ifdim 13pt = \the\catcode`_pt%
      \dref@catcode@setup%
    \fi%
    \edef\drefresult{#3}%
    \def\drefunit{}%
    \drefkeys{#1}%
    \expandafter\dref@set\expandafter{\drefunit}%
       {\drefresult}{\drefprefix #2}%
  \endgroup%
}

\newcommand{\drefsave}[3][]{%
  \drefkeys{@[, @init, value={#3}, #1, save={#2}, @set, @]}%
}

\def\dref@splitpath@helper#1/#2\@nnil{%
  \ifx&#2&% Basename found
     \def\dref@basename{#1}\let\@next\relax%
  \else% Another Dirname
     \edef\dref@dirname{\dref@dirname #1/}%
     \def\@next{\dref@splitpath@helper#2\@nnil}%
  \fi%
  \@next%
}
\def\dref@splitpath#1{%
   % Splits path into \dref@dirname and \dref@basename
   \def\dref@dirname{}%
   \dref@splitpath@helper #1/\@nnil%
}

\newcommand{\drefinput}[2][]{%
  \begingroup%
  \drefkeys{prefix/.append={#1}}%
  \dref@splitpath{#2}%
  \subimport{\dref@dirname}{\dref@basename}%
  \endgroup%
}


\def\drefref#1{\drefkeys{@reference key={#1}}}

% From here on, everything should be implemented using pgfkeys
\protected\def\dref{\@ifstar\dref@starred\dref@unstarred}
\newcommand{\dref@unstarred}[2][]{%
  \drefkeys{@[, @init, print=default, path={#2}, #1, @get, @calc, @print, @set,%
    @annotate={\textbackslash dref[#1]\{#2\}}, @]%
  }%
}
\newcommand{\dref@starred}[2][]{%
  \drefkeys{@[, @init, print=raw,     path={#2}, #1, @get, @calc, @print, @set,%
    @annotate={\textbackslash dref*[#1]\{#2\}}, @]%
  }%
}
\def\drefgetvalue#1#2{%
  \drefkeys{@[,@init, path={#1}, to macro={#2}, @get, @set, @]}%
}
\def\drefvalueof#1{%
  \pgfkeysvalueof{\dref@datapath \drefprefix #1}%
}

%% dref@ifstrmatch is copied from etextools, but etextools is
%% incompatible with etoolbox
%% \ifstrmatch{ pattern }{ string }{ true }{ false }
\ifPDFTeX%
  \let\dref@strmatch\pdfmatch
\fi
\ifLuaTeX%
 \newcommand{\dref@strmatch}[2]{%
  \directlua{%
    local match = string.find("\luaescapestring{#2}", "\luaescapestring{#1}");%
    if match then
      tex.print("1");
    else
      tex.print("0");
    end
  }%
}
\fi
\long\def\dref@firstoftwo#1#2{\z@#1} %% for romannumeral
\long\def\dref@secondoftwo#1#2{\z@#2}%% for romannumeral
\newcommand{\dref@ifstrmatch}[2]{%
  \romannumeral\csname dref@%
  \ifnum\dref@strmatch{#1}{#2}=1 first\else second\fi oftwo\endcsname%
}
\newcommand{\dref@help@match}[2]{%
  \dref@ifstrmatch{#1}{#2}%
}
\newcommand{\dref@help}[2][]{%
  \pgfkeysifdefined{#2/help}{%
    \pgfkeysvalueof{#2/help}%
  }{#1}%
}
\csdef{dref@helps}{}
\newcommand{\drefsethelp}[2]{
  \csdef{dref@help@#1}{#2}%
  \listcsadd{dref@helps}{#1}%
}
\newcommand{\drefhelp}[1]{
  \renewcommand{\do}[1]{%
    \dref@help@match{##1}{#1}{%
      \csuse{dref@help@##1}%
    \listbreak}{}%
  }%
  \ifcsvoid{dref@helps}{}{%
    \dolistcsloop{dref@helps}%
  }%
}
\drefkeys{
  @reference key/.code={%
    \edef\dref@thepage{\arabic{page}}%
    \drefifdefined{#1}{%
      \immediate\write\@auxout{%
        \noexpand\dref@found{\drefprefix #1}{\dref@thepage}}%
    }{%
      \immediate\write\@auxout{%
        \noexpand\dref@notfound{\drefprefix #1}{\dref@thepage}}%
    }%
    \immediate\write\@auxout{%
      \noexpand\dref@referenced{\drefprefix #1}{\dref@thepage}}%
  }
}
\def\dref@notfound#1#2{
  \ifdref@usagereport%
    \dref@usagereport@notfound{#1}{#2}%
  \else\relax\fi%
}
\def\dref@found#1#2{
  \ifdref@usagereport%
    \dref@usagereport@found{#1}{#2}%
  \else\relax\fi%
}
\def\dref@referenced#1#2{
  \ifdref@usagereport%
    \dref@usagereport@referenced{#1}{#2}%
  \else\relax\fi%
}


% The data("") || d() Parser
\def\dref@parser#1#2{%
  \edef\@tempa{#1}%
  \csdef{dref@parser@result}{}%
  \csdef{dref@parser@state}{}%
  \expandafter\dref@parser@parse\@tempa\@nnil%
  \xdef#2{\csuse{dref@parser@result}}%
}

\def\dref@parser@parse#1#2\@nnil{%
  %\typeout{#1 State: \csuse{dref@parser@state}}%
  \ifblank{#1#2}{%
    \csxdef{dref@parser@result}{\csuse{dref@parser@result}\csuse{dref@parser@state}}%
  }{%
    \ifcsdef{dref@parser@\csuse{dref@parser@state}@#1}{%
      \csuse{dref@parser@\csuse{dref@parser@state}@#1}#2\@nnil%
    }{%
      \csxdef{dref@parser@result}{\csuse{dref@parser@result}\csuse{dref@parser@state}#1}%
      \csdef{dref@parser@state}{}%
      \ifblank{#2}{}{%
        \dref@parser@parse#2\@nnil%
      }%
    }%
  }%
}

\csdef{dref@parser@@d}{\csdef{dref@parser@state}{d}\dref@parser@parse}
\csdef{dref@parser@d@a}{\csdef{dref@parser@state}{da}\dref@parser@parse}
\csdef{dref@parser@da@t}{\csdef{dref@parser@state}{dat}\dref@parser@parse}
\csdef{dref@parser@dat@a}{\csdef{dref@parser@state}{data}\dref@parser@parse}
\csdef{dref@parser@data@(}{\csdef{dref@parser@state}{data(}\dref@parser@parse}
\csdef{dref@parser@data(@"}{\dref@parser@tillquote}
\csdef{dref@parser@d@(}{\dref@parser@tillparen}

\def\dref@parser@tillquote#1")#2\@nnil{%
  \drefkeys{
    @get key to={#1}{\dref@math@value}{\dref@math@unit},
    unit/@combine=\dref@math@unit,
  }%
  \csxdef{dref@parser@result}{\csuse{dref@parser@result}(\dref@math@value)}%
  \csdef{dref@parser@state}{}%
  \ifblank{#2}{}{\dref@parser@parse#2\@nnil}}

\def\dref@parser@tillparen#1)#2\@nnil{%
  \drefkeys{@get key to={#1}{\dref@math@value}{\dref@math@unit},
            unit/@combine=\dref@math@unit}%
  \csxdef{dref@parser@result}{\csuse{dref@parser@result}(\dref@math@value)}%
  \csdef{dref@parser@state}{}%
  \ifblank{#2}{}{\dref@parser@parse#2\@nnil}}%

\def\dref@parser@end#1#2\@nnil{}
\csdef{dref@parser@@}{\dref@parser@end}

\newif\ifdrefbadmath
\newif\ifdref@xfp
\IfFileExists{xfp.sty}{\dref@xfptrue}{\dref@xfpfalse}

% For LuaLaTeX: use the lua math engine
\ifLuaTeX
  \drefbadmathfalse%
  \def\drefmathparse#1{%
    \edef\pgfmathresult{\directlua{%
      abs=math.abs ;
      result = (#1);
      if result == false then
         tex.print(0);
      elseif result == true then
         tex.print(1);
      else
         tex.print(string.format(string.char(37).."s", result))
      end
    }}}%
% We use the FP Library of expl3. This seems to work better for
% floating numbers and for integers
\else \ifdref@xfp
  \RequirePackage{xfp}
  \drefbadmathfalse%
  \ExplSyntaxOn% we want to do tests % Usepackage xfp
  \cs_set_eq:NN \dref@fpeval \fp_eval:n%
  \ExplSyntaxOff%
  \def\drefmathparse#1{%
    \edef\pgfmathresult{\dref@fpeval{#1}}%
  }%
%% Fallback to PGFMath
\else
  \drefbadmathtrue%
  \def\drefmathparse#1{%
    \pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
    \pgfmathparse{#1}%
  }%
  \dref@warning{****************************************************}%
  \dref@warning{Dataref will use bad math library (/pgf/fpu). Be aware%
  of floating point rounding errors}%
  \dref@warning{****************************************************}%
  \fi
\fi


\drefkeys{
  @init/.append style={%
    @calc/.code={},%
  },
  @calc pgf/.style={
    @calc/.append code={%
      \dref@parser{#1}{\dref@calc@@ready}%
      \drefmathparse{\dref@calc@@ready}%
      \dref@debug{#1 -> \dref@calc@@ready = \pgfmathresult}%
      \edef\drefresult{\pgfmathresult}%
    }
  }
}


\protected\def\drefcalc{\@ifstar\drefcalc@starred\drefcalc@unstarred}
\newcommand{\drefcalc@unstarred}[2][]{% Unstarred
  \drefkeys{@[,@init, print=default, @calc pgf={#2}, #1, @calc, @print, @set,%
    @annotate={\textbackslash drefcalc[#1]\{#2\}},@]}%
}
\newcommand{\drefcalc@starred}[2][]{% Starred
  \drefkeys{@[,@init, @calc pgf={#2}, #1, @calc, @set,%
    @annotate={\textbackslash \drefcalc*[#1]\{#2\}},@]%
  }%
}

\newcommand{\drefformat}[2][]{%
  \drefkeys{@[,@init, print=default, value={#2}, #1, @calc, @print, @]}%
}

\long\def\drefprojection#1#2#3{%
  \begingroup%
  \def\rename##1##2{%
    \drefkeys{@init, path={#1/##1}, set={#2/##2}, @get, @set}%
  }%
  \def\id##1{\rename{##1}{##1}}%
  \def\calc##1##2{%
    \edef\drefprojection@prefix{\drefprefix}%
    \drefcalc[prefix={#1}]{##1}%
    \edef\drefprefix{\drefprojection@prefix}%
    \drefset{#2/##2}{\drefresult}%
  }%
  #3%
  \endgroup%
}


\newtoks\dref@toks
\newcount\drefcellcount

\newcommand{\dref@makerow}[2]{%
  {\global\dref@toks={}%
    \drefcellcount=\z@%
    \def\do##1{%
      \advance\drefcellcount\@ne%
      \def\@tempa{\doX{##1}}%
      \expandafter\@tempa\expandafter{\the\drefcellcount}%
    }%
    \def\doX##1##2{%
      \csxdef{@cell\the\drefcellcount}{\detokenize{%
          #2%
        }}%
    }%
    \expandafter\def\expandafter\arglist\expandafter{#1}%
    \expandafter\docsvlist\expandafter{\arglist}%
    \@tempcntb=0\relax%
    {\loop\ifnum\@tempcntb<\drefcellcount%
      \advance\@tempcntb by 1\relax%
      \ifnum \@tempcntb = 1%
        \edef\@@next{\csuse{@cell\the\@tempcntb}}%
      \else%
        \edef\@@next{&\csuse{@cell\the\@tempcntb}}%
      \fi%
      \global%
      \dref@toks%
      \expandafter=%
      \expandafter{%
        \the%
        \expandafter\dref@toks%
        \@@next}%
      \repeat}%
  }%
  \expandafter\scantokens\expandafter{\the\dref@toks}%
}

\long\def\drefrow{\@ifstar{\drefrow@starred}{\drefrow@unstarred}}
\newcommand{\drefrow@unstarred}[3][]{\dref@makerow{#2}{\dref[#1]{#3}}\ignorespaces}
\def\drefrow@starred#1#2{\dref@makerow{#1}{#2}\ignorespaces}

\expandafter\ifstrequal\expandafter{\dref@annotate}{pdfcomment}{
  \RequirePackage{pdfcomment}
}


\drefkeys{
  annotate/.is choice,
  annotate/none/.style={@annotate/.code={\relax}},
  annotate/footnote/.style={@annotate/.code={\footnote{\texttt{##1}}}},
  annotate/pdfcomment/.style={@annotate/.code={\pdfcomment[opacity=0.4,voffset=2ex]{##1}}},
  annotate/typeout/.style={@annotate/.code={\typeout{##1}}},
  annotate=\dref@annotate,
}

%% Usagereport
\ifdref@usagereport
  \RequirePackage{xtab}
  \RequirePackage{booktabs}
\fi
\newcommand{\dref@usagereport@notfound}[2]{}
\newcommand{\dref@usagereport@found}[2]{}

\csdef{pgfdat@usagereport@keys}{}
\csdef{pgfdat@usagereport@matchedkeys}{}

\newcommand{\dref@usagereport@referenced}[2]{
  \ifinlistcs{#2}{dref@usagereport@referenced@#1}{}{
    \listcsgadd{dref@usagereport@referenced@#1}{#2}
  }
  \ifinlistcs{#1}{dref@usagereport@keys}{}{
    \listcsgadd{dref@usagereport@keys}{#1}
  }
}
\expandafter\def\expandafter\dref@usagereport@strippath@\dref@datapath#1\blanktest{#1}

\newcommand{\dref@usagereport@strippath}[1]{%
  \expandafter\dref@ifstrmatch\expandafter{\expandafter^\dref@datapath.*$}{#1}%$
    {\dref@usagereport@strippath@#1\blanktest}%
    {#1}%
}
\newcommand{\dref@usagereport@formatreferencelist}[1]{%
  \begingroup%
  \def\sep{}%
  \renewcommand{\do}[1]{\sep\ifdef{\hyperlink}{\hyperlink{page.##1}{##1}}{##1}\def\sep{, }}%
  \dolistcsloop{dref@usagereport@referenced@#1}%
  \endgroup%
}
\newif\ifdref@usagereport@keyheader@first
\dref@usagereport@keyheader@firsttrue
\newcommand{\dref@usagereport@keyheader}[1]{%
  \ifdref@usagereport@keyheader@first%
  \global\dref@usagereport@keyheader@firstfalse%
  \else%
    \\%
  \fi%
  \textbf{\ifdef{\hypertarget}%
    {\hypertarget{#1}{\dref@usagereport@strippath{#1}}}%
    {\dref@usagereport@strippath{#1}}}%
  & \dref@usagereport@formatreferencelist{#1}%
  & \drefifdefined{#1}{\dref*[@reference key/.code={}]{#1}}{\textbf{undefined}}%
}

\def\drefusagereportaftergroup{}

\def\drefusagereportbeforerow{}
\def\drefusagereportbeforetitle{}
\def\drefusagereportaftertitle{}

\def\drefusagereportbeforedescription{}


\newif\ifdref@withhelp
\errorcontextlines=23
\newlength{\dreflinewidth}%
\newcommand{\dref@usagereport@forhelp}[1]{%
  \begingroup%
  \dref@withhelpfalse%
  \renewcommand{\do}[1]{%
    \dref@help@match{#1}{##1}{%
      \dref@withhelptrue%
    }{}%
  }%
  \dolistcsloop{dref@usagereport@keys}%
  \dref@usagereport@keyheader@firsttrue%
  \renewcommand{\do}[1]{%
    \dref@help@match{#1}{##1}{%
      \drefusagereportbeforerow%
      \dref@usagereport@keyheader{##1}%
      \ifinlistcs{##1}{dref@usagereport@matchedkeys}{}{%
        \listcsgadd{dref@usagereport@matchedkeys}{##1}%
      }%
    }{}%
  }%
  \ifdref@withhelp
    \tablehead{\drefusagereportbeforetitle%
      \hline      & Page  & Value %
      \drefusagereportaftertitle\\\hline%
    }%
    \setlength\tabcolsep{3pt}%
    \dreflinewidth=\linewidth%
    \advance\dreflinewidth by -4\tabcolsep%
    \advance\dreflinewidth by -2\arrayrulewidth%
    \begin{xtabular}{|p{0.7\dreflinewidth}|p{0.15\dreflinewidth}|p{0.15\dreflinewidth}|}%
      \dolistcsloop{dref@usagereport@keys}\\\hline
      \drefusagereportbeforedescription%
      \multicolumn{3}{|p{\linewidth}|}{\csuse{dref@help@#1}}\\\hline
    \end{xtabular}%
  \fi%
  \drefusagereportaftergroup%

  \endgroup%
}
\newif\ifdref@withouthelp
\newcommand{\dref@usagereport@withouthelp}{%
  \begingroup%
  \dref@withouthelpfalse%
  \renewcommand{\do}[1]{%
    \ifinlistcs{##1}{dref@usagereport@matchedkeys}{}{%
      \dref@withouthelptrue%
    }%
  }%
  \dolistcsloop{dref@usagereport@keys}%
  \dref@usagereport@keyheader@firsttrue%
  \renewcommand{\do}[1]{%
    \ifinlistcs{##1}{dref@usagereport@matchedkeys}{}{%
      \drefusagereportbeforerow%
      \dref@usagereport@keyheader{##1}%
    }%
  }%
  \ifdref@withouthelp%
    \tablehead{\drefusagereportbeforetitle%
      \hline Keys without Description     & Page  & Value %
      \drefusagereportaftertitle\\\hline%
    }%
    \setlength\tabcolsep{3pt}%
    \dreflinewidth=\linewidth%
    \advance\dreflinewidth by -4\tabcolsep%
    \advance\dreflinewidth by -2\arrayrulewidth%
    \begin{xtabular}{|p{0.7\dreflinewidth}|p{0.15\dreflinewidth}|p{0.15\dreflinewidth}|}%
      \dolistcsloop{dref@usagereport@keys}\\\hline
      \drefusagereportbeforedescription%
      \multicolumn{3}{|p{\linewidth}|}{%
        \emph{For these keys, no description was given}}\\\hline
    \end{xtabular}%
   \fi%
   \endgroup%
}
\newcommand{\drefusagereport}{%
  \ifdref@usagereport%
  \ifcsvoid{dref@usagereport@keys}{}{%
  \begingroup%
  \renewcommand{\do}[1]{%
    \ifinlistcs{##1}{dref@usagereport@matchedkeys}{}{%
      \dref@usagereport@forhelp{##1}%
    }%
  }%
  \dolistcsloop{dref@helps} % For all help text
  \dref@usagereport@withouthelp\relax
  \endgroup%
  }% csempty @keys
  \fi%
}
\drefkeys{
  noassert/.is if=dref@noassert
}
\newcommand{\drefassert}[1]{%
  \begingroup%
    \drefcalc*{#1}%
    \ifdim\drefresult pt = 0pt%
      \ifdref@noassert%
        \dref@warning{Assertion failed: #1}%
      \else%
        \dref@error{Assertion failed: #1}%
        \fi%
     \else%
       \dref@warning{Assertion holds: #1}%
     \fi%
  \endgroup%
}
\drefkeys{%
  factor of/.style={%
    @get key or value to={#1}{\drefrel@tmp}{\drefrel@tmpunit},
    unit/@assert compatible=\drefrel@tmpunit,
    @calc pgf/.expanded={(\noexpand\drefresult)/(\drefrel@tmp)},
    @calc/.append code={\def\drefunit{}},
  },
  percent/.style={
    @calc pgf={100 * (\drefresult)},
  },
  percent of/.style={
    factor of={#1}, percent,
    @calc/.append code={\def\drefunit{}},
  },
  scale by/.style={
    @get key or value to={#1}{\drefrel@tmp}{\drefrel@tmpunit},%
    unit/@assert unitless=\drefrel@tmpunit,
    @calc pgf/.expanded={(\drefrel@tmp) * (\noexpand\drefresult)},
  },
  product/.style={scale by={#1}},
  divide by/.style={
    @get key or value to={#1}{\drefrel@tmp}{\drefrel@tmpunit},%
    unit/@assert unitless=\drefrel@tmpunit,
    @calc pgf/.expanded={(\noexpand\drefresult) / (\drefrel@tmp)},
  },
  divide/.style={divide by},
  product/.style={scale by={#1}},
  increase factor from/.style={
    @get key or value to={#1}{\drefrel@tmp}{\drefrel@tmpunit},
    unit/@assert compatible=\drefrel@tmpunit,
    @calc pgf/.expanded={((\noexpand\drefresult)-(\drefrel@tmp))/(\drefrel@tmp)},
    @calc/.append code={\def\drefunit{}},
  },
  increase percent from/.style={increase factor from={#1}, percent},
  decrease factor from/.style={increase factor from={#1}, negate},
  decrease percent from/.style={increase factor from={#1}, negate, percent},
  increase from/.style={
    @get key or value to={#1}{\drefrel@tmp}{\drefrel@tmpunit},%
    unit/@assert compatible=\drefrel@tmpunit,
    @calc pgf/.expanded={((\noexpand\drefresult)-(\drefrel@tmp))},
  },
  decrease from/.style={increase from={#1}, negate},
  abs/.style={
    @calc pgf={abs(\drefresult)}
  },
  negate/.style={
    @calc pgf={-1 * (\drefresult)}
  },
}

\def\drefrel{\@ifstar\drefrel@starred\drefrel@unstarred}

\newcommand{\drefrel@unstarred}[2][]{%
  \drefkeys{@[,
      @init,
      path={#2}, print=default, #1,
      @get key or value, @calc, @print, @set,
    @],
    @annotate={\textbackslash drefrel[#1]\{#2\}}}%
}

\newcommand{\drefrel@starred}[2][]{%
  \drefkeys{
    @[, @init,
      path={#2}, #1,
      @get key or value, @calc, @set,
    @],
    @annotate={\textbackslash drefrel[#1]\{#2\}},
  }%
}

% Unit scaling

\def\dref@unit@key#1#2{%
  dref@unit@\expandafter\detokenize\expandafter{#1}@\expandafter\detokenize\expandafter{#2}}

\def\dref@unit@new#1{%
  \def\dref@unit@scala{}%
  \def\dref@unit@new@outer##1/##2,##3\@nnil{%
    \def\dref@outer{\dref@unit@new@outer##3\@nnil}%
    \listadd{\dref@unit@scala}{##2}%
    \ifx##3&&%
       \def\dref@outer{}%
    \fi%
    \dref@outer%
  }%
  \dref@unit@new@outer#1,\@nnil%
  \def\dref@unit@new@outer##1/##2,##3\@nnil{%
    \def\dref@outer{\dref@unit@new@outer##3\@nnil}%
    \pgfkeys{/dref/units/\detokenize{##2} to \detokenize{##2}/.initial={* 1},%
      /dref/units/scala \detokenize{##2}/.initial/.expand once={\dref@unit@scala}}%
    \ifx##3&&%
       \def\dref@outer{}%
    \else%
       \def\dref@unit@factor{}%
       \dref@unit@new@inner{##2}##3\@stop%
    \fi%
    \dref@outer%
  }
  \def\dref@unit@new@inner##1##2/##3,##4\@stop{%
    \def\dref@inner{\dref@unit@new@inner{##1}##4\@stop}%
    \ifx##4&&\def\dref@inner{}\else\fi%
    \edef\dref@unit@factor{\dref@unit@factor * ##2}%
    \pgfkeys{/dref/units/\detokenize{##1} to \detokenize{##3}/.initial/.expanded={* (1 \dref@unit@factor)},%
             /dref/units/\detokenize{##3} to \detokenize{##1}/.initial/.expanded={/ (1 \dref@unit@factor)},%
    }%
    \dref@inner%
  }%
  \dref@unit@new@outer#1,\@nnil%
}

\drefkeys{
  unit/new scala/.code={%
     \dref@unit@new{#1}%
  },
  unit/.style={
    unit/@load={#1},
    unit/@format enable,
    @get/.append style={unit/@load={#1}}, % Override Unit from loads
  },
  unit/@load/.code={% #1 Is plain unit
    \def\drefunit{#1}%
  },
  unit/@try override/.code={% #1 must be unit holding macro
    \ifx#1\empty#1\else%
       \expandafter\def\expandafter\drefunit\expandafter{#1}%
    \fi%
  },
  unit/@format enable/.code={%
    \ifx\drefunit\empty\drefunit\else%
      \drefkeys{unit/format=default}%
    \fi%
  },
  unit/@assert unitless/.code={%
    \ifx\drefunit\empty\drefunit\else% We are unit less: good
    \ifx#1\empty#1\else% Other has no unit, also good
    \dref@error{At least one should be unitless:
      \expandafter\detokenize\expandafter{\drefunit},
      \expandafter\detokenize\expandafter{#1}}
      % There is some unit here. That is BAD
    \fi\fi%
  },
  unit/@assert compatible/.code={%
    \ifx\drefunit\empty\drefunit\else% We are unit less: good
    \ifx#1\empty#1\else% Other has no unit, also good
      \ifx\drefunit#1\else% Bot equal: also good
         \dref@error{Incompatible Units:
           \expandafter\detokenize\expandafter{\drefunit}
           != \expandafter\detokenize\expandafter{#1}}
         \fi%
       \fi%
    \fi%
  },
  unit/@combine/.style={
    unit/@assert compatible={#1}, unit/@try override={#1}, unit/@format enable
  },
  unit/scale to/.code={%
    \edef\dref@unit@key{/dref/units/\expandafter\detokenize\expandafter{\drefunit} to \detokenize{#1}}%
    \drefkeys{%
      \dref@unit@key/.get=\dref@unit@factor,%
      @calc pgf/.expanded={((\noexpand\drefresult) \dref@unit@factor)},%
      unit=#1%
    }%
  },
  unit/scale to auto/.default=50,
  unit/scale to auto/.style={% #1 is the optimal value
    @calc/.append code={
      \dref@ifunit{%Only do the scaling, if there is a unit
      \edef\dref@unit@key{/dref/units/scala \expandafter\detokenize\expandafter{\drefunit}}%
      % Get all other units in the same scala
      \drefkeys{\dref@unit@key/.get=\dref@unit@scala}%
      \expandafter\def\expandafter\drefunit@best\expandafter{\drefunit}%
      \def\drefunit@bestvalue{\drefresult}%
      \def\@@score####1{1 / ( abs(#1) - abs(####1))}%
      \def\do####1{%
        \edef\dref@unit@key{/dref/units/\expandafter\detokenize\expandafter{\drefunit} to \detokenize{####1}}%
        \pgfkeys{\dref@unit@key/.get=\dref@unit@factor}%
        \drefmathparse{\@@score{\drefunit@bestvalue} < \@@score{\drefresult \dref@unit@factor}}%
        %\typeout{\drefunit \pgfmathresult \detokenize{####1}}%
        \ifdim\pgfmathresult pt=1.0 pt%
          \drefmathparse{(\drefresult) \dref@unit@factor}%
          \edef\drefunit@bestvalue{\pgfmathresult}%
          \def\drefunit@best{####1}%
           %\typeout{\expandafter\detokenize\expandafter{\drefunit} to
           %  \detokenize{####1} : \drefunit@bestvalue}%
        \fi%
      }%
      \dolistloop\dref@unit@scala%
      \edef\drefresult{\drefunit@bestvalue}%
      \edef\drefunit{\expandonce{\drefunit@best}}%
      }{}% ! \drefunit=\empty
    }
  },
  unit/format default/.initial={plain},
  unit/format/.is choice,
  unit/format/no/.style={unit/format default=no, @print unit/.code={}},
  unit/format/false/.style={unit/format default=no, @print unit/.code={}},
  unit/format/plain/.style={
    unit/format default=plain,
    @print unit/.code={\dref@ifunit{\,\drefunit}{}}
  },
  unit/format/typeout/.style={
    unit/format default=typeout,
    @print unit/.code={\dref@ifunit{\expandafter\typeout\expandafter{\drefunit}}{}}
 },
  unit/format/siunitx/.style={
    unit/format default=siunitx,
    @print unit/.code={\dref@ifunit{\,\expandafter\si\expandafter{\drefunit}}{}}
  },
  unit/format/default/.style={%
    unit/format default/.get=\dref@unit@format,
    unit/format/.expand once=\dref@unit@format
  },
}

\def\dref@ifunit#1#2{%
  \expandafter\ifblank\expandafter{\drefunit}{#2}{#1}%
}


\endinput
%%
%% End of file `dataref.sty'.