KCoreAddons

kmacroexpander_win.cpp
1 /*
2  This file is part of the KDE libraries
3 
4  SPDX-FileCopyrightText: 2008 Oswald Buddenhagen <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "kmacroexpander_p.h"
10 #include "kshell_p.h"
11 
12 #include "kshell.h"
13 
14 #include <QString>
15 #include <QStringList>
16 
18 {
19  int len;
20  int pos2;
21  ushort uc;
22  ushort ec = d->escapechar.unicode();
23  bool shellQuote = false; // shell is in quoted state
24  bool crtQuote = false; // c runtime is in quoted state
25  bool escaped = false; // previous char was a circumflex
26  int bslashes = 0; // previous chars were backslashes
27  int parens = 0; // parentheses nesting level
28  QStringList rst;
29  QString rsts;
30 
31  while (pos < str.length()) {
32  ushort cc = str.unicode()[pos].unicode();
33  if (escaped) { // prevent anomalies due to expansion
34  goto notcf;
35  }
36  if (ec != 0) {
37  if (cc != ec) {
38  goto nohit;
39  }
40  if (!(len = expandEscapedMacro(str, pos, rst))) {
41  goto nohit;
42  }
43  } else {
44  if (!(len = expandPlainMacro(str, pos, rst))) {
45  goto nohit;
46  }
47  }
48  if (len < 0) {
49  pos -= len;
50  continue;
51  }
52  if (shellQuote != crtQuote) { // Silly, isn't it? Ahoy to Redmond.
53  return false;
54  }
55  if (shellQuote) {
56  rsts = KShell::quoteArgInternal(rst.join(QLatin1Char(' ')), true);
57  } else {
58  if (rst.isEmpty()) {
59  str.remove(pos, len);
60  continue;
61  }
62  rsts = KShell::joinArgs(rst);
63  }
64  pos2 = 0;
65  while (pos2 < rsts.length() && ((uc = rsts.unicode()[pos2].unicode()) == '\\' || uc == '^')) {
66  pos2++;
67  }
68  if (pos2 < rsts.length() && rsts.unicode()[pos2].unicode() == '"') {
69  QString bsl;
70  bsl.reserve(bslashes);
71  for (; bslashes; bslashes--) {
72  bsl.append(QLatin1String("\\"));
73  }
74  rsts.prepend(bsl);
75  }
76  bslashes = 0;
77  rst.clear();
78  str.replace(pos, len, rsts);
79  pos += rsts.length();
80  continue;
81  nohit:
82  if (!escaped && !shellQuote && cc == '^') {
83  escaped = true;
84  } else {
85  notcf:
86  if (cc == '\\') {
87  bslashes++;
88  } else {
89  if (cc == '"') {
90  if (!escaped) {
91  shellQuote = !shellQuote;
92  }
93  if (!(bslashes & 1)) {
94  crtQuote = !crtQuote;
95  }
96  } else if (!shellQuote) {
97  if (cc == '(') {
98  parens++;
99  } else if (cc == ')')
100  if (--parens < 0) {
101  break;
102  }
103  }
104  bslashes = 0;
105  }
106  escaped = false;
107  }
108  pos++;
109  }
110  return true;
111 }
void clear()
QString & append(QChar ch)
bool expandMacrosShellQuote(QString &str, int &pos)
Perform safe macro expansion (substitution) on a string for use in shell commands.
QString & prepend(QChar ch)
QString join(const QString &separator) const const
QString & remove(int position, int n)
virtual int expandEscapedMacro(const QString &str, int pos, QStringList &ret)
This function is called every time the escape char is found if it is not QChar::null.
bool isEmpty() const const
virtual int expandPlainMacro(const QString &str, int pos, QStringList &ret)
This function is called for every single char within the string if the escape char is QChar::null...
ushort unicode() const const
QString & replace(int position, int n, QChar after)
const QChar * unicode() const const
int length() const const
void reserve(int size)
KCOREADDONS_EXPORT QString joinArgs(const QStringList &args)
Quotes and joins args together according to system shell rules.
Definition: kshell.cpp:23
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Apr 18 2021 23:02:02 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.