Define YYOBJ in terms of YYFILES
[deliverable/binutils-gdb.git] / gdb / macroexp.c
index 6f81bbbc009250a2cccaace2a98ddba8cf6ce490..8d1876e0b3af8976d45f08b931b8b579cc677adc 100644 (file)
@@ -1,6 +1,5 @@
 /* C preprocessor macro expansion for GDB.
-   Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2002-2017 Free Software Foundation, Inc.
    Contributed by Red Hat, Inc.
 
    This file is part of GDB.
@@ -23,7 +22,6 @@
 #include "bcache.h"
 #include "macrotab.h"
 #include "macroexp.h"
-#include "gdb_assert.h"
 #include "c-lang.h"
 
 
@@ -55,8 +53,9 @@ struct macro_buffer
 
   /* Zero if TEXT can be safely realloc'ed (i.e., it's its own malloc
      block).  Non-zero if TEXT is actually pointing into the middle of
-     some other block, and we shouldn't reallocate it.  */
-  int shared;
+     some other block, or to a string literal, and we shouldn't
+     reallocate it.  */
+  bool shared;
 
   /* For detecting token splicing. 
 
@@ -87,19 +86,22 @@ init_buffer (struct macro_buffer *b, int n)
   else
     b->text = NULL;
   b->len = 0;
-  b->shared = 0;
+  b->shared = false;
   b->last_token = -1;
 }
 
 
 /* Set the macro buffer *BUF to refer to the LEN bytes at ADDR, as a
    shared substring.  */
+
 static void
-init_shared_buffer (struct macro_buffer *buf, char *addr, int len)
+init_shared_buffer (struct macro_buffer *buf, const char *addr, int len)
 {
-  buf->text = addr;
+  /* The function accept a "const char *" addr so that clients can
+     pass in string literals without casts.  */
+  buf->text = (char *) addr;
   buf->len = len;
-  buf->shared = 1;
+  buf->shared = true;
   buf->size = 0;
   buf->last_token = -1;
 }
@@ -114,6 +116,17 @@ free_buffer (struct macro_buffer *b)
     xfree (b->text);
 }
 
+/* Like free_buffer, but return the text as an xstrdup()d string.
+   This only exists to try to make the API relatively clean.  */
+
+static char *
+free_buffer_return_text (struct macro_buffer *b)
+{
+  gdb_assert (! b->shared);
+  gdb_assert (b->size);
+  /* Nothing to do.  */
+  return b->text;
+}
 
 /* A cleanup function for macro buffers.  */
 static void
@@ -137,7 +150,7 @@ resize_buffer (struct macro_buffer *b, int n)
     while (b->size <= n)
       b->size *= 2;
 
-  b->text = xrealloc (b->text, b->size);
+  b->text = (char *) xrealloc (b->text, b->size);
 }
 
 
@@ -157,7 +170,7 @@ appendc (struct macro_buffer *b, int c)
 
 /* Append the LEN bytes at ADDR to the buffer B.  */
 static void
-appendmem (struct macro_buffer *b, char *addr, int len)
+appendmem (struct macro_buffer *b, const char *addr, int len)
 {
   int new_len = b->len + len;
 
@@ -206,7 +219,7 @@ set_token (struct macro_buffer *tok, char *start, char *end)
   init_shared_buffer (tok, start, end - start);
   tok->last_token = 0;
 
-  /* Presumed; get_identifier may overwrite this. */
+  /* Presumed; get_identifier may overwrite this.  */
   tok->is_identifier = 0;
 }
 
@@ -327,7 +340,6 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end)
          && p[1] == '\''))
     {
       char *tok_start = p;
-      char *body_start;
       int char_count = 0;
 
       if (*p == '\'')
@@ -337,7 +349,6 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end)
       else
         gdb_assert_not_reached ("unexpected character constant");
 
-      body_start = p;
       for (;;)
         {
           if (p >= end)
@@ -352,8 +363,11 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end)
             }
           else if (*p == '\\')
             {
-              p++;
-             char_count += c_parse_escape (&p, NULL);
+             const char *s, *o;
+
+             s = o = ++p;
+             char_count += c_parse_escape (&s, NULL);
+             p += s - o;
             }
           else
            {
@@ -406,8 +420,11 @@ get_string_literal (struct macro_buffer *tok, char *p, char *end)
                    "constants."));
           else if (*p == '\\')
             {
-              p++;
-              c_parse_escape (&p, NULL);
+             const char *s, *o;
+
+             s = o = ++p;
+             c_parse_escape (&s, NULL);
+             p += s - o;
             }
           else
             p++;
