Consolidate .comm and .lcomm code

Alan Modra amodra@bigpond.net.au
Sat Dec 13 08:13:00 GMT 2003


Removes some duplication of code by merging code that handles .comm and
.lcomm.  In the process, the generic code gets the better error checking
of obj-elf.c, eg. that the size of a common var doesn't exceed that
representable by arch_info->bits_per_address.  This does change some
error messages (sorry translators!) because it's not appropriate to
mention ".comm" when emitting an error for ".lcomm".

gas/ChangeLog
	* read.c: Remove unneeded prototypes.
	(s_comm): Split out code to..
	(s_comm_internal): ..here.  Tidy error returns.  Rearrange so that
	"name" from input line may be used in more places.  Merge code
	testing for valid size from elf_common.  Merge code from
	s_lcomm_internal.  Call comm_parse_extra.
	(bss_alloc): New function, split out of s_lcomm_internal and
	elf_common.
	(parse_align): Likewise.
	(s_lcomm_internal): Rewrite.
	(s_lcomm, s_lcomm_bytes): Use s_comm_internal.
	* read.h (bss_alloc, parse_align, s_comm_internal): Declare.
	* config/obj-elf.c (elf_common): Split out code to..
	(elf_common_parse): ..here.  Remove code common to s_comm_internal,
	parse_align and bss_alloc.  Rearrange and Tidy.
	* config/tc-alpha.h (TC_IMPLICIT_LCOMM_ALIGNMENT): Define.

Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.71
diff -c -p -r1.71 read.c
*** gas/read.c	27 Nov 2003 19:14:41 -0000	1.71
--- gas/read.c	13 Dec 2003 02:53:13 -0000
*************** static int dwarf_file_string;
*** 214,235 ****
  #endif
  #endif
  
- static void cons_worker (int, int);
- static int scrub_from_string (char *, int);
  static void do_align (int, char *, int, int);
  static void s_align (int, int);
- static void s_lcomm_internal (int, int);
  static int hex_float (int, char *);
- static inline int sizeof_sleb128 (offsetT);
- static inline int sizeof_uleb128 (valueT);
- static inline int output_sleb128 (char *, offsetT);
- static inline int output_uleb128 (char *, valueT);
- static inline int output_big_sleb128 (char *, LITTLENUM_TYPE *, int);
- static inline int output_big_uleb128 (char *, LITTLENUM_TYPE *, int);
- static int output_big_leb128 (char *, LITTLENUM_TYPE *, int, int);
- static void do_org (segT, expressionS *, int);
- char *demand_copy_string (int *lenP);
- static segT get_segmented_expression (expressionS *expP);
  static segT get_known_segmented_expression (expressionS * expP);
  static void pobegin (void);
  static int get_line_sb (sb *);
--- 214,222 ----
*************** s_align_ptwo (int arg)
*** 1328,1343 ****
    s_align (arg, 0);
  }
  
! void
! s_comm (int ignore ATTRIBUTE_UNUSED)
  {
!   register char *name;
!   register char c;
!   register char *p;
!   offsetT temp;
!   register symbolS *symbolP;
    char *stop = NULL;
    char stopc;
  
    if (flag_mri)
      stop = mri_comment_field (&stopc);
--- 1315,1332 ----
    s_align (arg, 0);
  }
  
