% Copyright 2012-2024, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % SPLinT is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see . % prototypes of all the macros produced by the ld parser % we will follow the convention: 12string is a string of category 12 characters and spaces, tex_string: a string % of TeX tokens; sptr is a pointer to the stash stream, fptr is a pointer to the format stream \def\yyuniontag{\ldunion} \def\parserstrictnamespace{ld-parser-strict} % expands to an error message \def\parserprototypesnamespace{ld-parser-strict:headers} % the parameter strings \def\parserdebugnamespace{ld-parser-debug} % control sequences are \let...=\relax for debugging \def\ldunion{\currentyyunionnamespace} \def\currentyyunionnamespace{ld-generic} % types returned by the lexer (* marks the types that get removed by the parser in some cases) \defp\anint#1#2#3{} % integer :: \anint{integer}{fptr}{sptr} \defp\bint#1#2#3{} % integer in a specifix radix :: \bint{integer}{fptr}{sptr} \defp\hexint#1#2#3{} % hex integer :: \hexint{integer}{fptr}{sptr} % ld commands \defp\ldor{} % item separator :: \ldor, is only needed here for debugging (in the ld-parser-debug namespace) \defp\ldregexp#1{} % name pattern :: \ldregexp{{name}{name11}{fptr}{sptr}} \defp\ldregop#1{} % name pattern :: \ldregop{name} \defp\ldspace{} % space separator :: \ldspace \defp\ldattrstring#1#2#3#4{} % attributes string :: \ldattrstring{name}{name11}{fptr}{sptr} \defp\ldattrstringneg#1#2#3#4{} % complemented attributes string :: \ldattrstring{name}{name11}{fptr}{sptr} \defp\ldfilename#1{} % file name :: \ldfilename{name} \defp\ldcommandseparator#1#2#3#4{} % command separator :: \ldcommandseparator{fptr}{sptr}{prev command}{next command} \defp\ldassignment#1#2#3{} % assignment :: \ldassignment{lhs}{op}{rhs} \defp\ldhidden#1#2{} % hidden :: \ldhidden{lhs}{rhs} \defp\ldprovide#1#2{} % provide :: \ldprovide{lhs}{rhs} \defp\ldprovidehid#1#2{} % provide hidden :: \ldprovidehid{lhs}{rhs} \defp\ldkeep#1{} % keep :: \ldkeep{list} \defp\ldentry#1{} % entry :: \ldentry{name} \defp\ldinclude#1{} % file inclusion :: \ldinclude{file name} \defp\ldmemory#1{} % memory specification :: \ldmemory{memory spcification} \defp\ldfill#1{} % fill expression :: \ldfill{expression} \defp\ldmemoryspec#1#2#3#4{} % memory item :: \ldmemoryspec{name}{attributes}{origin}{length} \defp\ldmemspecstash#1#2{} % memory spec stash :: \ldmemspecstash{fptr}{sptr} \defp\ldmemspecseparator#1#2{} % memory spec separator :: \ldmemspecseparator{fptr}{sptr} \defp\ldoriginspec#1{} % origin :: \ldoriginspec{expression} \defp\ldlengthspec#1{} % length :: \ldlengthspec{expression} \defp\ldsections#1{} % ld sections :: \ldsections{sections} \defp\ldsectionseparator#1#2{} % section separator :: \ldsectionseparator{fptr}{sptr} \defp\ldtype#1{} % section type :: \ldtype{type} \defp\ldstatement#1{} % statement :: \ldstatement{statement} \defp\ldfreestmt#1{} % statement in a section :: \ldfreestmt{\ldstatement{statement}} \defp\ldsecspec#1{} % section spec :: \ldsecspec{section spec} \defp\ldinsertcweb#1#2#3#4{} % insert accumulated \CWEB\ material :: \ldinsertcweb % {fptr}{sptr}{command}{parsed segment} : never defined \defp\ldnamedsection#1#2#3#4#5#6#7{} % named section :: \ldnamedsection{name} % {expression}{type}}{at} % {{}{}{}:alignment} % {constraint}{statements} % {{}{}{}{}:placement} \defp\ldoverlay#1#2#3#4#5#6{} % overlay section list :: \ldoverlay{expression}{crossrefs}{at}{subalign} % {sections} % {{memspec}{memspec_at}{phdr}{fill}} \defp\ldoverlaysection#1#2#3#4{} % overlay section :: \ldoverlaysection{name}{statements}{phdr}{fill} \defp\ldsectionstash#1#2{} % sections spec stash :: \ldsectionstash{fptr}{sptr} \savecslist{ld-parser-prototypes}\ldunion % these consume parameters and expand to nothing \input ldint.sty \def\ldidxdomain{L} \let\writeldidxentry\writeidxentry % mix the \ld\ index with the \let\writeldidxhentry\writeidxhentry % \bison\ index for now \def\writeldidxhentry#1{% \indxe\gindex{{\secno}{{}{\hostparsernamespace}}{\ldidxdomain}{\headeridxrank}#1}% } \def\writeldidxentry#1{% \indxe\gindex{{\secno}{{}{\hostparsernamespace}}{\ldidxdomain}{\termidxrank}#1}% } \def\bigbracedel{\delimiter"4266308} \newtoks\lddisplay \restorecslist{ld-parser-strict}\ldunion \defc\ldinclude{% \toksa={&##\cr\ttl include\ &}#1% \concat\toksa\toksc \toksc{\cr} \concat\toksa\toksc \edef\next{\lddisplay{\the\lddisplay\halign{\the\toksa}}}\next } \defc\ldmemory{% \savecslist{local-namespace}{\ldunion}% \restorecslist{ld-parser:memory-spec}\ldunion \toksa{}#1% \toksc{% \hfil##\qquad&##\hfil&\qquad##\hfil\quad&\hfil##&\qquad\hfil##\cr \ttl memory&\hfil&\ttl attributes&\ttl starts at&\ttl length\cr \noalign{\smallskip}% }% \edef\next{\lddisplay{\the\lddisplay\halign{\the\toksc\the\toksa}}}\next \restorecslist{local-namespace}{\ldunion}% } \defc\ldsections{% \savecslist{local-namespace}{\ldunion}% \restorecslist{ld-parser:sections}\ldunion \toksa{}\def\sections@header{\ttl sections}% #1% \toksc{% &##\hfil\quad\cr }% \edef\next{\lddisplay{\the\lddisplay\halign{\the\toksc\the\toksa}}}\next \restorecslist{local-namespace}{\ldunion}% } \def\ldextractname#1#2#3#4{% \edef\next{\toksc{\gidxentry{\termttstring}{#2}{}{\ntt #2}}}\next } \def\ldextractattrs#1#2#3#4{% \edef\next{\toksc{{\ntt #2}}}\next } \def\ldextractmemname#1#2#3#4{% {% \expandafter\let\expandafter\tosmallparser\csname to\stripbrackets\cwebclinknamespace parser\endcsname \let\optstrextra\optstrextraesc \def\hostparsernamespace{[none]}% \nameproc{#2}\with\parsebin \edef\next{\toksc{\gidxentry{\termvstring}{#2}{}{\let\idxfont\nx\empty\ntt\the\toksa}}}% \expandafter }\next% } % the grammar of ld scripts is very uniform so the separator form % below should be more than adequate; if a more sophisticated spacing % strategy is required, one may consult the design of % \separatorswitcheq and \separatorswitchneq in yyunion.sty \defc\ldcommandseparator{% \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \yyifsamestring{#3}{#4}{}{\appendrnx\lddisplay{\medskip}}% \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \edef\next{\toksc{\toksa{}\the\yystashlocal \noexpand\ldmakestashbox{}}}\next \appendrnx\lddisplay{\smallskip\noindent}% \concat\lddisplay\toksc \appendrnx\lddisplay{\smallskip}% \fi } \defc\ldcommandseparator{% new version; TODO: remove the duplicates after the macros have been tested \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \yyifsamestring{#3}{#4}{}{\appendrnx\lddisplay{\medskip}}% \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \appendrnx\lddisplay{\smallskip\noindent}% \appendr \lddisplay{\toksa{\the\yystashlocal}}% \appendrnx\lddisplay{\ldmakestashbox{}\smallskip}% \fi } \defc\ldstatement{\toksc{\hbox{$#1$}}\concat\lddisplay\toksc} \let\ldsecspec\ldstatement \defc\ldassignment{% #1#2#3% } \defc\ldhidden{% \mathop{\hbox{\ssf hidden}}\hbox{$\langle\,$}#1\K#2\hbox{$\,\rangle$}% } \defc\ldprovide{% \mathop{\hbox{\ssf provide}}\hbox{$\langle\,$}#1\K#2\hbox{$\,\rangle$}% } \defc\ldprovidehid{% \mathop{\hbox{\ssf provide$_{h}$}}\hbox{$\langle\,$}#1\K#2\hbox{$\,\rangle$}% } \defc\anint{% \uppercase{\ldsciinteger{#1}}% } \defc\hexint{% \ldsciinteger{#1}% } \defc\bint{% \uppercase{\ldbasedinteger{#1}}% } \defc\ldregexp{% \ldreg@xp#1% } \def\ldreg@xp#1#2#3#4{% \expandafter\ifx\csname ldvarname[#2]\endcsname\relax {% \let\termindex\writeldidxentry \let\hostparsernamespace\cwebclinknamespace% process the variable names as in \CWEB \edef\next{\toksc{\gidxentry{\termttstring}{#1}{}}}\next \hbox{\ntt@#1}% \expandafter }\the\toksc \else \yyifsamestring{#2}{.}{% special . name {% \let\termindex\writeldidxentry \let\hostparsernamespace\cwebclinknamespace% for consistency \edef\next{\toksc{\gidxentry{\termexception}{.origin&}{.}}}\next \hbox{\csname\prettynamecs\hostparsernamespace{.origin&}\endcsname{}}% \expandafter }\the\toksc }{% {% \let\termindex\writeldidxentry \let\hostparsernamespace\cwebclinknamespace% process the variable names as in \CWEB \edef\next{\toksc{\gidxentry{\termhostidstring}{#1}{}}}\next \hbox{% \expandafter\let\expandafter\tosmallparser\csname to\stripbrackets\cwebclinknamespace parser\endcsname \let\optstrextra\optstrextraesc \nameproc{#2}\with\parsebin \\{\the\toksa}% }% \expandafter }\the\toksc }% \fi } \defc\ldregop{% \ldreg@p#1% } \def\ldreg@p#1#2#3#4{% \hbox{\ntt@#1}% } \defc\ldfill{% #1% } \defc\ldentry{% this command survives till the table time \hbox{\ttl entry{\rm: }} #1% } \defc\ldkeep{% \mathop{\hbox{\ssf keep}}(#1)% } \defc\ldfilename{\ldextractname#1} \savecslist{ld-display}\ldunion % memory specifications \restorecslist{ld-parser-strict}\ldunion \defc\ldmemoryspec{% \toksb{\hfil&}% \let\termindex\writeldidxhentry \ldextractmemname#1\concat\toksb\toksc \let\termindex\eatone \appendrnx\toksb{&}% \toksc{}#2\appendrnx\toksc{&}\concat\toksb\toksc% attributes \toksc{}#3\appendrnx\toksc{&}\concat\toksb\toksc \toksc{}#4\concat\toksb\toksc \concat\toksa\toksb \toksb{\cr}\concat\toksa\toksb } \defc\ldattrstring{% \appendrnx\toksc{{\ntt@ #2}}% } \defc\ldattrstringneg{% \appendrnx\toksc{\hbox{$\neg$}{\ntt@ #2}}% } \defc\ldspace{% } \defc\ldlengthspec{% \toksc{$#1$}% } \defc\ldoriginspec{% \toksc{#1}% } \defc\ldinclude{% \toksc={\hfil&\ttl include }% \concat\toksa\toksc#1% \concat\toksa\toksc \toksc{&\hfil&\hfil&\hfil\cr}% \concat\toksa\toksc } % TODO: change the code to use linked lists \defc\ldmemspecseparator{% \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \appendr\toksa{&\nx\multispan4\toksa{\the\yystashlocal}\nx\ldmakestashbox{\nx\cdotfill}\nx\quad\cr}% \fi } \defc\ldmemspecstash{% \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \appendr\toksa{&\nx\multispan4\toksa{\the\yystashlocal}\nx\ldmakestashbox{\nx\cdotfill}\nx\quad\cr}% \fi } \restorecs{ld-display}{\ldfilename\ldentry} \toyyunion{ld-parser:memory-spec} % sections commands \restorecslist{ld-parser-strict}\ldunion \newif\ifplacementpushed \newif\ifsectioncomplete \newif\iffillextracted \defc\ldnamedsection{ % named section :: \ldnamedsection{name} % {{bind?}{expression}{block?}{expression}{type}}{at} % {{}{}{}:alignment} % {constraint}{statements} % {{}{}{}{}:placement} \tempca=\z@ % line counter \tempcb=\z@ % alignment line counter \placementpushedfalse \sectioncompletefalse \fillextractedfalse \bloop \toksb{}% \ifnum\tempca=\z@ \toksb\expandafter{\sections@header&}% section header \ldextractname#1% section name \concat\toksb\toksc \appendrnx\toksb{&}% \ldexpwithtype#2% location and type \concat\toksb\toksc \appendrnx\toksb{&}% \yystringempty{#3}{\ldpushalignment#4}{\toksc{{\ttl at }$#3$}}% alignment \concat\toksb\toksc \appendrnx\toksb{&}% \yystringempty{#5}{\ldpushplacement#7}{\toksc{{\ttl #5}}}% constraint \concat\toksb\toksc \appendrnx\toksb{&}% \ldstartpheaders#7% possible pheaders \concat\toksb\toksc \appendrnx\toksb{\cr}% \def\sections@header{}% \else \toksb\expandafter{&}% section header \advance\tempca\m@ne \ldextractitem\tempca{#6}% next statement \advance\tempca\@ne \yytoksempty\toksc{% \ldextractfill#7% \iffillextracted \ifnum\tempcb<\tw@ \else \sectioncompletetrue \fi \fi \fillextractedtrue }{% \toksc\expandafter{\expandafter\qquad\the\toksc{}}% }% \concat\toksb\toksc \appendrnx\toksb{&}% % \ldexpwithtype#2% location and type % \concat\toksa\toksc \appendrnx\toksb{&}% \ldpushalignment#4% alignment \concat\toksb\toksc \appendrnx\toksb{&}% \ldpushplacement#7% placement \concat\toksb\toksc \appendrnx\toksb{&}% \ldpushpheaders#7% possible pheaders \concat\toksb\toksc \appendrnx\toksb{\cr}% \def\sections@header{}% \fi \ifsectioncomplete \else \concat\toksa\toksb \advance\tempca\@ne \repeat } % named section :: \ldnamedsection{name} % {{bind?}{expression}{block?}{expression}{type}}{at} % {{}{}{}:alignment} % {constraint}{statements} % {{memspec}{memspec_at}{phdr}{fill}} \defc\ldoverlay{% overlay sections :: \ldoverlay{expression}{crossrefs}{at}{subalign} % {sections} % {{memspec}{memspec_at}{phdr}{fill}} \yystringempty{#1}{\tokse{}}{\tokse{ $#1$}}% \yystringempty{#2}{\toksf{}}{\toksf{{ \ttl noxrefs}}}% \yystringempty{#3}{\toksg{}\toksc{}}{\toksg{{\ttl at} $#3$}\toksc{ }}% \yystringempty{#4}{\toksh{}}{\toksh\expandafter{\expandafter{\the\tokc\ttl subalign} $#4$}}% \appendr\toksa{&\hskip-1em\noexpand\ttl overlay\the\tokse\the\toksf&&\the\toksg\the\toksh}% \ldwrapoverlay#6% \appendr\toksa{&\the\toksc&\cr}% #5% \ldoverlayfill#6% \yytoksempty\toksd{}{\appendr\toksa{&\the\toksd&&&&&\cr}}% attach the fill at the end \appendr\toksa{&\hskip-1em{\ttl overlay end}&&&&&\cr}% } \defc\ldoverlaysection{% overlay section :: \ldoverlaysection{name}{statements}{phdr}{fill} \ldnamedsection{#1}% {{}{}{}{}{}}{}% {{}{}{}}% {}{#2}% {{}{}{#3}{#4}}% } \def\ldwrapoverlay#1#2#3#4{% puts memspec... in \toksc and fill in \toksd \toksc{}% \yystringempty{#1}{% any > ? }{% \ldextractname#1% \toksd{{\ttl in }}% \concatl\toksd\toksc }% \yystringempty{#2}{% any AT > ? }{% \yytoksempty\toksc{\toksc{{\ttl as }}}{\appendrnx\toksc{ {\ttl as }}}% \toksd=\toksc \ldextractname#2% \concat\toksd\toksc \toksc=\toksd }% } \def\ldoverlayfill#1#2#3#4{% \ld@xtractfill{#4}% } \def\ldextractitem#1#2{% #1 is a counter, #2 is a list separated by \ldor \yystringempty{#2}{% \toksc{}% }{% \let\ldor\or \toksc=\ifcase#1#2\else{}\fi \let\ldor\relax }% } \def\ldpushalignment#1#2#3{% \toksd=\ifcase\tempcb{#1}\or{#2}\or{#3}\else{}\fi \yytoksempty\toksd{% \advance\tempcb\@ne \ifnum\tempcb<\tw@ \yybreak{\ldpushalignment{#1}{#2}{#3}}% \else \yybreak{\toksc{}}% \yycontinue }{% \toksc=\ifcase\tempcb{{\ttl align }}\concat\toksc\toksd\or {{\ttl align\_with\_input}}\or {{\ttl subalign }}\concat\toksc\toksd\fi \advance\tempcb\@ne }% } \def\ldpushplacement#1#2#3#4{% \ifplacementpushed \toksc{}% \else \yystringempty{#1}{% any > ? \toksc{}% }{% \ldextractname#1% \toksd{{\ttl in }}% \concatl\toksd\toksc }% \yystringempty{#2}{% any AT > ? }{% \yytoksempty\toksc{\toksc{{\ttl as }}}{\appendrnx\toksc{ {\ttl as }}}% \toksd=\toksc \ldextractname#2% \concat\toksd\toksc \toksc=\toksd }% \placementpushedtrue \fi } \def\ldstartpheaders#1#2#3#4{% \tempcc=\z@ \yystringempty{#3}{\toksc{}}{\toksc{{\ttl phdrs}}}% } \def\ldextractfill#1#2#3#4{% \toksc{}% \yystringempty{#4}{% \fillextractedtrue }{% \iffillextracted \else \ld@xtractfill{#4}% \appendr\toksc{\noexpand\qquad{\noexpand\ttl fill }$\the\toksd$}% \fi }% } \def\ld@xtractfill#1{% #1 must be \ldfill{expression} \toksf{#1}% \toksd\expandafter{#1}% } \def\ldpushpheaders#1#2#3#4{% \ldextractitem\tempcc{#3}% \advance\tempcc\@ne \yytoksempty\toksc{}{\expandafter\ldextractname\the\toksc}% } \def\ldexpwithtype#1#2#3#4#5{% TODO \yystringempty{#2}{\toksc{$}}{\toksc{$#2}}%$ \yystringempty{#5}{\toksd{{}$}}{#5\appendlnx\toksd{[}\appendrnx\toksd{]$}}% \concat\toksc\toksd } \defc\ldtype{% \toksd{\hbox{\ttl #1}}% } \defc\ldstatement{{\let\ldrlap\relax\let\ldintfont\ntt@$#1$}} % the braces form the group for a \toks assignment \defc\ldfreestmt{\toksb\expandafter{#1}\appendr\toksa{&\the\toksb\cr}} \defc\ldsecspec{{$#1$}} \def\ldboxstash#1{% \ifchecktrim\errmessage{stash contents: \the\toksa}\fi {\setbox0 \vbox{\the\toksa}\ifdim\ht0=\z@\aftergroup\toksa\else\aftergroup\eatone\fi}{}% \yytoksempty\toksa{#1}{% $\vtop{\activateinlinec\tabskip\z@\halign{\strut\ignorespaces##\hfil\cr\the\toksa\crcr}}$\hfill}} \def\ldmakestashbox#1{\cleanstash\stripstash\ldboxstash{#1}} \defc\ldsectionseparator{% \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \appendr\toksa{&\nx\multispan5\toksa{\the\yystashlocal}\nx\ldmakestashbox{\nx\cdotfill}\nx\quad\cr}% \fi } \defc\ldsectionstash{% \expandafter\ifx\csname ldstashentry[#2]\endcsname\relax \else \expandafter\expandafter\expandafter\yystashlocal\expandafter\expandafter\expandafter{\csname ldstashentry[#2]\endcsname}% \appendr\toksa{\sections@header&\nx\multispan5\toksa{\the\yystashlocal}\nx\ldmakestashbox{\nx\cdotfill}\nx\quad\cr}% \let\sections@header\empty \fi } \restorecs{ld-display}{\ldregexp\ldassignment\ldfill\ldinsertcweb\ldentry} \toyyunion{ld-parser:sections} % preprocessing macros: collecting stash and marking variables % currently these macros do not get inside expressions to extract % variable names, consequently if the variable is used before it % appears in an assignment, it will not be displayed properly % (is this even legal in linker scripts?) although the index will % show it correctly \restorecslist{ld-parser-prototypes}\ldunion \restorecs{ld-parser-strict}{\insertcweb} \defc\ldmemory{#1} % memory specification :: \ldmemory{memory spcification} \defc\ldmemspecstash{% \readstash{#2}% \setbox0 \vbox{\toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash\the\toksa}% \ifdim\ht0=\z@ \expandafter\let\csname ldstashentry[#2]\endcsname\relax % this is redundant but we may change \relax to % something else later \else \expandafter\edef\csname ldstashentry[#2]\endcsname{\the\yystashlocal}% \fi } % memory spec stash :: \ldmemspecstash{fptr}{sptr} \defc\ldmemspecseparator{% \readstash{#2}% \setbox0 \vbox{\toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash\the\toksa}% \ifdim\ht0=\z@ \expandafter\let\csname ldstashentry[#2]\endcsname\relax \else \expandafter\edef\csname ldstashentry[#2]\endcsname{\the\yystashlocal}% \fi } % memory spec separator :: \ldmemspecseparator{fptr}{sptr} \defc\ldsections{#1} % ld sections :: \ldsections{sections} \defc\ldoverlay{% overlay section :: \ldoverlay{expression}{crossrefs}{at}{subalign} % {sections} % {{memspec}{memspec_at}{phdr}{fill}} #3#5% } % TODO: add handling of subalign, memmspec, and memspec_at \defc\ldsectionseparator{% \readstash{#2}% \setbox0 \vbox{\toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash\the\toksa}% \ifdim\ht0=\z@ \expandafter\let\csname ldstashentry[#2]\endcsname\relax \else \expandafter\edef\csname ldstashentry[#2]\endcsname{\the\yystashlocal}% \fi } % section separator :: \ldsectionseparator{fptr}{sptr} \defc\ldsectionstash{% \readstash{#2}% \setbox0 \vbox{\toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash\the\toksa}% \ifdim\ht0=\z@ \expandafter\let\csname ldstashentry[#2]\endcsname\relax \else \expandafter\edef\csname ldstashentry[#2]\endcsname{\the\yystashlocal}% \fi } % sections spec stash :: \ldsectionstash{fptr}{sptr} \defc\ldcommandseparator{% \readstash{#2}% \setbox0 \vbox{\toksa\expandafter{\the\yystashlocal}\cleanstash\stripstash\the\toksa}% \ifdim\ht0=\z@ \expandafter\let\csname ldstashentry[#2]\endcsname\relax \else \expandafter\edef\csname ldstashentry[#2]\endcsname{\the\yystashlocal}% \fi } % command separator :: \ldcommandseparator{fptr}{sptr}{prev command}{next command} \defc\ldstatement{#1} \defc\ldfreestmt{#1} \defc\ldassignment{#1} \defc\ldprovide{#1} \defc\ldentry{#1} \let\ldhidden\ldprovide \let\ldprovidehid\ldprovide \defc\ldnamedsection{\let\ldor\empty#6} \defc\ldregexp{% \ldr@gexprestash#1% } \def\ldr@gexprestash#1#2#3#4{ \expandafter\def\csname ldvarname[#2]\endcsname{\errmessage{Not an \\ldregexp!, maybe change the parser namespace?}}% } \toyyunion{ld-parser:restash}