On Mon, Dec 30, 2024 at 03:34:07PM +0100, Bruno Haible via Bug reports for the 
GNU Texinfo documentation system wrote:
> Hi,
> 
> In the 'info' program, when the user selects an index entry, it
> should display the node associated with that index entry. Instead,
> in some cases it displays a different node, with a similar name.
> 
> Reproduced with texinfo 7.1 and 7.2.
> How to reproduce: (I noticed this with the gnulib.info file. Here
> is a smaller example, based on GNU hello.)

I had hit the same problem myself recently.

The reason is the role of the "." character in Info syntax.  It terminates
the node name in an index entry, so in the index entry

* verify.h:                              assert.h.             (line  6)

the node name is taken as "assert", not "assert.h".

If I insert the DEL quoting characters into the file, then the link
works properly.  (I did this with the command below as I couldn't work
out how to enter a DEL in my text editor.)

perl -wple 's/(?<=    )(assert\.h)/\x7F$1\x7F/' ./hello.info > hello2.info"

Checking the code in texi2any, it appears a warning is only given for a
"." followed by a space.

      if ($node_name =~ /([,\t:]|\.\s)/) {
        my $warned_char = $1;

(process_printindex in tp/Texinfo/Convert/HTML.pm.)

So we could change the code in info to only recognize the "." as ending
the node name if it is followed by a whitespace character.

This is what we document in the Info format specification in the Texinfo
manual:

  Follow the menu entry name with a single colon, and follow the node
  name with tab, comma, newline, or the two characters period and space
  (@samp{. }).

This text was added in commit 7d6ecb6d (Karl Berry, 2008-05-12),
referencing node names containing "config.status".

Indeed, there are also broken index entries containing "config.status"
in the autoconf manual - but these end in ".\n" rather than ". ", so we
need to support both.

I've tried to do this in commit cc9f6f66c20 (2024-12-30) - this should
apply to Texinfo 7.2 so you could try it out.

diff --git a/ChangeLog b/ChangeLog
index 26c3f93c53..330af30877 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2024-12-30  Gavin Smith <gavinsmith0...@gmail.com>
+
+       ". " terminator for index entry node name
+
+       * info/scan.c (scan_reference_target):
+       First check for a ". " and ".\n" terminator for node name in menu,
+       rather than just a ".".  This allows index entries referring to
+       nodes with "." in their names.  Report from Bruno Haible.
+
 2024-12-30  Gavin Smith <gavinsmith0...@gmail.com>
 
        * info/scan.c [__hpux]: remove define of __va_copy which isn't
diff --git a/info/scan.c b/info/scan.c
index fd5ec525b0..e27b32af83 100644
--- a/info/scan.c
+++ b/info/scan.c
@@ -1321,8 +1321,42 @@ scan_reference_target (REFERENCE *entry, NODE *node, int 
in_parentheses)
       length += strspn (inptr + length, " ");
 
       /* Get the node name. */
-      length += read_quoted_string (inptr + length, ",.\t\n", 2,
-                                    &entry->nodename);
+      entry->nodename = 0;
+      char *node_start = inptr + length;
+
+      /* First check for . followed by space or end of line. */
+      if (*node_start != '\x7f')
+        {
+          /* Confine search to present line. */
+          char *nl = strchr (node_start, '\n');
+          if (nl)
+            *nl = '\0';
+
+          char *node_end = strstr (node_start, ". ");
+          if (!node_end)
+            {
+              /* Check for . at end of line. */
+              if (nl && nl > node_start && nl[-1] == '.')
+                node_end = &nl[-1];
+            }
+
+          if (nl)
+            *nl = '\n';
+
+          if (node_end)
+            {
+              entry->nodename = xmalloc (node_end - node_start + 1);
+              memcpy (entry->nodename, node_start,
+                      node_end - node_start);
+              entry->nodename[node_end - node_start] = '\0';
+              length += node_end - node_start;
+            }
+        }
+      if (!entry->nodename)
+        {
+          length += read_quoted_string (inptr + length, ",.\t\n", 2,
+                                        &entry->nodename);
+        }
       if (inptr[length] == '.') /* A '.' terminating the entry. */
         length++;
       canonicalize_whitespace (entry->nodename);


  • 'inf... Bruno Haible via Bug reports for the GNU Texinfo documentation system
    • ... Eli Zaretskii
    • ... Gavin Smith
      • ... Bruno Haible via Bug reports for the GNU Texinfo documentation system
        • ... Gavin Smith
        • ... Eli Zaretskii

Reply via email to