xref: /onnv-gate/usr/src/lib/libast/common/string/fmtesc.c (revision 12068:08a39a083754)
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