! symbolS *
! s_comm_internal (int param,
! 		 symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
  {
!   char *name;
!   char c;
!   char *p;
!   offsetT temp, size;
!   symbolS *symbolP = NULL;
    char *stop = NULL;
    char stopc;
+   expressionS exp;
  
    if (flag_mri)
      stop = mri_comment_field (&stopc);
*************** s_comm (int ignore ATTRIBUTE_UNUSED)
*** 1352,1426 ****
      {
        as_bad (_("expected symbol name"));
        discard_rest_of_line ();
!       return;
      }
  
    SKIP_WHITESPACE ();
  
!   if (*input_line_pointer != ',')
      {
!       *p = 0;
!       as_bad (_("expected comma after \"%s\""), name);
        *p = c;
        ignore_rest_of_line ();
!       if (flag_mri)
! 	mri_comment_end (stop, stopc);
!       return;
      }
! 
!   input_line_pointer++;		/* skip ',' */
! 
!   if ((temp = get_absolute_expression ()) < 0)
      {
!       as_warn (_(".COMMon length (%lu) out of range ignored"),
! 	       (unsigned long) temp);
        ignore_rest_of_line ();
!       if (flag_mri)
! 	mri_comment_end (stop, stopc);
!       return;
      }
  
-   *p = 0;
    symbolP = symbol_find_or_make (name);
-   *p = c;
- 
    if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
      {
!       as_bad (_("symbol `%s' is already defined"),
! 	      S_GET_NAME (symbolP));
        ignore_rest_of_line ();
!       if (flag_mri)
! 	mri_comment_end (stop, stopc);
!       return;
      }
  
!   if (S_GET_VALUE (symbolP))
!     {
!       if (S_GET_VALUE (symbolP) != (valueT) temp)
! 	as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"),
! 		S_GET_NAME (symbolP),
! 		(long) S_GET_VALUE (symbolP),
! 		(long) temp);
!     }
    else
      {
!       S_SET_VALUE (symbolP, (valueT) temp);
        S_SET_EXTERNAL (symbolP);
-     }
  #ifdef OBJ_VMS
!   {
!     extern int flag_one;
!     if (!temp || !flag_one)
!       S_GET_OTHER(symbolP) = const_flag;
!   }
! #endif /* not OBJ_VMS */
!   know (symbolP->sy_frag == &zero_address_frag);
  
    demand_empty_rest_of_line ();
! 
    if (flag_mri)
      mri_comment_end (stop, stopc);
! }				/* s_comm() */
  
  /* The MRI COMMON pseudo-op.  We handle this by creating a common
     symbol with the appropriate name.  We make s_space do the right
--- 1341,1423 ----
      {
        as_bad (_("expected symbol name"));
        discard_rest_of_line ();
!       goto out;
      }
  
    SKIP_WHITESPACE ();
  
!   /* Accept an optional comma after the name.  The comma used to be
!      required, but Irix 5 cc does not generate it for .lcomm.  */
!   if (*input_line_pointer == ',')
!     input_line_pointer++;
! 
!   *p = 0;
!   temp = get_absolute_expr (&exp);
!   size = temp;
! #ifdef BFD_ASSEMBLER
!   size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
! #endif
!   if (exp.X_op == O_absent)
      {
!       as_bad (_("missing size expression"));
        *p = c;
        ignore_rest_of_line ();
!       goto out;
      }
!   else if (temp != size || !exp.X_unsigned)
      {
!       as_warn (_("size (%ld) out of range, ignored"), (long) temp);
!       *p = c;
        ignore_rest_of_line ();
!       goto out;
      }
  
    symbolP = symbol_find_or_make (name);
    if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
      {
!       symbolP = NULL;
!       as_bad (_("symbol `%s' is already defined"), name);
!       *p = c;
        ignore_rest_of_line ();
!       goto out;
      }
  
!   size = S_GET_VALUE (symbolP);
!   if (size == 0)
!     size = temp;
!   else if (size != temp)
!     as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
! 	     name, (long) size, (long) temp);
! 
!   *p = c;
!   if (comm_parse_extra != NULL)
!     symbolP = (*comm_parse_extra) (param, symbolP, size);
    else
      {
!       S_SET_VALUE (symbolP, (valueT) size);
        S_SET_EXTERNAL (symbolP);
  #ifdef OBJ_VMS
!       {
! 	extern int flag_one;
! 	if (size == 0 || !flag_one)
! 	  S_GET_OTHER (symbolP) = const_flag;
!       }
! #endif
!     }
  
+   know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag);
    demand_empty_rest_of_line ();
!  out:
    if (flag_mri)
      mri_comment_end (stop, stopc);
