267 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/local/bin/ruby
 | 
						|
 | 
						|
#  HTML reference generator
 | 
						|
#  by A.Ito 1999/3/30
 | 
						|
 | 
						|
require 'kconv'
 | 
						|
 | 
						|
###########################################################################
 | 
						|
class URL
 | 
						|
  attr 'scheme'
 | 
						|
  attr 'host'
 | 
						|
  attr 'port'
 | 
						|
  attr 'file'
 | 
						|
  attr 'label'
 | 
						|
  def initialize(str)
 | 
						|
    if /([a-zA-Z+\-]+):(.*)/ =~ str then
 | 
						|
      @scheme = $1
 | 
						|
      str = $2
 | 
						|
    else
 | 
						|
      @scheme = 'unknown'
 | 
						|
    end
 | 
						|
    hostpart = ''
 | 
						|
    if %r'//([^/]*)(/.*)' =~ str then
 | 
						|
      hostpart = $1
 | 
						|
      str = $2
 | 
						|
    elsif %r'//([^/]*)$' =~ str then
 | 
						|
      hostpart = str
 | 
						|
      str = ''
 | 
						|
    end
 | 
						|
    if hostpart != '' then
 | 
						|
      if /(.*):(\d+)/ =~ hostpart then
 | 
						|
        @host = $1
 | 
						|
        @port = $2
 | 
						|
      else
 | 
						|
        @host = hostpart
 | 
						|
        @port = ''
 | 
						|
      end
 | 
						|
    else
 | 
						|
      @host = @port = ''
 | 
						|
    end
 | 
						|
    if /(.*)#(.*)/ =~ str then
 | 
						|
      @file = $1
 | 
						|
      @label = $2
 | 
						|
    else
 | 
						|
      @file = str
 | 
						|
      @label = ''
 | 
						|
    end
 | 
						|
  end
 | 
						|
  def to_s
 | 
						|
    s = "#{@scheme}:"
 | 
						|
    if s == 'news' or s == 'mailto' then
 | 
						|
      return s+@file
 | 
						|
    end
 | 
						|
    s += "//"+@host
 | 
						|
    s += ":"+@port if @port.size > 0
 | 
						|
    s += @file
 | 
						|
    s += "#"+@label if @label.size > 0
 | 
						|
    s
 | 
						|
  end
 | 
						|
  def complete(current)
 | 
						|
    @scheme = current.scheme  if @scheme == 'unknown'
 | 
						|
    @port = current.port if @host == '' and @port == ''
 | 
						|
    @host = current.host if @host == ''
 | 
						|
    unless @file =~ %r'^/' then
 | 
						|
      @file = File.expand_path(File.dirname(current.file)+'/'+@file)
 | 
						|
    end
 | 
						|
    self
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
class Tag
 | 
						|
  def initialize(str)
 | 
						|
    if str =~ /<(.+)>/ then
 | 
						|
      str = $1
 | 
						|
    end
 | 
						|
    tags = str.split
 | 
						|
    @tagname = tags.shift.downcase
 | 
						|
    @vals = {}
 | 
						|
    tags.each do |t|
 | 
						|
      if t =~ /=/ then
 | 
						|
	tn,tv = t.split(/\s*=\s*/,2)
 | 
						|
	tv.sub!(/^"/,"")
 | 
						|
	tv.sub!(/"$/,"")
 | 
						|
	@vals[tn.downcase] = tv
 | 
						|
      else
 | 
						|
	@vals[t.downcase] = TRUE
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
  def tagname
 | 
						|
    return @tagname
 | 
						|
  end
 | 
						|
  def each
 | 
						|
    @vals.each do |k,v|
 | 
						|
      yield k,v
 | 
						|
    end
 | 
						|
  end
 | 
						|
  def switch(k)
 | 
						|
    return @vals[k]
 | 
						|
  end
 | 
						|
  def to_s
 | 
						|
    if tagname =~ /!--/ then
 | 
						|
      return ''
 | 
						|
    end
 | 
						|
    t = "<"+tagname
 | 
						|
    if @vals.size == 0 then
 | 
						|
      return t+">"
 | 
						|
    end
 | 
						|
    each do |a,v|
 | 
						|
      if v == true then
 | 
						|
        t += " #{a}"
 | 
						|
      else
 | 
						|
        t += " #{a}=\"#{v}\""
 | 
						|
      end
 | 
						|
    end
 | 
						|
    t+">"
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
class TokenStream
 | 
						|
  TAG_START = ?<
 | 
						|
  TAG_END = ?>
 | 
						|
  AMP_START = ?&
 | 
						|
  AMP_END = ?;
 | 
						|
  
 | 
						|
  def initialize(file)
 | 
						|
    if file.kind_of?(IO) then
 | 
						|
      @f = file
 | 
						|
    else
 | 
						|
      @f = File.new(file)
 | 
						|
    end
 | 
						|
    @buf = nil
 | 
						|
    @bpos = 0
 | 
						|
  end
 | 
						|
  
 | 
						|
  def read_until(endsym)
 | 
						|
    complete = FALSE
 | 
						|
    tag = []
 | 
						|
    begin
 | 
						|
      while @bpos < @buf.size
 | 
						|
	c = @buf[@bpos]
 | 
						|
	if c == endsym then
 | 
						|
	  tag.push(c.chr)
 | 
						|
	  complete = TRUE
 | 
						|
	  @bpos += 1
 | 
						|
	  break
 | 
						|
	end
 | 
						|
	if c == 10 || c == 13 then
 | 
						|
	  tag.push(' ')
 | 
						|
	else
 | 
						|
	  tag.push(c.chr)
 | 
						|
	end
 | 
						|
	@bpos += 1
 | 
						|
      end
 | 
						|
      unless complete
 | 
						|
	@buf = @f.gets
 | 
						|
	@bpos = 0
 | 
						|
	break if @f.eof?
 | 
						|
      end
 | 
						|
    end until complete
 | 
						|
    return tag.join('')
 | 
						|
  end
 | 
						|
    
 | 
						|
  def get
 | 
						|
    while TRUE
 | 
						|
      if @buf.nil? then
 | 
						|
	@buf = @f.gets
 | 
						|
	if @f.eof? then
 | 
						|
	  return nil
 | 
						|
	end
 | 
						|
        @buf = Kconv.toeuc(@buf)
 | 
						|
	@bpos = 0
 | 
						|
      end
 | 
						|
      if @buf[@bpos] == TAG_START then
 | 
						|
	return Tag.new(read_until(TAG_END))
 | 
						|
      elsif @buf[@bpos] == AMP_START then
 | 
						|
	return read_until(AMP_END)
 | 
						|
      else
 | 
						|
	i = @bpos
 | 
						|
	while i < @buf.size && @buf[i] != TAG_START && @buf[i] != AMP_START
 | 
						|
	  i += 1
 | 
						|
	end
 | 
						|
	r = @buf[@bpos,i-@bpos]
 | 
						|
	if i == @buf.size then
 | 
						|
	  @buf = nil
 | 
						|
	else
 | 
						|
	  @bpos = i
 | 
						|
	end
 | 
						|
	redo if r =~ /^\s+$/
 | 
						|
	return r
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
  public :eof?
 | 
						|
  def eof?
 | 
						|
    @f.eof?
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
################################ MAIN ####################################
 | 
						|
 | 
						|
refs = []
 | 
						|
refnum = 0
 | 
						|
body_finished = false
 | 
						|
html_finished = false
 | 
						|
currentURL = nil
 | 
						|
immediate_ref = false
 | 
						|
 | 
						|
while ARGV[0] =~ /^-/
 | 
						|
  case ARGV.shift
 | 
						|
  when '-url'
 | 
						|
    currentURL = URL.new(ARGV.shift)
 | 
						|
  when '-u'
 | 
						|
    immediate_ref = true
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
if ARGV.size > 0 then
 | 
						|
  f = TokenStream.new(ARGV[0])
 | 
						|
else
 | 
						|
  f = TokenStream.new(STDIN)
 | 
						|
end
 | 
						|
 | 
						|
until f.eof?
 | 
						|
  tok = f.get
 | 
						|
  if tok.kind_of?(Tag) then
 | 
						|
    if tok.tagname == 'a' and !tok.switch('href').nil? then
 | 
						|
      refs[refnum] = tok.switch('href')
 | 
						|
      refnum += 1
 | 
						|
    elsif tok.tagname == '/a' then
 | 
						|
      if immediate_ref then
 | 
						|
        r = refs[refnum-1]
 | 
						|
        if !currentURL.nil? then
 | 
						|
          r = URL.new(r).complete(currentURL).to_s
 | 
						|
        end
 | 
						|
        print "[#{r}]"
 | 
						|
      else
 | 
						|
        print "[#{refnum}]"
 | 
						|
      end
 | 
						|
    elsif tok.tagname == '/body' then
 | 
						|
      body_finished = true
 | 
						|
      break
 | 
						|
    elsif tok.tagname == '/html' then
 | 
						|
      html_finished = true
 | 
						|
      break
 | 
						|
    end
 | 
						|
    print tok.to_s
 | 
						|
  elsif !tok.nil? then
 | 
						|
    print tok
 | 
						|
  end
 | 
						|
end
 | 
						|
if !immediate_ref and refs.size > 0 then
 | 
						|
  print "<hr><h2>References</h2>\n"
 | 
						|
  for i in 0..refs.size-1
 | 
						|
    if currentURL.nil? then
 | 
						|
      r = refs[i]
 | 
						|
    else
 | 
						|
      r = URL.new(refs[i])
 | 
						|
      r.complete(currentURL)
 | 
						|
      r = r.to_s
 | 
						|
    end
 | 
						|
    print "[#{i+1}] #{r}<br>\n"
 | 
						|
  end
 | 
						|
end
 | 
						|
print "</body>\n" unless body_finished
 | 
						|
print "</html>\n" unless html_finished
 |