Update Copyright year range in all files maintained by GDB.
[deliverable/binutils-gdb.git] / gdb / common / format.c
1 /* Parse a printf-style format string.
2
3 Copyright (C) 1986-2014 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 (const char **arg)
32 {
33 const char *s;
34 char *f, *string;
35 const char *prev_start;
36 const char *percent_loc;
37 char *sub_start, *current_substring;
38 struct format_piece *pieces;
39 int next_frag;
40 int max_pieces;
41 enum argclass this_argclass;
42
43 s = *arg;
44
45 /* Parse the format-control string and copy it into the string STRING,
46 processing some kinds of escape sequence. */
47
48 f = string = (char *) alloca (strlen (s) + 1);
49
50 while (*s != '"' && *s != '\0')
51 {
52 int c = *s++;
53 switch (c)
54 {
55 case '\0':
56 continue;
57
58 case '\\':
59 switch (c = *s++)
60 {
61 case '\\':
62 *f++ = '\\';
63 break;
64 case 'a':
65 *f++ = '\a';
66 break;
67 case 'b':
68 *f++ = '\b';
69 break;
70 case 'f':
71 *f++ = '\f';
72 break;
73 case 'n':
74 *f++ = '\n';
75 break;
76 case 'r':
77 *f++ = '\r';
78 break;
79 case 't':
80 *f++ = '\t';
81 break;
82 case 'v':
83 *f++ = '\v';
84 break;
85 case '"':
86 *f++ = '"';
87 break;
88 default:
89 /* ??? TODO: handle other escape sequences. */
90 error (_("Unrecognized escape character \\%c in format string."),
91 c);
92 }
93 break;
94
95 default:
96 *f++ = c;
97 }
98 }
99
100 /* Terminate our escape-processed copy. */
101 *f++ = '\0';
102
103 /* Whether the format string ended with double-quote or zero, we're
104 done with it; it's up to callers to complain about syntax. */
105 *arg = s;
106
107 /* Need extra space for the '\0's. Doubling the size is sufficient. */
108
109 current_substring = xmalloc (strlen (string) * 2 + 1000);
110
111 max_pieces = strlen (string) + 2;
112
113 pieces = (struct format_piece *)
114 xmalloc (max_pieces * sizeof (struct format_piece));
115
116 next_frag = 0;
117
118 /* Now scan the string for %-specs and see what kinds of args they want.
119 argclass classifies the %-specs so we can give printf-type functions
120 something of the right size. */
121
122 f = string;
123 prev_start = string;
124 while (*f)
125 if (*f++ == '%')
126 {
127 int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0;
128 int seen_space = 0, seen_plus = 0;
129 int seen_big_l = 0, seen_h = 0, seen_big_h = 0;
130 int seen_big_d = 0, seen_double_big_d = 0;
131 int bad = 0;
132
133 /* Skip over "%%", it will become part of a literal piece. */
134 if (*f == '%')
135 {
136 f++;
137 continue;
138 }
139
140 sub_start = current_substring;
141
142 strncpy (current_substring, prev_start, f - 1 - prev_start);
143 current_substring += f - 1 - prev_start;
144 *current_substring++ = '\0';
145
146 pieces[next_frag].string = sub_start;
147 pieces[next_frag].argclass = literal_piece;
148 next_frag++;
149
150 percent_loc = f - 1;
151
152 /* Check the validity of the format specifier, and work
153 out what argument it expects. We only accept C89
154 format strings, with the exception of long long (which
155 we autoconf for). */
156
157 /* The first part of a format specifier is a set of flag
158 characters. */
159 while (*f != '\0' && strchr ("0-+ #", *f))
160 {
161 if (*f == '#')
162 seen_hash = 1;
163 else if (*f == '0')
164 seen_zero = 1;
165 else if (*f == ' ')
166 seen_space = 1;
167 else if (*f == '+')
168 seen_plus = 1;
169 f++;
170 }
171
172 /* The next part of a format specifier is a width. */
173 while (*f != '\0' && strchr ("0123456789", *f))
174 f++;
175
176 /* The next part of a format specifier is a precision. */
177 if (*f == '.')
178 {
179 seen_prec = 1;
180 f++;
181 while (*f != '\0' && strchr ("0123456789", *f))
182 f++;
183 }
184
185 /* The next part of a format specifier is a length modifier. */
186 if (*f == 'h')
187 {
188 seen_h = 1;
189 f++;
190 }
191 else if (*f == 'l')
192 {
193 f++;
194 lcount++;
195 if (*f == 'l')
196 {
197 f++;
198 lcount++;
199 }
200 }
201 else if (*f == 'L')
202 {
203 seen_big_l = 1;
204 f++;
205 }
206 /* Decimal32 modifier. */
207 else if (*f == 'H')
208 {
209 seen_big_h = 1;
210 f++;
211 }
212 /* Decimal64 and Decimal128 modifiers. */
213 else if (*f == 'D')
214 {
215 f++;
216
217 /* Check for a Decimal128. */
218 if (*f == 'D')
219 {
220 f++;
221 seen_double_big_d = 1;
222 }
223 else
224 seen_big_d = 1;
225 }
226
227 switch (*f)
228 {
229 case 'u':
230 if (seen_hash)
231 bad = 1;
232 /* FALLTHROUGH */
233
234 case 'o':
235 case 'x':
236 case 'X':
237 if (seen_space || seen_plus)
238 bad = 1;
239 /* FALLTHROUGH */
240
241 case 'd':
242 case 'i':
243 if (lcount == 0)
244 this_argclass = int_arg;
245 else if (lcount == 1)
246 this_argclass = long_arg;
247 else
248 this_argclass = long_long_arg;
249
250 if (seen_big_l)
251 bad = 1;
252 break;
253
254 case 'c':
255 this_argclass = lcount == 0 ? int_arg : wide_char_arg;
256 if (lcount > 1 || seen_h || seen_big_l)
257 bad = 1;
258 if (seen_prec || seen_zero || seen_space || seen_plus)
259 bad = 1;
260 break;
261
262 case 'p':
263 this_argclass = ptr_arg;
264 if (lcount || seen_h || seen_big_l)
265 bad = 1;
266 if (seen_prec)
267 bad = 1;
268 if (seen_hash || seen_zero || seen_space || seen_plus)
269 bad = 1;
270 break;
271
272 case 's':
273 this_argclass = lcount == 0 ? string_arg : wide_string_arg;
274 if (lcount > 1 || seen_h || seen_big_l)
275 bad = 1;
276 if (seen_zero || seen_space || seen_plus)
277 bad = 1;
278 break;
279
280 case 'e':
281 case 'f':
282 case 'g':
283 case 'E':
284 case 'G':
285 if (seen_big_h || seen_big_d || seen_double_big_d)
286 this_argclass = decfloat_arg;
287 else if (seen_big_l)
288 this_argclass = long_double_arg;
289 else
290 this_argclass = double_arg;
291
292 if (lcount || seen_h)
293 bad = 1;
294 break;
295
296 case '*':
297 error (_("`*' not supported for precision or width in printf"));
298
299 case 'n':
300 error (_("Format specifier `n' not supported in printf"));
301
302 case '\0':
303 error (_("Incomplete format specifier at end of format string"));
304
305 default:
306 error (_("Unrecognized format specifier '%c' in printf"), *f);
307 }
308
309 if (bad)
310 error (_("Inappropriate modifiers to "
311 "format specifier '%c' in printf"),
312 *f);
313
314 f++;
315
316 sub_start = current_substring;
317
318 if (lcount > 1 && USE_PRINTF_I64)
319 {
320 /* Windows' printf does support long long, but not the usual way.
321 Convert %lld to %I64d. */
322 int length_before_ll = f - percent_loc - 1 - lcount;
323
324 strncpy (current_substring, percent_loc, length_before_ll);
325 strcpy (current_substring + length_before_ll, "I64");
326 current_substring[length_before_ll + 3] =
327 percent_loc[length_before_ll + lcount];
328 current_substring += length_before_ll + 4;
329 }
330 else if (this_argclass == wide_string_arg
331 || this_argclass == wide_char_arg)
332 {
333 /* Convert %ls or %lc to %s. */
334 int length_before_ls = f - percent_loc - 2;
335
336 strncpy (current_substring, percent_loc, length_before_ls);
337 strcpy (current_substring + length_before_ls, "s");
338 current_substring += length_before_ls + 2;
339 }
340 else
341 {
342 strncpy (current_substring, percent_loc, f - percent_loc);
343 current_substring += f - percent_loc;
344 }
345
346 *current_substring++ = '\0';
347
348 prev_start = f;
349
350 pieces[next_frag].string = sub_start;
351 pieces[next_frag].argclass = this_argclass;
352 next_frag++;
353 }
354
355 /* Record the remainder of the string. */
356
357 sub_start = current_substring;
358
359 strncpy (current_substring, prev_start, f - prev_start);
360 current_substring += f - prev_start;
361 *current_substring++ = '\0';
362
363 pieces[next_frag].string = sub_start;
364 pieces[next_frag].argclass = literal_piece;
365 next_frag++;
366
367 /* Record an end-of-array marker. */
368
369 pieces[next_frag].string = NULL;
370 pieces[next_frag].argclass = literal_piece;
371
372 return pieces;
373 }
374
375 void
376 free_format_pieces (struct format_piece *pieces)
377 {
378 if (!pieces)
379 return;
380
381 /* We happen to know that all the string pieces are in the block
382 pointed to by the first string piece. */
383 if (pieces[0].string)
384 xfree (pieces[0].string);
385
386 xfree (pieces);
387 }
388
389 void
390 free_format_pieces_cleanup (void *ptr)
391 {
392 void **location = ptr;
393
394 if (location == NULL)
395 return;
396
397 if (*location != NULL)
398 {
399 free_format_pieces (*location);
400 *location = NULL;
401 }
402 }
403
This page took 0.037114 seconds and 4 git commands to generate.