class AdLint::Cpp::Preprocessor

DESCRIPTION

C preprocessor language evaluator.

Preprocessor executes recursive descent parsing and evaluation at a time.

Public Instance Methods

execute(pp_ctxt, src) click to toggle source
# File lib/adlint/cpp/eval.rb, line 53
def execute(pp_ctxt, src)
  @pp_ctxt = pp_ctxt
  @pp_ctxt.push_lexer(create_lexer(@pp_ctxt, src))
  preprocessing_file(@pp_ctxt)
end

Private Instance Methods

asm_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 576
def asm_line(pp_ctxt)
  if keyword = pp_ctxt.next_token
    if keyword.type == :ASM
      discard_extra_tokens_until_newline(pp_ctxt)
      return AsmLine.new(keyword)
    end
  end
  nil
end
asm_section(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 567
def asm_section(pp_ctxt)
  asm_line = asm_line(pp_ctxt)
  pp_ctxt.skip_group
  endasm_line = endasm_line(pp_ctxt)
  asm_section = AsmSection.new(asm_line, endasm_line)
  notify_asm_section_evaled(asm_section)
  asm_section
end
attach_lexer_plugin(lexer) click to toggle source
# File lib/adlint/cpp/eval.rb, line 752
def attach_lexer_plugin(lexer)
  lexer.on_block_comment_found +=
    lambda { |*args| on_block_comment_found.invoke(*args) }
  lexer.on_line_comment_found +=
    lambda { |*args| on_line_comment_found.invoke(*args) }
  lexer.on_nested_block_comment_found +=
    lambda { |*args| on_nested_block_comment_found.invoke(*args) }
  lexer.on_unterminated_block_comment +=
    lambda { |*args| handle_unterminated_block_comment(*args) }
  lexer.on_eof_newline_not_found +=
    lambda { |*args| on_eof_newline_not_found.invoke(*args) }
  lexer.on_unlexable_char_found +=
    lambda { |*args| on_unlexable_char_found.invoke(*args) }
  lexer.on_cr_at_eol_found +=
    lambda { |*args| on_cr_at_eol_found.invoke(*args) }
  lexer.on_eof_mark_at_eof_found +=
    lambda { |*args| on_eof_mark_at_eof_found.invoke(*args) }
  lexer.on_illformed_newline_escape_found +=
    lambda { |*args| on_illformed_newline_escape_found.invoke(*args) }
end
control_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 272
def control_line(pp_ctxt)
  if keyword = pp_ctxt.top_token
    case keyword.type
    when :INCLUDE
      return include_line(pp_ctxt)
    when :INCLUDE_NEXT
      return include_next_line(pp_ctxt)
    when :DEFINE
      return define_line(pp_ctxt)
    when :UNDEF
      return undef_line(pp_ctxt)
    when :LINE
      return line_line(pp_ctxt)
    when :ERROR
      return error_line(pp_ctxt)
    when :PRAGMA
      return pragma_line(pp_ctxt)
    end
  end
  nil
end
create_lexer(pp_ctxt, src) click to toggle source
# File lib/adlint/cpp/eval.rb, line 748
def create_lexer(pp_ctxt, src)
  Lexer.new(src, pp_ctxt.traits).tap { |lexer| attach_lexer_plugin(lexer) }
end
define_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 415
def define_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  unless id = pp_ctxt.next_token and id.type == :IDENTIFIER
    return nil
  end
  sym = pp_ctxt.symbol_table.create_new_symbol(MacroName, id)

  if paren = pp_ctxt.top_token and paren.type == "("
    pp_ctxt.next_token
    id_list = identifier_list(pp_ctxt)
    unless paren_or_ellipsis = pp_ctxt.next_token
      return nil
    end
    case paren_or_ellipsis.type
    when "..."
      ellipsis = paren_or_ellipsis
      if paren = pp_ctxt.top_token and paren.type == ")"
        pp_ctxt.next_token
      else
        return nil
      end
    when ")"
      ellipsis = nil
    else
      return nil
    end
    repl_list = replacement_list(pp_ctxt)
    discard_extra_tokens_until_newline(pp_ctxt)
    if ellipsis
      define_line =
        VaFunctionLikeDefineLine.new(keyword, id, id_list, repl_list, sym)
      macro = VaFunctionLikeMacro.new(define_line)
      notify_va_function_like_macro_defined(define_line, macro)
    else
      define_line =
        FunctionLikeDefineLine.new(keyword, id, id_list, repl_list, sym)
      macro = FunctionLikeMacro.new(define_line)
      notify_function_like_macro_defined(define_line, macro)
    end
  else
    repl_list = replacement_list(pp_ctxt)
    discard_extra_tokens_until_newline(pp_ctxt)
    define_line = ObjectLikeDefineLine.new(keyword, id, repl_list, sym)
    macro = ObjectLikeMacro.new(define_line)
    notify_object_like_macro_defined(define_line, macro)
  end

  pp_ctxt.macro_table.define(macro)
  define_line
end
discard_extra_tokens_until_newline(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 736
def discard_extra_tokens_until_newline(pp_ctxt)
  extra_toks = []
  while tok = pp_ctxt.next_token
    if tok.type == :NEW_LINE
      break
    else
      extra_toks.push(tok)
    end
  end
  notify_extra_tokens_found(extra_toks) unless extra_toks.empty?
end
elif_group(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 222
def elif_group(pp_ctxt)
  unless top_tok = pp_ctxt.top_token and top_tok.type == :ELIF
    return nil
  end

  if keyword = pp_ctxt.next_token
    if keyword.type == :ELIF
      unless pp_toks = pp_tokens(pp_ctxt)
        return nil
      end
      discard_extra_tokens_until_newline(pp_ctxt)
      expr = ExpressionNormalizer.normalize(pp_toks, pp_ctxt, self)
      if pp_ctxt.branch_evaluated? || expr.value == 0
        pp_ctxt.skip_group
      else
        group = group(pp_ctxt)
        pp_ctxt.branch_evaluated = true
      end
      return ElifStatement.new(keyword, expr, group)
    end
  end
  nil
end
elif_groups(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 211
def elif_groups(pp_ctxt)
  if elif_group = elif_group(pp_ctxt)
    elif_groups = ElifGroups.new.push(elif_group)
    while elif_group = elif_group(pp_ctxt)
      elif_groups.push(elif_group)
    end
    return elif_groups
  end
  nil
end
else_group(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 246
def else_group(pp_ctxt)
  if keyword = pp_ctxt.next_token
    if keyword.type == :ELSE
      discard_extra_tokens_until_newline(pp_ctxt)
      if pp_ctxt.branch_evaluated?
        pp_ctxt.skip_group
      else
        group = group(pp_ctxt)
        pp_ctxt.branch_evaluated = true
      end
      return ElseStatement.new(keyword, group)
    end
  end
  nil
end
endasm_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 586
def endasm_line(pp_ctxt)
  if keyword = pp_ctxt.next_token
    if keyword.type == :ENDASM
      discard_extra_tokens_until_newline(pp_ctxt)
      return EndasmLine.new(keyword)
    end
  end
  nil
end
endif_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 262
def endif_line(pp_ctxt)
  if keyword = pp_ctxt.next_token
    if keyword.type == :ENDIF
      discard_extra_tokens_until_newline(pp_ctxt)
      return EndifLine.new(keyword)
    end
  end
  nil
end
error_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 506
def error_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  pp_toks = pp_tokens(pp_ctxt)
  discard_extra_tokens_until_newline(pp_ctxt)
  ErrorLine.new(keyword, pp_toks)
end
group(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 87
def group(pp_ctxt)
  if group_part = group_part(pp_ctxt)
    group = Group.new.push(group_part)
    while group_part = group_part(pp_ctxt)
      group.push(group_part)
    end
    return group
  end
  nil
end
group_part(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 98
def group_part(pp_ctxt)
  if top_tok = pp_ctxt.top_token
    case top_tok.type
    when :IF, :IFDEF, :IFNDEF
      return if_section(pp_ctxt)
    when :INCLUDE, :INCLUDE_NEXT, :DEFINE, :UNDEF, :LINE, :ERROR, :PRAGMA
      return control_line(pp_ctxt)
    when :ASM
      return asm_section(pp_ctxt)
    when :NULL_DIRECTIVE
      return NullDirective.new(pp_ctxt.next_token)
    when :UNKNOWN_DIRECTIVE
      return UnknownDirective.new(pp_ctxt.next_token)
    when :TEXT_LINE
      text_line = TextLine.new(pp_ctxt.next_token)
      toks = TextLineNormalizer.normalize(text_line, pp_ctxt)
      if toks
        pp_ctxt.deferred_text_lines.clear
        toks.each do |tok|
          pp_ctxt.source.add_token(tok)
          notify_pp_token_extracted(tok)
        end
      else
        pp_ctxt.deferred_text_lines.push(text_line)
      end
      return text_line
    end
  end
  nil
end
handle_unterminated_block_comment(loc) click to toggle source
# File lib/adlint/cpp/eval.rb, line 821
def handle_unterminated_block_comment(loc)
  E(:E0016, loc)
  raise UnterminatedCommentError.new(loc, @pp_ctxt.msg_fpath,
                                     @pp_ctxt.log_fpath)
end
identifier_list(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 527
def identifier_list(pp_ctxt)
  unless id = pp_ctxt.top_token and id.type == :IDENTIFIER
    return nil
  end
  id_list = IdentifierList.new
  while tok = pp_ctxt.next_token
    if tok.type == :IDENTIFIER
      id_list.push(tok)
    end
    if comma = pp_ctxt.top_token and comma.type == ","
      pp_ctxt.next_token
    else
      break
    end
    unless id = pp_ctxt.top_token and id.type == :IDENTIFIER
      break
    end
  end
  id_list
end
if_group(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 151
def if_group(pp_ctxt)
  if keyword = pp_ctxt.top_token
    case keyword.type
    when :IF
      return if_statement(pp_ctxt)
    when :IFDEF
      return ifdef_statement(pp_ctxt)
    when :IFNDEF
      return ifndef_statement(pp_ctxt)
    end
  end
  nil
end
if_section(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 129
def if_section(pp_ctxt)
  pp_ctxt.push_branch
  if_group = if_group(pp_ctxt)

  while top_tok = pp_ctxt.top_token
    case top_tok.type
    when :ELIF
      elif_groups = elif_groups(pp_ctxt)
    when :ELSE
      else_group = else_group(pp_ctxt)
    when :ENDIF
      endif_line = endif_line(pp_ctxt)
      break
    end
  end

  E(:E0004, if_group.location) unless endif_line

  pp_ctxt.pop_branch
  IfSection.new(if_group, elif_groups, else_group, endif_line)
end
if_statement(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 165
def if_statement(pp_ctxt)
  keyword = pp_ctxt.next_token
  unless pp_toks = pp_tokens(pp_ctxt)
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)
  expr = ExpressionNormalizer.normalize(pp_toks, pp_ctxt, self)
  if expr.value == 0
    pp_ctxt.skip_group
  else
    group = group(pp_ctxt)
    pp_ctxt.branch_evaluated = true
  end
  IfStatement.new(keyword, expr, group)
end
ifdef_statement(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 181
def ifdef_statement(pp_ctxt)
  keyword = pp_ctxt.next_token
  unless id = pp_ctxt.next_token and id.type == :IDENTIFIER
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)
  if macro_defined?(pp_ctxt, id)
    group = group(pp_ctxt)
    pp_ctxt.branch_evaluated = true
  else
    pp_ctxt.skip_group
  end
  IfdefStatement.new(keyword, id, group)
end
ifndef_statement(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 196
def ifndef_statement(pp_ctxt)
  keyword = pp_ctxt.next_token
  unless id = pp_ctxt.next_token and id.type == :IDENTIFIER
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)
  if macro_defined?(pp_ctxt, id)
    pp_ctxt.skip_group
  else
    group = group(pp_ctxt)
    pp_ctxt.branch_evaluated = true
  end
  IfndefStatement.new(keyword, id, group)
end
include_first_system_header(include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 633
def include_first_system_header(include_line, pp_ctxt)
  basename = include_line.header_name.value.sub(/\A<(.*)>\z/, "\\1")
  if fpath = resolve_first_system_header(basename, pp_ctxt)
    include_system_header(fpath, include_line, pp_ctxt)
  else
    E(:E0009, include_line.location, basename)
    raise MissingSystemHeaderError.new(include_line.location, basename,
                                       pp_ctxt.msg_fpath,
                                       pp_ctxt.log_fpath)
  end
end
include_first_user_header(include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 596
def include_first_user_header(include_line, pp_ctxt)
  basename = include_line.header_name.value.sub(/\A"(.*)"\z/, "\\1")
  cur_dpath = include_line.location.fpath.dirname
  if fpath = resolve_first_user_header(basename, cur_dpath, pp_ctxt)
    include_user_header(fpath, include_line, pp_ctxt)
  else
    E(:E0010, include_line.location, basename)
    raise MissingUserHeaderError.new(include_line.location, basename,
                                     pp_ctxt.msg_fpath, pp_ctxt.log_fpath)
  end
end
include_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 294
def include_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  if header_name = pp_ctxt.top_token
    case header_name.type
    when :USR_HEADER_NAME
      return user_include_line(pp_ctxt, keyword)
    when :SYS_HEADER_NAME
      return system_include_line(pp_ctxt, keyword)
    else
      return macro_include_line(pp_ctxt, keyword)
    end
  end
  nil
end
include_next_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 309
def include_next_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  if header_name = pp_ctxt.top_token
    case header_name.type
    when :USR_HEADER_NAME
      return user_include_next_line(pp_ctxt, keyword)
    when :SYS_HEADER_NAME
      return system_include_next_line(pp_ctxt, keyword)
    else
      return macro_include_next_line(pp_ctxt, keyword)
    end
  end
  nil
end
include_next_system_header(include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 645
def include_next_system_header(include_line, pp_ctxt)
  basename = include_line.header_name.value.sub(/\A<(.*)>\z/, "\\1")
  if fpath = resolve_next_system_header(basename, pp_ctxt)
    include_system_header(fpath, include_line, pp_ctxt)
  else
    E(:E0009, include_line.location, basename)
    raise MissingSystemHeaderError.new(include_line.location, basename,
                                       pp_ctxt.msg_fpath,
                                       pp_ctxt.log_fpath)
  end
end
include_next_user_header(include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 608
def include_next_user_header(include_line, pp_ctxt)
  basename = include_line.header_name.value.sub(/\A"(.*)"\z/, "\\1")
  cur_dpath = include_line.location.fpath.dirname
  if fpath = resolve_next_user_header(basename, cur_dpath, pp_ctxt)
    include_user_header(fpath, include_line, pp_ctxt)
  else
    E(:E0010, include_line.location, basename)
    raise MissingUserHeaderError.new(include_line.location, basename,
                                     pp_ctxt.msg_fpath, pp_ctxt.log_fpath)
  end
end
include_system_header(fpath, include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 657
def include_system_header(fpath, include_line, pp_ctxt)
  unless pp_ctxt.once_set.include?(fpath)
    LOG_I("including <#{fpath}> at #{include_line.location.to_s}")
    include_line.fpath = fpath
    # FIXME: The character encoding of system headers may not be same as
    #        one of project's source files.
    sys_header =
      SystemHeader.new(fpath, pp_ctxt.traits.of_project.file_encoding,
                       include_line.location)
    pp_ctxt.push_lexer(create_lexer(pp_ctxt, sys_header))
    pp_ctxt.sources.push(sys_header)
    notify_system_header_included(include_line, sys_header)
  end
end
include_user_header(fpath, include_line, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 620
def include_user_header(fpath, include_line, pp_ctxt)
  unless pp_ctxt.once_set.include?(fpath)
    LOG_I("including \"#{fpath}\" at #{include_line.location.to_s}")
    include_line.fpath = fpath
    usr_header =
      UserHeader.new(fpath, pp_ctxt.traits.of_project.file_encoding,
                     include_line.location)
    pp_ctxt.push_lexer(create_lexer(pp_ctxt, usr_header))
    pp_ctxt.sources.push(usr_header)
    notify_user_header_included(include_line, usr_header)
  end
end
line_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 482
def line_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  pp_toks = pp_tokens(pp_ctxt)
  discard_extra_tokens_until_newline(pp_ctxt)

  # NOTE: The ISO C99 standard says;
  #
  # 6.10.4 Line control
  #
  # Semantics
  #
  # 5 A preprocessing directive of the form
  #    # line pp-tokens new-line
  #   that does not match one of the two previous forms is permitted.  The
  #   preprocessing tokens after line on the directive are processed just
  #   as in normal text (each identifier currently defined as a macro name
  #   is replaced by its replacement list of preprocessing tokens).  The
  #   directive resulting after all replacements shall match one of the two
  #   previous forms and is then processed as appropriate.
  PPTokensNormalizer.normalize(pp_toks, pp_ctxt) if pp_toks

  LineLine.new(keyword, pp_toks)
end
macro_defined?(pp_ctxt, id) click to toggle source
# File lib/adlint/cpp/eval.rb, line 727
def macro_defined?(pp_ctxt, id)
  if macro = pp_ctxt.macro_table.lookup(id.value)
    macro.define_line.mark_as_referred_by(id)
    true
  else
    false
  end
end
macro_include_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 360
def macro_include_line(pp_ctxt, keyword)
  unless pp_toks = pp_tokens(pp_ctxt)
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)
  PPTokensNormalizer.normalize(pp_toks, pp_ctxt)
  unless pp_toks.tokens.empty?
    case param = pp_toks.tokens.map { |tok| tok.value }.join
    when /\A".*"\z/
      usr_include_line = UserIncludeLine.new(
        keyword, Token.new(:USR_HEADER_NAME, param,
                           pp_toks.tokens.first.location),
        pp_ctxt.include_depth)
      include_first_user_header(usr_include_line, pp_ctxt)
      return usr_include_line
    when /\A<.*>\z/
      sys_include_line = SystemIncludeLine.new(
        keyword, Token.new(:SYS_HEADER_NAME, param,
                           pp_toks.tokens.first.location),
        pp_ctxt.include_depth)
      include_first_system_header(sys_include_line, pp_ctxt)
      return sys_include_line
    end
  end
  E(:E0017, keyword.location)
  raise IllformedIncludeDirectiveError.new(
    keyword.location, pp_ctxt.msg_fpath, pp_ctxt.log_fpath)
end
macro_include_next_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 389
def macro_include_next_line(pp_ctxt, keyword)
  unless pp_toks = pp_tokens(pp_ctxt)
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)
  PPTokensNormalizer.normalize(pp_toks, pp_ctxt)
  return nil if pp_toks.tokens.empty?
  case param = pp_toks.tokens.map { |tok| tok.value }.join
  when /\A".*"\z/
    usr_include_next_line = UserIncludeNextLine.new(
      keyword, Token.new(:USR_HEADER_NAME, param,
                         pp_toks.tokens.first.location),
      pp_ctxt.include_depth)
    include_next_user_header(usr_include_next_line, pp_ctxt)
    return usr_include_next_line
  when /\A<.*>\z/
    sys_include_next_line = SystemIncludeNextLine.new(
      keyword, Token.new(:SYS_HEADER_NAME, param,
                         pp_toks.tokens.first.location),
      pp_ctxt.include_depth)
    include_next_system_header(sys_include_next_line, pp_ctxt)
    return sys_include_next_line
  end
  nil
end
notify_asm_section_evaled(asm_section) click to toggle source
# File lib/adlint/cpp/eval.rb, line 797
def notify_asm_section_evaled(asm_section)
  on_asm_section_evaled.invoke(asm_section)
end
notify_extra_tokens_found(extra_toks) click to toggle source
# File lib/adlint/cpp/eval.rb, line 817
def notify_extra_tokens_found(extra_toks)
  on_extra_tokens_found.invoke(extra_toks)
end
notify_function_like_macro_defined(define_line, macro) click to toggle source
# File lib/adlint/cpp/eval.rb, line 785
def notify_function_like_macro_defined(define_line, macro)
  on_function_like_macro_defined.invoke(define_line, macro)
end
notify_illformed_defined_op_found(loc, no_args) click to toggle source
# File lib/adlint/cpp/eval.rb, line 809
def notify_illformed_defined_op_found(loc, no_args)
  on_illformed_defined_op_found.invoke(loc, no_args)
end
notify_macro_undefined(undef_line, macro) click to toggle source
# File lib/adlint/cpp/eval.rb, line 793
def notify_macro_undefined(undef_line, macro)
  on_macro_undefined.invoke(undef_line, macro)
end
notify_object_like_macro_defined(define_line, macro) click to toggle source
# File lib/adlint/cpp/eval.rb, line 781
def notify_object_like_macro_defined(define_line, macro)
  on_object_like_macro_defined.invoke(define_line, macro)
end
notify_pp_token_extracted(pp_tok) click to toggle source
# File lib/adlint/cpp/eval.rb, line 805
def notify_pp_token_extracted(pp_tok)
  on_pp_token_extracted.invoke(pp_tok)
end
notify_system_header_included(sys_include_line, sys_header) click to toggle source
# File lib/adlint/cpp/eval.rb, line 777
def notify_system_header_included(sys_include_line, sys_header)
  on_system_header_included.invoke(sys_include_line, sys_header)
end
notify_undefined_macro_referred(id) click to toggle source
# File lib/adlint/cpp/eval.rb, line 813
def notify_undefined_macro_referred(id)
  on_undefined_macro_referred.invoke(id)
end
notify_unknown_pragma_evaled(pragma_line) click to toggle source
# File lib/adlint/cpp/eval.rb, line 801
def notify_unknown_pragma_evaled(pragma_line)
  on_unknown_pragma_evaled.invoke(pragma_line)
end
notify_user_header_included(usr_include_line, usr_header) click to toggle source
# File lib/adlint/cpp/eval.rb, line 773
def notify_user_header_included(usr_include_line, usr_header)
  on_user_header_included.invoke(usr_include_line, usr_header)
end
notify_va_function_like_macro_defined(define_line, macro) click to toggle source
# File lib/adlint/cpp/eval.rb, line 789
def notify_va_function_like_macro_defined(define_line, macro)
  on_va_function_like_macro_defined.invoke(define_line, macro)
end
pp_tokens(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 552
def pp_tokens(pp_ctxt)
  unless pp_tok = pp_ctxt.top_token and pp_tok.type == :PP_TOKEN
    return nil
  end
  pp_toks = PPTokens.new
  while tok = pp_ctxt.top_token
    if tok.type == :PP_TOKEN
      pp_toks.push(pp_ctxt.next_token)
    else
      break
    end
  end
  pp_toks
end
pragma_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 513
def pragma_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  pp_toks = pp_tokens(pp_ctxt)
  discard_extra_tokens_until_newline(pp_ctxt)
  pragma_line = PragmaLine.new(keyword, pp_toks)
  if pp_toks and
      pp_toks.tokens.size == 1 && pp_toks.tokens.first.value == "once"
    pp_ctxt.once_set.add(keyword.location.fpath)
  else
    notify_unknown_pragma_evaled(pragma_line)
  end
  pragma_line
end
preprocessing_file(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 83
def preprocessing_file(pp_ctxt)
  PreprocessingFile.new(pp_ctxt.tunit_root_fpath, group(pp_ctxt))
end
replacement_list(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 548
def replacement_list(pp_ctxt)
  pp_tokens(pp_ctxt)
end
resolve_first_system_header(basename, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 700
def resolve_first_system_header(basename, pp_ctxt)
  resolve_system_headers(basename, 1, pp_ctxt).first
end
resolve_first_user_header(basename, cur_dpath, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 672
def resolve_first_user_header(basename, cur_dpath, pp_ctxt)
  resolve_user_headers(basename, cur_dpath, 1, pp_ctxt).first
end
resolve_next_system_header(basename, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 704
def resolve_next_system_header(basename, pp_ctxt)
  resolve_system_headers(basename, 2, pp_ctxt).last
end
resolve_next_user_header(basename, cur_dpath, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 676
def resolve_next_user_header(basename, cur_dpath, pp_ctxt)
  resolve_user_headers(basename, cur_dpath, 2, pp_ctxt).last
end
resolve_system_headers(basename, max_num, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 708
def resolve_system_headers(basename, max_num, pp_ctxt)
  search_paths  = pp_ctxt.traits.of_project.file_search_paths
  search_paths += pp_ctxt.traits.of_compiler.file_search_paths

  base_fpath = Pathname.new(basename)
  if base_fpath.absolute? && base_fpath.readable?
    [base_fpath]
  else
    resolved = []
    search_paths.each do |dpath|
      fpath = dpath.join(base_fpath)
      fpath = Pathname.new(fpath.to_s.gsub(/\\\\|\\/, "/"))
      resolved.push(fpath) if fpath.readable?
      break if resolved.size == max_num
    end
    resolved
  end
end
resolve_user_headers(basename, cur_dpath, max_num, pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 680
def resolve_user_headers(basename, cur_dpath, max_num, pp_ctxt)
  search_paths  = [cur_dpath]
  search_paths += pp_ctxt.traits.of_project.file_search_paths
  search_paths += pp_ctxt.traits.of_compiler.file_search_paths

  base_fpath = Pathname.new(basename)
  if base_fpath.absolute? && base_fpath.readable?
    [base_fpath]
  else
    resolved = []
    search_paths.each do |dpath|
      fpath = dpath.join(base_fpath)
      fpath = Pathname.new(fpath.to_s.gsub(/\\\\|\\/, "/"))
      resolved.push(fpath) if fpath.readable?
      break if resolved.size == max_num
    end
    resolved
  end
end
system_include_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 342
def system_include_line(pp_ctxt, keyword)
  header_name = pp_ctxt.next_token
  discard_extra_tokens_until_newline(pp_ctxt)
  sys_include_line =
    SystemIncludeLine.new(keyword, header_name, pp_ctxt.include_depth)
  include_first_system_header(sys_include_line, pp_ctxt)
  sys_include_line
end
system_include_next_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 351
def system_include_next_line(pp_ctxt, keyword)
  header_name = pp_ctxt.next_token
  discard_extra_tokens_until_newline(pp_ctxt)
  sys_include_next_line =
    SystemIncludeNextLine.new(keyword, header_name, pp_ctxt.include_depth)
  include_next_system_header(sys_include_next_line, pp_ctxt)
  sys_include_next_line
end
undef_line(pp_ctxt) click to toggle source
# File lib/adlint/cpp/eval.rb, line 466
def undef_line(pp_ctxt)
  keyword = pp_ctxt.next_token
  unless id = pp_ctxt.next_token and id.type == :IDENTIFIER
    return nil
  end
  discard_extra_tokens_until_newline(pp_ctxt)

  undef_line = UndefLine.new(keyword, id)
  macro = pp_ctxt.macro_table.lookup(id.value)
  # NOTE: Undefining macro may be nil if not defined.
  notify_macro_undefined(undef_line, macro)

  pp_ctxt.macro_table.undef(id.value)
  undef_line
end
user_include_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 324
def user_include_line(pp_ctxt, keyword)
  header_name = pp_ctxt.next_token
  discard_extra_tokens_until_newline(pp_ctxt)
  usr_include_line =
    UserIncludeLine.new(keyword, header_name, pp_ctxt.include_depth)
  include_first_user_header(usr_include_line, pp_ctxt)
  usr_include_line
end
user_include_next_line(pp_ctxt, keyword) click to toggle source
# File lib/adlint/cpp/eval.rb, line 333
def user_include_next_line(pp_ctxt, keyword)
  header_name = pp_ctxt.next_token
  discard_extra_tokens_until_newline(pp_ctxt)
  usr_include_next_line =
    UserIncludeNextLine.new(keyword, header_name, pp_ctxt.include_depth)
  include_next_user_header(usr_include_next_line, pp_ctxt)
  usr_include_next_line
end