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]"))