aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter/quote.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-20 09:00:56 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-20 11:36:48 -0400
commit0780060124011b94af55830939c86cc0916be0f5 (patch)
tree883a4d0ed69862ab49e6d4bf4e19debafeb5c48c /Documentation/perf_counter/quote.c
parentd24e473e5b2ca86d1288b9416227ccc603313d0f (diff)
perf_counter tools: add in basic glue from Git
First very raw version at having a central 'perf' command and a list of subcommands: perf top perf stat perf record perf report ... This is done by picking up Git's collection of utility functions, and hacking them to build fine in this new environment. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/quote.c')
-rw-r--r--Documentation/perf_counter/quote.c478
1 files changed, 478 insertions, 0 deletions
diff --git a/Documentation/perf_counter/quote.c b/Documentation/perf_counter/quote.c
new file mode 100644
index 000000000000..7a49fcf69671
--- /dev/null
+++ b/Documentation/perf_counter/quote.c
@@ -0,0 +1,478 @@
1#include "cache.h"
2#include "quote.h"
3
4int quote_path_fully = 1;
5
6/* Help to copy the thing properly quoted for the shell safety.
7 * any single quote is replaced with '\'', any exclamation point
8 * is replaced with '\!', and the whole thing is enclosed in a
9 *
10 * E.g.
11 * original sq_quote result
12 * name ==> name ==> 'name'
13 * a b ==> a b ==> 'a b'
14 * a'b ==> a'\''b ==> 'a'\''b'
15 * a!b ==> a'\!'b ==> 'a'\!'b'
16 */
17static inline int need_bs_quote(char c)
18{
19 return (c == '\'' || c == '!');
20}
21
22void sq_quote_buf(struct strbuf *dst, const char *src)
23{
24 char *to_free = NULL;
25
26 if (dst->buf == src)
27 to_free = strbuf_detach(dst, NULL);
28
29 strbuf_addch(dst, '\'');
30 while (*src) {
31 size_t len = strcspn(src, "'!");
32 strbuf_add(dst, src, len);
33 src += len;
34 while (need_bs_quote(*src)) {
35 strbuf_addstr(dst, "'\\");
36 strbuf_addch(dst, *src++);
37 strbuf_addch(dst, '\'');
38 }
39 }
40 strbuf_addch(dst, '\'');
41 free(to_free);
42}
43
44void sq_quote_print(FILE *stream, const char *src)
45{
46 char c;
47
48 fputc('\'', stream);
49 while ((c = *src++)) {
50 if (need_bs_quote(c)) {
51 fputs("'\\", stream);
52 fputc(c, stream);
53 fputc('\'', stream);
54 } else {
55 fputc(c, stream);
56 }
57 }
58 fputc('\'', stream);
59}
60
61void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
62{
63 int i;
64
65 /* Copy into destination buffer. */
66 strbuf_grow(dst, 255);
67 for (i = 0; argv[i]; ++i) {
68 strbuf_addch(dst, ' ');
69 sq_quote_buf(dst, argv[i]);
70 if (maxlen && dst->len > maxlen)
71 die("Too many or long arguments");
72 }
73}
74
75char *sq_dequote_step(char *arg, char **next)
76{
77 char *dst = arg;
78 char *src = arg;
79 char c;
80
81 if (*src != '\'')
82 return NULL;
83 for (;;) {
84 c = *++src;
85 if (!c)
86 return NULL;
87 if (c != '\'') {
88 *dst++ = c;
89 continue;
90 }
91 /* We stepped out of sq */
92 switch (*++src) {
93 case '\0':
94 *dst = 0;
95 if (next)
96 *next = NULL;
97 return arg;
98 case '\\':
99 c = *++src;
100 if (need_bs_quote(c) && *++src == '\'') {
101 *dst++ = c;
102 continue;
103 }
104 /* Fallthrough */
105 default:
106 if (!next || !isspace(*src))
107 return NULL;
108 do {
109 c = *++src;
110 } while (isspace(c));
111 *dst = 0;
112 *next = src;
113 return arg;
114 }
115 }
116}
117
118char *sq_dequote(char *arg)
119{
120 return sq_dequote_step(arg, NULL);
121}
122
123int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
124{
125 char *next = arg;
126
127 if (!*arg)
128 return 0;
129 do {
130 char *dequoted = sq_dequote_step(next, &next);
131 if (!dequoted)
132 return -1;
133 ALLOC_GROW(*argv, *nr + 1, *alloc);
134 (*argv)[(*nr)++] = dequoted;
135 } while (next);
136
137 return 0;
138}
139
140/* 1 means: quote as octal
141 * 0 means: quote as octal if (quote_path_fully)
142 * -1 means: never quote
143 * c: quote as "\\c"
144 */
145#define X8(x) x, x, x, x, x, x, x, x
146#define X16(x) X8(x), X8(x)
147static signed char const sq_lookup[256] = {
148 /* 0 1 2 3 4 5 6 7 */
149 /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
150 /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
151 /* 0x10 */ X16(1),
152 /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1,
153 /* 0x28 */ X16(-1), X16(-1), X16(-1),
154 /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1,
155 /* 0x60 */ X16(-1), X8(-1),
156 /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1,
157 /* 0x80 */ /* set to 0 */
158};
159
160static inline int sq_must_quote(char c)
161{
162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
163}
164
165/* returns the longest prefix not needing a quote up to maxlen if positive.
166 This stops at the first \0 because it's marked as a character needing an
167 escape */
168static size_t next_quote_pos(const char *s, ssize_t maxlen)
169{
170 size_t len;
171 if (maxlen < 0) {
172 for (len = 0; !sq_must_quote(s[len]); len++);
173 } else {
174 for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
175 }
176 return len;
177}
178
179/*
180 * C-style name quoting.
181 *
182 * (1) if sb and fp are both NULL, inspect the input name and counts the
183 * number of bytes that are needed to hold c_style quoted version of name,
184 * counting the double quotes around it but not terminating NUL, and
185 * returns it.
186 * However, if name does not need c_style quoting, it returns 0.
187 *
188 * (2) if sb or fp are not NULL, it emits the c_style quoted version
189 * of name, enclosed with double quotes if asked and needed only.
190 * Return value is the same as in (1).
191 */
192static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
193 struct strbuf *sb, FILE *fp, int no_dq)
194{
195#undef EMIT
196#define EMIT(c) \
197 do { \
198 if (sb) strbuf_addch(sb, (c)); \
199 if (fp) fputc((c), fp); \
200 count++; \
201 } while (0)
202#define EMITBUF(s, l) \
203 do { \
204 if (sb) strbuf_add(sb, (s), (l)); \
205 if (fp) fwrite((s), (l), 1, fp); \
206 count += (l); \
207 } while (0)
208
209 size_t len, count = 0;
210 const char *p = name;
211
212 for (;;) {
213 int ch;
214
215 len = next_quote_pos(p, maxlen);
216 if (len == maxlen || !p[len])
217 break;
218
219 if (!no_dq && p == name)
220 EMIT('"');
221
222 EMITBUF(p, len);
223 EMIT('\\');
224 p += len;
225 ch = (unsigned char)*p++;
226 if (sq_lookup[ch] >= ' ') {
227 EMIT(sq_lookup[ch]);
228 } else {
229 EMIT(((ch >> 6) & 03) + '0');
230 EMIT(((ch >> 3) & 07) + '0');
231 EMIT(((ch >> 0) & 07) + '0');
232 }
233 }
234
235 EMITBUF(p, len);
236 if (p == name) /* no ending quote needed */
237 return 0;
238
239 if (!no_dq)
240 EMIT('"');
241 return count;
242}
243
244size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
245{
246 return quote_c_style_counted(name, -1, sb, fp, nodq);
247}
248
249void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
250{
251 if (quote_c_style(prefix, NULL, NULL, 0) ||
252 quote_c_style(path, NULL, NULL, 0)) {
253 if (!nodq)
254 strbuf_addch(sb, '"');
255 quote_c_style(prefix, sb, NULL, 1);
256 quote_c_style(path, sb, NULL, 1);
257 if (!nodq)
258 strbuf_addch(sb, '"');
259 } else {
260 strbuf_addstr(sb, prefix);
261 strbuf_addstr(sb, path);
262 }
263}
264
265void write_name_quoted(const char *name, FILE *fp, int terminator)
266{
267 if (terminator) {
268 quote_c_style(name, NULL, fp, 0);
269 } else {
270 fputs(name, fp);
271 }
272 fputc(terminator, fp);
273}
274
275extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
276 const char *name, FILE *fp, int terminator)
277{
278 int needquote = 0;
279
280 if (terminator) {
281 needquote = next_quote_pos(pfx, pfxlen) < pfxlen
282 || name[next_quote_pos(name, -1)];
283 }
284 if (needquote) {
285 fputc('"', fp);
286 quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
287 quote_c_style(name, NULL, fp, 1);
288 fputc('"', fp);
289 } else {
290 fwrite(pfx, pfxlen, 1, fp);
291 fputs(name, fp);
292 }
293 fputc(terminator, fp);
294}
295
296/* quote path as relative to the given prefix */
297char *quote_path_relative(const char *in, int len,
298 struct strbuf *out, const char *prefix)
299{
300 int needquote;
301
302 if (len < 0)
303 len = strlen(in);
304
305 /* "../" prefix itself does not need quoting, but "in" might. */
306 needquote = next_quote_pos(in, len) < len;
307 strbuf_setlen(out, 0);
308 strbuf_grow(out, len);
309
310 if (needquote)
311 strbuf_addch(out, '"');
312 if (prefix) {
313 int off = 0;
314 while (prefix[off] && off < len && prefix[off] == in[off])
315 if (prefix[off] == '/') {
316 prefix += off + 1;
317 in += off + 1;
318 len -= off + 1;
319 off = 0;
320 } else
321 off++;
322
323 for (; *prefix; prefix++)
324 if (*prefix == '/')
325 strbuf_addstr(out, "../");
326 }
327
328 quote_c_style_counted (in, len, out, NULL, 1);
329
330 if (needquote)
331 strbuf_addch(out, '"');
332 if (!out->len)
333 strbuf_addstr(out, "./");
334
335 return out->buf;
336}
337
338/*
339 * C-style name unquoting.
340 *
341 * Quoted should point at the opening double quote.
342 * + Returns 0 if it was able to unquote the string properly, and appends the
343 * result in the strbuf `sb'.
344 * + Returns -1 in case of error, and doesn't touch the strbuf. Though note
345 * that this function will allocate memory in the strbuf, so calling
346 * strbuf_release is mandatory whichever result unquote_c_style returns.
347 *
348 * Updates endp pointer to point at one past the ending double quote if given.
349 */
350int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
351{
352 size_t oldlen = sb->len, len;
353 int ch, ac;
354
355 if (*quoted++ != '"')
356 return -1;
357
358 for (;;) {
359 len = strcspn(quoted, "\"\\");
360 strbuf_add(sb, quoted, len);
361 quoted += len;
362
363 switch (*quoted++) {
364 case '"':
365 if (endp)
366 *endp = quoted;
367 return 0;
368 case '\\':
369 break;
370 default:
371 goto error;
372 }
373
374 switch ((ch = *quoted++)) {
375 case 'a': ch = '\a'; break;
376 case 'b': ch = '\b'; break;
377 case 'f': ch = '\f'; break;
378 case 'n': ch = '\n'; break;
379 case 'r': ch = '\r'; break;
380 case 't': ch = '\t'; break;
381 case 'v': ch = '\v'; break;
382
383 case '\\': case '"':
384 break; /* verbatim */
385
386 /* octal values with first digit over 4 overflow */
387 case '0': case '1': case '2': case '3':
388 ac = ((ch - '0') << 6);
389 if ((ch = *quoted++) < '0' || '7' < ch)
390 goto error;
391 ac |= ((ch - '0') << 3);
392 if ((ch = *quoted++) < '0' || '7' < ch)
393 goto error;
394 ac |= (ch - '0');
395 ch = ac;
396 break;
397 default:
398 goto error;
399 }
400 strbuf_addch(sb, ch);
401 }
402
403 error:
404 strbuf_setlen(sb, oldlen);
405 return -1;
406}
407
408/* quoting as a string literal for other languages */
409
410void perl_quote_print(FILE *stream, const char *src)
411{
412 const char sq = '\'';
413 const char bq = '\\';
414 char c;
415
416 fputc(sq, stream);
417 while ((c = *src++)) {
418 if (c == sq || c == bq)
419 fputc(bq, stream);
420 fputc(c, stream);
421 }
422 fputc(sq, stream);
423}
424
425void python_quote_print(FILE *stream, const char *src)
426{
427 const char sq = '\'';
428 const char bq = '\\';
429 const char nl = '\n';
430 char c;
431
432 fputc(sq, stream);
433 while ((c = *src++)) {
434 if (c == nl) {
435 fputc(bq, stream);
436 fputc('n', stream);
437 continue;
438 }
439 if (c == sq || c == bq)
440 fputc(bq, stream);
441 fputc(c, stream);
442 }
443 fputc(sq, stream);
444}
445
446void tcl_quote_print(FILE *stream, const char *src)
447{
448 char c;
449
450 fputc('"', stream);
451 while ((c = *src++)) {
452 switch (c) {
453 case '[': case ']':
454 case '{': case '}':
455 case '$': case '\\': case '"':
456 fputc('\\', stream);
457 default:
458 fputc(c, stream);
459 break;
460 case '\f':
461 fputs("\\f", stream);
462 break;
463 case '\r':
464 fputs("\\r", stream);
465 break;
466 case '\n':
467 fputs("\\n", stream);
468 break;
469 case '\t':
470 fputs("\\t", stream);
471 break;
472 case '\v':
473 fputs("\\v", stream);
474 break;
475 }
476 }
477 fputc('"', stream);
478}