Move common-utils.h to common-defs.h
[platform/upstream/binutils.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