From 87883222727894b13d3d4ce50e413a544a50fe20 Mon Sep 17 00:00:00 2001
From: Mark Wooding <mdw@distorted.org.uk>
Date: Sun, 28 Jul 2019 03:10:23 +0100
Subject: [PATCH] doc/sod.sty, doc/*.tex: Support category-specific arguments.

Now description categories can accept arguments and influence labels and
indexing.  Use this to collect method specializers and report them in
the index.
---
 doc/clang.tex   |  17 +++++----
 doc/meta.tex    |  11 +++---
 doc/output.tex  |   2 +-
 doc/parsing.tex |  32 ++++++++++------
 doc/sod.sty     | 112 ++++++++++++++++++++++++++++++++++++++------------------
 5 files changed, 113 insertions(+), 61 deletions(-)

diff --git a/doc/clang.tex b/doc/clang.tex
index 08aac24..b572fe4 100644
--- a/doc/clang.tex
+++ b/doc/clang.tex
@@ -208,12 +208,12 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
 
   The generic function @|c-type-equal-p| uses the @|and| method combination.
 
-  \begin{describe}{meth}{c-type-equal-p @<c-type>_1 @<c-type>_2}
+  \begin{describe}{meth}{t,t}{c-type-equal-p @<c-type>_1 @<c-type>_2}
     A default primary method for @|c-type-equal-p| is defined.  It simply
     returns @|nil|.  This way, methods can specialize on both arguments
     without fear that a call will fail because no methods are applicable.
   \end{describe}
-  \begin{describe}{ar-meth}{c-type-equal-p @<c-type>_1 @<c-type>_2}
+  \begin{describe}{ar-meth}{}{c-type-equal-p @<c-type>_1 @<c-type>_2}
     A default around-method for @|c-type-equal-p| is defined.  It returns
     true if @<c-type>_1 and @<c-type>_2 are @|eql|; otherwise it delegates to
     the primary methods.  Since several common kinds of C types are interned,
@@ -270,7 +270,7 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   Every concrete subclass of @|c-type| is expected to provide a primary
   method on this function.  There is no default primary method.
 
-  \begin{describe}{ar-meth}{pprint-c-type @<c-type> @<stream> @<kernel>}
+  \begin{describe}{ar-meth}{}{pprint-c-type @<c-type> @<stream> @<kernel>}
     A default around method is defined on @|pprint-c-type| which `canonifies'
     non-function @<kernel> arguments.  In particular:
     \begin{itemize}
@@ -375,7 +375,8 @@ methods to \descref{c-qualifier-keyword}{gf}.
   methods exist for qualifier keywords which need special handling, such as
   @|:atomic|; they are not listed here explicitly.
 
-  \begin{describe}{meth}{c-qualifier-keyword @<keyword> @> @<string>}
+  \begin{describe}{meth}{keyword}
+      {c-qualifier-keyword @<keyword> @> @<string>}
     Returns the @<keyword>'s print-name, in lower case.  This is sufficient
     for the standard qualifiers @|:const|, @|:restrict|, and @|:volatile|.
   \end{describe}
@@ -844,11 +845,13 @@ function type is the type of the function's return value.
   including file from defining such names as macros.  This generic function
   is used to convert names into a safe form.
 
-  \begin{describe}{meth}{commentify-argument-name (@<name> null) @> nil}
+  \begin{describe}{meth}{null}
+      {commentify-argument-name (@<name> null) @> nil}
     Returns nil: if the argument name is already omitted, it's safe for use
     in a header file.
   \end{describe}
-  \begin{describe}{meth}{commentify-argument-name (@<name> t) @> @<string>}
+  \begin{describe}{meth}{t}
+      {commentify-argument-name (@<name> t) @> @<string>}
     Returns the print form of @<name> wrapped in a C comment, as
     @`/*@<name>*/'.
   \end{describe}
@@ -1164,7 +1167,7 @@ Temporary names are represented by objects which implement a simple protocol.
   subclasses, but is also usable on its own.
 \end{describe}
 
-\begin{describe}{meth}
+\begin{describe}{meth}{temporary-name}
     {commentify-argument-name (@<name> temporary-name) @> nil}
 \end{describe}
 
diff --git a/doc/meta.tex b/doc/meta.tex
index 66d4e67..05a6fc0 100644
--- a/doc/meta.tex
+++ b/doc/meta.tex
@@ -334,10 +334,10 @@
 \end{describe}
 
 \begin{describe}{gf}{check-class-initializer @<slot> @<class>}
