emailler/dist/document_ca65_source_as_html.rb
2009-03-26 04:03:48 +00:00

328 lines
9.6 KiB
Ruby

def document_ca65_source_as_html(codebase_dir,codebase_title,output_dir)
Dir.mkdir(output_dir) unless File.exist?(output_dir)
symbol_attributes={}
html_filenames={}
file_overviews={}
puts "generating documentation for #{codebase_title}"
documentation_title="#{codebase_title} technical reference"
require 'find'
files_to_parse=[]
Find.find(codebase_dir) do |path|
Find.prune if path[0]=='.'
files_to_parse <<path.sub(codebase_dir,"").sub(/^\//,"") if path=~/\.s$/
end
files_to_parse.each do |filename|
html_filename="#{filename.gsub(/[\/.]/,"_")}.html"
puts "scanning #{filename} (#{html_filename})"
html_filenames[filename]=html_filename
last_comment=nil
symbol=nil
file_overviews[filename]=""
found_non_comment_line=false
full_filename="#{codebase_dir}/#{filename}"
File.open(full_filename).each_line do |line|
#skip to next line if this is nothing but white space
next if line=~/^\s*$/
last_symbol=symbol unless symbol.nil?
symbol=nil
if (line=~/^\s*;(.*)/) && !(found_non_comment_line) then
file_overviews[filename]<<"#{$1}\n"
else
found_non_comment_line=true
end
if line=~/\.export\s+(\w+)/ then
symbol=$1
symbol_attributes[symbol]={} if symbol_attributes[symbol].nil?
symbol_attributes[symbol][:type]=:function
symbol_attributes[symbol][:defined_in]=[] if symbol_attributes[symbol][:defined_in].nil?
symbol_attributes[symbol][:defined_in]<<filename
filename
end
if line=~/\.exportzp\s+(\w+)/ then
symbol=$1
symbol_attributes[symbol]={} if symbol_attributes[symbol].nil?
symbol_attributes[symbol][:type]=:variable
symbol_attributes[symbol][:zero_page]=true
symbol_attributes[symbol][:defined_in]=[] if symbol_attributes[symbol][:defined_in].nil?
symbol_attributes[symbol][:defined_in]<<filename
end
if line=~/(\w+):?.*\.res\s+(\S+)/ then
symbol=$1
size=$2
if !symbol_attributes[symbol].nil? then
symbol_attributes[symbol][:type]=:variable
symbol_attributes[symbol][:size]={} if symbol_attributes[symbol][:size].nil?
symbol_attributes[symbol][:size][filename]=size
end
end
if line=~/(\w*)(:)*\s*\.(byte|asciiz)\s+([^;]*)/ then
symbol=$1
symbol=last_symbol if symbol.length<1
value=$4
if !symbol_attributes[symbol].nil? then
symbol_attributes[symbol][:type]=:constant
symbol_attributes[symbol][:value]={} if symbol_attributes[symbol][:value].nil?
if symbol_attributes[symbol][:value][filename].nil? then
symbol_attributes[symbol][:value][filename]=value
else
symbol_attributes[symbol][:value][filename]+="\n#{value}"
end
end
end
if line=~/(\w+):?.*=/ then
symbol=$1
if !symbol_attributes[symbol].nil? then
symbol_attributes[symbol][:type]=:variable if symbol_attributes[symbol][:type]==:function
end
end
if line=~/(\w+).*=\s?([^;]*)/ then
symbol=$1
value=$2
if !symbol_attributes[symbol].nil? then
symbol_attributes[symbol][:type]=:constant
symbol_attributes[symbol][:value]={} if symbol_attributes[symbol][:value].nil?
symbol_attributes[symbol][:value][filename]=value
end
end
if (symbol.nil?) && line=~/^(\w+):/ then
symbol=$1
end
comment=nil
if (!(symbol.nil?) && line=~/;(.*)/) then
comment=$1
end
if ((comment.nil?) && (!last_comment.nil?) && (!symbol.nil?)) then
comment=last_comment
end
if !symbol_attributes[symbol].nil? && !comment.nil? then
symbol_attributes[symbol][:comment]={} if symbol_attributes[symbol][:comment].nil?
symbol_attributes[symbol][:comment][filename]=comment
end
if line=~/^;(.*)/ then
if last_comment.nil? then
last_comment=""
else
last_comment+="\n"
end
last_comment+=$1
else
last_comment=nil
end
end
end
symbol_names=symbol_attributes.keys.sort
source_files=[]
require 'markaby'
[:function,:variable,:constant].each do |symbol_type|
mab = Markaby::Builder.new
mab.html do
head do
link(:rel=>"stylesheet", :href=>"ca65-doc-style.css",:type=>"text/css")
end
body do
h2 "#{symbol_type}s"
table do
tr do
th "#{symbol_type}"
th "defined in"
end
symbol_names.each do |symbol|
if symbol_attributes[symbol][:type]==symbol_type then
tr do
td symbol
count=0
td do
symbol_attributes[symbol][:defined_in].each do |filename|
count+=1
text ", " unless count==1
a(:href=>"#{html_filenames[filename]}##{symbol_type}s", :target=>"docwin"){filename}
source_files<<filename unless source_files.include?(filename)
end
end
end
end
end
end
end
end
File.open("#{output_dir}/#{symbol_type}_index.html","w") <<mab.to_s
end
mab = Markaby::Builder.new
mab.html do
head do
link(:rel=>"stylesheet", :href=>"ca65-doc-style.css",:type=>"text/css")
end
body do
h1 "#{documentation_title}"
h2 "files"
table do
tr do
th "file"
th "symbols"
end
source_files.sort.each do |filename|
tr do
td {a(:href=>"#{html_filenames[filename]}", :target=>"docwin"){filename}}
symbols_in_file=(symbol_names.collect{|symbol| symbol_attributes[symbol][:defined_in].include?(filename) ? symbol:nil}).compact
td symbols_in_file.join(", ")
end
end
end
end
end
File.open("#{output_dir}/ref_index.html","w") <<mab.to_s
source_files.sort.each do |filename|
functions_in_file=[]
variables_in_file=[]
constants_in_file=[]
symbol_names.each do |symbol|
symbol_attribute=symbol_attributes[symbol]
if symbol_attribute[:defined_in].include?(filename) then
functions_in_file<<symbol if symbol_attribute[:type]==:function
variables_in_file<<symbol if symbol_attribute[:type]==:variable
constants_in_file<<symbol if symbol_attribute[:type]==:constant
end
end
mab = Markaby::Builder.new
mab.html do
head do
link(:rel=>"stylesheet", :href=>"ca65-doc-style.css",:type=>"text/css")
end
body do
a(:href=>"ref_index.html") { h1 documentation_title}
h1 "File : #{filename}"
pre file_overviews[filename] if file_overviews[filename].length>1
if functions_in_file.length>0 then
h2(:id=>"functions") {"functions"}
table do
tr do
th{"function"}
th{"description"}
end
functions_in_file.each do |symbol|
tr do
td(:id=>symbol){symbol}
td{pre symbol_attributes[symbol][:comment][filename] unless symbol_attributes[symbol][:comment].nil?}
end
end
end
end
if variables_in_file.length>0 then
h2(:id=>"variables"){"variables"}
table do
tr do
th{"variable"}
th{"description"}
th{"size (bytes)"}
end
variables_in_file.each do |symbol|
tr do
td(:id=>symbol){symbol}
td{symbol_attributes[symbol][:comment][filename] unless symbol_attributes[symbol][:comment].nil?}
td{symbol_attributes[symbol][:size][filename] unless symbol_attributes[symbol][:size].nil?}
end
end
end
end
if constants_in_file.length>0 then
h2(:id=>"constants") {"constants"}
table do
tr do
th{"constants"}
th{"description"}
th{"value"}
end
constants_in_file.each do |symbol|
tr do
td(:id=>symbol){symbol}
td{symbol_attributes[symbol][:comment][filename] unless symbol_attributes[symbol][:comment].nil?}
td{symbol_attributes[symbol][:value][filename] unless symbol_attributes[symbol][:value].nil?}
end
end
end
end
h2{ "implementation"}
pre(:id=>:code) {File.open("#{codebase_dir}/#{filename}").read.gsub("\t"," ")}
end
end
File.open("#{output_dir}/#{html_filenames[filename]}","w") <<mab.to_s
end
#markaby doesn't like framesets so do the index.html frameset the 'old fashioned' way
File.open("#{output_dir}/ref_frames.html","w") << <<EOF
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>#{documentation_title}</title>
</head>
<frameset rows="20%, 80%" border=1>
<frameset cols="5,5,5" border=1>
<frame src="function_index.html" title="functions" name="functions" />
<frame src="variable_index.html" title="variables" name="variables"/>
<frame src="constant_index.html" title="constants" name="constants"/>
</frameset>
<frame name="docwin" src="ref_index.html" />
</frameset>
EOF
end
if __FILE__ == $0 then
#run from command line
codebase_dir=Dir.pwd
output_dir="doc"
codebase_title=File.basename(codebase_dir)
document_ca65_source_as_html(codebase_dir,codebase_title,output_dir)
end