#! /usr/bin/env ruby
=begin
= NAME
rd2 - converter from RD to other mark-up language.
= SYNOPSIS
  rd2 [-r <visitor>] [options] <file>

= DESCRIPTION
rd2 inputs from ((|<file>|)) and outputs into (({STDOUT})). you can
choose ((|<visitor>|)) to select output format. For example, use
"rd/rd2html-lib.rb" to translate it into HTML, and "rd/rd2man-lib.rb"
to tranlate it into roff with man macros.

= OPTIONS
please read output of 
  % rd2 --help
and
  % rd2 -r rd/rd2html-lib.rb --help

= FILES
  * ~/.rd2rc - User configration file.

= SEE ALSO
ruby(1)
=end

require "kconv"
require "optparse"
require "rd/rdfmt"

def Kconv.name2const(name)
  case name
  when "iso-2022-jp"
    Kconv::JIS
  when "euc-jp"
    Kconv::EUC
  when "shift_jis"
    Kconv::SJIS
  end
end

include RD

# global vars
$Visitor = nil
$RD2_Sub_OptionParser = nil

# local vars
include_path = []
with_part = []
output_file = nil
output_index = nil
out_code = nil
from_rdo = nil

# user option
$DEFAULT_FORMAT_LIB = "rd/rd2html-lib"
$RC = {}
$RC["filter"] = Hash.new(RD::INCLUDE_FILTER)

if test(?r, File.expand_path("~/.rd2rc"))
  load "~/.rd2rc"
  STDERR << "#{$0}: loading ~/.rd2rc\n"
else
  load "rd/dot.rd2rc"
  STDERR << "#{$0}: loading rd/dot.rd2rc\n"
end

# initialize OptionParser
ARGV.options = OptionParser.new("Usage: #{$0} [options] rd-file > output\n") do
  |q|
  q.on_head("global options:")
  
  q.on("-rLIB", "--require=LIB",
       String,
       "choose format library.") do |i|
    # require LIB
    require i
    if $Visitor_Class && !$Visitor
      $Visitor = $Visitor_Class.new()
      if $RD2_Sub_OptionParser    
	require $RD2_Sub_OptionParser
	$RD2_Sub_OptionParser = nil
      end
    end
  end
  
  q.on("-oNAME",
       String,
       "indicate base name of output file") do |i|
    output_file = i
  end

  q.on("--out-code=KCODE",
       String,
       "choose charactor encode of output.(jis|euc|sjis)") do |i|
    case i
    when /jis|iso-2022-jp/i
      out_code = "iso-2022-jp"
    when /euc|euc-jp/i
      out_code = "euc-jp"
    when /sjis|shift-jis/i
      out_code = "shift_jis"
    end
  end
      
  q.on("--output-index",
       "output method index file (*.rmi)") do |i|
    output_index = true
  end
  
  q.on("-IPATH", "--include-path=PATH",
       String,
       "add PATH to list of include path") do |i|
    # add to include path
    include_path.unshift(i)
  end
  
  # accept "PART:FILTER" and "PART"
  q.accept(PartAndFilter = /(\w+)(?:\s*:\s*(\w+))?/) do |src, *pandf|
    pandf
  end
  
  q.on("--with-part=PART",
       PartAndFilter,
       "include PART with Filter") do |i|
    with_part.push(i)
    unless include_path.index(RD::RDTree::TMP_DIR)
      include_path.push(RD::RDTree::TMP_DIR)
    end
  end
  
  q.on("--from-rdo",
       "load from *.rdo instead of *.rd") do
    from_rdo = true
  end
  
  q.on_tail("--help",
	    "print this message") do
    STDERR.print(q.to_s)
    exit(0)
  end
end # OptionParser.new

# require format lib implicitly
unless File.basename($0) == "rd2"
  require "rd/" + File.basename($0) + "-lib.rb"
  require $RD2_Sub_OptionParser  if $RD2_Sub_OptionParser
  # make visitor
  $Visitor = $Visitor_Class.new()
end

begin
  ARGV.parse!
rescue
  STDERR.print("Error: " + $!.inspect + "\n")
  STDERR.print(ARGV.options.to_s)
  exit(1)
end

unless $Visitor_Class
  require $DEFAULT_FORMAT_LIB
  $Visitor = $Visitor_Class.new
end

# make tree (but not parsed yet)
if from_rdo
  rdos = []
  ARGV.each do |i|
    rdos.push(File.open(i))
    dirname = File.dirname(i)
    include_path.push(dirname, dirname + "/include")
  end
  tree = RDTree.new_from_rdo(*rdos)
  tree.include_path = include_path
else 
  # input from ARGF
  src = readlines
  
  # set Include_Path
  if ARGF.filename
    dir = File.dirname(ARGF.filename)
  else
    dir = "."
  end
  include_path.push(dir)
  include_path.push(dir + "/include")

  tree = RDTree.new(src, include_path, nil)

  # filter set tree.filter
  with_part.each do |i|
    tree.filter[i[0]] = $RC["filter"][i[1]]
  end
  
  # parse
  tree.parse
end

# filter: set visitor.include_suffix
with_part.each do |i|
  $Visitor.include_suffix.push(i[0])
end

# file base name setup
$Visitor.filename = output_file if output_file

# character encoding
if out_code
  begin
    $Visitor.charcode = out_code
  rescue NameError
  end
end

# output  
out = $Visitor.visit(tree)

# character encoding convert
out = Kconv.kconv(out, Kconv.name2const(out_code), Kconv::AUTO) if out_code

if output_file
  filename = output_file + "." + $Visitor.type::OUTPUT_SUFFIX
  file = open(filename, "w")
  file.print(out)
  file.close
  STDERR.print("#{$0}: output to #{filename}...\n")
else
  print(out)
end

# RMI
if output_index
  if output_file
    require "rd/rd2rmi-lib"
    rmivisitor = RD2RMIVisitor.new
    rmivisitor.filename = output_file
    rmi = rmivisitor.visit(tree)
    filename = output_file + ".rmi"
    file = open(filename, "w")
    file.print(rmi)
    file.close
    STDERR.print("#{$0}: output to #{filename}...\n")
  else
    raise %Q[Error: option "--output-index" must be used with option "-oNAME"]
  end
end


# filter: remove tmp file
Dir.glob("#{RD::RDTree::TMP_DIR}/rdtmp.#{$$}.*.*").each do |i|
  File.delete(i)
end

=begin script info
== script info.
 frontend of RDtool.
 $Id: rd2,v 1.1 2001/01/23 22:10:47 dave Exp $

== changes
:0.6.1
  * change RD into man style.
  * option --out-code.
:0.6.0
  * come to use nakada's OptionParser
  * marge rdld
  * bug fix. thanks. > Nakada
:0.5.7
  * bug fix. thanks. > Nakada
:0.5.4
  * filter.
  * RC file for user config
:0.5.3
  * Include other RD files.
:0.5.2
  * when running as "rd2foo", it come to require library "rd/rd2foo-lib.rb".
    thanks! > Arai
  * include RD.
:0.5.0
  * reborened for new RD
=end
