Fri Jul  2 22:13:14 1999  Mumit Khan  <khan@xraylith.wisc.edu>

	* c-pragma.h (PRAGMA_INSERT_ATTRIBUTES): Delete macro.
	(insert_pack_attributes): Delete prototype.
	(enum pragma_state): Simplify.

	* c-pragma.c (struct align_stack): Lose num_pushes field.
	(push_alignment): Remove redundant check for valid alignment;
	always push on stack.
	(pop_alignment): Update prototype. Implement combination rule.
	(insert_pack_attributes): Lose.
	(handle_pragma_token): Document syntax. Simplify pack(push/pop)
	attributes and implement documented syntax.

Index: gcc-2.95.2/gcc/c-pragma.c
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-2.95.2/gcc/c-pragma.c,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 c-pragma.c
--- gcc-2.95.2/gcc/c-pragma.c	1999/11/05 01:09:41	1.1.1.1
+++ gcc-2.95.2/gcc/c-pragma.c	1999/11/05 06:37:53
@@ -44,7 +44,6 @@ extern int maximum_field_alignment;
 typedef struct align_stack
 {
   int                  alignment;
-  unsigned int         num_pushes;
   tree                 id;
   struct align_stack * prev;
 } align_stack;
@@ -52,7 +51,7 @@ typedef struct align_stack
 static struct align_stack * alignment_stack = NULL;
 
 static int  push_alignment PROTO((int, tree));
-static int  pop_alignment  PROTO((tree));
+static int  pop_alignment  PROTO((int, tree));
 
 /* Push an alignment value onto the stack.  */
 static int
@@ -60,159 +59,88 @@ push_alignment (alignment, id)
      int alignment;
      tree id;
 {
-  switch (alignment)
+  align_stack * entry;
+
+  entry = (align_stack *) xmalloc (sizeof (* entry));
+
+  if (entry == NULL)
     {
-    case 0:
-    case 1:
-    case 2:
-    case 4:
-    case 8:
-    case 16:
-      break;
-    default:
-      warning ("\
-Alignment must be a small power of two, not %d, in #pragma pack",
-	       alignment);
+      warning ("Out of memory pushing #pragma pack");
       return 0;
     }
-  
-  if (alignment_stack == NULL
-      || alignment_stack->alignment != alignment
-      || id != NULL_TREE)
-    {
-      align_stack * entry;
 
-      entry = (align_stack *) xmalloc (sizeof (* entry));
-
-      if (entry == NULL)
-	{
-	  warning ("Out of memory pushing #pragma pack");
-	  return 0;
-	}
+  entry->alignment  = maximum_field_alignment;
+  entry->id         = id;
+  entry->prev       = alignment_stack;
 
-      entry->alignment  = alignment;
-      entry->num_pushes = 1;
-      entry->id         = id;
-      entry->prev       = alignment_stack;
-      
-      alignment_stack = entry;
+  alignment_stack = entry;
 
-      maximum_field_alignment = alignment * 8;
-    }
-  else
-    alignment_stack->num_pushes ++;
+  maximum_field_alignment = alignment;
 
   return 1;
 }
 
-/* Undo a push of an alignment onto the stack.  */
+/* Undo a push of an alignment onto the stack.  If the alignment argument
+   is > 0, then make that the new alignment after popping the stack instead 
+   of using TOS. See the combination rules in the #pragma pack(pop[,id][,n]) 
+   syntax for details.  */
 static int
