OSDN Git Service

* cpphash.h (struct _cpp_buff, _cpp_get_buff, _cpp_release_buff,
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Sep 2001 17:52:50 +0000 (17:52 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Sep 2001 17:52:50 +0000 (17:52 +0000)
_cpp_extend_buff, _cpp_free_buff): New.
(struct cpp_reader): New member free_buffs.
* cppinit.c (cpp_destroy): Free buffers.
* cpplex.c (new_buff, _cpp_release_buff, _cpp_get_buff,
_cpp_extend_buff, _cpp_free_buff): New.
* cpplib.h (struct cpp_options): Remove unused member.
* cppmacro.c (collect_args): New.  Combines the old parse_arg
and parse_args.  Use _cpp_buff for memory allocation.
(funlike_invocation_p, replace_args): Update.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45827 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cpphash.h
gcc/cppinit.c
gcc/cpplex.c
gcc/cpplib.h
gcc/cppmacro.c

index c24acee..891bfef 100644 (file)
@@ -1,3 +1,16 @@
+2001-09-26  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cpphash.h (struct _cpp_buff, _cpp_get_buff, _cpp_release_buff,
+       _cpp_extend_buff, _cpp_free_buff): New.
+       (struct cpp_reader): New member free_buffs.
+       * cppinit.c (cpp_destroy): Free buffers.
+       * cpplex.c (new_buff, _cpp_release_buff, _cpp_get_buff,
+       _cpp_extend_buff, _cpp_free_buff): New.
+       * cpplib.h (struct cpp_options): Remove unused member.
+       * cppmacro.c (collect_args): New.  Combines the old parse_arg
+       and parse_args.  Use _cpp_buff for memory allocation.
+       (funlike_invocation_p, replace_args): Update.
+
 Wed Sep 26 13:20:51 CEST 2001  Jan Hubicka  <jh@suse.cz>
 
        * final.c (final_scan_insn): Use delete_insn instead of delete_note.
index 001ac60..ee5b03e 100644 (file)
@@ -72,6 +72,21 @@ struct cpp_pool
   unsigned int locks;
 };
 
+/* A generic memory buffer.  */
+
+typedef struct _cpp_buff _cpp_buff;
+struct _cpp_buff
+{
+  struct _cpp_buff *next;
+  char *base, *cur, *limit;
+};
+
+extern _cpp_buff *_cpp_get_buff PARAMS ((cpp_reader *, unsigned int));
+extern void _cpp_release_buff PARAMS ((cpp_reader *, _cpp_buff *));
+extern _cpp_buff *_cpp_extend_buff PARAMS ((cpp_reader *, _cpp_buff *,
+                                           unsigned int));
+extern void _cpp_free_buff PARAMS ((_cpp_buff *));
+
 /* List of directories to look for include files in.  */
 struct search_path
 {
@@ -254,6 +269,9 @@ struct cpp_reader
   cpp_pool macro_pool;         /* For macro definitions.  Permanent.  */
   cpp_pool argument_pool;      /* For macro arguments.  Temporary.   */
 
+  /* Memory buffers.  */
+  _cpp_buff *free_buffs;
+
   /* Context stack.  */
   struct cpp_context base_context;
   struct cpp_context *context;
index 11c86aa..53e1c68 100644 (file)
@@ -591,6 +591,7 @@ cpp_destroy (pfile)
   _cpp_free_pool (&pfile->ident_pool);
   _cpp_free_pool (&pfile->macro_pool);
   _cpp_free_pool (&pfile->argument_pool);
+  _cpp_free_buff (pfile->free_buffs);
 
   for (run = &pfile->base_run; run; run = runn)
     {
index e822ba5..1ad608d 100644 (file)
@@ -107,6 +107,7 @@ static tokenrun *next_tokenrun PARAMS ((tokenrun *));
 static cpp_chunk *new_chunk PARAMS ((unsigned int));
 static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int));
 static unsigned int hex_digit_value PARAMS ((unsigned int));
+static _cpp_buff *new_buff PARAMS ((unsigned int));
 
 /* Utility routine:
 
@@ -2114,7 +2115,7 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
   return result;
 }
 
-/* Memory pools.  */
+/* Memory buffers.  */
 
 struct dummy
 {
@@ -2127,6 +2128,95 @@ struct dummy
 };
 
 #define DEFAULT_ALIGNMENT (offsetof (struct dummy, u))
