From 0233e9ec8bc1d65fbbd6be6fa798531a658b9ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 27 Jun 2013 15:21:37 +0200 Subject: Xcode: Fix string quoting to match ASCII plist format The logic for quoting and unescaping strings was a bit random. We now leave the strings alone, until writing them out as values, where we quote and escape the characters that need escaping. See: http://www.gnustep.org/resources/documentation/Developer/Base/Reference/NSPropertyList.html https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html https://code.google.com/p/plist/source/browse/trunk/src/main/java/com/dd/plist/NSString.java?r=107#230 Change-Id: I2096df531947abdce4f6b57428136f544d22c466 Reviewed-by: Oswald Buddenhagen --- qmake/generators/mac/pbuilder_pbx.cpp | 80 ++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'qmake/generators') diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 5af71cbc7b..c20a8f7a34 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1520,12 +1520,8 @@ ProjectBuilderMakefileGenerator::fixForOutput(const QString &values) project->values("QMAKE_PBX_VARS").append(reg_var.cap(1)); rep += reg_var.matchedLength(); } - QString ret = values; - ret = ret.replace(QRegExp("\\\\ "), " "); //unescape spaces - ret = ret.replace(QRegExp("('|\\\\|\")"), "\\\\1"); //fix quotes - ret = ret.replace("\t", " "); //fix tabs - ret = ret.replace(QRegExp(" "), "\\ "); //escape spaces - return ret; + + return values; } ProStringList @@ -1749,37 +1745,81 @@ ProjectBuilderMakefileGenerator::escapeFilePath(const QString &path) const #endif } +static QString quotedStringLiteral(const QString &value) +{ + QString result; + const int len = value.length(); + result.reserve(int(len * 1.1) + 2); + + result += QLatin1Char('"'); + + // Escape + for (int i = 0; i < len; ++i) { + QChar character = value.at(i);; + ushort code = character.unicode(); + switch (code) { + case '\\': + result += QLatin1String("\\\\"); + break; + case '"': + result += QLatin1String("\\\""); + break; + case '\b': + result += QLatin1String("\\b"); + break; + case '\n': + result += QLatin1String("\\n"); + break; + case '\r': + result += QLatin1String("\\r"); + break; + case '\t': + result += QLatin1String("\\t"); + break; + default: + if (code >= 32 && code <= 127) + result += character; + else + result += QLatin1String("\\u") + QString::number(code, 16).rightJustified(4, '0'); + } + } + + result += QLatin1Char('"'); + + result.squeeze(); + return result; +} + QString ProjectBuilderMakefileGenerator::writeSettings(const QString &var, const ProStringList &vals, int flags, int indent_level) { QString ret; - const QString quote = (flags & SettingsNoQuote) ? "" : "\""; - const QString escape_quote = quote.isEmpty() ? "" : QString("\\" + quote); + bool shouldQuote = !((flags & SettingsNoQuote)); + QString newline = "\n"; for(int i = 0; i < indent_level; ++i) newline += "\t"; + + ret += var + " = "; + if(flags & SettingsAsList) { - ret += var + " = (" + newline; + ret += "(" + newline; for(int i = 0, count = 0; i < vals.size(); ++i) { QString val = vals.at(i).toQString(); if(!val.isEmpty()) { if(count++ > 0) ret += "," + newline; - ret += quote + val.replace(quote, escape_quote) + quote; + if (shouldQuote) + val = quotedStringLiteral(val); + ret += val; } } ret += ")"; } else { - ret += var + " = " + quote; - for(int i = 0; i < vals.size(); ++i) { - QString val = vals.at(i).toQString(); -// if(val.isEmpty()) -// val = quote + quote; - if(i) - ret += " "; - ret += val; - } - ret += quote; + QString val = vals.join(QLatin1Char(' ')); + if (shouldQuote) + val = quotedStringLiteral(val); + ret += val; } return ret; } -- cgit v1.2.3