#! /usr/bin/ruby

#==============================================================================#
# exerb.rb
# $Id: exerb.rb,v 1.9 2002/09/20 09:12:12 yuya Exp $
#==============================================================================#

require 'getoptlong'
require 'exerb/exerb'

#==============================================================================#
# ExerbCommand Module
module ExerbCommand

  def self.main
    options = parse_argv

    if options['help'] || ARGV.size < 1
      print_usage
      return
    end

    corefile = if options['corepath']
                 options['corepath']
               elsif options['corename']
                 lookup_corefile(options['corename'])
               else
                 lookup_corefile('cui')
               end

    rbcfile = ARGV[0]
    exefile = options['output'] || make_filename(rbcfile, "exe")
    rbafile = make_filename(rbcfile, "rba")

    rbc = RbcFile.new(rbcfile)
    arc = rbc.archive

    if options['debug']
      File.open(rbafile, 'wb') { |file|
        arc.output(file)
      }
    end

    arcbin  = Exerb::Binary::Archive.new(arc.pack)
    corebin = Exerb::Binary::Core.new_from_file(corefile)
    exebin  = Exerb::Binary::Executable.new(arcbin, corebin)
    exebin.selfcheck

    File.open(exefile, 'wb') { |file|
      exebin.output(file)
    }
  end

  def self.lookup_corefile(name)
    require 'exerb/config'

    if Exerb::CORE.has_key?(name)
      return Exerb::CORE[name]
    else
      raise "core name not found in exerb/config.rb : #{options['corename']}"
    end
  end

  def self.make_filename(filename, extension)
    if /\.rbc$/i =~ filename
      return filename.sub(/\.rbc$/i, '.' + extension)
    else
      return filename + '.' + extension
    end
  end

  def self.parse_argv
    option = {}

    parser = GetoptLong.new
    parser.set_options(
      ['--corename', '-c', GetoptLong::REQUIRED_ARGUMENT],
      ['--corepath', '-C', GetoptLong::REQUIRED_ARGUMENT],
      ['--output',   '-o', GetoptLong::REQUIRED_ARGUMENT],
      ['--debug',    '-d', GetoptLong::NO_ARGUMENT],
      ['--help',     '-h', GetoptLong::NO_ARGUMENT]
    )

    parser.each_option { |name, argument|
      option[name.sub(/^--/, '')] = argument
    }

    return option
  end

  def self.print_usage
    puts "Usage: exerb [options] rbc-file"
    puts "Options:"
    puts "  -c  --corename  specifies exerb-core name."
    puts "  -C  --corepath  specifies exerb-core file."
    puts "  -o  --output    specifies output file."
    puts "  -h  --help      display this information."
  end

  class RbcFile

    def initialize(filepath)
      @basedir = File.dirname(File.expand_path(filepath))

      @list = File.open(filepath) { |file|
        file.to_a
      }.collect { |item|
        item.strip
      }.reject { |item|
        item.empty? || /^#/ =~ item
      }.collect { |item|
        item.split(/\t+/)
      }
    end

    def archive
      arc = Exerb::Archive.new

      @list.each { |type, name, path|
        case type
        when 'kcode'   then arc.set_kcode(name)
        when 'script'  then arc.add_script(name, File.expand_path(path, @basedir))
        when 'library' then arc.add_dll(name, File.expand_path(path, @basedir))
        else raise "syntax error : #{type}"
        end
      }

      return arc
    end

  end # RbcFile

end # ExerbCommand

#==============================================================================#

ExerbCommand.main

#==============================================================================#
#==============================================================================#
