1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2011 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
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 #if _hdr_wchar && _hdr_wctype
34 #include <wchar.h>
35 #include <wctype.h>
36 #endif
37
38 /*
39 * quote string as of length n with qb...qe
40 * (flags&FMT_ALWAYS) always quotes, otherwise quote output only if necessary
41 * qe and the usual suspects are \... escaped
42 * (flags&FMT_WIDE) doesn't escape 8 bit chars
43 * (flags&FMT_ESCAPED) doesn't \... escape the usual suspects
44 * (flags&FMT_SHELL) escape $`"#;~&|()<>[]*?
45 */
46
47 char*
fmtquote(const char * as,const char * qb,const char * qe,size_t n,int flags)48 fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags)
49 {
50 register unsigned char* s = (unsigned char*)as;
51 register unsigned char* e = s + n;
52 register char* b;
53 register int c;
54 register int m;
55 register int escaped;
56 register int spaced;
57 register int doublequote;
58 register int singlequote;
59 int shell;
60 char* f;
61 char* buf;
62
63 c = 4 * (n + 1);
64 if (qb)
65 c += strlen((char*)qb);
66 if (qe)
67 c += strlen((char*)qe);
68 b = buf = fmtbuf(c);
69 shell = 0;
70 doublequote = 0;
71 singlequote = 0;
72 if (qb)
73 {
74 if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0)
75 shell = 1;
76 else if ((flags & FMT_SHELL) && qb[1] == 0)
77 {
78 if (qb[0] == '"')
79 doublequote = 1;
80 else if (qb[0] == '\'')
81 singlequote = 1;
82 }
83 while (*b = *qb++)
84 b++;
85 }
86 else if (flags & FMT_SHELL)
87 doublequote = 1;
88 f = b;
89 escaped = spaced = !!(flags & FMT_ALWAYS);
90 while (s < e)
91 {
92 if ((m = mbsize(s)) > 1 && (s + m) <= e)
93 {
94 #if _hdr_wchar && _hdr_wctype
95 c = mbchar(s);
96 if (!spaced && !escaped && (iswspace(c) || iswcntrl(c)))
97 spaced = 1;
98 s -= m;
99 #endif
100 while (m--)
101 *b++ = *s++;
102 }
103 else
104 {
105 c = *s++;
106 if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\'))
107 {
108 escaped = 1;
109 *b++ = '\\';
110 switch (c)
111 {
112 case CC_bel:
113 c = 'a';
114 break;
115 case '\b':
116 c = 'b';
117 break;
118 case '\f':
119 c = 'f';
120 break;
121 case '\n':
122 c = 'n';
123 break;
124 case '\r':
125 c = 'r';
126 break;
127 case '\t':
128 c = 't';
129 break;
130 case CC_vt:
131 c = 'v';
132 break;
133 case CC_esc:
134 c = 'E';
135 break;
136 case '\\':
137 break;
138 default:
139 if (!(flags & FMT_WIDE) || !(c & 0200))
140 {
141 *b++ = '0' + ((c >> 6) & 07);
142 *b++ = '0' + ((c >> 3) & 07);
143 c = '0' + (c & 07);
144 }
145 else
146 b--;
147 break;
148 }
149 }
150 else if (c == '\\')
151 {
152 escaped = 1;
153 *b++ = c;
154 if (*s)
155 c = *s++;
156 }
157 else if (qe && strchr(qe, c))
158 {
159 if (singlequote && c == '\'')
160 {
161 spaced = 1;
162 *b++ = '\'';
163 *b++ = '\\';
164 *b++ = '\'';
165 c = '\'';
166 }
167 else
168 {
169 escaped = 1;
170 *b++ = '\\';
171 }
172 }
173 else if (c == '$' || c == '`')
174 {
175 if (c == '$' && (flags & FMT_PARAM) && (*s == '{' || *s == '('))
176 {
177 if (singlequote || shell)
178 {
179 escaped = 1;
180 *b++ = '\'';
181 *b++ = c;
182 *b++ = *s++;
183 if (shell)
184 {
185 spaced = 1;
186 *b++ = '$';
187 }
188 c = '\'';
189 }
190 else
191 {
192 escaped = 1;
193 *b++ = c;
194 c = *s++;
195 }
196 }
197 else if (doublequote)
198 *b++ = '\\';
199 else if (singlequote || (flags & FMT_SHELL))
200 spaced = 1;
201 }
202 else if (!spaced && !escaped && (isspace(c) || ((flags & FMT_SHELL) || shell) && (strchr("\";~&|()<>[]*?", c) || c == '#' && (b == f || isspace(*(b - 1))))))
203 spaced = 1;
204 *b++ = c;
205 }
206 }
207 if (qb)
208 {
209 if (!escaped)
210 buf += shell + !spaced;
211 if (qe && (escaped || spaced))
212 while (*b = *qe++)
213 b++;
214 }
215 *b = 0;
216 return buf;
217 }
218
219 /*
220 * escape the usual suspects and quote chars in qs
221 * in length n string as
222 */
223
224 char*
fmtnesq(const char * as,const char * qs,size_t n)225 fmtnesq(const char* as, const char* qs, size_t n)
226 {
227 return fmtquote(as, NiL, qs, n, 0);
228 }
229
230 /*
231 * escape the usual suspects and quote chars in qs
232 */
233
234 char*
fmtesq(const char * as,const char * qs)235 fmtesq(const char* as, const char* qs)
236 {
237 return fmtquote(as, NiL, qs, strlen((char*)as), 0);
238 }
239
240 /*
241 * escape the usual suspects
242 */
243
244 char*
fmtesc(const char * as)245 fmtesc(const char* as)
246 {
247 return fmtquote(as, NiL, NiL, strlen((char*)as), 0);
248 }
249