-  \begin{describe}{meth}
+  \begin{describe}{meth}{effective-slot,sod-class}
       {check-class-initializer (@<slot> effective-slot) (@<class> sod-class)}
   \end{describe}
-  \begin{describe}{meth}
+  \begin{describe}{meth}{sod-class-effective-slot,sod-class}
       {check-class-initializer (@<slot> sod-class-effective-slot)
                                (@<class> sod-class)}
   \end{describe}
@@ -347,10 +347,11 @@
 \end{describe}
 
 \begin{describe}{gf}{finalize-sod-class @<class> @> @<generalized-boolean>}
-  \begin{describe}{meth}{finalize-sod-class (@<class> sod-class)}
+  \begin{describe}{meth}{sod-class}
+      {finalize-sod-class (@<class> sod-class)}
   \end{describe}
-  \begin{describe}{ar-meth}{finalize-sod-class (@<class> sod-class)
-                              @> @<generalized-boolean>}
+  \begin{describe}{ar-meth}{sod-class}
+      {finalize-sod-class (@<class> sod-class) @> @<generalized-boolean>}
   \end{describe}
 \end{describe}
 
diff --git a/doc/output.tex b/doc/output.tex
index 4571b6a..37ab159 100644
--- a/doc/output.tex
+++ b/doc/output.tex
@@ -150,7 +150,7 @@ until the third.  So the final processing order is
 \end{describe}
 
 \begin{describe}{gf}{hook-output progn @<object> @<reason> @<sequencer>}
-  \begin{describe}{meth}
+  \begin{describe}{meth}{t,t}
     {hook-output progn (@<object> t) (@<reason> t) @<sequencer>}
   \end{describe}
 \end{describe}
diff --git a/doc/parsing.tex b/doc/parsing.tex
index 4cb6ef1..8aeb26b 100644
--- a/doc/parsing.tex
+++ b/doc/parsing.tex
@@ -71,18 +71,21 @@ consumed any input items.
 \end{describe*}
 
 \begin{describe}{gf}{file-location @<object> @> @<floc>}
-  \begin{describe}{meth}{file-location (@<floc> file-location) @> @<floc>}
+  \begin{describe}{meth}{file-location}
+      {file-location (@<floc> file-location) @> @<floc>}
   \end{describe}
-  \begin{describe}{meth}{file-location (@<stream> stream) @> @<floc>}
+  \begin{describe}{meth}{stream}
+      {file-location (@<stream> stream) @> @<floc>}
   \end{describe}
-  \begin{describe}{meth}{file-location (@<any> t) @> @<floc>}
+  \begin{describe}{meth}{t}
+      {file-location (@<any> t) @> @<floc>}
   \end{describe}
 \end{describe}
 
 \begin{describe}{cls}{condition-with-location (condition) \&key :location}
 \end{describe}
 
-\begin{describe}{meth}
+\begin{describe}{meth}{condition-with-location}
     {file-location (@<condition> condition-with-location) @> @<floc>}
 \end{describe}
 
@@ -175,14 +178,19 @@ consumed any input items.
 
 \begin{describe}{gf}{classify-condition @<condition> @> @<string>}
   \begin{describe*}
-      {\dhead{meth}{classify-condition (@<condition> error) @> @<string>}
-       \dhead{meth}{classify-condition (@<condition> warning) @> @<string>}
-       \dhead{meth}{classify-condition (@<condition> information)
-                       @> @<string>}
-       \dhead{meth}{classify-condition (@<condition> base-lexer-error)
-                       @> @<string>}
-       \dhead{meth}{classify-condition (@<condition> base-syntax-error)
-                       @> @<string>}}
+      {\dhead{meth}{error}
+         {classify-condition (@<condition> error) @> @<string>}
+       \dhead{meth}{warning}
+         {classify-condition (@<condition> warning) @> @<string>}
+       \dhead{meth}{information}
+         {classify-condition (@<condition> information)
+             @> @<string>}
+       \dhead{meth}{base-lexer-error}
+         {classify-condition (@<condition> base-lexer-error)
+             @> @<string>}
+       \dhead{meth}{base-syntax-error}
+         {classify-condition (@<condition> base-syntax-error)
+             @> @<string>}}
   \end{describe*}
 \end{describe}
 
diff --git a/doc/sod.sty b/doc/sod.sty
index 293411c..43b77cc 100644
--- a/doc/sod.sty
+++ b/doc/sod.sty
@@ -181,7 +181,9 @@
 }
 
 %% Lisp documentation machinery.
