aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/app/qbs/qbs.qbs1
-rw-r--r--src/lib/corelib/corelib.qbs1
-rw-r--r--src/lib/corelib/jsextensions/utilitiesextension.cpp142
-rw-r--r--tests/auto/api/api.qbs1
-rw-r--r--tests/auto/blackbox/blackbox.qbs3
-rw-r--r--tests/auto/cmdlineparser/cmdlineparser.qbs1
6 files changed, 149 insertions, 0 deletions
diff --git a/src/app/qbs/qbs.qbs b/src/app/qbs/qbs.qbs
index 66947e550..da02da68f 100644
--- a/src/app/qbs/qbs.qbs
+++ b/src/app/qbs/qbs.qbs
@@ -5,6 +5,7 @@ QbsApp {
name: "qbs_app"
Depends { name: "qbs resources" }
targetName: "qbs"
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat([
'QBS_VERSION="' + QbsFunctions.qbsVersion() + '"',
'QBS_RELATIVE_LIBEXEC_PATH="' + qbsbuildconfig.relativeLibexecPath + '"',
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index eee8600a5..aece5d776 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -17,6 +17,7 @@ QbsLibrary {
])
property stringList projectFileUpdateDefines:
qbsbuildconfig.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : []
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat([
'QBS_RELATIVE_LIBEXEC_PATH="' + qbsbuildconfig.relativeLibexecPath + '"',
"QBS_VERSION=\"" + version + "\"",
diff --git a/src/lib/corelib/jsextensions/utilitiesextension.cpp b/src/lib/corelib/jsextensions/utilitiesextension.cpp
index 9152f3e0c..ec1089f11 100644
--- a/src/lib/corelib/jsextensions/utilitiesextension.cpp
+++ b/src/lib/corelib/jsextensions/utilitiesextension.cpp
@@ -75,6 +75,7 @@ public:
static QScriptValue js_canonicalTargetArchitecture(QScriptContext *context,
QScriptEngine *engine);
static QScriptValue js_canonicalToolchain(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_cStringQuote(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_getHash(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_getNativeSetting(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_nativeSettingGroups(QScriptContext *context, QScriptEngine *engine);
@@ -100,6 +101,8 @@ static void initializeJsExtensionUtilities(QScriptValue extensionObject)
UtilitiesExtension::js_canonicalTargetArchitecture, 4));
environmentObj.setProperty(QStringLiteral("canonicalToolchain"),
engine->newFunction(UtilitiesExtension::js_canonicalToolchain));
+ environmentObj.setProperty(QStringLiteral("cStringQuote"),
+ engine->newFunction(UtilitiesExtension::js_cStringQuote, 1));
environmentObj.setProperty(QStringLiteral("getHash"),
engine->newFunction(UtilitiesExtension::js_getHash, 1));
environmentObj.setProperty(QStringLiteral("getNativeSetting"),
@@ -171,6 +174,145 @@ QScriptValue UtilitiesExtension::js_canonicalToolchain(QScriptContext *context,
return engine->toScriptValue(canonicalToolchain(toolchain));
}
+// copied from src/corelib/tools/qtools_p.h
+Q_DECL_CONSTEXPR inline char toHexUpper(uint value) Q_DECL_NOTHROW
+{
+ return "0123456789ABCDEF"[value & 0xF];
+}
+
+Q_DECL_CONSTEXPR inline int fromHex(uint c) Q_DECL_NOTHROW
+{
+ return ((c >= '0') && (c <= '9')) ? int(c - '0') :
+ ((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) :
+ ((c >= 'a') && (c <= 'f')) ? int(c - 'a' + 10) :
+ /* otherwise */ -1;
+}
+
+// copied from src/corelib/io/qdebug.cpp
+static inline bool isPrintable(uchar c)
+{ return c >= ' ' && c < 0x7f; }
+
+// modified
+template <typename Char>
+static inline QString escapedString(const Char *begin, int length, bool isUnicode = true)
+{
+ QChar quote(QLatin1Char('"'));
+ QString out = quote;
+
+ bool lastWasHexEscape = false;
+ const Char *end = begin + length;
+ for (const Char *p = begin; p != end; ++p) {
+ // check if we need to insert "" to break an hex escape sequence
+ if (Q_UNLIKELY(lastWasHexEscape)) {
+ if (fromHex(*p) != -1) {
+ // yes, insert it
+ out += QLatin1Char('"');
+ out += QLatin1Char('"');
+ }
+ lastWasHexEscape = false;
+ }
+
+ if (sizeof(Char) == sizeof(QChar)) {
+ // Surrogate characters are category Cs (Other_Surrogate), so isPrintable = false for them
+ int runLength = 0;
+ while (p + runLength != end &&
+ isPrintable(p[runLength]) && p[runLength] != '\\' && p[runLength] != '"')
+ ++runLength;
+ if (runLength) {
+ out += QString(reinterpret_cast<const QChar *>(p), runLength);
+ p += runLength - 1;
+ continue;
+ }
+ } else if (isPrintable(*p) && *p != '\\' && *p != '"') {
+ QChar c = QLatin1Char(*p);
+ out += c;
+ continue;
+ }
+
+ // print as an escape sequence (maybe, see below for surrogate pairs)
+ int buflen = 2;
+ ushort buf[sizeof "\\U12345678" - 1];
+ buf[0] = '\\';
+
+ switch (*p) {
+ case '"':
+ case '\\':
+ buf[1] = *p;
+ break;
+ case '\b':
+ buf[1] = 'b';
+ break;
+ case '\f':
+ buf[1] = 'f';
+ break;
+ case '\n':
+ buf[1] = 'n';
+ break;
+ case '\r':
+ buf[1] = 'r';
+ break;
+ case '\t':
+ buf[1] = 't';
+ break;
+ default:
+ if (!isUnicode) {
+ // print as hex escape
+ buf[1] = 'x';
+ buf[2] = toHexUpper(uchar(*p) >> 4);
+ buf[3] = toHexUpper(uchar(*p));
+ buflen = 4;
+ lastWasHexEscape = true;
+ break;
+ }
+ if (QChar::isHighSurrogate(*p)) {
+ if ((p + 1) != end && QChar::isLowSurrogate(p[1])) {
+ // properly-paired surrogates
+ uint ucs4 = QChar::surrogateToUcs4(*p, p[1]);
+ if (isPrintable(ucs4)) {
+ buf[0] = *p;
+ buf[1] = p[1];
+ buflen = 2;
+ } else {
+ buf[1] = 'U';
+ buf[2] = '0'; // toHexUpper(ucs4 >> 32);
+ buf[3] = '0'; // toHexUpper(ucs4 >> 28);
+ buf[4] = toHexUpper(ucs4 >> 20);
+ buf[5] = toHexUpper(ucs4 >> 16);
+ buf[6] = toHexUpper(ucs4 >> 12);
+ buf[7] = toHexUpper(ucs4 >> 8);
+ buf[8] = toHexUpper(ucs4 >> 4);
+ buf[9] = toHexUpper(ucs4);
+ buflen = 10;
+ }
+ ++p;
+ break;
+ }
+ // improperly-paired surrogates, fall through
+ }
+ buf[1] = 'u';
+ buf[2] = toHexUpper(ushort(*p) >> 12);
+ buf[3] = toHexUpper(ushort(*p) >> 8);
+ buf[4] = toHexUpper(*p >> 4);
+ buf[5] = toHexUpper(*p);
+ buflen = 6;
+ }
+ out += QString(reinterpret_cast<QChar *>(buf), buflen);
+ }
+
+ out += quote;
+ return out;
+}
+
+QScriptValue UtilitiesExtension::js_cStringQuote(QScriptContext *context, QScriptEngine *engine)
+{
+ if (Q_UNLIKELY(context->argumentCount() < 1)) {
+ return context->throwError(QScriptContext::SyntaxError,
+ QStringLiteral("cStringQuote expects 1 argument"));
+ }
+ QString value = context->argument(0).toString();
+ return engine->toScriptValue(escapedString(reinterpret_cast<const ushort *>(value.constData()), value.size()));
+}
+
QScriptValue UtilitiesExtension::js_getHash(QScriptContext *context, QScriptEngine *engine)
{
if (Q_UNLIKELY(context->argumentCount() < 1)) {
diff --git a/tests/auto/api/api.qbs b/tests/auto/api/api.qbs
index 68e7cde46..887bb999a 100644
--- a/tests/auto/api/api.qbs
+++ b/tests/auto/api/api.qbs
@@ -3,6 +3,7 @@ import qbs
QbsAutotest {
testName: "api"
files: ["../shared.h", "tst_api.h", "tst_api.cpp"]
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat([
'SRCDIR="' + path + '"',
'QBS_RELATIVE_LIBEXEC_PATH="' + qbsbuildconfig.relativeLibexecPath + '"',
diff --git a/tests/auto/blackbox/blackbox.qbs b/tests/auto/blackbox/blackbox.qbs
index 2aba61139..7ae40e471 100644
--- a/tests/auto/blackbox/blackbox.qbs
+++ b/tests/auto/blackbox/blackbox.qbs
@@ -21,6 +21,7 @@ Project {
"tst_blackbox.cpp",
"tst_blackbox.h",
]
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat(['SRCDIR="' + path + '"'])
}
@@ -41,6 +42,7 @@ Project {
"tst_blackboxjava.cpp",
"tst_blackboxjava.h",
]
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat(['SRCDIR="' + path + '"'])
}
@@ -64,6 +66,7 @@ Project {
"tst_clangdb.cpp",
"tst_clangdb.h",
]
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat(['SRCDIR="' + path + '"'])
}
}
diff --git a/tests/auto/cmdlineparser/cmdlineparser.qbs b/tests/auto/cmdlineparser/cmdlineparser.qbs
index d18982389..774372c61 100644
--- a/tests/auto/cmdlineparser/cmdlineparser.qbs
+++ b/tests/auto/cmdlineparser/cmdlineparser.qbs
@@ -4,6 +4,7 @@ import QbsFunctions
QbsAutotest {
testName: "cmdlineparser"
files: ["tst_cmdlineparser.cpp", "../../../src/app/qbs/qbstool.cpp"]
+ // TODO: Use Utilities.cStringQuote
cpp.defines: base.concat([
'SRCDIR="' + path + '"',
"QBS_VERSION=\"" + QbsFunctions.qbsVersion() + "\""