Branch data Line data Source code
1 : : // Copyright (C) 2021 The Qt Company Ltd.
2 : : // Copyright (C) 2019 Luxoft Sweden AB
3 : : // Copyright (C) 2018 Pelagicore AG
4 : : // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
5 : :
6 : : #include "debugwrapper.h"
7 : :
8 : : using namespace Qt::StringLiterals;
9 : :
10 : : QT_BEGIN_NAMESPACE_AM
11 : :
12 : : namespace DebugWrapper {
13 : :
14 : 24 : bool parseSpecification(const QString &debugWrapperSpecification, QStringList &resultingCommand,
15 : : QMap<QString, QString> &resultingEnvironment)
16 : : {
17 : 24 : QStringList cmd;
18 : 24 : QMap<QString, QString> env;
19 : :
20 : : // split at ' ', but also accept escape sequences for '\ ', '\n' and '\\'
21 : : // all leading FOO=BAR args will be converted to env var assignments
22 : 24 : bool escaped = false;
23 : 24 : bool canBeEnvVar = true;
24 : 24 : bool isEnvVar = false;
25 [ + + + - ]: 24 : static const QString program = u"%program%"_s;
26 [ + + + - ]: 24 : static const QString arguments = u"%arguments%"_s;
27 : 24 : int foundProgram = 0;
28 : 24 : int foundArguments = 0;
29 : 24 : QString str;
30 : 24 : QString value;
31 : 24 : QString *current = &str;
32 : 24 : qsizetype size = debugWrapperSpecification.size();
33 [ + + ]: 364 : for (qsizetype i = 0; i <= size; ++i) {
34 [ + + ]: 340 : const QChar c = (i < size) ? debugWrapperSpecification.at(i) : QChar(0);
35 [ + + - + ]: 340 : if (!escaped || c.isNull()) {
36 [ + + + + ]: 334 : switch (c.unicode()) {
37 : : case '\\':
38 : : escaped = true;
39 : : break;
40 : 13 : case '=':
41 : : // switch to value parsing if this can be an env var and if this is the first =
42 : : // all other = are copied verbatim
43 : 13 : isEnvVar = canBeEnvVar;
44 [ + + + + ]: 13 : if (isEnvVar && current == &str)
45 : : current = &value;
46 : : else
47 [ + - ]: 2 : current->append(u'=');
48 : : break;
49 : 58 : case ' ':
50 : 58 : case '\0':
51 : : // found the end of an argument: add to env vars or cmd and reset state
52 [ + + ]: 58 : if (!str.isEmpty()) {
53 [ + + ]: 49 : if (isEnvVar) {
54 [ + - ]: 11 : env.insert(str, value);
55 : : } else {
56 [ + - ]: 38 : cmd.append(str);
57 : :
58 [ + + + + ]: 74 : foundArguments = foundArguments || str.contains(arguments);
59 [ + + + + ]: 71 : foundProgram = foundProgram || str.contains(program);
60 : : }
61 : : }
62 : 58 : canBeEnvVar = isEnvVar; // stop parsing as envvar as soon as we get a normal arg
63 : 58 : isEnvVar = false;
64 : 58 : current = &str;
65 : 58 : str.clear();
66 : 58 : value.clear();
67 : 58 : break;
68 : 257 : default:
69 [ + - ]: 257 : current->append(c);
70 : : break;
71 : : }
72 : : } else {
73 [ + + + - ]: 6 : switch (c.unicode()) {
74 [ + - ]: 1 : case '\\': current->append(u'\\'); break;
75 [ + - ]: 3 : case ' ': current->append(u' '); break;
76 [ + - ]: 2 : case 'n': current->append(u'\n'); break;
77 : 24 : default: return false;
78 : : }
79 : : escaped = false;
80 : : }
81 : : }
82 : :
83 [ + + + - ]: 51 : if (cmd.isEmpty() && env.isEmpty())
84 : : return false;
85 : :
86 : : // convenience: if the spec doesn't include %program% or %arguments%, then simply append them
87 [ + + ]: 21 : if (!foundProgram)
88 [ + - ]: 15 : cmd << program;
89 [ + + ]: 21 : if (!foundArguments)
90 [ + - ]: 15 : cmd << arguments;
91 : :
92 : 21 : resultingCommand = cmd;
93 : 21 : resultingEnvironment = env;
94 : 21 : return true;
95 : 24 : }
96 : :
97 : 6 : QStringList substituteCommand(const QStringList &debugWrapperCommand, const QString &program,
98 : : const QStringList &arguments)
99 : : {
100 : 6 : QString stringifiedArguments = arguments.join(u' ');
101 : 6 : QStringList result;
102 : :
103 [ + + ]: 24 : for (const QString &s : debugWrapperCommand) {
104 [ + + ]: 18 : if (s == u"%arguments%") {
105 [ + - ]: 24 : result << arguments;
106 : : } else {
107 : 12 : QString str(s);
108 [ + - ]: 12 : str.replace(u"%program%"_s, program);
109 [ + - ]: 12 : str.replace(u"%arguments%"_s, stringifiedArguments);
110 [ + - ]: 24 : result << str;
111 : 12 : }
112 : : }
113 : 6 : return result;
114 : 6 : }
115 : :
116 : : } // namespace DebugWrapper
117 : :
118 : : QT_END_NAMESPACE_AM
|