23 #include <kmacroexpander.h>
25 #include <tqvaluestack.h>
53 TQChar ec( escapechar );
57 for (pos = 0; pos < str.length(); ) {
58 if (ec != (TQChar)0) {
59 if (str.unicode()[pos] != ec)
71 rsts = rst.join(
" " );
73 str.replace( pos, len, rsts );
85 enum Quoting { noquote, singlequote, doublequote, dollarquote,
86 paren, subst, group, math };
100 bool KMacroExpanderBase::expandMacrosShellQuote( TQString &str, uint &pos )
104 TQChar ec( escapechar );
105 State state = { noquote,
false };
106 TQValueStack<State> sstack;
107 TQValueStack<Save> ostack;
111 while (pos < str.length()) {
112 TQChar cc( str.unicode()[pos] );
113 if (ec != (TQChar)0) {
116 if (!(len = expandEscapedMacro( str, pos, rst )))
119 if (!(len = expandPlainMacro( str, pos, rst )))
127 rsts = rst.join(
" " );
128 rsts.replace( TQRegExp(
"([$`\"\\\\])"),
"\\\\1" );
129 }
else if (state.current == dollarquote) {
130 rsts = rst.join(
" " );
131 rsts.replace( TQRegExp(
"(['\\\\])"),
"\\\\1" );
132 }
else if (state.current == singlequote) {
133 rsts = rst.join(
" " );
134 rsts.replace(
'\'',
"'\\''");
137 str.remove( pos, len );
142 for (TQStringList::Iterator it = rst.begin(); it != rst.end(); ++it)
143 (*it).replace(
'\'',
"'\\''" );
144 rsts += rst.join(
"' '" );
146 for (TQStringList::ConstIterator it = rst.begin(); it != rst.end(); ++it) {
147 if (it != rst.begin())
149 TQString trsts( *it );
150 trsts.replace(
'\'',
"'\\''" );
158 str.replace( pos, len, rsts );
159 pos += rsts.length();
162 if (state.current == singlequote) {
163 if (cc == (TQChar)
'\'')
164 state = sstack.pop();
165 }
else if (cc == (TQChar)
'\\') {
169 }
else if (state.current == dollarquote) {
170 if (cc == (TQChar)
'\'')
171 state = sstack.pop();
172 }
else if (cc == (TQChar)
'$') {
174 if (cc == (TQChar)
'(') {
175 sstack.push( state );
176 if (str[pos + 1] == (TQChar)
'(') {
177 Save sav = { str, pos + 2 };
179 state.current = math;
183 state.current = paren;
184 state.dquote =
false;
186 }
else if (cc == (TQChar)
'{') {
187 sstack.push( state );
188 state.current = subst;
189 }
else if (!state.dquote) {
190 if (cc == (TQChar)
'\'') {
191 sstack.push( state );
192 state.current = dollarquote;
193 }
else if (cc == (TQChar)
'"') {
194 sstack.push( state );
195 state.current = doublequote;
200 }
else if (cc == (TQChar)
'`') {
201 str.replace( pos, 1,
"$( " );
204 if (pos2 >= str.length()) {
208 cc = str.unicode()[pos2];
209 if (cc == (TQChar)
'`')
211 if (cc == (TQChar)
'\\') {
213 if (cc == (TQChar)
'$' || cc == (TQChar)
'`' || cc == (TQChar)
'\\' ||
214 (cc == (TQChar)
'"' && state.dquote))
216 str.remove( pos2 - 1, 1 );
223 sstack.push( state );
224 state.current = paren;
225 state.dquote =
false;
227 }
else if (state.current == doublequote) {
228 if (cc == (TQChar)
'"')
229 state = sstack.pop();
230 }
else if (cc == (TQChar)
'\'') {
232 sstack.push( state );
233 state.current = singlequote;
235 }
else if (cc == (TQChar)
'"') {
237 sstack.push( state );
238 state.current = doublequote;
241 }
else if (state.current == subst) {
242 if (cc == (TQChar)
'}')
243 state = sstack.pop();
244 }
else if (cc == (TQChar)
')') {
245 if (state.current == math) {
246 if (str[pos + 1] == (TQChar)
')') {
247 state = sstack.pop();
252 pos = ostack.top().pos;
253 str = ostack.top().str;
255 state.current = paren;
256 state.dquote =
false;
257 sstack.push( state );
260 }
else if (state.current == paren)
261 state = sstack.pop();
264 }
else if (cc == (TQChar)
'}') {
265 if (state.current == KMacroExpander::group)
266 state = sstack.pop();
269 }
else if (cc == (TQChar)
'(') {
270 sstack.push( state );
271 state.current = paren;
272 }
else if (cc == (TQChar)
'{') {
273 sstack.push( state );
274 state.current = KMacroExpander::group;
278 return sstack.empty();
281 bool KMacroExpanderBase::expandMacrosShellQuote( TQString &str )
288 { tqFatal(
"KMacroExpanderBase::expandPlainMacro called!" );
return 0; }
291 { tqFatal(
"KMacroExpanderBase::expandEscapedMacro called!" );
return 0; }
296 template<
class KT,
class VT>
300 KMacroMapExpander(
const TQMap<KT,VT> &map, TQChar c =
'%' ) :
304 virtual int expandPlainMacro(
const TQString &str, uint pos, TQStringList &ret );
305 virtual int expandEscapedMacro(
const TQString &str, uint pos, TQStringList &ret );
308 TQMap<KT,VT> macromap;
311 static TQStringList &operator+=( TQStringList &s,
const TQString &n) { s << n;
return s; }
316 isIdentifier( uint c )
318 return c ==
'_' || (c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z') || (c >=
'0' && c <=
'9');
327 KMacroMapExpander(
const TQMap<TQChar,VT> &map, TQChar c =
'%' ) :
331 virtual int expandPlainMacro(
const TQString &str, uint pos, TQStringList &ret );
332 virtual int expandEscapedMacro(
const TQString &str, uint pos, TQStringList &ret );
335 TQMap<TQChar,VT> macromap;
340 KMacroMapExpander<TQChar,VT>::expandPlainMacro(
const TQString &str, uint pos, TQStringList &ret )
342 TQMapConstIterator<TQChar,VT> it = macromap.find(str[pos]);
343 if (it != macromap.end()) {
352 KMacroMapExpander<TQChar,VT>::expandEscapedMacro(
const TQString &str, uint pos, TQStringList &ret )
354 if (str[pos + 1] == escapeChar()) {
355 ret += TQString( escapeChar() );
358 TQMapConstIterator<TQChar,VT> it = macromap.find(str[pos+1]);
359 if (it != macromap.end()) {
371 KMacroMapExpander(
const TQMap<TQString,VT> &map, TQChar c =
'%' ) :
375 virtual int expandPlainMacro(
const TQString &str, uint pos, TQStringList &ret );
376 virtual int expandEscapedMacro(
const TQString &str, uint pos, TQStringList &ret );
379 TQMap<TQString,VT> macromap;
384 KMacroMapExpander<TQString,VT>::expandPlainMacro(
const TQString &str, uint pos, TQStringList &ret )
386 if (isIdentifier( str[pos - 1].unicode() ))
389 for (sl = 0; isIdentifier( str[pos + sl].unicode() ); sl++);
392 TQMapConstIterator<TQString,VT> it =
393 macromap.find( TQConstString( str.unicode() + pos, sl ).string() );
394 if (it != macromap.end()) {
403 KMacroMapExpander<TQString,VT>::expandEscapedMacro(
const TQString &str, uint pos, TQStringList &ret )
405 if (str[pos + 1] == escapeChar()) {
406 ret += TQString( escapeChar() );
410 if (str[pos + 1] == (TQChar)
'{') {
412 for (sl = 0; str[rpos + sl] != (TQChar)
'}'; sl++)
413 if (rpos + sl >= str.length())
418 for (sl = 0; isIdentifier( str[rpos + sl].unicode() ); sl++);
423 TQMapConstIterator<TQString,VT> it =
424 macromap.find( TQConstString( str.unicode() + rpos, sl ).string() );
425 if (it != macromap.end()) {
437 if (expandMacro( str[pos], ret ))
445 if (str[pos + 1] == escapeChar()) {
446 ret += TQString( escapeChar() );
449 if (expandMacro( str[pos+1], ret ))
457 if (isIdentifier( str[pos - 1].unicode() ))
460 for (sl = 0; isIdentifier( str[pos + sl].unicode() ); sl++);
463 if (expandMacro( TQConstString( str.unicode() + pos, sl ).string(), ret ))
471 if (str[pos + 1] == escapeChar()) {
472 ret += TQString( escapeChar() );
476 if (str[pos + 1] == (TQChar)
'{') {
478 for (sl = 0; str[rpos + sl] != (TQChar)
'}'; sl++)
479 if (rpos + sl >= str.length())
484 for (sl = 0; isIdentifier( str[rpos + sl].unicode() ); sl++);
489 if (expandMacro( TQConstString( str.unicode() + rpos, sl ).string(), ret ))
496 template<
class KT,
class VT>
498 TexpandMacros(
const TQString &ostr,
const TQMap<KT,VT> &map, TQChar c )
500 TQString str( ostr );
501 KMacroMapExpander<KT,VT> kmx( map, c );
502 kmx.expandMacros( str );
506 template<
class KT,
class VT>
508 TexpandMacrosShellQuote(
const TQString &ostr,
const TQMap<KT,VT> &map, TQChar c )
510 TQString str( ostr );
511 KMacroMapExpander<KT,VT> kmx( map, c );
512 if (!kmx.expandMacrosShellQuote( str ))
520 TQString
expandMacros(
const TQString &ostr,
const TQMap<TQChar,TQString> &map, TQChar c ) {
return TexpandMacros( ostr, map, c ); }
521 TQString
expandMacrosShellQuote(
const TQString &ostr,
const TQMap<TQChar,TQString> &map, TQChar c ) {
return TexpandMacrosShellQuote( ostr, map, c ); }
522 TQString
expandMacros(
const TQString &ostr,
const TQMap<TQString,TQString> &map, TQChar c ) {
return TexpandMacros( ostr, map, c ); }
523 TQString
expandMacrosShellQuote(
const TQString &ostr,
const TQMap<TQString,TQString> &map, TQChar c ) {
return TexpandMacrosShellQuote( ostr, map, c ); }
524 TQString
expandMacros(
const TQString &ostr,
const TQMap<TQChar,TQStringList> &map, TQChar c ) {
return TexpandMacros( ostr, map, c ); }
525 TQString
expandMacrosShellQuote(
const TQString &ostr,
const TQMap<TQChar,TQStringList> &map, TQChar c ) {
return TexpandMacrosShellQuote( ostr, map, c ); }
526 TQString
expandMacros(
const TQString &ostr,
const TQMap<TQString,TQStringList> &map, TQChar c ) {
return TexpandMacros( ostr, map, c ); }
527 TQString
expandMacrosShellQuote(
const TQString &ostr,
const TQMap<TQString,TQStringList> &map, TQChar c ) {
return TexpandMacrosShellQuote( ostr, map, c ); }
virtual int expandEscapedMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called every time the escape char is found if it is not TQChar::null.
virtual int expandPlainMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called for every single char within the string if the escape char is TQChar::null.
Abstract base class for the worker classes behind the KMacroExpander namespace and the KCharMacroExpa...
void setEscapeChar(TQChar c)
Set the macro escape character.
virtual int expandPlainMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called for every single char within the string if the escape char is TQChar::null.
virtual int expandEscapedMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called every time the escape char is found if it is not TQChar::null.
void expandMacros(TQString &str)
Perform safe macro expansion (substitution) on a string.
virtual ~KMacroExpanderBase()
Destructor.
KMacroExpanderBase(TQChar c='%')
Constructor.
TQChar escapeChar() const
Obtain the macro escape character.
virtual int expandPlainMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called for every single char within the string if the escape char is TQChar::null.
virtual int expandEscapedMacro(const TQString &str, uint pos, TQStringList &ret)
This function is called every time the escape char is found if it is not TQChar::null.
A group of functions providing macro expansion (substitution) in strings, optionally with quoting app...
TQString expandMacros(const TQString &ostr, const TQMap< TQChar, TQString > &map, TQChar c)
Perform safe macro expansion (substitution) on a string.
TQString expandMacrosShellQuote(const TQString &ostr, const TQMap< TQChar, TQString > &map, TQChar c)
Perform safe macro expansion (substitution) on a string for use in shell commands.