!   return symbolP;
! }
! 
! void
! s_comm (int ignore)
! {
!   s_comm_internal (ignore, NULL);
! }
  
  /* The MRI COMMON pseudo-op.  We handle this by creating a common
     symbol with the appropriate name.  We make s_space do the right
*************** s_linkonce (int ignore ATTRIBUTE_UNUSED)
*** 1917,1983 ****
    demand_empty_rest_of_line ();
  }
  
! static void
! s_lcomm_internal (/* 1 if this was a ".bss" directive, which may
! 		     require a 3rd argument (alignment); 0 if it was
! 		     an ".lcomm" (2 args only).  */
! 		  int needs_align,
! 		  /* 1 if the alignment value should be interpreted as
! 		     the byte boundary, rather than the power of 2.  */
! 		  int bytes_p)
  {
!   register char *name;
!   register char c;
!   register char *p;
!   register int temp;
!   register symbolS *symbolP;
    segT current_seg = now_seg;
    subsegT current_subseg = now_subseg;
-   const int max_alignment = 15;
-   int align = 0;
    segT bss_seg = bss_section;
  
-   name = input_line_pointer;
-   c = get_symbol_end ();
-   p = input_line_pointer;
-   *p = c;
- 
-   if (name == p)
-     {
-       as_bad (_("expected symbol name"));
-       discard_rest_of_line ();
-       return;
-     }
- 
-   SKIP_WHITESPACE ();
- 
-   /* Accept an optional comma after the name.  The comma used to be
-      required, but Irix 5 cc does not generate it.  */
-   if (*input_line_pointer == ',')
-     {
-       ++input_line_pointer;
-       SKIP_WHITESPACE ();
-     }
- 
-   if (is_end_of_line[(unsigned char) *input_line_pointer])
-     {
-       as_bad (_("missing size expression"));
-       return;
-     }
- 
-   if ((temp = get_absolute_expression ()) < 0)
-     {
-       as_warn (_("BSS length (%d) < 0 ignored"), temp);
-       ignore_rest_of_line ();
-       return;
-     }
- 
  #if defined (TC_MIPS) || defined (TC_ALPHA)
    if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
        || OUTPUT_FLAVOR == bfd_target_elf_flavour)
      {
        /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
!       if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
  	{
  	  bss_seg = subseg_new (".sbss", 1);
  	  seg_info (bss_seg)->bss = 1;
--- 1914,1933 ----
    demand_empty_rest_of_line ();
  }
  
! void
! bss_alloc (symbolS *symbolP, addressT size, int align)
  {
!   char *pfrag;
    segT current_seg = now_seg;
    subsegT current_subseg = now_subseg;
    segT bss_seg = bss_section;
  
  #if defined (TC_MIPS) || defined (TC_ALPHA)
    if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
        || OUTPUT_FLAVOR == bfd_target_elf_flavour)
      {
        /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
!       if (size <= bfd_get_gp_size (stdoutput))
  	{
  	  bss_seg = subseg_new (".sbss", 1);
  	  seg_info (bss_seg)->bss = 1;
*************** s_lcomm_internal (/* 1 if this was a ".b
*** 1989,2135 ****
  	}
      }
  #endif
  
!   if (!needs_align)
      {
!       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
! 
!       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
!       if (align)
! 	record_alignment (bss_seg, align);
      }
  
!   if (needs_align)
!     {
!       align = 0;
!       SKIP_WHITESPACE ();
  
!       if (*input_line_pointer != ',')
! 	{
! 	  as_bad (_("expected comma after size"));
! 	  ignore_rest_of_line ();
! 	  return;
! 	}
  
!       input_line_pointer++;
!       SKIP_WHITESPACE ();
  
!       if (is_end_of_line[(unsigned char) *input_line_pointer])
! 	{
! 	  as_bad (_("missing alignment"));
! 	  return;
! 	}
  
!       align = get_absolute_expression ();
  
!       if (bytes_p)
! 	{
! 	  /* Convert to a power of 2.  */
! 	  if (align != 0)
! 	    {
! 	      unsigned int i;
  
! 	      for (i = 0; (align & 1) == 0; align >>= 1, ++i)
! 		;
! 	      if (align != 1)
! 		as_bad (_("alignment not a power of 2"));
! 	      align = i;
! 	    }
! 	}
  
!       if (align > max_alignment)
! 	{
! 	  align = max_alignment;
! 	  as_warn (_("alignment too large; %d assumed"), align);
! 	}
!       else if (align < 0)
! 	{
! 	  align = 0;
! 	  as_warn (_("alignment negative; 0 assumed"));
! 	}
  
!       record_alignment (bss_seg, align);
      }
!   else
      {
!       /* Assume some objects may require alignment on some systems.  */
! #if defined (TC_ALPHA) && ! defined (VMS)
!       if (temp > 1)
  	{
! 	  align = ffs (temp) - 1;
! 	  if (temp % (1 << align))
! 	    abort ();
  	}
! #endif
      }
  
!   *p = 0;
!   symbolP = symbol_find_or_make (name);
!   *p = c;
! 
!   if (
! #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
!      || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
! #ifdef BFD_ASSEMBLER
!       (OUTPUT_FLAVOR != bfd_target_aout_flavour
!        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
! #else
!       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
! #endif
! #endif
!       (S_GET_SEGMENT (symbolP) == bss_seg
!        || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
!     {
!       char *pfrag;
! 
!       subseg_set (bss_seg, 1);
! 
!       if (align)
! 	frag_align (align, 0, 0);
! 
!       /* Detach from old frag.  */
!       if (S_GET_SEGMENT (symbolP) == bss_seg)
! 	symbol_get_frag (symbolP)->fr_symbol = NULL;
! 
!       symbol_set_frag (symbolP, frag_now);
!       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
! 			(offsetT) temp, (char *) 0);
!       *pfrag = 0;
! 
!       S_SET_SEGMENT (symbolP, bss_seg);
  
! #ifdef OBJ_COFF
!       /* The symbol may already have been created with a preceding
! 	 ".globl" directive -- be careful not to step on storage class
! 	 in that case.  Otherwise, set it to static.  */
!       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
! 	{
! 	  S_SET_STORAGE_CLASS (symbolP, C_STAT);
! 	}
! #endif /* OBJ_COFF */
  
! #ifdef S_SET_SIZE
!       S_SET_SIZE (symbolP, temp);
! #endif
      }
    else
!     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
! 
!   subseg_set (current_seg, current_subseg);
  
!   demand_empty_rest_of_line ();
  }
  
  void
  s_lcomm (int needs_align)
  {
!   s_lcomm_internal (needs_align, 0);
  }
  
  void
  s_lcomm_bytes (int needs_align)
  {
!   s_lcomm_internal (needs_align, 1);
  }
  
  void
--- 1939,2056 ----
  	}
      }
  #endif
+   subseg_set (bss_seg, 1);
  
!   if (align)
      {
!       record_alignment (bss_seg, align);
!       frag_align (align, 0, 0);
      }
  
!   /* Detach from old frag.  */
!   if (S_GET_SEGMENT (symbolP) == bss_seg)
!     symbol_get_frag (symbolP)->fr_symbol = NULL;
  
!   symbol_set_frag (symbolP, frag_now);
!   pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
!   *pfrag = 0;
  
! #ifdef S_SET_SIZE
!   S_SET_SIZE (symbolP, size);
! #endif
!   S_SET_SEGMENT (symbolP, bss_seg);
  
! #ifdef OBJ_COFF
!   /* The symbol may already have been created with a preceding
!      ".globl" directive -- be careful not to step on storage class
!      in that case.  Otherwise, set it to static.  */
!   if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
!     S_SET_STORAGE_CLASS (symbolP, C_STAT);
! #endif /* OBJ_COFF */
  
!   subseg_set (current_seg, current_subseg);
! }
  
