summaryrefslogtreecommitdiff
path: root/tool/mdoc2man.rb
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-10-21 04:19:56 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-10-21 04:19:56 +0000
commit89dfcd82f09ca83ac2fc793f6524393c6ae45fdd (patch)
treec98759280f009752d321e1d49bad95b70764d9d0 /tool/mdoc2man.rb
parent5225f2c143fa69d73c1b90818a8b6a5be1175379 (diff)
* mdoc2man.rb: moved into tools/.
* instruby.rb: followed the change of mdoc2man. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'tool/mdoc2man.rb')
-rwxr-xr-xtool/mdoc2man.rb465
1 files changed, 465 insertions, 0 deletions
diff --git a/tool/mdoc2man.rb b/tool/mdoc2man.rb
new file mode 100755
index 0000000..910b2e5
--- /dev/null
+++ b/tool/mdoc2man.rb
@@ -0,0 +1,465 @@
+#!/usr/bin/env ruby
+###
+### mdoc2man - mdoc to man converter
+###
+### Quick usage: mdoc2man.rb < mdoc_manpage.8 > man_manpage.8
+###
+### Ported from Perl by Akinori MUSHA.
+###
+### Copyright (c) 2001 University of Illinois Board of Trustees
+### Copyright (c) 2001 Mark D. Roth
+### Copyright (c) 2002, 2003 Akinori MUSHA
+### All rights reserved.
+###
+### Redistribution and use in source and binary forms, with or without
+### modification, are permitted provided that the following conditions
+### are met:
+### 1. Redistributions of source code must retain the above copyright
+### notice, this list of conditions and the following disclaimer.
+### 2. Redistributions in binary form must reproduce the above copyright
+### notice, this list of conditions and the following disclaimer in the
+### documentation and/or other materials provided with the distribution.
+### 3. All advertising materials mentioning features or use of this software
+### must display the following acknowledgement:
+### This product includes software developed by the University of
+### Illinois at Urbana, and their contributors.
+### 4. The University nor the names of their
+### contributors may be used to endorse or promote products derived from
+### this software without specific prior written permission.
+###
+### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND
+### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+### ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE
+### FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+### DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+### OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+### HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+### LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+### OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+### SUCH DAMAGE.
+###
+### $Id$
+###
+
+class Mdoc2Man
+ ANGLE = 1
+ OPTION = 2
+ PAREN = 3
+
+ RE_PUNCT = /^[!"'),\.\/:;>\?\]`]$/
+
+ def initialize
+ @name = @date = @id = nil
+ @refauthors = @reftitle = @refissue = @refdate = @refopt = nil
+
+ @optlist = 0 ### 1 = bullet, 2 = enum, 3 = tag, 4 = item
+ @oldoptlist = 0
+ @nospace = 0 ### 0, 1, 2
+ @enum = 0
+ @synopsis = true
+ @reference = false
+ @ext = false
+ @extopt = false
+ @literal = false
+ end
+
+ def mdoc2man(i, o)
+ i.each { |line|
+ if /^\./ !~ line
+ o.print line
+ o.print ".br\n" if @literal
+ next
+ end
+
+ line.slice!(0, 1)
+
+ next if /\\"/ =~ line
+
+ line = parse_macro(line) and o.print line
+ }
+
+ initialize
+ end
+
+ def parse_macro(line)
+ words = line.split
+ retval = ''
+
+ quote = []
+ dl = false
+
+ while word = words.shift
+ case word
+ when RE_PUNCT
+ while q = quote.pop
+ case q
+ when OPTION
+ retval << ']'
+ when PAREN
+ retval << ')'
+ when ANGLE
+ retval << '>'
+ end
+ end
+ retval << word
+ next
+ when 'Li', 'Pf'
+ @nospace = 1
+ next
+ when 'Xo'
+ @ext = true
+ retval << ' ' unless retval.empty? || /[\n ]\z/ =~ retval
+ next
+ when 'Xc'
+ @ext = false
+ retval << "\n" unless @extopt
+ break
+ when 'Bd'
+ @literal = true if words[0] == '-literal'
+ retval << "\n"
+ break
+ when 'Ed'
+ @literal = false
+ break
+ when 'Ns'
+ @nospace = 1 if @nospace == 0
+ retval.chomp!(' ')
+ next
+ when 'No'
+ retval.chomp!(' ')
+ retval << words.shift
+ next
+ when 'Dq'
+ retval << '``'
+ begin
+ retval << words.shift << ' '
+ end until words.empty? || RE_PUNCT =~ words[0]
+ retval.chomp!(' ')
+ retval << '\'\''
+ @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ when 'Sq', 'Ql'
+ retval << '`' << words.shift << '\''
+ @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ # when 'Ic'
+ # retval << '\\fB' << words.shift << '\\fP'
+ # next
+ when 'Oo'
+ #retval << "[\\c\n"
+ @extopt = true
+ @nospace = 1 if @nospace == 0
+ retval << '['
+ next
+ when 'Oc'
+ @extopt = false
+ retval << ']'
+ next
+ when 'Ao'
+ @nospace = 1 if @nospace == 0
+ retval << '<'
+ next
+ when 'Ac'
+ retval << '>'
+ next
+ end
+
+ retval << ' ' if @nospace == 0 && !(retval.empty? || /[\n ]\z/ =~ retval)
+ @nospace = 0 if @nospace == 1
+
+ case word
+ when 'Dd'
+ @date = words.join(' ')
+ return nil
+ when 'Dt'
+ if words.size >= 2 && words[1] == '""' &&
+ /^(.*)\(([0-9])\)$/ =~ words[0]
+ words[0] = $1
+ words[1] = $2
+ end
+ @id = words.join(' ')
+ return nil
+ when 'Os'
+ retval << '.TH ' << @id << ' "' << @date << '" "' <<
+ words.join(' ') << '"'
+ break
+ when 'Sh'
+ retval << '.SH'
+ @synopsis = (words[0] == 'SYNOPSIS')
+ next
+ when 'Xr'
+ retval << '\\fB' << words.shift <<
+ '\\fP(' << words.shift << ')' << words.shift
+ break
+ when 'Rs'
+ @refauthors = []
+ @reftitle = ''
+ @refissue = ''
+ @refdate = ''
+ @refopt = ''
+ @reference = true
+ break
+ when 'Re'
+ retval << "\n"
+
+ # authors
+ while @refauthors.size > 1
+ retval << @refauthors.shift << ', '
+ end
+ retval << 'and ' unless retval.empty?
+ retval << @refauthors.shift
+
+ # title
+ retval << ', \\fI' << @reftitle << '\\fP'
+
+ # issue
+ retval << ', ' << @refissue unless @refissue.empty?
+
+ # date
+ retval << ', ' << @refdate unless @refdate.empty?
+
+ # optional info
+ retval << ', ' << @refopt unless @refopt.empty?
+
+ retval << ".\n"
+
+ @reference = false
+ break
+ when 'An'
+ next
+ when 'Dl'
+ retval << ".nf\n" << '\\& '
+ dl = true
+ next
+ when 'Ux'
+ retval << "UNIX"
+ next
+ end
+
+ if @reference
+ case word
+ when '%A'
+ @refauthors.unshift(words.join(' '))
+ break
+ when '%T'
+ @reftitle = words.join(' ')
+ @reftitle.sub!(/^"/, '')
+ @reftitle.sub!(/"$/, '')
+ break
+ when '%N'
+ @refissue = words.join(' ')
+ break
+ when '%D'
+ @refdate = words.join(' ')
+ break
+ when '%O'
+ @refopt = words.join(' ')
+ break
+ end
+ end
+
+ case word
+ when 'Nm'
+ name = words.empty? ? @name : words.shift
+ @name ||= name
+ retval << ".br\n" if @synopsis
+ retval << "\\fB" << name << "\\fP"
+ @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ when 'Nd'
+ retval << '\\-'
+ next
+ when 'Fl'
+ retval << '\\fB\\-' << words.shift << '\\fP'
+ @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ when 'Ar'
+ retval << '\\fI'
+ if words.empty?
+ retval << 'file ...\\fP'
+ else
+ retval << words.shift << '\\fP'
+ while words[0] == '|'
+ retval << ' ' << words.shift << ' \\fI' << words.shift << '\\fP'
+ end
+ @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ end
+ when 'Cm'
+ retval << '\\fB' << words.shift << '\\fP'
+ while RE_PUNCT =~ words[0]
+ retval << words.shift
+ end
+ next
+ when 'Op'
+ quote << OPTION
+ @nospace = 1 if @nospace == 0
+ retval << '['
+ # words.push(words.pop + ']')
+ next
+ when 'Aq'
+ quote << ANGLE
+ @nospace = 1 if @nospace == 0
+ retval << '<'
+ # words.push(words.pop + '>')
+ next
+ when 'Pp'
+ retval << "\n"
+ next
+ when 'Ss'
+ retval << '.SS'
+ next
+ end
+
+ if word == 'Pa' && !quote.include?(OPTION)
+ retval << '\\fI'
+ retval << '\\&' if /^\./ =~ words[0]
+ retval << words.shift << '\\fP'
+ while RE_PUNCT =~ words[0]
+ retval << words.shift
+ end
+ # @nospace = 1 if @nospace == 0 && RE_PUNCT =~ words[0]
+ next
+ end
+
+ case word
+ when 'Dv'
+ retval << '.BR'
+ next
+ when 'Em', 'Ev'
+ retval << '.IR'
+ next
+ when 'Pq'
+ retval << '('
+ @nospace = 1
+ quote << PAREN
+ next
+ when 'Sx', 'Sy'
+ retval << '.B ' << words.join(' ')
+ break
+ when 'Ic'
+ retval << '\\fB'
+ until words.empty? || RE_PUNCT =~ words[0]
+ case words[0]
+ when 'Op'
+ words.shift
+ retval << '['
+ words.push(words.pop + ']')
+ next
+ when 'Aq'
+ words.shift
+ retval << '<'
+ words.push(words.pop + '>')
+ next
+ when 'Ar'
+ words.shift
+ retval << '\\fI' << words.shift << '\\fP'
+ else
+ retval << words.shift
+ end
+
+ retval << ' ' if @nospace == 0
+ end
+
+ retval.chomp!(' ')
+ retval << '\\fP'
+ retval << words.shift unless words.empty?
+ break
+ when 'Bl'
+ @oldoptlist = @optlist
+
+ case words[0]
+ when '-bullet'
+ @optlist = 1
+ when '-enum'
+ @optlist = 2
+ @enum = 0
+ when '-tag'
+ @optlist = 3
+ when '-item'
+ @optlist = 4
+ end
+
+ break
+ when 'El'
+ @optlist = @oldoptlist
+ next
+ end
+
+ if @optlist != 0 && word == 'It'
+ case @optlist
+ when 1
+ # bullets
+ retval << '.IP \\(bu'
+ when 2
+ # enum
+ @enum += 1
+ retval << '.IP ' << @enum << '.'
+ when 3
+ # tags
+ retval << ".TP\n"
+ case words[0]
+ when 'Pa', 'Ev'
+ words.shift
+ retval << '.B'
+ end
+ when 4
+ # item
+ retval << ".IP\n"
+ end
+
+ next
+ end
+
+ case word
+ when 'Sm'
+ case words[0]
+ when 'off'
+ @nospace = 2
+ when 'on'
+ # retval << "\n"
+ @nospace = 0
+ end
+ words.shift
+ next
+ end
+
+ retval << word
+ end
+
+ return nil if retval == '.'
+
+ retval.sub!(/\A\.([^a-zA-Z])/, "\\1")
+ # retval.chomp!(' ')
+
+ while q = quote.pop
+ case q
+ when OPTION
+ retval << ']'
+ when PAREN
+ retval << ')'
+ when ANGLE
+ retval << '>'
+ end
+ end
+
+ # retval << ' ' unless @nospace == 0 || retval.empty? || /\n\z/ =~ retval
+
+ retval << ' ' unless !@ext || @extopt || / $/ =~ retval
+
+ retval << "\n" unless @ext || @extopt || retval.empty? || /\n\z/ =~ retval
+
+ retval << ".fi\n" if dl
+
+ return retval
+ end
+
+ def self.mdoc2man(i, o)
+ new.mdoc2man(i, o)
+ end
+end
+
+if $0 == __FILE__
+ Mdoc2Man.mdoc2man(ARGF, STDOUT)
+end