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