+#define CPP_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
+
+/* Create a new allocation buffer.  */
+static _cpp_buff *
+new_buff (len)
+     unsigned int len;
+{
+  _cpp_buff *result;
+  char *base;
+
+  if (len < 4000)
+    len = 4000;
+  len = CPP_ALIGN (len, DEFAULT_ALIGNMENT);
+
+  base = xmalloc (len + sizeof (_cpp_buff));
+  result = (_cpp_buff *) (base + len);
+  result->base = base;
+  result->cur = base;
+  result->limit = base + len;
+  result->next = NULL;
+  return result;
+}
+
+/* Place a chain of unwanted allocation buffers on the free list.  */
+void
+_cpp_release_buff (pfile, buff)
+     cpp_reader *pfile;
+     _cpp_buff *buff;
+{
+  _cpp_buff *end = buff;
+
+  while (end->next)
+    end = end->next;
+  end->next = pfile->free_buffs;
+  pfile->free_buffs = buff;
+}
+
+/* Return a free buffer of size at least MIN_SIZE.  */
+_cpp_buff *
+_cpp_get_buff (pfile, min_size)
+     cpp_reader *pfile;
+     unsigned int min_size;
+{
+  _cpp_buff *result, **p;
+
+  for (p = &pfile->free_buffs;; p = &(*p)->next)
+    {
+      if (*p == NULL || (*p)->next == NULL)
+       return new_buff (min_size);
+      result = (*p)->next;
+      if ((unsigned int) (result->limit - result->base) > min_size)
+       break;
+    }
+
+  *p = result->next;
+  result->next = NULL;
+  result->cur = result->base;
+  return result;
+}
+
+/* Return a buffer chained on the end of BUFF.  Copy to it the
+   uncommitted remaining bytes of BUFF, with at least MIN_EXTRA more
+   bytes.  */
+_cpp_buff *
+_cpp_extend_buff (pfile, buff, min_extra)
+     cpp_reader *pfile;
+     _cpp_buff *buff;
+     unsigned int min_extra;
+{
+  unsigned int size = min_extra + (buff->limit - buff->cur) * 2;
+
+  buff->next = _cpp_get_buff (pfile, size);
+  memcpy (buff->next->base, buff->cur, buff->limit - buff->cur);
+  return buff->next;
+}
+
+/* Free a chain of buffers starting at BUFF.  */
+void
+_cpp_free_buff (buff)
+     _cpp_buff *buff;
+{
+  _cpp_buff *next;
+
+  for (; buff; buff = next)
+    {
+      next = buff->next;
+      free (buff->base);
+    }
+}
 
 static int
 chunk_suitable (pool, chunk, size)
index b8db366..5dc6828 100644 (file)
@@ -236,9 +236,6 @@ struct cpp_options
   /* The language we're preprocessing.  */
   enum c_lang lang;
 
-  /* Nonzero means to return spacing characters for stand-alone CPP.  */
-  unsigned char spacing;
-
   /* Non-0 means -v, so print the full set of include dirs.  */
   unsigned char verbose;
 
index 6cc4502..fd38c08 100644 (file)
@@ -62,8 +62,7 @@ static void push_token_context
   PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int));
 static void push_ptoken_context
   PARAMS ((cpp_reader *, cpp_macro *, const cpp_token **, unsigned int));
-static enum cpp_ttype parse_arg PARAMS ((cpp_reader *, macro_arg *, int));
-static macro_arg *parse_args PARAMS ((cpp_reader *, const cpp_hashnode *));
+static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *));
 static cpp_context *next_context PARAMS ((cpp_reader *));
 static const cpp_token *padding_token
   PARAMS ((cpp_reader *, const cpp_token *));
@@ -461,116 +460,131 @@ paste_all_tokens (pfile, lhs)
   push_token_context (pfile, NULL, pasted, 1);
 }
 
-/* Reads the unexpanded tokens of a macro argument into ARG.  VAR_ARGS
-   is non-zero if this is a variadic macro.  Returns the type of the
-   token that caused reading to finish.  */
-static enum cpp_ttype
-parse_arg (pfile, arg, variadic)
+/* Reads and returns the arguments to a function-like macro invocation.
+   Assumes the opening parenthesis has been processed.  If there is an
+   error, emits an appropriate diagnostic and returns NULL.  */
+static _cpp_buff *
+collect_args (pfile, node)
      cpp_reader *pfile;
