14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin * Glenn Fowler
254887Schin * AT&T Research
264887Schin *
274887Schin * return string with expanded escape chars
284887Schin */
294887Schin
304887Schin #include <ast.h>
314887Schin #include <ccode.h>
324887Schin #include <ctype.h>
334887Schin
344887Schin /*
354887Schin * quote string as of length n with qb...qe
364887Schin * (flags&FMT_ALWAYS) always quotes, otherwise quote output only if necessary
374887Schin * qe and the usual suspects are \... escaped
384887Schin * (flags&FMT_WIDE) doesn't escape 8 bit chars
394887Schin * (flags&FMT_ESCAPED) doesn't \... escape the usual suspects
404887Schin * (flags&FMT_SHELL) escape $`"#;~&|()<>[]*?
414887Schin */
424887Schin
434887Schin char*
fmtquote(const char * as,const char * qb,const char * qe,size_t n,int flags)444887Schin fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags)
454887Schin {
464887Schin register unsigned char* s = (unsigned char*)as;
474887Schin register unsigned char* e = s + n;
484887Schin register char* b;
494887Schin register int c;
504887Schin register int escaped;
514887Schin register int spaced;
524887Schin register int doublequote;
534887Schin register int singlequote;
544887Schin int shell;
554887Schin char* f;
564887Schin char* buf;
574887Schin
584887Schin c = 4 * (n + 1);
594887Schin if (qb)
604887Schin c += strlen((char*)qb);
614887Schin if (qe)
624887Schin c += strlen((char*)qe);
634887Schin b = buf = fmtbuf(c);
644887Schin shell = 0;
654887Schin doublequote = 0;
664887Schin singlequote = 0;
674887Schin if (qb)
684887Schin {
694887Schin if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0)
704887Schin shell = 1;
714887Schin else if ((flags & FMT_SHELL) && qb[1] == 0)
724887Schin {
734887Schin if (qb[0] == '"')
744887Schin doublequote = 1;
754887Schin else if (qb[0] == '\'')
764887Schin singlequote = 1;
774887Schin }
784887Schin while (*b = *qb++)
794887Schin b++;
804887Schin }
814887Schin else if (flags & FMT_SHELL)
824887Schin doublequote = 1;
834887Schin f = b;
844887Schin escaped = spaced = !!(flags & FMT_ALWAYS);
854887Schin while (s < e)
864887Schin {
874887Schin if ((c = mbsize(s)) > 1)
884887Schin {
894887Schin while (c-- && s < e)
904887Schin *b++ = *s++;
914887Schin }
924887Schin else
934887Schin {
944887Schin c = *s++;
954887Schin if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\'))
964887Schin {
974887Schin escaped = 1;
984887Schin *b++ = '\\';
994887Schin switch (c)
1004887Schin {
1014887Schin case CC_bel:
1024887Schin c = 'a';
1034887Schin break;
1044887Schin case '\b':
1054887Schin c = 'b';
1064887Schin break;
1074887Schin case '\f':
1084887Schin c = 'f';
1094887Schin break;
1104887Schin case '\n':
1114887Schin c = 'n';
1124887Schin break;
1134887Schin case '\r':
1144887Schin c = 'r';
1154887Schin break;
1164887Schin case '\t':
1174887Schin c = 't';
1184887Schin break;
1194887Schin case CC_vt:
1204887Schin c = 'v';
1214887Schin break;
1224887Schin case CC_esc:
1234887Schin c = 'E';
1244887Schin break;
1254887Schin case '\\':
1264887Schin break;
1274887Schin default:
1284887Schin if (!(flags & FMT_WIDE) || !(c & 0200))
1294887Schin {
1304887Schin *b++ = '0' + ((c >> 6) & 07);
1314887Schin *b++ = '0' + ((c >> 3) & 07);
1324887Schin c = '0' + (c & 07);
1334887Schin }
1344887Schin else
1354887Schin b--;
1364887Schin break;
1374887Schin }
1384887Schin }
1394887Schin else if (c == '\\')
1404887Schin {
1414887Schin escaped = 1;
1424887Schin *b++ = c;
1434887Schin if (*s)
1444887Schin c = *s++;
1454887Schin }
1464887Schin else if (qe && strchr(qe, c))
1474887Schin {
1484887Schin if (singlequote && c == '\'')
1494887Schin {
1504887Schin spaced = 1;
1514887Schin *b++ = '\'';
1524887Schin *b++ = '\\';
1534887Schin *b++ = '\'';
1544887Schin c = '\'';
1554887Schin }
1564887Schin else
1574887Schin {
1584887Schin escaped = 1;
1594887Schin *b++ = '\\';
1604887Schin }
1614887Schin }
1624887Schin else if (c == '$' || c == '`')
1634887Schin {
1644887Schin if (c == '$' && (flags & FMT_PARAM) && (*s == '{' || *s == '('))
1654887Schin {
1664887Schin if (singlequote || shell)
1674887Schin {
1684887Schin escaped = 1;
1694887Schin *b++ = '\'';
1704887Schin *b++ = c;
1714887Schin *b++ = *s++;
1724887Schin if (shell)
1734887Schin {
1744887Schin spaced = 1;
1754887Schin *b++ = '$';
1764887Schin }
1774887Schin c = '\'';
1784887Schin }
1794887Schin else
1804887Schin {
1814887Schin escaped = 1;
1824887Schin *b++ = c;
1834887Schin c = *s++;
1844887Schin }
1854887Schin }
1864887Schin else if (doublequote)
1874887Schin *b++ = '\\';
1884887Schin else if (singlequote || (flags & FMT_SHELL))
1894887Schin spaced = 1;
1904887Schin }
1914887Schin else if (!spaced && !escaped && (isspace(c) || ((flags & FMT_SHELL) || shell) && (strchr("\";~&|()<>[]*?", c) || c == '#' && (b == f || isspace(*(b - 1))))))
1924887Schin spaced = 1;
1934887Schin *b++ = c;
1944887Schin }
1954887Schin }
1964887Schin if (qb)
1974887Schin {
1984887Schin if (!escaped)
1994887Schin buf += shell + !spaced;
2004887Schin if (qe && (escaped || spaced))
2014887Schin while (*b = *qe++)
2024887Schin b++;
2034887Schin }
2044887Schin *b = 0;
2054887Schin return buf;
2064887Schin }
2074887Schin
2084887Schin /*
2094887Schin * escape the usual suspects and quote chars in qs
2104887Schin * in length n string as
2114887Schin */
2124887Schin
2134887Schin char*
fmtnesq(const char * as,const char * qs,size_t n)2144887Schin fmtnesq(const char* as, const char* qs, size_t n)
2154887Schin {
2164887Schin return fmtquote(as, NiL, qs, n, 0);
2174887Schin }
2184887Schin
2194887Schin /*
2204887Schin * escape the usual suspects and quote chars in qs
2214887Schin */
2224887Schin
2234887Schin char*
fmtesq(const char * as,const char * qs)2244887Schin fmtesq(const char* as, const char* qs)
2254887Schin {
2264887Schin return fmtquote(as, NiL, qs, strlen((char*)as), 0);
2274887Schin }
2284887Schin
2294887Schin /*
2304887Schin * escape the usual suspects
2314887Schin */
2324887Schin
2334887Schin char*
fmtesc(const char * as)2344887Schin fmtesc(const char* as)
2354887Schin {
2364887Schin return fmtquote(as, NiL, NiL, strlen((char*)as), 0);
2374887Schin }
238