blob: fddb2e09d06df313cb55a4ea71ff1e5605dc602a [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);
Tim Rice45344922001-04-29 18:01:51 -070043my ($optlist, $oldoptlist, $nospace, $enum, $synopsis);
44my ($reference, $block, $ext, $extopt, $literal);
45my (@refauthors, $reftitle, $refissue, $refdate, $refopt);
Ben Lindstrome68c5672001-02-22 06:20:10 +000046
47
Tim Rice45344922001-04-29 18:01:51 -070048$optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag, 4 = item
49$oldoptlist = 0;
Ben Lindstrome68c5672001-02-22 06:20:10 +000050$nospace = 0;
51$synopsis = 0;
Tim Rice45344922001-04-29 18:01:51 -070052$reference = 0;
53$block = 0;
54$ext = 0;
55$extopt = 0;
56$literal = 0;
Ben Lindstrome68c5672001-02-22 06:20:10 +000057
58while ($line = <STDIN>)
59{
60 if ($line !~ /^\./)
61 {
62 print $line;
Tim Rice45344922001-04-29 18:01:51 -070063 print ".br\n"
64 if ($literal);
Ben Lindstrome68c5672001-02-22 06:20:10 +000065 next;
66 }
67
68 $line =~ s/^\.//;
69
70 next
71 if ($line =~ m/\\"/);
72
73 $line = ParseMacro($line);
74 print($line)
75 if (defined $line);
76}
77
78
79
80sub ParseMacro # ($line)
81{
82 my ($line) = @_;
Tim Rice45344922001-04-29 18:01:51 -070083 my (@words, $retval, $option, $parens);
Ben Lindstrome68c5672001-02-22 06:20:10 +000084
85 @words = split(/\s+/, $line);
86 $retval = '';
87 $option = 0;
88 $parens = 0;
Ben Lindstrome68c5672001-02-22 06:20:10 +000089
90# print('@words = ', scalar(@words), ': ', join(' ', @words), "\n");
91
92 while ($_ = shift @words)
93 {
94# print "WORD: $_\n";
95
96 next
Tim Rice45344922001-04-29 18:01:51 -070097 if (/^(Li|Pf)$/);
Ben Lindstrome68c5672001-02-22 06:20:10 +000098
Tim Rice45344922001-04-29 18:01:51 -070099 if (/^Xo$/)
100 {
101 $ext = 1;
102 $retval .= ' '
103 if ($retval ne '' && $retval !~ m/[\n ]$/);
104 next;
105 }
106
107 if (/^Xc$/)
108 {
109 $ext = 0;
110 $retval .= "\n"
111 if (! $extopt);
112 last;
113 }
114
115 if (/^Bd$/)
116 {
117 $literal = 1
118 if ($words[0] eq '-literal');
119 $retval .= "\n";
120 last;
121 }
122
123 if (/^Ed$/)
124 {
125 $literal = 0;
126 last;
127 }
128
129 if (/^Ns$/)
Ben Lindstrome68c5672001-02-22 06:20:10 +0000130 {
131 $nospace = 1
132 if (! $nospace);
133 $retval =~ s/ $//;
134 next;
135 }
136
Tim Rice45344922001-04-29 18:01:51 -0700137 if (/^No$/)
Ben Lindstrome68c5672001-02-22 06:20:10 +0000138 {
139 $retval =~ s/ $//;
140 $retval .= shift @words;
141 next;
142 }
143
Tim Rice45344922001-04-29 18:01:51 -0700144 if (/^Dq$/)
145 {
146 $retval .= '``';
147 do
148 {
149 $retval .= (shift @words) . ' ';
150 }
151 while (@words > 0 && $words[0] !~ m/^[\.,]/);
152 $retval =~ s/ $//;
153 $retval .= '\'\'';
Ben Lindstrome68c5672001-02-22 06:20:10 +0000154 $nospace = 1
155 if (! $nospace && $words[0] =~ m/^[\.,]/);
156 next;
157 }
158
Tim Rice45344922001-04-29 18:01:51 -0700159 if (/^(Sq|Ql)$/)
160 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000161 $retval .= '`' . (shift @words) . '\'';
162 $nospace = 1
163 if (! $nospace && $words[0] =~ m/^[\.,]/);
164 next;
165 }
166
Tim Rice45344922001-04-29 18:01:51 -0700167# if (/^Ic$/)
168# {
169# $retval .= '\\fB' . shift(@words) . '\\fP';
170# next;
171# }
172
173 if (/^Oo$/)
174 {
175# $retval .= "[\\c\n";
176 $extopt = 1;
177 $nospace = 1
178 if (! $nospace);
179 $retval .= '[';
180 next;
181 }
182
183 if (/^Oc$/)
184 {
185 $extopt = 0;
186 $retval .= ']';
187 next;
188 }
189
Ben Lindstrome68c5672001-02-22 06:20:10 +0000190 $retval .= ' '
191 if (! $nospace && $retval ne '' && $retval !~ m/[\n ]$/);
192 $nospace = 0
193 if ($nospace == 1);
194
Tim Rice45344922001-04-29 18:01:51 -0700195 if (/^Dd$/)
196 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000197 $date = join(' ', @words);
198 return undef;
199 }
200
Tim Rice45344922001-04-29 18:01:51 -0700201 if (/^Dt$/)
202 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000203 $id = join(' ', @words);
204 return undef;
205 }
206
Tim Rice45344922001-04-29 18:01:51 -0700207 if (/^Os$/)
208 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000209 $retval .= '.TH '
210 . $id
211 . " \"$date\" \""
212 . join(' ', @words)
213 . "\"";
214 last;
215 }
216
Tim Rice45344922001-04-29 18:01:51 -0700217 if (/^Sh$/)
218 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000219 $retval .= '.SH';
220 if ($words[0] eq 'SYNOPSIS')
221 {
222 $synopsis = 1;
223 }
224 else
225 {
226 $synopsis = 0;
227 }
228 next;
229 }
230
Tim Rice45344922001-04-29 18:01:51 -0700231 if (/^Xr$/)
232 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000233 $retval .= '\\fB' . (shift @words) .
Tim Rice45344922001-04-29 18:01:51 -0700234 '\\fP(' . (shift @words) . ')'
Ben Lindstrome68c5672001-02-22 06:20:10 +0000235 . (shift @words);
236 last;
237 }
238
Tim Rice45344922001-04-29 18:01:51 -0700239 if (/^Rs/)
240 {
241 @refauthors = ();
242 $reftitle = '';
243 $refissue = '';
244 $refdate = '';
245 $refopt = '';
246 $reference = 1;
247 last;
248 }
249
250 if (/^Re/)
251 {
252 $retval .= "\n";
253
254 # authors
255 while (scalar(@refauthors) > 1)
256 {
257 $retval .= shift(@refauthors) . ', ';
258 }
259 $retval .= 'and '
260 if ($retval ne '');
261 $retval .= shift(@refauthors);
262
263 # title
264 $retval .= ', \\fI' . $reftitle . '\\fP';
265
266 # issue
267 $retval .= ', ' . $refissue
268 if ($refissue ne '');
269
270 # date
271 $retval .= ', ' . $refdate
272 if ($refdate ne '');
273
274 # optional info
275 $retval .= ', ' . $refopt
276 if ($refopt ne '');
277
278 $retval .= ".\n";
279
280 $reference = 0;
281 last;
282 }
283
284 if ($reference)
285 {
286 if (/^%A$/)
287 {
288 unshift(@refauthors, join(' ', @words));
289 last;
290 }
291
292 if (/^%T$/)
293 {
294 $reftitle = join(' ', @words);
295 $reftitle =~ s/^"//;
296 $reftitle =~ s/"$//;
297 last;
298 }
299
300 if (/^%N$/)
301 {
302 $refissue = join(' ', @words);
303 last;
304 }
305
306 if (/^%D$/)
307 {
308 $refdate = join(' ', @words);
309 last;
310 }
311
312 if (/^%O$/)
313 {
314 $refopt = join(' ', @words);
315 last;
316 }
317 }
318
319 if (/^Nm$/)
320 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000321 $name = shift @words
322 if (@words > 0);
323 $retval .= ".br\n"
324 if ($synopsis);
Tim Rice45344922001-04-29 18:01:51 -0700325 $retval .= "\\fB$name\\fP";
Ben Lindstrome68c5672001-02-22 06:20:10 +0000326 $nospace = 1
327 if (! $nospace && $words[0] =~ m/^[\.,]/);
328 next;
329 }
330
Tim Rice45344922001-04-29 18:01:51 -0700331 if (/^Nd$/)
332 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000333 $retval .= '\\-';
334 next;
335 }
336
Tim Rice45344922001-04-29 18:01:51 -0700337 if (/^Fl$/)
338 {
339 $retval .= '\\fB\\-' . (shift @words) . '\\fP';
Ben Lindstrome68c5672001-02-22 06:20:10 +0000340 $nospace = 1
341 if (! $nospace && $words[0] =~ m/^[\.,]/);
342 next;
343 }
344
Tim Rice45344922001-04-29 18:01:51 -0700345 if (/^Ar$/)
346 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000347 $retval .= '\\fI';
348 if (! defined $words[0])
349 {
Tim Rice45344922001-04-29 18:01:51 -0700350 $retval .= 'file ...\\fP';
Ben Lindstrome68c5672001-02-22 06:20:10 +0000351 }
Tim Rice45344922001-04-29 18:01:51 -0700352 else
353 {
354 $retval .= shift(@words) . '\\fP';
355 while ($words[0] eq '|')
356 {
357 $retval .= ' ' . shift(@words);
358 $retval .= ' \\fI' . shift(@words);
359 $retval .= '\\fP';
360 }
361 }
Ben Lindstrome68c5672001-02-22 06:20:10 +0000362 $nospace = 1
Tim Rice45344922001-04-29 18:01:51 -0700363 if (! $nospace && $words[0] =~ m/^[\.,]/);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000364 next;
365 }
366
Tim Rice45344922001-04-29 18:01:51 -0700367 if (/^Cm$/)
368 {
369 $retval .= '\\fB' . (shift @words) . '\\fP';
370 while ($words[0] =~ m/^[\.,:)]$/)
371 {
372 $retval .= shift(@words);
373 }
Ben Lindstrome68c5672001-02-22 06:20:10 +0000374 next;
375 }
376
Tim Rice45344922001-04-29 18:01:51 -0700377 if (/^Op$/)
378 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000379 $option = 1;
380 $nospace = 1
381 if (! $nospace);
382 $retval .= '[';
Tim Rice45344922001-04-29 18:01:51 -0700383# my $tmp = pop(@words);
384# $tmp .= ']';
385# push(@words, $tmp);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000386 next;
387 }
388
Tim Rice45344922001-04-29 18:01:51 -0700389 if (/^Pp$/)
390 {
391 $retval .= "\n";
Ben Lindstrome68c5672001-02-22 06:20:10 +0000392 next;
393 }
394
Tim Rice45344922001-04-29 18:01:51 -0700395 if (/^Ss$/)
396 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000397 $retval .= '.SS';
398 next;
399 }
400
Tim Rice45344922001-04-29 18:01:51 -0700401 if (/^Pa$/ && ! $option)
402 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000403 $retval .= '\\fI';
404 $retval .= '\\&'
405 if ($words[0] =~ m/^\./);
Tim Rice45344922001-04-29 18:01:51 -0700406 $retval .= (shift @words) . '\\fP';
407 while ($words[0] =~ m/^[\.,:;)]$/)
408 {
409 $retval .= shift(@words);
410 }
411# $nospace = 1
412# if (! $nospace && $words[0] =~ m/^[\.,:)]/);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000413 next;
414 }
415
Tim Rice45344922001-04-29 18:01:51 -0700416 if (/^Dv$/)
417 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000418 $retval .= '.BR';
419 next;
420 }
421
Tim Rice45344922001-04-29 18:01:51 -0700422 if (/^(Em|Ev)$/)
423 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000424 $retval .= '.IR';
425 next;
426 }
427
Tim Rice45344922001-04-29 18:01:51 -0700428 if (/^Pq$/)
429 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000430 $retval .= '(';
431 $nospace = 1;
432 $parens = 1;
433 next;
434 }
435
Tim Rice45344922001-04-29 18:01:51 -0700436 if (/^(S[xy])$/)
437 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000438 $retval .= '.B ' . join(' ', @words);
439 last;
440 }
441
442 if (/^Ic$/)
443 {
444 $retval .= '\\fB';
445 while (defined $words[0]
446 && $words[0] !~ m/^[\.,]/)
447 {
Tim Rice45344922001-04-29 18:01:51 -0700448 if ($words[0] eq 'Op')
449 {
450 shift(@words);
451 $retval .= '[';
452 my $tmp = pop(@words);
453 $tmp .= ']';
454 push(@words, $tmp);
455 next;
456 }
457 if ($words[0] eq 'Ar')
458 {
459 shift @words;
460 $retval .= '\\fI';
461 $retval .= shift @words;
462 $retval .= '\\fP';
463 }
464 else
465 {
466 $retval .= shift @words;
467 }
Ben Lindstrome68c5672001-02-22 06:20:10 +0000468 $retval .= ' '
469 if (! $nospace);
470 }
471 $retval =~ s/ $//;
Tim Rice45344922001-04-29 18:01:51 -0700472 $retval .= '\\fP';
Ben Lindstrome68c5672001-02-22 06:20:10 +0000473 $retval .= shift @words
474 if (defined $words[0]);
475 last;
476 }
477
Tim Rice45344922001-04-29 18:01:51 -0700478 if (/^Bl$/)
479 {
480 $oldoptlist = $optlist;
481 if ($words[0] eq '-bullet')
482 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000483 $optlist = 1;
Tim Rice45344922001-04-29 18:01:51 -0700484 }
485 elsif ($words[0] eq '-enum')
486 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000487 $optlist = 2;
488 $enum = 0;
Tim Rice45344922001-04-29 18:01:51 -0700489 }
490 elsif ($words[0] eq '-tag')
491 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000492 $optlist = 3;
493 }
Tim Rice45344922001-04-29 18:01:51 -0700494 elsif ($words[0] eq '-item')
495 {
496 $optlist = 4;
497 }
Ben Lindstrome68c5672001-02-22 06:20:10 +0000498 last;
499 }
500
Tim Rice45344922001-04-29 18:01:51 -0700501 if (/^El$/)
502 {
503 $optlist = $oldoptlist;
Ben Lindstrome68c5672001-02-22 06:20:10 +0000504 next;
505 }
506
Tim Rice45344922001-04-29 18:01:51 -0700507 if ($optlist && /^It$/)
508 {
509 if ($optlist == 1)
510 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000511 # bullets
512 $retval .= '.IP \\(bu';
513 next;
514 }
515
Tim Rice45344922001-04-29 18:01:51 -0700516 if ($optlist == 2)
517 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000518 # enum
519 $retval .= '.IP ' . (++$enum) . '.';
520 next;
521 }
522
Tim Rice45344922001-04-29 18:01:51 -0700523 if ($optlist == 3)
524 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000525 # tags
526 $retval .= ".TP\n";
527 if ($words[0] =~ m/^(Pa|Ev)$/)
528 {
529 shift @words;
530 $retval .= '.B';
531 }
532 next;
533 }
534
Tim Rice45344922001-04-29 18:01:51 -0700535 if ($optlist == 4)
536 {
537 # item
538 $retval .= ".IP\n";
539 next;
540 }
541
Ben Lindstrome68c5672001-02-22 06:20:10 +0000542 next;
543 }
544
Tim Rice45344922001-04-29 18:01:51 -0700545 if (/^Sm$/)
546 {
547 if ($words[0] eq 'off')
548 {
Ben Lindstrome68c5672001-02-22 06:20:10 +0000549 $nospace = 2;
Tim Rice45344922001-04-29 18:01:51 -0700550 }
551 elsif ($words[0] eq 'on')
552 {
553# $retval .= "\n";
Ben Lindstrome68c5672001-02-22 06:20:10 +0000554 $nospace = 0;
555 }
556 shift @words;
557 next;
558 }
559
560 $retval .= "$_";
561 }
562
563 return undef
564 if ($retval eq '.');
565
566 $retval =~ s/^\.([^a-zA-Z])/$1/;
Tim Rice45344922001-04-29 18:01:51 -0700567# $retval =~ s/ $//;
Ben Lindstrome68c5672001-02-22 06:20:10 +0000568
569 $retval .= ')'
570 if ($parens == 1);
571
572 $retval .= ']'
573 if ($option == 1);
574
Tim Rice45344922001-04-29 18:01:51 -0700575# $retval .= ' '
576# if ($nospace && $retval ne '' && $retval !~ m/\n$/);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000577
Tim Rice45344922001-04-29 18:01:51 -0700578# $retval .= ' '
579# if ($extended && $retval !~ m/ $/);
580
581 $retval .= ' '
582 if ($ext && ! $extopt && $retval !~ m/ $/);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000583
584 $retval .= "\n"
Tim Rice45344922001-04-29 18:01:51 -0700585 if (! $ext && ! $extopt && $retval ne '' && $retval !~ m/\n$/);
Ben Lindstrome68c5672001-02-22 06:20:10 +0000586
587 return $retval;
588}
Tim Rice45344922001-04-29 18:01:51 -0700589
590