! offsetT
! parse_align (int align_bytes)
! {
!   expressionS exp;
!   addressT align;
  
!   SKIP_WHITESPACE ();
!   if (*input_line_pointer != ',')
!     {
!     no_align:
!       as_bad (_("expected alignment after size"));
!       ignore_rest_of_line ();
!       return -1;
!     }
  
!   input_line_pointer++;
!   SKIP_WHITESPACE ();
  
!   align = get_absolute_expr (&exp);
!   if (exp.X_op == O_absent)
!     goto no_align;
! 
!   if (!exp.X_unsigned)
!     {
!       as_warn (_("alignment negative; 0 assumed"));
!       align = 0;
      }
! 
!   if (align_bytes && align != 0)
      {
!       /* convert to a power of 2 alignment */
!       unsigned int alignp2 = 0;
!       while ((align & 1) == 0)
! 	align >>= 1, ++alignp2;
!       if (align != 1)
  	{
! 	  as_bad (_("alignment not a power of 2"));
! 	  ignore_rest_of_line ();
! 	  return -1;
  	}
!       align = alignp2;
      }
+   return align;
+ }
  
! /* Called from s_comm_internal after symbol name and size have been
!    parsed.  NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only),
!    1 if this was a ".bss" directive which has a 3rd argument
!    (alignment as a power of 2), or 2 if this was a ".bss" directive
!    with alignment in bytes.  */
  
