class ParseC::SourceFile

Source file contains C-function definitions and header file inclusions.

Attributes

name[R]

File name.

Public Class Methods

new( name, headerPath ) click to toggle source

Set file to parse and path for header search. Finally, perform parsing for the file.

# File lib/parsec.rb, line 48
def initialize( name, headerPath )
    @name = name
    @headerPath = headerPath

    @localHeader = {}
    @funcdefs = {}
    @funcalls = {}

    @conf = {}
    @conf[ :defsonly ] = false
    @conf[ :mainonly ] = false
end
parseLocalDefs( name, headerPath ) click to toggle source
# File lib/parsec.rb, line 37
def SourceFile.parseLocalDefs( name, headerPath )
    file = SourceFile.new( name, headerPath )
    file.conf( :defsonly, true )
    file.conf( :mainonly, true )
    file.parse
    file
end

Public Instance Methods

conf( opt, value = nil ) click to toggle source
# File lib/parsec.rb, line 62
def conf( opt, value = nil )
    if value
        @conf[ opt ] = value
    else
        @conf[ opt ]
    end
end
display() click to toggle source

Display c-file content.

# File lib/parsec.rb, line 190
def display
    puts "File: #{@name}"
    puts "  Includes:"
    @localHeader.each_value do |i|
        puts "    #{i.name} | #{i.path}"
    end
    puts "  Functions:"
    @funcdefs.each_value do |f|
        puts "    #{f.declaration}"
    end
end
dump( headerPath = @headerPath ) click to toggle source

Show raw content of c-file.

# File lib/parsec.rb, line 204
def dump( headerPath = @headerPath )
    index = FFI::Clang::Index.new
    translation_unit = index.parse_translation_unit( @name, headerPath )
    cursor = translation_unit.cursor
    cursor.visit_children do |cursor, parent|
        puts "#{cursor.kind} #{cursor.spelling}"
        next :recurse
    end
end
funcalls() click to toggle source
# File lib/parsec.rb, line 90
def funcalls
    @funcalls
end
funcdefs() click to toggle source

Return list of defined functions. Can be used e.g. to generate function declarations to a header file (automatically).

@return [Array<HeaderFile>] Functions.

# File lib/parsec.rb, line 85
def funcdefs
    @funcdefs
end
headers() click to toggle source

Return list of included (local) header files. Can be used e.g. for c-to-h file dependence.

@return [Array<HeaderFile>] Headers.

# File lib/parsec.rb, line 75
def headers
    @localHeader
end
isLocalHeader?( file ) click to toggle source

Return true if file name is for a local header.

# File lib/parsec.rb, line 96
def isLocalHeader?( file )
    if file[0] != '/' && /\.h$/.match( file )
        true
    else
        false
    end
end
parse( headerPath = @headerPath ) click to toggle source

Parse c-file.

@param headerPath [String] Path for system header lookup.

# File lib/parsec.rb, line 108
def parse( headerPath = @headerPath )

    index = FFI::Clang::Index.new
    translation_unit = index.parse_translation_unit( @name, headerPath )
    cursor = translation_unit.cursor

    # Get list of included local headers.
    translation_unit.inclusions do |header|
        if isLocalHeader? header
            @localHeader[ header ] = HeaderFile.new( header )
        end
    end

    # Recursively travel the c-file hierarchy to detect
    # function definitions.
    cursor.visit_children do |cursor, parent|

        if cursor.kind == :cursor_function

            # Check that function is in the file that is being
            # analysed. Might also be from an included header.
            if ( @conf[:mainonly] == false ) || cursor.location.from_main_file?

                f = Function.new( cursor.spelling, cursor.variadic? )
                f.setReturnType( cursor.result_type.spelling )

                # Get argument list.
                cursor.visit_children do |cursor, parent|

                    case cursor.kind

                    when :cursor_parm_decl
                        f.addArgument( cursor.spelling, cursor.type.spelling )

                    else
                        # puts cursor.kind
                        true

                    end

                    next :continue
                end


                # Mark function complete and add to list.
                @funcdefs[ f.name ] = f.done

                if @conf[:defsonly]
                    # Don't recurse anymore.
                    next :continue
                else
                    next :recurse
                end

            else

                next :continue

            end

        elsif cursor.kind == :cursor_call_expr


            # if cursor.location.from_main_file?
            f = FunCall.new( cursor.spelling )
            @funcalls[ f.name ] = f
            # end

            next :recurse

        else

            # Non-functions are not interesting.
            next :recurse

        end

    end
end