xref: /titanic_50/usr/src/lib/libast/common/string/fmtesc.c (revision 356f72340a69936724c69f2f87fffa6f5887f885)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
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