! static symbolS *
! s_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
! {
!   addressT align = 0;
  
!   if (needs_align)
!     {
!       align = parse_align (needs_align - 1);
!       if (align == (addressT) -1)
! 	return NULL;
      }
    else
!     /* Assume some objects may require alignment on some systems.  */
!     TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
  
!   bss_alloc (symbolP, size, align);
!   return symbolP;
  }
  
  void
  s_lcomm (int needs_align)
  {
!   s_comm_internal (needs_align, s_lcomm_internal);
  }
  
  void
  s_lcomm_bytes (int needs_align)
  {
!   s_comm_internal (needs_align * 2, s_lcomm_internal);
  }
  
  void
Index: gas/read.h
===================================================================
RCS file: /cvs/src/src/gas/read.h,v
retrieving revision 1.19
diff -c -p -r1.19 read.h
*** gas/read.h	27 Nov 2003 19:14:41 -0000	1.19
--- gas/read.h	13 Dec 2003 02:53:13 -0000
*************** extern void generate_lineno_debug (void)
*** 139,144 ****
--- 139,147 ----
  extern void s_abort (int) ATTRIBUTE_NORETURN;
  extern void s_align_bytes (int arg);
  extern void s_align_ptwo (int);
+ extern void bss_alloc (symbolS *, addressT, int);
+ extern offsetT parse_align (int);
+ extern symbolS *s_comm_internal (int, symbolS *(*) (int, symbolS *, addressT));
  extern void s_app_file_string (char *);
  extern void s_app_file (int);
  extern void s_app_line (int);
Index: gas/config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.76
diff -c -p -r1.76 obj-elf.c
*** gas/config/obj-elf.c	3 Dec 2003 03:20:13 -0000	1.76
--- gas/config/obj-elf.c	13 Dec 2003 02:53:14 -0000
*************** static void adjust_stab_sections PARAMS 
*** 63,69 ****
  static void build_group_lists PARAMS ((bfd *, asection *, PTR));
  static int elf_separate_stab_sections PARAMS ((void));
  static void elf_init_stab_section PARAMS ((segT));
- static symbolS *elf_common PARAMS ((int));
  
  #ifdef NEED_ECOFF_DEBUG
  static bfd_boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
--- 63,68 ----
*************** elf_file_symbol (s)
*** 287,471 ****
  #endif
  }
  
  static symbolS *
