makeref (4905B)
1 #!/usr/local/bin/ruby 2 3 # HTML reference generator 4 # by A.Ito 1999/3/30 5 6 require 'kconv' 7 8 ########################################################################### 9 class URL 10 attr 'scheme' 11 attr 'host' 12 attr 'port' 13 attr 'file' 14 attr 'label' 15 def initialize(str) 16 if /([a-zA-Z+\-]+):(.*)/ =~ str then 17 @scheme = $1 18 str = $2 19 else 20 @scheme = 'unknown' 21 end 22 hostpart = '' 23 if %r'//([^/]*)(/.*)' =~ str then 24 hostpart = $1 25 str = $2 26 elsif %r'//([^/]*)$' =~ str then 27 hostpart = str 28 str = '' 29 end 30 if hostpart != '' then 31 if /(.*):(\d+)/ =~ hostpart then 32 @host = $1 33 @port = $2 34 else 35 @host = hostpart 36 @port = '' 37 end 38 else 39 @host = @port = '' 40 end 41 if /(.*)#(.*)/ =~ str then 42 @file = $1 43 @label = $2 44 else 45 @file = str 46 @label = '' 47 end 48 end 49 def to_s 50 s = "#{@scheme}:" 51 if s == 'news' or s == 'mailto' then 52 return s+@file 53 end 54 s += "//"+@host 55 s += ":"+@port if @port.size > 0 56 s += @file 57 s += "#"+@label if @label.size > 0 58 s 59 end 60 def complete(current) 61 @scheme = current.scheme if @scheme == 'unknown' 62 @port = current.port if @host == '' and @port == '' 63 @host = current.host if @host == '' 64 unless @file =~ %r'^/' then 65 @file = File.expand_path(File.dirname(current.file)+'/'+@file) 66 end 67 self 68 end 69 end 70 71 class Tag 72 def initialize(str) 73 if str =~ /<(.+)>/ then 74 str = $1 75 end 76 tags = str.split 77 @tagname = tags.shift.downcase 78 @vals = {} 79 tags.each do |t| 80 if t =~ /=/ then 81 tn,tv = t.split(/\s*=\s*/,2) 82 tv.sub!(/^"/,"") 83 tv.sub!(/"$/,"") 84 @vals[tn.downcase] = tv 85 else 86 @vals[t.downcase] = TRUE 87 end 88 end 89 end 90 def tagname 91 return @tagname 92 end 93 def each 94 @vals.each do |k,v| 95 yield k,v 96 end 97 end 98 def switch(k) 99 return @vals[k] 100 end 101 def to_s 102 if tagname =~ /!--/ then 103 return '' 104 end 105 t = "<"+tagname 106 if @vals.size == 0 then 107 return t+">" 108 end 109 each do |a,v| 110 if v == true then 111 t += " #{a}" 112 else 113 t += " #{a}=\"#{v}\"" 114 end 115 end 116 t+">" 117 end 118 end 119 120 class TokenStream 121 TAG_START = ?< 122 TAG_END = ?> 123 AMP_START = ?& 124 AMP_END = ?; 125 126 def initialize(file) 127 if file.kind_of?(IO) then 128 @f = file 129 else 130 @f = File.new(file) 131 end 132 @buf = nil 133 @bpos = 0 134 end 135 136 def read_until(endsym) 137 complete = FALSE 138 tag = [] 139 begin 140 while @bpos < @buf.size 141 c = @buf[@bpos] 142 if c == endsym then 143 tag.push(c.chr) 144 complete = TRUE 145 @bpos += 1 146 break 147 end 148 if c == 10 || c == 13 then 149 tag.push(' ') 150 else 151 tag.push(c.chr) 152 end 153 @bpos += 1 154 end 155 unless complete 156 @buf = @f.gets 157 @bpos = 0 158 break if @f.eof? 159 end 160 end until complete 161 return tag.join('') 162 end 163 164 def get 165 while TRUE 166 if @buf.nil? then 167 @buf = @f.gets 168 if @f.eof? then 169 return nil 170 end 171 @buf = Kconv.toeuc(@buf) 172 @bpos = 0 173 end 174 if @buf[@bpos] == TAG_START then 175 return Tag.new(read_until(TAG_END)) 176 elsif @buf[@bpos] == AMP_START then 177 return read_until(AMP_END) 178 else 179 i = @bpos 180 while i < @buf.size && @buf[i] != TAG_START && @buf[i] != AMP_START 181 i += 1 182 end 183 r = @buf[@bpos,i-@bpos] 184 if i == @buf.size then 185 @buf = nil 186 else 187 @bpos = i 188 end 189 redo if r =~ /^\s+$/ 190 return r 191 end 192 end 193 end 194 public :eof? 195 def eof? 196 @f.eof? 197 end 198 end 199 200 ################################ MAIN #################################### 201 202 refs = [] 203 refnum = 0 204 body_finished = false 205 html_finished = false 206 currentURL = nil 207 immediate_ref = false 208 209 while ARGV[0] =~ /^-/ 210 case ARGV.shift 211 when '-url' 212 currentURL = URL.new(ARGV.shift) 213 when '-u' 214 immediate_ref = true 215 end 216 end 217 218 if ARGV.size > 0 then 219 f = TokenStream.new(ARGV[0]) 220 else 221 f = TokenStream.new(STDIN) 222 end 223 224 until f.eof? 225 tok = f.get 226 if tok.kind_of?(Tag) then 227 if tok.tagname == 'a' and !tok.switch('href').nil? then 228 refs[refnum] = tok.switch('href') 229 refnum += 1 230 elsif tok.tagname == '/a' then 231 if immediate_ref then 232 r = refs[refnum-1] 233 if !currentURL.nil? then 234 r = URL.new(r).complete(currentURL).to_s 235 end 236 print "[#{r}]" 237 else 238 print "[#{refnum}]" 239 end 240 elsif tok.tagname == '/body' then 241 body_finished = true 242 break 243 elsif tok.tagname == '/html' then 244 html_finished = true 245 break 246 end 247 print tok.to_s 248 elsif !tok.nil? then 249 print tok 250 end 251 end 252 if !immediate_ref and refs.size > 0 then 253 print "<hr><h2>References</h2>\n" 254 for i in 0..refs.size-1 255 if currentURL.nil? then 256 r = refs[i] 257 else 258 r = URL.new(refs[i]) 259 r.complete(currentURL) 260 r = r.to_s 261 end 262 print "[#{i+1}] #{r}<br>\n" 263 end 264 end 265 print "</body>\n" unless body_finished 266 print "</html>\n" unless html_finished