diff options
Diffstat (limited to 'lib/rdoc/parser/c.rb')
-rw-r--r-- | lib/rdoc/parser/c.rb | 277 |
1 files changed, 144 insertions, 133 deletions
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb index 9d8db6cdee..4050d7aa49 100644 --- a/lib/rdoc/parser/c.rb +++ b/lib/rdoc/parser/c.rb @@ -122,6 +122,11 @@ class RDoc::Parser::C < RDoc::Parser include RDoc::Text + # :stopdoc: + BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/ + TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze + # :startdoc: + ## # Maps C variable names to names of Ruby classes or modules @@ -173,6 +178,8 @@ class RDoc::Parser::C < RDoc::Parser @classes = load_variable_map :c_class_variables @singleton_classes = load_variable_map :c_singleton_class_variables + @markup = @options.markup + # class_variable => { function => [method, ...] } @methods = Hash.new { |h, f| h[f] = Hash.new { |i, m| i[m] = [] } } @@ -257,18 +264,18 @@ class RDoc::Parser::C < RDoc::Parser @content.scan(/rb_attr\s*\( \s*(\w+), \s*([\w"()]+), - \s*([01]), - \s*([01]), - \s*\w+\);/xm) do |var_name, attr_name, read, write| + #{BOOL_ARG_PATTERN}, + #{BOOL_ARG_PATTERN}, + \s*\w+\);/xmo) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end @content.scan(%r%rb_define_attr\( \s*([\w\.]+), \s*"([^"]+)", - \s*(\d+), - \s*(\d+)\s*\); - %xm) do |var_name, attr_name, read, write| + #{BOOL_ARG_PATTERN}, + #{BOOL_ARG_PATTERN}\); + %xmo) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end end @@ -293,94 +300,92 @@ class RDoc::Parser::C < RDoc::Parser @content.scan( %r( + (?<open>\s*\(\s*) {0} + (?<close>\s*\)\s*) {0} + (?<name>\s*"(?<class_name>\w+)") {0} + (?<parent>\s*(?: + (?<parent_name>[\w\*\s\(\)\.\->]+) | + rb_path2class\s*\(\s*"(?<path>[\w:]+)"\s*\) + )) {0} + (?<under>\w+) {0} + (?<var_name>[\w\.]+)\s* = \s*rb_(?: define_(?: - class(?: # rb_define_class(class_name_1, parent_name_1) - \s*\( - \s*"(?<class_name_1>\w+)", - \s*(?<parent_name_1>\w+)\s* - \) - | - _under\s*\( # rb_define_class_under(class_under, class_name2, parent_name2...) - \s* (?<class_under>\w+), - \s* "(?<class_name_2>\w+)", - \s* - (?: - (?<parent_name_2>[\w\*\s\(\)\.\->]+) | - rb_path2class\("(?<path>[\w:]+)"\) - ) + class(?: # rb_define_class(name, parent_name) + \(\s* + \g<name>, + \g<parent> \s*\) + | + _under\g<open> # rb_define_class_under(under, name, parent_name...) + \g<under>, + \g<name>, + \g<parent> + \g<close> ) | - module(?: # rb_define_module(module_name_1) - \s*\( - \s*"(?<module_name_1>\w+)"\s* - \) + (?<module>) + module(?: # rb_define_module(name) + \g<open> + \g<name> + \g<close> | - _under\s*\( # rb_define_module_under(module_under, module_name_2) - \s*(?<module_under>\w+), - \s*"(?<module_name_2>\w+)" - \s*\) + _under\g<open> # rb_define_module_under(under, name) + \g<under>, + \g<name> + \g<close> ) ) | - struct_define_without_accessor\s*\( # rb_struct_define_without_accessor(class_name_3, parent_name_3, ...) - \s*"(?<class_name_3>\w+)", - \s*(?<parent_name_3>\w+), - \s*\w+, # Allocation function - (?:\s*"\w+",)* # Attributes - \s*NULL - \) + (?<attributes>(?:\s*"\w+",)*\s*NULL\s*) {0} + struct_define(?: + \g<open> # rb_struct_define(name, ...) + \g<name>, + | + _under\g<open> # rb_struct_define_under(under, name, ...) + \g<under>, + \g<name>, + | + _without_accessor(?: + \g<open> # rb_struct_define_without_accessor(name, parent_name, ...) + | + _under\g<open> # rb_struct_define_without_accessor_under(under, name, parent_name, ...) + \g<under>, + ) + \g<name>, + \g<parent>, + \s*\w+, # Allocation function + ) + \g<attributes> + \g<close> | - singleton_class\s*\( # rb_singleton_class(target_class_name) - \s*(?<target_class_name>\w+) - \) + singleton_class\g<open> # rb_singleton_class(target_class_name) + (?<target_class_name>\w+) + \g<close> ) )mx ) do - class_name = $~[:class_name_1] - type = :class - if class_name - # rb_define_class(class_name_1, parent_name_1) - parent_name = $~[:parent_name_1] - #under = nil - else - class_name = $~[:class_name_2] - if class_name - # rb_define_class_under(class_under, class_name2, parent_name2...) - parent_name = $~[:parent_name_2] || $~[:path] - under = $~[:class_under] - else - class_name = $~[:class_name_3] - if class_name - # rb_struct_define_without_accessor(class_name_3, parent_name_3, ...) - parent_name = $~[:parent_name_3] - #under = nil - else - type = :module - class_name = $~[:module_name_1] - #parent_name = nil - if class_name - # rb_define_module(module_name_1) - #under = nil - else - class_name = $~[:module_name_2] - if class_name - # rb_define_module_under(module_under, module_name_1) - under = $~[:module_under] - else - # rb_singleton_class(target_class_name) - target_class_name = $~[:target_class_name] - handle_singleton $~[:var_name], target_class_name - next - end - end - end - end + if target_class_name = $~[:target_class_name] + # rb_singleton_class(target_class_name) + handle_singleton $~[:var_name], target_class_name + next end - handle_class_module($~[:var_name], type, class_name, parent_name, under) + var_name = $~[:var_name] + type = $~[:module] ? :module : :class + class_name = $~[:class_name] + parent_name = $~[:parent_name] || $~[:path] + under = $~[:under] + attributes = $~[:attributes] + + handle_class_module(var_name, type, class_name, parent_name, under) + if attributes and !parent_name # rb_struct_define *not* without_accessor + true_flag = 'Qtrue' + attributes.scan(/"\K\w+(?=")/) do |attr_name| + handle_attr var_name, attr_name, true_flag, true_flag + end + end end end @@ -435,11 +440,11 @@ class RDoc::Parser::C < RDoc::Parser # Scans #content for rb_include_module def do_includes - @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m| + @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c, m| next unless cls = @classes[c] m = @known_classes[m] || m - comment = RDoc::Comment.new '', @top_level, :c + comment = new_comment '', @top_level, :c incl = cls.add_include RDoc::Include.new(m, comment) incl.record_location @top_level end @@ -521,7 +526,7 @@ class RDoc::Parser::C < RDoc::Parser \s*"#{Regexp.escape new_name}"\s*, \s*"#{Regexp.escape old_name}"\s*\);%xm - RDoc::Comment.new($1 || '', @top_level, :c) + new_comment($1 || '', @top_level, :c) end ## @@ -560,7 +565,7 @@ class RDoc::Parser::C < RDoc::Parser '' end - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -570,19 +575,18 @@ class RDoc::Parser::C < RDoc::Parser table = {} file_content.scan(%r{ ((?>/\*.*?\*/\s*)?) - ((?:(?:\w+)\s+)? - (?:intern\s+)?VALUE\s+(\w+) - \s*(?:\([^)]*\))(?:[^\);]|$)) + ((?:\w+\s+){0,2} VALUE\s+(\w+) + \s*(?:\([^\)]*\))(?:[^\);]|$)) | ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+)) | ^\s*\#\s*define\s+(\w+)\s+(\w+) }xm) do case - when $1 - table[$3] = [:func_def, $1, $2, $~.offset(2)] if !table[$3] || table[$3][0] != :func_def - when $4 - table[$6] = [:macro_def, $4, $5, $~.offset(5), $7] if !table[$6] || table[$6][0] == :macro_alias - when $8 - table[$8] ||= [:macro_alias, $9] + when name = $3 + table[name] = [:func_def, $1, $2, $~.offset(2)] if !(t = table[name]) || t[0] != :func_def + when name = $6 + table[name] = [:macro_def, $4, $5, $~.offset(5), $7] if !(t = table[name]) || t[0] == :macro_alias + when name = $8 + table[name] ||= [:macro_alias, $9] end end table @@ -600,7 +604,7 @@ class RDoc::Parser::C < RDoc::Parser case type when :func_def - comment = RDoc::Comment.new args[0], @top_level, :c + comment = new_comment args[0], @top_level, :c body = args[1] offset, = args[2] @@ -630,7 +634,7 @@ class RDoc::Parser::C < RDoc::Parser body when :macro_def - comment = RDoc::Comment.new args[0], @top_level, :c + comment = new_comment args[0], @top_level, :c body = args[1] offset, = args[2] @@ -675,13 +679,14 @@ class RDoc::Parser::C < RDoc::Parser ## # Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+ - def find_class(raw_name, name) + def find_class(raw_name, name, base_name = nil) unless @classes[raw_name] if raw_name =~ /^rb_m/ container = @top_level.add_module RDoc::NormalModule, name else container = @top_level.add_class RDoc::NormalClass, name end + container.name = base_name if base_name container.record_location @top_level @classes[raw_name] = container @@ -722,7 +727,7 @@ class RDoc::Parser::C < RDoc::Parser ((?>/\*.*?\*/\s+)) (static\s+)? void\s+ - Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then + Init(?:VM)?_(?i:#{class_name})\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xm then comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '') elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*? (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then @@ -737,7 +742,7 @@ class RDoc::Parser::C < RDoc::Parser comment = '' end - comment = RDoc::Comment.new comment, @top_level, :c + comment = new_comment comment, @top_level, :c comment.normalize look_for_directives_in class_mod, comment @@ -751,17 +756,27 @@ class RDoc::Parser::C < RDoc::Parser def gen_const_table file_content table = {} @content.scan(%r{ - ((?>^\s*/\*.*?\*/\s+)) - rb_define_(\w+)\((?:\s*(?:\w+),)?\s* - "(\w+)"\s*, + (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_define_(?<type>\w+)\(\s*(?:\w+),\s* + "(?<name>\w+)"\s*, .*?\)\s*; + | (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_file_(?<type>const)\(\s* + "(?<name>\w+)"\s*, + .*?\)\s*; + | (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_curses_define_(?<type>const)\(\s* + (?<name>\w+) + \s*\)\s*; | Document-(?:const|global|variable):\s - ((?:\w+::)*\w+) - \s*?\n((?>.*?\*/)) + (?<name>(?:\w+::)*\w+) + \s*?\n(?<doc>(?>.*?\*/)) }mxi) do - case - when $1 then table[[$2, $3]] = $1 - when $4 then table[$4] = "/*\n" + $5 + name, doc, type = $~.values_at(:name, :doc, :type) + if type + table[[type, name]] = doc + else + table[name] = "/*\n" + doc end end table @@ -782,7 +797,7 @@ class RDoc::Parser::C < RDoc::Parser table[const_name] || '' - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -813,7 +828,7 @@ class RDoc::Parser::C < RDoc::Parser return unless comment - RDoc::Comment.new comment, @top_level, :c + new_comment comment, @top_level, :c end ## @@ -822,8 +837,8 @@ class RDoc::Parser::C < RDoc::Parser def handle_attr(var_name, attr_name, read, write) rw = '' - rw += 'R' if '1' == read - rw += 'W' if '1' == write + rw += 'R' if TRUE_VALUES.include?(read) + rw += 'W' if TRUE_VALUES.include?(write) class_name = @known_classes[var_name] @@ -919,7 +934,7 @@ class RDoc::Parser::C < RDoc::Parser return unless class_name - class_obj = find_class var_name, class_name + class_obj = find_class var_name, class_name, class_name[/::\K[^:]+\z/] unless class_obj then @options.warn 'Enclosing class or module %p is not known' % [const_name] @@ -933,21 +948,20 @@ class RDoc::Parser::C < RDoc::Parser # "/* definition: comment */" form. The literal ':' and '\' characters # can be escaped with a backslash. if type.downcase == 'const' then - no_match, new_definition, new_comment = comment.text.split(/(\A.*):/) + if /\A(.+?)?:(?!\S)/ =~ comment.text + new_definition, new_comment = $1, $' - if no_match and no_match.empty? then - if new_definition.empty? then # Default to literal C definition + if !new_definition # Default to literal C definition new_definition = definition else - new_definition = new_definition.gsub("\:", ":") - new_definition = new_definition.gsub("\\", '\\') + new_definition = new_definition.gsub(/\\([\\:])/, '\1') end new_definition.sub!(/\A(\s+)/, '') new_comment = "#{$1}#{new_comment.lstrip}" - new_comment = RDoc::Comment.new new_comment, @top_level, :c + new_comment = self.new_comment(new_comment, @top_level, :c) con = RDoc::Constant.new const_name, new_definition, new_comment else @@ -1023,12 +1037,18 @@ class RDoc::Parser::C < RDoc::Parser elsif p_count == -1 then # argc, argv rb_scan_args body else - "(#{(1..p_count).map { |i| "p#{i}" }.join ', '})" + args = (1..p_count).map { |i| "p#{i}" } + "(#{args.join ', '})" end meth_obj.record_location @top_level + + if meth_obj.section_title + class_obj.temporary_section = class_obj.add_section(meth_obj.section_title) + end class_obj.add_method meth_obj + @stats.add_method meth_obj meth_obj.visibility = :private if 'private_method' == type end @@ -1046,23 +1066,6 @@ class RDoc::Parser::C < RDoc::Parser end ## - # Normalizes tabs in +body+ - - def handle_tab_width(body) - if /\t/ =~ body - tab_width = @options.tab_width - body.split(/\n/).map do |line| - 1 while line.gsub!(/\t+/) do - ' ' * (tab_width * $&.length - $`.length % tab_width) - end && $~ - line - end.join "\n" - else - body - end - end - - ## # Loads the variable map with the given +name+ from the RDoc::Store, if # present. @@ -1222,4 +1225,12 @@ class RDoc::Parser::C < RDoc::Parser @top_level end + ## + # Creates a RDoc::Comment instance. + + def new_comment text = nil, location = nil, language = nil + RDoc::Comment.new(text, location, language).tap do |comment| + comment.format = @markup + end + end end |