OSDN Git Service

* read.c: Remove unneeded prototypes.
authorAlan Modra <amodra@bigpond.net.au>
Sat, 13 Dec 2003 08:23:05 +0000 (08:23 +0000)
committerAlan Modra <amodra@bigpond.net.au>
Sat, 13 Dec 2003 08:23:05 +0000 (08:23 +0000)
(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.

gas/ChangeLog
gas/config/obj-elf.c
gas/config/tc-alpha.h
gas/read.c
gas/read.h

index 677e0d0..b4c156a 100644 (file)
@@ -1,3 +1,22 @@
+2003-12-13  Alan Modra  <amodra@bigpond.net.au>
+
+       * 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.
+
 2003-12-10  Zack Weinberg  <zack@codesourcery.com>
 
        * tc-ppc.c (md_assemble): Rewrite comment about optional operands
index 697dd4f..dd33ec4 100644 (file)
@@ -63,7 +63,6 @@ static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
 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 *));
@@ -287,185 +286,96 @@ elf_file_symbol (s)
 #endif
 }
 
+/* Called from read.c:s_comm after we've parsed .comm symbol, size.
+   Parse a possible alignment value.  */
+
 static symbolS *
-elf_common (is_common)
-     int is_common;
+elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
 {
-  char *name;
-  char c;
-  char *p;
-  offsetT temp, size, sign;
-  symbolS *symbolP;
-  int have_align;
-  expressionS exp;
+  addressT align = 0;
+  int is_local = symbol_get_obj (symbolP)->local;
 
-  if (flag_mri && is_common)
+  if (*input_line_pointer == ',')
     {
-      s_mri_common (0);
-      return NULL;
-    }
+      char *save = input_line_pointer;
 
-  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)
+
+      if (*input_line_pointer == '"')
        {
-         segT old_sec;
-         int old_subsec;
-         char *pfrag;
-         int align;
-
-       /* allocate_bss: */
-         old_sec = now_seg;
-         old_subsec = now_subseg;
-         if (temp)
+         /* 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
            {
-             /* 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;
-               }
+             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;
            }
-         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);
+         /* ??? Don't ask me why these are always global.  */
+         is_local = 0;
        }
       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);
+         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
     {
-      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;
+      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;
 
-  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);
+  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 = elf_common (0);
+  symbolS *symbolP = s_comm_internal (0, elf_common_parse);
 
   if (symbolP)
     symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
index 5287686..939a14f 100644 (file)
@@ -80,6 +80,21 @@ extern valueT alpha_gp_value;
        : 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));
index 186d28b..55a68be 100644 (file)
@@ -214,22 +214,9 @@ static int dwarf_file_string;
 #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 *);
@@ -1328,16 +1315,18 @@ s_align_ptwo (int arg)
   s_align (arg, 0);
 }
 
-void
-s_comm (int ignore ATTRIBUTE_UNUSED)
+symbolS *
+s_comm_internal (int param,
+                symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
 {
-  register char *name;
-  register char c;
-  register char *p;
-  offsetT temp;
-  register symbolS *symbolP;
+  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);
@@ -1352,75 +1341,83 @@ s_comm (int ignore ATTRIBUTE_UNUSED)
     {
       as_bad (_("expected symbol name"));
       discard_rest_of_line ();
-      return;
+      goto out;
     }
 
   SKIP_WHITESPACE ();
 
-  if (*input_line_pointer != ',')
+  /* 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)
     {
-      *p = 0;
-      as_bad (_("expected comma after \"%s\""), name);
+      as_bad (_("missing size expression"));
       *p = c;
       ignore_rest_of_line ();
-      if (flag_mri)
-       mri_comment_end (stop, stopc);
-      return;
+      goto out;
     }
-
-  input_line_pointer++;                /* skip ',' */
-
-  if ((temp = get_absolute_expression ()) < 0)
+  else if (temp != size || !exp.X_unsigned)
     {
-      as_warn (_(".COMMon length (%lu) out of range ignored"),
-              (unsigned long) temp);
+      as_warn (_("size (%ld) out of range, ignored"), (long) temp);
+      *p = c;
       ignore_rest_of_line ();
-      if (flag_mri)
-       mri_comment_end (stop, stopc);
-      return;
+      goto out;
     }
 
-  *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));
+      symbolP = NULL;
+      as_bad (_("symbol `%s' is already defined"), name);
+      *p = c;
       ignore_rest_of_line ();
-      if (flag_mri)
-       mri_comment_end (stop, stopc);
-      return;
+      goto out;
     }
 
-  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);
-    }
+  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) temp);
+      S_SET_VALUE (symbolP, (valueT) size);
       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);
