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