Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 466 lines (422 sloc) 9.632 kB
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
1 #!/usr/bin/env ruby
2 ###
3 ### mdoc2man - mdoc to man converter
4 ###
5 ### Quick usage: mdoc2man.rb < mdoc_manpage.8 > man_manpage.8
6 ###
7 ### Ported from Perl by Akinori MUSHA.
8 ###
9 ### Copyright (c) 2001 University of Illinois Board of Trustees
10 ### Copyright (c) 2001 Mark D. Roth
11 ### Copyright (c) 2002, 2003 Akinori MUSHA
12 ### All rights reserved.
13 ###
14 ### Redistribution and use in source and binary forms, with or without
15 ### modification, are permitted provided that the following conditions
16 ### are met:
17 ### 1. Redistributions of source code must retain the above copyright
18 ### notice, this list of conditions and the following disclaimer.
19 ### 2. Redistributions in binary form must reproduce the above copyright
20 ### notice, this list of conditions and the following disclaimer in the
21 ### documentation and/or other materials provided with the distribution.
22 ### 3. All advertising materials mentioning features or use of this software
23 ### must display the following acknowledgement:
24 ### This product includes software developed by the University of
25 ### Illinois at Urbana, and their contributors.
26 ### 4. The University nor the names of their
27 ### contributors may be used to endorse or promote products derived from
28 ### this software without specific prior written permission.
29 ###
30 ### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND
31 ### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 ### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 ### ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE
34 ### FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 ### DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 ### OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 ### HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 ### LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 ### OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 ### SUCH DAMAGE.
41 ###
42 ### $Id$
43 ###
44
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
45 class Mdoc2Man
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
46 ANGLE = 1
47 OPTION = 2
48 PAREN = 3
49
50 RE_PUNCT = /^[!"'),\.\/:;>\?\]`]$/
51
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
52 def initialize
53 @name = @date = @id = nil
54 @refauthors = @reftitle = @refissue = @refdate = @refopt = nil
55
56 @optlist = 0 ### 1 = bullet, 2 = enum, 3 = tag, 4 = item
57 @oldoptlist = 0
58 @nospace = 0 ### 0, 1, 2
59 @enum = 0
60 @synopsis = true
61 @reference = false
62 @ext = false
63 @extopt = false
64 @literal = false
65 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
66
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
67 def mdoc2man(i, o)
68 i.each { |line|
69 if /^\./ !~ line
70 o.print line
71 o.print ".br\n" if @literal
72 next
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
73 end
74
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
75 line.slice!(0, 1)
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
76
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
77 next if /\\"/ =~ line
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
78
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
79 line = parse_macro(line) and o.print line
80 }
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
81
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
82 initialize
83 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
84
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
85 def parse_macro(line)
86 words = line.split
87 retval = ''
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
88
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
89 quote = []
90 dl = false
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
91
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
92 while word = words.shift
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
93 case word
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
94 when RE_PUNCT
95 while q = quote.pop
96 case q
97 when OPTION
98 retval << ']'
99 when PAREN
100 retval << ')'
101 when ANGLE
102 retval << '>'
103 end
104 end
105 retval << word
106 next
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
107 when 'Li', 'Pf'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
108 @nospace = 1
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
109 next
110 when 'Xo'
111 @ext = true
112 retval << ' ' unless retval.empty? || /[\n ]\z/ =~ retval
113 next
114 when 'Xc'
115 @ext = false
116 retval << "\n" unless @extopt
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
117 break
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
118 when 'Bd'
119 @literal = true if words[0] == '-literal'
120 retval << "\n"
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
121 break
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
122 when 'Ed'
123 @literal = false
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
124 break
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
125 when 'Ns'
126 @nospace = 1 if @nospace == 0
127 retval.chomp!(' ')
128 next
129 when 'No'
130 retval.chomp!(' ')
131 retval << words.shift
132 next
133 when 'Dq'
134 retval << '``'
135 begin
136 retval << words.shift << ' '
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
137 end until words.empty? || RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
138 retval.chomp!(' ')
139 retval << '\'\''
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
140 @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
141 next
142 when 'Sq', 'Ql'
143 retval << '`' << words.shift << '\''
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
144 @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
145 next
146 # when 'Ic'
147 # retval << '\\fB' << words.shift << '\\fP'
148 # next
149 when 'Oo'
150 #retval << "[\\c\n"
151 @extopt = true
152 @nospace = 1 if @nospace == 0
153 retval << '['
154 next
155 when 'Oc'
156 @extopt = false
157 retval << ']'
158 next
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
159 when 'Ao'
160 @nospace = 1 if @nospace == 0
161 retval << '<'
162 next
163 when 'Ac'
164 retval << '>'
165 next
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
166 end
167
168 retval << ' ' if @nospace == 0 && !(retval.empty? || /[\n ]\z/ =~ retval)
169 @nospace = 0 if @nospace == 1
170
171 case word
172 when 'Dd'
173 @date = words.join(' ')
174 return nil
175 when 'Dt'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
176 if words.size >= 2 && words[1] == '""' &&
177 /^(.*)\(([0-9])\)$/ =~ words[0]
178 words[0] = $1
179 words[1] = $2
180 end
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
181 @id = words.join(' ')
182 return nil
183 when 'Os'
184 retval << '.TH ' << @id << ' "' << @date << '" "' <<
185 words.join(' ') << '"'
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
186 break
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
187 when 'Sh'
188 retval << '.SH'
189 @synopsis = (words[0] == 'SYNOPSIS')
190 next
191 when 'Xr'
192 retval << '\\fB' << words.shift <<
193 '\\fP(' << words.shift << ')' << words.shift
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
194 break
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
195 when 'Rs'
196 @refauthors = []
197 @reftitle = ''
198 @refissue = ''
199 @refdate = ''
200 @refopt = ''
201 @reference = true
202 break
203 when 'Re'
204 retval << "\n"
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
205
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
206 # authors
207 while @refauthors.size > 1
208 retval << @refauthors.shift << ', '
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
209 end
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
210 retval << 'and ' unless retval.empty?
211 retval << @refauthors.shift
212
213 # title
214 retval << ', \\fI' << @reftitle << '\\fP'
215
216 # issue
217 retval << ', ' << @refissue unless @refissue.empty?
218
219 # date
220 retval << ', ' << @refdate unless @refdate.empty?
221
222 # optional info
223 retval << ', ' << @refopt unless @refopt.empty?
224
225 retval << ".\n"
226
227 @reference = false
228 break
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
229 when 'An'
230 next
231 when 'Dl'
232 retval << ".nf\n" << '\\& '
233 dl = true
234 next
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
235 when 'Ux'
236 retval << "UNIX"
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
237 next
238 end
239
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
240 if @reference
241 case word
242 when '%A'
243 @refauthors.unshift(words.join(' '))
244 break
245 when '%T'
246 @reftitle = words.join(' ')
247 @reftitle.sub!(/^"/, '')
248 @reftitle.sub!(/"$/, '')
249 break
250 when '%N'
251 @refissue = words.join(' ')
252 break
253 when '%D'
254 @refdate = words.join(' ')
255 break
256 when '%O'
257 @refopt = words.join(' ')
258 break
259 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
260 end
261
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
262 case word
263 when 'Nm'
264 name = words.empty? ? @name : words.shift
265 @name ||= name
266 retval << ".br\n" if @synopsis
267 retval << "\\fB" << name << "\\fP"
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
268 @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
269 next
270 when 'Nd'
271 retval << '\\-'
272 next
273 when 'Fl'
274 retval << '\\fB\\-' << words.shift << '\\fP'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
275 @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
276 next
277 when 'Ar'
278 retval << '\\fI'
279 if words.empty?
280 retval << 'file ...\\fP'
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
281 else
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
282 retval << words.shift << '\\fP'
283 while words[0] == '|'
284 retval << ' ' << words.shift << ' \\fI' << words.shift << '\\fP'
285 end
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
286 @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
287 next
288 end
289 when 'Cm'
290 retval << '\\fB' << words.shift << '\\fP'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
291 while RE_PUNCT =~ words[0]
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
292 retval << words.shift
293 end
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
294 next
295 when 'Op'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
296 quote << OPTION
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
297 @nospace = 1 if @nospace == 0
298 retval << '['
299 # words.push(words.pop + ']')
300 next
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
301 when 'Aq'
302 quote << ANGLE
303 @nospace = 1 if @nospace == 0
304 retval << '<'
305 # words.push(words.pop + '>')
306 next
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
307 when 'Pp'
308 retval << "\n"
309 next
310 when 'Ss'
311 retval << '.SS'
312 next
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
313 end
314
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
315 if word == 'Pa' && !quote.include?(OPTION)
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
316 retval << '\\fI'
317 retval << '\\&' if /^\./ =~ words[0]
318 retval << words.shift << '\\fP'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
319 while RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
320 retval << words.shift
321 end
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
322 # @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
323 next
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
324 end
325
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
326 case word
327 when 'Dv'
328 retval << '.BR'
329 next
330 when 'Em', 'Ev'
331 retval << '.IR'
332 next
333 when 'Pq'
334 retval << '('
335 @nospace = 1
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
336 quote << PAREN
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
337 next
338 when 'Sx', 'Sy'
339 retval << '.B ' << words.join(' ')
340 break
341 when 'Ic'
342 retval << '\\fB'
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
343 until words.empty? || RE_PUNCT =~ words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
344 case words[0]
345 when 'Op'
346 words.shift
347 retval << '['
348 words.push(words.pop + ']')
349 next
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
350 when 'Aq'
351 words.shift
352 retval << '<'
353 words.push(words.pop + '>')
354 next
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
355 when 'Ar'
356 words.shift
357 retval << '\\fI' << words.shift << '\\fP'
358 else
359 retval << words.shift
360 end
361
362 retval << ' ' if @nospace == 0
363 end
364
365 retval.chomp!(' ')
366 retval << '\\fP'
367 retval << words.shift unless words.empty?
368 break
369 when 'Bl'
370 @oldoptlist = @optlist
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
371
372 case words[0]
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
373 when '-bullet'
374 @optlist = 1
375 when '-enum'
376 @optlist = 2
377 @enum = 0
378 when '-tag'
379 @optlist = 3
380 when '-item'
381 @optlist = 4
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
382 end
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
383
384 break
385 when 'El'
386 @optlist = @oldoptlist
387 next
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
388 end
389
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
390 if @optlist != 0 && word == 'It'
391 case @optlist
392 when 1
393 # bullets
394 retval << '.IP \\(bu'
395 when 2
396 # enum
397 @enum += 1
398 retval << '.IP ' << @enum << '.'
399 when 3
400 # tags
401 retval << ".TP\n"
402 case words[0]
403 when 'Pa', 'Ev'
404 words.shift
405 retval << '.B'
406 end
407 when 4
408 # item
409 retval << ".IP\n"
410 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
411
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
412 next
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
413 end
414
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
415 case word
416 when 'Sm'
417 case words[0]
418 when 'off'
419 @nospace = 2
420 when 'on'
421 # retval << "\n"
422 @nospace = 0
423 end
424 words.shift
425 next
426 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
427
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
428 retval << word
429 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
430
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
431 return nil if retval == '.'
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
432
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
433 retval.sub!(/\A\.([^a-zA-Z])/, "\\1")
434 # retval.chomp!(' ')
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
435
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
436 while q = quote.pop
437 case q
438 when OPTION
439 retval << ']'
440 when PAREN
441 retval << ')'
442 when ANGLE
443 retval << '>'
444 end
445 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
446
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
447 # retval << ' ' unless @nospace == 0 || retval.empty? || /\n\z/ =~ retval
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
448
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
449 retval << ' ' unless !@ext || @extopt || / $/ =~ retval
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
450
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
451 retval << "\n" unless @ext || @extopt || retval.empty? || /\n\z/ =~ retval
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
452
778b242 @knu * mdoc2man.rb: Properly put nested braces, parentheses and angles.
knu authored
453 retval << ".fi\n" if dl
454
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
455 return retval
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
456 end
457
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
458 def self.mdoc2man(i, o)
459 new.mdoc2man(i, o)
460 end
461 end
fa4cf2f @knu * mdoc2man.rb: New file. A mdoc to man converter ported from
knu authored
462
1d11cd1 @knu * mdoc2man.rb: Make this work as a library.
knu authored
463 if $0 == __FILE__
464 Mdoc2Man.mdoc2man(ARGF, STDOUT)
465 end
Something went wrong with that request. Please try again.