gdb/common/format.c - gdb

Functions defined

Source code

  1. /* Parse a printf-style format string.

  2.    Copyright (C) 1986-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "common-defs.h"
  15. #include "format.h"

  16. struct format_piece *
  17. parse_format_string (const char **arg)
  18. {
  19.   const char *s;
  20.   char *f, *string;
  21.   const char *prev_start;
  22.   const char *percent_loc;
  23.   char *sub_start, *current_substring;
  24.   struct format_piece *pieces;
  25.   int next_frag;
  26.   int max_pieces;
  27.   enum argclass this_argclass;

  28.   s = *arg;

  29.   /* Parse the format-control string and copy it into the string STRING,
  30.      processing some kinds of escape sequence.  */

  31.   f = string = (char *) alloca (strlen (s) + 1);

  32.   while (*s != '"' && *s != '\0')
  33.     {
  34.       int c = *s++;
  35.       switch (c)
  36.         {
  37.         case '\0':
  38.           continue;

  39.         case '\\':
  40.           switch (c = *s++)
  41.             {
  42.             case '\\':
  43.               *f++ = '\\';
  44.               break;
  45.             case 'a':
  46.               *f++ = '\a';
  47.               break;
  48.             case 'b':
  49.               *f++ = '\b';
  50.               break;
  51.             case 'f':
  52.               *f++ = '\f';
  53.               break;
  54.             case 'n':
  55.               *f++ = '\n';
  56.               break;
  57.             case 'r':
  58.               *f++ = '\r';
  59.               break;
  60.             case 't':
  61.               *f++ = '\t';
  62.               break;
  63.             case 'v':
  64.               *f++ = '\v';
  65.               break;
  66.             case '"':
  67.               *f++ = '"';
  68.               break;
  69.             default:
  70.               /* ??? TODO: handle other escape sequences.  */
  71.               error (_("Unrecognized escape character \\%c in format string."),
  72.                      c);
  73.             }
  74.           break;

  75.         default:
  76.           *f++ = c;
  77.         }
  78.     }

  79.   /* Terminate our escape-processed copy.  */
  80.   *f++ = '\0';

  81.   /* Whether the format string ended with double-quote or zero, we're
  82.      done with it; it's up to callers to complain about syntax.  */
  83.   *arg = s;

  84.   /* Need extra space for the '\0's.  Doubling the size is sufficient.  */

  85.   current_substring = xmalloc (strlen (string) * 2 + 1000);

  86.   max_pieces = strlen (string) + 2;

  87.   pieces = (struct format_piece *)
  88.     xmalloc (max_pieces * sizeof (struct format_piece));

  89.   next_frag = 0;

  90.   /* Now scan the string for %-specs and see what kinds of args they want.
  91.      argclass classifies the %-specs so we can give printf-type functions
  92.      something of the right size.  */

  93.   f = string;
  94.   prev_start = string;
  95.   while (*f)
  96.     if (*f++ == '%')
  97.       {
  98.         int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0;
  99.         int seen_space = 0, seen_plus = 0;
  100.         int seen_big_l = 0, seen_h = 0, seen_big_h = 0;
  101.         int seen_big_d = 0, seen_double_big_d = 0;
  102.         int bad = 0;

  103.         /* Skip over "%%", it will become part of a literal piece.  */
  104.         if (*f == '%')
  105.           {
  106.             f++;
  107.             continue;
  108.           }

  109.         sub_start = current_substring;

  110.         strncpy (current_substring, prev_start, f - 1 - prev_start);
  111.         current_substring += f - 1 - prev_start;
  112.         *current_substring++ = '\0';

  113.         pieces[next_frag].string = sub_start;
  114.         pieces[next_frag].argclass = literal_piece;
  115.         next_frag++;

  116.         percent_loc = f - 1;

  117.         /* Check the validity of the format specifier, and work
  118.            out what argument it expects.  We only accept C89
  119.            format strings, with the exception of long long (which
  120.            we autoconf for).  */

  121.         /* The first part of a format specifier is a set of flag
  122.            characters.  */
  123.         while (*f != '\0' && strchr ("0-+ #", *f))
  124.           {
  125.             if (*f == '#')
  126.               seen_hash = 1;
  127.             else if (*f == '0')
  128.               seen_zero = 1;
  129.             else if (*f == ' ')
  130.               seen_space = 1;
  131.             else if (*f == '+')
  132.               seen_plus = 1;
  133.             f++;
  134.           }

  135.         /* The next part of a format specifier is a width.  */
  136.         while (*f != '\0' && strchr ("0123456789", *f))
  137.           f++;

  138.         /* The next part of a format specifier is a precision.  */
  139.         if (*f == '.')
  140.           {
  141.             seen_prec = 1;
  142.             f++;
  143.             while (*f != '\0' && strchr ("0123456789", *f))
  144.               f++;
  145.           }

  146.         /* The next part of a format specifier is a length modifier.  */
  147.         if (*f == 'h')
  148.           {
  149.             seen_h = 1;
  150.             f++;
  151.           }
  152.         else if (*f == 'l')
  153.           {
  154.             f++;
  155.             lcount++;
  156.             if (*f == 'l')
  157.               {
  158.                 f++;
  159.                 lcount++;
  160.               }
  161.           }
  162.         else if (*f == 'L')
  163.           {
  164.             seen_big_l = 1;
  165.             f++;
  166.           }
  167.         /* Decimal32 modifier.  */
  168.         else if (*f == 'H')
  169.           {
  170.             seen_big_h = 1;
  171.             f++;
  172.           }
  173.         /* Decimal64 and Decimal128 modifiers.  */
  174.         else if (*f == 'D')
  175.           {
  176.             f++;

  177.             /* Check for a Decimal128.  */
  178.             if (*f == 'D')
  179.               {
  180.                 f++;
  181.                 seen_double_big_d = 1;
  182.               }
  183.             else
  184.               seen_big_d = 1;
  185.           }

  186.         switch (*f)
  187.           {
  188.           case 'u':
  189.             if (seen_hash)
  190.               bad = 1;
  191.             /* FALLTHROUGH */

  192.           case 'o':
  193.           case 'x':
  194.           case 'X':
  195.             if (seen_space || seen_plus)
  196.               bad = 1;
  197.           /* FALLTHROUGH */

  198.           case 'd':
  199.           case 'i':
  200.             if (lcount == 0)
  201.               this_argclass = int_arg;
  202.             else if (lcount == 1)
  203.               this_argclass = long_arg;
  204.             else
  205.               this_argclass = long_long_arg;

  206.             if (seen_big_l)
  207.               bad = 1;
  208.             break;

  209.           case 'c':
  210.             this_argclass = lcount == 0 ? int_arg : wide_char_arg;
  211.             if (lcount > 1 || seen_h || seen_big_l)
  212.               bad = 1;
  213.             if (seen_prec || seen_zero || seen_space || seen_plus)
  214.               bad = 1;
  215.             break;

  216.           case 'p':
  217.             this_argclass = ptr_arg;
  218.             if (lcount || seen_h || seen_big_l)
  219.               bad = 1;
  220.             if (seen_prec)
  221.               bad = 1;
  222.             if (seen_hash || seen_zero || seen_space || seen_plus)
  223.               bad = 1;
  224.             break;

  225.           case 's':
  226.             this_argclass = lcount == 0 ? string_arg : wide_string_arg;
  227.             if (lcount > 1 || seen_h || seen_big_l)
  228.               bad = 1;
  229.             if (seen_zero || seen_space || seen_plus)
  230.               bad = 1;
  231.             break;

  232.           case 'e':
  233.           case 'f':
  234.           case 'g':
  235.           case 'E':
  236.           case 'G':
  237.             if (seen_big_h || seen_big_d || seen_double_big_d)
  238.               this_argclass = decfloat_arg;
  239.             else if (seen_big_l)
  240.               this_argclass = long_double_arg;
  241.             else
  242.               this_argclass = double_arg;

  243.             if (lcount || seen_h)
  244.               bad = 1;
  245.             break;

  246.           case '*':
  247.             error (_("`*' not supported for precision or width in printf"));

  248.           case 'n':
  249.             error (_("Format specifier `n' not supported in printf"));

  250.           case '\0':
  251.             error (_("Incomplete format specifier at end of format string"));

  252.           default:
  253.             error (_("Unrecognized format specifier '%c' in printf"), *f);
  254.           }

  255.         if (bad)
  256.           error (_("Inappropriate modifiers to "
  257.                    "format specifier '%c' in printf"),
  258.                  *f);

  259.         f++;

  260.         sub_start = current_substring;

  261.         if (lcount > 1 && USE_PRINTF_I64)
  262.           {
  263.             /* Windows' printf does support long long, but not the usual way.
  264.                Convert %lld to %I64d.  */
  265.             int length_before_ll = f - percent_loc - 1 - lcount;

  266.             strncpy (current_substring, percent_loc, length_before_ll);
  267.             strcpy (current_substring + length_before_ll, "I64");
  268.             current_substring[length_before_ll + 3] =
  269.               percent_loc[length_before_ll + lcount];
  270.             current_substring += length_before_ll + 4;
  271.           }
  272.         else if (this_argclass == wide_string_arg
  273.                  || this_argclass == wide_char_arg)
  274.           {
  275.             /* Convert %ls or %lc to %s.  */
  276.             int length_before_ls = f - percent_loc - 2;

  277.             strncpy (current_substring, percent_loc, length_before_ls);
  278.             strcpy (current_substring + length_before_ls, "s");
  279.             current_substring += length_before_ls + 2;
  280.           }
  281.         else
  282.           {
  283.             strncpy (current_substring, percent_loc, f - percent_loc);
  284.             current_substring += f - percent_loc;
  285.           }

  286.         *current_substring++ = '\0';

  287.         prev_start = f;

  288.         pieces[next_frag].string = sub_start;
  289.         pieces[next_frag].argclass = this_argclass;
  290.         next_frag++;
  291.       }

  292.   /* Record the remainder of the string.  */

  293.   sub_start = current_substring;

  294.   strncpy (current_substring, prev_start, f - prev_start);
  295.   current_substring += f - prev_start;
  296.   *current_substring++ = '\0';

  297.   pieces[next_frag].string = sub_start;
  298.   pieces[next_frag].argclass = literal_piece;
  299.   next_frag++;

  300.   /* Record an end-of-array marker.  */

  301.   pieces[next_frag].string = NULL;
  302.   pieces[next_frag].argclass = literal_piece;

  303.   return pieces;
  304. }

  305. void
  306. free_format_pieces (struct format_piece *pieces)
  307. {
  308.   if (!pieces)
  309.     return;

  310.   /* We happen to know that all the string pieces are in the block
  311.      pointed to by the first string piece.  */
  312.   if (pieces[0].string)
  313.     xfree (pieces[0].string);

  314.   xfree (pieces);
  315. }

  316. void
  317. free_format_pieces_cleanup (void *ptr)
  318. {
  319.   void **location = ptr;

  320.   if (location == NULL)
  321.     return;

  322.   if (*location != NULL)
  323.     {
  324.       free_format_pieces (*location);
  325.       *location = NULL;
  326.     }
  327. }