cpphash.c: Fix formatting, update commentary.
authorZack Weinberg <zack@wolery.cumb.org>
Fri, 11 Feb 2000 20:17:27 +0000 (20:17 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Fri, 11 Feb 2000 20:17:27 +0000 (20:17 +0000)
* cpphash.c: Fix formatting, update commentary.
(dump_definition): Take three separate arguments instead of a
MACRODEF structure argument.
* cpphash.h: Update prototype of dump_definition.
* cppinit.c (cpp_finish): Update call of dump_definition.

* cpplib.c (do_define): Always create new hash entry with
T_MACRO type.  Remove redundant check for redefinition of
poisoned identifier.  Update call of dump_definition.
(do_undef): Don't call check_macro_name.  Rename sym_length to
len.
(do_error, do_warning): Don't use copy_rest_of_line or
SKIP_WHITE_SPACE.
(do_warning): Don't use pedwarn for the actual warning,
only the notice about its not being in the standard.  (Fixes
bug with #warning in system headers.)
(do_ident): Stricter argument checking - accept only a single
string after #ident.  Also, macro-expand the line.
(do_xifdef): Use cpp_defined.  De-obfuscate.

(do_pragma): Split out specific pragma handling to separate
functions.  Use get_directive_token.  Update commentary.  Do
not pass on #pragma once or #pragma poison to the front end.
(do_pragma_once, do_pragma_implementation, do_pragma_poison,
do_pragma_default): New.

From-SVN: r31931

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

index a4cdc7354a26814dc49084d2411a9392d89fdde1..3b5ff570d2b5b6e68cf272566a2dddb69e0c5d5b 100644 (file)
@@ -1,3 +1,31 @@
+2000-02-11  Zack Weinberg  <zack@wolery.cumb.org>
+
+       * cpphash.c: Fix formatting, update commentary.
+       (dump_definition): Take three separate arguments instead of a
+       MACRODEF structure argument.
+       * cpphash.h: Update prototype of dump_definition.
+       * cppinit.c (cpp_finish): Update call of dump_definition.
+
+       * cpplib.c (do_define): Always create new hash entry with
+       T_MACRO type.  Remove redundant check for redefinition of
+       poisoned identifier.  Update call of dump_definition.
+       (do_undef): Don't call check_macro_name.  Rename sym_length to
+       len.
+       (do_error, do_warning): Don't use copy_rest_of_line or
+       SKIP_WHITE_SPACE.
+       (do_warning): Don't use pedwarn for the actual warning,
+       only the notice about its not being in the standard.  (Fixes
+       bug with #warning in system headers.)
+       (do_ident): Stricter argument checking - accept only a single
+       string after #ident.  Also, macro-expand the line.
+       (do_xifdef): Use cpp_defined.  De-obfuscate.
+
+       (do_pragma): Split out specific pragma handling to separate
+       functions.  Use get_directive_token.  Update commentary.  Do
+       not pass on #pragma once or #pragma poison to the front end.
+       (do_pragma_once, do_pragma_implementation, do_pragma_poison,
+       do_pragma_default): New.
+
 Feb 11 12:30:53 2000  Jeffrey A Law  (law@cygnus.com)
 
        * jump.c (jump_optimize_1): The first operand in a relational
index 5d6e760921064f437376da8971e56590260216cc..fc2b8ff76d5076eb785ebd38f12c829592aa186d 100644 (file)
@@ -89,8 +89,7 @@ struct argdata
 };
 
 
-/* Return hash function on name.  must be compatible with the one
-   computed a step at a time, elsewhere  */
+/* Calculate hash function on a string.  */
 
 static unsigned int
 hashf (s, len)
@@ -169,7 +168,6 @@ void
 delete_macro (hp)
      HASHNODE *hp;
 {
-
   if (hp->prev != NULL)
     hp->prev->next = hp->next;
   if (hp->next != NULL)
@@ -1575,15 +1573,15 @@ comp_def_part (first, beg1, len1, beg2, len2, last)
    to be read back in again. */
 
 void
-dump_definition (pfile, macro)
+dump_definition (pfile, sym, len, defn)
      cpp_reader *pfile;
-     MACRODEF macro;
+     const U_CHAR *sym;
+     long len;
+     DEFINITION *defn;
 {
-  DEFINITION *defn = macro.defn;
-
-  CPP_RESERVE (pfile, macro.symlen + sizeof "#define ");
+  CPP_RESERVE (pfile, len + sizeof "#define ");
   CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
-  CPP_PUTS_Q (pfile, macro.symnam, macro.symlen);
+  CPP_PUTS_Q (pfile, sym, len);
 
   if (defn->nargs == -1)
     {
index b9742843ed9536c0770c749b7404b6908101608d..c9273d56db954d60f6641e8694e4b6c3193050d7 100644 (file)
@@ -107,6 +107,7 @@ extern MACRODEF create_definition PARAMS ((U_CHAR *, U_CHAR *,
 extern int compare_defs                  PARAMS ((cpp_reader *, DEFINITION *,
                                           DEFINITION *));
 extern void macroexpand                  PARAMS ((cpp_reader *, HASHNODE *));
-extern void dump_definition      PARAMS ((cpp_reader *, MACRODEF));
+extern void dump_definition      PARAMS ((cpp_reader *, const U_CHAR *, long,
+                                          DEFINITION *));
 
 #endif
index 9ca7e7e5616d1e12ceabd3ecb9464f5c0de02f4b..d941546b1ba45d400974558ee16b5ea581435d6f 100644 (file)
@@ -1040,16 +1040,12 @@ cpp_finish (pfile)
     {
       int i;
       HASHNODE *h;
-      MACRODEF m;
       for (i = HASHSIZE; --i >= 0;)
        {
          for (h = pfile->hashtab[i]; h; h = h->next)
            if (h->type == T_MACRO)
              {
-               m.defn = h->value.defn;
-               m.symnam = h->name;
-               m.symlen = h->length;
-               dump_definition (pfile, m);
+               dump_definition (pfile, h->name, h->length, h->value.defn);
                CPP_PUTC (pfile, '\n');
              }
        }
index c64e682f8881e158cc61bd035d3f0eef6a6050dc..9238d3346022893dffd184d02687e9b652a3e54c 100644 (file)
@@ -669,16 +669,10 @@ do_define (pfile, keyword)
   HASHNODE *hp;
   long here;
   U_CHAR *macro, *buf, *end;
-  enum node_type new_type;
 
   here = CPP_WRITTEN (pfile);
   copy_rest_of_line (pfile);
 
-  if (keyword == NULL || keyword->type == T_DEFINE)
-    new_type = T_MACRO;
-  else
-    new_type = T_POISON;
-
   /* Copy out the line so we can pop the token buffer. */
   buf = pfile->token_buffer + here;
   end = CPP_PWRITTEN (pfile);
@@ -694,18 +688,19 @@ do_define (pfile, keyword)
 
   if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen)) != NULL)
     {
-      int ok = 0;
-      /* Redefining a poisoned identifier is even worse than `not ok'.  */
-      if (hp->type == T_POISON)
-       ok = -1;
+      int ok;
+
       /* Redefining a macro is ok if the definitions are the same.  */
-      else if (hp->type == T_MACRO)
+      if (hp->type == T_MACRO)
        ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
       /* Redefining a constant is ok with -D.  */
       else if (hp->type == T_CONST || hp->type == T_STDC)
         ok = ! CPP_OPTIONS (pfile)->done_initializing;
+      /* Otherwise it's not ok.  */
+      else
+       ok = 0;
       /* Print the warning or error if it's not ok.  */
-      if (ok <= 0)
+      if (! ok)
        {
          if (hp->type == T_POISON)
            cpp_error (pfile, "redefining poisoned `%.*s'", 
@@ -720,19 +715,19 @@ do_define (pfile, keyword)
       if (hp->type != T_POISON)
        {
          /* Replace the old definition.  */
-         hp->type = new_type;
+         hp->type = T_MACRO;
          free_definition (hp->value.defn);
          hp->value.defn = mdef.defn;
        }
     }
   else
-    cpp_install (pfile, mdef.symnam, mdef.symlen, new_type, (char *)mdef.defn);
+    cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO, (char *)mdef.defn);
 
   if (keyword != NULL && keyword->type == T_DEFINE)
     {
       if (CPP_OPTIONS (pfile)->debug_output
          || CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
-       dump_definition (pfile, mdef);
+       dump_definition (pfile, mdef.symnam, mdef.symlen, mdef.defn);
       else if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
        pass_thru_directive (mdef.symnam, mdef.symlen, pfile, keyword);
     }
@@ -1444,7 +1439,7 @@ do_undef (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword;
 {
-  int sym_length;
+  int len;
   HASHNODE *hp;
   U_CHAR *buf, *name, *limit;
   int c;
@@ -1465,8 +1460,9 @@ do_undef (pfile, keyword)
   limit = CPP_PWRITTEN(pfile);
 
   /* Copy out the token so we can pop the token buffer. */
-  name = (U_CHAR *) alloca (limit - buf + 1);
-  bcopy(buf, name, limit - buf);
+  len = limit - buf;
+  name = (U_CHAR *) alloca (len + 1);
+  memcpy (name, buf, len);
   name[limit - buf] = '\0';
 
   token = get_directive_token (pfile);
@@ -1478,14 +1474,12 @@ do_undef (pfile, keyword)
 
   CPP_SET_WRITTEN (pfile, here);
 
-  sym_length = check_macro_name (pfile, buf);
-
-  while ((hp = cpp_lookup (pfile, name, sym_length)) != NULL)
+  while ((hp = cpp_lookup (pfile, name, len)) != NULL)
     {
       /* If we are generating additional info for debugging (with -g) we
         need to pass through all effective #undef commands.  */
       if (CPP_OPTIONS (pfile)->debug_output && keyword)
-       pass_thru_directive (name, sym_length, pfile, keyword);
+       pass_thru_directive (name, len, pfile, keyword);
       if (hp->type == T_POISON)
        cpp_error (pfile, "cannot undefine poisoned `%s'", hp->name);
       else 
@@ -1529,14 +1523,14 @@ do_error (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  long here = CPP_WRITTEN (pfile);
-  U_CHAR *text;
-  copy_rest_of_line (pfile);
-  text = pfile->token_buffer + here;
-  SKIP_WHITE_SPACE(text);
+  U_CHAR *text, *limit;
 
-  cpp_error (pfile, "#error %s", text);
-  CPP_SET_WRITTEN (pfile, here);
+  cpp_skip_hspace (pfile);
+  text = CPP_BUFFER (pfile)->cur;
+  skip_rest_of_line (pfile);
+  limit = CPP_BUFFER (pfile)->cur;
+
+  cpp_error (pfile, "#error %.*s", (int)(limit - text), text);
   return 0;
 }
 
@@ -1550,169 +1544,233 @@ do_warning (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  U_CHAR *text;
-  long here = CPP_WRITTEN(pfile);
-  copy_rest_of_line (pfile);
-  text = pfile->token_buffer + here;
-  SKIP_WHITE_SPACE(text);
+  U_CHAR *text, *limit;
+
+  cpp_skip_hspace (pfile);
+  text = CPP_BUFFER (pfile)->cur;
+  skip_rest_of_line (pfile);
+  limit = CPP_BUFFER (pfile)->cur;
 
   if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
     cpp_pedwarn (pfile, "ANSI C does not allow `#warning'");
 
-  /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
-     if -pedantic-errors is given, #warning should cause an error.  */
-  cpp_pedwarn (pfile, "#warning %s", text);
-  CPP_SET_WRITTEN (pfile, here);
+  cpp_warning (pfile, "#warning %.*s", (int)(limit - text), text);
   return 0;
 }
 
-/* Report program identification.
-   This is not precisely what cccp does with #ident, however I believe
-   it matches `closely enough' (behavior is identical as long as there
-   are no macros on the #ident line, which is pathological in my opinion).  */
+/* Report program identification.  */
 
 static int
 do_ident (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
+  long old_written = CPP_WRITTEN (pfile);
+
   /* Allow #ident in system headers, since that's not user's fault.  */
   if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
     cpp_pedwarn (pfile, "ANSI C does not allow `#ident'");
 
   CPP_PUTS (pfile, "#ident ", 7);
-  cpp_skip_hspace (pfile);
-  copy_rest_of_line (pfile);
+
+  /* Next token should be a string constant.  */
+  if (get_directive_token (pfile) == CPP_STRING)
+    /* And then a newline.  */
+    if (get_directive_token (pfile) == CPP_VSPACE)
+      /* Good - ship it.  */
+      return 0;
+
+  cpp_error (pfile, "invalid #ident");
+  skip_rest_of_line (pfile);
+  CPP_SET_WRITTEN (pfile, old_written);  /* discard directive */
 
   return 0;
 }
 
-/* Just check for some recognized pragmas that need validation here,
-   and leave the text in the token buffer to be output. */
+/* Pragmata handling.  We handle some of these, and pass the rest on
+   to the front end.  C99 defines three pragmas and says that no macro
+   expansion is to be performed on them; whether or not macro
+   expansion happens for other pragmas is implementation defined.
+   This implementation never macro-expands the text after #pragma.
+
+   We currently do not support the _Pragma operator.  Support for that
+   has to be coordinated with the front end.  Proposed implementation:
+   both #pragma blah blah and _Pragma("blah blah") become
+   __builtin_pragma(blah blah) and we teach the parser about that.  */
+
+/* Sub-handlers for the pragmas needing treatment here.
+   They return 1 if the token buffer is to be popped, 0 if not. */
+static int do_pragma_once              PARAMS ((cpp_reader *));
+static int do_pragma_implementation    PARAMS ((cpp_reader *));
+static int do_pragma_poison            PARAMS ((cpp_reader *));
+static int do_pragma_default           PARAMS ((cpp_reader *));
 
 static int
 do_pragma (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  long here;
+  long here, key;
   U_CHAR *buf;
+  int pop;
 
-  CPP_PUTS (pfile, "#pragma ", 8);
-  cpp_skip_hspace (pfile);
-  
   here = CPP_WRITTEN (pfile);
-  copy_rest_of_line (pfile);
-  buf = pfile->token_buffer + here;
-  
-  if (!strncmp (buf, "once", 4))
-    {
-      cpp_buffer *ip = NULL;
+  CPP_PUTS (pfile, "#pragma ", 8);
 
-      /* Allow #pragma once in system headers, since that's not the user's
-        fault.  */
-      if (!CPP_BUFFER (pfile)->system_header_p)
-       cpp_warning (pfile, "`#pragma once' is obsolete");
-      
-      for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
-        {
-         if (ip == CPP_NULL_BUFFER (pfile))
-           return 0;
-         if (ip->fname != NULL)
-           break;
-       }
+  key = CPP_WRITTEN (pfile);
+  pfile->no_macro_expand++;
+  if (get_directive_token (pfile) != CPP_NAME)
+    goto skip;
+
+  buf = pfile->token_buffer + key;
+  CPP_PUTC (pfile, ' ');
+
+#define tokis(x) !strncmp(buf, x, sizeof(x) - 1)
+  if (tokis ("once"))
+    pop = do_pragma_once (pfile);
+  else if (tokis ("implementation"))
+    pop = do_pragma_implementation (pfile);
+  else if (tokis ("poison"))
+    pop = do_pragma_poison (pfile);
+  else
+    pop = do_pragma_default (pfile);
+#undef tokis
 
-      if (CPP_PREV_BUFFER (ip) == CPP_NULL_BUFFER (pfile))
-       cpp_warning (pfile, "`#pragma once' outside include file");
-      else
-       ip->ihash->control_macro = "";  /* never repeat */
-    }
-  else if (!strncmp (buf, "implementation", 14))
-    {
-      /* Be quiet about `#pragma implementation' for a file only if it hasn't
-        been included yet.  */
-      struct include_hash *ptr;
-      U_CHAR *p = buf + 14, *fname, *fcopy;
-      SKIP_WHITE_SPACE (p);
-      if (*p == '\n' || *p != '\"')
-        return 0;
+  if (get_directive_token (pfile) != CPP_VSPACE)
+    goto skip;
 
-      fname = p + 1;
-      p = (U_CHAR *) index (fname, '\"');
+  if (pop)
+    CPP_SET_WRITTEN (pfile, here);
+  pfile->no_macro_expand--;
+  return 0;
 
-      fcopy = (U_CHAR *) alloca (p - fname + 1);
-      bcopy (fname, fcopy, p - fname);
-      fcopy[p-fname] = '\0';
+ skip:
+  cpp_error (pfile, "malformed #pragma directive");
+  skip_rest_of_line (pfile);
+  CPP_SET_WRITTEN (pfile, here);
+  pfile->no_macro_expand--;
+  return 0;
+}
 
-      ptr = include_hash (pfile, fcopy, 0);
-      if (ptr)
-        cpp_warning (pfile,
-         "`#pragma implementation' for `%s' appears after file is included",
-                    fcopy);
-    }
-  else if (!strncmp (buf, "poison", 6))
+static int
+do_pragma_default (pfile)
+     cpp_reader *pfile;
+{
+  while (get_directive_token (pfile) != CPP_VSPACE)
+    CPP_PUTC (pfile, ' ');
+  return 0;
+}
+
+static int
+do_pragma_once (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *ip = CPP_BUFFER (pfile);
+
+  if (ip->fname == NULL)
     {
-      /* Poison these symbols so that all subsequent usage produces an
-        error message.  */
-      U_CHAR *p = buf + 6;
-      size_t plen;
-      U_CHAR *syms;
-      int writeit;
+      cpp_ice (pfile, "ip->fname == NULL in do_pragma_once");
+      return 1;
+    }
+  
+  /* Allow #pragma once in system headers, since that's not the user's
+     fault.  */
+  if (!ip->system_header_p)
+    cpp_warning (pfile, "`#pragma once' is obsolete");
+      
+  if (CPP_PREV_BUFFER (ip) == CPP_NULL_BUFFER (pfile))
+    cpp_warning (pfile, "`#pragma once' outside include file");
+  else
+    ip->ihash->control_macro = "";  /* never repeat */
 
-      SKIP_WHITE_SPACE (p);
-      plen = strlen(p) + 1;
+  return 1;
+}
 
-      syms = (U_CHAR *) alloca (plen);
-      memcpy (syms, p, plen);
+static int
+do_pragma_implementation (pfile)
+     cpp_reader *pfile;
+{
+  /* Be quiet about `#pragma implementation' for a file only if it hasn't
+     been included yet.  */
+  struct include_hash *ptr;
+  enum cpp_token token;
+  long written = CPP_WRITTEN (pfile);
+  U_CHAR *name;
+  U_CHAR *copy;
 
-      /* As a rule, don't include #pragma poison commands in output,  
-         unless the user asks for them.  */
-      writeit = (CPP_OPTIONS (pfile)->debug_output
-                || CPP_OPTIONS (pfile)->dump_macros == dump_definitions
-                || CPP_OPTIONS (pfile)->dump_macros == dump_names);
+  token = get_directive_token (pfile);
+  if (token == CPP_VSPACE)
+    return 0;
+  else if (token != CPP_STRING)
+    {
+      cpp_error (pfile, "malformed #pragma implementation");
+      return 1;
+    }
 
-      if (writeit)
-       CPP_SET_WRITTEN (pfile, here);
-      else
-       CPP_SET_WRITTEN (pfile, here-8);
+  name = pfile->token_buffer + written + 1;
+  copy = xstrdup (name);
+  copy[strlen(copy)] = '\0';  /* trim trailing quote */
+  
+  ptr = include_hash (pfile, copy, 0);
+  if (ptr)
+    cpp_warning (pfile,
+        "`#pragma implementation' for `%s' appears after file is included",
+                copy);
+  free (copy);
+  return 0;
+}
 
-      if (writeit)
+static int
+do_pragma_poison (pfile)
+     cpp_reader *pfile;
+{
+  /* Poison these symbols so that all subsequent usage produces an
+     error message.  */
+  U_CHAR *p;
+  HASHNODE *hp;
+  long written;
+  size_t len;
+  enum cpp_token token;
+  int writeit;
+  /* As a rule, don't include #pragma poison commands in output,  
+     unless the user asks for them.  */
+  writeit = (CPP_OPTIONS (pfile)->debug_output
+            || CPP_OPTIONS (pfile)->dump_macros == dump_definitions
+            || CPP_OPTIONS (pfile)->dump_macros == dump_names);
+
+  for (;;)
+    {
+      written = CPP_WRITTEN (pfile);
+      token = get_directive_token (pfile);
+      if (token == CPP_VSPACE)
+       break;
+      if (token != CPP_NAME)
        {
-         CPP_RESERVE (pfile, plen + 7);
-         CPP_PUTS_Q (pfile, "poison", 7);
+         cpp_error (pfile, "invalid #pragma poison directive");
+         skip_rest_of_line (pfile);
+         return 1;
        }
 
-      while (*syms != '\0')
+      p = pfile->token_buffer + written;
+      len = strlen (p);
+      if ((hp = cpp_lookup (pfile, p, len)))
        {
-         U_CHAR *end = syms;
-         
-         while (is_idchar(*end))
-           end++;
-
-         if (!is_hspace(*end) && *end != '\0')
-           {
-             cpp_error (pfile, "invalid #pragma poison directive");
-             return 1;
-           }
-
-         if (cpp_push_buffer (pfile, syms, end - syms) != NULL)
-           {
-             do_define (pfile, keyword);
-             cpp_pop_buffer (pfile);
-           }
-         if (writeit)
+         if (hp->type != T_POISON)
            {
-             CPP_PUTC_Q (pfile, ' ');
-             CPP_PUTS_Q (pfile, syms, end - syms);
+             cpp_warning (pfile, "poisoning existing macro `%s'", p);
+             free_definition (hp->value.defn);
+             hp->value.defn = 0;
+             hp->type = T_POISON;
            }
-         syms = end;
-         SKIP_WHITE_SPACE (syms);
        }
+      else
+       cpp_install (pfile, p, len, T_POISON, 0);
+      if (writeit)
+       CPP_PUTC (pfile, ' ');
     }
-
-  return 0;
+  return !writeit;
 }
-
 #ifdef SCCS_DIRECTIVE
 /* Just ignore #sccs, on systems where we define it at all.  */
 
@@ -1727,7 +1785,6 @@ do_sccs (pfile, keyword)
   return 0;
 }
 #endif
-\f
 
 /* We've found an `#if' directive.  If the only thing before it in
    this file is white space, and if it is of the form
@@ -1933,18 +1990,15 @@ do_xifdef (pfile, keyword)
     }
   else if (token == CPP_NAME)
     {
-      HASHNODE *hp = cpp_lookup (pfile, ident, ident_length);
-      skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
+      skip = cpp_defined (pfile, ident, ident_length);
+      if (keyword->type == T_IFDEF)
+       skip = !skip;
+
       if (start_of_file && !skip)
        {
          control_macro = (U_CHAR *) xmalloc (ident_length + 1);
          bcopy (ident, control_macro, ident_length + 1);
        }
-      if (hp != NULL && hp->type == T_POISON)
-       {
-         cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
-         skip = !skip;
-       }
     }
   else
     {