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