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 (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 (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 (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 (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 || seen_zero || seen_space || seen_plus) 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 290 if (lcount || seen_h) 291 bad = 1; 292 break; 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 373 void 374 free_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 387 void 388 free_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 402