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() &&
66  ((uc = rsts.unicode()[pos2].unicode()) == '\\' || uc == '^')) {
67  pos2++;
68  }
69  if (pos2 < rsts.length() && rsts.unicode()[pos2].unicode() == '"') {
70  QString bsl;
71  bsl.reserve(bslashes);
72  for (; bslashes; bslashes--) {
73  bsl.append(QLatin1String("\\"));
74  }
75  rsts.prepend(bsl);
76  }
77  bslashes = 0;
78  rst.clear();
79  str.replace(pos, len, rsts);
80  pos += rsts.length();
81  continue;
82  nohit:
83  if (!escaped && !shellQuote && cc == '^') {
84  escaped = true;
85  } else {
86  notcf:
87  if (cc == '\\') {
88  bslashes++;
89  } else {
90  if (cc == '"') {
91  if (!escaped) {
92  shellQuote = !shellQuote;
93  }
94  if (!(bslashes & 1)) {
95  crtQuote = !crtQuote;
96  }
97  } else if (!shellQuote) {
98  if (cc == '(') {
99  parens++;
100  } else if (cc == ')')
101  if (--parens < 0) {
102  break;
103  }
104  }
105  bslashes = 0;
106  }
107  escaped = false;
108  }
109  pos++;
110  }
111  return true;
112 }
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-2020 The KDE developers.
Generated on Sun May 31 2020 23:11:13 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.