1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 34 /* 35 * quote string as of length n with qb...qe 36 * (flags&FMT_ALWAYS) always quotes, otherwise quote output only if necessary 37 * qe and the usual suspects are \... escaped 38 * (flags&FMT_WIDE) doesn't escape 8 bit chars 39 * (flags&FMT_ESCAPED) doesn't \... escape the usual suspects 40 * (flags&FMT_SHELL) escape $`"#;~&|()<>[]*? 41 */ 42 43 char* 44 fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags) 45 { 46 register unsigned char* s = (unsigned char*)as; 47 register unsigned char* e = s + n; 48 register char* b; 49 register int c; 50 register int escaped; 51 register int spaced; 52 register int doublequote; 53 register int singlequote; 54 int shell; 55 char* f; 56 char* buf; 57 58 c = 4 * (n + 1); 59 if (qb) 60 c += strlen((char*)qb); 61 if (qe) 62 c += strlen((char*)qe); 63 b = buf = fmtbuf(c); 64 shell = 0; 65 doublequote = 0; 66 singlequote = 0; 67 if (qb) 68 { 69 if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0) 70 shell = 1; 71 else if ((flags & FMT_SHELL) && qb[1] == 0) 72 { 73 if (qb[0] == '"') 74 doublequote = 1; 75 else if (qb[0] == '\'') 76 singlequote = 1; 77 } 78 while (*b = *qb++) 79 b++; 80 } 81 else if (flags & FMT_SHELL) 82 doublequote = 1; 83 f = b; 84 escaped = spaced = !!(flags & FMT_ALWAYS); 85 while (s < e) 86 { 87 if ((c = mbsize(s)) > 1) 88 { 89 while (c-- && s < e) 90 *b++ = *s++; 91 } 92 else 93 { 94 c = *s++; 95 if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\')) 96 { 97 escaped = 1; 98 *b++ = '\\'; 99 switch (c) 100 { 101 case CC_bel: 102 c = 'a'; 103 break; 104 case '\b': 105 c = 'b'; 106 break; 107 case '\f': 108 c = 'f'; 109 break; 110 case '\n': 111 c = 'n'; 112 break; 113 case '\r': 114 c = 'r'; 115 break; 116 case '\t': 117 c = 't'; 118 break; 119 case CC_vt: 120 c = 'v'; 121 break; 122 case CC_esc: 123 c = 'E'; 124 break; 125 case '\\': 126 break; 127 default: 128 if (!(flags & FMT_WIDE) || !(c & 0200)) 129 { 130 *b++ = '0' + ((c >> 6) & 07); 131 *b++ = '0' + ((c >> 3) & 07); 132 c = '0' + (c & 07); 133 } 134 else 135 b--; 136 break; 137 } 138 } 139 else if (c == '\\') 140 { 141 escaped = 1; 142 *b++ = c; 143 if (*s) 144 c = *s++; 145 } 146 else if (qe && strchr(qe, c)) 147 { 148 if (singlequote && c == '\'') 149 { 150 spaced = 1; 151 *b++ = '\''; 152 *b++ = '\\'; 153 *b++ = '\''; 154 c = '\''; 155 } 156 else 157 { 158 escaped = 1; 159 *b++ = '\\'; 160 } 161 } 162 else if (c == '$' || c == '`') 163 { 164 if (c == '$' && (flags & FMT_PARAM) && (*s == '{' || *s == '(')) 165 { 166 if (singlequote || shell) 167 { 168 escaped = 1; 169 *b++ = '\''; 170 *b++ = c; 171 *b++ = *s++; 172 if (shell) 173 { 174 spaced = 1; 175 *b++ = '$'; 176 } 177 c = '\''; 178 } 179 else 180 { 181 escaped = 1; 182 *b++ = c; 183 c = *s++; 184 } 185 } 186 else if (doublequote) 187 *b++ = '\\'; 188 else if (singlequote || (flags & FMT_SHELL)) 189 spaced = 1; 190 } 191 else if (!spaced && !escaped && (isspace(c) || ((flags & FMT_SHELL) || shell) && (strchr("\";~&|()<>[]*?", c) || c == '#' && (b == f || isspace(*(b - 1)))))) 192 spaced = 1; 193 *b++ = c; 194 } 195 } 196 if (qb) 197 { 198 if (!escaped) 199 buf += shell + !spaced; 200 if (qe && (escaped || spaced)) 201 while (*b = *qe++) 202 b++; 203 } 204 *b = 0; 205 return buf; 206 } 207 208 /* 209 * escape the usual suspects and quote chars in qs 210 * in length n string as 211 */ 212 213 char* 214 fmtnesq(const char* as, const char* qs, size_t n) 215 { 216 return fmtquote(as, NiL, qs, n, 0); 217 } 218 219 /* 220 * escape the usual suspects and quote chars in qs 221 */ 222 223 char* 224 fmtesq(const char* as, const char* qs) 225 { 226 return fmtquote(as, NiL, qs, strlen((char*)as), 0); 227 } 228 229 /* 230 * escape the usual suspects 231 */ 232 233 char* 234 fmtesc(const char* as) 235 { 236 return fmtquote(as, NiL, NiL, strlen((char*)as), 0); 237 } 238