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
 |