2007-12-29 Bruno Haible * info/search.c (skip_node_characters): When newlines_okay is false, continue parsing a node name past ". " or ".)". * makeinfo/node.c (remember_node): Give a warning when the node name does not satisfy the documented constraints. *** texinfo-4.11/info/search.c.bak 2007-07-01 23:20:31.000000000 +0200 --- texinfo-4.11/info/search.c 2007-12-30 12:50:16.000000000 +0100 *************** *** 290,302 **** return (i); } ! /* Return the index of the first non-node character in STRING. Note that ! this function contains quite a bit of hair to ignore periods in some ! special cases. This is because we here at GNU ship some info files which ! contain nodenames that contain periods. No such nodename can start with ! a period, or continue with whitespace, newline, or ')' immediately following ! the period. If second argument NEWLINES_OKAY is non-zero, newlines should ! be skipped while parsing out the nodename specification. */ int skip_node_characters (char *string, int newlines_okay) { --- 290,306 ---- return (i); } ! /* Return the index of the first non-node character in STRING. ! If second argument NEWLINES_OKAY is non-zero, we are parsing a reference ! to a node inside normal text; in this case, newlines should be skipped ! while parsing out the nodename specification. ! Note that this function contains quite a bit of hair to ignore periods ! in some special cases. This is because we here at GNU ship some info ! files which contain nodenames that contain periods. ! 1. No such nodename can start with a period. ! 2. When a nodename contains a period immediatey followed by whitespace, ! newline, or ')', it cannot be used in references, but is otherwise ! ok. */ int skip_node_characters (char *string, int newlines_okay) { *************** *** 338,344 **** ((!newlines_okay) && (c == '\n')) || ((paren_seen && string[i - 1] == ')') && (c == ' ' || c == '.')) || ! (c == '.' && ( #if 0 /* This test causes a node name ending in a period, like `This.', not to --- 342,352 ---- ((!newlines_okay) && (c == '\n')) || ((paren_seen && string[i - 1] == ')') && (c == ' ' || c == '.')) || ! /* When we see "Foo vs. Bar", we assume the node name ends at the ! period when parsing a reference (newlines_okay), but we assume ! that the node name continues past the period when parsing a ! node definition (!newlines_okay). */ ! (newlines_okay && c == '.' && ( #if 0 /* This test causes a node name ending in a period, like `This.', not to *** texinfo-4.11/makeinfo/node.c.bak 2007-07-08 15:11:48.000000000 +0200 --- texinfo-4.11/makeinfo/node.c 2007-12-30 12:51:24.000000000 +0100 *************** *** 280,285 **** --- 280,319 ---- node, tag->line_no); return; } + /* The documentation says: "You cannot use periods, commas, colons or + parentheses within a node name." */ + if (strchr (node, '(') != NULL || strchr (node, ')') != NULL) + { + warning (_("Node name `%s' contains a parenthesis"), node); + } + if (strchr (node, ':') != NULL) + { + warning (_("Node name `%s' contains a colon"), node); + } + if (strchr (node, ',') != NULL) + { + warning (_("Node name `%s' contains a comma"), node); + } + /* periods are only dangerous - see info/node.c function + skip_node_characters - when at the start of the node name or + when followed by whitespace, newline, or ')'. */ + if (*node == '.') + { + warning (_("Node name `%s' starts with a period"), node); + } + { + const char *np; + + for (np = node; *np != '\0'; np++) + if (*np == '.' + && (np[1] == ' ' || np[1] == '\t' || np[1] == '\n' + || np[1] == ')')) + { + warning (_("Node name `%s' contains a period followed by whitespace or a closing parenthesis; references to this node will not work"), + node); + break; + } + } } if (!(flags & TAG_FLAG_ANCHOR))