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