diff --git a/dtool/src/cppparser/cppExpression.cxx b/dtool/src/cppparser/cppExpression.cxx index f185514de4..13248847a6 100644 --- a/dtool/src/cppparser/cppExpression.cxx +++ b/dtool/src/cppparser/cppExpression.cxx @@ -1558,6 +1558,10 @@ output(ostream &out, int indent_level, CPPScope *scope, bool) const { out << "\\\""; break; + case '\\': + out << "\\\\"; + break; + default: if (isprint(*si)) { out << *si; diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index feda153530..c6a7dd0b07 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -1870,11 +1870,19 @@ get_identifier(int c) { loc.last_column = get_col_number(); if ((c == '\'' || c == '"') && - (name == "L" || name == "u8" || - name == "u" || name == "U")) { + (name == "L" || name == "u8" || name == "u" || name == "U" || + name == "R" || name == "LR" || name == "u8R" || name == "uR" || name == "UR")) { // This is actually a wide-character or wide-string literal or some such. - // Figure out the correct character type to use. + get(); + string str; + if (name[name.size() - 1] == 'R') { + name.resize(name.size() - 1); + str = scan_raw(c); + } else { + str = scan_quoted(c); + } + // Figure out the correct character type to use. CPPExpression::Type type; if (name == "L") { type = CPPExpression::T_wstring; @@ -1887,8 +1895,6 @@ get_identifier(int c) { } else { type = CPPExpression::T_string; } - get(); - string str = scan_quoted(c); loc.last_line = get_line_number(); loc.last_column = get_col_number(); @@ -2772,6 +2778,43 @@ scan_quoted(int c) { return str; } +/** + * Parses a C++11 raw string. + */ +string CPPPreprocessor:: +scan_raw(int c) { + int quote_mark = c; + + string delimiter = ")"; + + string str; + c = get(); + while (c != EOF && c != '(') { + delimiter += c; + c = get(); + } + + // OK, now start parsing the string, until we see the delimiter again. + c = get(); + while (c != EOF) { + if (c == quote_mark) { + // We encountered a quote mark - did the last part of the string end + // with the given delimiter? If so, we've reached the end. + if (str.compare(str.size() - delimiter.size(), delimiter.size(), delimiter) == 0) { + str.resize(str.size() - delimiter.size()); + break; + } + } + str += c; + c = get(); + } + + if (c != quote_mark) { + warning("Unclosed string"); + } + return str; +} + /** * Returns true if the manifest is one that is being ignored right now * (presumably because we are presently expanding it). diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index e119211596..20f313758a 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -166,6 +166,7 @@ private: static int check_keyword(const string &name); int scan_escape_sequence(int c); string scan_quoted(int c); + string scan_raw(int c); bool should_ignore_manifest(const CPPManifest *manifest) const; bool should_ignore_preprocessor() const;