Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: gdb/common/format.c

Issue 11969036: Merge GDB 7.5.1 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@master
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gdb/common/format.h ('k') | gdb/common/gdb_assert.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Parse a printf-style format string.
2
3 Copyright (C) 1986-2012 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #ifdef GDBSERVER
21 #include "server.h"
22 #else
23 #include "defs.h"
24 #endif
25
26 #include <string.h>
27
28 #include "format.h"
29
30 struct format_piece *
31 parse_format_string (char **arg)
32 {
33 char *s, *f, *string;
34 char *prev_start;
35 char *percent_loc;
36 char *sub_start, *current_substring;
37 struct format_piece *pieces;
38 int next_frag;
39 int max_pieces;
40 enum argclass this_argclass;
41
42 s = *arg;
43
44 /* Parse the format-control string and copy it into the string STRING,
45 processing some kinds of escape sequence. */
46
47 f = string = (char *) alloca (strlen (s) + 1);
48
49 while (*s != '"' && *s != '\0')
50 {
51 int c = *s++;
52 switch (c)
53 {
54 case '\0':
55 continue;
56
57 case '\\':
58 switch (c = *s++)
59 {
60 case '\\':
61 *f++ = '\\';
62 break;
63 case 'a':
64 *f++ = '\a';
65 break;
66 case 'b':
67 *f++ = '\b';
68 break;
69 case 'f':
70 *f++ = '\f';
71 break;
72 case 'n':
73 *f++ = '\n';
74 break;
75 case 'r':
76 *f++ = '\r';
77 break;
78 case 't':
79 *f++ = '\t';
80 break;
81 case 'v':
82 *f++ = '\v';
83 break;
84 case '"':
85 *f++ = '"';
86 break;
87 default:
88 /* ??? TODO: handle other escape sequences. */
89 error (_("Unrecognized escape character \\%c in format string."),
90 c);
91 }
92 break;
93
94 default:
95 *f++ = c;
96 }
97 }
98
99 /* Terminate our escape-processed copy. */
100 *f++ = '\0';
101
102 /* Whether the format string ended with double-quote or zero, we're
103 done with it; it's up to callers to complain about syntax. */
104 *arg = s;
105
106 /* Need extra space for the '\0's. Doubling the size is sufficient. */
107
108 current_substring = xmalloc (strlen (string) * 2 + 1000);
109
110 max_pieces = strlen (string) + 2;
111
112 pieces = (struct format_piece *)
113 xmalloc (max_pieces * sizeof (struct format_piece));
114
115 next_frag = 0;
116
117 /* Now scan the string for %-specs and see what kinds of args they want.
118 argclass classifies the %-specs so we can give printf-type functions
119 something of the right size. */
120
121 f = string;
122 prev_start = string;
123 while (*f)
124 if (*f++ == '%')
125 {
126 int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0;
127 int seen_space = 0, seen_plus = 0;
128 int seen_big_l = 0, seen_h = 0, seen_big_h = 0;
129 int seen_big_d = 0, seen_double_big_d = 0;
130 int bad = 0;
131
132 /* Skip over "%%", it will become part of a literal piece. */
133 if (*f == '%')
134 {
135 f++;
136 continue;
137 }
138
139 sub_start = current_substring;
140
141 strncpy (current_substring, prev_start, f - 1 - prev_start);
142 current_substring += f - 1 - prev_start;
143 *current_substring++ = '\0';
144
145 pieces[next_frag].string = sub_start;
146 pieces[next_frag].argclass = literal_piece;
147 next_frag++;
148
149 percent_loc = f - 1;
150
151 /* Check the validity of the format specifier, and work
152 out what argument it expects. We only accept C89
153 format strings, with the exception of long long (which
154 we autoconf for). */
155
156 /* The first part of a format specifier is a set of flag
157 characters. */
158 while (strchr ("0-+ #", *f))
159 {
160 if (*f == '#')
161 seen_hash = 1;
162 else if (*f == '0')
163 seen_zero = 1;
164 else if (*f == ' ')
165 seen_space = 1;
166 else if (*f == '+')
167 seen_plus = 1;
168 f++;
169 }
170
171 /* The next part of a format specifier is a width. */
172 while (strchr ("0123456789", *f))
173 f++;
174
175 /* The next part of a format specifier is a precision. */
176 if (*f == '.')
177 {
178 seen_prec = 1;
179 f++;
180 while (strchr ("0123456789", *f))
181 f++;
182 }
183
184 /* The next part of a format specifier is a length modifier. */
185 if (*f == 'h')
186 {
187 seen_h = 1;
188 f++;
189 }
190 else if (*f == 'l')
191 {
192 f++;
193 lcount++;
194 if (*f == 'l')
195 {
196 f++;
197 lcount++;
198 }
199 }
200 else if (*f == 'L')
201 {
202 seen_big_l = 1;
203 f++;
204 }
205 /* Decimal32 modifier. */
206 else if (*f == 'H')
207 {
208 seen_big_h = 1;
209 f++;
210 }
211 /* Decimal64 and Decimal128 modifiers. */
212 else if (*f == 'D')
213 {
214 f++;
215
216 /* Check for a Decimal128. */
217 if (*f == 'D')
218 {
219 f++;
220 seen_double_big_d = 1;
221 }
222 else
223 seen_big_d = 1;
224 }
225
226 switch (*f)
227 {
228 case 'u':
229 if (seen_hash)
230 bad = 1;
231 /* FALLTHROUGH */
232
233 case 'o':
234 case 'x':
235 case 'X':
236 if (seen_space || seen_plus)
237 bad = 1;
238 /* FALLTHROUGH */
239
240 case 'd':
241 case 'i':
242 if (lcount == 0)
243 this_argclass = int_arg;
244 else if (lcount == 1)
245 this_argclass = long_arg;
246 else
247 this_argclass = long_long_arg;
248
249 if (seen_big_l)
250 bad = 1;
251 break;
252
253 case 'c':
254 this_argclass = lcount == 0 ? int_arg : wide_char_arg;
255 if (lcount > 1 || seen_h || seen_big_l)
256 bad = 1;
257 if (seen_prec || seen_zero || seen_space || seen_plus)
258 bad = 1;
259 break;
260
261 case 'p':
262 this_argclass = ptr_arg;
263 if (lcount || seen_h || seen_big_l)
264 bad = 1;
265 if (seen_prec || seen_zero || seen_space || seen_plus)
266 bad = 1;
267 break;
268
269 case 's':
270 this_argclass = lcount == 0 ? string_arg : wide_string_arg;
271 if (lcount > 1 || seen_h || seen_big_l)
272 bad = 1;
273 if (seen_zero || seen_space || seen_plus)
274 bad = 1;
275 break;
276
277 case 'e':
278 case 'f':
279 case 'g':
280 case 'E':
281 case 'G':
282 if (seen_big_h || seen_big_d || seen_double_big_d)
283 this_argclass = decfloat_arg;
284 else if (seen_big_l)
285 this_argclass = long_double_arg;
286 else
287 this_argclass = double_arg;
288
289 if (lcount || seen_h)
290 bad = 1;
291 break;
292
293 case '*':
294 error (_("`*' not supported for precision or width in printf"));
295
296 case 'n':
297 error (_("Format specifier `n' not supported in printf"));
298
299 case '\0':
300 error (_("Incomplete format specifier at end of format string"));
301
302 default:
303 error (_("Unrecognized format specifier '%c' in printf"), *f);
304 }
305
306 if (bad)
307 error (_("Inappropriate modifiers to "
308 "format specifier '%c' in printf"),
309 *f);
310
311 f++;
312
313 sub_start = current_substring;
314
315 if (lcount > 1 && USE_PRINTF_I64)
316 {
317 /* Windows' printf does support long long, but not the usual way.
318 Convert %lld to %I64d. */
319 int length_before_ll = f - percent_loc - 1 - lcount;
320
321 strncpy (current_substring, percent_loc, length_before_ll);
322 strcpy (current_substring + length_before_ll, "I64");
323 current_substring[length_before_ll + 3] =
324 percent_loc[length_before_ll + lcount];
325 current_substring += length_before_ll + 4;
326 }
327 else if (this_argclass == wide_string_arg
328 || this_argclass == wide_char_arg)
329 {
330 /* Convert %ls or %lc to %s. */
331 int length_before_ls = f - percent_loc - 2;
332
333 strncpy (current_substring, percent_loc, length_before_ls);
334 strcpy (current_substring + length_before_ls, "s");
335 current_substring += length_before_ls + 2;
336 }
337 else
338 {
339 strncpy (current_substring, percent_loc, f - percent_loc);
340 current_substring += f - percent_loc;
341 }
342
343 *current_substring++ = '\0';
344
345 prev_start = f;
346
347 pieces[next_frag].string = sub_start;
348 pieces[next_frag].argclass = this_argclass;
349 next_frag++;
350 }
351
352 /* Record the remainder of the string. */
353
354 sub_start = current_substring;
355
356 strncpy (current_substring, prev_start, f - prev_start);
357 current_substring += f - prev_start;
358 *current_substring++ = '\0';
359
360 pieces[next_frag].string = sub_start;
361 pieces[next_frag].argclass = literal_piece;
362 next_frag++;
363
364 /* Record an end-of-array marker. */
365
366 pieces[next_frag].string = NULL;
367 pieces[next_frag].argclass = literal_piece;
368
369 return pieces;
370 }
371
372 void
373 free_format_pieces (struct format_piece *pieces)
374 {
375 if (!pieces)
376 return;
377
378 /* We happen to know that all the string pieces are in the block
379 pointed to by the first string piece. */
380 if (pieces[0].string)
381 xfree (pieces[0].string);
382
383 xfree (pieces);
384 }
385
386 void
387 free_format_pieces_cleanup (void *ptr)
388 {
389 void **location = ptr;
390
391 if (location == NULL)
392 return;
393
394 if (*location != NULL)
395 {
396 free_format_pieces (*location);
397 *location = NULL;
398 }
399 }
400
OLDNEW
« no previous file with comments | « gdb/common/format.h ('k') | gdb/common/gdb_assert.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698