-pop_alignment (id)
+pop_alignment (alignment, id)
+     int alignment;
      tree id;
 {
   align_stack * entry;
-      
-  if (alignment_stack == NULL)
+
+  /* If popping an empty stack, revert to default packing. Defer warning
+     if we got an identifier.  */
+  if (alignment_stack == NULL && id == NULL)
     {
-      warning ("\
-#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
-	       );
-      return 0;
+      warning 
+        ("#pragma pack(pop) encountered without matching #pragma pack(push)");
+      maximum_field_alignment = 0;
+      return 1;
     }
 
   /* If we got an identifier, strip away everything above the target
-     entry so that the next step will restore the state just below it.  */
+     entry so that the next step will restore the state that existed
+     just before the identifier was pushed on the stack.  */
   if (id)
-    {
-      for (entry = alignment_stack; entry; entry = entry->prev)
-	if (entry->id == id)
-	  {
-	    entry->num_pushes = 1;
-	    alignment_stack = entry;
-	    break;
-	  }
-      if (entry == NULL)
-	warning ("\
-#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
-		 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
-    }
-
-  if (-- alignment_stack->num_pushes == 0)
     {
-      entry = alignment_stack->prev;
+      align_stack * popped = NULL;
+      for (entry = alignment_stack; entry; 
+           popped = entry, entry = entry->prev)
+	{
+	  if (popped)
+	    free (popped);
 
+	  if (entry->id == id)
+	    {
+	      alignment_stack = entry;
+	      break;
+	    }
+	}
       if (entry == NULL)
-	maximum_field_alignment = 0;
-      else
-	maximum_field_alignment = entry->alignment * 8;
-
-      free (alignment_stack);
-
-      alignment_stack = entry;
+        {
+	  warning
+	    ("#pragma pack(pop,%s) encountered without matching #pragma pack(push,%s)",
+	     IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
+	  alignment_stack = NULL;
+	  maximum_field_alignment = 0;
+	  return 1;
+	}
     }
 
-  return 1;
-}
+  entry = alignment_stack->prev;
 
-/* Generate 'packed' and 'aligned' attributes for decls whilst a
-   #pragma pack(push... is in effect.  */
-void
-insert_pack_attributes (node, attributes, prefix)
-     tree node;
-     tree * attributes;
-     tree * prefix;
-{
-  tree a;
-  int field_alignment;
+  /* The new alignment is either a user specified one (combination rule)
+     or restored from the stack. */
+  maximum_field_alignment = 
+    (alignment > 0) ? alignment : alignment_stack->alignment;
 
-  /* If we are not packing, then there is nothing to do.  */
-  if (maximum_field_alignment == 0
-      || alignment_stack == NULL)
-    return;
-
-  /* We are only interested in fields.  */
-  if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
-      || TREE_CODE (node) != FIELD_DECL)
-    return;
-  
-  field_alignment = TYPE_ALIGN (TREE_TYPE (node));
-  if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
-    field_alignment = maximum_field_alignment;
-
-  /* Add a 'packed' attribute.  */
-  * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
-  
-  /* If the alignment is > 8 then add an alignment attribute as well.  */
-  if (field_alignment > 8)
-    {
-      /* If the aligned attribute is already present then do not override it.  */
-      for (a = * attributes; a; a = TREE_CHAIN (a))
-	{
-	  tree name = TREE_PURPOSE (a);
-	  if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
-	    break;
-	}
-      
-      if (a == NULL)
-	for (a = * prefix; a; a = TREE_CHAIN (a))
-	  {
-	    tree name = TREE_PURPOSE (a);
-	    if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
-	      break;
-	  }
-  
-      if (a == NULL)
-	{
-	  * attributes = tree_cons
-	      (get_identifier ("aligned"),
-	       tree_cons (NULL,
-			  build_int_2 (field_alignment / 8, 0),
-			  NULL),
-	       * attributes);
-	}
-    }
+  free (alignment_stack);
+  alignment_stack = entry;
 
-  return;
+  return 1;
 }
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
 
@@ -227,8 +155,52 @@ insert_pack_attributes (node, attributes
    the line containing the #pragma directive.  If STRING is NULL, the entire
    line has now been presented to handle_pragma_token() and the return value
    should be zero if the pragma flawed in some way, or if the pragma was not
-   recognised, and non-zero if it was successfully handled.  */
+   recognised, and non-zero if it was successfully handled.
 
+   If HANDLE_PRAGMA_WEAK is defined, handle the weak directives using
+   the following syntax:
+
+   #pragma weak name [= alias]
+
+   If HANDLE_PRAGMA_PACK is defined, handle the pack directives using 
+   the following syntax:
+                                       
+   #pragma pack([n])
+   
+   Specifies packing alignment for structure and union members. The 
+   packing alignment is set at the data-declaration level by the pack 
+   pragma. The pragma takes effect at the first structure or union 
+   declaration after the pragma is seen; the pragma has no effect on 
+   definitions.
+   
+   When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each
+   structure member after the first is stored on the smaller member type
+   or n-byte boundaries. If you use #pragma pack without an argument,
+   the alignment reverts to the default for the target.
+   
+   If HANDLE_PRAGMA_PACK_PUSH_POP is defined, also handle the 
+   following syntax:
+   
+   #pragma pack({ push | pop} [,identifier] [,n])
+   
+   Each occurrence of a #pragma pack with a push argument stores the
+   current packing alignment on a stack; If you provide a value for n, 
+   that value becomes the new packing value. If you specify an 
+   identifier, the identifier is associated with the new packing value.
+   
+   Each occurrence of a #pragma pack with a pop argument pops the stack
+   and uses the value the new packing alignment. If you use pop and the 
+   internal compiler stack is empty, the new alignment is set to be
+   the default alignment for target, and an warning is issued.  If you 
+   use pop and specify a value for n, that value becomes the new packing 
+   value. If you use pop and specify an identifier, all values stored on 
+   the stack are removed from the stack until a matching identifier is 
+   found. The packing value associated with the identifier is also 
+   removed from the stack and the packing value that existed just before 
+   the identifier was pushed becomes the new packing value. If no 
+   matching identifier is found, the packing value set to the default
+   and a warning is issued.  */
+
 int
 handle_pragma_token (string, token)
      const char * string;
@@ -238,7 +210,7 @@ handle_pragma_token (string, token)
   static enum pragma_state type;
   static char * name;
   static char * value;
-  static int align;
+  static int align = -1;
   static tree id;
 
   /* If we have reached the end of the #pragma directive then
@@ -262,11 +234,14 @@ handle_pragma_token (string, token)
 	case ps_pack:
 	  if (state == ps_right)
 	    {
-	      maximum_field_alignment = align * 8;
+	      maximum_field_alignment = align;
 	      ret_val = 1;
 	    }
 	  else
-	    warning ("malformed `#pragma pack'");
+	    {
+	      ret_val = 1; /* Ignore the pragma.  */
+	      warning ("malformed `#pragma pack'");
+	    }
 	  break;
 #endif /* HANDLE_PRAGMA_PACK */
 	  
@@ -275,14 +250,20 @@ handle_pragma_token (string, token)
 	  if (state == ps_right)
 	    ret_val = push_alignment (align, id);
 	  else
-	    warning ("malformed '#pragma pack(push[,id],<n>)'");
+	    {
+	      ret_val = 1; /* Ignore the pragma.  */
+	      warning ("malformed '#pragma pack(push[,id][,n])'");
+	    }
 	  break;
 	  
 	case ps_pop:
 	  if (state == ps_right)
-	    ret_val = pop_alignment (id);
+	    ret_val = pop_alignment (align, id);
 	  else
-	    warning ("malformed '#pragma pack(pop[,id])'");
+	    {
+	      ret_val = 1; /* Ignore the pragma.  */
+	      warning ("malformed '#pragma pack(pop[,id][,n])'");
+	    }
 	  break;
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
 	  
@@ -305,6 +286,7 @@ handle_pragma_token (string, token)
 
       type = state = ps_start;
       id = NULL_TREE;
+      align = -1;
       
       return ret_val;
     }
