class RDoc::RDoc

def self.add_generator(klass)

def self.add_generator(klass)
  name = klass.name.sub(/^RDoc::Generator::/, '').downcase
  GENERATORS[name] = klass
end

def self.current

def self.current
  @current
end

def self.current=(rdoc)

def self.current=(rdoc)
  @current = rdoc
end

def document(argv)

def document(argv)
  RDoc::TopLevel.reset
  RDoc::Parser::C.reset
  @options = RDoc::Options.new
  @options.parse argv
  if @options.pipe then
    handle_pipe
    exit
  end
  @exclude = @options.exclude
  @last_modified = setup_output_dir @options.op_dir, @options.force_update
  start_time = Time.now
  file_info = parse_files @options.files
  @options.title = "RDoc Documentation"
  if file_info.empty?
    $stderr.puts "\nNo newer files." unless @options.quiet
  else
    gen_klass = @options.generator
    unless @options.quiet then
      $stderr.puts "\nGenerating #{gen_klass.name.sub(/^.*::/, '')}..."
    end
    @generator = gen_klass.for @options
    pwd = Dir.pwd
    Dir.chdir @options.op_dir do
      begin
        self.class.current = self
        @generator.generate file_info
        update_output_dir ".", start_time, @last_modified
      ensure
        self.class.current = nil
      end
    end
  end
  unless @options.quiet or not @stats then
    puts
    @stats.print
  end
end

def error(msg)

def error(msg)
  raise RDoc::Error, msg
end

def gather_files files

def gather_files files
  files = ["."] if files.empty?
  file_list = normalized_file_list files, true, @exclude
  file_list = file_list.uniq
  file_list = remove_unparseable file_list
end

def handle_pipe

def handle_pipe
  @html = RDoc::Markup::ToHtml.new
  out = @html.convert $stdin.read
  $stdout.write out
end

def initialize

def initialize
  @current       = nil
  @exclude       = nil
  @generator     = nil
  @last_modified = {}
  @old_siginfo   = nil
  @options       = nil
  @stats         = nil
end

def install_siginfo_handler

def install_siginfo_handler
  return unless Signal.list.include? 'INFO'
  @old_siginfo = trap 'INFO' do
    puts @current if @current
  end
end

def list_files_in_directory dir

def list_files_in_directory dir
  files = Dir.glob File.join(dir, "*")
  normalized_file_list files, false, @options.exclude
end

def normalized_file_list(relative_files, force_doc = false,

def normalized_file_list(relative_files, force_doc = false,
                         exclude_pattern = nil)
  file_list = []
  relative_files.each do |rel_file_name|
    next if exclude_pattern && exclude_pattern =~ rel_file_name
    stat = File.stat rel_file_name rescue next
    case type = stat.ftype
    when "file" then
      next if last_modified = @last_modified[rel_file_name] and
              stat.mtime.to_i <= last_modified.to_i
      if force_doc or RDoc::Parser.can_parse(rel_file_name) then
        file_list << rel_file_name.sub(/^\.\//, '')
        @last_modified[rel_file_name] = stat.mtime
      end
    when "directory" then
      next if rel_file_name == "CVS" || rel_file_name == ".svn"
      dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME
      if File.file? dot_doc then
        file_list << parse_dot_doc_file(rel_file_name, dot_doc)
      else
        file_list << list_files_in_directory(rel_file_name)
      end
    else
      raise RDoc::Error, "I can't deal with a #{type} #{rel_file_name}"
    end
  end
  file_list.flatten
end

def output_flag_file(op_dir)

def output_flag_file(op_dir)
  File.join op_dir, "created.rid"
end

def parse_dot_doc_file in_dir, filename

def parse_dot_doc_file in_dir, filename
  # read and strip comments
  patterns = File.read(filename).gsub(/#.*/, '')
  result = []
  patterns.split.each do |patt|
    candidates = Dir.glob(File.join(in_dir, patt))
    result.concat normalized_file_list(candidates)
  end
  result
end

def parse_file filename

def parse_file filename
  @stats.add_file filename
  content = read_file_contents filename
  return unless content
  top_level = RDoc::TopLevel.new filename
  parser = RDoc::Parser.for top_level, filename, content, @options, @stats
  return unless parser
  parser.scan
rescue => e
  $stderr.puts <<-EOF
fore reporting this, could you check that the file you're documenting
mpiles cleanly--RDoc is not a full Ruby parser, and gets confused easily if
d invalid programs.
e internal error was:
(#{e.class}) #{e.message}
  EOF
  $stderr.puts e.backtrace.join("\n\t") if $RDOC_DEBUG
  raise e
  nil
end

def parse_files files

def parse_files files
  file_list = gather_files files
  return [] if file_list.empty?
  file_info = []
  @stats = RDoc::Stats.new file_list.size, @options.verbosity
  @stats.begin_adding
  file_info = file_list.map do |filename|
    @current = filename
    parse_file filename
  end.compact
  @stats.done_adding
  file_info
end

def read_file_contents(filename)

def read_file_contents(filename)
  content = open filename, "rb" do |f| f.read end
  if defined? Encoding then
    if /coding[=:]\s*([^\s;]+)/i =~ content[%r"\A(?:#!.*\n)?.*\n"]
      if enc = ::Encoding.find($1)
        content.force_encoding(enc)
      end
    end
  end
  content
rescue Errno::EISDIR, Errno::ENOENT
  nil
end

def remove_siginfo_handler

def remove_siginfo_handler
  return unless Signal.list.key? 'INFO'
  handler = @old_siginfo || 'DEFAULT'
  trap 'INFO', handler
end

def remove_unparseable files

def remove_unparseable files
  files.reject do |file|
    file =~ /\.(?:class|eps|erb|scpt\.txt|ttf|yml)$/i
  end
end

def setup_output_dir(dir, force)

def setup_output_dir(dir, force)
  flag_file = output_flag_file dir
  last = {}
  if File.exist? dir then
    error "#{dir} exists and is not a directory" unless File.directory? dir
    begin
      open flag_file do |io|
        unless force then
          Time.parse io.gets
          io.each do |line|
            file, time = line.split "\t", 2
            time = Time.parse(time) rescue next
            last[file] = time
          end
        end
      end
    rescue SystemCallError, TypeError
      error <<-ERROR
rectory #{dir} already exists, but it looks like it isn't an RDoc directory.
cause RDoc doesn't want to risk destroying any of your existing files,
u'll need to specify a different output directory name (using the --op <dir>
tion)
      ERROR
    end
  else
    FileUtils.mkdir_p dir
  end
  last
end

def update_output_dir(op_dir, time, last = {})

def update_output_dir(op_dir, time, last = {})
  open output_flag_file(op_dir), "w" do |f|
    f.puts time.rfc2822
    last.each do |n, t|
      f.puts "#{n}\t#{t.rfc2822}"
    end
  end
end