-\def\definedescribecategory#1#2{\@namedef{cat!#1}##1{#2}}
+\def\definedescribecategory#1{%
+  \@ifnextchar[{\def@desc{#1}}{\def@desc{#1}[plain]}}
+\def\def@desc#1[#2]#3{\@namedef{cat!#1}##1{#3}\@namedef{catsw!#1}{#2}}
 \def\describecategoryname{\@ifnextchar[\@descname@i{\@descname@i[]}}
 \def\@descname@i[#1]#2{%
   \expandafter\let\expandafter\@tempa\csname cat!#2\endcsname%
@@ -196,10 +198,10 @@
 \definedescribecategory{var}{variable}
 \definedescribecategory{modvar}{module variable}
 \definedescribecategory{const}{constant}
-\definedescribecategory{meth}{primary #1{method}}
-\definedescribecategory{ar-meth}{\code{:around} #1{method}}
-\definedescribecategory{be-meth}{\code{:before} #1{method}}
-\definedescribecategory{af-meth}{\code{:after} #1{method}}
+\definedescribecategory{meth}[method]{primary #1{method}}
+\definedescribecategory{ar-meth}[method]{\code{:around} #1{method}}
+\definedescribecategory{be-meth}[method]{\code{:before} #1{method}}
+\definedescribecategory{af-meth}[method]{\code{:after} #1{method}}
 \definedescribecategory{cls}{class}
 \definedescribecategory{rst}{restart}
 \definedescribecategory{ty}{type}
@@ -217,52 +219,90 @@
 
 \@namedef{descmod/setf}#1{\code{setf}-#1}
 
+\@namedef{descargs/plain}#1{#1{}}
+\@namedef{desclabel/plain}#1#2#3{#1:\@maybe@modlabel{#2}{#3}}
+\@namedef{descindex/plain}#1#2#3{%
+  #3@\noexpand\code{#3}!%
+  \protect\describecategoryname[#2]{#1}%
+}
+
+\@namedef{descargs/method}#1#2{#1{{#2}}}
+\@namedef{desclabel/method}#1#2#3#4{#1:\@maybe@modlabel{#2}{#3}(#4)}
+\@namedef{descindex/method}#1#2#3#4{%
+  #3@\noexpand\code{#3}!%
+  \protect\describecategoryname[#2]{#1}%
+  \protect\fmtspecs{ specialized at }{#4}%
+}
+
+\def\@desc@dispatch#1#2{%
+  \csname #1/%
+  \expandafter\ifx\csname catsw!#2\endcsname\relax plain%
+  \else \csname catsw!#2\endcsname \fi%
+  \endcsname%
+}
+
 \def\q@{\q@}
 \def\@setf{setf}
 
-%% \parse@dhd{NEXT}{CAT}[NAME]{SYNOPSIS}
-%% call NEXT{MOD}{CAT}{NAME}{SYNOPSIS}
-%%            #1   #2   #3      #4
+\def\fmtspecs#1#2{%
+  \if!#2!\else\count@\z@\toks@{}#1\@fmtspecs@i#2,\q@,\fi}
+\def\@fmtspecs@i#1,{%
+  \def\@tempa{#1}%
+  \ifx\@tempa\q@%
+    \ifcase\count@(no args?!)%
+    \or% nothin' doin
+    \or \space and %
+    \else, and %
+    \fi%
+    \the\toks@%
+  \else%
+    \ifnum\count@>\@ne, \fi%
+    \the\toks@%
+    \toks@{\code{#1}}\advance\count@\@ne%
+    \expandafter\@fmtspecs@i%
+  \fi%
+}
+
+%% \parse@dhd{NEXT}{CAT}{...}...[NAME]{SYNOPSIS}
+%% call NEXT{MOD}{CAT}{{...}...}{NAME}{SYNOPSIS}
+%%            #1   #2      #3     #4      #5
 \def\parse@dhd#1#2{%  {NEXT}{CAT}
-  \@ifnextchar[{\parse@dhd@cc{#1}{#2}}{\parse@dhd@cd{#1}{#2}}}
-\def\parse@dhd@cc#1#2[#3]#4{%  {NEXT}{CAT}[NAME]{SYNOPSIS}
-  #1{}{#2}{#3}{#4}}
-\def\parse@dhd@cd#1#2#3{%  {NEXT}{CAT}{SYNOPSIS}
-  \parse@dhd@ce{#1}{#2}{#3}#3 \q@}
-\def\parse@dhd@ce#1#2#3#4 #5\q@{%
-  % {NEXT}{CAT}{SYNOPSIS}NAME [ARGS...]\q@
-  \def\temp@{#4}%
-  \ifx\temp@\@setf\def\next@{\parse@dhd@csetf{#1}{#2}{#3}#5 \q@}%
-  \else\def\next@{#1{}{#2}{#4}{#3}}\fi%
+  \@desc@dispatch{descargs}{#2}{\parse@dhd@cb{#1}{#2}}}
+\def\parse@dhd@cb#1#2#3{%  {NEXT}{CAT}{{...}...}
+  \@ifnextchar[{\parse@dhd@cc{#1}{#2}{#3}}{\parse@dhd@cd{#1}{#2}{#3}}}
+\def\parse@dhd@cc#1#2#3[#4]#5{%  {NEXT}{CAT}{{...}...}[NAME]{SYNOPSIS}
+  #1{}{#2}{#3}{#4}{#5}}
+\def\parse@dhd@cd#1#2#3#4{%  {NEXT}{CAT}{{...}...}{SYNOPSIS}
+  \parse@dhd@ce{#1}{#2}{#3}{#4}#4 \q@}
+\def\parse@dhd@ce#1#2#3#4#5 #6\q@{%
+  % {NEXT}{CAT}{{...}...}{SYNOPSIS}NAME [ARGS...]\q@
+  \def\temp@{#5}%
+  \ifx\@setf\temp@\def\next@{\parse@dhd@csetf{#1}{#2}{#3}{#4}#6 \q@}%
+  \else\def\next@{#1{}{#2}{#3}{#5}{#4}}\fi%
   \next@%
 }
-\def\parse@dhd@csetf#1#2#3(#4 #5\q@{%
-  % {NEXT}{CAT}{SYNOPSIS}(NAME [ARGS...])\q@
-  #1{setf}{#2}{#4}{#3}}
+\def\parse@dhd@csetf#1#2#3#4(#5 #6\q@{%
+  % {NEXT}{CAT}{{...}...}{SYNOPSIS}(NAME [ARGS...])\q@
+  #1{setf}{#2}{#3}{#5}{#4}}
 
 \newif\if@dheadfirst
 \def\dhead{\parse@dhd\dhead@}
-\def\dhead@#1#2#3#4{%  {}{CAT}{NAME}{SYNOPSIS}
+\def\dhead@#1#2#3#4#5{%  {MOD}{CAT}{{...}...}{NAME}{SYNOPSIS}
   \if@dheadfirst\global\@dheadfirstfalse\else\relax\\[\smallskipamount]\fi%
   {\let\protect\@empty\let\@uscore\relax%
-   \edef\temp@{#2:\@maybe@modlabel{#1}{#3}}%
-   \def\@uscore{_\@gobble}\message{\temp@}%
-   \def\@uscore{-\@gobble}\label{\temp@}}%
+   \edef\temp@{\@desc@dispatch{desclabel}{#2}{#2}{#1}{#4}#3}%
+   \def\@uscore{_\@gobble}\expandafter\message\expandafter{\temp@}%
+   \def\@uscore{-\@gobble}\expandafter\label\expandafter{\temp@}}%
   {\begingroup\lccode`\~=`\_\lowercase{\endgroup\def~{_}}%
    \protected@edef\@tempa##1{%
-     \noexpand\index{%
-       #3@{\noexpand\code{#3}}!%
-       \protect\describecategoryname[#1]{#2}%
-       ##1%
-     }%
-   }%
-   \toks@\expandafter{\after@desc}%
-   \toks\tw@\expandafter{\@tempa{|)}}%
-   \xdef\after@desc{\the\toks@\the\toks\tw@}%
+     \noexpand\index{\@desc@dispatch{descindex}{#2}{#2}{#1}{#4}#3##1}}%
+   \toks@\expandafter{\@tempa{|)}}%
+   \toks\tw@\expandafter{\after@desc}%
+   \xdef\after@desc{\the\toks\tw@\the\toks@}%
    \@tempa{|(}}%
   \rlap{\hb@xt@\linewidth{\hfil\normalfont\bfseries
       [\describecategoryname[#1]{#2}]}}%
-  #4%
+  #5%
 }
 
 \def\desc@begin#1{%
@@ -284,7 +324,7 @@
 \@namedef{describe*}#1{\desc@begin{#1}}
 \expandafter\let\csname enddescribe*\endcsname\desc@end
 \def\describe{\parse@dhd\desc@}
-\def\desc@#1#2#3#4{\desc@begin{\dhead@{#1}{#2}{#3}{#4}}}
+\def\desc@#1#2#3#4#5{\desc@begin{\dhead@{#1}{#2}{#3}{#4}{#5}}}
 \let\enddescribe\desc@end
 
 \def\descref#1{\@ifnextchar[{\descref@i{#1}}{\descref@ii{#1}{}}}
-- 
2.11.0