+      {
+       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);
-}                              /* s_comm() */
+  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
@@ -1917,67 +1914,20 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
   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)
+void
+bss_alloc (symbolS *symbolP, addressT size, int align)
 {
-  register char *name;
-  register char c;
-  register char *p;
-  register int temp;
-  register symbolS *symbolP;
+  char *pfrag;
   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))
+      if (size <= bfd_get_gp_size (stdoutput))
        {
          bss_seg = subseg_new (".sbss", 1);
          seg_info (bss_seg)->bss = 1;
@@ -1989,147 +1939,118 @@ s_lcomm_internal (/* 1 if this was a ".bss" directive, which may
        }
     }
 #endif
+  subseg_set (bss_seg, 1);
 
-  if (!needs_align)
+  if (align)
     {
-      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
-
-      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
-      if (align)
-       record_alignment (bss_seg, align);
+      record_alignment (bss_seg, align);
+      frag_align (align, 0, 0);
     }
 
-  if (needs_align)
-    {
-      align = 0;
-      SKIP_WHITESPACE ();
+  /* Detach from old frag.  */
+  if (S_GET_SEGMENT (symbolP) == bss_seg)
+    symbol_get_frag (symbolP)->fr_symbol = NULL;
 
-      if (*input_line_pointer != ',')
-       {
-         as_bad (_("expected comma after size"));
-         ignore_rest_of_line ();
-         return;
-       }
+  symbol_set_frag (symbolP, frag_now);
+  pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
+  *pfrag = 0;
 
-      input_line_pointer++;
-      SKIP_WHITESPACE ();
+#ifdef S_SET_SIZE
+  S_SET_SIZE (symbolP, size);
+#endif
+  S_SET_SEGMENT (symbolP, bss_seg);
 
-      if (is_end_of_line[(unsigned char) *input_line_pointer])
-       {
-         as_bad (_("missing alignment"));
-         return;
-       }
+#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 */
 
-      align = get_absolute_expression ();
+  subseg_set (current_seg, current_subseg);
+}
 
-      if (bytes_p)
-       {
-         /* Convert to a power of 2.  */
-         if (align != 0)
-           {
-             unsigned int i;
+offsetT
+parse_align (int align_bytes)
+{
+  expressionS exp;
+  addressT align;
 
-             for (i = 0; (align & 1) == 0; align >>= 1, ++i)
-               ;
-             if (align != 1)
-               as_bad (_("alignment not a power of 2"));
-             align = i;
-           }
-       }
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer != ',')
+    {
+    no_align:
+      as_bad (_("expected alignment after size"));
+      ignore_rest_of_line ();
+      return -1;
+    }
 
-      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"));
-       }
+  input_line_pointer++;
+  SKIP_WHITESPACE ();
 
-      record_alignment (bss_seg, align);
+  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;
     }
-  else
+
+  if (align_bytes && align != 0)
     {
-      /* Assume some objects may require alignment on some systems.  */
-#if defined (TC_ALPHA) && ! defined (VMS)
-      if (temp > 1)
+      /* convert to a power of 2 alignment */
+      unsigned int alignp2 = 0;
+      while ((align & 1) == 0)
+       align >>= 1, ++alignp2;
+      if (align != 1)
        {
-         align = ffs (temp) - 1;
-         if (temp % (1 << align))
-           abort ();
+         as_bad (_("alignment not a power of 2"));
+         ignore_rest_of_line ();
+         return -1;
        }
-#endif
+      align = alignp2;
     }
+  return align;
+}
 
-  *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);
+/* 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.  */
 
-#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 */
+static symbolS *
+s_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
+{
+  addressT align = 0;
 
-#ifdef S_SET_SIZE
-      S_SET_SIZE (symbolP, temp);
-#endif
+  if (needs_align)
+    {
+      align = parse_align (needs_align - 1);
+      if (align == (addressT) -1)
+       return NULL;
     }
   else
-    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
+    /* Assume some objects may require alignment on some systems.  */
+    TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
 
-  subseg_set (current_seg, current_subseg);
-
-  demand_empty_rest_of_line ();
+  bss_alloc (symbolP, size, align);
+  return symbolP;
 }
 
 void
 s_lcomm (int needs_align)
 {
-  s_lcomm_internal (needs_align, 0);
+  s_comm_internal (needs_align, s_lcomm_internal);
 }
 
 void
 s_lcomm_bytes (int needs_align)
 {
-  s_lcomm_internal (needs_align, 1);
+  s_comm_internal (needs_align * 2, s_lcomm_internal);
 }
 
 void
index 9c09599..614d570 100644 (file)
@@ -139,6 +139,9 @@ extern void generate_lineno_debug (void);
 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);