1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * return string with expanded escape chars 28 */ 29 30 #include <ast.h> 31 #include <ccode.h> 32 #include <ctype.h> 33 #if _hdr_wchar && _hdr_wctype 34 #include <wchar.h> 35 #include <wctype.h> 36 #endif 37 38 /* 39 * quote string as of length n with qb...qe 40 * (flags&FMT_ALWAYS) always quotes, otherwise quote output only if necessary 41 * qe and the usual suspects are \... escaped 42 * (flags&FMT_WIDE) doesn't escape 8 bit chars 43 * (flags&FMT_ESCAPED) doesn't \... escape the usual suspects 44 * (flags&FMT_SHELL) escape $`"#;~&|()<>[]*? 45 */ 46 47 char* 48 fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags) 49 { 50 register unsigned char* s = (unsigned char*)as; 51 register unsigned char* e = s + n; 52 register char* b; 53 register int c; 54 register int m; 55 register int escaped; 56 register int spaced; 57 register int doublequote; 58 register int singlequote; 59 int shell; 60 char* f; 61 char* buf; 62 63 c = 4 * (n + 1); 64 if (qb) 65 c += strlen((char*)qb); 66 if (qe) 67 c += strlen((char*)qe); 68 b = buf = fmtbuf(c); 69 shell = 0; 70 doublequote = 0; 71 singlequote = 0; 72 if (qb) 73 { 74 if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0) 75 shell = 1; 76 else if ((flags & FMT_SHELL) && qb[1] == 0) 77 { 78 if (qb[0] == '"') 79 doublequote = 1; 80 else if (qb[0] == '\'') 81 singlequote = 1; 82 } 83 while (*b = *qb++) 84 b++; 85 } 86 else if (flags & FMT_SHELL) 87 doublequote = 1; 88 f = b; 89 escaped = spaced = !!(flags & FMT_ALWAYS); 90 while (s < e) 91 { 92 if ((m = mbsize(s)) > 1 && (s + m) <= e) 93 { 94 #if _hdr_wchar && _hdr_wctype 95 c = mbchar(s); 96 if (!spaced && !escaped && (iswspace(c) || iswcntrl(c))) 97 spaced = 1; 98 s -= m; 99 #endif 100 while (m--) 101 *b++ = *s++; 102 } 103 else 104 { 105 c = *s++; 106 if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\')) 107 { 108 escaped = 1; 109 *b++ = '\\'; 110 switch (c) 111 { 112 case CC_bel: 113 c = 'a'; 114 break; 115 case '\b': 116 c = 'b'; 117 break; 118 case '\f': 119 c = 'f'; 120 break; 121 case '\n': 122 c = 'n'; 123 break; 124 case '\r': 125 c = 'r'; 126 break; 127 case '\t': 128 c = 't'; 129 break; 130 case CC_vt: 131 c = 'v'; 132 break; 133 case CC_esc: 134 c = 'E'; 135 break; 136 case '\\': 137 break; 138 default: 139 if (!(flags & FMT_WIDE) || !(c & 0200)) 140 { 141 *b++ = '0' + ((c >> 6) & 07); 142 *b++ = '0' + ((c >> 3) & 07); 143 c = '0' + (c & 07); 144 } 145 else 146 b--; 147 break; 148 } 149 } 150 else if (c == '\\') 151 { 152 escaped = 1; 153 *b++ = c; 154 if (*s) 155 c = *s++; 156 } 157 else if (qe && strchr(qe, c)) 158 { 159 if (singlequote && c == '\'') 160 { 161 spaced = 1; 162 *b++ = '\''; 163 *b++ = '\\'; 164 *b++ = '\''; 165 c = '\''; 166 } 167 else 168 { 169 escaped = 1; 170 *b++ = '\\'; 171 } 172 } 173 else if (c == '$' || c == '`') 174 { 175 if (c == '$' && (flags & FMT_PARAM) && (*s == '{' || *s == '(')) 176 { 177 if (singlequote || shell) 178 { 179 escaped = 1; 180 *b++ = '\''; 181 *b++ = c; 182 *b++ = *s++; 183 if (shell) 184 { 185 spaced = 1; 186 *b++ = '$'; 187 } 188 c = '\''; 189 } 190 else 191 { 192 escaped = 1; 193 *b++ = c; 194 c = *s++; 195 } 196 } 197 else if (doublequote) 198 *b++ = '\\'; 199 else if (singlequote || (flags & FMT_SHELL)) 200 spaced = 1; 201 } 202 else if (!spaced && !escaped && (isspace(c) || ((flags & FMT_SHELL) || shell) && (strchr("\";~&|()<>[]*?", c) || c == '#' && (b == f || isspace(*(b - 1)))))) 203 spaced = 1; 204 *b++ = c; 205 } 206 } 207 if (qb) 208 { 209 if (!escaped) 210 buf += shell + !spaced; 211 if (qe && (escaped || spaced)) 212 while (*b = *qe++) 213 b++; 214 } 215 *b = 0; 216 return buf; 217 } 218 219 /* 220 * escape the usual suspects and quote chars in qs 221 * in length n string as 222 */ 223 224 char* 225 fmtnesq(const char* as, const char* qs, size_t n) 226 { 227 return fmtquote(as, NiL, qs, n, 0); 228 } 229 230 /* 231 * escape the usual suspects and quote chars in qs 232 */ 233 234 char* 235 fmtesq(const char* as, const char* qs) 236 { 237 return fmtquote(as, NiL, qs, strlen((char*)as), 0); 238 } 239 240 /* 241 * escape the usual suspects 242 */ 243 244 char* 245 fmtesc(const char* as) 246 { 247 return fmtquote(as, NiL, NiL, strlen((char*)as), 0); 248 } 249