diff --git a/src/arduino.cc/builder/compare_prototypes_from_source_and_preproc_source.go b/src/arduino.cc/builder/compare_prototypes_from_source_and_preproc_source.go deleted file mode 100644 index 0f19b7f1..00000000 --- a/src/arduino.cc/builder/compare_prototypes_from_source_and_preproc_source.go +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Arduino Builder. - * - * Arduino Builder is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As a special exception, you may use this file as part of a free software - * library without restriction. Specifically, if other files instantiate - * templates or use macros or inline functions from this file, or you compile - * this file and link it with other files to produce an executable, this - * file does not by itself cause the resulting executable to be covered by - * the GNU General Public License. This exception does not however - * invalidate any other reasons why the executable file might be covered by - * the GNU General Public License. - * - * Copyright 2015 Arduino LLC (http://www.arduino.cc/) - */ - -package builder - -// XXX: Obsolete? - -import "arduino.cc/builder/types" - -type ComparePrototypesFromSourceAndPreprocSource struct{} - -func (s *ComparePrototypesFromSourceAndPreprocSource) Run(ctx *types.Context) error { - ctagsOfSource := ctx.CTagsOfSource - ctagsOfPreprocSource := ctx.CTagsOfPreprocessedSource - - actualCTags := []*types.CTag{} - for _, ctagOfPreprocSource := range ctagsOfPreprocSource { - if sliceContainsCTag(ctagsOfSource, ctagOfPreprocSource) { - actualCTags = append(actualCTags, ctagOfPreprocSource) - } - } - - ctx.CTagsCollected = actualCTags - - return nil -} - -func sliceContainsCTag(slice []*types.CTag, target *types.CTag) bool { - for _, value := range slice { - if value.FunctionName == target.FunctionName { - return true - } - } - return false -} diff --git a/src/arduino.cc/builder/container_add_prototypes.go b/src/arduino.cc/builder/container_add_prototypes.go index 28ba1645..8a138b44 100644 --- a/src/arduino.cc/builder/container_add_prototypes.go +++ b/src/arduino.cc/builder/container_add_prototypes.go @@ -42,10 +42,10 @@ func (s *ContainerAddPrototypes) Run(ctx *types.Context) error { commands := []types.Command{ &GCCPreprocRunner{TargetFileName: constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E}, &ReadFileAndStoreInContext{Target: &ctx.SourceGccMinusE}, + &FilterSketchSource{Source: &ctx.SourceGccMinusE}, &CTagsTargetFileSaver{Source: &ctx.SourceGccMinusE, TargetFileName: constants.FILE_CTAGS_TARGET_FOR_GCC_MINUS_E}, &ctags.CTagsRunner{}, &ctags.CTagsParser{}, - &CollectCTagsFromSketchFiles{}, &ctags.CTagsToPrototypes{}, &PrototypesAdder{}, &SketchSaver{}, diff --git a/src/arduino.cc/builder/ctags/ctags_parser.go b/src/arduino.cc/builder/ctags/ctags_parser.go index 55497155..3926c8ff 100644 --- a/src/arduino.cc/builder/ctags/ctags_parser.go +++ b/src/arduino.cc/builder/ctags/ctags_parser.go @@ -229,7 +229,14 @@ func parseTag(row string) *types.CTag { parts := strings.Split(row, "\t") tag.FunctionName = parts[0] - tag.Filename = parts[1] + // This unescapes any backslashes in the filename. These + // filenames that ctags outputs originate from the line markers + // in the source, as generated by gcc. gcc escapes both + // backslashes and double quotes, but ctags ignores any escaping + // and just cuts off the filename at the first double quote it + // sees. This means any backslashes are still escaped, and need + // to be unescape, and any quotes will just break the build. + tag.Filename = strings.Replace(parts[1], "\\\\", "\\", -1) parts = parts[2:] diff --git a/src/arduino.cc/builder/ctags/ctags_to_prototypes.go b/src/arduino.cc/builder/ctags/ctags_to_prototypes.go index c6528fec..954cb424 100644 --- a/src/arduino.cc/builder/ctags/ctags_to_prototypes.go +++ b/src/arduino.cc/builder/ctags/ctags_to_prototypes.go @@ -37,7 +37,7 @@ import ( type CTagsToPrototypes struct{} func (s *CTagsToPrototypes) Run(ctx *types.Context) error { - tags := ctx.CTagsCollected + tags := ctx.CTagsOfPreprocessedSource lineWhereToInsertPrototypes := findLineWhereToInsertPrototypes(tags) if lineWhereToInsertPrototypes != -1 { diff --git a/src/arduino.cc/builder/collect_ctags_from_sketch_files.go b/src/arduino.cc/builder/filter_sketch_source.go similarity index 51% rename from src/arduino.cc/builder/collect_ctags_from_sketch_files.go rename to src/arduino.cc/builder/filter_sketch_source.go index aee6935c..34e5aa47 100644 --- a/src/arduino.cc/builder/collect_ctags_from_sketch_files.go +++ b/src/arduino.cc/builder/filter_sketch_source.go @@ -32,31 +32,68 @@ package builder import ( "arduino.cc/builder/types" "arduino.cc/builder/utils" + "strconv" "strings" ) -type CollectCTagsFromSketchFiles struct{} +type FilterSketchSource struct { + Source *string +} -func (s *CollectCTagsFromSketchFiles) Run(ctx *types.Context) error { - sketchFileNames := collectSketchFileNamesFrom(ctx.Sketch) +func (s *FilterSketchSource) Run(ctx *types.Context) error { + lines := strings.Split(*s.Source, "\n") - allCtags := ctx.CTagsOfPreprocessedSource - ctagsOfSketch := []*types.CTag{} - for _, ctag := range allCtags { - if utils.SliceContains(sketchFileNames, strings.Replace(ctag.Filename, "\\\\", "\\", -1)) { - ctagsOfSketch = append(ctagsOfSketch, ctag) - } + fileNames := []string{ctx.Sketch.MainFile.Name} + for _, file := range ctx.Sketch.OtherSketchFiles { + fileNames = append(fileNames, file.Name) } - ctx.CTagsCollected = ctagsOfSketch + inSketch := false + filtered := "" + + for _, line := range lines { + filename := parseLineMarker(line) + if filename != "" { + inSketch = utils.SliceContains(fileNames, filename) + } + + if inSketch { + filtered += line + "\n" + } + } + *s.Source = filtered return nil } -func collectSketchFileNamesFrom(sketch *types.Sketch) []string { - fileNames := []string{sketch.MainFile.Name} - for _, file := range sketch.OtherSketchFiles { - fileNames = append(fileNames, file.Name) +// Parses the given line as a gcc line marker and returns the contained +// filename. +func parseLineMarker(line string) string { + // A line marker contains the line number and filename and looks like: + // # 123 /path/to/file.cpp + // It can be followed by zero or more flag number that indicate the + // preprocessor state and can be ignored. + // For exact details on this format, see: + // https://github.com/gcc-mirror/gcc/blob/edd716b6b1caa1a5cb320a8cd7f626f30198e098/gcc/c-family/c-ppoutput.c#L413-L415 + + split := strings.SplitN(line, " ", 3) + if len(split) < 2 || split[0] != "#" { + return "" + } + + _, err := strconv.Atoi(split[1]) + if err != nil { + return "" } - return fileNames + + // If we get here, we found a # followed by a line number, so + // assume this is a line marker and see if the rest of the line + // starts with a string containing the filename + str, rest, ok := utils.ParseCppString(split[2]) + + if ok && (rest == "" || rest[0] == ' ') { + return str + } + return "" } + diff --git a/src/arduino.cc/builder/prototypes_adder.go b/src/arduino.cc/builder/prototypes_adder.go index 9e05b109..d80b656d 100644 --- a/src/arduino.cc/builder/prototypes_adder.go +++ b/src/arduino.cc/builder/prototypes_adder.go @@ -32,6 +32,7 @@ package builder import ( "arduino.cc/builder/constants" "arduino.cc/builder/types" + "arduino.cc/builder/utils" "fmt" "strconv" "strings" @@ -87,7 +88,7 @@ func composePrototypeSection(line int, prototypes []*types.Prototype) string { str := joinPrototypes(prototypes) str += "\n#line " str += strconv.Itoa(line) - str += " \"" + prototypes[0].File + "\"" + str += " " + utils.QuoteCppString(prototypes[0].File) str += "\n" return str @@ -99,7 +100,7 @@ func joinPrototypes(prototypes []*types.Prototype) string { if signatureContainsaDefaultArg(proto) { continue } - prototypesSlice = append(prototypesSlice, "#line "+strconv.Itoa(proto.Line)+" \""+proto.File+"\"") + prototypesSlice = append(prototypesSlice, "#line "+strconv.Itoa(proto.Line)+" "+utils.QuoteCppString(proto.File)) prototypeParts := []string{} if proto.Modifiers != "" { prototypeParts = append(prototypeParts, proto.Modifiers) diff --git a/src/arduino.cc/builder/sketch_source_merger.go b/src/arduino.cc/builder/sketch_source_merger.go index 36c7c7a9..3ad088db 100644 --- a/src/arduino.cc/builder/sketch_source_merger.go +++ b/src/arduino.cc/builder/sketch_source_merger.go @@ -32,8 +32,8 @@ package builder import ( "arduino.cc/builder/types" + "arduino.cc/builder/utils" "regexp" - "strings" ) type SketchSourceMerger struct{} @@ -47,7 +47,7 @@ func (s *SketchSourceMerger) Run(ctx *types.Context) error { includeSection += "#include \n" lineOffset++ } - includeSection += "#line 1 \"" + strings.Replace((&sketch.MainFile).Name, "\\", "\\\\", -1) + "\"\n" + includeSection += "#line 1 " + utils.QuoteCppString(sketch.MainFile.Name) + "\n" lineOffset++ ctx.IncludeSection = includeSection @@ -73,7 +73,7 @@ func sketchIncludesArduinoH(sketch *types.SketchFile) bool { } func addSourceWrappedWithLineDirective(sketch *types.SketchFile) string { - source := "#line 1 \"" + strings.Replace(sketch.Name, "\\", "\\\\", -1) + "\"\n" + source := "#line 1 " + utils.QuoteCppString(sketch.Name) + "\n" source += sketch.Source source += "\n" diff --git a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go index ca1a2a6b..d379d97c 100644 --- a/src/arduino.cc/builder/test/ctags_to_prototypes_test.go +++ b/src/arduino.cc/builder/test/ctags_to_prototypes_test.go @@ -38,13 +38,6 @@ import ( "testing" ) -type CollectCtagsFromPreprocSource struct{} - -func (*CollectCtagsFromPreprocSource) Run(ctx *types.Context) error { - ctx.CTagsCollected = ctx.CTagsOfPreprocessedSource - return nil -} - func TestCTagsToPrototypesShouldListPrototypes(t *testing.T) { ctx := &types.Context{} @@ -55,7 +48,6 @@ func TestCTagsToPrototypesShouldListPrototypes(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -87,7 +79,6 @@ func TestCTagsToPrototypesShouldListTemplates(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -117,7 +108,6 @@ func TestCTagsToPrototypesShouldListTemplates2(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -148,7 +138,6 @@ func TestCTagsToPrototypesShouldDealWithClasses(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -174,7 +163,6 @@ func TestCTagsToPrototypesShouldDealWithStructs(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -204,7 +192,6 @@ func TestCTagsToPrototypesShouldDealWithMacros(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -236,7 +223,6 @@ func TestCTagsToPrototypesShouldDealFunctionWithDifferentSignatures(t *testing.T commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -264,7 +250,6 @@ func TestCTagsToPrototypesClassMembersAreFilteredOut(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -293,7 +278,6 @@ func TestCTagsToPrototypesStructWithFunctions(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -322,7 +306,6 @@ func TestCTagsToPrototypesDefaultArguments(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -352,7 +335,6 @@ func TestCTagsToPrototypesNamespace(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -381,7 +363,6 @@ func TestCTagsToPrototypesStatic(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -412,7 +393,6 @@ func TestCTagsToPrototypesFunctionPointer(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } @@ -442,7 +422,6 @@ func TestCTagsToPrototypesFunctionPointers(t *testing.T) { commands := []types.Command{ &ctags.CTagsParser{}, - &CollectCtagsFromPreprocSource{}, &ctags.CTagsToPrototypes{}, } diff --git a/src/arduino.cc/builder/test/helper.go b/src/arduino.cc/builder/test/helper.go index 3e83d337..cd6e2b3d 100644 --- a/src/arduino.cc/builder/test/helper.go +++ b/src/arduino.cc/builder/test/helper.go @@ -33,22 +33,20 @@ package test import ( "arduino.cc/builder/constants" "arduino.cc/builder/types" + "arduino.cc/builder/utils" "bytes" "fmt" "github.com/go-errors/errors" "github.com/stretchr/testify/assert" "io/ioutil" "path/filepath" - "strings" "testing" "text/template" ) func LoadAndInterpolate(t *testing.T, filename string, ctx *types.Context) string { funcsMap := template.FuncMap{ - "EscapeBackSlashes": func(s string) string { - return strings.Replace(s, "\\", "\\\\", -1) - }, + "QuoteCppString": utils.QuoteCppString, } tpl, err := template.New(filepath.Base(filename)).Funcs(funcsMap).ParseFiles(filename) diff --git a/src/arduino.cc/builder/test/prototypes_adder_test.go b/src/arduino.cc/builder/test/prototypes_adder_test.go index a6f46a45..db33a440 100644 --- a/src/arduino.cc/builder/test/prototypes_adder_test.go +++ b/src/arduino.cc/builder/test/prototypes_adder_test.go @@ -33,6 +33,7 @@ package test import ( "arduino.cc/builder" "arduino.cc/builder/types" + "arduino.cc/builder/utils" "github.com/stretchr/testify/require" "os" "path/filepath" @@ -44,7 +45,7 @@ func TestPrototypesAdderBridgeExample(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("downloaded_libraries", "Bridge", "examples", "Bridge", "Bridge.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -81,8 +82,8 @@ func TestPrototypesAdderBridgeExample(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 33 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 46 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 62 \""+absoluteSketchLocation+"\"\nvoid process(BridgeClient client);\n#line 82 \""+absoluteSketchLocation+"\"\nvoid digitalCommand(BridgeClient client);\n#line 109 \""+absoluteSketchLocation+"\"\nvoid analogCommand(BridgeClient client);\n#line 149 \""+absoluteSketchLocation+"\"\nvoid modeCommand(BridgeClient client);\n#line 33 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 " + quotedSketchLocation + "\n", ctx.IncludeSection) + require.Equal(t, "#line 33 "+quotedSketchLocation+"\nvoid setup();\n#line 46 "+quotedSketchLocation+"\nvoid loop();\n#line 62 "+quotedSketchLocation+"\nvoid process(BridgeClient client);\n#line 82 "+quotedSketchLocation+"\nvoid digitalCommand(BridgeClient client);\n#line 109 "+quotedSketchLocation+"\nvoid analogCommand(BridgeClient client);\n#line 149 "+quotedSketchLocation+"\nvoid modeCommand(BridgeClient client);\n#line 33 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } func TestPrototypesAdderSketchWithIfDef(t *testing.T) { @@ -374,7 +375,7 @@ func TestPrototypesAdderSketchWithConfig(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_config", "sketch_with_config.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -409,8 +410,8 @@ func TestPrototypesAdderSketchWithConfig(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 13 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 17 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 13 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 13 "+quotedSketchLocation+"\nvoid setup();\n#line 17 "+quotedSketchLocation+"\nvoid loop();\n#line 13 "+quotedSketchLocation+"\n", ctx.PrototypesSection) preprocessed := LoadAndInterpolate(t, filepath.Join("sketch_with_config", "sketch_with_config.preprocessed.txt"), ctx) require.Equal(t, preprocessed, strings.Replace(ctx.Source, "\r\n", "\n", -1)) @@ -420,7 +421,7 @@ func TestPrototypesAdderSketchNoFunctionsTwoFiles(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_no_functions_two_files", "main.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -455,7 +456,7 @@ func TestPrototypesAdderSketchNoFunctionsTwoFiles(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) require.Equal(t, "", ctx.PrototypesSection) } @@ -477,7 +478,7 @@ func TestPrototypesAdderSketchNoFunctions(t *testing.T) { defer os.RemoveAll(buildPath) sketchLocation := filepath.Join("sketch_no_functions", "main.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) commands := []types.Command{ @@ -498,7 +499,7 @@ func TestPrototypesAdderSketchNoFunctions(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) require.Equal(t, "", ctx.PrototypesSection) } @@ -506,7 +507,7 @@ func TestPrototypesAdderSketchWithDefaultArgs(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_default_args", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -541,15 +542,15 @@ func TestPrototypesAdderSketchWithDefaultArgs(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 4 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 7 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 4 "+quotedSketchLocation+"\nvoid setup();\n#line 7 "+quotedSketchLocation+"\nvoid loop();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } func TestPrototypesAdderSketchWithInlineFunction(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_inline_function", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -584,9 +585,9 @@ func TestPrototypesAdderSketchWithInlineFunction(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) - expected := "#line 1 \"" + absoluteSketchLocation + "\"\nvoid setup();\n#line 2 \"" + absoluteSketchLocation + "\"\nvoid loop();\n#line 4 \"" + absoluteSketchLocation + "\"\nshort unsigned int testInt();\n#line 8 \"" + absoluteSketchLocation + "\"\nstatic int8_t testInline();\n#line 12 \"" + absoluteSketchLocation + "\"\n__attribute__((always_inline)) uint8_t testAttribute();\n#line 1 \"" + absoluteSketchLocation + "\"\n" + expected := "#line 1 " + quotedSketchLocation + "\nvoid setup();\n#line 2 " + quotedSketchLocation + "\nvoid loop();\n#line 4 " + quotedSketchLocation + "\nshort unsigned int testInt();\n#line 8 " + quotedSketchLocation + "\nstatic int8_t testInline();\n#line 12 " + quotedSketchLocation + "\n__attribute__((always_inline)) uint8_t testAttribute();\n#line 1 " + quotedSketchLocation + "\n" obtained := ctx.PrototypesSection // ctags based preprocessing removes "inline" but this is still OK // TODO: remove this exception when moving to a more powerful parser @@ -603,7 +604,7 @@ func TestPrototypesAdderSketchWithFunctionSignatureInsideIFDEF(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_function_signature_inside_ifdef", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -638,15 +639,15 @@ func TestPrototypesAdderSketchWithFunctionSignatureInsideIFDEF(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 3 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 15 \""+absoluteSketchLocation+"\"\nint8_t adalight();\n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 1 "+quotedSketchLocation+"\nvoid setup();\n#line 3 "+quotedSketchLocation+"\nvoid loop();\n#line 15 "+quotedSketchLocation+"\nint8_t adalight();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } func TestPrototypesAdderSketchWithUSBCON(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_usbcon", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -681,15 +682,15 @@ func TestPrototypesAdderSketchWithUSBCON(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid ciao();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 15 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 5 "+quotedSketchLocation+"\nvoid ciao();\n#line 10 "+quotedSketchLocation+"\nvoid setup();\n#line 15 "+quotedSketchLocation+"\nvoid loop();\n#line 5 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } func TestPrototypesAdderSketchWithTypename(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_typename", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -723,13 +724,13 @@ func TestPrototypesAdderSketchWithTypename(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - expected := "#line 6 \"" + absoluteSketchLocation + "\"\nvoid setup();\n#line 10 \"" + absoluteSketchLocation + "\"\nvoid loop();\n#line 12 \"" + absoluteSketchLocation + "\"\ntypename Foo::Bar func();\n#line 6 \"" + absoluteSketchLocation + "\"\n" + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + expected := "#line 6 " + quotedSketchLocation + "\nvoid setup();\n#line 10 " + quotedSketchLocation + "\nvoid loop();\n#line 12 " + quotedSketchLocation + "\ntypename Foo::Bar func();\n#line 6 " + quotedSketchLocation + "\n" obtained := ctx.PrototypesSection // ctags based preprocessing ignores line with typename // TODO: remove this exception when moving to a more powerful parser - expected = strings.Replace(expected, "#line 12 \""+absoluteSketchLocation+"\"\ntypename Foo::Bar func();\n", "", -1) - obtained = strings.Replace(obtained, "#line 12 \""+absoluteSketchLocation+"\"\ntypename Foo::Bar func();\n", "", -1) + expected = strings.Replace(expected, "#line 12 "+quotedSketchLocation+"\ntypename Foo::Bar func();\n", "", -1) + obtained = strings.Replace(obtained, "#line 12 "+quotedSketchLocation+"\ntypename Foo::Bar func();\n", "", -1) require.Equal(t, expected, obtained) } @@ -737,7 +738,7 @@ func TestPrototypesAdderSketchWithIfDef2(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_ifdef", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -772,8 +773,8 @@ func TestPrototypesAdderSketchWithIfDef2(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 5 \""+absoluteSketchLocation+"\"\nvoid elseBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 5 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 5 "+quotedSketchLocation+"\nvoid elseBranch();\n#line 9 "+quotedSketchLocation+"\nvoid f1();\n#line 10 "+quotedSketchLocation+"\nvoid f2();\n#line 12 "+quotedSketchLocation+"\nvoid setup();\n#line 14 "+quotedSketchLocation+"\nvoid loop();\n#line 5 "+quotedSketchLocation+"\n", ctx.PrototypesSection) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.txt"), ctx) require.Equal(t, expectedSource, strings.Replace(ctx.Source, "\r\n", "\n", -1)) @@ -783,7 +784,7 @@ func TestPrototypesAdderSketchWithIfDef2SAM(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_ifdef", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -818,8 +819,8 @@ func TestPrototypesAdderSketchWithIfDef2SAM(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 2 \""+absoluteSketchLocation+"\"\nvoid ifBranch();\n#line 9 \""+absoluteSketchLocation+"\"\nvoid f1();\n#line 10 \""+absoluteSketchLocation+"\"\nvoid f2();\n#line 12 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 14 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 2 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 2 "+quotedSketchLocation+"\nvoid ifBranch();\n#line 9 "+quotedSketchLocation+"\nvoid f1();\n#line 10 "+quotedSketchLocation+"\nvoid f2();\n#line 12 "+quotedSketchLocation+"\nvoid setup();\n#line 14 "+quotedSketchLocation+"\nvoid loop();\n#line 2 "+quotedSketchLocation+"\n", ctx.PrototypesSection) expectedSource := LoadAndInterpolate(t, filepath.Join("sketch_with_ifdef", "sketch.preprocessed.SAM.txt"), ctx) require.Equal(t, expectedSource, strings.Replace(ctx.Source, "\r\n", "\n", -1)) @@ -829,7 +830,7 @@ func TestPrototypesAdderSketchWithConst(t *testing.T) { DownloadCoresAndToolsAndLibraries(t) sketchLocation := filepath.Join("sketch_with_const", "sketch.ino") - absoluteSketchLocation := strings.Replace(Abs(t, sketchLocation), "\\", "\\\\", -1) + quotedSketchLocation := utils.QuoteCppString(Abs(t, sketchLocation)) ctx := &types.Context{ HardwareFolders: []string{filepath.Join("..", "hardware"), "hardware", "downloaded_hardware"}, @@ -864,8 +865,8 @@ func TestPrototypesAdderSketchWithConst(t *testing.T) { NoError(t, err) } - require.Equal(t, "#include \n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.IncludeSection) - require.Equal(t, "#line 1 \""+absoluteSketchLocation+"\"\nvoid setup();\n#line 2 \""+absoluteSketchLocation+"\"\nvoid loop();\n#line 4 \""+absoluteSketchLocation+"\"\nconst __FlashStringHelper* test();\n#line 6 \""+absoluteSketchLocation+"\"\nconst int test3();\n#line 8 \""+absoluteSketchLocation+"\"\nvolatile __FlashStringHelper* test2();\n#line 10 \""+absoluteSketchLocation+"\"\nvolatile int test4();\n#line 1 \""+absoluteSketchLocation+"\"\n", ctx.PrototypesSection) + require.Equal(t, "#include \n#line 1 "+quotedSketchLocation+"\n", ctx.IncludeSection) + require.Equal(t, "#line 1 "+quotedSketchLocation+"\nvoid setup();\n#line 2 "+quotedSketchLocation+"\nvoid loop();\n#line 4 "+quotedSketchLocation+"\nconst __FlashStringHelper* test();\n#line 6 "+quotedSketchLocation+"\nconst int test3();\n#line 8 "+quotedSketchLocation+"\nvolatile __FlashStringHelper* test2();\n#line 10 "+quotedSketchLocation+"\nvolatile int test4();\n#line 1 "+quotedSketchLocation+"\n", ctx.PrototypesSection) } func TestPrototypesAdderSketchWithDosEol(t *testing.T) { diff --git a/src/arduino.cc/builder/test/sketch1/merged_sketch.txt b/src/arduino.cc/builder/test/sketch1/merged_sketch.txt index 38af5a38..4654de32 100644 --- a/src/arduino.cc/builder/test/sketch1/merged_sketch.txt +++ b/src/arduino.cc/builder/test/sketch1/merged_sketch.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} void setup() { } @@ -8,9 +8,9 @@ void setup() { void loop() { } -#line 1 "{{EscapeBackSlashes (index .sketch.OtherSketchFiles 0).Name}}" +#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 0).Name}} -#line 1 "{{EscapeBackSlashes (index .sketch.OtherSketchFiles 1).Name}}" +#line 1 {{QuoteCppString (index .sketch.OtherSketchFiles 1).Name}} String hello() { return "world"; } diff --git a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt index 4c7c7545..e0380e17 100644 --- a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.preprocessed.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #define DEBUG 1 #define DISABLED 0 @@ -16,17 +16,17 @@ typedef int MyType; #include "empty_2.h" -#line 16 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 16 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 21 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 21 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 33 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 33 {{QuoteCppString .sketch.MainFile.Name}} void debug(); -#line 44 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 44 {{QuoteCppString .sketch.MainFile.Name}} void disabledIsDefined(); -#line 48 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 48 {{QuoteCppString .sketch.MainFile.Name}} int useMyType(MyType type); -#line 16 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 16 {{QuoteCppString .sketch.MainFile.Name}} void setup() { // put your setup code here, to run once: diff --git a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt index 1f7492ad..c01a6fe3 100644 --- a/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt +++ b/src/arduino.cc/builder/test/sketch2/SketchWithIfDef.resolved.directives.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #define DEBUG 1 #define DISABLED 0 diff --git a/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt b/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt index fd7fd313..989b6b9b 100644 --- a/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch3/Baladuino.preprocessed.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} /* * The code is released under the GNU General Public License. * Developed by Kristian Lauszus, TKJ Electronics 2013 @@ -88,11 +88,11 @@ WII Wii(&Btd); // The Wii library can communicate with Wiimotes and the Nunchuck // This can also be done using the Android or Processing application #endif -#line 88 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 88 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 204 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 204 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 88 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 88 {{QuoteCppString .sketch.MainFile.Name}} void setup() { /* Initialize UART */ Serial.begin(115200); diff --git a/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt b/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt index b7cfb728..62fa1ac6 100644 --- a/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch4/CharWithEscapedDoubleQuote.preprocessed.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include // required to send and receive AT commands from the GPRS Shield #include // required for I2C communication with the RTC @@ -39,49 +39,49 @@ Code Exclusively for GPRS shield: // Default set of instructions for GPRS Shield power control // -#line 39 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 39 {{QuoteCppString .sketch.MainFile.Name}} void setPowerStateTo( int newState ); -#line 64 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 64 {{QuoteCppString .sketch.MainFile.Name}} int getPowerState(); -#line 75 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 75 {{QuoteCppString .sketch.MainFile.Name}} void powerUpOrDown(); -#line 90 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 90 {{QuoteCppString .sketch.MainFile.Name}} void clearBufferArray(); -#line 96 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 96 {{QuoteCppString .sketch.MainFile.Name}} void makeMissedCall( char num[] ); -#line 111 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 111 {{QuoteCppString .sketch.MainFile.Name}} void sendTextMessage( char number[], char messg[] ); -#line 129 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 129 {{QuoteCppString .sketch.MainFile.Name}} void analise(byte incoming[], int length); -#line 179 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 179 {{QuoteCppString .sketch.MainFile.Name}} byte decToBcd( byte b ); -#line 184 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 184 {{QuoteCppString .sketch.MainFile.Name}} boolean getBit( byte addr, int pos ); -#line 190 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 190 {{QuoteCppString .sketch.MainFile.Name}} void setBit( byte addr, int pos, boolean newBit ); -#line 204 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 204 {{QuoteCppString .sketch.MainFile.Name}} byte getByte( byte addr ); -#line 213 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 213 {{QuoteCppString .sketch.MainFile.Name}} boolean getBytes( byte addr, int amount ); -#line 230 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 230 {{QuoteCppString .sketch.MainFile.Name}} void setByte( byte addr, byte newByte ); -#line 235 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 235 {{QuoteCppString .sketch.MainFile.Name}} void setBytes( byte addr, byte newBytes[], int amount ); -#line 244 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 244 {{QuoteCppString .sketch.MainFile.Name}} void getTime(); -#line 260 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 260 {{QuoteCppString .sketch.MainFile.Name}} void setTime( byte newTime[ 7 ] ); -#line 267 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 267 {{QuoteCppString .sketch.MainFile.Name}} void getRTCTemperature(); -#line 277 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 277 {{QuoteCppString .sketch.MainFile.Name}} void gprsListen(); -#line 294 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 294 {{QuoteCppString .sketch.MainFile.Name}} void printTime(); -#line 317 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 317 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 334 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 334 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 39 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 39 {{QuoteCppString .sketch.MainFile.Name}} void setPowerStateTo( int newState ) { if( newState != 1 && newState != 0 ) { // tests for an invalid state. In this case no change is made to powerstate diff --git a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt index b29c05e7..a19528dc 100644 --- a/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch5/IncludeBetweenMultilineComment.preprocessed.txt @@ -1,16 +1,16 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include /* #include */ CapacitiveSensor cs_13_8 = CapacitiveSensor(13,8); -#line 6 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 6 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 10 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 6 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 6 {{QuoteCppString .sketch.MainFile.Name}} void setup() { Serial.begin(9600); diff --git a/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt b/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt index 567d373c..1d584583 100644 --- a/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch6/LineContinuations.preprocessed.txt @@ -1,17 +1,17 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} const char *foo = "\ hello \ world\n"; //" delete this comment line and the IDE parser will crash -#line 7 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 7 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 11 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 11 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 7 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 7 {{QuoteCppString .sketch.MainFile.Name}} void setup() { } diff --git a/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt b/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt index 9700f3e2..f4432fcd 100644 --- a/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch7/StringWithComment.preprocessed.txt @@ -1,11 +1,11 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 10 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} void setup() { // put your setup code here, to run once: // "comment with a double quote diff --git a/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt b/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt index cdfcd34e..35302e16 100644 --- a/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch8/SketchWithStruct.preprocessed.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} /* START CODE */ struct A_NEW_TYPE { @@ -9,13 +9,13 @@ struct A_NEW_TYPE { int c; } foo; -#line 9 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 9 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 13 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 13 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 17 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 17 {{QuoteCppString .sketch.MainFile.Name}} void dostuff (A_NEW_TYPE * bar); -#line 9 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 9 {{QuoteCppString .sketch.MainFile.Name}} void setup() { } diff --git a/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt b/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt index 0216d1d0..2d56efd3 100644 --- a/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch_with_config/sketch_with_config.preprocessed.txt @@ -1,6 +1,6 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #include "config.h" #ifdef DEBUG @@ -13,11 +13,11 @@ #include -#line 13 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 13 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 17 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 17 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 13 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 13 {{QuoteCppString .sketch.MainFile.Name}} void setup() { } diff --git a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt index ae868905..2eb36912 100644 --- a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt +++ b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.SAM.txt @@ -1,18 +1,18 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #if __SAM3X8E__ -#line 2 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 2 {{QuoteCppString .sketch.MainFile.Name}} void ifBranch(); -#line 9 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 9 {{QuoteCppString .sketch.MainFile.Name}} void f1(); -#line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 10 {{QuoteCppString .sketch.MainFile.Name}} void f2(); -#line 12 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 12 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 14 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 14 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 2 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 2 {{QuoteCppString .sketch.MainFile.Name}} void ifBranch() { } #else diff --git a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt index 88778cd2..31c86758 100644 --- a/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt +++ b/src/arduino.cc/builder/test/sketch_with_ifdef/sketch.preprocessed.txt @@ -1,21 +1,21 @@ #include -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" -#line 1 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 1 {{QuoteCppString .sketch.MainFile.Name}} +#line 1 {{QuoteCppString .sketch.MainFile.Name}} #if __SAM3X8E__ void ifBranch() { } #else -#line 5 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 5 {{QuoteCppString .sketch.MainFile.Name}} void elseBranch(); -#line 9 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 9 {{QuoteCppString .sketch.MainFile.Name}} void f1(); -#line 10 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 10 {{QuoteCppString .sketch.MainFile.Name}} void f2(); -#line 12 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 12 {{QuoteCppString .sketch.MainFile.Name}} void setup(); -#line 14 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 14 {{QuoteCppString .sketch.MainFile.Name}} void loop(); -#line 5 "{{EscapeBackSlashes .sketch.MainFile.Name}}" +#line 5 {{QuoteCppString .sketch.MainFile.Name}} void elseBranch() { } #endif diff --git a/src/arduino.cc/builder/test/utils_test.go b/src/arduino.cc/builder/test/utils_test.go index c3662e1d..09cbce92 100644 --- a/src/arduino.cc/builder/test/utils_test.go +++ b/src/arduino.cc/builder/test/utils_test.go @@ -87,3 +87,44 @@ func TestMapTrimSpace(t *testing.T) { require.Equal(t, "how are", parts[2]) require.Equal(t, "you?", parts[3]) } + +func TestQuoteCppString(t *testing.T) { + cases := map[string]string { + `foo`: `"foo"`, + `foo\bar`: `"foo\\bar"`, + `foo "is" quoted and \\bar"" escaped\`: `"foo \"is\" quoted and \\\\bar\"\" escaped\\"`, + // ASCII 0x20 - 0x7e, excluding ` + ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~`: `" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~"`, + } + for input, expected := range cases { + require.Equal(t, expected, utils.QuoteCppString(input)) + } +} + +func TestParseCppString(t *testing.T) { + str, rest, ok := utils.ParseCppString(`foo`) + require.Equal(t, false, ok) + + str, rest, ok = utils.ParseCppString(`"foo`) + require.Equal(t, false, ok) + + str, rest, ok = utils.ParseCppString(`"foo"`) + require.Equal(t, true, ok) + require.Equal(t, `foo`, str) + require.Equal(t, ``, rest) + + str, rest, ok = utils.ParseCppString(`"foo\\bar"`) + require.Equal(t, true, ok) + require.Equal(t, `foo\bar`, str) + require.Equal(t, ``, rest) + + str, rest, ok = utils.ParseCppString(`"foo \"is\" quoted and \\\\bar\"\" escaped\\" and "then" some`) + require.Equal(t, true, ok) + require.Equal(t, `foo "is" quoted and \\bar"" escaped\`, str) + require.Equal(t, ` and "then" some`, rest) + + str, rest, ok = utils.ParseCppString(`" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~"`,) + require.Equal(t, true, ok) + require.Equal(t, ` !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~`, str) + require.Equal(t, ``, rest) +} diff --git a/src/arduino.cc/builder/types/context.go b/src/arduino.cc/builder/types/context.go index 09546536..8be5a858 100644 --- a/src/arduino.cc/builder/types/context.go +++ b/src/arduino.cc/builder/types/context.go @@ -65,9 +65,7 @@ type Context struct { // C++ Parsing CTagsOutput string CTagsTargetFile string - CTagsOfSource []*CTag CTagsOfPreprocessedSource []*CTag - CTagsCollected []*CTag IncludeSection string LineOffset int PrototypesSection string diff --git a/src/arduino.cc/builder/utils/utils.go b/src/arduino.cc/builder/utils/utils.go index ad8d50e5..5bef8295 100644 --- a/src/arduino.cc/builder/utils/utils.go +++ b/src/arduino.cc/builder/utils/utils.go @@ -407,3 +407,56 @@ func LogIfVerbose(level string, format string, args ...interface{}) types.Comman func LogThis(level string, format string, args ...interface{}) types.Command { return &loggerAction{false, level, format, args} } + +// Returns the given string as a quoted string for use with the C +// preprocessor. This adds double quotes around it and escapes any +// double quotes and backslashes in the string. +func QuoteCppString(str string) string { + str = strings.Replace(str, "\\", "\\\\", -1) + str = strings.Replace(str, "\"", "\\\"", -1) + return "\"" + str + "\"" +} + +// Parse a C-preprocessor string as emitted by the preprocessor. This +// is a string contained in double quotes, with any backslashes or +// quotes escaped with a backslash. If a valid string was present at the +// start of the given line, returns the unquoted string contents, the +// remaineder of the line (everything after the closing "), and true. +// Otherwise, returns the empty string, the entire line and false. +func ParseCppString(line string) (string, string, bool) { + // For details about how these strings are output by gcc, see: + // https://github.com/gcc-mirror/gcc/blob/a588355ab948cf551bc9d2b89f18e5ae5140f52c/libcpp/macro.c#L491-L511 + // Note that the documentaiton suggests all non-printable + // characters are also escaped, but the implementation does not + // actually do this. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51259 + if len(line) < 1 || line[0] != '"' { + return "", line, false + } + + i := 1 + res := "" + for { + if i >= len(line) { + return "", line, false + } + + switch (line[i]) { + // Backslash, next character is used unmodified + case '\\': + i++ + if i >= len(line) { + return "", line, false + } + res += string(line[i]) + break + // Quote, end of string + case '"': + return res, line[i+1:], true + default: + res += string(line[i]) + break + } + + i++ + } +}