@@ -18,16 +18,111 @@ package preprocessor
18
18
import (
19
19
"context"
20
20
"fmt"
21
+ "strconv"
21
22
"strings"
22
23
24
+ "github.com/arduino/arduino-cli/arduino/builder/preprocessor/ctags"
25
+ "github.com/arduino/arduino-cli/arduino/sketch"
23
26
"github.com/arduino/arduino-cli/executils"
24
27
"github.com/arduino/arduino-cli/i18n"
28
+ "github.com/arduino/arduino-cli/legacy/builder/utils"
25
29
"github.com/arduino/go-paths-helper"
26
30
"github.com/arduino/go-properties-orderedmap"
27
31
"github.com/pkg/errors"
28
32
)
29
33
30
34
var tr = i18n .Tr
35
+ var DebugPreprocessor bool
36
+
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
+ if err != nil {
40
+ return ctagsStdErr , err
41
+ }
42
+
43
+ // func PrototypesAdder(sketch *sketch.Sketch, source string, ctagsStdout []byte, lineOffset int) string {
44
+ parser := & ctags.CTagsParser {}
45
+ prototypes , firstFunctionLine := parser .Parse (ctagsOutput , sketch .MainFile )
46
+ if firstFunctionLine == - 1 {
47
+ firstFunctionLine = 0
48
+ }
49
+
50
+ var source string
51
+ if sourceData , err := targetFile .ReadFile (); err != nil {
52
+ return nil , err
53
+ } else {
54
+ source = string (sourceData )
55
+ }
56
+ source = strings .Replace (source , "\r \n " , "\n " , - 1 )
57
+ source = strings .Replace (source , "\r " , "\n " , - 1 )
58
+ sourceRows := strings .Split (source , "\n " )
59
+ if isFirstFunctionOutsideOfSource (firstFunctionLine , sourceRows ) {
60
+ return nil , nil
61
+ }
62
+
63
+ insertionLine := firstFunctionLine + lineOffset - 1
64
+ firstFunctionChar := len (strings .Join (sourceRows [:insertionLine ], "\n " )) + 1
65
+ prototypeSection := composePrototypeSection (firstFunctionLine , prototypes )
66
+ preprocessedSource := source [:firstFunctionChar ] + prototypeSection + source [firstFunctionChar :]
67
+
68
+ if DebugPreprocessor {
69
+ fmt .Println ("#PREPROCESSED SOURCE" )
70
+ prototypesRows := strings .Split (prototypeSection , "\n " )
71
+ prototypesRows = prototypesRows [:len (prototypesRows )- 1 ]
72
+ for i := 0 ; i < len (sourceRows )+ len (prototypesRows ); i ++ {
73
+ if i < insertionLine {
74
+ fmt .Printf (" |%s\n " , sourceRows [i ])
75
+ } else if i < insertionLine + len (prototypesRows ) {
76
+ fmt .Printf ("PRO|%s\n " , prototypesRows [i - insertionLine ])
77
+ } else {
78
+ fmt .Printf (" |%s\n " , sourceRows [i - len (prototypesRows )])
79
+ }
80
+ }
81
+ fmt .Println ("#END OF PREPROCESSED SOURCE" )
82
+ }
83
+
84
+ err = targetFile .WriteFile ([]byte (preprocessedSource ))
85
+ return ctagsStdErr , err
86
+ }
87
+
88
+ func composePrototypeSection (line int , prototypes []* ctags.Prototype ) string {
89
+ if len (prototypes ) == 0 {
90
+ return ""
91
+ }
92
+
93
+ str := joinPrototypes (prototypes )
94
+ str += "\n #line "
95
+ str += strconv .Itoa (line )
96
+ str += " " + utils .QuoteCppString (prototypes [0 ].File )
97
+ str += "\n "
98
+
99
+ return str
100
+ }
101
+
102
+ func joinPrototypes (prototypes []* ctags.Prototype ) string {
103
+ prototypesSlice := []string {}
104
+ for _ , proto := range prototypes {
105
+ if signatureContainsaDefaultArg (proto ) {
106
+ continue
107
+ }
108
+ prototypesSlice = append (prototypesSlice , "#line " + strconv .Itoa (proto .Line )+ " " + utils .QuoteCppString (proto .File ))
109
+ prototypeParts := []string {}
110
+ if proto .Modifiers != "" {
111
+ prototypeParts = append (prototypeParts , proto .Modifiers )
112
+ }
113
+ prototypeParts = append (prototypeParts , proto .Prototype )
114
+ prototypesSlice = append (prototypesSlice , strings .Join (prototypeParts , " " ))
115
+ }
116
+ return strings .Join (prototypesSlice , "\n " )
117
+ }
118
+
119
+ func signatureContainsaDefaultArg (proto * ctags.Prototype ) bool {
120
+ return strings .Contains (proto .Prototype , "=" )
121
+ }
122
+
123
+ func isFirstFunctionOutsideOfSource (firstFunctionLine int , sourceRows []string ) bool {
124
+ return firstFunctionLine > len (sourceRows )- 1
125
+ }
31
126
32
127
func RunCTags (sourceFile * paths.Path , buildProperties * properties.Map ) ([]byte , []byte , error ) {
33
128
ctagsBuildProperties := properties .NewMap ()
0 commit comments