From 89092cc1f7b225d6caa59f2c10e7126009b0df02 Mon Sep 17 00:00:00 2001
From: Mark Wooding <mdw@distorted.org.uk>
Date: Wed, 7 Aug 2019 16:24:33 +0100
Subject: [PATCH] doc/sod.sty: Rewrite `\descref' to support a [MOD] argument.

Take the opportunity to factor out an annoying part of the parsing,
which `might' come in handy later.
---
 doc/sod.sty | 71 ++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 49 insertions(+), 22 deletions(-)

diff --git a/doc/sod.sty b/doc/sod.sty
index 75acc2d..4d50de9 100644
--- a/doc/sod.sty
+++ b/doc/sod.sty
@@ -468,8 +468,29 @@
 \@namedef{describe*}#1{\desc@begin{#1}}
 \expandafter\let\csname enddescribe*\endcsname\desc@end
 
-%% \descref{CAT}{...}...{LABEL}[TEXT]
-%% \descref*{CAT}{...}...{LABEL}
+%% \parse@dlbl{NEXT}[MOD]{CAT}{...}...{LABEL}
+%%
+%% Parse a description label, and call
+%%
+%%      NEXT{MOD}{CAT}{{...}...}{LABEL}
+%%
+%% This handles defaulting the MOD correctly, based on the LABEL text.  See
+%% `\descref' for the details.
+\def\parse@dlbl#1{\@ifnextchar[{\parse@dlbl@a{#1}}{\parse@dlbl@c{#1}}}
+\def\parse@dlbl@a#1[#2]#3{\@desc@dispatch{descargs}{#3}{#1{#2}{#3}}}
+\def\parse@dlbl@c#1#2%
+  {\@desc@dispatch{descargs}{#2}{\parse@dlbl@cb{#1}{#2}}}
+\def\parse@dlbl@cb#1#2#3#4{%
+  \def\temp@##1##2*##3\q@{\def\temp@{##1##3}}\temp@#4*\q@%
+    \ifx\temp@\@starstar\def\next@{#1{muffs}{#2}{#3}{#4}}%
+    \else\def\temp@##1##2\q@{\def\temp@{##1}}\temp@#4\q@%
+      \if:\temp@\def\next@{#1{kwd}{#2}{#3}{#4}}
+      \else\def\next@{#1{plain}{#2}{#3}{#4}}\fi\fi%
+  \next@%
+}
+
+%% \descref[MOD]{CAT}{...}...{LABEL}[TEXT]
+%% \descref*[MOD]{CAT}{...}...{LABEL}
 %%
 %% Typesets a cross-reference to a described thing.  The CAT names the
 %% category of thing being described, and the LABEL names the specific thing.
@@ -477,32 +498,38 @@
 %% The {...}... are any additional arguments required by the category's kind
 %% (e.g., method specializers).
 %%
-%% The precise rules for how the LABEL matches the name in the description
-%% depend on the description's modifier:
+%% The MOD is the modifier to apply, similar (but subtly different from) to
+%% the `describe' environment.  If omitted, it will usually default to
+%% `plain', but in the absence of a NAME, some kinds of synopses are
+%% recognized specially:
+%%
+%%   * `*NAME*': defaults MOD to `muffs'.
 %%
-%%   * `plain', `muffs', and `kwd': the LABEL is the same as the NAME.
-%%   * `setf': the LABEL should be `setf/NAME'.
+%%   * `:NAME': defaults MOD to `kwd'.
+%%
+%% (`setf' is /not/ specially detected here.  Write an explicit `setf'
+%% modifier if necessary, because it's no more typing.)
 %%
 %% Usually a page-number cross-reference is included, so as to help readers
 %% of a dead-tree copy; this is suppressed by the `*' version.
 \def\descref{\@ifstar%
-  {\descref@i{}\@gobble{}}%
-  {\descref@i{ (}{\noexpand\autopageref}{)}}}
-\def\descref@i#1#2#3#4#5{\@ifnextchar@preserve[%
-  {\descref@ii{#1}{#2}{#3}{#4}{#5}}%
-  {\descref@iii{#1}{#2}{#3}{#4}{#5}{}}}
-\def\descref@ii#1#2#3#4#5[#6]{\descref@iii{#1}{#2}{#3}{#4}{#5}{ #6}}
-\def\descref@iii#1#2#3#4#5#6{%
+  {\parse@dlbl{\descref@i\relax\@gobble\relax}}%
+  {\parse@dlbl{\descref@i{ (}\autopageref)}}}
+\def\descref@i#1#2#3#4#5#6#7{\@ifnextchar@preserve[%
+  % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL}
+  {\descref@ii{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
+  {\descref@iii{#1}{#2}{#3}{#4}{#5}{#6}{#7}{}}}
+\def\descref@ii#1#2#3#4#5#6#7[#8]%
+  % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL}[AFTER]
+  {\descref@iii{#1}{#2}{#3}{#4}{#5}{#6}{#7}{ #8}}
+\def\descref@iii#1#2#3#4#5#6#7#8{%
+  % {PGA}{PGB}{PGC}{MOD}{CAT}{{...}...}{LABEL}{AFTER}
   \begingroup%
-    \let\protect\@empty%
-    \def\@uscore{-\@gobble}%
-    \edef\@tempa##1{%
-      \endgroup%
-      \noexpand\hyperref[#4:#5]%
-      ##1%
-      #2{#4:#5}%
-    }%
-  \@tempa{{\code{#5}}#6#1}#3%
+    \let\protect\@empty\def\@uscore{-\@gobble}%
+    \edef\temp@{\@desc@dispatch{desclabel}{#5}{#4}{#5}#6{#7}}%
+    \hyperref[\temp@]{\code{#7}}#8%
+    #1#2{\temp@}#3%
+  \endgroup%
 }
 
 %% Description categories.
-- 
2.11.0

