summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Simplify handling of no-fill mode in man(7) by inspecting NODE_NOFILLIngo Schwarze2022-08-151-24/+20
| | | | | | | | | | | | | at the beginning of the node handler, in the same way as it is done in the mdoc(7) node handler. As a side effect, this also fixes a bug: if an input line contained nothing but an escape sequence producing no output whatsoever (for example, \fR), the old code incorrectly emitted a blank line anyway, whereas the new code only emits such a blank link if the input line actually produces output (even invisible zero-width output). To make the distinction, the ASCII_NBRZW -> lastcol -> term_newln() mechanism established in term.c rev. 1.289 is used.
* Distinguish between escape sequences that produce no outputIngo Schwarze2022-08-157-17/+52
| | | | | | | | | | | | | | | | | whatsoever (for example \fR) and escape sequences that produce invisible zero-width output (for example \&). No, i'm not joking, groff does make that distinction, and it has consequences in some situations, for example for vertical spacing in no-fill mode. Heirloom and Plan 9 behaviour is subtly different, but in case of doubt, we want to follow groff. While this fixes the behaviour for the majority of escape sequences, in particular for those most likely to occur in practice, it is not perfect yet because some of the more exotic ESCAPE_IGNORE sequences are actually of the "no output whatsoever" type but treated as "invisible zero-width" for now. With the new ASCII_NBRZW mechanism in place, switching them over one by one when the need arises will no longer be very difficult.
* In GNU, Heirloom, and Plan 9 roff, tab positions apply to *input* lines,Ingo Schwarze2022-08-153-7/+12
| | | | | | | | | | | | | not to *output* lines. In particular, if an input line gets broken in fill mode and a tab occurs in the second output line, it advances to a position of at least (width of the first output line) + (width of a space character even though this is never printed) + (width of the part of the second output line that precedes the tab). Implement the same logic in mandoc. Again, do not use tabs in filled text: they have surprising effects, including this one.
* In GNU, Heirloom, and Plan 9 roff, literal tab characters areIngo Schwarze2022-08-151-19/+15
| | | | | | | | | | | | | non-breakable in exactly the same way as "\ ". That is, the preceding word, the tab character, and the following word are always kept together on the same output line. If filling is enabled and an output line break is required before the end of the following word, the break occurs before the beginning of the preceding word. Make mandoc behave in the same way. Of course, using literal tab characters in filled text remains a bad idea, and the "WARNING: tab in filled text" remains unchanged.
* two ideas from RGBDSIngo Schwarze2022-08-091-0/+8
|
* prevent breakable hyphens in segment identifiersIngo Schwarze2022-08-091-2/+5
| | | | | from being turned into underscores; bug reported by <Eldred dot fr> Habert
* For clarity and consistency, refer to ".Bx 4.0" rather than ".Bx 4".Ingo Schwarze2022-08-041-1/+3
| | | | Also, mention /usr/ucb/man because /usr/bin/man did not provide -f in 4.0BSD.
* If the body of a man(7) .MT or .UR block is empty, do not emit a warning.Ingo Schwarze2022-08-024-9/+1
| | | | | | | | | | | | | | | Leaving the body empty is legitimate in this case if the author only wants to display a mail address or URI without providing a link text. Output modules already handle this correctly: terminal output shows just the URI without an accompanying text, HTML output uses the URI for *both* the href= attribute and as the content of the <a> element. The documentation was also wrong and claimed that an .MT or .UR block with an empty body would produce no output. As explained above, this isn't true. Bogus warning reported by Alejandro Colomar <alx dot manpages at gmail dot com>.
* Delete OpenBSD-only rules from the regress/roff/de MakefileIngo Schwarze2022-08-021-38/+0
| | | | | after they were changed in OpenBSD. Tracking these rules here would be useless.
* For accessibility, label the last two widgets in the search form.Ingo Schwarze2022-07-061-4/+6
| | | | Patch from Anna Vyalkova <cyber at sysrq dot in>, significantly tweaked by me.
* https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/ says:Ingo Schwarze2022-07-063-7/+7
| | | | | | | "Start names with a capital letter; it helps some screen readers speak them with appropriate inflection." Anna Vyalkova already did that correctly when sending patches, but i ruined it when committing, so fix it now.
* improve the description of header.html and footer.htmlIngo Schwarze2022-07-061-4/+6
|
* assign the ARIA role "doc-subtitle" to the .Nd element;Ingo Schwarze2022-07-061-1/+1
| | | | discussed with Anna Vyalkova <cyber at sysrq dot in>
* While the HTML standard allows multiple <h1> elements in the sameIngo Schwarze2022-07-0614-41/+41
| | | | | | | | | | | | document, <h1> is intended for top level headers, and most of the sections in a manual page can hardly be considered top-level. It is more usual to use <h1> only for the main title of the document of for the site name. Consequently, move .Sh/.SH from <h1> to <h2> and .Ss/.SS from <h2> to <h3>, freeing <h1> for use by header.html in man.cgi(8). Discussed with Anna Vyalkova <cyber at sysrq dot in>.
* Finally get rid of the archaic <table> markup for header and footer linesIngo Schwarze2022-07-054-41/+49
| | | | | | | | | | | and use flexbox CSS instead. Improve accessibility by adding role and aria-label attributes to these header and footer lines. Using ideas from both Anna Vyalkova <cyber at sysrq dot in> and myself. As a welcome side effect, this also resolves the long-standing issue that the rendering was always 65em wide, requiring horizontal scrolling when the window was narrower. Now, rendering nicely adapts to browser windows of arbitrary narrowness.
* Somehow, the content of header.html ended upIngo Schwarze2022-07-051-30/+42
| | | | | | before and outside the <header> element. Fix this by moving it into the <header> element where it belongs. While here, also wrap footer.html in a <footer> element.
* Improve accessibility of man.cgi(8) in various respects,Ingo Schwarze2022-07-041-15/+32
| | | | | | | in particular adding <header>, <main>, and <nav> elements and role and aria-label attributes in several places. Patch from Anna Vyalkova <cyber at sysrq dot in>, minimally tweaked by me.
* Put the HTML comment containing the Copyright header (if any)Ingo Schwarze2022-07-042-4/+4
| | | | | | | between the <head> and the <body> rather than before the <head> because the <meta charset="utf-8"/> element ought to be within the first 1024 bytes of the HTML code. Issue found with validator.w3.org.
* spelling; patch from jsg@Ingo Schwarze2022-07-031-1/+1
|
* Instead of the custom <div class="manual-text">, use the standardIngo Schwarze2022-07-035-6/+7
| | | | | | | | | | HTML <main> element. The benefit is that it has the ARIA landmark role "main" by default. To ease the transition for people using their own CSS file instead of mandoc.css, retain the custom class for now. I had this idea in a discussion with Anna Vyalkova <cyber at sysrq dot in>. Patch from Anna, slightly tweaked by me.
* In groff commit 78e66624 on May 7 20:15:33 2021 +1000,Ingo Schwarze2022-06-262-2/+2
| | | | | | G. Branden Robinson changed the -T ascii rendering of \(sd, the "second" symbol, U+2033 DOUBLE PRIME, from '' to ". Follow suit in mandoc.
* additional info regarding the .nf <br/> issueIngo Schwarze2022-06-261-1/+3
|
* If an .Xr macro contains a section argument, write an aria-label attributeIngo Schwarze2022-06-252-11/+21
| | | | | | | | such that users of screen readers aren't forced to listen to lengthy and distracting readings like "mdoc, left parenthesis, 7, right parenthesis". Based on a patch from Anna Vyalkova <cyber at sysrq dot in>, significantly tweaked by me.
* Improve accessibility of -T html -O toc output by using the <nav> elementIngo Schwarze2022-06-244-2/+12
| | | | | | | | | | | | | in the DPUB-ARIA doc-toc role. Patch from Anna Vyalkova <cyber at sysrq dot in> slightly tweaked by me. This is hopefully the start of a collaboration to improve accessibility of Unix manual pages using the WAI-ARIA, HTML-ARIA, and DPUB-ARIA standards. Progress appears to be possible without changing *anything* with respect to the way manual pages are written. Instead, it seems sufficient to properly translate semantic cues already implied by existing mdoc(7) markup into the appropriate HTML elements and ARIA attributes. Overall, the total length of HTML output is likely to increase slightly, but not much.
* Delete the statement that the default stylesheet only used CSS1Ingo Schwarze2022-06-221-1/+0
| | | | | | | | | | | | | | | | because that has no longer been true for some time now. I would certainly like to adhere to a coherent standard and state which one that is. Unfortunately, the W3C deliberately smashed the CSS standard into pieces such that a coherent standard no longer exists and such that statements about standard conformance have become next to meaningless. Consequently, i now remain reluctantly silent regarding CSS standard(s) conformance. Going back to CSS2.1, published in 2011, which was the last CSS standard in the proper sense of the word, is not an option because it has gaping holes in functionality and is no longer adequate for use on today's WWW.
* #include <stddef.h>, needed for NULL; bug reported by op@Ingo Schwarze2022-06-211-0/+2
|
* When looking for the next block to tag, we aren't interested in childrenIngo Schwarze2022-06-081-1/+2
| | | | | of the current block but really want the next block instead. This fixes a segfault reported by Evan Silberman <evan at jklol dot net> on bugs@.
* Surprisingly, every escape sequence can also be used as an argumentIngo Schwarze2022-06-0829-52/+1053
| | | | | | | delimiter for an outer escape sequence, in which case the delimiting escape sequence retains its syntax but usually ignores its argument and loses its inherent effect. Add rudimentary support for this syntax quirk in order to improve parsing compatibility with groff.
* Split the excessively generic diagnostic message "invalid escape sequence"Ingo Schwarze2022-06-0710-21/+44
| | | | | into the more specific messages "invalid escape argument delimiter" and "invalid escape sequence argument".
* Purge duplicate error reporting from the .tr request parser:Ingo Schwarze2022-06-071-11/+2
| | | | | the error was already reported earlier when roff_expand() called roff_escape().
* To better match groff parsing, reject digits and some mathematicalIngo Schwarze2022-06-061-7/+9
| | | | | | | | | | | | | | | | | | operators as argument delimiters for some escape sequences that take numerical arguments, in the same way as it had already been done for \h. Argument delimiter parsing for escape sequences taking numerical arguments is not perfect yet. In particular, when a character representing a scaling unit is abused as the argument delimiter, parsing for that character becomes context-dependent, and it is no longer possible to find the end of the escape sequence without calling the full numerical expression parser, which i refrain from attempting in this commit. For now, continuing to misparse insane constructions like \Bc1c+1cc (which is valid in groff and resolves to "1" because 1c+1c = two centimeters is a valid numerical expression and 'c' is also a valid delimiter) is a small price to pay for keeping complexity at bay and for not losing focus in the ongoing series of refinements.
* adjust two desired error messages after roff_escape.c rev. 1.11Ingo Schwarze2022-06-061-2/+2
| | | | improved diagnostics for the \C escape sequence
* Allow arbitrary argument delimiters for \C, like groff does.Ingo Schwarze2022-06-061-4/+5
| | | | | | | | | The restriction of only allowing ' as the delimiter was introduced by kristaps@ on 2011/04/09 when he first supported \C. For most other escape sequences, similar restrictions were relaxed later on, but for the rarely used \C, it was apparently forgotten. While here, reject empty character names: they are never valid.
* add and update a few entriesIngo Schwarze2022-06-061-0/+11
|
* With the improved escape sequence parser, it becomes easy to also improveIngo Schwarze2022-06-0516-96/+147
| | | | | | | | | diagnostics. Distinguish "incomplete escape sequence", "invalid special character", and "unknown special character" from the generic "invalid escape sequence", also promoting them from WARNING to ERROR because incomplete escape sequences are severe syntax violations and because encountering an invalid or unknown special character makes it likely that part of the document content intended by the authors gets lost.
* Small cleanup of error reporting:Ingo Schwarze2022-06-051-11/+12
| | | | | | | call mandoc_msg() only once at the end, not sometimes in the middle, classify incomplete, non-expanding escape sequences as ESCAPE_ERROR, and also reduce the number of return statemants; no formatting change intended.
* During identifier parsing, handle undefined escape sequencesIngo Schwarze2022-06-0318-58/+222
| | | | | | | | | | | | | | | | | | | | | | in the same way as groff: * \\ is always reduced to \ * \. is always reduced to . * other undefined escape sequences are usually reduced to the escape name, for example \G to G, except during the expansion of expanding escape sequences having the standard argument form (in particular \* and \n), in which case the backslash is preserved literally. Yes, this is confusing indeed. For example, the following have the same meaning: * .ds \. and .ds . which is not the same as .ds \\. * \*[\.] and \*[.] which is not the same as \*[\\.] * .ds \G and .ds G which is not the same as .ds \\G * \*[\G] and \*[\\G] which is not the same as \*[G] <- sic! To feel less dirty, have a leaning toothpick, if you are so inclined. This patch also slightly improves the string shown by the "escaped character not allowed in a name" error message.
* Since \. is not a character escape sequence, re-classify it from theIngo Schwarze2022-06-023-11/+15
| | | | | | | | | | | | | wrong parsing class ESCAPE_SPECIAL to the better-suited parsing class ESCAPE_UNDEF, exactly like it is already done for the similar \\, which isn't a character escape sequence either. No formatting change is intended just yet, but this will matter for upcoming improvements in the parser for roff(7) macro, string, and register names. See the node "5.23.2 Copy Mode" in "info groff" regarding what \\ and \. really mean.
* Avoid the layering violation of re-parsing for \E in roff_expand().Ingo Schwarze2022-06-023-31/+25
| | | | | | | | | To that end, add another argument to roff_escape() returning the index of the escape name. This also makes the code in roff_escape() a bit more uniform in so far as it no longer needs the "char esc_name" local variable but now does everything with indices into buf[]. No functional change.
* Fix a buffer overrun in the roff(7) escape sequence parser that couldIngo Schwarze2022-06-011-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | be triggered by macro arguments ending in double backslashes, for example if people wrote .Sq "\\" instead of the correct .Sq "\e". The bug was hard to find because it caused a segfault only very rarely, according to my measurements with a probability of less than one permille. I'm sorry that the first one to hit the bug was an arm64 release build run by deraadt@. Thanks to bluhm@ for providing access to an arm64 machine for debugging purposes. In the end, the bug turned out to be architecture-independent. The reason for the bug was that i assumed an invariant that does not exist. The function roff_parse_comment() is very careful to make sure that the input buffer does not end in an escape character before passing it on, so i assumed this is still true when reaching roff_expand() immediately afterwards. But roff_expand() can also be reached from roff_getarg(), in which case there *can* be a lone escape character at the end of the buffer in case copy mode processing found and converted a double backslash. Fix this by handling a trailing escape character correctly in the function roff_escape(). The lesson here probably is to refrain from assuming an invariant unless verifying that the invariant actually holds is reasonably simple. In some cases, in particular for invariants that are important but not simple, it might also make sense to assert(3) rather than just assume the invariant. An assertion failure is so much better than a buffer overrun...
* Rudimentary implementation of the \A escape sequence, following groffIngo Schwarze2022-05-313-5/+40
| | | | | | | | | | | | | | | | | | | | semantics (test identifier for syntactical validity), not at all following the completely unrelated Heirloom semantics (define hyperlink target position). The main motivation for providing this implementation is to get \A into the parsing class ESCAPE_EXPAND that corresponds to groff parsing behaviour, which is quite similar to the \B escape sequence (test numerical expression for syntactical validity). This is likely to improve parsing of nested escape sequences in the future. Validation isn't perfect yet. In particular, this implementation rejects \A arguments containing some escape sequences that groff allows to slip through. But that is unlikely to cause trouble even in documents using \A for non-trivial purposes. Rejecting the nested escapes in question might even improve robustnest because the rejected names are unlikely to really be usable for practical purposes - no matter that groff dubiously considers them syntactically valid.
* Trivial patch to put the roff(7) \g (interpolate format of register)Ingo Schwarze2022-05-313-2/+5
| | | | | | | | | | | | | escape sequence into the correct parsing class, ESCAPE_EXPAND. Expansion of \g is supposed to work exactly like the expansion of the related escape sequence \n (interpolate register value), but since we ignore the .af (assign output format) request, we just interpolate an empty string to replace the \g sequence. Surprising as it may seem, this actually makes a formatting difference for deviate input like ".O\gNx" which used to raise bogus "escaped character not allowed in a name" and "skipping unknown macro" errors and printed nothing, whereas now it correctly prints "OpenBSD".
* Dummy implementation of the roff(7) \V (interpolate environment variable)Ingo Schwarze2022-05-307-9/+47
| | | | | | | | | escape sequence. This is needed to get \V into the correct parsing class, ESCAPE_EXPAND. It is intentional that mandoc(1) output is *not* influenced by environment variables, so interpolate the name of the variable with some decorating punctuation rather than interpolating its value.
* Re-classify the roff(7) \r (reverse line feed) escape sequenceIngo Schwarze2022-05-206-10/+36
| | | | | | | from "ignore" to "unsupported" because when an input file uses it, mandoc(1) is likely to significantly misformat the output, usually showing parts of the output in a different order than the author intended.
* Test the handling of some additional one-character escape sequencesIngo Schwarze2022-05-203-13/+43
| | | | | that take no argument and are ignored: \% \& \^ \a \d \t \u \{ \| \} No change to parsing or formatting needed.
* following the fixed parsing direction of roff_expand() in roff.c rev. 1.388,Ingo Schwarze2022-05-193-29/+29
| | | | some diagnostics now appear in a more reasonable order, too
* Adjust a column number in an error messageIngo Schwarze2022-05-191-1/+1
| | | | | | | | | | | | | | | | | | | | after the roff_expand() reorganization in roff.c rev. 1.388. The new parsing direction has two effects: 1. Correct output when a line contains more than one expanding escape sequence that has a side effect. 2. Column numbers in diagnostic messages now report the changed column numbers after any expansions left of them have taken place; in the past, column numbers refered to the original input line. Arguably, item 2 was a bit better in its old state, but slightly less helpful diagnostics are a small price to pay for correct output. Besides, when the expansion of user-defined strings or macros is involved, in many cases, mandoc(1) is already unable to report meaningful line and column numbers, so item 2 is not a noteworthy regression. The effort and code complication for fixing that would probably be excessive, in particular since well-written manual pages are not supposed to use such features in the first place.
* fix a wrong column number that got fixed as a side effectIngo Schwarze2022-05-191-1/+1
| | | | of the roff_expand() reorganization in roff.c rev. 1.388
* remove a bogus warning that went away as a side effectIngo Schwarze2022-05-191-1/+0
| | | | of the roff_expand() reorganization in roff.c rev. 1.388
* Make roff_expand() parse left-to-right rather than right-to-left.Ingo Schwarze2022-05-196-646/+677
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some escape sequences have side effects on global state, implying that the order of evaluation matters. For example, this fixes the long-standing bug that "\n+x\n+x\n+x" after ".nr x 0 1" used to print "321"; now it correctly prints "123". Right-to-left parsing was convenient because it implicitly handled nested escape sequences. With correct left-to-right parsing, nesting now requires an explicit implementation, here solved as follows: 1. Handle nested expanding escape sequences iteratively. When finding one, expand it, then retry parsing the enclosing escape sequence from the beginning, which will ultimately succeed as soon as it no longer contains any nested expanding escape sequences. 2. Handle nested non-expanding escape sequences recursively. When finding one, the escape sequence parser calls itself to find the end of the inner sequence, then continues parsing the outer sequence after that point. This requires the mandoc_escape() function to operate in two different modes. The roff(7) parser uses it in a mode where it generates diagnostics and may return an expansion request instead of a parse result. All other callers, in particular the formatters, use it in a simpler mode that never generates diagnostics and always returns a definite parsing result, but that requires all expanding escape sequences to already have been expanded earlier. The bulk of the code is the same for both modes. Since this required a major rewrite of the function anyway, move it into its own new file roff_escape.c and out of the file mandoc.c, which was misnamed in the first place and lacks a clear focus. As a side benefit, this also fixes a number of assertion failures that tb@ found with afl(1), for example "\n\\\\*0", "\v\-\\*0", and "\w\-\\\\\$0*0". As another side benefit, it also resolves some code duplication between mandoc_escape() and roff_expand() and centralizes all handling of escape sequences (except for expansion) in roff_escape.c, hopefully easing maintenance and feature improvements in the future. While here, also move end-of-input handling out of the complicated function roff_expand() and into the simpler function roff_parse_comment(), making the logic easier to understand. Since this is a major reorganization of a central component of mandoc(1), stability of the program might slightly suffer for a few weeks, but i believe that's not a problem at this point of the release cycle. The new code already satisfies the regression suite, but more tweaking and regression testing to further improve the handling of various escape sequences will likely follow in the near future.