Class: PreprocessinatorExtractor
- Defined in:
- lib/ceedling/preprocessinator_extractor.rb
Instance Method Summary collapse
-
#extract_file_as_array_from_expansion(input, filepath) ⇒ Object
‘input` must have the interface of IO – StringIO for testing or File in typical use.
-
#extract_file_as_string_from_expansion(input, filepath) ⇒ Object
Simple variation of preceding that returns file contents as single string.
-
#extract_include_guard(file_contents) ⇒ Object
Find include guard in file contents as string.
-
#extract_macro_defs(file_contents, include_guard) ⇒ Object
Extract all macro definitions as a list from a file as string.
-
#extract_pragmas(file_contents) ⇒ Object
Extract all pragmas as a list from a file as string.
-
#extract_test_directive_macro_calls(file_contents) ⇒ Object
Extract all test directive macros as a list from a file as string.
Instance Method Details
#extract_file_as_array_from_expansion(input, filepath) ⇒ Object
‘input` must have the interface of IO – StringIO for testing or File in typical use
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 78 def extract_file_as_array_from_expansion(input, filepath) # Iterate through all lines and alternate between extract and ignore modes. # All lines between a '#' line containing the file name of our filepath and the # next '#' line should be extracted. # # Notes: # 1. Successive blocks can all be from the same source text file without a different, intervening '#' line. # Multiple back-to-back blocks could all begin with '# 99 "path/file.c"'. # 2. The first line of the file could start a text block we care about. # 3. End of file could end a text block. base_name = File.basename( filepath ) # Preprocessor output blocks take the form of '# <digits> <text> [optional digits]' directive = /^# \d+ \"/ # Preprocessor output blocks for the file we care about take the form of '# <digits> "path/filename.ext" [optional digits]' marker = /^# \d+ \".*#{Regexp.escape(base_name)}\"/ # Boolean to ping pong between line-by-line extract/ignore extract = false lines = [] # Use `each_line()` instead of `readlines()` (chomp removes newlines). # `each_line()` processes the IO buffer one line at a time instead of ingesting lines in an array. # At large buffer sizes needed for potentially lengthy preprocessor output this is far more memory efficient and faster. input.each_line( chomp:true ) do |line| # Clean up any oddball characters in an otherwise ASCII document = { :invalid => :replace, # Replace invalid byte sequences :undef => :replace, # Replace anything not defined in ASCII :replace => '', # Use a blank for those replacements :universal_newline => true # Always break lines with \n } line = line.encode("ASCII", **).encode('UTF-8') # Handle extraction if the line is not a preprocessor directive if extract and not line =~ directive # Strip a line so we can omit useless blank lines _line = line.strip() # Restore text with left-side whitespace if previous stripping left some text _line = line.rstrip() if !_line.empty? lines << _line # Otherwise the line contained a preprocessor directive; drop out of extract mode else extract = false end # Enter extract mode if the line is a preprocessor directive with filename of interest extract = true if line =~ marker end return lines end |
#extract_file_as_string_from_expansion(input, filepath) ⇒ Object
Simple variation of preceding that returns file contents as single string
136 137 138 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 136 def extract_file_as_string_from_expansion(input, filepath) return extract_file_as_array_from_expansion(input, filepath).join( "\n" ) end |
#extract_include_guard(file_contents) ⇒ Object
Find include guard in file contents as string
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 161 def extract_include_guard(file_contents) # Look for first occurrence of #ifndef <sring> followed by #define <string> regex = /#\s*ifndef\s+(\w+)(?:\s*\n)+\s*#\s*define\s+(\w+)/ matches = file_contents.match( regex ) # Return if no match results return nil if matches.nil? # Return if match results are not expected size return nil if matches.size != 3 # Return if #ifndef <string> does not match #define <string> return nil if matches[1] != matches[2] # Return string in common return matches[1] end |
#extract_macro_defs(file_contents, include_guard) ⇒ Object
Extract all macro definitions as a list from a file as string
181 182 183 184 185 186 187 188 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 181 def extract_macro_defs(file_contents, include_guard) macro_definitions = extract_multiline_directives( file_contents, 'define' ) # Remove an include guard if provided macro_definitions.reject! {|macro| macro.include?( include_guard ) } if !include_guard.nil? return macro_definitions end |
#extract_pragmas(file_contents) ⇒ Object
Extract all pragmas as a list from a file as string
155 156 157 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 155 def extract_pragmas(file_contents) return extract_multiline_directives( file_contents, 'pragma' ) end |
#extract_test_directive_macro_calls(file_contents) ⇒ Object
Extract all test directive macros as a list from a file as string
142 143 144 145 146 147 148 149 150 151 |
# File 'lib/ceedling/preprocessinator_extractor.rb', line 142 def extract_test_directive_macro_calls(file_contents) # Look for TEST_SOURCE_FILE("...") and TEST_INCLUDE_PATH("...") in a string (i.e. a file's contents as a string) regexes = [ /#{UNITY_TEST_SOURCE_FILE}.+?"\)/, /#{UNITY_TEST_INCLUDE_PATH}.+?"\)/ ] return extract_tokens_by_regex_list( file_contents, *regexes ) end |