! elf_common (is_common)
!      int is_common;
  {
!   char *name;
!   char c;
!   char *p;
!   offsetT temp, size, sign;
!   symbolS *symbolP;
!   int have_align;
!   expressionS exp;
  
!   if (flag_mri && is_common)
      {
!       s_mri_common (0);
!       return NULL;
!     }
  
-   name = input_line_pointer;
-   c = get_symbol_end ();
-   /* just after name is now '\0' */
-   p = input_line_pointer;
-   *p = c;
-   SKIP_WHITESPACE ();
-   if (*input_line_pointer != ',')
-     {
-       as_bad (_("expected comma after symbol-name"));
-       ignore_rest_of_line ();
-       return NULL;
-     }
-   input_line_pointer++;		/* skip ',' */
-   temp = get_absolute_expr (&exp);
-   sign = (offsetT) 1 << (stdoutput->arch_info->bits_per_address - 1);
-   size = temp & ((sign << 1) - 1);
-   if (temp != size || !exp.X_unsigned)
-     {
-       as_bad (_(".COMMon length (%ld) out of range, ignored."), (long) temp);
-       ignore_rest_of_line ();
-       return NULL;
-     }
-   *p = 0;
-   symbolP = symbol_find_or_make (name);
-   *p = c;
-   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
-     {
-       as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
-       ignore_rest_of_line ();
-       return NULL;
-     }
-   if (S_GET_VALUE (symbolP) != 0)
-     {
-       if (S_GET_VALUE (symbolP) != (valueT) size)
- 	{
- 	  as_warn (_("length of .comm \"%s\" is already %ld; not changed to %ld"),
- 		   S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP),
- 		   (long) size);
- 	}
-     }
-   know (symbolP->sy_frag == &zero_address_frag);
-   if (*input_line_pointer != ',')
-     have_align = 0;
-   else
-     {
-       have_align = 1;
        input_line_pointer++;
        SKIP_WHITESPACE ();
!     }
!   if (! have_align || *input_line_pointer != '"')
!     {
!       if (! have_align)
! 	temp = 0;
!       else
! 	{
! 	  temp = get_absolute_expr (&exp);
! 	  if (!exp.X_unsigned)
! 	    {
! 	      temp = 0;
! 	      as_warn (_("common alignment negative; 0 assumed"));
! 	    }
! 	}
!       if (symbol_get_obj (symbolP)->local)
  	{
! 	  segT old_sec;
! 	  int old_subsec;
! 	  char *pfrag;
! 	  int align;
! 
! 	/* allocate_bss: */
! 	  old_sec = now_seg;
! 	  old_subsec = now_subseg;
! 	  if (temp)
  	    {
! 	      /* convert to a power of 2 alignment */
! 	      for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
! 	      if (temp != 1)
! 		{
! 		  as_bad (_("common alignment not a power of 2"));
! 		  ignore_rest_of_line ();
! 		  return NULL;
! 		}
  	    }
! 	  else
! 	    align = 0;
! 	  record_alignment (bss_section, align);
! 	  subseg_set (bss_section, 0);
! 	  if (align)
! 	    frag_align (align, 0, 0);
! 	  if (S_GET_SEGMENT (symbolP) == bss_section)
! 	    symbol_get_frag (symbolP)->fr_symbol = 0;
! 	  symbol_set_frag (symbolP, frag_now);
! 	  pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
! 			    (offsetT) size, (char *) 0);
! 	  *pfrag = 0;
! 	  S_SET_SIZE (symbolP, size);
! 	  S_SET_SEGMENT (symbolP, bss_section);
! 	  S_CLEAR_EXTERNAL (symbolP);
! 	  subseg_set (old_sec, old_subsec);
  	}
        else
  	{
! 	allocate_common:
! 	  S_SET_VALUE (symbolP, (valueT) size);
! 	  S_SET_ALIGN (symbolP, temp);
! 	  S_SET_EXTERNAL (symbolP);
! 	  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
  	}
      }
    else
      {
!       input_line_pointer++;
!       /* @@ Some use the dot, some don't.  Can we get some consistency??  */
!       if (*input_line_pointer == '.')
! 	input_line_pointer++;
!       /* @@ Some say data, some say bss.  */
!       if (strncmp (input_line_pointer, "bss\"", 4)
! 	  && strncmp (input_line_pointer, "data\"", 5))
! 	{
! 	  while (*--input_line_pointer != '"')
! 	    ;
! 	  input_line_pointer--;
! 	  goto bad_common_segment;
! 	}
!       while (*input_line_pointer++ != '"')
! 	;
!       goto allocate_common;
      }
  
    symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
  
-   demand_empty_rest_of_line ();
    return symbolP;
- 
-   {
-   bad_common_segment:
-     p = input_line_pointer;
-     while (*p && *p != '\n')
-       p++;
-     c = *p;
-     *p = '\0';
-     as_bad (_("bad .common segment %s"), input_line_pointer + 1);
-     *p = c;
-     input_line_pointer = p;
-     ignore_rest_of_line ();
-     return NULL;
-   }
  }
  
  void
  obj_elf_common (is_common)
       int is_common;
  {
!   elf_common (is_common);
  }
  
  static void
  obj_elf_tls_common (ignore)
       int ignore ATTRIBUTE_UNUSED;
  {
!   symbolS *symbolP = elf_common (0);
  
    if (symbolP)
      symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
--- 286,381 ----
  #endif
  }
  