@@ -418,6 +400,8 @@ handle_pragma_token (string, token)
       break;
 
     handle_align:
+      /* User specified alignment in bytes, but is converted to bits 
+         before use.  */
       align = TREE_INT_CST_LOW (token);
       switch (align)
 	{
@@ -426,10 +410,20 @@ handle_pragma_token (string, token)
 	case 4:
 	case 8:
 	case 16:
+	  align *= 8;
 	  state = ps_align;
 	  break;
 
 	default:
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
+          warning 
+	    ("Alignment must be a small power of two, not %d, in #pragma %s",
+	     align, (type == ps_pop) ? "pop" : "pack");
+#else
+          warning 
+	    ("Alignment must be a small power of two, not %d, in #pragma pack",
+	     align);
+#endif
 	  state = ps_bad;
 	  break;
 	}
@@ -446,45 +440,48 @@ handle_pragma_token (string, token)
 
 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
     case ps_push:
-      state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
-      break;
+      /* If no alignment is specified, push the current alignment.  */
+      align = maximum_field_alignment;
 
-    case ps_pushid:
-      state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
+      /* fall through. */
+    case ps_pop:
+      /* If no alignment is specified, we'll just use the stored one.  */
+      if (strcmp (string, ",") == 0)
+        state = ps_comma;
+      else if (strcmp (string, ")") == 0)
+        {
+	  state = ps_right;
+	}
+      else
+	state = ps_bad;
       break;
 
-    case ps_pushcomma:
+    case ps_comma:
+      /* Id or <n> or both specified. */
       if (token && TREE_CODE (token) == IDENTIFIER_NODE)
 	{
 	  id = token;
-	  state = ps_pushid;
+	  state = ps_id;
 	  break;
 	}
 
-      /* else fall through */
-    case ps_pushcomma2:
+      /* else no id, but <n> specified, so fall through */
+    case ps_comma2:
       if (token && TREE_CODE (token) == INTEGER_CST)
 	goto handle_align;
       else
 	state = ps_bad;
       break;
 
-    case ps_pop:
+    case ps_id:
       if (strcmp (string, ",") == 0)
-	state = ps_popcomma;
+        state = ps_comma2;
+      else if (strcmp (string, ")") == 0)
+	state = ps_right;
       else
-	state = (strcmp (string, ")") ? ps_bad : ps_right);
-      break;
-
-    case ps_popcomma:
-      if (token && TREE_CODE (token) == IDENTIFIER_NODE)
-	{
-	  id = token;
-	  state = ps_align;
-	}
-      else
 	state = ps_bad;
       break;
+
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
       
     case ps_bad:
Index: gcc-2.95.2/gcc/c-pragma.h
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-2.95.2/gcc/c-pragma.h,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 c-pragma.h
--- gcc-2.95.2/gcc/c-pragma.h	1999/11/05 01:09:41	1.1.1.1
+++ gcc-2.95.2/gcc/c-pragma.h	1999/11/05 06:37:53
@@ -39,9 +39,6 @@ Boston, MA 02111-1307, USA.  */
 /* If we are supporting #pragma pack(push... then we automatically
    support #pragma pack(<n>)  */
 #define HANDLE_PRAGMA_PACK 1
-#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \
-  insert_pack_attributes (node, pattr, prefix_attr)
-extern void insert_pack_attributes PROTO((tree, tree *, tree *));
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
 
 
@@ -88,8 +85,11 @@ enum pragma_state
   ps_right,
 #endif
 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
-  ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2,
-  ps_pop, ps_popcomma,
+  ps_push, 
+  ps_pop, 
+  ps_comma, 
+  ps_comma2,
+  ps_id, 
 #endif
   ps_bad
 };
