@@ -14,92 +14,108 @@ function(_write_source_file _sketch_lines _file_path)
14
14
15
15
endfunction ()
16
16
17
- #=============================================================================#
18
- # Finds the best line to insert an '#include' of the platform's main header to.
19
- # The function assumes that the initial state of the given 'active index' is set to the line that
20
- # best fitted the insertion, however, it might need a bit more optimization. Why?
21
- # Because above those lines there might be a comment, or a comment block,
22
- # all of which should be taken into account in order to minimize the effect on code's readability.
23
- # _sketch_lines - List of lines-of-code belonging to the sketch.
24
- # _active_index - Index that indicates the best-not-optimized line to insert header to.
25
- # _return_var - Name of variable in parent-scope holding the return value.
26
- # Returns - Best fitted index to insert platform's main header '#include' to.
27
- #=============================================================================#
28
- function (_get_matching_header_insertion_index _sketch_lines _active_index _return_var )
17
+ macro (_setup_regex_patterns)
18
+
19
+ string (CONCAT function_prototype_pattern
20
+ " ${ARDUINO_CMAKE_FUNCTION_DECLARATION_REGEX_PATTERN} "
21
+ "| ${ARDUINO_CMAKE_FUNCTION_DEFINITION_REGEX_PATTERN} " )
22
+ string (CONCAT code_pattern
23
+ " ${ARDUINO_CMAKE_PREPROCESSOR_REGEX_PATTERN} "
24
+ "| ${function_prototype_pattern} " )
25
+
26
+ set (comment_line_pattern " \\ / \\ /" )
27
+ set (comment_block_start_pattern " \\ / \\ *" )
28
+ set (comment_block_end_pattern " \\ * \\ /" )
29
29
30
- if (${_active_index} EQUAL 0) # First line in a file will always result in the 1st index
31
- set (${_return_var} 0 PARENT_SCOPE)
32
- return ()
30
+ endmacro ()
31
+
32
+ macro (_insert_platform_header _current_line _line_index)
33
+
34
+ if ("${_current_line} " MATCHES "${ARDUINO_CMAKE_HEADER_INCLUDE_REGEX_PATTERN} " )
35
+ set (include_line "${ARDUINO_CMAKE_PLATFORM_HEADER_INCLUDE_LINE} \n " )
33
36
else ()
34
- decrement_integer(_active_index 1)
37
+ set (include_line "${ARDUINO_CMAKE_PLATFORM_HEADER_INCLUDE_LINE} \n\n " )
38
+ set (header_inclusion_block FALSE )
35
39
endif ()
36
40
37
- list (GET _sketch_lines ${_active_index} previous_loc)
41
+ list (INSERT converted_source ${_line_index} "${include_line} " )
42
+
43
+ endmacro ()
38
44
39
- if ("${previous_loc} " MATCHES "^//" ) # Simple one-line comment
40
- set (matching_index ${_active_index} )
41
- elseif ("${previous_loc} " MATCHES "\\ */$" ) # End of multi-line comment
45
+ macro (_handle_platform_header)
42
46
43
- foreach (index RANGE ${_active_index} 0)
44
- list (GET _sketch_lines ${index} multi_comment_line)
47
+ if ("${line} " MATCHES "${comment_line_pattern} " )
48
+ set (last_comment_start_index ${line_index} )
49
+ set (last_comment_end_index ${line_index} )
50
+ elseif ("${line} " MATCHES "${comment_block_start_pattern} " )
51
+ set (last_comment_start_index ${line_index} )
52
+ elseif ("${line} " MATCHES "${comment_block_end_pattern} " )
53
+ set (last_comment_end_index ${line_index} )
54
+ elseif ("${line} " MATCHES "${code_pattern} " )
45
55
46
- if ("${multi_comment_line} " MATCHES "^\\ /\\ *" ) # Start of multi-line comment
47
- set (matching_index ${index} )
48
- break ()
49
- endif ()
50
- endforeach ()
56
+ set (header_inclusion_block TRUE )
57
+
58
+ # Calculate difference between current line index and last comment's end index
59
+ math (EXPR line_index_diff "${line_index} - ${last_comment_end_index} " )
60
+
61
+ # Comment ends above current line, any lines should be inserted above
62
+ if (${line_index_diff} EQUAL 1)
63
+ _insert_platform_header("${line} " ${last_comment_start_index} )
64
+ else ()
65
+ _insert_platform_header("${line} " ${line_index} )
66
+ endif ()
67
+
68
+ set (header_inserted TRUE )
51
69
52
- else () # Previous line isn't a comment - Return original index
53
- increment_integer(_active_index 1)
54
- set (matching_index ${_active_index} )
55
70
endif ()
56
71
57
- set ( ${_return_var} ${matching_index} PARENT_SCOPE )
72
+ endmacro ( )
58
73
59
- endfunction ( )
74
+ macro (_handle_prototype_generation )
60
75
61
- #=============================================================================#
62
- # Inline macro which handles the process of inserting a line including the platform header.
63
- # _sketch_lines - List of code lines read from the converted sketch file.
64
- # _insertion_line_index - Index of a code line at which the header should be inserted
65
- #=============================================================================#
66
- macro (_insert_line _inserted_line _sketch_lines _insertion_line_index)
76
+ if (NOT "${line} " MATCHES "${ARDUINO_CMAKE_HEADER_INCLUDE_REGEX_PATTERN} " )
77
+ if (NOT "${line} " STREQUAL "" ) # Not a newline
67
78
68
- _get_matching_header_insertion_index("${_sketch_lines} " ${_insertion_line_index} header_index)
79
+ if (NOT header_inclusion_block)
80
+ # Insert a newline to separate prototypes from the rest of the code
81
+ list (INSERT converted_source ${line_index} "\n " )
82
+ endif ()
69
83
70
- if (${header_index} LESS ${_insertion_line_index} )
71
- set (formatted_include_line ${_inserted_line} "\n\n " )
72
- elseif (${header_index} EQUAL 0)
73
- set (formatted_include_line ${_inserted_line} "\n " )
74
- else ()
75
- set (formatted_include_line "\n " ${_inserted_line} )
84
+ foreach (prototype ${_sketch_prototypes} )
85
+ # Add missing semicolon to make a definition a declaration and escape it
86
+ escape_semicolon_in_string("${prototype} ;" escaped_prototype)
87
+ list (INSERT converted_source ${line_index} "${escaped_prototype} \n " )
88
+ endforeach ()
89
+
90
+ if (header_inclusion_block)
91
+ list (INSERT converted_source ${line_index} "\n // Prototypes generated by Arduino-CMake\n " )
92
+ else ()
93
+ list (INSERT converted_source ${line_index} "// Prototypes generated by Arduino-CMake\n " )
94
+ endif ()
95
+
96
+ set (prototypes_inserted TRUE )
97
+ set (header_inclusion_block FALSE )
76
98
77
- if (${header_index} GREATER_EQUAL ${_insertion_line_index} )
78
- decrement_integer(header_index 1)
79
- string (APPEND formatted_include_line "\n " )
80
99
endif ()
81
100
endif ()
82
101
83
- list (INSERT converted_source ${header_index} ${formatted_include_line} )
84
-
85
102
endmacro ()
86
103
87
- macro (_insert_prototypes _prototypes _sketch_lines _insertion_line_index )
104
+ macro (_handle_simple_lines )
88
105
89
- foreach (prototype ${_prototypes} )
90
- # Add semicolon ';' to make it a declaration
91
- escape_semicolon_in_string("${prototype} ;" formatted_prototype)
92
-
93
- _insert_line("${formatted_prototype} " "${sketch_lines} " ${line_index} )
94
- increment_integer(_insertion_line_index 1)
95
- endforeach ()
106
+ if ("${line} " STREQUAL "" )
107
+ list (APPEND converted_source "\n " )
108
+ else ()
109
+ escape_semicolon_in_string("${line} " formatted_line)
110
+ list (APPEND converted_source "${formatted_line} \n " )
111
+ endif ()
96
112
97
113
endmacro ()
98
114
99
115
#=============================================================================#
100
- # Converts the given sketch file into a valid 'cpp' source file under the project's working dir.
101
- # During the conversion process the platform's main header file is inserted to the source file
102
- # since it's critical for it to include it - Something that doesn't happen in "Standard" sketches .
116
+ # Converts the given sketch file into a valid '. cpp' source file under the project's working dir.
117
+ # During the conversion process the platform's main header file is inserted to the source file,
118
+ # as well as any given prototypes, found earlier through a function def-dec matching process .
103
119
# _sketch_file - Full path to the original sketch file (Read from).
104
120
# _converted_source_path - Full path to the converted target source file (Written to).
105
121
# _sketch_prototypes - List of prototypes to genereate, i.e. function definitions without a declaration.
@@ -108,38 +124,28 @@ function(convert_sketch_to_source _sketch_file _converted_source_path _sketch_pr
108
124
109
125
file (STRINGS "${_sketch_file} " sketch_lines)
110
126
111
- set (function_prototype_pattern
112
- "${ARDUINO_CMAKE_FUNCTION_DECLARATION_REGEX_PATTERN} |${ARDUINO_CMAKE_FUNCTION_DEFINITION_REGEX_PATTERN} " )
113
- set (header_insert_pattern
114
- "${ARDUINO_CMAKE_HEADER_INCLUDE_REGEX_PATTERN} |${function_prototype_pattern} " )
127
+ _setup_regex_patterns()
115
128
116
129
set (header_inserted FALSE )
117
130
set (prototypes_inserted FALSE )
131
+ set (header_inclusion_block FALSE )
132
+
133
+ set (last_comment_start_index 0)
134
+ set (last_comment_end_index 0)
118
135
119
136
list_max_index("${sketch_lines} " lines_count)
120
- #[[list(LENGTH sketch_lines lines_count)
121
- decrement_integer(lines_count 1)]]
122
137
123
138
foreach (line_index RANGE ${lines_count} )
124
139
125
140
list (GET sketch_lines ${line_index} line)
126
141
127
- if (NOT ${header_inserted} )
128
- if ("${line} " MATCHES "${header_insert_pattern} " )
129
- _insert_line("${ARDUINO_CMAKE_PLATFORM_HEADER_INCLUDE_LINE} " "${sketch_lines} " ${line_index} )
130
- set (header_inserted TRUE )
131
- endif ()
132
- elseif (NOT ${prototypes_inserted} AND "${line} " MATCHES "${function_prototype_pattern} " )
133
- _insert_prototypes("${_sketch_prototypes} " "${sketch_lines} " ${line_index} )
134
- set (prototypes_inserted TRUE )
142
+ if (NOT header_inserted)
143
+ _handle_platform_header()
144
+ elseif (NOT prototypes_inserted)
145
+ _handle_prototype_generation()
135
146
endif ()
136
147
137
- if ("${line} " STREQUAL "" )
138
- list (APPEND converted_source "\n " )
139
- else ()
140
- escape_semicolon_in_string("${line} " formatted_line)
141
- list (APPEND converted_source "${formatted_line} \n " )
142
- endif ()
148
+ _handle_simple_lines()
143
149
144
150
endforeach ()
145
151
0 commit comments