KDECore
kmacroexpander_unix.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kmacroexpander_p.h"
00024
00025 #include "kshell.h"
00026
00027 #include <QtCore/QStringList>
00028 #include <QtCore/QStack>
00029 #include <QtCore/QRegExp>
00030
00031 namespace KMacroExpander {
00032
00033 enum Quoting { noquote, singlequote, doublequote, dollarquote,
00034 paren, subst, group, math };
00035 typedef struct {
00036 Quoting current;
00037 bool dquote;
00038 } State;
00039 typedef struct {
00040 QString str;
00041 int pos;
00042 } Save;
00043
00044 }
00045
00046 using namespace KMacroExpander;
00047
00048 bool KMacroExpanderBase::expandMacrosShellQuote( QString &str, int &pos )
00049 {
00050 int len;
00051 int pos2;
00052 ushort ec = d->escapechar.unicode();
00053 State state = { noquote, false };
00054 QStack<State> sstack;
00055 QStack<Save> ostack;
00056 QStringList rst;
00057 QString rsts;
00058
00059 while (pos < str.length()) {
00060 ushort cc = str.unicode()[pos].unicode();
00061 if (ec != 0) {
00062 if (cc != ec)
00063 goto nohit;
00064 if (!(len = expandEscapedMacro( str, pos, rst )))
00065 goto nohit;
00066 } else {
00067 if (!(len = expandPlainMacro( str, pos, rst )))
00068 goto nohit;
00069 }
00070 if (len < 0) {
00071 pos -= len;
00072 continue;
00073 }
00074 if (state.dquote) {
00075 rsts = rst.join( QLatin1String(" ") );
00076 rsts.replace( QRegExp(QLatin1String("([$`\"\\\\])")), QLatin1String("\\\\1") );
00077 } else if (state.current == dollarquote) {
00078 rsts = rst.join( QLatin1String(" ") );
00079 rsts.replace( QRegExp(QLatin1String("(['\\\\])")), QLatin1String("\\\\1") );
00080 } else if (state.current == singlequote) {
00081 rsts = rst.join( QLatin1String(" ") );
00082 rsts.replace( QLatin1Char('\''), QLatin1String("'\\''") );
00083 } else {
00084 if (rst.isEmpty()) {
00085 str.remove( pos, len );
00086 continue;
00087 } else {
00088 rsts = KShell::joinArgs( rst );
00089 }
00090 }
00091 rst.clear();
00092 str.replace( pos, len, rsts );
00093 pos += rsts.length();
00094 continue;
00095 nohit:
00096 if (state.current == singlequote) {
00097 if (cc == '\'')
00098 state = sstack.pop();
00099 } else if (cc == '\\') {
00100
00101 pos += 2;
00102 continue;
00103 } else if (state.current == dollarquote) {
00104 if (cc == '\'')
00105 state = sstack.pop();
00106 } else if (cc == '$') {
00107 cc = str.unicode()[++pos].unicode();
00108 if (cc == '(') {
00109 sstack.push( state );
00110 if (str.unicode()[pos + 1].unicode() == '(') {
00111 Save sav = { str, pos + 2 };
00112 ostack.push( sav );
00113 state.current = math;
00114 pos += 2;
00115 continue;
00116 } else {
00117 state.current = paren;
00118 state.dquote = false;
00119 }
00120 } else if (cc == '{') {
00121 sstack.push( state );
00122 state.current = subst;
00123 } else if (!state.dquote) {
00124 if (cc == '\'') {
00125 sstack.push( state );
00126 state.current = dollarquote;
00127 } else if (cc == '"') {
00128 sstack.push( state );
00129 state.current = doublequote;
00130 state.dquote = true;
00131 }
00132 }
00133
00134 } else if (cc == '`') {
00135 str.replace( pos, 1, QLatin1String("$( " ));
00136 pos2 = pos += 3;
00137 for (;;) {
00138 if (pos2 >= str.length()) {
00139 pos = pos2;
00140 return false;
00141 }
00142 cc = str.unicode()[pos2].unicode();
00143 if (cc == '`')
00144 break;
00145 if (cc == '\\') {
00146 cc = str.unicode()[++pos2].unicode();
00147 if (cc == '$' || cc == '`' || cc == '\\' ||
00148 (cc == '"' && state.dquote))
00149 {
00150 str.remove( pos2 - 1, 1 );
00151 continue;
00152 }
00153 }
00154 pos2++;
00155 }
00156 str[pos2] = QLatin1Char(')');
00157 sstack.push( state );
00158 state.current = paren;
00159 state.dquote = false;
00160 continue;
00161 } else if (state.current == doublequote) {
00162 if (cc == '"')
00163 state = sstack.pop();
00164 } else if (cc == '\'') {
00165 if (!state.dquote) {
00166 sstack.push( state );
00167 state.current = singlequote;
00168 }
00169 } else if (cc == '"') {
00170 if (!state.dquote) {
00171 sstack.push( state );
00172 state.current = doublequote;
00173 state.dquote = true;
00174 }
00175 } else if (state.current == subst) {
00176 if (cc == '}')
00177 state = sstack.pop();
00178 } else if (cc == ')') {
00179 if (state.current == math) {
00180 if (str.unicode()[pos + 1].unicode() == ')') {
00181 state = sstack.pop();
00182 pos += 2;
00183 } else {
00184
00185
00186 pos = ostack.top().pos;
00187 str = ostack.top().str;
00188 ostack.pop();
00189 state.current = paren;
00190 state.dquote = false;
00191 sstack.push( state );
00192 }
00193 continue;
00194 } else if (state.current == paren)
00195 state = sstack.pop();
00196 else
00197 break;
00198 } else if (cc == '}') {
00199 if (state.current == KMacroExpander::group)
00200 state = sstack.pop();
00201 else
00202 break;
00203 } else if (cc == '(') {
00204 sstack.push( state );
00205 state.current = paren;
00206 } else if (cc == '{') {
00207 sstack.push( state );
00208 state.current = KMacroExpander::group;
00209 }
00210 pos++;
00211 }
00212 return sstack.empty();
00213 }