@@ -640,7 +657,7 @@ append_tokens_without_splicing (struct macro_buffer *dest,
    stringify; it is LEN bytes long.  */
 
 static void
-stringify (struct macro_buffer *dest, char *arg, int len)
+stringify (struct macro_buffer *dest, const char *arg, int len)
 {
   /* Trim initial whitespace from ARG.  */
   while (len > 0 && macro_is_whitespace (*arg))
@@ -683,6 +700,21 @@ stringify (struct macro_buffer *dest, char *arg, int len)
   dest->last_token = dest->len;
 }
 
+/* See macroexp.h.  */
+
+char *
+macro_stringify (const char *str)
+{
+  struct macro_buffer buffer;
+  int len = strlen (str);
+
+  init_buffer (&buffer, len);
+  stringify (&buffer, str, len);
+  appendc (&buffer, '\0');
+
+  return free_buffer_return_text (&buffer);
+}
+
 \f
 /* Expanding macros!  */
 
@@ -704,7 +736,7 @@ struct macro_name_list {
    particular macro, and otherwise delegates the decision to another
    function/baton pair.  But that makes the linked list of excluded
    macros chained through untyped baton pointers, which will make it
-   harder to debug.  :( */
+   harder to debug.  :(  */
 static int
 currently_rescanning (struct macro_name_list *list, const char *name)
 {
@@ -786,7 +818,7 @@ gather_arguments (const char *name, struct macro_buffer *src,
 
   args_len = 0;
   args_size = 6;
-  args = (struct macro_buffer *) xmalloc (sizeof (*args) * args_size);
+  args = XNEWVEC (struct macro_buffer, args_size);
 
   for (;;)
     {
@@ -797,7 +829,7 @@ gather_arguments (const char *name, struct macro_buffer *src,
       if (args_len >= args_size)
         {
           args_size *= 2;
-          args = xrealloc (args, sizeof (*args) * args_size);
+          args = XRESIZEVEC (struct macro_buffer, args, args_size);
         }
 
       /* Initialize the next argument.  */
@@ -830,7 +862,8 @@ gather_arguments (const char *name, struct macro_buffer *src,
                      if (args_len >= args_size)
                        {
                          args_size++;
-                         args = xrealloc (args, sizeof (*args) * args_size);
+                         args = XRESIZEVEC (struct macro_buffer, args,
+                                            args_size);
                        }
                      arg = &args[args_len++];
                      set_token (arg, src->text, src->text);
@@ -902,7 +935,8 @@ find_parameter (const struct macro_buffer *tok,
     return -1;
 
   for (i = 0; i < argc; ++i)
-    if (tok->len == strlen (argv[i]) && ! memcmp (tok->text, argv[i], tok->len))
+    if (tok->len == strlen (argv[i]) 
+       && !memcmp (tok->text, argv[i], tok->len))
       return i;
 
   if (is_varargs && tok->len == va_arg_name->len
@@ -912,6 +946,30 @@ find_parameter (const struct macro_buffer *tok,
   return -1;
 }
  
+/* Helper function for substitute_args that gets the next token and
+   updates the passed-in state variables.  */
+
+static void
+get_next_token_for_substitution (struct macro_buffer *replacement_list,
+                                struct macro_buffer *token,
+                                char **start,
+                                struct macro_buffer *lookahead,
+                                char **lookahead_start,
+                                int *lookahead_valid,
+                                bool *keep_going)
+{
+  if (!*lookahead_valid)
+    *keep_going = false;
+  else
+    {
+      *keep_going = true;
+      *token = *lookahead;
+      *start = *lookahead_start;
+      *lookahead_start = replacement_list->text;
+      *lookahead_valid = get_token (lookahead, replacement_list);
+    }
+}
+
 /* Given the macro definition DEF, being invoked with the actual
    arguments given by ARGC and ARGV, substitute the arguments into the
    replacement list, and store the result in DEST.
@@ -950,7 +1008,7 @@ substitute_args (struct macro_buffer *dest,
      lexed.  */
   char *lookahead_rl_start;
 
-  init_shared_buffer (&replacement_list, (char *) def->replacement,
+  init_shared_buffer (&replacement_list, def->replacement,
                       strlen (def->replacement));
 
   gdb_assert (dest->len == 0);
@@ -962,8 +1020,64 @@ substitute_args (struct macro_buffer *dest,
   lookahead_rl_start = replacement_list.text;
   lookahead_valid = get_token (&lookahead, &replacement_list);
 
-  for (;;)
+  /* __VA_OPT__ state variable.  The states are:
+     0 - nothing happening
+     1 - saw __VA_OPT__
+     >= 2 in __VA_OPT__, the value encodes the parenthesis depth.  */
+  unsigned vaopt_state = 0;
+
+  for (bool keep_going = true;
+       keep_going;
+       get_next_token_for_substitution (&replacement_list,
+                                       &tok,
+                                       &original_rl_start,
+                                       &lookahead,
+                                       &lookahead_rl_start,
+                                       &lookahead_valid,
+                                       &keep_going))
     {
+      bool token_is_vaopt = (tok.len == 10
+                            && strncmp (tok.text, "__VA_OPT__", 10) == 0);
+
+      if (vaopt_state > 0)
+       {
+         if (token_is_vaopt)
+           error (_("__VA_OPT__ cannot appear inside __VA_OPT__"));
+         else if (tok.len == 1 && tok.text[0] == '(')
+           {
+             ++vaopt_state;
+             /* We just entered __VA_OPT__, so don't emit this
+                token.  */
+             continue;
+           }
+         else if (vaopt_state == 1)
+           error (_("__VA_OPT__ must be followed by an open parenthesis"));
+         else if (tok.len == 1 && tok.text[0] == ')')
+           {
+             --vaopt_state;
+             if (vaopt_state == 1)
+               {
+                 /* Done with __VA_OPT__.  */
+                 vaopt_state = 0;
+                 /* Don't emit.  */
+                 continue;
+               }
+           }
+
+         /* If __VA_ARGS__ is empty, then drop the contents of
+            __VA_OPT__.  */
+         if (argv[argc - 1].len == 0)
+           continue;
+       }
+      else if (token_is_vaopt)
+       {
+         if (!is_varargs)
+           error (_("__VA_OPT__ is only valid in a variadic macro"));
+         vaopt_state = 1;
+         /* Don't emit this token.  */
+         continue;
+       }
+
       /* Just for aesthetics.  If we skipped some whitespace, copy
          that to DEST.  */
       if (tok.text > original_rl_start)
@@ -1123,16 +1237,10 @@ substitute_args (struct macro_buffer *dest,
          if (! substituted)
            append_tokens_without_splicing (dest, &tok);
        }
-
-      if (! lookahead_valid)
-       break;
-
-      tok = lookahead;
-      original_rl_start = lookahead_rl_start;
-
-      lookahead_rl_start = replacement_list.text;
-      lookahead_valid = get_token (&lookahead, &replacement_list);
     }
+
+  if (vaopt_state > 0)
+    error (_("Unterminated __VA_OPT__"));
 }
 
 
@@ -1140,7 +1248,7 @@ substitute_args (struct macro_buffer *dest,
    its expansion to DEST.  SRC is the input text following the ID
    token.  We are currently rescanning the expansions of the macros
    named in NO_LOOP; don't re-expand them.  Use LOOKUP_FUNC and
-   LOOKUP_BATON to find definitions for any nested macro references.  
+   LOOKUP_BATON to find definitions for any nested macro references.
 
    Return 1 if we decided to expand it, zero otherwise.  (If it's a
    function-like macro name that isn't followed by an argument list,
@@ -1169,7 +1277,7 @@ expand (const char *id,
     {
       struct macro_buffer replacement_list;
 
-      init_shared_buffer (&replacement_list, (char *) def->replacement,
+      init_shared_buffer (&replacement_list, def->replacement,
                           strlen (def->replacement));
 
       scan (dest, &replacement_list, &new_no_loop, lookup_func, lookup_baton);
@@ -1182,7 +1290,7 @@ expand (const char *id,
       struct macro_buffer *argv = NULL;
       struct macro_buffer substituted;
       struct macro_buffer substituted_src;
-      struct macro_buffer va_arg_name;
+      struct macro_buffer va_arg_name = {0};
       int is_varargs = 0;
 
       if (def->argc >= 1)
@@ -1206,7 +1314,7 @@ expand (const char *id,
                     substitution parameter is the name of the formal
                     argument without the "...".  */
                  init_shared_buffer (&va_arg_name,
-                                     (char *) def->argv[def->argc - 1],
+                                     def->argv[def->argc - 1],
                                      len - 3);
                  is_varargs = 1;
                }
@@ -1301,7 +1409,7 @@ maybe_expand (struct macro_buffer *dest,
     {
       /* Make a null-terminated copy of it, since that's what our
          lookup function expects.  */
-      char *id = xmalloc (src_first->len + 1);
+      char *id = (char *) xmalloc (src_first->len + 1);
       struct cleanup *back_to = make_cleanup (xfree, id);
 
       memcpy (id, src_first->text, src_first->len);
@@ -1385,7 +1493,7 @@ macro_expand (const char *source,
   struct macro_buffer src, dest;
   struct cleanup *back_to;
 
-  init_shared_buffer (&src, (char *) source, strlen (source));
+  init_shared_buffer (&src, source, strlen (source));
 
   init_buffer (&dest, 0);
   dest.last_token = 0;
@@ -1410,7 +1518,7 @@ macro_expand_once (const char *source,
 
 
 char *
-macro_expand_next (char **lexptr,
+macro_expand_next (const char **lexptr,
                    macro_lookup_ftype *lookup_func,
                    void *lookup_baton)
 {
This page took 0.028025 seconds and 4 git commands to generate.