1 /* Parse a printf-style format string.
3 Copyright (C) 1986-2015 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "common-defs.h"
24 parse_format_string (const char **arg
)
28 const char *prev_start
;
29 const char *percent_loc
;
30 char *sub_start
, *current_substring
;
31 struct format_piece
*pieces
;
34 enum argclass this_argclass
;
38 /* Parse the format-control string and copy it into the string STRING,
39 processing some kinds of escape sequence. */
41 f
= string
= (char *) alloca (strlen (s
) + 1);
43 while (*s
!= '"' && *s
!= '\0')
82 /* ??? TODO: handle other escape sequences. */
83 error (_("Unrecognized escape character \\%c in format string."),
93 /* Terminate our escape-processed copy. */
96 /* Whether the format string ended with double-quote or zero, we're
97 done with it; it's up to callers to complain about syntax. */
100 /* Need extra space for the '\0's. Doubling the size is sufficient. */
102 current_substring
= xmalloc (strlen (string
) * 2 + 1000);
104 max_pieces
= strlen (string
) + 2;
106 pieces
= (struct format_piece
*)
107 xmalloc (max_pieces
* sizeof (struct format_piece
));
111 /* Now scan the string for %-specs and see what kinds of args they want.
112 argclass classifies the %-specs so we can give printf-type functions
113 something of the right size. */
120 int seen_hash
= 0, seen_zero
= 0, lcount
= 0, seen_prec
= 0;
121 int seen_space
= 0, seen_plus
= 0;
122 int seen_big_l
= 0, seen_h
= 0, seen_big_h
= 0;
123 int seen_big_d
= 0, seen_double_big_d
= 0;
126 /* Skip over "%%", it will become part of a literal piece. */
133 sub_start
= current_substring
;
135 strncpy (current_substring
, prev_start
, f
- 1 - prev_start
);
136 current_substring
+= f
- 1 - prev_start
;
137 *current_substring
++ = '\0';
139 pieces
[next_frag
].string
= sub_start
;
140 pieces
[next_frag
].argclass
= literal_piece
;
145 /* Check the validity of the format specifier, and work
146 out what argument it expects. We only accept C89
147 format strings, with the exception of long long (which
150 /* The first part of a format specifier is a set of flag
152 while (*f
!= '\0' && strchr ("0-+ #", *f
))
165 /* The next part of a format specifier is a width. */
166 while (*f
!= '\0' && strchr ("0123456789", *f
))
169 /* The next part of a format specifier is a precision. */
174 while (*f
!= '\0' && strchr ("0123456789", *f
))
178 /* The next part of a format specifier is a length modifier. */
199 /* Decimal32 modifier. */
205 /* Decimal64 and Decimal128 modifiers. */
210 /* Check for a Decimal128. */
214 seen_double_big_d
= 1;
230 if (seen_space
|| seen_plus
)
237 this_argclass
= int_arg
;
238 else if (lcount
== 1)
239 this_argclass
= long_arg
;
241 this_argclass
= long_long_arg
;
248 this_argclass
= lcount
== 0 ? int_arg
: wide_char_arg
;
249 if (lcount
> 1 || seen_h
|| seen_big_l
)
251 if (seen_prec
|| seen_zero
|| seen_space
|| seen_plus
)
256 this_argclass
= ptr_arg
;
257 if (lcount
|| seen_h
|| seen_big_l
)
261 if (seen_hash
|| seen_zero
|| seen_space
|| seen_plus
)
266 this_argclass
= lcount
== 0 ? string_arg
: wide_string_arg
;
267 if (lcount
> 1 || seen_h
|| seen_big_l
)
269 if (seen_zero
|| seen_space
|| seen_plus
)
278 if (seen_big_h
|| seen_big_d
|| seen_double_big_d
)
279 this_argclass
= decfloat_arg
;
281 this_argclass
= long_double_arg
;
283 this_argclass
= double_arg
;
285 if (lcount
|| seen_h
)
290 error (_("`*' not supported for precision or width in printf"));
293 error (_("Format specifier `n' not supported in printf"));
296 error (_("Incomplete format specifier at end of format string"));
299 error (_("Unrecognized format specifier '%c' in printf"), *f
);
303 error (_("Inappropriate modifiers to "
304 "format specifier '%c' in printf"),
309 sub_start
= current_substring
;
311 if (lcount
> 1 && USE_PRINTF_I64
)
313 /* Windows' printf does support long long, but not the usual way.
314 Convert %lld to %I64d. */
315 int length_before_ll
= f
- percent_loc
- 1 - lcount
;
317 strncpy (current_substring
, percent_loc
, length_before_ll
);
318 strcpy (current_substring
+ length_before_ll
, "I64");
319 current_substring
[length_before_ll
+ 3] =
320 percent_loc
[length_before_ll
+ lcount
];
321 current_substring
+= length_before_ll
+ 4;
323 else if (this_argclass
== wide_string_arg
324 || this_argclass
== wide_char_arg
)
326 /* Convert %ls or %lc to %s. */
327 int length_before_ls
= f
- percent_loc
- 2;
329 strncpy (current_substring
, percent_loc
, length_before_ls
);
330 strcpy (current_substring
+ length_before_ls
, "s");
331 current_substring
+= length_before_ls
+ 2;
335 strncpy (current_substring
, percent_loc
, f
- percent_loc
);
336 current_substring
+= f
- percent_loc
;
339 *current_substring
++ = '\0';
343 pieces
[next_frag
].string
= sub_start
;
344 pieces
[next_frag
].argclass
= this_argclass
;
348 /* Record the remainder of the string. */
350 sub_start
= current_substring
;
352 strncpy (current_substring
, prev_start
, f
- prev_start
);
353 current_substring
+= f
- prev_start
;
354 *current_substring
++ = '\0';
356 pieces
[next_frag
].string
= sub_start
;
357 pieces
[next_frag
].argclass
= literal_piece
;
360 /* Record an end-of-array marker. */
362 pieces
[next_frag
].string
= NULL
;
363 pieces
[next_frag
].argclass
= literal_piece
;
369 free_format_pieces (struct format_piece
*pieces
)
374 /* We happen to know that all the string pieces are in the block
375 pointed to by the first string piece. */
376 if (pieces
[0].string
)
377 xfree (pieces
[0].string
);
383 free_format_pieces_cleanup (void *ptr
)
385 void **location
= ptr
;
387 if (location
== NULL
)
390 if (*location
!= NULL
)
392 free_format_pieces (*location
);