// 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 ""
	}

	// 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 ""
}
Example #2
0
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)

	str, rest, ok = utils.ParseCppString(`"/home/ççç/"`)
	require.Equal(t, true, ok)
	require.Equal(t, `/home/ççç/`, str)
	require.Equal(t, ``, rest)

	str, rest, ok = utils.ParseCppString(`"/home/ççç/ /$sdsdd\\"`)
	require.Equal(t, true, ok)
	require.Equal(t, `/home/ççç/ /$sdsdd\`, str)
	require.Equal(t, ``, rest)
}