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*
fmtquote(const char * as,const char * qb,const char * qe,size_t n,int flags)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*
fmtnesq(const char * as,const char * qs,size_t n)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*
fmtesq(const char * as,const char * qs)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*
fmtesc(const char * as)234 fmtesc(const char* as)
235 {
236 return fmtquote(as, NiL, NiL, strlen((char*)as), 0);
237 }
238