Class: MakeMakefile::Depend::Scanner
Do not use. This class is for internal use only.
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/mkmf/depend.rb |
Class Method Summary
Instance Attribute Summary
- #accessed readonly
- #unresolved readonly
Instance Method Summary
- #scan(source)
- #expression_condition(expression) private
- #relative(path) private
- #resolve(name, current, quoted) private
- #scan_include(argument, current, dependencies, visited) private
- #source_directives(path) private
- #symbol_condition(symbol) private
- #visit(path, dependencies, visited, record: true) private
Constructor Details
.new(root:, include_dirs:, quote_dirs: [], macros: {}, targets: [], aliases: {}, dependencies: {}, defined: [], undefined: [], cache: {}) ⇒ Scanner
# File 'lib/mkmf/depend.rb', line 75
def initialize(root:, include_dirs:, quote_dirs: [], macros: {}, targets: [], aliases: {}, dependencies: {}, defined: [], undefined: [], cache: {}) @root = File.(root) @include_dirs = include_dirs.map {|dir| File.(dir, @root)} @quote_dirs = quote_dirs.map {|dir| File.(dir, @root)} @macros = macros @targets = targets.to_set @aliases = aliases @dependencies = dependencies @defined = defined.to_set @undefined = undefined.to_set @accessed = Set.new @unresolved = Set.new @cache = cache end
Instance Attribute Details
#accessed (readonly)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 73
attr_reader :accessed, :unresolved
#unresolved (readonly)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 73
attr_reader :accessed, :unresolved
Instance Method Details
#expression_condition(expression) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 176
def expression_condition(expression) case expression.sub(%r{/\*.*}, '').strip when /\A0+[LU]*(?:\z|\s*&&)/i return false when /\A1+[LU]*(?:\z|\s*\|\|)/i return true when /\A(!?)\s*defined\s*(?:\(\s*)?(\w+)/ condition = symbol_condition($2) return condition if condition == :all return $1.empty? ? condition : !condition when /\A(!?)(\w+)\z/ condition = symbol_condition($2) return condition if condition == :all return $1.empty? ? condition : !condition end :all end
#relative(path) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 244
def relative(path) prefix = @root + File::SEPARATOR path.start_with?(prefix) ? path.delete_prefix(prefix) : path end
#resolve(name, current, quoted) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 232
def resolve(name, current, quoted) dirs = [] dirs << File.dirname(current) if quoted dirs.concat(@quote_dirs) if quoted dirs.concat(@include_dirs) dirs.each do |dir| path = File.(name, dir) return path if source_directives(path) end nil end
#scan(source)
[ GitHub ]#scan_include(argument, current, dependencies, visited) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 194
def scan_include(argument, current, dependencies, visited) case argument.sub(%r{//.*\z}, '').strip when /\A([<"])([^<>"]+)[>"]/ quoted = $1 == '"' name = $2 when /\A([A-Za-z_]\w*)/ name = $1 unless @aliases.key?(name) || @dependencies.key?(name) || @targets.include?(name) name = @macros[name] end quoted = true end return unless name if alias_path = @aliases[name] if virtual = @dependencies[name] dependencies.merge(virtual) else dependencies.add(name) end visit(File.(alias_path, @root), dependencies, visited, record: false) return end if virtual = @dependencies[name] dependencies.merge(virtual) elsif name.end_with?(".inc", ".rbinc", ".rbbin") dependencies.add(name) elsif path = resolve(name, current, quoted) visit(path, dependencies, visited) elsif @targets.include?(name) dependencies.add(name) else @unresolved.add(name) end end
#source_directives(path) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 142
def source_directives(path) path = File.(path) @accessed.add(path) return @cache[path] if @cache.key?(path) @cache[path] = if File.file?(path) File.open(path, "rb") do |file| directives = [] logical_line = "".b file.each_line do |line| logical_line << line next if logical_line.sub!(/\\\r?\n\z/, "") if directive = logical_line[/\A\s*#\s*\K.*/] directives << directive end logical_line.clear end unless logical_line.empty? if directive = logical_line[/\A\s*#\s*\K.*/] directives << directive end end directives end end end
#symbol_condition(symbol) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 170
def symbol_condition(symbol) return true if @defined.include?(symbol) return false if @undefined.include?(symbol) :all end
#visit(path, dependencies, visited, record: true) (private)
[ GitHub ]# File 'lib/mkmf/depend.rb', line 100
def visit(path, dependencies, visited, record: true) path = File.(path) return if visited.include?(path) directives = source_directives(path) return unless directives visited.add(path) dependencies.add(relative(path)) if record conditions = [] directives.each do |directive| case directive when /\Aifdef\s(\w)/ conditions << symbol_condition($1) when /\Aifndef\s(\w)/ condition = symbol_condition($1) conditions << (condition == :all ? :all : !condition) when /\Aif\s(.)/ conditions << expression_condition($1) when /\Aelif\s(.)/ conditions[-1] = if conditions[-1] == true false elsif conditions[-1] == false expression_condition($1) else :all end when /\Aelse\b/ conditions[-1] = !conditions[-1] if [true, false].include?(conditions[-1]) when /\Aendif\b/ conditions.pop else next if conditions.include?(false) case directive when /\A(?:line\s)?\d\s"([^"<>])"/ dependencies.add($1.delete_prefix("./")) when /\Ainclude(?:_next)?\s(.)/ scan_include($1, path, dependencies, visited) end end end end