/* read.c - read a source file -
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
-This file is part of GAS, the GNU Assembler.
+ This file is part of GAS, the GNU Assembler.
-GAS is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
-GAS is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GAS; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
-02110-1301, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF).
But then, GNU isn't spozed to run on your machine anyway.
#include "sb.h"
#include "macro.h"
#include "obstack.h"
-#include "listing.h"
#include "ecoff.h"
#include "dw2gencfi.h"
static void s_align (int, int);
static void s_altmacro (int);
static void s_bad_end (int);
+#ifdef OBJ_ELF
+static void s_gnu_attribute (int);
+#endif
+static void s_reloc (int);
static int hex_float (int, char *);
static segT get_known_segmented_expression (expressionS * expP);
static void pobegin (void);
{"abort", s_abort, 0},
{"align", s_align_ptwo, 0},
{"altmacro", s_altmacro, 1},
- {"ascii", stringer, 0},
- {"asciz", stringer, 1},
+ {"ascii", stringer, 8+0},
+ {"asciz", stringer, 8+1},
{"balign", s_align_bytes, 0},
{"balignw", s_align_bytes, -2},
{"balignl", s_align_bytes, -4},
/* extend */
{"extern", s_ignore, 0}, /* We treat all undef as ext. */
{"appfile", s_app_file, 1},
- {"appline", s_app_line, 0},
+ {"appline", s_app_line, 1},
{"fail", s_fail, 0},
{"file", s_app_file, 0},
{"fill", s_fill, 0},
{"func", s_func, 0},
{"global", s_globl, 0},
{"globl", s_globl, 0},
+#ifdef OBJ_ELF
+ {"gnu_attribute", s_gnu_attribute, 0},
+#endif
{"hword", cons, 2},
{"if", s_if, (int) O_ne},
{"ifb", s_ifb, 1},
{"irepc", s_irp, 1},
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0}, /* Listing flags. */
+ {"linefile", s_app_line, 0},
{"linkonce", s_linkonce, 0},
{"list", listing_list, 1}, /* Turn listing on. */
{"llen", listing_psize, 1},
{"psize", listing_psize, 0}, /* Set paper size. */
{"purgem", s_purgem, 0},
{"quad", cons, 8},
+ {"reloc", s_reloc, 0},
{"rep", s_rept, 0},
{"rept", s_rept, 0},
{"rva", s_rva, 4},
{"stabd", s_stab, 'd'},
{"stabn", s_stab, 'n'},
{"stabs", s_stab, 's'},
- {"string", stringer, 1},
+ {"string", stringer, 8+1},
+ {"string8", stringer, 8+1},
+ {"string16", stringer, 16+1},
+ {"string32", stringer, 32+1},
+ {"string64", stringer, 64+1},
{"struct", s_struct, 0},
/* tag */
{"text", s_text, 0},
{"xref", s_ignore, 0},
{"xstabs", s_xstab, 's'},
{"warning", s_errwarn, 0},
+ {"weakref", s_weakref, 0},
{"word", cons, 2},
{"zero", s_space, 0},
{NULL, NULL, 0} /* End sentinel. */
last_eol = NULL;
#endif
- know (buffer_limit[-1] == '\n'); /* Must have a sentinel. */
-
while (input_line_pointer < buffer_limit)
{
/* We have more of this buffer to parse. */
Depending on what compiler is used, the order of these tests
may vary to catch most common case 1st.
- Each test is independent of all other tests at the (top) level.
- PLEASE make a compiler that doesn't use this assembler.
- It is crufty to waste a compiler's time encoding things for this
- assembler, which then wastes more time decoding it.
- (And communicating via (linear) files is silly!
- If you must pass stuff, please pass a tree!) */
- if ((c = *input_line_pointer++) == '\t'
- || c == ' '
- || c == '\f'
- || c == 0)
+ Each test is independent of all other tests at the (top)
+ level. */
+ do
c = *input_line_pointer++;
-
- know (c != ' '); /* No further leading whitespace. */
+ while (c == '\t' || c == ' ' || c == '\f');
#ifndef NO_LISTING
/* If listing is on, and we are expanding a macro, then give
unsigned int new_length;
char *tmp_buf = 0;
- bump_line_counters ();
s = input_line_pointer;
if (strncmp (s, "APP\n", 4))
- continue; /* We ignore it */
+ {
+ /* We ignore it. */
+ ignore_rest_of_line ();
+ continue;
+ }
+ bump_line_counters ();
s += 4;
sb_new (&sbuf);
continue;
#endif
input_line_pointer--;
- /* Report unknown char as ignored. */
+ /* Report unknown char as error. */
demand_empty_rest_of_line ();
}
(in bytes). A negative ARG is the negative of the length of the
fill pattern. BYTES_P is non-zero if the alignment value should be
interpreted as the byte boundary, rather than the power of 2. */
-
-#define ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1)
+#ifndef TC_ALIGN_LIMIT
+#define TC_ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1)
+#endif
static void
s_align (int arg, int bytes_p)
{
- unsigned int align_limit = ALIGN_LIMIT;
+ unsigned int align_limit = TC_ALIGN_LIMIT;
unsigned int align;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
offsetT fill = 0;
int max;
int fill_p;
offsetT temp, size;
symbolS *symbolP = NULL;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
expressionS exp;
if (flag_mri)
*p = 0;
symbolP = symbol_find_or_make (name);
- if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
+ if ((S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
+ && !S_IS_COMMON (symbolP))
{
- symbolP = NULL;
- as_bad (_("symbol `%s' is already defined"), name);
- *p = c;
- ignore_rest_of_line ();
- goto out;
+ if (!S_IS_VOLATILE (symbolP))
+ {
+ symbolP = NULL;
+ as_bad (_("symbol `%s' is already defined"), name);
+ *p = c;
+ ignore_rest_of_line ();
+ goto out;
+ }
+ symbolP = symbol_clone (symbolP, 1);
+ S_SET_SEGMENT (symbolP, undefined_section);
+ S_SET_VALUE (symbolP, 0);
+ symbol_set_frag (symbolP, &zero_address_frag);
+ S_CLEAR_VOLATILE (symbolP);
}
size = S_GET_VALUE (symbolP);
{
S_SET_VALUE (symbolP, (valueT) size);
S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
#ifdef OBJ_VMS
{
extern int flag_one;
symbolS *sym;
offsetT align;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
if (!flag_mri)
{
}
S_SET_EXTERNAL (sym);
+ S_SET_SEGMENT (sym, bfd_com_section_ptr);
mri_common_symbol = sym;
#ifdef S_SET_ALIGN
/* Some assemblers tolerate immediately following '"'. */
if ((s = demand_copy_string (&length)) != 0)
{
- /* If this is a fake .appfile, a fake newline was inserted into
- the buffer. Passing -2 to new_logical_line tells it to
- account for it. */
int may_omit
- = (!new_logical_line (s, appfile ? -2 : -1) && appfile);
+ = (!new_logical_line_flags (s, -1, 1) && appfile);
/* In MRI mode, the preprocessor may have inserted an extraneous
backquote. */
}
}
+static int
+get_linefile_number (int *flag)
+{
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer < '0' || *input_line_pointer > '9')
+ return 0;
+
+ *flag = get_absolute_expression ();
+
+ return 1;
+}
+
/* Handle the .appline pseudo-op. This is automatically generated by
do_scrub_chars when a preprocessor # line comment is seen. This
default definition may be overridden by the object or CPU specific
pseudo-ops. */
void
-s_app_line (int ignore ATTRIBUTE_UNUSED)
+s_app_line (int appline)
{
+ char *file = NULL;
int l;
/* The given number is that of the next line. */
- l = get_absolute_expression () - 1;
+ if (appline)
+ l = get_absolute_expression ();
+ else if (!get_linefile_number (&l))
+ {
+ ignore_rest_of_line ();
+ return;
+ }
+
+ l--;
if (l < -1)
/* Some of the back ends can't deal with non-positive line numbers.
l + 1);
else
{
- new_logical_line ((char *) NULL, l);
+ int flags = 0;
+ int length = 0;
+
+ if (!appline)
+ {
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer == '"')
+ file = demand_copy_string (&length);
+
+ if (file)
+ {
+ int this_flag;
+
+ while (get_linefile_number (&this_flag))
+ switch (this_flag)
+ {
+ /* From GCC's cpp documentation:
+ 1: start of a new file.
+ 2: returning to a file after having included
+ another file.
+ 3: following text comes from a system header file.
+ 4: following text should be treated as extern "C".
+
+ 4 is nonsensical for the assembler; 3, we don't
+ care about, so we ignore it just in case a
+ system header file is included while
+ preprocessing assembly. So 1 and 2 are all we
+ care about, and they are mutually incompatible.
+ new_logical_line_flags() demands this. */
+ case 1:
+ case 2:
+ if (flags && flags != (1 << this_flag))
+ as_warn (_("incompatible flag %i in line directive"),
+ this_flag);
+ else
+ flags |= 1 << this_flag;
+ break;
+
+ case 3:
+ case 4:
+ /* We ignore these. */
+ break;
+
+ default:
+ as_warn (_("unsupported flag %i in line directive"),
+ this_flag);
+ break;
+ }
+
+ if (!is_end_of_line[(unsigned char)*input_line_pointer])
+ file = 0;
+ }
+ }
+
+ if (appline || file)
+ {
+ new_logical_line_flags (file, l, flags);
#ifdef LISTING
- if (listing)
- listing_source_line (l);
+ if (listing)
+ listing_source_line (l);
#endif
+ }
}
- demand_empty_rest_of_line ();
+ if (appline || file)
+ demand_empty_rest_of_line ();
+ else
+ ignore_rest_of_line ();
}
/* Handle the .end pseudo-op. Actually, the real work is done in
{
offsetT temp;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
if (flag_mri)
stop = mri_comment_field (&stopc);
int c;
symbolS *symbolP;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
if (flag_mri)
stop = mri_comment_field (&stopc);
mri_comment_end (stop, stopc);
}
+#ifdef OBJ_ELF
+#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0)
+
+static inline int
+skip_past_char (char ** str, char c)
+{
+ if (**str == c)
+ {
+ (*str)++;
+ return 0;
+ }
+ else
+ return -1;
+}
+#define skip_past_comma(str) skip_past_char (str, ',')
+
+/* Parse an attribute directive for VENDOR. */
+void
+s_vendor_attribute (int vendor)
+{
+ expressionS exp;
+ int type;
+ int tag;
+ unsigned int i = 0;
+ char *s = NULL;
+ char saved_char;
+
+ expression (& exp);
+ if (exp.X_op != O_constant)
+ goto bad;
+
+ tag = exp.X_add_number;
+ type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
+
+ if (skip_past_comma (&input_line_pointer) == -1)
+ goto bad;
+ if (type & 1)
+ {
+ expression (& exp);
+ if (exp.X_op != O_constant)
+ {
+ as_bad (_("expected numeric constant"));
+ ignore_rest_of_line ();
+ return;
+ }
+ i = exp.X_add_number;
+ }
+ if (type == 3
+ && skip_past_comma (&input_line_pointer) == -1)
+ {
+ as_bad (_("expected comma"));
+ ignore_rest_of_line ();
+ return;
+ }
+ if (type & 2)
+ {
+ skip_whitespace(input_line_pointer);
+ if (*input_line_pointer != '"')
+ goto bad_string;
+ input_line_pointer++;
+ s = input_line_pointer;
+ while (*input_line_pointer && *input_line_pointer != '"')
+ input_line_pointer++;
+ if (*input_line_pointer != '"')
+ goto bad_string;
+ saved_char = *input_line_pointer;
+ *input_line_pointer = 0;
+ }
+ else
+ {
+ s = NULL;
+ saved_char = 0;
+ }
+
+ switch (type)
+ {
+ case 3:
+ bfd_elf_add_obj_attr_compat (stdoutput, vendor, i, s);
+ break;
+ case 2:
+ bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
+ break;
+ case 1:
+ bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
+ break;
+ default:
+ abort ();
+ }
+
+ if (s)
+ {
+ *input_line_pointer = saved_char;
+ input_line_pointer++;
+ }
+ demand_empty_rest_of_line ();
+ return;
+bad_string:
+ as_bad (_("bad string constant"));
+ ignore_rest_of_line ();
+ return;
+bad:
+ as_bad (_("expected <tag> , <value>"));
+ ignore_rest_of_line ();
+}
+
+/* Parse a .gnu_attribute directive. */
+
+static void
+s_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+ s_vendor_attribute (OBJ_ATTR_GNU);
+}
+#endif /* OBJ_ELF */
+
/* Handle the MRI IRP and IRPC pseudo-ops. */
void
*p = 0;
symbolP = symbol_find_or_make (name);
- /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 &&
- symbolP->sy_desc == 0) out of this test because coff doesn't have
- those fields, and I can't see when they'd ever be tripped. I
- don't think I understand why they were here so I may have
- introduced a bug. As recently as 1.37 didn't have this test
- anyway. xoxorich. */
-
- if (S_GET_SEGMENT (symbolP) == undefined_section
- && S_GET_VALUE (symbolP) == 0)
+ if (S_GET_SEGMENT (symbolP) == undefined_section)
{
/* The name might be an undefined .global symbol; be sure to
keep the "external" bit. */
#endif
}
- if (S_IS_DEFINED (symbolP))
+ if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
{
/* Permit register names to be redefined. */
if ((mode != 0 || !S_IS_VOLATILE (symbolP))
/* If the symbol is volatile, copy the symbol and replace the
original with the copy, so that previous uses of the symbol will
retain the value of the symbol at the point of use. */
- else if (S_IS_VOLATILE (symbolP)
- /* This could be avoided when the symbol wasn't used so far, but
- the comment in struc-symbol.h says this flag isn't reliable. */
- && (1 || symbol_used_p (symbolP)))
+ else if (S_IS_VOLATILE (symbolP))
symbolP = symbol_clone (symbolP, 1);
}
expressionS val;
char *p = 0;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
int bytes;
#ifdef md_flush_pending_output
if (exp.X_op == O_constant)
{
- long repeat;
+ offsetT repeat;
repeat = exp.X_add_number;
if (mult)
int flen;
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
char *stop = NULL;
- char stopc;
+ char stopc = 0;
if (flag_mri)
stop = mri_comment_field (&stopc);
err = md_atof (float_type, temp, &flen);
know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (flen > 0);
+ know (err != NULL || flen > 0);
if (err)
{
as_bad (_("bad floating literal: %s"), err);
s_struct (int ignore ATTRIBUTE_UNUSED)
{
char *stop = NULL;
- char stopc;
+ char stopc = 0;
if (flag_mri)
stop = mri_comment_field (&stopc);
abs_section_offset = get_absolute_expression ();
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+ /* The ELF backend needs to know that we are changing sections, so
+ that .previous works correctly. */
+ if (IS_ELF)
+ obj_elf_section_change_hook ();
+#endif
subseg_set (absolute_section, 0);
demand_empty_rest_of_line ();
if (flag_mri)
const_flag &= ~IN_DEFAULT_SECTION;
#endif
}
+
+/* .weakref x, y sets x as an alias to y that, as long as y is not
+ referenced directly, will cause y to become a weak symbol. */
+void
+s_weakref (int ignore ATTRIBUTE_UNUSED)
+{
+ char *name;
+ char delim;
+ char *end_name;
+ symbolS *symbolP;
+ symbolS *symbolP2;
+ expressionS exp;
+
+ name = input_line_pointer;
+ delim = get_symbol_end ();
+ end_name = input_line_pointer;
+
+ if (name == end_name)
+ {
+ as_bad (_("expected symbol name"));
+ *end_name = delim;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ symbolP = symbol_find_or_make (name);
+
+ if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
+ {
+ if (!S_IS_VOLATILE (symbolP))
+ {
+ as_bad (_("symbol `%s' is already defined"), name);
+ *end_name = delim;
+ ignore_rest_of_line ();
+ return;
+ }
+ symbolP = symbol_clone (symbolP, 1);
+ S_CLEAR_VOLATILE (symbolP);
+ }
+
+ *end_name = delim;
+
+ SKIP_WHITESPACE ();
+
+ if (*input_line_pointer != ',')
+ {
+ *end_name = 0;
+ as_bad (_("expected comma after \"%s\""), name);
+ *end_name = delim;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ input_line_pointer++;
+
+ SKIP_WHITESPACE ();
+
+ name = input_line_pointer;
+ delim = get_symbol_end ();
+ end_name = input_line_pointer;
+
+ if (name == end_name)
+ {
+ as_bad (_("expected symbol name"));
+ ignore_rest_of_line ();
+ return;
+ }
+
+ if ((symbolP2 = symbol_find_noref (name, 1)) == NULL
+ && (symbolP2 = md_undefined_symbol (name)) == NULL)
+ {
+ symbolP2 = symbol_find_or_make (name);
+ S_SET_WEAKREFD (symbolP2);
+ }
+ else
+ {
+ symbolS *symp = symbolP2;
+
+ while (S_IS_WEAKREFR (symp) && symp != symbolP)
+ {
+ expressionS *expP = symbol_get_value_expression (symp);
+
+ assert (expP->X_op == O_symbol
+ && expP->X_add_number == 0);
+ symp = expP->X_add_symbol;
+ }
+ if (symp == symbolP)
+ {
+ char *loop;
+
+ loop = concat (S_GET_NAME (symbolP),
+ " => ", S_GET_NAME (symbolP2), (const char *) NULL);
+
+ symp = symbolP2;
+ while (symp != symbolP)
+ {
+ char *old_loop = loop;
+ symp = symbol_get_value_expression (symp)->X_add_symbol;
+ loop = concat (loop, " => ", S_GET_NAME (symp),
+ (const char *) NULL);
+ free (old_loop);
+ }
+
+ as_bad (_("%s: would close weakref loop: %s"),
+ S_GET_NAME (symbolP), loop);
+
+ free (loop);
+
+ *end_name = delim;
+ ignore_rest_of_line ();
+ return;
+ }
+
+ /* Short-circuiting instead of just checking here might speed
+ things up a tiny little bit, but loop error messages would
+ miss intermediate links. */
+ /* symbolP2 = symp; */
+ }
+
+ *end_name = delim;
+
+ memset (&exp, 0, sizeof (exp));
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbolP2;
+
+ S_SET_SEGMENT (symbolP, undefined_section);
+ symbol_set_value_expression (symbolP, &exp);
+ symbol_set_frag (symbolP, &zero_address_frag);
+ S_SET_WEAKREFR (symbolP);
+
+ demand_empty_rest_of_line ();
+}
\f
/* Verify that we are at the end of a line. If not, issue an error and
S_SET_SEGMENT (symbolP, reg_section);
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
set_zero_frag (symbolP);
+ symbol_get_value_expression (symbolP)->X_op = O_register;
break;
case O_symbol:
int c;
expressionS exp;
char *stop = NULL;
- char stopc;
+ char stopc = 0;
#ifdef md_flush_pending_output
md_flush_pending_output ();
cons_worker (size, 1);
}
+/* .reloc offset, reloc_name, symbol+addend. */
+
+void
+s_reloc (int ignore ATTRIBUTE_UNUSED)
+{
+ char *stop = NULL;
+ char stopc = 0;
+ expressionS exp;
+ char *r_name;
+ int c;
+ struct reloc_list *reloc;
+
+ reloc = xmalloc (sizeof (*reloc));
+
+ if (flag_mri)
+ stop = mri_comment_field (&stopc);
+
+ expression (&exp);
+ switch (exp.X_op)
+ {
+ case O_illegal:
+ case O_absent:
+ case O_big:
+ case O_register:
+ as_bad (_("missing or bad offset expression"));
+ goto err_out;
+ case O_constant:
+ exp.X_add_symbol = section_symbol (now_seg);
+ exp.X_op = O_symbol;
+ /* Fall thru */
+ case O_symbol:
+ if (exp.X_add_number == 0)
+ {
+ reloc->u.a.offset_sym = exp.X_add_symbol;
+ break;
+ }
+ /* Fall thru */
+ default:
+ reloc->u.a.offset_sym = make_expr_symbol (&exp);
+ break;
+ }
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer != ',')
+ {
+ as_bad (_("missing reloc type"));
+ goto err_out;
+ }
+
+ ++input_line_pointer;
+ SKIP_WHITESPACE ();
+ r_name = input_line_pointer;
+ c = get_symbol_end ();
+ reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name);
+ *input_line_pointer = c;
+ if (reloc->u.a.howto == NULL)
+ {
+ as_bad (_("unrecognized reloc type"));
+ goto err_out;
+ }
+
+ exp.X_op = O_absent;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ expression_and_evaluate (&exp);
+ }
+ switch (exp.X_op)
+ {
+ case O_illegal:
+ case O_big:
+ case O_register:
+ as_bad (_("bad reloc expression"));
+ err_out:
+ ignore_rest_of_line ();
+ free (reloc);
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
+ case O_absent:
+ reloc->u.a.sym = NULL;
+ reloc->u.a.addend = 0;
+ break;
+ case O_constant:
+ reloc->u.a.sym = NULL;
+ reloc->u.a.addend = exp.X_add_number;
+ break;
+ case O_symbol:
+ reloc->u.a.sym = exp.X_add_symbol;
+ reloc->u.a.addend = exp.X_add_number;
+ break;
+ default:
+ reloc->u.a.sym = make_expr_symbol (&exp);
+ reloc->u.a.addend = 0;
+ break;
+ }
+
+ as_where (&reloc->file, &reloc->line);
+ reloc->next = reloc_list;
+ reloc_list = reloc;
+
+ demand_empty_rest_of_line ();
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+}
+
/* Put the contents of expression EXP into the object file using
NBYTES bytes. If need_pass_2 is 1, this does nothing. */
&& ((get & mask) != mask
|| (get & hibit) == 0))
{ /* Leading bits contain both 0s & 1s. */
+#if defined (BFD64) && BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
+ as_warn (_("value 0x%llx truncated to 0x%llx"),
+ (unsigned long long) get, (unsigned long long) use);
+#else
+ as_warn (_("value 0x%I64x truncated to 0x%I64x"),
+ (unsigned long long) get, (unsigned long long) use);
+#endif
+#else
as_warn (_("value 0x%lx truncated to 0x%lx"),
(unsigned long) get, (unsigned long) use);
+#endif
}
/* Put bytes in right order. */
md_number_to_chars (p, use, (int) nbytes);
}
}
else
- {
- memset (p, 0, nbytes);
+ emit_expr_fix (exp, nbytes, frag_now, p);
+}
- /* Now we need to generate a fixS to record the symbol value. */
+void
+emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p)
+{
+ memset (p, 0, nbytes);
+
+ /* Generate a fixS to record the symbol value. */
#ifdef TC_CONS_FIX_NEW
- TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
+ TC_CONS_FIX_NEW (frag, p - frag->fr_literal, nbytes, exp);
#else
- {
- bfd_reloc_code_real_type r;
+ {
+ bfd_reloc_code_real_type r;
- switch (nbytes)
- {
- case 1:
- r = BFD_RELOC_8;
- break;
- case 2:
- r = BFD_RELOC_16;
- break;
- case 4:
- r = BFD_RELOC_32;
- break;
- case 8:
- r = BFD_RELOC_64;
- break;
- default:
- as_bad (_("unsupported BFD relocation size %u"), nbytes);
- r = BFD_RELOC_32;
- break;
- }
- fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
- 0, r);
+ switch (nbytes)
+ {
+ case 1:
+ r = BFD_RELOC_8;
+ break;
+ case 2:
+ r = BFD_RELOC_16;
+ break;
+ case 4:
+ r = BFD_RELOC_32;
+ break;
+ case 8:
+ r = BFD_RELOC_64;
+ break;
+ default:
+ as_bad (_("unsupported BFD relocation size %u"), nbytes);
+ r = BFD_RELOC_32;
+ break;
}
+ fix_new_exp (frag, p - frag->fr_literal, (int) nbytes, exp,
+ 0, r);
+ }
#endif
- }
}
\f
#ifdef BITFIELD_CONS_EXPRESSIONS
{
err = md_atof (float_type, temp, &length);
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (length > 0);
+ know (err != NULL || length > 0);
if (err)
{
as_bad (_("bad floating literal: %s"), err);
demand_empty_rest_of_line ();
}
\f
-/* We read 0 or more ',' separated, double-quoted strings.
+static void
+stringer_append_char (int c, int bitsize)
+{
+ if (!target_big_endian)
+ FRAG_APPEND_1_CHAR (c);
+
+ switch (bitsize)
+ {
+ case 64:
+ FRAG_APPEND_1_CHAR (0);
+ FRAG_APPEND_1_CHAR (0);
+ FRAG_APPEND_1_CHAR (0);
+ FRAG_APPEND_1_CHAR (0);
+ /* Fall through. */
+ case 32:
+ FRAG_APPEND_1_CHAR (0);
+ FRAG_APPEND_1_CHAR (0);
+ /* Fall through. */
+ case 16:
+ FRAG_APPEND_1_CHAR (0);
+ /* Fall through. */
+ case 8:
+ break;
+ default:
+ /* Called with invalid bitsize argument. */
+ abort ();
+ break;
+ }
+ if (target_big_endian)
+ FRAG_APPEND_1_CHAR (c);
+}
+
+/* Worker to do .ascii etc statements.
+ Reads 0 or more ',' separated, double-quoted strings.
Caller should have checked need_pass_2 is FALSE because we don't
- check it. */
+ check it.
+ Checks for end-of-line.
+ BITS_APPENDZERO says how many bits are in a target char.
+ The bottom bit is set if a NUL char should be appended to the strings. */
void
-stringer (/* Worker to do .ascii etc statements. */
- /* Checks end-of-line. */
- register int append_zero /* 0: don't append '\0', else 1. */)
+stringer (int bits_appendzero)
{
- register unsigned int c;
+ const int bitsize = bits_appendzero & ~7;
+ const int append_zero = bits_appendzero & 1;
+ unsigned int c;
char *start;
#ifdef md_flush_pending_output
case '\"':
++input_line_pointer; /*->1st char of string. */
start = input_line_pointer;
+
while (is_a_char (c = next_char_of_string ()))
- {
- FRAG_APPEND_1_CHAR (c);
- }
+ stringer_append_char (c, bitsize);
+
if (append_zero)
- {
- FRAG_APPEND_1_CHAR (0);
- }
+ stringer_append_char (0, bitsize);
+
know (input_line_pointer[-1] == '\"');
#ifndef NO_LISTING
case '<':
input_line_pointer++;
c = get_single_number ();
- FRAG_APPEND_1_CHAR (c);
+ stringer_append_char (c, bitsize);
if (*input_line_pointer != '>')
- {
- as_bad (_("expected <nn>"));
- }
+ as_bad (_("expected <nn>"));
+
input_line_pointer++;
break;
case ',':
}
demand_empty_rest_of_line ();
-} /* stringer() */
+}
\f
/* FIXME-SOMEDAY: I had trouble here on characters with the
high bits set. We'll probably also have trouble with
equals (char *sym_name, int reassign)
{
char *stop = NULL;
- char stopc;
+ char stopc = 0;
input_line_pointer++;
if (*input_line_pointer == '=')
if (*input_line_pointer != ',')
{
if (default_prefix)
- asprintf (&label, "%s%s", default_prefix, name);
+ {
+ if (asprintf (&label, "%s%s", default_prefix, name) == -1)
+ as_fatal ("%s", xstrerror (errno));
+ }
else
{
char leading_char = bfd_get_symbol_leading_char (stdoutput);
/* Missing entry point, use function's name with the leading
char prepended. */
if (leading_char)
- asprintf (&label, "%c%s", leading_char, name);
+ {
+ if (asprintf (&label, "%c%s", leading_char, name) == -1)
+ as_fatal ("%s", xstrerror (errno));
+ }
else
label = name;
}