-     struct macro_arg *arg;
-     int variadic;
+     const cpp_hashnode *node;
 {
-  enum cpp_ttype result;
-  unsigned int paren = 0;
-
-  arg->first = (const cpp_token **) POOL_FRONT (&pfile->argument_pool);
-  for (;; arg->count++)
+  _cpp_buff *buff, *base_buff;
+  cpp_macro *macro;
+  macro_arg *args, *arg;
+  const cpp_token *token;
+  unsigned int argc;
+  bool error = false;
+
+  macro = node->value.macro;
+  if (macro->paramc)
+    argc = macro->paramc;
+  else
+    argc = 1;
+  buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
+                                      + sizeof (macro_arg)));
+  base_buff = buff;
+  args = (macro_arg *) buff->base;
+  memset (args, 0, argc * sizeof (macro_arg));
+  buff->cur = (char *) &args[argc];
+  arg = args, argc = 0;
+
+  /* Collect the tokens making up each argument.  We don't yet know
+     how many arguments have been supplied, whether too many or too
+     few.  Hence the slightly bizarre usage of "argc" and "arg".  */
+  do
     {
-      const cpp_token *token;
-      const cpp_token **ptoken = &arg->first[arg->count];
-      if ((unsigned char *) (ptoken + 2) >= POOL_LIMIT (&pfile->argument_pool))
-       {
-         _cpp_next_chunk (&pfile->argument_pool, 2 * sizeof (cpp_token *),
-                          (unsigned char **) &arg->first);
-         ptoken = &arg->first[arg->count];
-       }
+      unsigned int paren_depth = 0;
+      unsigned int ntokens = 0;
 
-      /* Drop leading padding.  */
-      do
-       token = cpp_get_token (pfile);
-      while (arg->count == 0 && token->type == CPP_PADDING);
-      *ptoken++ = token;
-      result = token->type;
+      argc++;
+      arg->first = (const cpp_token **) buff->cur;
 
-      if (result == CPP_OPEN_PAREN)
-       paren++;
-      else if (result == CPP_CLOSE_PAREN && paren-- == 0)
-       break;
-      /* Commas are not terminators within parantheses or variadic.  */
-      else if (result == CPP_COMMA && paren == 0 && !variadic)
-       break;
-      else if (result == CPP_EOF)
-       {
-         /* We still need the EOF (added below) to end pre-expansion
-            and directives.  */
-         if (pfile->context->prev || pfile->state.in_directive)
-           _cpp_backup_tokens (pfile, 1);
-         /* Error reported by caller.  */
-         break;
-       }
-      else if (result == CPP_HASH && token->flags & BOL)
+      for (;;)
        {
-         /* 6.10.3 paragraph 11: If there are sequences of
-            preprocessing tokens within the list of arguments that
-            would otherwise act as preprocessing directives, the
-            behavior is undefined.
-
-            This implementation will report a hard error, terminate
-            the macro invocation, and proceed to process the
-            directive.  */
-         cpp_error (pfile,
-                    "directives may not be used inside a macro argument");
-         _cpp_backup_tokens (pfile, 1);
-         result = CPP_EOF;
-         break;
-       }
-    }
-
-  /* Drop trailing padding.  */
-  while (arg->count > 0 && arg->first[arg->count - 1]->type == CPP_PADDING)
-    arg->count--;
+         /* Require space for 2 new tokens (including a CPP_EOF).  */
+         if ((char *) &arg->first[ntokens + 2] > buff->limit)
+           {
+             buff = _cpp_extend_buff (pfile, buff,
+                                      1000 * sizeof (cpp_token *));
+             arg->first = (const cpp_token **) buff->cur;
+           }
 
-  /* Commit the memory used to store the arguments.  We make the last
-     argument a CPP_EOF, so that it terminates macro pre-expansion,
-     but it is not included in arg->count.  */
-  arg->first[arg->count] = &pfile->eof;  
-  POOL_COMMIT (&pfile->argument_pool, (arg->count + 1) * sizeof (cpp_token *));
-  return result;
-}
+         token = cpp_get_token (pfile);
 
-/* Parse the arguments making up a macro invocation.  */
-static macro_arg *
-parse_args (pfile, node)
-     cpp_reader *pfile;
-     const cpp_hashnode *node;
-{
-  cpp_macro *macro = node->value.macro;
-  macro_arg *args, *cur;
-  enum cpp_ttype type;
-  int argc, error = 0;
+         if (token->type == CPP_PADDING)
+           {
+             /* Drop leading padding.  */
+             if (ntokens == 0)
+               continue;
+           }
+         else if (token->type == CPP_OPEN_PAREN)
+           paren_depth++;
+         else if (token->type == CPP_CLOSE_PAREN)
+           {
+             if (paren_depth-- == 0)
+               break;
+           }
+         else if (token->type == CPP_COMMA)
+           {
+             /* A comma does not terminate an argument within
+                parentheses or as part of a variable argument.  */
+             if (paren_depth == 0
+                 && ! (macro->variadic && argc == macro->paramc))
+               break;
+           }
+         else if (token->type == CPP_EOF
+                  || (token->type == CPP_HASH && token->flags & BOL))
+           break;
 
-  /* Allocate room for at least one argument, and zero it out.  */
-  argc = macro->paramc ? macro->paramc: 1;
-  args = xcnewvec (macro_arg, argc);
+         arg->first[ntokens++] = token;
+       }
 