+ /* Called from read.c:s_comm after we've parsed .comm symbol, size.
+    Parse a possible alignment value.  */
+ 
  static symbolS *
! elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
  {
!   addressT align = 0;
!   int is_local = symbol_get_obj (symbolP)->local;
  
!   if (*input_line_pointer == ',')
      {
!       char *save = input_line_pointer;
  
        input_line_pointer++;
        SKIP_WHITESPACE ();
! 
!       if (*input_line_pointer == '"')
  	{
! 	  /* For sparc.  Accept .common symbol, length, "bss"  */
! 	  input_line_pointer++;
! 	  /* Some use the dot, some don't.  */
! 	  if (*input_line_pointer == '.')
! 	    input_line_pointer++;
! 	  /* Some say data, some say bss.  */
! 	  if (strncmp (input_line_pointer, "bss\"", 4) == 0)
! 	    input_line_pointer += 4;
! 	  else if (strncmp (input_line_pointer, "data\"", 5) == 0)
! 	    input_line_pointer += 5;
! 	  else
  	    {
! 	      char *p = input_line_pointer;
! 	      char c;
! 
! 	      while (*--p != '"')
! 		;
! 	      while (!is_end_of_line[(unsigned char) *input_line_pointer])
! 		if (*input_line_pointer++ == '"')
! 		  break;
! 	      c = *input_line_pointer;
! 	      *input_line_pointer = '\0';
! 	      as_bad (_("bad .common segment %s"), p);
! 	      *input_line_pointer = c;
! 	      ignore_rest_of_line ();
! 	      return NULL;
  	    }
! 	  /* ??? Don't ask me why these are always global.  */
! 	  is_local = 0;
  	}
        else
  	{
! 	  input_line_pointer = save;
! 	  align = parse_align (is_local);
! 	  if (align == (addressT) -1)
! 	    return NULL;
  	}
      }
+ 
+   if (is_local)
+     {
+       bss_alloc (symbolP, size, align);
+       S_CLEAR_EXTERNAL (symbolP);
+     }
    else
      {
!       S_SET_VALUE (symbolP, size);
!       S_SET_ALIGN (symbolP, align);
!       S_SET_EXTERNAL (symbolP);
!       S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
      }
  
    symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
  
    return symbolP;
  }
  
  void
  obj_elf_common (is_common)
       int is_common;
  {
!   if (flag_mri && is_common)
!     s_mri_common (0);
!   else
!     s_comm_internal (0, elf_common_parse);
  }
  
  static void
  obj_elf_tls_common (ignore)
       int ignore ATTRIBUTE_UNUSED;
  {
!   symbolS *symbolP = s_comm_internal (0, elf_common_parse);
  
    if (symbolP)
      symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
Index: gas/config/tc-alpha.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.h,v
retrieving revision 1.20
diff -c -p -r1.20 tc-alpha.h
*** gas/config/tc-alpha.h	21 Nov 2003 00:24:40 -0000	1.20
--- gas/config/tc-alpha.h	13 Dec 2003 02:53:18 -0000
*************** extern valueT alpha_gp_value;
*** 80,85 ****
--- 80,100 ----
  	: BFD_RELOC_ALPHA_LINKAGE);
  #endif
  
+ #ifndef VMS
+ #define TC_IMPLICIT_LCOMM_ALIGNMENT(size, align) \
+   do							\
+     {							\
+       align = 0;					\
+       if (size > 1)					\
+ 	{						\
+ 	  addressT temp = 1;				\
+ 	  while ((size & temp) == 0)			\
+ 	    ++align, temp <<= 1;			\
+ 	}						\
+     }							\
+   while (0)
+ #endif
+ 
  #define md_number_to_chars		number_to_chars_littleendian
  
  extern int tc_get_register PARAMS ((int frame));

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Binutils mailing list