/* read.c - read a source file -
- Copyright (C) 1986, 1987, 1990, 1991, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
char *input_line_pointer; /*->next char of source file to parse. */
+int generate_asm_line_stab = 0; /* flag to generate line stab for .s file */
+
#if BITS_PER_CHAR != 8
/* The following table is indexed by[(char)] and will break if
a char does not have exactly 256 states (hopefully 0:255!)! */
#define LEX_AT 0
#endif
+#ifndef LEX_BR
+/* The RS/6000 assembler uses {,},[,] as parts of symbol names. */
+#define LEX_BR 0
+#endif
+
+#ifndef LEX_PCT
+/* The Delta 68k assembler permits % inside label names. */
+#define LEX_PCT 0
+#endif
+
/* used by is_... macros. our ctype[] */
const char lex_type[256] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
- 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+ 0, 0, 0, 0, 3, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 0, /* pqrstuvwxyz{|}~. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
int new_broken_words;
#endif
-static char *demand_copy_string PARAMS ((int *lenP));
+char *demand_copy_string PARAMS ((int *lenP));
int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
static segT get_known_segmented_expression PARAMS ((expressionS * expP));
{"string", stringer, 1},
/* tag */
{"text", s_text, 0},
+
+ /* This is for gcc to use. It's only just been added (2/94), so gcc
+ won't be able to use it for a while -- probably a year or more.
+ But once this has been released, check with gcc maintainers
+ before deleting it or even changing the spelling. */
+ {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
+ /* If we're folding case -- done for some targets, not necessarily
+ all -- the above string in an input file will be converted to
+ this one. Match it either way... */
+ {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
+
{"title", listing_title, 0}, /* Listing title */
/* type */
/* use */
/* val */
{"xstabs", s_xstab, 's'},
{"word", cons, 2},
+ {"zero", s_space, 0},
{NULL} /* end sentinel */
};
* Input_line_pointer points after that character.
*/
if (is_name_beginner (c))
- { /* want user-defined label or pseudo/opcode */
+ {
+ /* want user-defined label or pseudo/opcode */
HANDLE_CONDITIONAL_ASSEMBLY ();
s = --input_line_pointer;
c = *input_line_pointer;
*input_line_pointer = '\0';
+#ifdef OBJ_GENERATE_ASM_LINE_STAB
+ if (generate_asm_line_stab)
+ {
+ int lineno;
+ char *s;
+ as_where (&s, &lineno);
+ OBJ_GENERATE_ASM_LINE_STAB (lineno);
+ }
+#endif
+
md_assemble (s); /* Assemble 1 instruction. */
*input_line_pointer++ = c;
num = buffer_limit - buffer;
tmp_buf = xrealloc (tmp_buf, tmp_len + num);
- memcpy (tmp_buf, buffer + tmp_len, num);
+ memcpy (tmp_buf + tmp_len, buffer, num);
tmp_len += num;
}
while (!ends);
} /* while (more buffers to scan) */
input_scrub_close (); /* Close the input file */
-} /* read_a_source_file() */
+}
void
s_abort (ignore)
int ignore;
{
as_fatal (".abort detected. Abandoning ship.");
-} /* s_abort() */
+}
+
+/* Guts of .align directive. */
+static void
+do_align (n, fill)
+ int n;
+ char *fill;
+{
+#ifdef md_do_align
+ md_do_align (n, fill, just_record_alignment);
+#endif
+ if (!fill)
+ {
+ /* @@ Fix this right for BFD! */
+ static char zero;
+ static char nop_opcode = NOP_OPCODE;
+
+ if (now_seg != data_section && now_seg != bss_section)
+ {
+ fill = &nop_opcode;
+ }
+ else
+ {
+ fill = &zero;
+ }
+ }
+ /* Only make a frag if we HAVE to. . . */
+ if (n && !need_pass_2)
+ frag_align (n, *fill);
+
+#ifdef md_do_align
+ just_record_alignment:
+#endif
+
+ record_alignment (now_seg, n);
+}
/* For machines where ".align 4" means align to a 4 byte boundary. */
void
int arg;
{
register unsigned int temp;
- register long temp_fill;
+ char temp_fill;
unsigned int i = 0;
unsigned long max_alignment = 1 << 15;
as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
}
- /*
- * For the sparc, `.align (1<<n)' actually means `.align n'
- * so we have to convert it.
- */
+ /* For the sparc, `.align (1<<n)' actually means `.align n' so we
+ have to convert it. */
if (temp != 0)
{
for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
{
input_line_pointer++;
temp_fill = get_absolute_expression ();
+ do_align (temp, &temp_fill);
}
- else if (now_seg != data_section && now_seg != bss_section)
- temp_fill = NOP_OPCODE;
else
- temp_fill = 0;
- /* Only make a frag if we HAVE to. . . */
- if (temp && !need_pass_2)
- frag_align ((int) temp, (int) temp_fill);
-
- record_alignment (now_seg, (int) temp);
+ do_align (temp, (char *) 0);
demand_empty_rest_of_line ();
-} /* s_align_bytes() */
+}
/* For machines where ".align 4" means align to 2**4 boundary. */
void
int ignore;
{
register int temp;
- register long temp_fill;
+ char temp_fill;
long max_alignment = 15;
temp = get_absolute_expression ();
{
input_line_pointer++;
temp_fill = get_absolute_expression ();
+ do_align (temp, &temp_fill);
}
- /* @@ Fix this right for BFD! */
- else if (now_seg != data_section && now_seg != bss_section)
- temp_fill = NOP_OPCODE;
else
- temp_fill = 0;
- /* Only make a frag if we HAVE to. . . */
- if (temp && !need_pass_2)
- frag_align (temp, (int) temp_fill);
-
- record_alignment (now_seg, temp);
+ do_align (temp, (char *) 0);
demand_empty_rest_of_line ();
-} /* s_align_ptwo() */
+}
void
s_comm (ignore)
*p = c;
if (S_IS_DEFINED (symbolP))
{
- as_bad ("Ignoring attempt to re-define symbol");
+ as_bad ("Ignoring attempt to re-define symbol `%s'.",
+ S_GET_NAME (symbolP));
ignore_rest_of_line ();
return;
}
S_SET_EXTERNAL (symbolP);
}
#ifdef OBJ_VMS
- if ( (!temp) || !flagseen['1'])
- S_GET_OTHER(symbolP) = const_flag;
+ {
+ 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 ();
register int temp;
temp = get_absolute_expression ();
- if (flagseen['R'])
+ if (flag_readonly_data_in_text)
{
section = text_section;
temp += 1000;
}
#endif
#endif
+ if (!needs_align)
+ {
+ /* FIXME. This needs to be machine independent. */
+ if (temp >= 8)
+ align = 3;
+ else if (temp >= 4)
+ align = 2;
+ else if (temp >= 2)
+ align = 1;
+ else
+ align = temp;
+
+ record_alignment(bss_seg, align);
+ }
if (needs_align)
{
}
record_alignment (bss_seg, align);
} /* if needs align */
+ else
+ {
+ /* Assume some objects may require alignment on some systems. */
+#ifdef TC_ALPHA
+ if (temp > 1)
+ {
+ align = ffs (temp) - 1;
+ if (temp % (1 << align))
+ abort ();
+ }
+#endif
+ }
*p = 0;
symbolP = symbol_find_or_make (name);
#endif /* OBJ_COFF */
}
else
- {
- as_bad ("Ignoring attempt to re-define symbol %s.", name);
- }
+ as_bad ("Ignoring attempt to re-define symbol `%s'.",
+ S_GET_NAME (symbolP));
subseg_set (current_seg, current_subseg);
symbolS *symbolP;
{
expressionS exp;
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
int ext;
#endif /* OBJ_AOUT or OBJ_BOUT */
know (symbolP); /* NULL pointer is logic error. */
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD. */
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
ext = S_IS_EXTERNAL (symbolP);
#endif /* OBJ_AOUT or OBJ_BOUT */
/* Fall through. */
case O_constant:
S_SET_SEGMENT (symbolP, absolute_section);
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD. */
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
if (ext)
S_SET_EXTERNAL (symbolP);
else
else
{
S_SET_SEGMENT (symbolP, S_GET_SEGMENT (exp.X_add_symbol));
-#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
- /* @@ Fix this right for BFD! */
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
if (ext)
S_SET_EXTERNAL (symbolP);
else
}
else
{
- md_number_to_chars (p, (valueT) 0, (int) nbytes);
+ memset (p, 0, nbytes);
/* Now we need to generate a fixS to record the symbol value.
This is easy for BFD. For other targets it can be more
c = NOT_A_CHAR;
break;
+#ifndef NO_STRING_ESCAPES
case '\\':
switch (c = *input_line_pointer++)
{
break;
} /* switch on escaped char */
break;
+#endif /* ! defined (NO_STRING_ESCAPES) */
default:
break;
* Demand string, but return a safe (=private) copy of the string.
* Return NULL if we can't read a string here.
*/
-static char *
+char *
demand_copy_string (lenP)
int *lenP;
{