blob: f2d794539a73d91b58572264352555a89f20b786 [file] [log] [blame]
Ben Lindstrome68c5672001-02-22 06:20:10 +00001#!/usr/bin/perl
2###
Damien Miller897741e2001-04-16 10:41:46 +10003### Quick usage: mdoc2man.pl < mdoc_manpage.8 > man_manpage.8
Ben Lindstrome68c5672001-02-22 06:20:10 +00004###
5###
6### Copyright (c) 2001 University of Illinois Board of Trustees
7### Copyright (c) 2001 Mark D. Roth
8### All rights reserved.
9###
10### Redistribution and use in source and binary forms, with or without
11### modification, are permitted provided that the following conditions
12### are met:
13### 1. Redistributions of source code must retain the above copyright
14### notice, this list of conditions and the following disclaimer.
15### 2. Redistributions in binary form must reproduce the above copyright
16### notice, this list of conditions and the following disclaimer in the
17### documentation and/or other materials provided with the distribution.
18### 3. All advertising materials mentioning features or use of this software
19### must display the following acknowledgement:
20### This product includes software developed by the University of
21### Illinois at Urbana, and their contributors.
22### 4. The University nor the names of their
23### contributors may be used to endorse or promote products derived from
24### this software without specific prior written permission.
25###
26### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND
27### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29### ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE
30### FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31### DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32### OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33### HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34### LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35### OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36### SUCH DAMAGE.
37###
38
39use strict;
40
41my ($name, $date, $id);
42my ($line);
43my ($optlist, $nospace, $enum, $synopsis);
44
45
46$optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag
47$nospace = 0;
48$synopsis = 0;
49
50while ($line = <STDIN>)
51{
52 if ($line !~ /^\./)
53 {
54 print $line;
55 next;
56 }
57
58 $line =~ s/^\.//;
59
60 next
61 if ($line =~ m/\\"/);
62
63 $line = ParseMacro($line);
64 print($line)
65 if (defined $line);
66}
67
68
69
70sub ParseMacro # ($line)
71{
72 my ($line) = @_;
73 my (@words, $retval, $option, $parens, $arg);
74
75 @words = split(/\s+/, $line);
76 $retval = '';
77 $option = 0;
78 $parens = 0;
79 $arg = 0;
80
81# print('@words = ', scalar(@words), ': ', join(' ', @words), "\n");
82
83 while ($_ = shift @words)
84 {
85# print "WORD: $_\n";
86
87 next
88 if (/^(Li|Pf|X[oc])$/);
89
90 if (/^Ns/)
91 {
92 $nospace = 1
93 if (! $nospace);
94 $retval =~ s/ $//;
95 next;
96 }
97
98 if (/^No/)
99 {
100 $retval =~ s/ $//;
101 $retval .= shift @words;
102 next;
103 }
104
105 if (/^Dq$/) {
106 $retval .= '``' . (shift @words) . '\'\'';
107 $nospace = 1
108 if (! $nospace && $words[0] =~ m/^[\.,]/);
109 next;
110 }
111
112 if (/^(Sq|Ql)$/) {
113 $retval .= '`' . (shift @words) . '\'';
114 $nospace = 1
115 if (! $nospace && $words[0] =~ m/^[\.,]/);
116 next;
117 }
118
119 $retval .= ' '
120 if (! $nospace && $retval ne '' && $retval !~ m/[\n ]$/);
121 $nospace = 0
122 if ($nospace == 1);
123
124 if (/^Dd$/) {
125 $date = join(' ', @words);
126 return undef;
127 }
128
129 if (/^Dt$/) {
130 $id = join(' ', @words);
131 return undef;
132 }
133
134 if (/^Os$/) {
135 $retval .= '.TH '
136 . $id
137 . " \"$date\" \""
138 . join(' ', @words)
139 . "\"";
140 last;
141 }
142
143 if (/^Sh$/) {
144 $retval .= '.SH';
145 if ($words[0] eq 'SYNOPSIS')
146 {
147 $synopsis = 1;
148 }
149 else
150 {
151 $synopsis = 0;
152 }
153 next;
154 }
155
156 if (/^Xr$/) {
157 $retval .= '\\fB' . (shift @words) .
158 '\\fR(' . (shift @words) . ')'
159 . (shift @words);
160 last;
161 }
162
163 if (/^Nm$/) {
164 $name = shift @words
165 if (@words > 0);
166 $retval .= ".br\n"
167 if ($synopsis);
168 $retval .= "\\fB$name\\fR";
169 $nospace = 1
170 if (! $nospace && $words[0] =~ m/^[\.,]/);
171 next;
172 }
173
174 if (/^Nd$/) {
175 $retval .= '\\-';
176 next;
177 }
178
179 if (/^Fl$/) {
180 $retval .= '\\fB\\-' . (shift @words) . '\\fR';
181 $nospace = 1
182 if (! $nospace && $words[0] =~ m/^[\.,]/);
183 next;
184 }
185
186 if (/^Ar$/) {
187 $retval .= '\\fI';
188 if (! defined $words[0])
189 {
190 $retval .= 'file ...\\fR';
191 }
192 $arg = 1;
193 $nospace = 1
194 if (! $nospace);
195 next;
196 }
197
198 if (/^Cm$/) {
199 $retval .= '\\fB' . (shift @words) . '\\fR';
200 next;
201 }
202
203 if (/^Op$/) {
204 $option = 1;
205 $nospace = 1
206 if (! $nospace);
207 $retval .= '[';
208 next;
209 }
210
211 if (/^Oo$/) {
212 $retval .= "[\\c\n";
213 next;
214 }
215
216 if (/^Oc$/) {
217 $retval .= ']';
218 next;
219 }
220
221 if (/^Pp$/) {
222 if ($optlist) {
223 $retval .= "\n";
224 } else {
225 $retval .= '.LP';
226 }
227 next;
228 }
229
230 if (/^Ss$/) {
231 $retval .= '.SS';
232 next;
233 }
234
235 if (/^Pa$/ && ! $option) {
236 $retval .= '\\fI';
237 $retval .= '\\&'
238 if ($words[0] =~ m/^\./);
239 $retval .= (shift @words) . '\\fR';
240 $nospace = 1
241 if (! $nospace && $words[0] =~ m/^[\.,]/);
242 next;
243 }
244
245 if (/^Dv$/) {
246 $retval .= '.BR';
247 next;
248 }
249
250 if (/^(Em|Ev)$/) {
251 $retval .= '.IR';
252 next;
253 }
254
255 if (/^Pq$/) {
256 $retval .= '(';
257 $nospace = 1;
258 $parens = 1;
259 next;
260 }
261
262 if (/^(S[xy])$/) {
263 $retval .= '.B ' . join(' ', @words);
264 last;
265 }
266
267 if (/^Ic$/)
268 {
269 $retval .= '\\fB';
270 while (defined $words[0]
271 && $words[0] !~ m/^[\.,]/)
272 {
273 $retval .= shift @words;
274 $retval .= ' '
275 if (! $nospace);
276 }
277 $retval =~ s/ $//;
278 $retval .= '\\fR';
279 $retval .= shift @words
280 if (defined $words[0]);
281 last;
282 }
283
284 if (/^Bl$/) {
285 if ($words[0] eq '-bullet') {
286 $optlist = 1;
287 } elsif ($words[0] eq '-enum') {
288 $optlist = 2;
289 $enum = 0;
290 } elsif ($words[0] eq '-tag') {
291 $optlist = 3;
292 }
293 last;
294 }
295
296 if (/^El$/) {
297 $optlist = 0;
298 next;
299 }
300
301 if ($optlist && /^It$/) {
302 if ($optlist == 1) {
303 # bullets
304 $retval .= '.IP \\(bu';
305 next;
306 }
307
308 if ($optlist == 2) {
309 # enum
310 $retval .= '.IP ' . (++$enum) . '.';
311 next;
312 }
313
314 if ($optlist == 3) {
315 # tags
316 $retval .= ".TP\n";
317 if ($words[0] =~ m/^(Pa|Ev)$/)
318 {
319 shift @words;
320 $retval .= '.B';
321 }
322 next;
323 }
324
325 next;
326 }
327
328 if (/^Sm$/) {
329 if ($words[0] eq 'off') {
330 $nospace = 2;
331 } elsif ($words[0] eq 'on') {
332 $retval .= "\n";
333 $nospace = 0;
334 }
335 shift @words;
336 next;
337 }
338
339 $retval .= "$_";
340 }
341
342 return undef
343 if ($retval eq '.');
344
345 $retval =~ s/^\.([^a-zA-Z])/$1/;
346 $retval =~ s/ $//;
347
348 $retval .= ')'
349 if ($parens == 1);
350
351 $retval .= ']'
352 if ($option == 1);
353
354 $retval .= '\\fR'
355 if ($arg);
356
357 $retval .= '\\c'
358 if ($nospace && $retval ne '' && $retval !~ m/\n$/);
359
360 $retval .= "\n"
361 if ($retval ne '' && $retval !~ m/\n$/);
362
363 return $retval;
364}