File indexing completed on 2024-04-28 03:53:48
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2008 Oswald Buddenhagen <ossi@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "kmacroexpander_p.h" 0010 #include "kshell_p.h" 0011 0012 #include "kshell.h" 0013 0014 #include <QString> 0015 #include <QStringList> 0016 0017 bool KMacroExpanderBase::expandMacrosShellQuote(QString &str, int &pos) 0018 { 0019 int len; 0020 int pos2; 0021 ushort uc; 0022 ushort ec = d->escapechar.unicode(); 0023 bool shellQuote = false; // shell is in quoted state 0024 bool crtQuote = false; // c runtime is in quoted state 0025 bool escaped = false; // previous char was a circumflex 0026 int bslashes = 0; // previous chars were backslashes 0027 int parens = 0; // parentheses nesting level 0028 QStringList rst; 0029 QString rsts; 0030 0031 while (pos < str.length()) { 0032 ushort cc = str.unicode()[pos].unicode(); 0033 if (escaped) { // prevent anomalies due to expansion 0034 goto notcf; 0035 } 0036 if (ec != 0) { 0037 if (cc != ec) { 0038 goto nohit; 0039 } 0040 if (!(len = expandEscapedMacro(str, pos, rst))) { 0041 goto nohit; 0042 } 0043 } else { 0044 if (!(len = expandPlainMacro(str, pos, rst))) { 0045 goto nohit; 0046 } 0047 } 0048 if (len < 0) { 0049 pos -= len; 0050 continue; 0051 } 0052 if (shellQuote != crtQuote) { // Silly, isn't it? Ahoy to Redmond. 0053 return false; 0054 } 0055 if (shellQuote) { 0056 rsts = KShell::quoteArgInternal(rst.join(QLatin1Char(' ')), true); 0057 } else { 0058 if (rst.isEmpty()) { 0059 str.remove(pos, len); 0060 continue; 0061 } 0062 rsts = KShell::joinArgs(rst); 0063 } 0064 pos2 = 0; 0065 while (pos2 < rsts.length() && ((uc = rsts.unicode()[pos2].unicode()) == '\\' || uc == '^')) { 0066 pos2++; 0067 } 0068 if (pos2 < rsts.length() && rsts.unicode()[pos2].unicode() == '"') { 0069 QString bsl; 0070 bsl.reserve(bslashes); 0071 for (; bslashes; bslashes--) { 0072 bsl.append(QLatin1String("\\")); 0073 } 0074 rsts.prepend(bsl); 0075 } 0076 bslashes = 0; 0077 rst.clear(); 0078 str.replace(pos, len, rsts); 0079 pos += rsts.length(); 0080 continue; 0081 nohit: 0082 if (!escaped && !shellQuote && cc == '^') { 0083 escaped = true; 0084 } else { 0085 notcf: 0086 if (cc == '\\') { 0087 bslashes++; 0088 } else { 0089 if (cc == '"') { 0090 if (!escaped) { 0091 shellQuote = !shellQuote; 0092 } 0093 if (!(bslashes & 1)) { 0094 crtQuote = !crtQuote; 0095 } 0096 } else if (!shellQuote) { 0097 if (cc == '(') { 0098 parens++; 0099 } else if (cc == ')') 0100 if (--parens < 0) { 0101 break; 0102 } 0103 } 0104 bslashes = 0; 0105 } 0106 escaped = false; 0107 } 0108 pos++; 0109 } 0110 return true; 0111 }