3 # Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
5 # Permission to use, copy, modify, and distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 # Dramatically overhauled by Tim Kientzle. This version almost
18 # handles library-style pages with Fn, Ft, etc commands. Still
19 # a lot of problems...
29 # Add a word with appropriate preceding whitespace
30 # Maintain a short queue of the expected upcoming word separators.
37 # Add a word with no following whitespace
38 # Use for opening punctuation such as '('
39 function addopen(str) {
44 # Add a word with no preceding whitespace
45 # Use for closing punctuation such as ')' or '.'
46 function addclose(str) {
51 # Add a word with no space before or after
52 # Use for separating punctuation such as '='
53 function addpunct(str) {
59 # Emit the current line so far
67 if(displaylines > 0) {
68 displaylines = displaylines - 1
69 if (displaylines == 0)
72 # First word on next line has no preceding whitespace
76 function linecmd(cmd) {
82 function breakline() {
86 # Start an indented display
87 function dispstart() {
91 # End an indented display
96 # Collect rest of input line
102 retval=retval words[++w]
107 function splitwords(l, dest, n, o, w) {
110 while (length(l) > 0) {
111 sub("^[ \t]*", "", l)
112 if (match(l, "^\"")) {
116 w = substr(l, 1, o-1)
124 o = match(l, "[ \t]")
126 w = substr(l, 1, o-1)
148 nwords=splitwords($0, words)
149 # TODO: Instead of iterating 'w' over the array, have a separate
150 # function that returns 'next word' and use that. This will allow
151 # proper handling of double-quoted arguments as well.
152 for(w=1;w<=nwords;w++) {
153 if(match(words[w],"^Li$")) { # Literal; rest of line is unformatted
156 } else if(match(words[w],"^Dl$")) { # Display literal
159 } else if(match(words[w],"^Bd$")) { # Begin display
160 if(match(words[w+1],"-literal")) {
166 } else if(match(words[w],"^Ed$")) { # End display
169 } else if(match(words[w],"^Ns$")) { # Suppress space after next word
171 } else if(match(words[w],"^No$")) { # Normal text
173 } else if(match(words[w],"^Dq$")) { # Quote
176 while(w<nwords&&!match(words[w+1],"^[\\.,]"))
179 } else if(match(words[w],"^Do$")) {
181 } else if(match(words[w],"^Dc$")) {
183 } else if(match(words[w],"^Oo$")) {
185 } else if(match(words[w],"^Oc$")) {
187 } else if(match(words[w],"^Ao$")) {
189 } else if(match(words[w],"^Ac$")) {
191 } else if(match(words[w],"^Dd$")) {
194 } else if(match(words[w],"^Dt$")) {
197 } else if(match(words[w],"^Ox$")) {
199 } else if(match(words[w],"^Fx$")) {
201 } else if(match(words[w],"^Nx$")) {
203 } else if(match(words[w],"^St$")) {
204 if (match(words[w+1], "^-p1003.1$")) {
206 add("IEEE Std 1003.1 (``POSIX.1'')")
207 } else if(match(words[w+1], "^-p1003.1-96$")) {
209 add("ISO/IEC 9945-1:1996 (``POSIX.1'')")
210 } else if(match(words[w+1], "^-p1003.1-88$")) {
212 add("IEEE Std 1003.1-1988 (``POSIX.1'')")
213 } else if(match(words[w+1], "^-p1003.1-2001$")) {
215 add("IEEE Std 1003.1-2001 (``POSIX.1'')")
216 } else if(match(words[w+1], "^-susv2$")) {
218 add("Version 2 of the Single UNIX Specification (``SUSv2'')")
220 } else if(match(words[w],"^Ex$")) {
221 if (match(words[w+1], "^-std$")) {
223 add("The \\fB" name "\\fP utility exits 0 on success, and >0 if an error occurs.")
225 } else if(match(words[w],"^Os$")) {
226 add(".TH " id " \"" date "\" \"" wtail() "\"")
227 } else if(match(words[w],"^Sh$")) {
231 } else if(match(words[w],"^Xr$")) {
232 add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
233 } else if(match(words[w],"^Nm$")) {
234 if(match(section,"SYNOPSIS"))
238 else if (match(words[w+1], "^[A-Z][a-z]$"))
240 else if (match(words[w+1], "^[.,;:]$"))
249 add("\\fB\\%" n "\\fP")
250 } else if(match(words[w],"^Nd$")) {
252 } else if(match(words[w],"^Fl$")) {
253 add("\\fB\\-" words[++w] "\\fP")
254 } else if(match(words[w],"^Ar$")) {
259 add(words[++w] "\\fP")
260 } else if(match(words[w],"^Cm$")) {
261 add("\\fB" words[++w] "\\fP")
262 } else if(match(words[w],"^Op$")) {
266 } else if(match(words[w],"^Pp$")) {
268 } else if(match(words[w],"^An$")) {
270 } else if(match(words[w],"^Ss$")) {
272 } else if(match(words[w],"^Ft$")) {
273 if (match(section, "SYNOPSIS")) {
276 add("\\fI" wtail() "\\fP")
277 if (match(section, "SYNOPSIS")) {
280 } else if(match(words[w],"^Fn$")) {
282 F = "\\fB\\%" words[w] "\\fP("
286 if (match(words[w], "^[.,:]$")) {
290 gsub(" ", "\\ ", words[w])
291 F = F Fsep "\\fI\\%" words[w] "\\fP"
295 if (match(section, "SYNOPSIS")) {
298 } else if(match(words[w],"^Fo$")) {
300 F = "\\fB\\%" words[w] "\\fP("
302 } else if(match(words[w],"^Fa$")) {
304 gsub(" ", "\\ ", words[w])
305 F = F Fsep "\\fI\\%" words[w] "\\fP"
307 } else if(match(words[w],"^Fc$")) {
309 if (match(section, "SYNOPSIS")) {
312 } else if(match(words[w],"^Va$")) {
314 add("\\fI" words[w] "\\fP")
315 } else if(match(words[w],"^In$")) {
317 add("\\fB#include <" words[w] ">\\fP")
318 } else if(match(words[w],"^Pa$")) {
321 if(match(words[w],"^\\."))
324 } else if(match(words[w],"^Dv$")) {
326 } else if(match(words[w],"^Em|Ev$")) {
328 } else if(match(words[w],"^Pq$")) {
331 } else if(match(words[w],"^Aq$")) {
334 } else if(match(words[w],"^Brq$")) {
337 } else if(match(words[w],"^S[xy]$")) {
339 } else if(match(words[w],"^Ic$")) {
341 trailer="\\fP" trailer
342 } else if(match(words[w],"^Bl$")) {
345 if(match(words[w+1],"-bullet"))
347 else if(match(words[w+1],"-enum")) {
350 } else if(match(words[w+1],"-tag"))
352 else if(match(words[w+1],"-item"))
354 else if(match(words[w+1],"-bullet"))
357 } else if(match(words[w],"^El$")) {
360 } else if(match(words[w],"^It$")&&optlist) {
364 add(".IP " ++enum ".")
365 else if(optlist==3) {
368 if(match(words[w+1],"^Pa$|^Ev$")) {
372 } else if(optlist==4)
374 } else if(match(words[w],"^Xo$")) {
375 # TODO: Figure out how to handle this
376 } else if(match(words[w],"^Xc$")) {
377 # TODO: Figure out how to handle this
378 } else if(match(words[w],"^[=]$")) {
380 } else if(match(words[w],"^[[{(]$")) {
382 } else if(match(words[w],"^[\\])}.,;:]$")) {
388 if(match(out,"^\\.[^a-zA-Z]"))