]
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK)
+# @markup.add_special(/\b(\S+?\[\S+?\.\S+?\])/, :TIDYLINK)
+
+ if Options.instance.mathml
+ # TeX inline form
+ @markup.add_special(/(\$(.*?)[^\\]\$)/im, :TEXINLINE)
+
+ # TeX inline delimiter
+ @markup.add_special(/(\\\$)/im, :TEXINLINEDELIMITER)
+
+ # TeX block form
+ @markup.add_special(/(\\\[(.+?)\\\])/im, :TEXBLOCK)
+ end
+
+ end
+ unless defined? @html_formatter
+ @html_formatter = TexParser.new(self.path, self)
+ end
+
+ # Convert leading comment markers to spaces, but only
+ # if all non-blank lines have them
+
+ if str =~ /^(?>\s*)[^\#]/
+ content = str
+ else
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
+ end
+
+ block_exceptions = []
+ if Options.instance.mathml
+ block_exceptions << {
+ 'name' => :texblockform,
+ 'start' => Regexp.new("^\\\\\\["),
+ 'end' => Regexp.new("\\\\\\]$"),
+ 'replaces' => []
+ }
+ block_exceptions[0]['replaces'] << {
+ 'from' => Regexp.new("\\\\\\\\"),
+ 'to' => "\\\\\\\\\\\\\\\\",
+ }
+ end
+
+ res = @markup.convert(content, @html_formatter, block_exceptions)
+ if remove_para
+ res.sub!(/^/, '')
+ res.sub!(/<\/p>$/, '')
+ end
+ res
+ end
+ end
+
+ class XHTMLGenerator < HTMLGenerator
+
+ def XHTMLGenerator.gen_url(path, target)
+ Generators::HTMLGenerator.gen_url(path, target)
+ end
+ def XHTMLGenerator.for(options)
+ AllReferences::reset
+ HtmlMethod::reset
+
+ if options.all_one_file
+ XHTMLGeneratorInOne.new(options)
+ else
+ XHTMLGenerator.new(options)
+ end
+ end
+
+ def generate(toplevels)
+ super(toplevels)
+ copy_xsls
+ end
+
+ private
+
+ def build_indices
+ @toplevels.each do |toplevel|
+ @files << XHtmlFile.new(toplevel, @options, FILE_DIR)
+ end
+
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
+ build_class_list(cls, @files[0], CLASS_DIR)
+ end
+ end
+
+ def build_class_list(from, html_file, class_dir)
+ @classes << XHtmlClass.new(from, html_file, class_dir, @options)
+ from.each_classmodule do |mod|
+ build_class_list(mod, html_file, class_dir)
+ end
+ end
+
+ def gen_method_index
+ gen_an_index(XHtmlMethod.all_methods, 'Methods',
+ RDoc::Page::METHOD_INDEX,
+ "fr_method_index.html")
+ end
+
+ def gen_an_index(collection, title, template, filename)
+ template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template)
+ res = []
+ collection.sort.each do |f|
+ if f.document_self
+ res << { "href" => f.path, "name" => f.index_name }
+ end
+ end
+
+ values = {
+ "entries" => res,
+ 'list_title' => CGI.escapeHTML(title),
+ 'index_url' => main_url,
+ 'charset' => @options.charset,
+ 'style_url' => style_url('', @options.css),
+ 'mathml_xsl_url' => style_url('', "mathml.xsl"),
+ }
+
+ File.open(filename, "w") do |f|
+ template.write_html_on(f, values)
+ end
+ end
+
+ def copy_xsls
+ xsl_files = ["mathml.xsl", "pmathmlcss.xsl", "ctop.xsl", "pmathml.xsl"]
+ xsl_dir = "rdoc/generators/template/xhtml"
+ hit = 0
+ $LOAD_PATH.each{ |path|
+ hit = 0
+ xsl_files.each{ |file|
+ hit += 1 if File.exist?(File.join(path, xsl_dir, file))
+ }
+ if hit >= 4
+ xsl_files.each{ |file|
+ File.copy(File.join(path, xsl_dir, file), "./")
+ }
+ break
+ else
+ hit = 0
+ end
+ }
+ if hit < 4
+ $stderr.puts "Couldn't find xsl files (#{xsl_files.join(', ')})\n"
+ exit
+ end
+ end
+
+ end
+
+ class XHTMLGeneratorInOne < HTMLGeneratorInOne
+ def build_class_list(from, html_file, class_dir)
+ @classes << XHtmlClass.new(from, html_file, class_dir, @options)
+ from.each_classmodule do |mod|
+ build_class_list(mod, html_file, class_dir)
+ end
+ end
+
+ def build_indices
+ @toplevels.each do |toplevel|
+ @files << XHtmlFile.new(toplevel, @options, FILE_DIR)
+ end
+
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
+ build_class_list(cls, @files[0], CLASS_DIR)
+ end
+ end
+
+ def gen_method_index
+ gen_an_index(XHtmlMethod.all_methods, 'Methods')
+ end
+ end
+
+ class XHtmlClass < HtmlClass
+ def value_hash
+ super
+ @values["mathml_xsl_url"] = style_url(path, "mathml.xsl")
+ @values
+ end
+
+ def collect_methods
+ list = @context.method_list
+ unless @options.show_all
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
+ end
+ @methods = list.collect {|m| XHtmlMethod.new(m, self, @options) }
+ end
+
+ end
+
+ class XHtmlFile < HtmlFile
+ def value_hash
+ super
+ @values["mathml_xsl_url"] = style_url(path, "mathml.xsl")
+ @values
+ end
+
+ def collect_methods
+ list = @context.method_list
+ unless @options.show_all
+ list = list.find_all {|m| m.visibility == :public || m.visibility == :protected || m.force_documentation }
+ end
+ @methods = list.collect {|m| XHtmlMethod.new(m, self, @options) }
+ end
+
+ end
+
+ class XHtmlMethod < HtmlMethod
+ def create_source_code_file(code_body)
+ template_regexp = Regexp.new("\\." + @options.template + "$")
+ meth_path = @html_class.path.sub(template_regexp, '.src')
+ File.makedirs(meth_path)
+ file_path = File.join(meth_path, @seq) + '.' + @options.template
+
+ template = TemplatePage.new(RDoc::Page::SRC_PAGE)
+ File.open(file_path, "w") do |f|
+ values = {
+ 'title' => CGI.escapeHTML(index_name),
+ 'code' => code_body,
+ 'style_url' => style_url(file_path, @options.css),
+ 'mathml_xsl_url' => style_url('', "mathml.xsl"),
+ 'charset' => @options.charset
+ }
+ template.write_html_on(f, values)
+ end
+ XHTMLGenerator.gen_url(path, file_path)
+ end
+ end
+
+end
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/install.rb ../rdoc-f95-20060814/install.rb
--- ruby-1.8.4/lib/rdoc/install.rb 1970-01-01 09:00:00.000000000 +0900
+++ ../rdoc-f95-20060814/install.rb 2006-08-10 17:31:30.000000000 +0900
@@ -0,0 +1,178 @@
+require 'rbconfig'
+require 'find'
+require 'ftools'
+require 'optparse'
+
+include Config
+
+$ruby = CONFIG['ruby_install_name']
+
+##
+# Install a binary file. We patch in on the way through to
+# insert a #! line. If this is a Unix install, we name
+# the command (for example) 'rdoc' and let the shebang line
+# handle running it. Under windows, we add a '.rb' extension
+# and let file associations to their stuff
+#
+
+def installBIN(from, opfile)
+
+ tmp_dir = nil
+ for t in [".", "/tmp", "c:/temp", $bindir]
+ stat = File.stat(t) rescue next
+ if stat.directory? and stat.writable?
+ tmp_dir = t
+ break
+ end
+ end
+
+ fail "Cannot find a temporary directory" unless tmp_dir
+ tmp_file = File.join(tmp_dir, "_tmp")
+
+
+ File.open(from) do |ip|
+ File.open(tmp_file, "w") do |op|
+ ruby = File.join($realbindir, $ruby)
+# op.puts "#!#{ruby}"
+ op.write ip.read
+ end
+ end
+
+ opfile += ".rb" if CONFIG["target_os"] =~ /mswin/i
+ File::install(tmp_file, File.join($bindir, opfile), 0755, true)
+ File::unlink(tmp_file)
+end
+
+# Main Program
+
+opt = OptionParser.new
+OPTS = {}
+opt.summary_width = 23
+opt.summary_indent = ''*1
+opt.on('--bindir=VAL',
+ 'Directory to which the executable file is installed') \
+ {|v| $bindir = v.to_s}
+opt.on('--binname=VAL',
+ 'Name of the executable file (default name is "rdoc")') \
+ {|v| $binname = v.to_s}
+opt.on('--libdir=VAL',
+ 'Directory to which the libraries are installed') \
+ {|v| $libdir = v.to_s}
+opt.on('--help', 'Show help message') {|v| OPTS[:help] = v}
+
+opt.parse!(ARGV)
+
+$bindir = File.expand_path($bindir) if $bindir
+$binname ||= "rdoc"
+$libdir = File.expand_path($libdir) if $libdir
+
+install_opt = ""
+install_opt = "--libdir=#{$libdir}" if $libdir
+
+if $libdir
+ $sitedir = $libdir
+else
+ $sitedir = CONFIG["sitelibdir"]
+ unless $sitedir
+ version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
+ $libdir = File.join(CONFIG["libdir"], "ruby", version)
+ $sitedir = $:.find {|x| x =~ /site_ruby/}
+ if !$sitedir
+ $sitedir = File.join($libdir, "site_ruby")
+ elsif $sitedir !~ Regexp.quote(version)
+ $sitedir = File.join($sitedir, version)
+ end
+ end
+end
+
+$bindir ||= CONFIG["bindir"]
+$realbindir = $bindir
+
+bindir = CONFIG["bindir"]
+
+rdoc_dest = File.join($sitedir, "rdoc")
+dot_dest = File.join(rdoc_dest, "dot")
+rdoc_generators = File.join(rdoc_dest, "generators")
+rdoc_templates = File.join(rdoc_generators, "template")
+rdoc_parsers = File.join(rdoc_dest, "parsers")
+rdoc_ri = File.join(rdoc_dest, "ri")
+
+# help message
+if ARGV[0] || OPTS[:help]
+ print <<-HELP
+
+ This ruby script installs libraries to \"#{rdoc_dest}\",
+ and executables to \"#{$bindir}/#{$binname}\". (See \"rbconfig.rb\")
+
+ If you want to install other directory, use following options.
+
+ OPTIONS: \n#{opt.to_a[1..-1].join("")}
+
+HELP
+ exit
+end
+
+# make directories
+File::makedirs(rdoc_dest,
+ dot_dest,
+ rdoc_generators,
+ rdoc_templates,
+ rdoc_parsers,
+ rdoc_ri,
+ true)
+
+File::chmod(0755, rdoc_dest)
+
+
+
+# The library files
+files = %w{
+ code_objects.rb
+ generators/*_generator.rb
+ options.rb
+ parsers/parserfactory.rb
+ parsers/parse_*.rb
+ template.rb
+ tokenstream.rb
+ diagram.rb
+ rdoc.rb
+ dot/dot.rb
+ ri/ri_*.rb
+}.collect {|f| Dir.glob(f)}.flatten
+
+for template in ["chm", "html", "xml", "xhtml"]
+ File::makedirs(File.join(rdoc_templates, template), true)
+ files.concat Dir.glob("generators/template/#{template}/*.rb")
+ files.concat Dir.glob("generators/template/#{template}/*.xsl")
+end
+
+for aFile in files
+ File::install(aFile, File.join(rdoc_dest, aFile), 0644, true)
+end
+
+# and the executable
+
+installBIN("rdoc", $binname)
+
+# Temporary - we used to install html_generator in the rdoc
+# directory, but now it's moved
+
+File.unlink(File.join(rdoc_dest, "html_generator.rb")) rescue 1;
+
+# and we used to have the templates under html_template
+template = File.join(rdoc_dest, "generators", "html_template")
+File.unlink(File.join(template, "standard.rb")) rescue 1;
+File.unlink(File.join(template, "kilmer.rb")) rescue 1;
+
+# and then they were in template/ ...
+template = File.join(rdoc_dest, "generators", "template")
+File.unlink(File.join(template, "standard.rb")) rescue 1;
+File.unlink(File.join(template, "kilmer.rb")) rescue 1;
+File.unlink(File.join(template, "xml.rb")) rescue 1;
+File.unlink(File.join(template, "rdf.rb")) rescue 1;
+
+
+# 'Markup' will eventually be a separate package, but
+# for now we'll install it automatically
+
+Dir.chdir("markup") && system("#$ruby install.rb #{install_opt}")
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/markup/install.rb ../rdoc-f95-20060814/markup/install.rb
--- ruby-1.8.4/lib/rdoc/markup/install.rb 1970-01-01 09:00:00.000000000 +0900
+++ ../rdoc-f95-20060814/markup/install.rb 2005-11-15 19:46:27.000000000 +0900
@@ -0,0 +1,58 @@
+require 'rbconfig'
+require 'find'
+require 'ftools'
+require 'optparse'
+
+include Config
+
+opt = OptionParser.new
+libdir = nil
+opt.on('--libdir=VAL') {|v| libdir = v}
+opt.parse!(ARGV)
+
+libdir = File.expand_path(libdir) if libdir
+
+if libdir
+ sitedir = libdir
+else
+ sitedir = CONFIG["sitelibdir"]
+ unless sitedir
+ version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
+ libdir = File.join(CONFIG["libdir"], "ruby", version)
+ sitedir = $:.find {|x| x =~ /site_ruby/}
+ if !sitedir
+ sitedir = File.join(libdir, "site_ruby")
+ elsif sitedir !~ Regexp.quote(version)
+ sitedir = File.join(sitedir, version)
+ end
+ end
+end
+
+unless /^\// =~ sitedir.strip
+ sitedir = File.join("..", sitedir)
+end
+
+if !File.directory?(sitedir)
+ $stderr.puts "Cannot find sitedir #{sitedir}"
+ exit 1
+end
+
+rdoc_dest = File.join(sitedir, "rdoc")
+
+dest = File.join(rdoc_dest, "markup")
+
+File.mkpath(dest, true)
+
+Find.find("simple_markup.rb",
+ "simple_markup",
+ "sample",
+ "test") do |fname|
+ if File.directory?(fname)
+ next if fname =~ /CVS/
+ File.mkpath(File.join(dest, fname), true)
+ else
+ next unless fname =~ /\.rb$/
+ next if fname =~ /install.rb$/
+ File.install(fname, File.join(dest, fname), 0444, true)
+ end
+end
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/markup/simple_markup/mathml_wrapper.rb ../rdoc-f95-20060814/markup/simple_markup/mathml_wrapper.rb
--- ruby-1.8.4/lib/rdoc/markup/simple_markup/mathml_wrapper.rb 1970-01-01 09:00:00.000000000 +0900
+++ ../rdoc-f95-20060814/markup/simple_markup/mathml_wrapper.rb 2006-08-05 17:23:55.000000000 +0900
@@ -0,0 +1,24 @@
+# This class is MathML module wrapper.
+# If MathML module can not be loaded, methods in this module return
+# raw argument without modification.
+
+class MathMLWrapper
+ def initialize
+ @load_error_flag = false
+ begin
+ require "mathml"
+ rescue LoadError
+ @load_error_flag = true
+ end
+ end
+ def parse(formula, block=false)
+ return formula if @load_error_flag
+ mathml_formula = MathML::LaTeX::Parser.new
+ begin
+ mathml_formula_str = mathml_formula.parse(formula, block).to_s
+ rescue MathML::LaTeX::ParseError
+ return formula, 1
+ end
+ return mathml_formula_str, 0
+ end
+end
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/markup/simple_markup/preprocess.rb ../rdoc-f95-20060814/markup/simple_markup/preprocess.rb
--- ruby-1.8.4/lib/rdoc/markup/simple_markup/preprocess.rb 2004-11-26 13:32:11.000000000 +0900
+++ ../rdoc-f95-20060814/markup/simple_markup/preprocess.rb 2005-09-22 16:49:19.000000000 +0900
@@ -43,7 +43,12 @@
def include_file(name, indent)
if (full_name = find_include_file(name))
content = File.open(full_name) {|f| f.read}
- res = content.gsub(/^#?/, indent)
+ # strip leading '#'s, but only if all lines start with them
+ if content =~ /^[^#]/
+ content.gsub(/^/, indent)
+ else
+ content.gsub(/^#?/, indent)
+ end
else
$stderr.puts "Couldn't find file to include: '#{name}'"
''
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/markup/simple_markup.rb ../rdoc-f95-20060814/markup/simple_markup.rb
--- ruby-1.8.4/lib/rdoc/markup/simple_markup.rb 2005-10-25 02:13:42.000000000 +0900
+++ ../rdoc-f95-20060814/markup/simple_markup.rb 2006-08-05 23:21:19.000000000 +0900
@@ -207,6 +207,7 @@
def initialize
@am = AttributeManager.new
@output = nil
+ @block_exceptions = nil
end
##
@@ -246,11 +247,12 @@
# all lines in a paragraph). We then invoke the output formatter
# using a Visitor to display the result
- def convert(str, op)
+ def convert(str, op, block_exceptions=nil)
@lines = Lines.new(str.split(/\r?\n/).collect { |aLine|
Line.new(aLine) })
return "" if @lines.empty?
@lines.normalize
+ @block_exceptions = block_exceptions
assign_types_to_lines
group = group_lines
# call the output formatter to handle the result
@@ -270,8 +272,35 @@
#
def assign_types_to_lines(margin = 0, level = 0)
-
+ now_blocking = false
while line = @lines.next
+ if @block_exceptions
+ if now_blocking
+ line.stamp(Line::PARAGRAPH, level)
+ @block_exceptions.each{ |be|
+ if now_blocking == be['name']
+ be['replaces'].each{ |rep|
+ line.text.gsub!(rep['from'], rep['to'])
+ }
+ end
+ if now_blocking == be['name'] && line.text =~ be['end']
+ now_blocking = false
+ break
+ end
+ }
+ next
+ else
+ @block_exceptions.each{ |be|
+ if line.text =~ be['start']
+ now_blocking = be['name']
+ line.stamp(Line::PARAGRAPH, level)
+ break
+ end
+ }
+ next if now_blocking
+ end
+ end
+
if line.isBlank?
line.stamp(Line::BLANK, level)
next
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/options.rb ../rdoc-f95-20060814/options.rb
--- ruby-1.8.4/lib/rdoc/options.rb 2004-11-21 00:02:56.000000000 +0900
+++ ../rdoc-f95-20060814/options.rb 2006-08-05 00:46:32.000000000 +0900
@@ -2,6 +2,7 @@
# object to be queried for option values
require "rdoc/ri/ri_paths"
+require "pathname"
class Options
@@ -56,6 +57,9 @@
# should we draw fileboxes in diagrams
attr_reader :fileboxes
+ # TeX formatted formula is converted to MathML
+ attr_reader :mathml
+
# include the '#' at the front of hyperlinked instance method names
attr_reader :show_hash
@@ -91,6 +95,9 @@
# multiple files
attr_reader :promiscuous
+ # The case of names of classes or modules or methods are ignored
+ attr_reader :ignore_case
+
module OptionList
OPTION_LIST = [
@@ -116,6 +123,12 @@
"option correctly. Dot is available from\n"+
"http://www.research.att.com/sw/tools/graphviz/" ],
+ [ "--mathml", "-l", nil,
+ "TeX formatted formula is converted to MathML.\n" +
+ "You need mathml.rb V0.5 to use the --mathml\n" +
+ "option correctly. mathml.rb V0.5 is available from\n"+
+ "http://www.hinet.mydns.jp/~hiraku/data/files/mathml-0.5.tar.gz" ],
+
[ "--exclude", "-x", "pattern",
"do not process files or directories matching\n" +
"pattern. Files given explicitly on the command\n" +
@@ -143,6 +156,10 @@
[ "--help-output", "-O", nil,
"explain the various output options" ],
+ [ "--ignore-case", "-C", nil,
+ "The case of names of classes or modules\n" +
+ "or methods are ignored" ],
+
[ "--image-format", "-I", "gif/png/jpg/jpeg",
"Sets output image format for diagrams. Can\n" +
"be png, gif, jpeg, jpg. If this option is\n" +
@@ -320,6 +337,8 @@
These files will appear in the directory given by the --op
option (doc/ by default).
+ - XHTML output is the same as HTML.
+
- XML output by default is written to standard output. If a
--opname option is given, the output will instead be written
to a file with that name in the output directory.
@@ -354,6 +373,7 @@
@title = nil
@template = nil
@diagram = false
+ @mathml = false
@fileboxes = false
@show_hash = false
@image_format = 'png'
@@ -363,6 +383,7 @@
@include_line_numbers = false
@extra_accessor_flags = {}
@promiscuous = false
+ @ignore_case = false
@css = nil
@webcvs = nil
@@ -392,17 +413,30 @@
when "--main" then @main_page = arg
when "--merge" then @merge = true
when "--one-file" then @all_one_file = @inline_source = true
- when "--op" then @op_dir = arg
when "--opname" then @op_name = arg
when "--promiscuous" then @promiscuous = true
when "--quiet" then @quiet = true
when "--show-hash" then @show_hash = true
- when "--style" then @css = arg
when "--template" then @template = arg
when "--title" then @title = arg
when "--webcvs" then @webcvs = arg
+ when "--ignore-case" then @ignore_case = true
+
+ when "--op"
+ if @css && ! (%r{^(https?:/)?/} =~ @css)
+ @css = relative_str(File.join(arg, "."),
+ relative_str(File.join(@op_dir.split("/").fill(".."), ".."), @css))
+ end
+ @op_dir = arg
- when "--accessor"
+ when "--style"
+ if %r{^(https?:/)?/} =~ arg
+ @css = arg
+ else
+ @css = relative_str(File.join(@op_dir, "."), arg)
+ end
+
+ when "--accessor"
arg.split(/,/).each do |accessor|
if accessor =~ /^(\w+)(=(.*))?$/
accessors << $1
@@ -417,6 +451,13 @@
when "--fileboxes"
@fileboxes = true if @diagram
+ when "--mathml"
+ check_mathml
+ @mathml = true
+ @generator_name = 'xhtml'
+ @template = @generator_name
+ setup_generator(generators)
+
when "--fmt"
@generator_name = arg.downcase
setup_generator(generators)
@@ -557,7 +598,49 @@
# exit
end
end
-
+
+ # Check that the right version of 'mathml.rb' is available.
+ #
+ def check_mathml
+ not_found = true
+ fpath = ""
+ $LOAD_PATH.each{ |lpath|
+ fpath = File.join(lpath, "mathml.rb")
+ if File.exist?(fpath)
+ not_found = false
+ break
+ end
+ }
+
+ if not_found
+ $stderr.puts <<-"EOT"
+You need the 'mathml.rb' to convert TeX to MathML.
+(see http://www.hinet.mydns.jp/~hiraku/hiki/, but JAPANESE only.
+ You can download 'mathml.rb' directly from
+ http://www.hinet.mydns.jp/~hiraku/data/files/mathml-0.5.tar.gz)
+
+EOT
+ exit
+ end
+
+ contents = File.open(fpath, "r") {|f| f.read}
+ num = 1
+ if !(contents =~ /^\s*module\s+MathML/) ||
+ !(contents =~ /^\s*module\s+LaTeX/) ||
+ !(contents =~ /^\s*class\s+Parser/) ||
+ !(contents =~ /^\s*def\s+parse/)
+ $stderr.puts <<-"EOT"
+You need the 'mathml.rb' V0.5 or later to use.
+(see http://www.hinet.mydns.jp/~hiraku/hiki/, but JAPANESE only.
+ You can download 'mathml.rb' directly from
+ http://www.hinet.mydns.jp/~hiraku/data/files/mathml-0.5.tar.gz)
+
+EOT
+
+ exit
+ end
+ end
+
# Check that the files on the command line exist
def check_files
@@ -572,4 +655,19 @@
exit(1)
end
+ def relative_str(from, target)
+ from_dir = File.dirname(from)
+ target_dir = File.dirname(target)
+ target_base = File.basename(target)
+
+ from_ab_path = Pathname.new(File.expand_path(from_dir))
+ target_ab_path = Pathname.new(File.expand_path(target_dir))
+
+ target_re_path = target_ab_path.relative_path_from(from_ab_path)
+
+ result = target_re_path.to_s + "/" + target_base
+
+ return result
+ end
+
end
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/parsers/parse_c.rb ../rdoc-f95-20060814/parsers/parse_c.rb
--- ruby-1.8.4/lib/rdoc/parsers/parse_c.rb 2005-07-16 00:00:11.000000000 +0900
+++ ../rdoc-f95-20060814/parsers/parse_c.rb 2005-12-17 21:01:31.000000000 +0900
@@ -167,7 +167,7 @@
extend ParserFactory
- parse_files_matching(/\.(c|cc|cpp|CC)$/)
+ parse_files_matching(/\.(c|cc|cpp|CC|cxx)$/)
@@known_bodies = {}
@@ -262,7 +262,7 @@
def find_class_comment(class_name, class_meth)
comment = nil
if @body =~ %r{((?>/\*.*?\*/\s+))
- (static\s+)?void\s+Init_#{class_name}\s*\(\)}xmi
+ (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi
comment = $1
elsif @body =~ %r{Document-(class|module):\s#{class_name}\s*?\n((?>.*?\*/))}m
comment = $2
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/parsers/parse_f95.rb ../rdoc-f95-20060814/parsers/parse_f95.rb
--- ruby-1.8.4/lib/rdoc/parsers/parse_f95.rb 2004-01-02 15:01:12.000000000 +0900
+++ ../rdoc-f95-20060814/parsers/parse_f95.rb 2006-08-09 18:05:38.000000000 +0900
@@ -1,15 +1,351 @@
-# Parse a Fortran 95 file.
+#= parse_f95.rb - Fortran95 Parser
+#
+#Note that Japanese and English are described in parallel.
+#
+#== ³µÍ×
+#
+#parse_f95.rb ¤Ï³ÈÄ¥»Ò¤¬ f90, F90, f95, F95 ¤Î¥Õ¥¡¥¤¥ë¤ò¹½Ê¸²òÀϤ·¤Þ¤¹.
+#¥½¡¼¥¹¥³¡¼¥É¤Ï Fortran 95 µ¬³Ê¤Ç¿ä¾©¤µ¤ì¤ë½ñË¡¤Çµ½Ò¤µ¤ì¤ë¤³¤È¤ò
+#Á°Äó¤È¤·¤Æ¤¤¤Þ¤¹.
+#
+#== Overview
+#
+#"parse_f95.rb" parses Fortran95 files with suffixes "f90", "F90", "f95"
+#and "F95". Fortran95 files are expected to be conformed to Fortran95
+#standards.
+#
+#== ½ñË¡
+#
+#´ðËÜŪ¤Ê½ñË¡¤Ï{Ruby ¤Î½ñË¡}[http://www.ruby-doc.org/stdlib/libdoc/rdoc/rdoc/index.html]
+#¤ÈƱÍͤǤ¹¤¬, ¥³¥á¥ó¥ÈÉô¤Ï '#' ¤Ç¤Ï¤Ê¤¯ '!' ¤Ç»Ï¤Þ¤ë¤³¤È¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤.
+#
+#== Rules
+#
+#Fundamental rules are same as that of the Ruby parser.
+#But comment markers are '!' not '#'.
+#
+#=== RDoc ¥É¥¥å¥á¥ó¥Æ¡¼¥·¥ç¥ó¤È Fortran95 ¥×¥í¥°¥é¥à¤È¤ÎÂбþ
+#
+#parse_f95.rb ¤Ï Fortran 90/95 µ¬³Ê¤Ë¤ª¤±¤ë¸À¸ìÍ×ÁÇ, ¤¹¤Ê¤ï¤Á,
+#¼ç¥×¥í¥°¥é¥à, ¥â¥¸¥å¡¼¥ë, ¥µ¥Ö¥ë¡¼¥Á¥ó, ´Ø¿ô¤Î¾,
+#public »ØÄê¤Ë¤è¤Ã¤Æ¸ø³«¤µ¤ì¤ëÊÑ¿ô¤äÄê¿ô, ¤½¤·¤ÆÍøÍѼÔÄêµÁ±é»»»Ò,
+#ÍøÍѼÔÄêµÁÂåÆþ¤ò¹½Ê¸²òÀϤ·¤Þ¤¹.
+#¤³¤ì¤é¤Î¸À¸ìÍ×ÁÇ¤Ï RDoc ¥É¥¥å¥á¥ó¥Æ¡¼¥·¥ç¥ó¤Î³Æ¹àÌܤË,
+#°Ê²¼¤Î¤è¤¦¤Ëµ½Ò¤µ¤ì¤Þ¤¹.
+#
+#Files :: ¥Õ¥¡¥¤¥ë (Ruby ¤ÈƱÍͤǤ¹)
+#Classes :: ¥â¥¸¥å¡¼¥ë, NAMELIST ÊÑ¿ô·²Ì¾¥ê¥¹¥È
+#Methods :: ¼ç¥×¥í¥°¥é¥à, ¥µ¥Ö¥ë¡¼¥Á¥ó, ´Ø¿ô, ÊÑ¿ô, Äê¿ô, ¹½Â¤¥Ç¡¼¥¿·¿,
+# ÍøÍѼÔÄêµÁ±é»»»Ò, ÍøÍѼÔÄêµÁÂåÆþ, NAMELIST ÊÑ¿ô·²Ì¾
+#Required files :: »²¾È¤¹¤ë¥â¥¸¥å¡¼¥ë¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë,
+# µÚ¤Ó»²¾È¤¹¤ë³°Éô´Ø¿ô¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤Î¥ê¥¹¥È
+#Included Modules :: »²¾È¤¹¤ë¥â¥¸¥å¡¼¥ë¤Î¥ê¥¹¥È
+#Attributes :: ¹½Â¤¥Ç¡¼¥¿·¿¤Î¥ê¥¹¥È, »²¾È¤·³î¤Ä¤½¤ÎÁ´¤Æ¤Î¸À¸ìÍ×ÁǤò¸ø³«¤¹¤ë
+# ¥â¥¸¥å¡¼¥ë¤Î¥ê¥¹¥È
+#
+#'Methods' ¤Ë¥ê¥¹¥È¤µ¤ì¤ë¸À¸ìÍ×ÁÇ (¥µ¥Ö¥ë¡¼¥Á¥ó, ´Ø¿ô, ¡Ä) ¤Ï,
+#¥â¥¸¥å¡¼¥ëÆâ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç¤¢¤ì¤Ð, 'Classes' ¤Î¹àÌܤ˵½Ò¤µ¤ì¤Þ¤¹.
+#¼ç¥×¥í¥°¥é¥àÆâ¤ÇÄêµÁ¤µ¤ì¤¿¤ê, ³°Éô¼ê³¤¤È¤·¤ÆÄêµÁ¤µ¤ì¤ë¾ì¹ç¤Ë¤Ï
+#'Files' ¤Î¹àÌܤ˵½Ò¤µ¤ì¤Þ¤¹.
+#¼ç¥×¥í¥°¥é¥à¼«ÂΤâ 'Files' ¤Î¹àÌܤ˵½Ò¤µ¤ì¤Þ¤¹.
+#
+#
+#=== Correspondence between RDoc documentation and Fortran95 programs
+#
+#"parse_f95.rb" parses entities of Fortran 90/95 standards, or main programs,
+#modules, subroutines, functions, derived types, public variables,
+#public constants, defined operators and defined assignments.
+#These entities are described in items of RDoc documentation, as follows.
+#
+#Files :: Files (same as Ruby)
+#Classes :: Modules, list of NAMELIST group names
+#Methods :: Main programs, Subroutines, functions, variables, constants,
+# derived types, defined operators, defined assignments,
+# NAMELIST group names
+#Required files :: Files in which imported modules, external subroutines
+# and external functions are defined.
+#Included Modules :: List of imported modules
+#Attributes :: List of derived types, List of imported modules all of
+# whose components are published again
+#
+#Entities listed in 'Methods' (subroutines, functions, ...)
+#defined in modules are described in the item of 'Classes'.
+#On the other hand, defined in main programs or
+#as external procedures are described in the item of 'Files'.
+#Main programs are described in the item of 'Files', too.
+#
+#=== ¹½Ê¸²òÀϤµ¤ì¤ë¸À¸ìÍ×ÁÇ
+#
+#¼ç¥×¥í¥°¥é¥à¤ª¤è¤Ó, ³°Éô¤«¤é»²¾È¤¬²Äǽ¤Ê¥µ¥Ö¥ë¡¼¥Á¥ó,
+#´Ø¿ô, ÊÑ¿ô, Äê¿ô, ¹½Â¤¥Ç¡¼¥¿·¿, ÍøÍѼÔÄêµÁ±é»»»Ò,
+#ÍøÍѼÔÄêµÁÂåÆþ, NAMELIST ÊÑ¿ô·²Ì¾¤¬¥É¥¥å¥á¥ó¥È¤È¤·¤Æ½ÐÎϤµ¤ì¤Þ¤¹. --all
+#¥ª¥×¥·¥ç¥ó¤ò¤Ä¤±¤Æ rdoc ¤ò¼Â¹Ô¤¹¤ë¾ì¹ç¤Ë¤Ï, ³°Éô¤«¤é¤Î»²¾È¤¬µö²Ä¤µ¤ì¤Ê¤¤
+#¸À¸ìÍ×ÁǤâ´Þ¤á, Á´¤Æ¤¬½ÐÎϤµ¤ì¤Þ¤¹.
+#
+#
+#=== Parsed entities
+#
+#Documentation on public entities (main programs,
+#subroutines, functions, variables, constants,
+#derived types, defined operators,
+#defined assignments, NAMELIST group names) are generated.
+#With "--all" option, documentation on all entities
+#are generated (almost same as the Ruby parser).
+#
+#
+#=== ¹½Ê¸²òÀϤµ¤ì¤ë¾ðÊó
+#
+#°Ê²¼¤Î¾ðÊó¤Ï, ¼«Æ°Åª¤Ë¹½Ê¸²òÀϤµ¤ì¤Æ¥³¥á¥ó¥ÈÉô¤È¤·¤Æ½ÐÎϤµ¤ì¤Þ¤¹.
+#
+#* ¥µ¥Ö¥ë¡¼¥Á¥ó, ´Ø¿ô¤Î°ú¿ô¤Î¥Ç¡¼¥¿·¿
+#* ¸ø³«ÊÑ¿ô, ¸ø³«Äê¿ô¤Î¥Ç¡¼¥¿·¿
+#* ¹½Â¤¥Ç¡¼¥¿·¿¤ÎÍ×ÁǤΥǡ¼¥¿·¿, ½é´üÃÍ
+#* NAMELIST ʸ¤ÇÀë¸À¤µ¤ì¤ëÊÑ¿ô̾ʤӤÎÊÑ¿ô¤Î¥Ç¡¼¥¿·¿, ½é´üÃÍ
+#
+#interface ʸ¤Ë¤è¤Ã¤Æ, ¤¢¤ë¼ê³¤¤Ë´Ø¤·¤Æ¸ÄÊÌ̾¤È¤ÏÊ̤Î̾Á°¤ò
+#Àë¸À¤¹¤ë¾ì¹ç, ¤½¤ÎÊÌ̾¤â 'Methods' ¤ËÄɲä·¤Þ¤¹.
+#
+#»²¾È¤·¤¿Ê̤Υ⥸¥å¡¼¥ëÆâ¤Î¸ø³«¸À¸ìÍ×ÁÇ (¥µ¥Ö¥ë¡¼¥Á¥ó, ´Ø¿ô, ÊÑ¿ô¤Ê¤É)
+#¤ò¼«¿È¤Î¸À¸ìÍ×ÁǤȤ·¤Æ²þ¤á¤Æ¸ø³«¤¹¤ë¾ì¹ç,
+#¤½¤Î¸À¸ìÍ×ÁǤϼ«¿È¤Î¸À¸ìÍ×ÁǤȤ·¤Æ¥â¥¸¥å¡¼¥ë¤Î 'Methods' ¥ê¥¹¥È¤ËÄɲ䵤ì¤Þ¤¹.
+#
+#interface ¤Ë¤è¤Ã¤Æ³°ÉôÉû¥×¥í¥°¥é¥à¤ò¼«¿È¤ÎÉû¥×¥í¥°¥é¥à¤È¤·¤Æ¸ø³«¤¹¤ë
+#¾ì¹ç, ¤½¤Î³°ÉôÉû¥×¥í¥°¥é¥à¤â¥â¥¸¥å¡¼¥ë¤Î 'Methods' ¥ê¥¹¥È¤ËÄɲä·¤Þ¤¹.
+#
+#
+#=== Parsed information
+#
+#The following information is automatically parsed.
+#
+#* Data types of arguments
+#* Data types of public variables and public constants
+#* Data types and initial values of variables in the derived types
+#* Data types and initial values of variables declared in NAMELIST statement
+#
+#Aliases declared by interface statement are described in the item
+#of 'Methods'.
+#
+#Entities which are imported from other modules and published again
+#are described in the item of 'Methods'.
+#
+#
+#=== ¥³¥á¥ó¥ÈÉô¤Î½ñ¤Êý
+#
+#¥³¥á¥ó¥ÈÉô¤Ï°Ê²¼¤Î¤è¤¦¤Ëµ½Ò¤·¤Þ¤¹. ¸¶Â§Åª¤Ë¹ÔËö¤Þ¤¿¤Ï Fortran
+#¤Îʸ¤Î²¼Éô¤Ë¥³¥á¥ó¥È¤òµ½Ò¤·¤Þ¤¹. '!' ¤ò´Þ¤Þ¤Ê¤¤¹Ô¤¬¸½¤ì¤¿»þÅÀ¤Ç,
+#¥³¥á¥ó¥ÈÉô¤Ï½ªÎ»¤·¤¿¤È¸«¤Ê¤µ¤ì¤Þ¤¹.
+#Îã¤Ç¤Ï¥³¥á¥ó¥È¹Ô¤â¥¤¥ó¥Ç¥ó¥È¤µ¤ì¤Æ¤¤¤Þ¤¹¤¬, ¥¤¥ó¥Ç¥ó¥È¤¹¤ë¤³¤È¤Ï
+#ɬ¿Ü¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó.
+#
+# ! (¥Õ¥¡¥¤¥ë¤Î¹ÔƬ)
+# !
+# ! ¥Õ¥¡¥¤¥ë¤ËÂФ¹¤ë¥³¥á¥ó¥È¤Ï¤³¤³¤Ëµ½Ò¤·¤Þ¤¹
+# !
+# !--
+# ! "!--" ¤È "!++" ¤Ë°Ï¤Þ¤ì¤¿Éôʬ¤Ëµ½Ò¤µ¤ì¤¿¥³¥á¥ó¥È¤Ï
+# ! ¥É¥¥å¥á¥ó¥È¤ËÈ¿±Ç¤µ¤ì¤Þ¤»¤ó.
+# !++
+# !
+# module hogehoge
+# !
+# ! ¥â¥¸¥å¡¼¥ë (program ¤Î¾ì¹ç¤Ï¼ç¥×¥í¥°¥é¥à)
+# ! ¤ËÂФ¹¤ë¥³¥á¥ó¥È¤Ï¤³¤³¤Ëµ½Ò¤·¤Þ¤¹
+# !
+#
+# private
+#
+# logical :: a ! Èó¸ø³«ÊÑ¿ô
+# real, public :: b ! ¸ø³«ÊÑ¿ô
+# integer, parameter :: c = 0 ! ¸ø³«Äê¿ô
+#
+# public :: c
+# public :: MULTI_ARRAY
+# public :: hoge, foo
+#
+# type MULTI_ARRAY
+# !
+# ! ¹½Â¤¥Ç¡¼¥¿·¿¤ËÂФ¹¤ë¥³¥á¥ó¥È¤Ï¤³¤³¤Ëµ½Ò¤·¤Þ¤¹.
+# !
+# real, pointer :: var(:) =>null() ! ÊÑ¿ô¤ËÂФ¹¤ë¥³¥á¥ó¥È
+# integer :: num = 0
+# end type MULTI_ARRAY
+#
+# contains
+#
+# subroutine hoge( in, & ! ·Ñ³¹ÔÃæ¤Î¥³¥á¥ó¥È¤Ï̵»ë¤µ¤ì¤Þ¤¹.
+# & out )
+# !
+# ! ¥µ¥Ö¥ë¡¼¥Á¥ó¤ä´Ø¿ô¤ËÂФ¹¤ë¥³¥á¥ó¥È¤Ï¤³¤³¤Ëµ½Ò¤·¤Þ¤¹
+# !
+# character(*),intent(in):: in ! °ú¿ô¤ËÂФ¹¤ë¥³¥á¥ó¥È
+# character(*),intent(out),allocatable,target :: in
+# ! ²¼¤Î¹Ô¤Ëµ½Ò¤¹¤ë
+# ! ¤³¤È¤â²Äǽ¤Ç¤¹.
+#
+# character(32) :: file ! NAMELIST ʸ¤ÎÊÑ¿ô¤È¤·¤Æ¹½Ê¸²òÀϤµ¤ì¤Þ¤¹
+# integer :: id
+#
+# namelist /varinfo_nml/ file, id
+# !
+# ! NAMELIST ʸ¤Ë´Ø¤¹¤ë¾ðÊó¤Ï¤³¤³¤Ëµ½Ò¤·¤Þ¤¹. ÊÑ¿ô¤Ë
+# ! ´Ø¤¹¤ë¾ðÊó¤Ï, ÊÑ¿ôÄêµÁÉôʬ¤ò»²¾È¤·¤Þ¤¹.
+# !
+#
+# ....
+#
+# end subroutine hoge
+#
+# integer function foo( in )
+# !
+# ! ¤³¤ÎÉôʬ¤Ï¥³¥á¥ó¥È¤È¤·¤Æ¼±Ê̤µ¤ì¤Þ¤¹.
+#
+# ! '!' ¤Î´Ö³Ö¤ò¶õ¤±¤ë¤È°Ê¹ß¤Ï¥³¥á¥ó¥È¤È¤·¤Æ°·¤ï¤ì¤Þ¤»¤ó.
+# ! ¤Ä¤Þ¤ê¤³¤Î 2 ¹Ô¤Ï¥³¥á¥ó¥È¤È¤·¤Æ°·¤ï¤ì¤Þ¤»¤ó.
+# !
+# integer, intent(in):: inA ! ¥³¥á¥ó¥È¤È¤·¤Æ¼±Ê̤µ¤ì¤Þ¤¹
+#
+# ! ¥³¥á¥ó¥È¤È¤·¤Æ¼±Ê̤µ¤ì¤Þ¤»¤ó.
+#
+# end function foo
+#
+# subroutine hide( in, &
+# & out ) !:nodoc:
+# !
+# ! ¾åµ¤Î¤è¤¦¤Ë, subroutine ʸ¤ÎËöÈø¤Ë
+# ! "!:nodoc:" ¤Èµ½Ò¤¹¤ë¤³¤È¤Ç, ¤½¤Î¥µ¥Ö¥ë¡¼¥Á¥ó
+# ! ¤Ï¥É¥¥å¥á¥ó¥È¤ËÈ¿±Ç¤µ¤ì¤Ê¤¯¤Ê¤ê¤Þ¤¹.
+# ! ¤³¤Î»ØÄê¤Ï, ¼ç¥×¥í¥°¥é¥à, ¥â¥¸¥å¡¼¥ë, ¥µ¥Ö¥ë¡¼¥Á¥ó,
+# ! ´Ø¿ô, ÊÑ¿ô, Äê¿ô, ¹½Â¤¥Ç¡¼¥¿·¿, ÍøÍѼÔÄêµÁ±é»»»Ò,
+# ! ÍøÍѼÔÄêµÁÂåÆþ, »²¾È¤¹¤ë¥â¥¸¥å¡¼¥ë¤Î¥ê¥¹¥È (use ʸ)
+# ! ¤ËÂФ·¤Æ͸ú¤Ç¤¹.
+# !
+#
+# ....
+#
+# end subroutine hide
+#
+# end module hogehoge
+#
+#=== Format of comment blocks
+#
+#Comment blocks should be written as follows.
+#Comment blocks are considered to be ended when the line without '!'
+#appears.
+#The indentation is not necessary.
+#
+# ! (Top of file)
+# !
+# ! Comment blocks for the files.
+# !
+# !--
+# ! The comment described in the part enclosed by
+# ! "!--" and "!++" is ignored.
+# !++
+# !
+# module hogehoge
+# !
+# ! Comment blocks for the modules (or the main programs).
+# !
+#
+# private
+#
+# logical :: a ! a private variable
+# real, public :: b ! a public variable
+# integer, parameter :: c = 0 ! a public constant
+#
+# public :: c
+# public :: MULTI_ARRAY
+# public :: hoge, foo
+#
+# type MULTI_ARRAY
+# !
+# ! Comment blocks for the derived types.
+# !
+# real, pointer :: var(:) =>null() ! Comments block for the variables.
+# integer :: num = 0
+# end type MULTI_ARRAY
+#
+# contains
+#
+# subroutine hoge( in, & ! Comment blocks between continuation lines are ignored.
+# & out )
+# !
+# ! Comment blocks for the subroutines or functions
+# !
+# character(*),intent(in):: in ! Comment blocks for the arguments.
+# character(*),intent(out),allocatable,target :: in
+# ! Comment blocks can be
+# ! written under Fortran statements.
+#
+# character(32) :: file ! This comment parsed as a variable in below NAMELIST.
+# integer :: id
+#
+# namelist /varinfo_nml/ file, id
+# !
+# ! Comment blocks for the NAMELIST statement.
+# ! Information about variables are described above.
+# !
+#
+# ....
+#
+# end subroutine hoge
+#
+# integer function foo( in )
+# !
+# ! This part is considered as comment block.
+#
+# ! Comment blocks under blank lines are ignored.
+# !
+# integer, intent(in):: inA ! This part is considered as comment block.
+#
+# ! This part is ignored.
+#
+# end function foo
+#
+# subroutine hide( in, &
+# & out ) !:nodoc:
+# !
+# ! If "!:nodoc:" is described at end-of-line in subroutine
+# ! statement as above, the subroutine is ignored.
+# ! This assignment can be used to main programs, modules,
+# ! subroutines, functions, variables, constants, derived types,
+# ! defined operators, defined assignments,
+# ! list of imported modules ("use" statement).
+# !
+#
+# ....
+#
+# end subroutine hide
+#
+# end module hogehoge
+#
+#--
+#
+#== º£¸å¤Î²þÎÉͽÄê
+#
+#* operator ¤ä assignment ¤Î¥¯¥í¥¹¥ê¥Õ¥¡¥ì¥ó¥¹¤¬È¾Ê¬¤¦¤Þ¤¯¤¤¤«¤Ê¤¤ÌäÂê
+# ¤Î²ò·è. (module_name#operator(.hoge.) ¤Ï¤¦¤Þ¤¯¤¤¤¯¤Î¤À¤¬, ¤½¤Î¥â¥¸¥å¡¼¥ë
+# Æâ¤Î¥³¥á¥ó¥È¤Ë¤ª¤¤¤Æ, operator(.hoge.) ¤È¤·¤Æ¤â¥ê¥ó¥¯¤Ë¤Ê¤é¤Ê¤¤).
+#
+# ¤³¤ÎÌäÂê¤Ë´Ø¤·¤Æ¤Ï generator/html_generator.html ¤ò
+# ²þÊѤ¹¤ëɬÍפ¢¤ê.
+#
+#* ¹½Â¤¥Ç¡¼¥¿·¿, ÊÑ¿ô, Äê¿ô¤Î»þ¤Ë¥á¥½¥Ã¥É¤Î²£¤Ë½ÐÎϤµ¤ì¤ë̵ÂÌ¤Ê "( )" ¤ò¾Ã¤¹.
+# html_generator ¤Ë¼ê¤òÆþ¤ì¤ì¤Ð°Õ³°¤È´Êñ¤Ë½èÍý¤Ç¤¤ë¤Ï¤º.
+# * ¶ñÂΰÆ1
+# * :nobracket ¤È¤¤¤¦¥·¥ó¥Ü¥ë¤ò»ØÄꤷ¤¿¾ì¹ç¤Ï´°Á´¤Ë¶õÇò¤Î¤ß½ÐÎϤ¹¤ë.
+#
+#++
+
require "rdoc/code_objects"
module RDoc
- # See rdoc/parsers/parse_f95.rb
-
class Token
NO_TEXT = "??".freeze
-
+
def initialize(line_no, char_no)
@line_no = line_no
@char_no = char_no
@@ -26,84 +362,1157 @@
end
+ # See rdoc/parsers/parse_f95.rb
+
class Fortran95parser
extend ParserFactory
- parse_files_matching(/\.(f9(0|5)|F)$/)
-
+ parse_files_matching(/\.((f|F)9(0|5)|F)$/)
+
+ @@external_aliases = []
+ @@public_methods = []
+
+ # "false":: Comments are below source code
+ # "true" :: Comments are upper source code
+ COMMENTS_ARE_UPPER = false
+
+ # Internal alias message
+ INTERNAL_ALIAS_MES = "Alias for"
+
+ # External alias message
+ EXTERNAL_ALIAS_MES = "Original external subprogram is"
+
+ # Provided modules message
+ PROVIDED_MODULES_MES = "This file provides following module"
+
+ # Repository of NAMELIST statements
+ NAMELIST_REPOSITORY_NAME = "NAMELIST"
+
# prepare to parse a Fortran 95 file
def initialize(top_level, file_name, body, options, stats)
@body = body
@stats = stats
+ @file_name = file_name
@options = options
@top_level = top_level
@progress = $stderr unless options.quiet
end
-
+
# devine code constructs
def scan
- # modules and programs
- if @body =~ /^(module|program)\s+(\w+)/i
- progress "m"
- f9x_module = @top_level.add_module NormalClass, $2
- f9x_module.record_location @top_level
- first_comment, second_comment = $`.gsub(/^!\s?/,"").split "\n\s*\n"
- if second_comment
- @top_level.comment = first_comment if first_comment
- f9x_module.comment = second_comment
- else
- f9x_module.comment = first_comment if first_comment
- end
- end
-
- # use modules
- remaining_code = @body
- while remaining_code =~ /^\s*use\s+(\w+)/i
- remaining_code = $~.post_match
- progress "."
- f9x_module.add_include Include.new($1, "") if f9x_module
- end
-
- # subroutines
- remaining_code = @body
- while remaining_code =~ /^\s*subroutine\s+(\w+)\s*\((.*?)\)/im
- remaining_code = $~.post_match
- subroutine = AnyMethod.new("Text", $1)
- subroutine.singleton = false
-
- prematchText = $~.pre_match
- params = $2
- params.gsub!(/&/,'')
- subroutine.params = params
- comment = find_comments prematchText
- subroutine.comment = comment if comment
-
- subroutine.start_collecting_tokens
- remaining_code =~ /^\s*end\s+subroutine/i
- code = "subroutine #{subroutine.name} (#{subroutine.params})\n"
- code += $~.pre_match
- code += "\nend subroutine\n"
- subroutine.add_token Token.new(1,1).set_text(code)
-
- progress "s"
- f9x_module.add_method subroutine if f9x_module
- end
+ # remove private comment
+ remaining_code = remove_private_comments(@body)
+
+ # continuation lines are united to one line
+ remaining_code = united_to_one_line(remaining_code)
+
+ # semicolons are replaced to line feed
+ remaining_code = semicolon_to_linefeed(remaining_code)
+
+ # collect comment for file entity
+ whole_comment, remaining_code = collect_first_comment(remaining_code)
+ @top_level.comment = whole_comment
+
+ # String "remaining_code" is converted to Array "remaining_lines"
+ remaining_lines = remaining_code.split("\n")
+
+ # "module" or "program" parts are parsed (new)
+ #
+ level_depth = 0
+ block_searching_flag = nil
+ block_searching_lines = []
+ pre_comment = []
+ module_program_trailing = ""
+ module_program_name = ""
+ other_block_level_depth = 0
+ other_block_searching_flag = nil
+ remaining_lines.collect!{|line|
+ if !block_searching_flag && !other_block_searching_flag
+ if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i
+ block_searching_flag = :module
+ block_searching_lines << line
+ module_program_name = $1
+ module_program_trailing = find_comments($2)
+ next false
+ elsif line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
+ line =~ /^\s*?\w/ && !block_start?(line)
+ block_searching_flag = :program
+ block_searching_lines << line
+ module_program_name = $1 || ""
+ module_program_trailing = find_comments($2)
+ next false
+
+ elsif block_start?(line)
+ other_block_searching_flag = true
+ next line
+
+ elsif line =~ /^\s*?!\s?(.*)/
+ pre_comment << line
+ next line
+ else
+ pre_comment = []
+ next line
+ end
+ elsif other_block_searching_flag
+ other_block_level_depth += 1 if block_start?(line)
+ other_block_level_depth -= 1 if block_end?(line)
+ if other_block_level_depth < 0
+ other_block_level_depth = 0
+ other_block_searching_flag = nil
+ end
+ next line
+ end
+
+ block_searching_lines << line
+ level_depth += 1 if block_start?(line)
+ level_depth -= 1 if block_end?(line)
+ if level_depth >= 0
+ next false
+ end
+
+ # "module_program_code" is formatted.
+ # ":nodoc:" flag is checked.
+ #
+ module_program_code = block_searching_lines.join("\n")
+ module_program_code = remove_empty_head_lines(module_program_code)
+ if module_program_trailing =~ /^:nodoc:/
+ # next loop to search next block
+ level_depth = 0
+ block_searching_flag = false
+ block_searching_lines = []
+ pre_comment = []
+ next false
+ end
+
+ # NormalClass is created, and added to @top_level
+ #
+ if block_searching_flag == :module
+ module_name = module_program_name
+ module_code = module_program_code
+ module_trailing = module_program_trailing
+ progress "m"
+ @stats.num_modules += 1
+ f9x_module = @top_level.add_module NormalClass, module_name
+ f9x_module.record_location @top_level
+
+ #
+ # Add provided modules information to @top_level comment
+ #
+ provided_modules = []
+ provided_mes_line_num = nil
+ top_level_comment_lines = []
+ line_num = 0
+ @top_level.comment.split("\n").each{|line|
+ top_level_comment_lines << line
+ line_num += 1
+ next if line.empty?
+ if !provided_mes_line_num && /^\s?#{PROVIDED_MODULES_MES}/ =~ line
+ provided_mes_line_num = line_num
+ next
+ end
+ if provided_mes_line_num
+ if /^\s?\*\s+(\w+)<\/b>/ =~ line
+ provided_modules << $1
+ else
+ provided_mes_line_num = nil
+ end
+ end
+ }
+ line_num = 0
+ if provided_mes_line_num
+ top_level_comment_lines.collect!{ |line|
+ line_num += 1
+ if line_num < provided_mes_line_num
+ line
+ else
+ nil
+ end
+ }
+ top_level_comment_lines.delete_if{|line| !line }
+ end
+ top_level_comment_lines << "\n" + PROVIDED_MODULES_MES + "."
+ if provided_mes_line_num
+ top_level_comment_lines[-1].sub!(/\.$/, '')
+ top_level_comment_lines[-1] << "s."
+ end
+ provided_modules.each{ |mod|
+ top_level_comment_lines << "* " + mod + ""
+ }
+ top_level_comment_lines << "* " + module_name + ""
+ @top_level.comment = top_level_comment_lines.join("\n")
+
+ #
+ # Information about the module is parsed
+ #
+ f9x_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) +
+ "\n" + module_trailing : module_trailing + "\n" +
+ find_comments(module_code.sub(/^.*$\n/i, ''))
+ f9x_module.comment = f9x_comment
+ parse_program_or_module(f9x_module, module_code)
+
+ TopLevel.all_files.each do |name, toplevel|
+ if toplevel.include_includes?(module_name, @options.ignore_case)
+ if !toplevel.include_requires?(@file_name, @options.ignore_case)
+ toplevel.add_require(Require.new(@file_name, ""))
+ end
+ end
+ toplevel.each_classmodule{|m|
+ if m.include_includes?(module_name, @options.ignore_case)
+ if !m.include_requires?(@file_name, @options.ignore_case)
+ m.add_require(Require.new(@file_name, ""))
+ end
+ end
+ }
+ end
+
+ namelist_comment =
+ find_namelists(f9x_module, before_contains(module_code))
+ f9x_module.comment << namelist_comment if namelist_comment
+
+ elsif block_searching_flag == :program
+ program_name = module_program_name
+ program_name = "main_program" if program_name.empty?
+ program_code = module_program_code
+ program_trailing = module_program_trailing
+ program_comment = COMMENTS_ARE_UPPER ? find_comments(pre_comment.join("\n")) +
+ "\n" + program_trailing : program_trailing + "\n" +
+ find_comments(program_code.sub(/^.*$\n/i, ''))
+
+ progress "p"
+ @stats.num_methods += 1
+ f9x_mainprogram = AnyMethod.new("main_program", program_name)
+ f9x_mainprogram.singleton = false
+ f9x_mainprogram.comment = " Main Program :\n"
+ f9x_mainprogram.comment << program_comment
+ f9x_mainprogram.params = ""
+
+ # For output source code
+ f9x_mainprogram.start_collecting_tokens
+ f9x_mainprogram.add_token Token.new(1,1).set_text(program_code)
+
+ @top_level.add_method f9x_mainprogram
+ parse_program_or_module(@top_level, program_code, :private)
+
+ namelist_comment = find_namelists(f9x_mainprogram, program_code)
+ f9x_mainprogram.comment << namelist_comment if namelist_comment
+ end
+
+ # next loop to search next block
+ level_depth = 0
+ block_searching_flag = false
+ block_searching_lines = []
+ pre_comment = []
+ next false
+ }
+
+ remaining_lines.delete_if{ |line|
+ line == false
+ }
+
+ # External subprograms and functions are parsed
+ #
+ # ñ°ì¤Î¥Õ¥¡¥¤¥ëÆâ¤Ë¤ª¤¤¤Æ program ¤ä module ¤Ë³ÊǼ¤µ¤ì¤Ê¤¤,
+ # ³°Éô¥µ¥Ö¥ë¡¼¥Á¥ó, ³°Éô´Ø¿ôÉôʬ¤Î²òÀÏ.
+ #
+ parse_program_or_module(@top_level, remaining_lines.join("\n"),
+ :public, true)
@top_level
+ end # End of scan
+
+ private
+
+ def parse_program_or_module(container, code,
+ visibility=:public, external=nil)
+ return unless container
+ return unless code
+ remaining_lines = code.split("\n")
+ remaining_code = "#{code}"
+
+ #
+ # Parse variables before "contains" in module
+ #
+ # namelist ÊÑ¿ô¤ÎÄêµÁ¤Ë»È¤ï¤ì¤¿¤ê, ¤³¤ì¼«ÂΤ¬Äê¿ô, ÊÑ¿ô
+ # Ä󶡤µ¤ì¤ë¤Î¤ËÍøÍѤµ¤ì¤ë. (ÊÑ¿ô¤äÄê¿ô¤È¤·¤ÆÍøÍѤµ¤ì¤ë¾ì¹ç,
+ # ¤³¤ì¤â¥á¥½¥Ã¥É¤È¤·¤ÆÄ󶡤¹¤ë.
+ #
+ before_contains_code = before_contains(remaining_code)
+
+ #
+ # Parse global "use"
+ #
+ use_check_code = "#{before_contains_code}"
+ cascaded_modules_list = []
+ while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
+ use_check_code = $~.pre_match
+ use_check_code << $~.post_match
+ used_mod_name = $1.strip.chomp
+ used_list = $2 || ""
+ used_trailing = $3 || ""
+ next if used_trailing =~ /!:nodoc:/
+ if !container.include_includes?(used_mod_name, @options.ignore_case)
+ progress "."
+ container.add_include Include.new(used_mod_name, "")
+ end
+ if ! (used_list =~ /\,\s*?only\s*?:/i )
+ cascaded_modules_list << "\#" + used_mod_name
+ end
+ end
+
+ #
+ # Parse public and private, and store information.
+ # This information is used when "add_method" and
+ # "set_visibility_for" are called.
+ #
+ visibility_default, visibility_info =
+ parse_visibility(remaining_lines.join("\n"), visibility, container)
+ @@public_methods.concat visibility_info
+ if visibility_default == :public
+ if !cascaded_modules_list.empty?
+ cascaded_modules =
+ Attr.new("Cascaded Modules",
+ "Imported modules all of whose components are published again",
+ "",
+ cascaded_modules_list.join(", "))
+ container.add_attribute(cascaded_modules)
+ end
+ end
+
+ #
+ # Check rename elements
+ #
+ use_check_code = "#{before_contains_code}"
+ while use_check_code =~ /^\s*?use\s+(\w+)\s*?\,(.+)$/i
+ use_check_code = $~.pre_match
+ use_check_code << $~.post_match
+ used_mod_name = $1.strip.chomp
+ used_elements = $2.sub(/\s*?only\s*?:\s*?/i, '')
+ used_elements.split(",").each{ |used|
+ if /\s*?(\w+)\s*?=>\s*?(\w+)\s*?/ =~ used
+ local = $1
+ org = $2
+ @@public_methods.collect!{ |pub_meth|
+ if local == pub_meth["name"] ||
+ local.upcase == pub_meth["name"].upcase &&
+ @options.ignore_case
+ pub_meth["name"] = org
+ pub_meth["local_name"] = local
+ end
+ pub_meth
+ }
+ end
+ }
+ end
+
+ #
+ # Parse private "use"
+ #
+ use_check_code = remaining_lines.join("\n")
+ while use_check_code =~ /^\s*?use\s+(\w+)(.*?)(!.*?)?$/i
+ use_check_code = $~.pre_match
+ use_check_code << $~.post_match
+ used_mod_name = $1.strip.chomp
+ used_trailing = $3 || ""
+ next if used_trailing =~ /!:nodoc:/
+ if !container.include_includes?(used_mod_name, @options.ignore_case)
+ progress "."
+ container.add_include Include.new(used_mod_name, "")
+ end
+ end
+
+ container.each_includes{ |inc|
+ TopLevel.all_files.each do |name, toplevel|
+ indicated_mod = toplevel.find_symbol(inc.name,
+ nil, @options.ignore_case)
+ if indicated_mod
+ indicated_name = indicated_mod.parent.file_relative_name
+ if !container.include_requires?(indicated_name, @options.ignore_case)
+ container.add_require(Require.new(indicated_name, ""))
+ end
+ break
+ end
+ end
+ }
+
+ #
+ # Parse derived types definitions
+ #
+ derived_types_comment = ""
+ remaining_code = remaining_lines.join("\n")
+ while remaining_code =~ /^\s*?
+ type[\s\,]+(public|private)?\s*?(::)?\s*?
+ (\w+)\s*?(!.*?)?$
+ (.*?)
+ ^\s*?end\s+type.*?$
+ /imx
+ remaining_code = $~.pre_match
+ remaining_code << $~.post_match
+ typename = $3.chomp.strip
+ type_elements = $5 || ""
+ type_code = remove_empty_head_lines($&)
+ type_trailing = find_comments($4)
+ next if type_trailing =~ /^:nodoc:/
+ type_visibility = $1
+ type_comment = COMMENTS_ARE_UPPER ?
+ find_comments($~.pre_match) + "\n" + type_trailing :
+ type_trailing + "\n" + find_comments(type_code.sub(/^.*$\n/i, ''))
+ type_element_visibility_public = true
+ type_code.split("\n").each{ |line|
+ if /^\s*?private\s*?$/ =~ line
+ type_element_visibility_public = nil
+ break
+ end
+ } if type_code
+
+ args_comment = ""
+ type_args_info = nil
+
+ if @options.show_all
+ args_comment = find_arguments(nil, type_code, true)
+ else
+ type_public_args_list = []
+ type_args_info = definition_info(type_code)
+ type_args_info.each{ |arg|
+ arg_is_public = type_element_visibility_public
+ arg_is_public = true if arg.include_attr?("public")
+ arg_is_public = nil if arg.include_attr?("private")
+ type_public_args_list << arg.varname if arg_is_public
+ }
+ args_comment = find_arguments(type_public_args_list, type_code)
+ end
+
+ type = AnyMethod.new("type #{typename}", typename)
+ type.singleton = false
+ type.params = ""
+ type.comment = " Derived Type :: \n"
+ type.comment << args_comment if args_comment
+ type.comment << type_comment if type_comment
+ progress "t"
+ @stats.num_methods += 1
+ container.add_method type
+
+ set_visibility(container, typename, visibility_default, @@public_methods)
+
+ if type_visibility
+ type_visibility.gsub!(/\s/,'')
+ type_visibility.gsub!(/\,/,'')
+ type_visibility.gsub!(/:/,'')
+ type_visibility.downcase!
+ if type_visibility == "public"
+ container.set_visibility_for([typename], :public)
+ elsif type_visibility == "private"
+ container.set_visibility_for([typename], :private)
+ end
+ end
+
+ check_public_methods(type, container.name)
+
+ if @options.show_all
+ derived_types_comment << ", " unless derived_types_comment.empty?
+ derived_types_comment << typename
+ else
+ if type.visibility == :public
+ derived_types_comment << ", " unless derived_types_comment.empty?
+ derived_types_comment << typename
+ end
+ end
+
+ end
+
+ if !derived_types_comment.empty?
+ derived_types_table =
+ Attr.new("Derived Types", "Derived_Types", "",
+ derived_types_comment)
+ container.add_attribute(derived_types_table)
+ end
+
+ #
+ # move interface scope
+ #
+ interface_code = ""
+ while remaining_code =~ /^\s*?
+ interface(
+ \s+\w+ |
+ \s+operator\s*?\(.*?\) |
+ \s+assignment\s*?\(\s*?=\s*?\)
+ )?\s*?$
+ (.*?)
+ ^\s*?end\s+interface.*?$
+ /imx
+ interface_code << remove_empty_head_lines($&) + "\n"
+ remaining_code = $~.pre_match
+ remaining_code << $~.post_match
+ end
+
+ #
+ # Parse global constants or variables in modules
+ #
+ const_var_defs = definition_info(before_contains_code)
+ const_var_defs.each{|defitem|
+ next if defitem.nodoc
+ const_or_var_type = "Variable"
+ const_or_var_progress = "v"
+ if defitem.include_attr?("parameter")
+ const_or_var_type = "Constant"
+ const_or_var_progress = "c"
+ end
+ const_or_var = AnyMethod.new(const_or_var_type, defitem.varname)
+ const_or_var.singleton = false
+ const_or_var.params = ""
+ self_comment = find_arguments([defitem.varname], before_contains_code)
+ const_or_var.comment = "" + const_or_var_type + " :: \n"
+ const_or_var.comment << self_comment if self_comment
+ progress const_or_var_progress
+ @stats.num_methods += 1
+ container.add_method const_or_var
+
+ set_visibility(container, defitem.varname, visibility_default, @@public_methods)
+
+ if defitem.include_attr?("public")
+ container.set_visibility_for([defitem.varname], :public)
+ elsif defitem.include_attr?("private")
+ container.set_visibility_for([defitem.varname], :private)
+ end
+
+ check_public_methods(const_or_var, container.name)
+
+ } if const_var_defs
+
+ remaining_lines = remaining_code.split("\n")
+
+ # "subroutine" or "function" parts are parsed (new)
+ #
+ level_depth = 0
+ block_searching_flag = nil
+ block_searching_lines = []
+ pre_comment = []
+ procedure_trailing = ""
+ procedure_name = ""
+ procedure_params = ""
+ procedure_prefix = ""
+ procedure_result_arg = ""
+ procedure_type = ""
+ contains_lines = []
+ contains_flag = nil
+ remaining_lines.collect!{|line|
+ if !block_searching_flag
+ # subroutine
+ if line =~ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+ /ix
+ block_searching_flag = :subroutine
+ block_searching_lines << line
+
+ procedure_name = $2.chomp.strip
+ procedure_params = $3 || ""
+ procedure_prefix = $1 || ""
+ procedure_trailing = $4 || "!"
+ next false
+
+ # function
+ elsif line =~ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ (
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | type\s*?\([\w\s]+?\)\s+
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | double\s+precision\s+
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ )?
+ function\s+(\w+)\s*?
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+ /ix
+ block_searching_flag = :function
+ block_searching_lines << line
+
+ procedure_prefix = $1 || ""
+ procedure_type = $2 ? $2.chomp.strip : nil
+ procedure_name = $8.chomp.strip
+ procedure_params = $9 || ""
+ procedure_result_arg = $11 ? $11.chomp.strip : procedure_name
+ procedure_trailing = $12 || "!"
+ next false
+ elsif line =~ /^\s*?!\s?(.*)/
+ pre_comment << line
+ next line
+ else
+ pre_comment = []
+ next line
+ end
+ end
+ contains_flag = true if line =~ /^\s*?contains\s*?(!.*?)?$/
+ block_searching_lines << line
+ contains_lines << line if contains_flag
+
+ level_depth += 1 if block_start?(line)
+ level_depth -= 1 if block_end?(line)
+ if level_depth >= 0
+ next false
+ end
+
+ # "procedure_code" is formatted.
+ # ":nodoc:" flag is checked.
+ #
+ procedure_code = block_searching_lines.join("\n")
+ procedure_code = remove_empty_head_lines(procedure_code)
+ if procedure_trailing =~ /^!:nodoc:/
+ # next loop to search next block
+ level_depth = 0
+ block_searching_flag = nil
+ block_searching_lines = []
+ pre_comment = []
+ procedure_trailing = ""
+ procedure_name = ""
+ procedure_params = ""
+ procedure_prefix = ""
+ procedure_result_arg = ""
+ procedure_type = ""
+ contains_lines = []
+ contains_flag = nil
+ next false
+ end
+
+ # AnyMethod is created, and added to container
+ #
+ subroutine_function = nil
+ if block_searching_flag == :subroutine
+ subroutine_prefix = procedure_prefix
+ subroutine_name = procedure_name
+ subroutine_params = procedure_params
+ subroutine_trailing = procedure_trailing
+ subroutine_code = procedure_code
+
+ subroutine_comment = COMMENTS_ARE_UPPER ?
+ pre_comment.join("\n") + "\n" + subroutine_trailing :
+ subroutine_trailing + "\n" + subroutine_code.sub(/^.*$\n/i, '')
+ subroutine = AnyMethod.new("subroutine", subroutine_name)
+ parse_subprogram(subroutine, subroutine_params,
+ subroutine_comment, subroutine_code,
+ before_contains_code, nil, subroutine_prefix)
+ progress "s"
+ @stats.num_methods += 1
+ container.add_method subroutine
+ subroutine_function = subroutine
+
+ namelist_comment =
+ find_namelists(subroutine, subroutine_code, before_contains_code)
+ subroutine.comment << namelist_comment if namelist_comment
+
+ elsif block_searching_flag == :function
+ function_prefix = procedure_prefix
+ function_type = procedure_type
+ function_name = procedure_name
+ function_params_org = procedure_params
+ function_result_arg = procedure_result_arg
+ function_trailing = procedure_trailing
+ function_code_org = procedure_code
+
+ function_comment = COMMENTS_ARE_UPPER ?
+ pre_comment.join("\n") + "\n" + function_trailing :
+ function_trailing + "\n " + function_code_org.sub(/^.*$\n/i, '')
+
+ function_code = "#{function_code_org}"
+ if function_type
+ function_code << "\n" + function_type + " :: " + function_result_arg
+ end
+
+ function_params =
+ function_params_org.sub(/^\(/, "\(#{function_result_arg}, ")
+
+ function = AnyMethod.new("function", function_name)
+ parse_subprogram(function, function_params,
+ function_comment, function_code,
+ before_contains_code, true, function_prefix)
+
+ # Specific modification due to function
+ function.params.sub!(/\(\s*?#{function_result_arg}\s*?,\s*?/, "\( ")
+ function.params << " result(" + function_result_arg + ")"
+ function.start_collecting_tokens
+ function.add_token Token.new(1,1).set_text(function_code_org)
+
+ progress "f"
+ @stats.num_methods += 1
+ container.add_method function
+ subroutine_function = function
+
+ namelist_comment =
+ find_namelists(function, function_code, before_contains_code)
+ function.comment << namelist_comment if namelist_comment
+
+ end
+
+ # The visibility of procedure is specified
+ #
+ set_visibility(container, procedure_name,
+ visibility_default, @@public_methods)
+
+ # The alias for this procedure from external modules
+ #
+ check_external_aliases(procedure_name,
+ subroutine_function.params,
+ subroutine_function.comment, subroutine_function) if external
+ check_public_methods(subroutine_function, container.name)
+
+
+ # contains_lines are parsed as private procedures
+ if contains_flag
+ parse_program_or_module(container,
+ contains_lines.join("\n"), :private)
+ end
+
+ # next loop to search next block
+ level_depth = 0
+ block_searching_flag = nil
+ block_searching_lines = []
+ pre_comment = []
+ procedure_trailing = ""
+ procedure_name = ""
+ procedure_params = ""
+ procedure_prefix = ""
+ procedure_result_arg = ""
+ contains_lines = []
+ contains_flag = nil
+ next false
+ } # End of remaining_lines.collect!{|line|
+
+ # Array remains_lines is converted to String remains_code again
+ #
+ remaining_code = remaining_lines.join("\n")
+
+ #
+ # Parse interface
+ #
+ interface_scope = false
+ generic_name = ""
+ interface_code.split("\n").each{ |line|
+ if /^\s*?
+ interface(
+ \s+\w+|
+ \s+operator\s*?\(.*?\)|
+ \s+assignment\s*?\(\s*?=\s*?\)
+ )?
+ \s*?(!.*?)?$
+ /ix =~ line
+ generic_name = $1 ? $1.strip.chomp : nil
+ interface_trailing = $2 || "!"
+ interface_scope = true
+ interface_scope = false if interface_trailing =~ /!:nodoc:/
+# if generic_name =~ /operator\s*?\((.*?)\)/i
+# operator_name = $1
+# if operator_name && !operator_name.empty?
+# generic_name = "#{operator_name}"
+# end
+# end
+# if generic_name =~ /assignment\s*?\((.*?)\)/i
+# assignment_name = $1
+# if assignment_name && !assignment_name.empty?
+# generic_name = "#{assignment_name}"
+# end
+# end
+ end
+ if /^\s*?end\s+interface/i =~ line
+ interface_scope = false
+ generic_name = nil
+ end
+ # internal alias
+ if interface_scope && /^\s*?module\s+procedure\s+(.*?)(!.*?)?$/i =~ line
+ procedures = $1.strip.chomp
+ procedures_trailing = $2 || "!"
+ next if procedures_trailing =~ /!:nodoc:/
+ procedures.split(",").each{ |proc|
+ proc.strip!
+ proc.chomp!
+ next if generic_name == proc || !generic_name
+ old_meth = container.find_symbol(proc, nil, @options.ignore_case)
+ next if !old_meth
+ nolink = old_meth.visibility == :private ? true : nil
+ nolink = nil if @options.show_all
+ new_meth =
+ initialize_external_method(generic_name, proc,
+ old_meth.params, nil,
+ old_meth.comment,
+ old_meth.clone.token_stream[0].text,
+ true, nolink)
+ new_meth.singleton = old_meth.singleton
+
+ progress "i"
+ @stats.num_methods += 1
+ container.add_method new_meth
+
+ set_visibility(container, generic_name, visibility_default, @@public_methods)
+
+ check_public_methods(new_meth, container.name)
+
+ }
+ end
+
+ # external aliases
+ if interface_scope
+ # subroutine
+ proc = nil
+ params = nil
+ procedures_trailing = nil
+ if line =~ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+ /ix
+ proc = $2.chomp.strip
+ generic_name = proc unless generic_name
+ params = $3 || ""
+ procedures_trailing = $4 || "!"
+
+ # function
+ elsif line =~ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ (
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | type\s*?\([\w\s]+?\)\s+
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | double\s+precision\s+
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ )?
+ function\s+(\w+)\s*?
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+ /ix
+ proc = $8.chomp.strip
+ generic_name = proc unless generic_name
+ params = $9 || ""
+ procedures_trailing = $12 || "!"
+ else
+ next
+ end
+ next if procedures_trailing =~ /!:nodoc:/
+ indicated_method = nil
+ indicated_file = nil
+ TopLevel.all_files.each do |name, toplevel|
+ indicated_method = toplevel.find_local_symbol(proc, @options.ignore_case)
+ indicated_file = name
+ break if indicated_method
+ end
+
+ if indicated_method
+ external_method =
+ initialize_external_method(generic_name, proc,
+ indicated_method.params,
+ indicated_file,
+ indicated_method.comment)
+
+ progress "e"
+ @stats.num_methods += 1
+ container.add_method external_method
+ set_visibility(container, generic_name, visibility_default, @@public_methods)
+ if !container.include_requires?(indicated_file, @options.ignore_case)
+ container.add_require(Require.new(indicated_file, ""))
+ end
+ check_public_methods(external_method, container.name)
+
+ else
+ @@external_aliases << {
+ "new_name" => generic_name,
+ "old_name" => proc,
+ "file_or_module" => container,
+ "visibility" => find_visibility(container, generic_name, @@public_methods) || visibility_default
+ }
+ end
+ end
+
+ } if interface_code # End of interface_code.split("\n").each ...
+
+ #
+ # Already imported methods are removed from @@public_methods.
+ # Remainders are assumed to be imported from other modules.
+ #
+ # ´û¤Ë»²¾ÈºÑ¤ß¤Î¥á¥½¥Ã¥É¤Ï @@public_methods ¤«¤é¼è¤ê½ü¤¯.
+ # »Ä¤ê¤Ï³°Éô¥â¥¸¥å¡¼¥ë¤«¤é¤Î»²¾È¤È²¾Äꤹ¤ë.
+ #
+ @@public_methods.delete_if{ |method| method["entity_is_discovered"]}
+
+ @@public_methods.each{ |pub_meth|
+ next unless pub_meth["file_or_module"].name == container.name
+ pub_meth["used_modules"].each{ |used_mod|
+ TopLevel.all_classes_and_modules.each{ |modules|
+ if modules.name == used_mod ||
+ modules.name.upcase == used_mod.upcase &&
+ @options.ignore_case
+ modules.method_list.each{ |meth|
+ if meth.name == pub_meth["name"] ||
+ meth.name.upcase == pub_meth["name"].upcase &&
+ @options.ignore_case
+ new_meth = initialize_public_method(meth,
+ modules.name)
+ if pub_meth["local_name"]
+ new_meth.name = pub_meth["local_name"]
+ end
+ progress "e"
+ @stats.num_methods += 1
+ container.add_method new_meth
+ end
+ }
+ end
+ }
+ }
+ }
+
+ container
+ end # End of parse_program_or_module
+
+ #
+ # Parse arguments, comment, code of subroutine and function.
+ # Return AnyMethod object.
+ #
+ def parse_subprogram(subprogram, params, comment, code,
+ before_contains=nil, function=nil, prefix=nil)
+ subprogram.singleton = false
+ prefix = "" if !prefix
+ arguments = params.sub(/\(/, "").sub(/\)/, "").split(",") if params
+ args_comment, params_opt =
+ find_arguments(arguments, code.sub(/^s*?contains\s*?(!.*?)?$.*/im, ""),
+ nil, nil, true)
+ params_opt = "( " + params_opt + " ) " if params_opt
+ subprogram.params = params_opt || ""
+
+ block_comment = find_comments comment
+ if function
+ subprogram.comment = " Function :: #{prefix}\n"
+ else
+ subprogram.comment = " Subroutine :: #{prefix}\n"
+ end
+ subprogram.comment << args_comment if args_comment
+ subprogram.comment << block_comment if block_comment
+
+ # For output source code
+ subprogram.start_collecting_tokens
+ subprogram.add_token Token.new(1,1).set_text(code)
+
+ subprogram
+ end
+
+ #
+ # Return lines before "contains" statement in modules.
+ # "interface", "type" statements are removed.
+ #
+ def before_contains(code)
+ level_depth = 0
+ before_contains_lines = []
+ before_contains_code = nil
+ before_contains_flag = nil
+ code.split("\n").each{ |line|
+ if !before_contains_flag
+ if line =~ /^\s*?module\s+\w+\s*?(!.*?)?$/i
+ before_contains_flag = true
+ end
+ else
+ break if line =~ /^\s*?contains\s*?(!.*?)?$/i
+ level_depth += 1 if block_start?(line)
+ level_depth -= 1 if block_end?(line)
+ break if level_depth < 0
+ before_contains_lines << line
+ end
+
+ }
+ before_contains_code = before_contains_lines.join("\n")
+ if before_contains_code
+ before_contains_code.gsub!(/^\s*?interface\s+.*?\s+end\s+interface.*?$/im, "")
+ before_contains_code.gsub!(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
+ end
+ before_contains_code
end
+ #
+ # Collect comment for file entity
+ #
+ def collect_first_comment(body)
+ comment = ""
+ not_comment = ""
+ comment_start = false
+ comment_end = false
+ body.split("\n").each{ |line|
+ if comment_end
+ not_comment << line
+ not_comment << "\n"
+ elsif /^\s*?!\s?(.*)$/i =~ line
+ comment_start = true
+ comment << $1
+ comment << "\n"
+ elsif /^\s*?$/i =~ line
+ comment_end = true if comment_start && COMMENTS_ARE_UPPER
+ else
+ comment_end = true
+ not_comment << line
+ not_comment << "\n"
+ end
+ }
+ return comment, not_comment
+ end
+
+
+ # Return comments of definitions of arguments
+ #
+ # If "all" argument is true, information of all arguments are returned.
+ # If "modified_params" is true, list of arguments are decorated,
+ # for exameple, optional arguments are parenthetic as "[arg]".
+ #
+ def find_arguments(args, text, all=nil, indent=nil, modified_params=nil)
+ return unless args || all
+ indent = "" unless indent
+ args = ["all"] if all
+ params = "" if modified_params
+ comma = ""
+ return unless text
+ args_rdocforms = "\n"
+ remaining_lines = "#{text}"
+ definitions = definition_info(remaining_lines)
+ args.each{ |arg|
+ arg.strip!
+ arg.chomp!
+ definitions.each { |defitem|
+ if arg == defitem.varname.strip.chomp || all
+ args_rdocforms << <<-"EOF"
+
+#{indent}#{defitem.varname.chomp.strip}#{defitem.arraysuffix} #{defitem.inivalue} ::
+#{indent} #{defitem.types.chomp.strip}
+EOF
+ if !defitem.comment.chomp.strip.empty?
+ comment = ""
+ defitem.comment.split("\n").each{ |line|
+ comment << " " + line + "\n"
+ }
+ args_rdocforms << <<-"EOF"
+
+#{indent} ::
+#{indent}
+#{indent} #{comment.chomp.strip}
+EOF
+ end
+
+ if modified_params
+ if defitem.include_attr?("optional")
+ params << "#{comma}[#{arg}]"
+ else
+ params << "#{comma}#{arg}"
+ end
+ comma = ", "
+ end
+ end
+ }
+ }
+ if modified_params
+ return args_rdocforms, params
+ else
+ return args_rdocforms
+ end
+ end
+
+ #
+ # Add namelist information to Repository (dummy module of each
+ # @top_level) of NAMELIST statements.
+ # And return comments about namelist group names
+ #
+ def find_namelists(container, text, before_contains=nil)
+ return nil if !text
+ top_level = find_toplevel(container)
+
+ if text =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)(!.*?)?$/i
+ if top_level.include_includes?(NAMELIST_REPOSITORY_NAME)
+ namelist_module =
+ top_level.find_module_named(NAMELIST_REPOSITORY_NAME)
+ else
+ namelist_module =
+ top_level.add_module NormalClass, NAMELIST_REPOSITORY_NAME
+ namelist_module.record_location top_level
+ namelist_module.comment = <<-"EOF"
+This is not a module but a repository of NAMELIST group names declared
+in all Fortran 90/95 files
+EOF
+ end
+ else
+ return ""
+ end
+
+ nml_group_name_lists = []
+ lines = "#{text}"
+ before_contains = "" if !before_contains
+ while lines =~ /^\s*?namelist\s+\/\s*?(\w+)\s*?\/([\s\w\,]+)(!.*?)?$/i
+ lines = $~.post_match
+ pre_match = $~.pre_match ; post_match = $~.post_match
+ nml_group_name = $1
+ nml_vars_list = $2.split(",")
+ nml_comment = COMMENTS_ARE_UPPER ?
+ find_comments(pre_match.sub(/\n$/, '')) :
+ find_comments(post_match.sub(/^\n/, ''))
+ if lines.split("\n")[0] =~ /^\//i
+ lines = "namelist " + lines
+ end
+
+ nml_meth = AnyMethod.new("NAMELIST", nml_group_name)
+ nml_meth.singleton = false
+ nml_meth.params = "( " + nml_vars_list.join(", ") + " )"
+ nml_meth.comment = " NAMELIST :: \n"
+ nml_meth.comment << find_arguments(nml_vars_list, "#{text}" + "\n" + before_contains)
+ nml_meth.comment << "\n" + nml_comment if nml_comment
+ if container.parent.parent
+ parent_object = container.parent.name
+ else
+ parent_object = container.parent.file_relative_name
+ end
+ nml_meth.comment << "\n\nThis namelist group name is input/output in "
+ nml_meth.comment << parent_object + "#" + container.name
+
+ progress "n"
+ @stats.num_methods += 1
+ namelist_module.add_method nml_meth
+
+ nml_group_name_lists << NAMELIST_REPOSITORY_NAME + "#" + nml_group_name
+ end
+
+ if !nml_group_name_lists.empty?
+ comments_in_procedures = "\n\nThis procedure input/output "
+ comments_in_procedures << nml_group_name_lists.join(", ") + " . "
+ else
+ comments_in_procedures = ""
+ end
+
+ comments_in_procedures
+ end
+
+ #
+ # Return toplevel class of container
+ #
+ def find_toplevel(container)
+ top_level = container
+ while top_level.parent
+ top_level = top_level.parent
+ end
+ top_level
+ end
+
+ #
+ # Comments just after module or subprogram, or arguments are
+ # returnd. If "COMMENTS_ARE_UPPER" is true, comments just before
+ # modules or subprograms are returnd
+ #
def find_comments text
- lines = text.split("\n").reverse
+ return "" unless text
+ lines = text.split("\n")
+ lines.reverse! if COMMENTS_ARE_UPPER
comment_block = Array.new
lines.each do |line|
- break if line =~ /^\s*\w/
- comment_block.unshift line.sub(/^!\s?/,"")
+ break if line =~ /^\s*?\w/ || line =~ /^\s*?$/
+ if COMMENTS_ARE_UPPER
+ comment_block.unshift line.sub(/^\s*?!\s?/,"")
+ else
+ comment_block.push line.sub(/^\s*?!\s?/,"")
+ end
end
- nice_lines = comment_block.join("\n").split "\n\s*\n"
- nice_lines.shift
- nice_lines.shift
+ nice_lines = comment_block.join("\n").split "\n\s*?\n"
+ nice_lines[0] ||= ""
nice_lines.shift
end
@@ -114,6 +1523,706 @@
end
end
+ #
+ # Create method for internal alias
+ #
+ def initialize_public_method(method, parent)
+ return if !method || !parent
+
+ new_meth = AnyMethod.new("External Alias for module", method.name)
+ new_meth.singleton = method.singleton
+ new_meth.params = method.params.clone
+ new_meth.comment = remove_trailing_alias(method.comment.clone)
+ new_meth.comment << "\n\n#{EXTERNAL_ALIAS_MES} #{parent.strip.chomp}\##{method.name}"
+
+ return new_meth
+ end
+
+ #
+ # Create method for external alias
+ #
+ # If argument "internal" is true, file is ignored.
+ #
+ def initialize_external_method(new, old, params, file, comment, token=nil,
+ internal=nil, nolink=nil)
+ return nil unless new || old
+
+ if internal
+ external_alias_header = "#{INTERNAL_ALIAS_MES} "
+ external_alias_text = external_alias_header + old
+ elsif file
+ external_alias_header = "#{EXTERNAL_ALIAS_MES} "
+ external_alias_text = external_alias_header + file + "#" + old
+ else
+ return nil
+ end
+ external_meth = AnyMethod.new(external_alias_text, new)
+ external_meth.singleton = false
+ external_meth.params = params
+ external_comment = remove_trailing_alias(comment) + "\n\n" if comment
+ external_meth.comment = external_comment || ""
+ if nolink && token
+ external_meth.start_collecting_tokens
+ external_meth.add_token Token.new(1,1).set_text(token)
+ else
+ external_meth.comment << external_alias_text
+ end
+
+ return external_meth
+ end
+
+
+
+ #
+ # Parse visibility
+ #
+ def parse_visibility(code, default, container)
+ result = []
+ visibility_default = default || :public
+
+ used_modules = []
+ container.includes.each{|i| used_modules << i.name} if container
+
+ remaining_code = code.gsub(/^\s*?type[\s\,]+.*?\s+end\s+type.*?$/im, "")
+ remaining_code.split("\n").each{ |line|
+ if /^\s*?private\s*?$/ =~ line
+ visibility_default = :private
+ break
+ end
+ } if remaining_code
+
+ remaining_code.split("\n").each{ |line|
+ if /^\s*?private\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
+ methods = $2.sub(/!.*$/, '')
+ methods.split(",").each{ |meth|
+ meth.sub!(/!.*$/, '')
+ meth.gsub!(/:/, '')
+ result << {
+ "name" => meth.chomp.strip,
+ "visibility" => :private,
+ "used_modules" => used_modules.clone,
+ "file_or_module" => container,
+ "entity_is_discovered" => nil,
+ "local_name" => nil
+ }
+ }
+ elsif /^\s*?public\s*?(::)?\s+(.*)\s*?(!.*?)?/i =~ line
+ methods = $2.sub(/!.*$/, '')
+ methods.split(",").each{ |meth|
+ meth.sub!(/!.*$/, '')
+ meth.gsub!(/:/, '')
+ result << {
+ "name" => meth.chomp.strip,
+ "visibility" => :public,
+ "used_modules" => used_modules.clone,
+ "file_or_module" => container,
+ "entity_is_discovered" => nil,
+ "local_name" => nil
+ }
+ }
+ end
+ } if remaining_code
+
+ if container
+ result.each{ |vis_info|
+ vis_info["parent"] = container.name
+ }
+ end
+
+ return visibility_default, result
+ end
+
+ #
+ # Set visibility
+ #
+ # "subname" element of "visibility_info" is deleted.
+ #
+ def set_visibility(container, subname, visibility_default, visibility_info)
+ return unless container || subname || visibility_default || visibility_info
+ not_found = true
+ visibility_info.collect!{ |info|
+ if info["name"] == subname ||
+ @options.ignore_case && info["name"].upcase == subname.upcase
+ if info["file_or_module"].name == container.name
+ container.set_visibility_for([subname], info["visibility"])
+ info["entity_is_discovered"] = true
+ not_found = false
+ end
+ end
+ info
+ }
+ if not_found
+ return container.set_visibility_for([subname], visibility_default)
+ else
+ return container
+ end
+ end
+
+ #
+ # Find visibility
+ #
+ def find_visibility(container, subname, visibility_info)
+ return nil if !subname || !visibility_info
+ visibility_info.each{ |info|
+ if info["name"] == subname ||
+ @options.ignore_case && info["name"].upcase == subname.upcase
+ if info["parent"] == container.name
+ return info["visibility"]
+ end
+ end
+ }
+ return nil
+ end
+
+ #
+ # Check external aliases
+ #
+ # subname ¤È¤¤¤¦¥µ¥Ö¥ë¡¼¥Á¥ó̾, ¤Þ¤¿¤Ï´Ø¿ô̾¤ò»ý¤Ä¥Õ¥¡¥¤¥ë¤ò
+ # õºº¤·, ¸ºß¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¥Õ¥¡¥¤¥ëÆâ¤Ø¥á¥½¥Ã¥É¤òÄɲ乤ë.
+ #
+ def check_external_aliases(subname, params, comment, test=nil)
+ @@external_aliases.each{ |alias_item|
+ if subname == alias_item["old_name"] ||
+ subname.upcase == alias_item["old_name"].upcase &&
+ @options.ignore_case
+
+ new_meth = initialize_external_method(alias_item["new_name"],
+ subname, params, @file_name,
+ comment)
+ new_meth.visibility = alias_item["visibility"]
+
+ progress "e"
+ @stats.num_methods += 1
+ alias_item["file_or_module"].add_method(new_meth)
+
+ if !alias_item["file_or_module"].include_requires?(@file_name, @options.ignore_case)
+ alias_item["file_or_module"].add_require(Require.new(@file_name, ""))
+ end
+ end
+ }
+ end
+
+ #
+ # Check public_methods
+ #
+ # use ¤·¤¿¥â¥¸¥å¡¼¥ë¤«¤é¤½¤Î¤Þ¤Þ°ú¤·Ñ¤¤¤Ç public ¤È¤·¤Æ
+ # ¸ø³«¤¹¤ë¾ì¹ç¤Î¥Á¥§¥Ã¥¯¤ò¹Ô¤¦.
+ # subname ¤È¤¤¤¦¥µ¥Ö¥ë¡¼¥Á¥ó̾, ¤Þ¤¿¤Ï´Ø¿ô̾¤ò»ý¤Ä¥Õ¥¡¥¤¥ë¤ò
+ # õºº¤·, ¸ºß¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¥Õ¥¡¥¤¥ëÆâ¤Ø¥á¥½¥Ã¥É¤òÄɲ乤ë.
+ #
+ def check_public_methods(method, parent)
+ return if !method || !parent
+ @@public_methods.each{ |alias_item|
+ parent_is_used_module = nil
+ alias_item["used_modules"].each{ |used_module|
+ if used_module == parent ||
+ used_module.upcase == parent.upcase &&
+ @options.ignore_case
+ parent_is_used_module = true
+ end
+ }
+ next if !parent_is_used_module
+
+ if method.name == alias_item["name"] ||
+ method.name.upcase == alias_item["name"].upcase &&
+ @options.ignore_case
+
+ new_meth = initialize_public_method(method, parent)
+ if alias_item["local_name"]
+ new_meth.name = alias_item["local_name"]
+ end
+
+ progress "e"
+ @stats.num_methods += 1
+ alias_item["file_or_module"].add_method new_meth
+ end
+ }
+ end
+
+ #
+ # Continuous lines are united.
+ #
+ # Comments in continuous lines are removed.
+ # If delete_space=false, spaces around "&" are not deleted.
+ #
+ # Example
+ #
+ # before
+ #
+ # subroutine func(a, b, c, d, e, & ! ignored comments
+ # & f, g, h) ! valid comments
+ #
+ # after
+ #
+ # subroutine func(a, b, c, d, e, f, g, h) ! valid comments
+ #
+ def united_to_one_line(f90src, delete_space=true)
+ return "" unless f90src
+ lines = f90src.split("\n")
+ previous_continuing = false
+ now_continuing = false
+ body = ""
+ lines.each{ |line|
+ words = line.split("")
+ next if words.empty? && previous_continuing
+ commentout = false
+ brank_flag = true ; brank_char = ""
+ squote = false ; dquote = false
+ ignore = false
+ words.collect! { |char|
+ if previous_continuing && brank_flag
+ now_continuing = true
+ ignore = true
+ case char
+ when "!" ; break
+ when " " ; brank_char << char ; next ""
+ when "&"
+ brank_flag = false
+ now_continuing = false
+ next ""
+ else
+ brank_flag = false
+ now_continuing = false
+ ignore = false
+ next brank_char + char
+ end
+ end
+ ignore = false
+
+ if now_continuing
+ next ""
+ elsif !(squote) && !(dquote) && !(commentout)
+ case char
+ when "!" ; commentout = true ; next char
+ when "\""; dquote = true ; next char
+ when "\'"; squote = true ; next char
+ when "&" ; now_continuing = true ; next ""
+ else next char
+ end
+ elsif commentout
+ next char
+ elsif squote
+ case char
+ when "\'"; squote = false ; next char
+ else next char
+ end
+ elsif dquote
+ case char
+ when "\""; dquote = false ; next char
+ else next char
+ end
+ end
+ }
+ if !ignore && !previous_continuing || !brank_flag
+ if previous_continuing
+ if delete_space
+ joined_words = words.join("")
+ body = body.rstrip + " " + joined_words.lstrip
+ else
+ body << words.join("")
+ end
+ else
+ body << "\n" + words.join("")
+ end
+ end
+ previous_continuing = now_continuing ? true : nil
+ now_continuing = nil
+ }
+ return body
+ end
+
+
+ #
+ # Continuous line checker
+ #
+ def continuous_line?(line)
+ continuous = false
+ if /&\s*?(!.*)?$/ =~ line
+ continuous = true
+ if comment_out?($~.pre_match)
+ continuous = false
+ end
+ end
+ return continuous
+ end
+
+ #
+ # Comment out checker
+ #
+ def comment_out?(line)
+ return nil unless line
+ commentout = false
+ squote = false ; dquote = false
+ line.split("").each { |char|
+ if !(squote) && !(dquote)
+ case char
+ when "!" ; commentout = true ; break
+ when "\""; dquote = true
+ when "\'"; squote = true
+ else next
+ end
+ elsif squote
+ case char
+ when "\'"; squote = false
+ else next
+ end
+ elsif dquote
+ case char
+ when "\""; dquote = false
+ else next
+ end
+ end
+ }
+ return commentout
+ end
+
+ #
+ # Semicolons are replaced to line feed.
+ #
+ def semicolon_to_linefeed(text)
+ return "" unless text
+ lines = text.split("\n")
+ lines.collect!{ |line|
+ indent_space = ""
+ if line =~ /^(\s+)/
+ indent_space = $1
+ end
+ words = line.split("")
+ commentout = false
+ squote = false ; dquote = false
+ words.collect! { |char|
+ if !(squote) && !(dquote) && !(commentout)
+ case char
+ when "!" ; commentout = true ; next char
+ when "\""; dquote = true ; next char
+ when "\'"; squote = true ; next char
+ when ";" ; "\n"+indent_space
+ else next char
+ end
+ elsif commentout
+ next char
+ elsif squote
+ case char
+ when "\'"; squote = false ; next char
+ else next char
+ end
+ elsif dquote
+ case char
+ when "\""; dquote = false ; next char
+ else next char
+ end
+ end
+ }
+ words.join("")
+ }
+ return lines.join("\n")
+ end
+
+ #
+ # Which "line" is start of block (module, program, block data,
+ # subroutine, function) statement ?
+ #
+ def block_start?(line)
+ return nil if !line
+
+ if line =~ /^\s*?module\s+(\w+)\s*?(!.*?)?$/i ||
+ line =~ /^\s*?program\s+(\w+)\s*?(!.*?)?$/i ||
+ line =~ /^\s*?block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
+ line =~ \
+ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ subroutine\s+(\w+)\s*?(\(.*?\))?\s*?(!.*?)?$
+ /ix ||
+ line =~ \
+ /^\s*?
+ (recursive|pure|elemental)?\s*?
+ (
+ character\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | type\s*?\([\w\s]+?\)\s+
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | double\s+precision\s+
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?\s+
+ )?
+ function\s+(\w+)\s*?
+ (\(.*?\))?(\s+result\((.*?)\))?\s*?(!.*?)?$
+ /ix
+ return true
+ end
+
+ return nil
+ end
+
+ #
+ # Which "line" is end of block (module, program, block data,
+ # subroutine, function) statement ?
+ #
+ def block_end?(line)
+ return nil if !line
+
+ if line =~ /^\s*?end\s*?(!.*?)?$/i ||
+ line =~ /^\s*?end\s+module(\s+\w+)?\s*?(!.*?)?$/i ||
+ line =~ /^\s*?end\s+program(\s+\w+)?\s*?(!.*?)?$/i ||
+ line =~ /^\s*?end\s+block\s+data(\s+\w+)?\s*?(!.*?)?$/i ||
+ line =~ /^\s*?end\s+subroutine(\s+\w+)?\s*?(!.*?)?$/i ||
+ line =~ /^\s*?end\s+function(\s+\w+)?\s*?(!.*?)?$/i
+ return true
+ end
+
+ return nil
+ end
+
+ #
+ # Remove "Alias for" in end of comments
+ #
+ def remove_trailing_alias(text)
+ return "" if !text
+ lines = text.split("\n").reverse
+ comment_block = Array.new
+ checked = false
+ lines.each do |line|
+ if !checked
+ if /^\s?#{INTERNAL_ALIAS_MES}/ =~ line ||
+ /^\s?#{EXTERNAL_ALIAS_MES}/ =~ line
+ checked = true
+ next
+ end
+ end
+ comment_block.unshift line
+ end
+ nice_lines = comment_block.join("\n")
+ nice_lines ||= ""
+ return nice_lines
+ end
+
+ # Empty lines in header are removed
+ def remove_empty_head_lines(text)
+ return "" unless text
+ lines = text.split("\n")
+ header = true
+ lines.delete_if{ |line|
+ header = false if /\S/ =~ line
+ header && /^\s*?$/ =~ line
+ }
+ lines.join("\n")
+ end
+
+
+ # header marker "=", "==", ... are removed
+ def remove_header_marker(text)
+ return text.gsub(/^\s?(=+)/, '\1')
+ end
+
+ def remove_private_comments(body)
+ body.gsub!(/^(\s*)!--\s*?$.*?^\s*!\+\+\s*?$/m, '\\1!')
+ return body
+ end
+
+
+ #
+ # Information of arguments of subroutines and functions in Fortran95
+ #
+ class Fortran95Definition
+
+ # Name of variable
+ #
+ # ÊÑ¿ô̾
+ attr_reader :varname
+
+ # Types of variable
+ #
+ # ¥Ç¡¼¥¿·¿¾ðÊó
+ attr_reader :types
+
+ # Initial Value
+ #
+ # ½é´üÃÍ
+ attr_reader :inivalue
+
+ # Suffix of array
+ #
+ # ÇÛÎóÀÜÈø»ì
+ attr_reader :arraysuffix
+
+ # Comments
+ #
+ # ¹Ô¤ÎËöÈø¤Ë¤«¤«¤ì¤ë¥³¥á¥ó¥È
+ attr_accessor :comment
+
+ # Flag of non documentation
+ #
+ # ¥É¥¥å¥á¥ó¥È½ÐÎϤ·¤Ê¤¤¥Õ¥é¥°
+ attr_accessor :nodoc
+
+ def initialize(varname, types, inivalue, arraysuffix, comment,
+ nodoc=false)
+ @varname = varname
+ @types = types
+ @inivalue = inivalue
+ @arraysuffix = arraysuffix
+ @comment = comment
+ @nodoc = nodoc
+ end
+
+ def to_s
+ return <<-EOF
+
+EOF
+ end
+
+ #
+ # If attr is included, true is returned
+ #
+ def include_attr?(attr)
+ return if !attr
+ @types.split(",").each{ |type|
+ return true if type.strip.chomp.upcase == attr.strip.chomp.upcase
+ }
+ return nil
+ end
+
+ end # End of Fortran95Definition
+
+ #
+ # Parse string argument "text", and Return Array of
+ # Fortran95Definition object
+ #
+ def definition_info(text)
+ return nil unless text
+ lines = "#{text}"
+ defs = Array.new
+ comment = ""
+ trailing_comment = ""
+ under_comment_valid = false
+ lines.split("\n").each{ |line|
+ if /^\s*?!\s?(.*)/ =~ line
+ if COMMENTS_ARE_UPPER
+ comment << remove_header_marker($1)
+ comment << "\n"
+ elsif defs[-1] && under_comment_valid
+ defs[-1].comment << "\n"
+ defs[-1].comment << remove_header_marker($1)
+ end
+ next
+ elsif /^\s*?$/ =~ line
+ comment = ""
+ under_comment_valid = false
+ next
+ end
+ type = ""
+ characters = ""
+ if line =~ /^\s*?
+ (
+ character\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+ | type\s*?\([\w\s]+?\)[\s\,]*
+ | integer\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+ | real\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+ | double\s+precision[\s\,]*
+ | logical\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+ | complex\s*?(\([\w\s\=\(\)\*]+?\))?[\s\,]*
+ )
+ (.*?::)?
+ (.+)$
+ /ix
+ characters = $8
+ type = $1
+ type << $7.gsub(/::/, '').gsub(/^\s*?\,/, '') if $7
+ else
+ under_comment_valid = false
+ next
+ end
+ squote = false ; dquote = false ; bracket = 0
+ iniflag = false; commentflag = false
+ varname = "" ; arraysuffix = "" ; inivalue = ""
+ start_pos = defs.size
+ characters.split("").each { |char|
+ if !(squote) && !(dquote) && bracket <= 0 && !(iniflag) && !(commentflag)
+ case char
+ when "!" ; commentflag = true
+ when "(" ; bracket += 1 ; arraysuffix = char
+ when "\""; dquote = true
+ when "\'"; squote = true
+ when "=" ; iniflag = true ; inivalue << char
+ when ","
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+ varname = "" ; arraysuffix = "" ; inivalue = ""
+ under_comment_valid = true
+ when " " ; next
+ else ; varname << char
+ end
+ elsif commentflag
+ comment << remove_header_marker(char)
+ trailing_comment << remove_header_marker(char)
+ elsif iniflag
+ if dquote
+ case char
+ when "\"" ; dquote = false ; inivalue << char
+ else ; inivalue << char
+ end
+ elsif squote
+ case char
+ when "\'" ; squote = false ; inivalue << char
+ else ; inivalue << char
+ end
+ elsif bracket > 0
+ case char
+ when "(" ; bracket += 1 ; inivalue << char
+ when ")" ; bracket -= 1 ; inivalue << char
+ else ; inivalue << char
+ end
+ else
+ case char
+ when ","
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+ varname = "" ; arraysuffix = "" ; inivalue = ""
+ iniflag = false
+ under_comment_valid = true
+ when "(" ; bracket += 1 ; inivalue << char
+ when "\""; dquote = true ; inivalue << char
+ when "\'"; squote = true ; inivalue << char
+ when "!" ; commentflag = true
+ else ; inivalue << char
+ end
+ end
+ elsif !(squote) && !(dquote) && bracket > 0
+ case char
+ when "(" ; bracket += 1 ; arraysuffix << char
+ when ")" ; bracket -= 1 ; arraysuffix << char
+ else ; arraysuffix << char
+ end
+ elsif squote
+ case char
+ when "\'"; squote = false ; inivalue << char
+ else ; inivalue << char
+ end
+ elsif dquote
+ case char
+ when "\""; dquote = false ; inivalue << char
+ else ; inivalue << char
+ end
+ end
+ }
+ defs << Fortran95Definition.new(varname, type, inivalue, arraysuffix, comment)
+ if trailing_comment =~ /^:nodoc:/
+ defs[start_pos..-1].collect!{ |defitem|
+ defitem.nodoc = true
+ }
+ end
+ varname = "" ; arraysuffix = "" ; inivalue = ""
+ comment = ""
+ under_comment_valid = true
+ trailing_comment = ""
+ }
+ return defs
+ end
+
+
end # class Fortran95parser
end # module RDoc
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/parsers/parse_rb.rb ../rdoc-f95-20060814/parsers/parse_rb.rb
--- ruby-1.8.4/lib/rdoc/parsers/parse_rb.rb 2005-11-01 22:44:58.000000000 +0900
+++ ../rdoc-f95-20060814/parsers/parse_rb.rb 2005-10-19 23:00:26.000000000 +0900
@@ -436,7 +436,6 @@
def_exception(:SyntaxError, "%s")
include RubyToken
- include IRB
attr_reader :continue
attr_reader :lex_state
@@ -589,6 +588,7 @@
def lex_init()
@OP = SLex.new
+# @OP = IRB::SLex.new # 1.8 doesn't support #IRB::SLex
@OP.def_rules("\0", "\004", "\032") do |chars, io|
Token(TkEND_OF_SCRIPT).set_text(chars)
end
@@ -2328,6 +2328,7 @@
when "section"
context.set_current_section(param, comment)
+# comment.clear # latest version
comment.replace("") # 1.8 doesn't support #clear
break
else
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/rdoc ../rdoc-f95-20060814/rdoc
--- ruby-1.8.4/lib/rdoc/rdoc 1970-01-01 09:00:00.000000000 +0900
+++ ../rdoc-f95-20060814/rdoc 2005-09-22 18:40:11.000000000 +0900
@@ -0,0 +1,67 @@
+#!/usr/bin/env ruby
+#
+# RDoc: Documentation tool for source code
+# (see lib/rdoc/rdoc.rb for more information)
+#
+# Copyright (c) 2003 Dave Thomas
+# Released under the same terms as Ruby
+#
+# $Revision: 1.1 $
+
+## Transitional Hack ####
+#
+# RDoc was initially distributed independently, and installed
+# itself into /lib/ruby/site_ruby//rdoc...
+#
+# Now that RDoc is part of the distribution, it's installed into
+# /lib/ruby/, which unfortunately appears later in the
+# search path. This means that if you have previously installed RDoc,
+# and then install from ruby-lang, you'll pick up the old one by
+# default. This hack checks for the condition, and readjusts the
+# search path if necessary.
+
+#def adjust_for_existing_rdoc(path)
+#
+# $stderr.puts %{
+# It seems as if you have a previously-installed RDoc in
+# the directory #{path}.
+#
+# Because this is now out-of-date, you might want to consider
+# removing the directories:
+#
+# #{File.join(path, "rdoc")}
+#
+# and
+#
+# #{File.join(path, "markup")}
+#
+# }
+#
+# # Move all the site_ruby directories to the end
+# p $:
+# $:.replace($:.partition {|path| /site_ruby/ !~ path}.flatten)
+# p $:
+#end
+#
+# $:.each do |path|
+# if /site_ruby/ =~ path
+# rdoc_path = File.join(path, 'rdoc', 'rdoc.rb')
+# if File.exists?(rdoc_path)
+# adjust_for_existing_rdoc(path)
+# break
+# end
+# end
+#end
+
+## End of Transitional Hack ##
+
+
+require 'rdoc/rdoc'
+
+begin
+ r = RDoc::RDoc.new
+ r.document(ARGV)
+rescue RDoc::RDocError => e
+ $stderr.puts e.message
+ exit(1)
+end
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/rdoc.rb ../rdoc-f95-20060814/rdoc.rb
--- ruby-1.8.4/lib/rdoc/rdoc.rb 2004-12-12 10:16:19.000000000 +0900
+++ ../rdoc-f95-20060814/rdoc.rb 2006-08-09 15:02:28.000000000 +0900
@@ -2,7 +2,10 @@
#
-VERSION_STRING = %{RDoc V1.0.1 - 20041108}
+VERSION_STRING = <<-"EOF"
+RDoc modified by GFD Dennou Club: Version $Name: rdoc-f95-20060814 $
+ See http://www.gfd-dennou.org/library/dcmodel
+EOF
require 'rdoc/parsers/parse_rb.rb'
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/ri/ri_display.rb ../rdoc-f95-20060814/ri/ri_display.rb
--- ruby-1.8.4/lib/rdoc/ri/ri_display.rb 2004-03-25 04:17:42.000000000 +0900
+++ ../rdoc-f95-20060814/ri/ri_display.rb 2005-09-22 16:49:20.000000000 +0900
@@ -194,12 +194,15 @@
######################################################################
def page
- setup_pager
+ return yield unless pager = setup_pager
begin
+ save_stdout = STDOUT.clone
+ STDOUT.reopen(pager)
yield
- page_output
ensure
- STDOUT.reopen(@save_stdout) if @save_stdout
+ STDOUT.reopen(save_stdout)
+ save_stdout.close
+ pager.close
end
end
@@ -207,31 +210,11 @@
def setup_pager
unless @options.use_stdout
- require 'tempfile'
-
- @save_stdout = STDOUT.clone
- STDOUT.reopen(Tempfile.new("ri_"))
- end
- end
-
- ######################################################################
-
- def page_output
- unless @options.use_stdout
- path = STDOUT.path
- STDOUT.reopen(@save_stdout)
- @save_stdout = nil
- paged = false
- for pager in [ ENV['PAGER'], "less", "more <", 'pager' ].compact.uniq
- if system("#{pager} #{path}")
- paged = true
- break
- end
- end
- if !paged
- @options.use_stdout = true
- puts File.read(path)
+ for pager in [ ENV['PAGER'], "less", "more", 'pager' ].compact.uniq
+ return IO.popen(pager, "w") rescue nil
end
+ @options.use_stdout = true
+ nil
end
end
@@ -253,12 +236,7 @@
@formatter.break_to_newline
end
end
- ######################################################################
-
- def warn_no_database
- puts "Before using ri, you need to generate documentation"
- puts "using 'rdoc' with the --ri option"
- end
+
######################################################################
def display_flow(flow)
@@ -269,5 +247,10 @@
end
end
-
+ ######################################################################
+
+ def warn_no_database
+ puts "Before using ri, you need to generate documentation"
+ puts "using 'rdoc' with the --ri option"
+ end
end # class RiDisplay
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/ri/ri_formatter.rb ../rdoc-f95-20060814/ri/ri_formatter.rb
--- ruby-1.8.4/lib/rdoc/ri/ri_formatter.rb 2004-12-31 14:22:05.000000000 +0900
+++ ../rdoc-f95-20060814/ri/ri_formatter.rb 2005-09-22 16:49:20.000000000 +0900
@@ -43,7 +43,7 @@
end
end
res << work if work.length.nonzero?
- puts (prefix + res.join("\n" + next_prefix))
+ puts(prefix + res.join("\n" + next_prefix))
end
######################################################################
diff -Nur --exclude=doc ruby-1.8.4/lib/rdoc/ri/ri_paths.rb ../rdoc-f95-20060814/ri/ri_paths.rb
--- ruby-1.8.4/lib/rdoc/ri/ri_paths.rb 2004-01-13 01:10:52.000000000 +0900
+++ ../rdoc-f95-20060814/ri/ri_paths.rb 2005-09-22 16:49:20.000000000 +0900
@@ -29,13 +29,7 @@
version = Config::CONFIG['ruby_version']
base = File.join(Config::CONFIG['datadir'], "ri", version)
-
- if ENV["DESTDIR"]
- SYSDIR = File.join(ENV["DESTDIR"], base, "system")
- else
- SYSDIR = File.join(base, "system")
- end
-
+ SYSDIR = File.join(base, "system")
SITEDIR = File.join(base, "site")
homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']