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