16
16
package preprocessor
17
17
18
18
import (
19
+ "bytes"
19
20
"context"
20
21
"fmt"
21
22
"strconv"
22
23
"strings"
23
24
25
+ "github.com/arduino/arduino-cli/arduino/builder"
24
26
"github.com/arduino/arduino-cli/arduino/builder/cpp"
25
27
"github.com/arduino/arduino-cli/arduino/builder/preprocessor/ctags"
26
28
"github.com/arduino/arduino-cli/arduino/sketch"
@@ -34,30 +36,73 @@ import (
34
36
var tr = i18n .Tr
35
37
var DebugPreprocessor bool
36
38
37
- func CTags (sourceFile * paths.Path , targetFile * paths.Path , sketch * sketch.Sketch , lineOffset int , buildProperties * properties.Map ) ([]byte , error ) {
38
- ctagsOutput , ctagsStdErr , err := RunCTags (sourceFile , buildProperties )
39
+ func PreprocessSketchWithCtags (sketch * sketch.Sketch , buildPath * paths.Path , includes paths.PathList , lineOffset int , buildProperties * properties.Map , onlyUpdateCompilationDatabase bool ) ([]byte , []byte , error ) {
40
+ // Create a temporary working directory
41
+ tmpDir , err := paths .MkTempDir ("" , "" )
39
42
if err != nil {
40
- return ctagsStdErr , err
43
+ return nil , nil , err
44
+ }
45
+ defer tmpDir .RemoveAll ()
46
+ ctagsTarget := tmpDir .Join ("sketch_merged.cpp" )
47
+
48
+ normalOutput := & bytes.Buffer {}
49
+ verboseOutput := & bytes.Buffer {}
50
+
51
+ // Run GCC preprocessor
52
+ sourceFile := buildPath .Join ("sketch" , sketch .MainFile .Base ()+ ".cpp" )
53
+ gccStdout , gccStderr , err := GCC (sourceFile , ctagsTarget , includes , buildProperties )
54
+ verboseOutput .Write (gccStdout )
55
+ verboseOutput .Write (gccStderr )
56
+ normalOutput .Write (gccStderr )
57
+ if err != nil {
58
+ if ! onlyUpdateCompilationDatabase {
59
+ return normalOutput .Bytes (), verboseOutput .Bytes (), errors .WithStack (err )
60
+ }
61
+
62
+ // Do not bail out if we are generating the compile commands database
63
+ normalOutput .WriteString (fmt .Sprintf ("%s: %s" ,
64
+ tr ("An error occurred adding prototypes" ),
65
+ tr ("the compilation database may be incomplete or inaccurate" )))
66
+ if err := sourceFile .CopyTo (ctagsTarget ); err != nil {
67
+ return normalOutput .Bytes (), verboseOutput .Bytes (), errors .WithStack (err )
68
+ }
69
+ }
70
+
71
+ if src , err := ctagsTarget .ReadFile (); err != nil {
72
+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
73
+ } else {
74
+ filteredSource := builder .FilterSketchSource (sketch , bytes .NewReader (src ), false )
75
+ if err := ctagsTarget .WriteFile ([]byte (filteredSource )); err != nil {
76
+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
77
+ }
78
+ }
79
+
80
+ // Run CTags on gcc-preprocessed source
81
+ ctagsOutput , ctagsStdErr , err := RunCTags (ctagsTarget , buildProperties )
82
+ verboseOutput .Write (ctagsStdErr )
83
+ if err != nil {
84
+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
41
85
}
42
86
43
- // func PrototypesAdder(sketch *sketch.Sketch, source string, ctagsStdout []byte, lineOffset int) string {
87
+ // Parse CTags output
44
88
parser := & ctags.CTagsParser {}
45
89
prototypes , firstFunctionLine := parser .Parse (ctagsOutput , sketch .MainFile )
46
90
if firstFunctionLine == - 1 {
47
91
firstFunctionLine = 0
48
92
}
49
93
94
+ // Add prototypes to the original sketch source
50
95
var source string
51
- if sourceData , err := targetFile .ReadFile (); err != nil {
52
- return nil , err
96
+ if sourceData , err := sourceFile .ReadFile (); err != nil {
97
+ return normalOutput . Bytes (), verboseOutput . Bytes () , err
53
98
} else {
54
99
source = string (sourceData )
55
100
}
56
101
source = strings .Replace (source , "\r \n " , "\n " , - 1 )
57
102
source = strings .Replace (source , "\r " , "\n " , - 1 )
58
103
sourceRows := strings .Split (source , "\n " )
59
104
if isFirstFunctionOutsideOfSource (firstFunctionLine , sourceRows ) {
60
- return nil , nil
105
+ return normalOutput . Bytes (), verboseOutput . Bytes () , nil
61
106
}
62
107
63
108
insertionLine := firstFunctionLine + lineOffset - 1
@@ -81,8 +126,9 @@ func CTags(sourceFile *paths.Path, targetFile *paths.Path, sketch *sketch.Sketch
81
126
fmt .Println ("#END OF PREPROCESSED SOURCE" )
82
127
}
83
128
84
- err = targetFile .WriteFile ([]byte (preprocessedSource ))
85
- return ctagsStdErr , err
129
+ // Write back arduino-preprocess output to the sourceFile
130
+ err = sourceFile .WriteFile ([]byte (preprocessedSource ))
131
+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
86
132
}
87
133
88
134
func composePrototypeSection (line int , prototypes []* ctags.Prototype ) string {
0 commit comments