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