-  for (cur = args, argc = 0; ;)
-    {
-      argc++;
+      /* Drop trailing padding.  */
+      while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
+       ntokens--;
 
-      type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic);
-      if (type == CPP_CLOSE_PAREN || type == CPP_EOF)
-       break;
+      arg->count = ntokens;
+      arg->first[ntokens] = &pfile->eof;
 
-      /* Re-use the last argument for excess arguments.  */
-      if (argc < macro->paramc)
-       cur++;
+      /* Terminate the argument.  Excess arguments loop back and
+        overwrite the final legitimate argument, before failing.  */
+      if (argc <= macro->paramc)
+       {
+         buff->cur = (char *) &arg->first[ntokens + 1];
+         if (argc != macro->paramc)
+           arg++;
+       }
     }
+  while (token->type != CPP_CLOSE_PAREN
+        && token->type != CPP_EOF
+        && token->type != CPP_HASH);
 
-  if (type == CPP_EOF)
+  if (token->type == CPP_EOF || token->type == CPP_HASH)
     {
+      bool step_back = false;
+
+      /* 6.10.3 paragraph 11: If there are sequences of preprocessing
+        tokens within the list of arguments that would otherwise act
+        as preprocessing directives, the behavior is undefined.
+
+        This implementation will report a hard error, terminate the
+        macro invocation, and proceed to process the directive.  */
+      if (token->type == CPP_HASH)
+       {
+         cpp_error (pfile,
+                    "directives may not be used inside a macro argument");
+         step_back = true;
+       }
+      else
+       /* We still need the CPP_EOF to end directives, and to end
+           pre-expansion of a macro argument.  */
+       step_back = (pfile->context->prev || pfile->state.in_directive);
+
+      if (step_back)
+       _cpp_backup_tokens (pfile, 1);
       cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
                 NODE_NAME (node));
-      error = 1;
+      error = true;
     }
   else if (argc < macro->paramc)
     {
@@ -592,28 +606,26 @@ parse_args (pfile, node)
          cpp_error (pfile,
                     "macro \"%s\" requires %u arguments, but only %u given",
                     NODE_NAME (node), macro->paramc, argc);
-         error = 1;
+         error = true;
        }
     }
   else if (argc > macro->paramc)
     {
       /* Empty argument to a macro taking no arguments is OK.  */
-      if (argc != 1 || cur->count)
+      if (argc != 1 || arg->count)
        {
          cpp_error (pfile,
                     "macro \"%s\" passed %u arguments, but takes just %u",
                     NODE_NAME (node), argc, macro->paramc);
-         error = 1;
+         error = true;
        }
     }
 
-  if (error)
-    {
-      free (args);
-      args = 0;
-    }
+  if (!error)
+    return base_buff;
 
-  return args;
+  _cpp_release_buff (pfile, base_buff);
+  return NULL;
 }
 
 static int
@@ -622,7 +634,7 @@ funlike_invocation_p (pfile, node)
      const cpp_hashnode *node;
 {
   const cpp_token *maybe_paren;
-  macro_arg *args = 0;
+  _cpp_buff *buff = NULL;
 
   pfile->state.prevent_expansion++;
   pfile->keep_tokens++;
@@ -634,7 +646,7 @@ funlike_invocation_p (pfile, node)
   pfile->state.parsing_args = 2;
 
   if (maybe_paren->type == CPP_OPEN_PAREN)
-    args = parse_args (pfile, node);
+    buff = collect_args (pfile, node);
   else
     {
       _cpp_backup_tokens (pfile, 1);
@@ -648,14 +660,14 @@ funlike_invocation_p (pfile, node)
   pfile->keep_tokens--;
   pfile->state.prevent_expansion--;
 
-  if (args)
+  if (buff)
     {
       if (node->value.macro->paramc > 0)
-       replace_args (pfile, node->value.macro, args);
-      free (args);
+       replace_args (pfile, node->value.macro, (macro_arg *) buff->base);
+      _cpp_release_buff (pfile, buff);
     }
 
-  return args != 0;
+  return buff != 0;
 }
 
 /* Push the context of a macro onto the context stack.  TOKEN is the
@@ -694,8 +706,8 @@ enter_macro_context (pfile, node)
 }
 
 /* Take the expansion of a function-like MACRO, replacing parameters
-   with the actual arguments.  Each instance is first macro-expanded,
-   unless that paramter is operated upon by the # or ## operators.  */
+   with the actual arguments.  Each argument is macro-expanded before
+   replacement, unless operated upon by the # or ## operators.  */
 static void
 replace_args (pfile, macro, args)
      cpp_reader *pfile;
@@ -904,7 +916,6 @@ expand_arg (pfile, arg)
 {
   unsigned int capacity;
 
-  arg->expanded_count = 0;
   if (arg->count == 0)
     return;