X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fread.c;h=1718aaa4d63fa53a612fa146b87bf9aeb724be40;hb=e896287c1643b8b47080c4a8ddbe9a92d9fa585b;hp=21c42b27342fb8e2c687417bcdacc4c16e3905b7;hpb=d2ae702c466d7d01de50427a048df0cfd5b90e24;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/read.c b/gas/read.c index 21c42b2734..1718aaa4d6 100644 --- a/gas/read.c +++ b/gas/read.c @@ -1,7 +1,5 @@ /* 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, 2006, 2007, 2008, 2009, - 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1986-2015 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -43,7 +41,7 @@ #include "wchar.h" #ifndef TC_START_LABEL -#define TC_START_LABEL(x,y,z) (x == ':') +#define TC_START_LABEL(STR, NUL_CHAR, NEXT_CHAR) (NEXT_CHAR == ':') #endif /* Set by the object-format or the target. */ @@ -244,9 +242,6 @@ static void do_align (int, char *, int, int); 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); @@ -268,8 +263,11 @@ read_begin (void) obstack_begin (¬es, chunksize); obstack_begin (&cond_obstack, chunksize); +#ifndef tc_line_separator_chars +#define tc_line_separator_chars line_separator_chars +#endif /* Use machine dependent syntax. */ - for (p = line_separator_chars; *p; p++) + for (p = tc_line_separator_chars; *p; p++) is_end_of_line[(unsigned char) *p] = 2; /* Use more. FIXME-SOMEDAY. */ @@ -378,9 +376,6 @@ static const pseudo_typeS potable[] = { {"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}, @@ -562,10 +557,11 @@ pobegin (void) cfi_pop_insert (); } -#define HANDLE_CONDITIONAL_ASSEMBLY() \ +#define HANDLE_CONDITIONAL_ASSEMBLY(num_read) \ if (ignore_input ()) \ { \ - char *eol = find_end_of_line (input_line_pointer, flag_m68k_mri); \ + char *eol = find_end_of_line (input_line_pointer - (num_read), \ + flag_m68k_mri); \ input_line_pointer = (input_line_pointer <= buffer_limit \ && eol >= buffer_limit) \ ? buffer_limit \ @@ -745,7 +741,8 @@ single instruction is %u bytes long but .bundle_align_mode limit is %u"), void read_a_source_file (char *name) { - char c; + char nul_char; + char next_char; char *s; /* String of symbol, '\0' appended. */ int temp; pseudo_typeS *pop; @@ -832,16 +829,18 @@ read_a_source_file (char *name) if (LABELS_WITHOUT_COLONS || flag_m68k_mri) { + next_char = * input_line_pointer; /* Text at the start of a line must be a label, we run down and stick a colon in. */ - if (is_name_beginner (*input_line_pointer)) + if (is_name_beginner (next_char) || next_char == '"') { - char *line_start = input_line_pointer; + char *line_start; int mri_line_macro; - HANDLE_CONDITIONAL_ASSEMBLY (); + HANDLE_CONDITIONAL_ASSEMBLY (0); - c = get_symbol_end (); + nul_char = get_symbol_name (& line_start); + next_char = (nul_char == '"' ? input_line_pointer[1] : nul_char); /* In MRI mode, the EQU and MACRO pseudoops must be handled specially. */ @@ -875,8 +874,7 @@ read_a_source_file (char *name) symbol in the symbol table. */ if (!mri_line_macro #ifdef TC_START_LABEL_WITHOUT_COLON - && TC_START_LABEL_WITHOUT_COLON(c, - input_line_pointer) + && TC_START_LABEL_WITHOUT_COLON (nul_char, next_char) #endif ) line_label = colon (line_start); @@ -886,8 +884,8 @@ read_a_source_file (char *name) (valueT) 0, &zero_address_frag); - *input_line_pointer = c; - if (c == ':') + next_char = restore_line_pointer (nul_char); + if (next_char == ':') input_line_pointer++; } } @@ -902,30 +900,32 @@ read_a_source_file (char *name) Each test is independent of all other tests at the (top) level. */ do - c = *input_line_pointer++; - while (c == '\t' || c == ' ' || c == '\f'); + nul_char = next_char = *input_line_pointer++; + while (next_char == '\t' || next_char == ' ' || next_char == '\f'); /* C is the 1st significant character. Input_line_pointer points after that character. */ - if (is_name_beginner (c)) + if (is_name_beginner (next_char) || next_char == '"') { + char *rest; + /* Want user-defined label or pseudo/opcode. */ - HANDLE_CONDITIONAL_ASSEMBLY (); + HANDLE_CONDITIONAL_ASSEMBLY (1); - s = --input_line_pointer; - c = get_symbol_end (); /* name's delimiter. */ + --input_line_pointer; + nul_char = get_symbol_name (& s); /* name's delimiter. */ + next_char = (nul_char == '"' ? input_line_pointer[1] : nul_char); + rest = input_line_pointer + (nul_char == '"' ? 2 : 1); - /* C is character after symbol. - That character's place in the input line is now '\0'. + /* NEXT_CHAR is character after symbol. + The end of symbol in the input line is now '\0'. S points to the beginning of the symbol. [In case of pseudo-op, s->'.'.] - Input_line_pointer->'\0' where c was. */ - if (TC_START_LABEL (c, s, input_line_pointer)) + Input_line_pointer->'\0' where NUL_CHAR was. */ + if (TC_START_LABEL (s, nul_char, next_char)) { if (flag_m68k_mri) { - char *rest = input_line_pointer + 1; - /* In MRI mode, \tsym: set 0 is permitted. */ if (*rest == ':') ++rest; @@ -944,27 +944,27 @@ read_a_source_file (char *name) } line_label = colon (s); /* User-defined label. */ - /* Put ':' back for error messages' sake. */ - *input_line_pointer++ = ':'; + restore_line_pointer (nul_char); + ++ input_line_pointer; #ifdef tc_check_label tc_check_label (line_label); #endif /* Input_line_pointer->after ':'. */ SKIP_WHITESPACE (); } - else if ((c == '=' && input_line_pointer[1] == '=') - || ((c == ' ' || c == '\t') - && input_line_pointer[1] == '=' - && input_line_pointer[2] == '=')) + else if ((next_char == '=' && *rest == '=') + || ((next_char == ' ' || next_char == '\t') + && rest[0] == '=' + && rest[1] == '=')) { equals (s, -1); demand_empty_rest_of_line (); } - else if ((c == '=' - || ((c == ' ' || c == '\t') - && input_line_pointer[1] == '=')) + else if ((next_char == '=' + || ((next_char == ' ' || next_char == '\t') + && *rest == '=')) #ifdef TC_EQUAL_IN_INSN - && !TC_EQUAL_IN_INSN (c, s) + && !TC_EQUAL_IN_INSN (next_char, s) #endif ) { @@ -1004,7 +1004,7 @@ read_a_source_file (char *name) { /* PSEUDO - OP. - WARNING: c has next char, which may be end-of-line. + WARNING: next_char may be end-of-line. We lookup the pseudo-op table with s+1 because we already know that the pseudo-op begins with a '.'. */ @@ -1049,25 +1049,25 @@ read_a_source_file (char *name) { char *end = input_line_pointer; - *input_line_pointer = c; + (void) restore_line_pointer (nul_char); s_ignore (0); - c = *--input_line_pointer; + nul_char = next_char = *--input_line_pointer; *input_line_pointer = '\0'; - if (! macro_defined || ! try_macro (c, s)) + if (! macro_defined || ! try_macro (next_char, s)) { *end = '\0'; as_bad (_("unknown pseudo-op: `%s'"), s); - *input_line_pointer++ = c; + *input_line_pointer++ = nul_char; } continue; } /* Put it back for error messages etc. */ - *input_line_pointer = c; + next_char = restore_line_pointer (nul_char); /* The following skip of whitespace is compulsory. A well shaped space is sometimes all that separates keyword from operands. */ - if (c == ' ' || c == '\t') + if (next_char == ' ' || next_char == '\t') input_line_pointer++; /* Input_line is restored. @@ -1081,16 +1081,16 @@ read_a_source_file (char *name) } else { - /* WARNING: c has char, which may be end-of-line. */ - /* Also: input_line_pointer->`\0` where c was. */ - *input_line_pointer = c; + /* WARNING: next_char may be end-of-line. */ + /* Also: input_line_pointer->`\0` where nul_char was. */ + (void) restore_line_pointer (nul_char); input_line_pointer = _find_end_of_line (input_line_pointer, flag_m68k_mri, 1, 0); - c = *input_line_pointer; + next_char = nul_char = *input_line_pointer; *input_line_pointer = '\0'; generate_lineno_debug (); - if (macro_defined && try_macro (c, s)) + if (macro_defined && try_macro (next_char, s)) continue; if (mri_pending_align) @@ -1106,7 +1106,7 @@ read_a_source_file (char *name) assemble_one (s); /* Assemble 1 instruction. */ - *input_line_pointer++ = c; + *input_line_pointer++ = nul_char; /* We resume loop AFTER the end-of-line from this instruction. */ @@ -1116,17 +1116,20 @@ read_a_source_file (char *name) } /* Empty statement? */ - if (is_end_of_line[(unsigned char) c]) + if (is_end_of_line[(unsigned char) next_char]) continue; - if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) + if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (next_char)) { /* local label ("4:") */ char *backup = input_line_pointer; - HANDLE_CONDITIONAL_ASSEMBLY (); + HANDLE_CONDITIONAL_ASSEMBLY (1); - temp = c - '0'; + temp = next_char - '0'; + + if (nul_char == '"') + ++ input_line_pointer; /* Read the whole number. */ while (ISDIGIT (*input_line_pointer)) @@ -1160,9 +1163,9 @@ read_a_source_file (char *name) } input_line_pointer = backup; - } /* local label ("4:") */ + } - if (c && strchr (line_comment_chars, c)) + if (next_char && strchr (line_comment_chars, next_char)) { /* Its a comment. Better say APP or NO_APP. */ sb sbuf; char *ends; @@ -1271,10 +1274,10 @@ read_a_source_file (char *name) continue; } - HANDLE_CONDITIONAL_ASSEMBLY (); + HANDLE_CONDITIONAL_ASSEMBLY (1); #ifdef tc_unrecognized_line - if (tc_unrecognized_line (c)) + if (tc_unrecognized_line (next_char)) continue; #endif input_line_pointer--; @@ -1312,10 +1315,10 @@ read_a_source_file (char *name) } /* Convert O_constant expression EXP into the equivalent O_big representation. - Take the sign of the number from X_unsigned rather than X_add_number. */ + Take the sign of the number from SIGN rather than X_add_number. */ static void -convert_to_bignum (expressionS *exp) +convert_to_bignum (expressionS *exp, int sign) { valueT value; unsigned int i; @@ -1328,8 +1331,8 @@ convert_to_bignum (expressionS *exp) } /* Add a sequence of sign bits if the top bit of X_add_number is not the sign of the original value. */ - if ((exp->X_add_number < 0) != !exp->X_unsigned) - generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK; + if ((exp->X_add_number < 0) == !sign) + generic_bignum[i++] = sign ? LITTLENUM_MASK : 0; exp->X_op = O_big; exp->X_add_number = i; } @@ -1475,6 +1478,11 @@ s_align (int arg, int bytes_p) { align = get_absolute_expression (); SKIP_WHITESPACE (); + +#ifdef TC_ALIGN_ZERO_IS_DEFAULT + if (arg > 0 && align == 0) + align = arg; +#endif } if (bytes_p) @@ -1583,7 +1591,7 @@ s_align_ptwo (int arg) /* Switch in and out of alternate macro mode. */ -void +static void s_altmacro (int on) { demand_empty_rest_of_line (); @@ -1604,7 +1612,7 @@ s_altmacro (int on) If a symbol name could not be read, the routine issues an error messages, skips to the end of the line and returns NULL. */ -static char * +char * read_symbol_name (void) { char * name; @@ -1636,7 +1644,7 @@ read_symbol_name (void) name_end = start + len; name = start + sofar; } - + *name++ = (char) C; } *name = 0; @@ -1678,7 +1686,7 @@ read_symbol_name (void) ignore_rest_of_line (); return NULL; } - + SKIP_WHITESPACE (); return start; @@ -1709,7 +1717,7 @@ s_comm_internal (int param, temp = get_absolute_expr (&exp); size = temp; - size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1; + size &= ((addressT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1; if (exp.X_op == O_absent) { as_bad (_("missing size expression")); @@ -1799,7 +1807,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED) name = input_line_pointer; if (!ISDIGIT (*name)) - c = get_symbol_end (); + c = get_symbol_name (& name); else { do @@ -1822,7 +1830,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED) } sym = symbol_find_or_make (name); - *input_line_pointer = c; + c = restore_line_pointer (c); if (alc != NULL) free (alc); @@ -2292,139 +2300,6 @@ s_globl (int ignore ATTRIBUTE_UNUSED) 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. - Returns the attribute number read, or zero on error. */ -int -s_vendor_attribute (int vendor) -{ - expressionS exp; - int type; - int tag; - unsigned int i = 0; - char *s = NULL; - - /* Read the first number or name. */ - skip_whitespace (input_line_pointer); - s = input_line_pointer; - if (ISDIGIT (*input_line_pointer)) - { - expression (& exp); - if (exp.X_op != O_constant) - goto bad; - tag = exp.X_add_number; - } - else - { - char *name; - - /* A name may contain '_', but no other punctuation. */ - for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_'; - ++input_line_pointer) - i++; - if (i == 0) - goto bad; - - name = (char *) alloca (i + 1); - memcpy (name, s, i); - name[i] = '\0'; - -#ifndef CONVERT_SYMBOLIC_ATTRIBUTE -#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1 -#endif - - tag = CONVERT_SYMBOLIC_ATTRIBUTE (name); - if (tag == -1) - { - as_bad (_("Attribute name not recognised: %s"), name); - ignore_rest_of_line (); - return 0; - } - } - - 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 0; - } - i = exp.X_add_number; - } - if ((type & 3) == 3 - && skip_past_comma (&input_line_pointer) == -1) - { - as_bad (_("expected comma")); - ignore_rest_of_line (); - return 0; - } - if (type & 2) - { - int len; - - skip_whitespace (input_line_pointer); - if (*input_line_pointer != '"') - goto bad_string; - s = demand_copy_C_string (&len); - } - - switch (type & 3) - { - case 3: - bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, 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 (); - } - - demand_empty_rest_of_line (); - return tag; -bad_string: - as_bad (_("bad string constant")); - ignore_rest_of_line (); - return 0; -bad: - as_bad (_("expected , ")); - ignore_rest_of_line (); - return 0; -} - -/* 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 @@ -2475,8 +2350,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED) char *s; char c; - s = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& s); if (strcasecmp (s, "discard") == 0) type = LINKONCE_DISCARD; else if (strcasecmp (s, "one_only") == 0) @@ -2488,7 +2362,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED) else as_warn (_("unrecognized .linkonce type `%s'"), s); - *input_line_pointer = c; + (void) restore_line_pointer (c); } #ifdef obj_handle_link_once @@ -2982,7 +2856,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) name = input_line_pointer; if (!ISDIGIT (*name)) - c = get_symbol_end (); + c = get_symbol_name (& name); else { do @@ -2997,11 +2871,11 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) name = xstrdup (name); - *input_line_pointer = c; + c = restore_line_pointer (c); seg = subseg_new (name, 0); - if (*input_line_pointer == ',') + if (c == ',') { int align; @@ -3056,16 +2930,15 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) SKIP_WHITESPACE (); - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& name); name = xstrdup (name); - *input_line_pointer = c; + c = restore_line_pointer (c); seg = subseg_new (name, 0); - if (*input_line_pointer != ',') + if (c != ',') *type = 'C'; else { @@ -3073,8 +2946,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) ++input_line_pointer; SKIP_WHITESPACE (); - sectype = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& sectype); if (*sectype == '\0') *type = 'C'; else if (strcasecmp (sectype, "text") == 0) @@ -3085,7 +2957,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) *type = 'R'; else as_warn (_("unrecognized section type `%s'"), sectype); - *input_line_pointer = c; + (void) restore_line_pointer (c); } if (*input_line_pointer == ',') @@ -3094,8 +2966,7 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) ++input_line_pointer; SKIP_WHITESPACE (); - seccmd = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& seccmd); if (strcasecmp (seccmd, "absolute") == 0) { as_bad (_("absolute sections are not supported")); @@ -3107,14 +2978,14 @@ s_mri_sect (char *type ATTRIBUTE_UNUSED) { int align; - *input_line_pointer = c; + (void) restore_line_pointer (c); align = get_absolute_expression (); record_alignment (seg, align); } else { as_warn (_("unrecognized section command `%s'"), seccmd); - *input_line_pointer = c; + (void) restore_line_pointer (c); } } @@ -3160,11 +3031,10 @@ s_purgem (int ignore ATTRIBUTE_UNUSED) char c; SKIP_WHITESPACE (); - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (& name); delete_macro (name); *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); } while (*input_line_pointer++ == ','); @@ -3325,7 +3195,7 @@ assign_symbol (char *name, int mode) symbol_set_frag (symbolP, dummy_frag); } #endif -#ifdef OBJ_COFF +#if defined (OBJ_COFF) && !defined (TE_PE) /* "set" symbols are local unless otherwise specified. */ SF_SET_LOCAL (symbolP); #endif @@ -3989,19 +3859,22 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes); #ifndef TC_PARSE_CONS_EXPRESSION #ifdef BITFIELD_CONS_EXPRESSIONS -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (parse_bitfield_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE) static void parse_bitfield_cons (expressionS *exp, unsigned int nbytes); #endif #ifdef REPEAT_CONS_EXPRESSIONS -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (parse_repeat_cons (EXP, NBYTES), TC_PARSE_CONS_RETURN_NONE) static void parse_repeat_cons (expressionS *exp, unsigned int nbytes); #endif /* If we haven't gotten one yet, just call expression. */ #ifndef TC_PARSE_CONS_EXPRESSION -#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP) +#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ + (expression (EXP), TC_PARSE_CONS_RETURN_NONE) #endif #endif @@ -4009,7 +3882,7 @@ void do_parse_cons_expression (expressionS *exp, int nbytes ATTRIBUTE_UNUSED) { - TC_PARSE_CONS_EXPRESSION (exp, nbytes); + (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes); } @@ -4052,19 +3925,29 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ c = 0; do { + TC_PARSE_CONS_RETURN_TYPE ret = TC_PARSE_CONS_RETURN_NONE; +#ifdef TC_CONS_FIX_CHECK + fixS **cur_fix = &frchain_now->fix_tail; + + if (*cur_fix != NULL) + cur_fix = &(*cur_fix)->fx_next; +#endif + #ifdef TC_M68K if (flag_m68k_mri) parse_mri_cons (&exp, (unsigned int) nbytes); else #endif { +#if 0 if (*input_line_pointer == '"') { as_bad (_("unexpected `\"' in expression")); ignore_rest_of_line (); return; } - TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); +#endif + ret = TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); } if (rva) @@ -4074,7 +3957,10 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ else as_fatal (_("rva without symbol")); } - emit_expr (&exp, (unsigned int) nbytes); + emit_expr_with_reloc (&exp, (unsigned int) nbytes, ret); +#ifdef TC_CONS_FIX_CHECK + TC_CONS_FIX_CHECK (&exp, nbytes, *cur_fix); +#endif ++c; } while (*input_line_pointer++ == ','); @@ -4107,7 +3993,7 @@ s_rva (int size) /* .reloc offset, reloc_name, symbol+addend. */ -void +static void s_reloc (int ignore ATTRIBUTE_UNUSED) { char *stop = NULL; @@ -4116,6 +4002,14 @@ s_reloc (int ignore ATTRIBUTE_UNUSED) char *r_name; int c; struct reloc_list *reloc; + struct _bfd_rel { char *name; bfd_reloc_code_real_type code; }; + static struct _bfd_rel bfd_relocs[] = { + { "NONE", BFD_RELOC_NONE }, + { "8", BFD_RELOC_8 }, + { "16", BFD_RELOC_16 }, + { "32", BFD_RELOC_32 }, + { "64", BFD_RELOC_64 } + }; reloc = (struct reloc_list *) xmalloc (sizeof (*reloc)); @@ -4156,9 +4050,21 @@ s_reloc (int ignore ATTRIBUTE_UNUSED) ++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); + c = get_symbol_name (& r_name); + if (strncasecmp (r_name, "BFD_RELOC_", 10) == 0) + { + unsigned int i; + + for (reloc->u.a.howto = NULL, i = 0; i < ARRAY_SIZE (bfd_relocs); i++) + if (strcasecmp (r_name + 10, bfd_relocs[i].name) == 0) + { + reloc->u.a.howto = bfd_reloc_type_lookup (stdoutput, + bfd_relocs[i].code); + break; + } + } + else + reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name); *input_line_pointer = c; if (reloc->u.a.howto == NULL) { @@ -4167,7 +4073,7 @@ s_reloc (int ignore ATTRIBUTE_UNUSED) } exp.X_op = O_absent; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer == ',') { ++input_line_pointer; @@ -4217,6 +4123,14 @@ s_reloc (int ignore ATTRIBUTE_UNUSED) void emit_expr (expressionS *exp, unsigned int nbytes) +{ + emit_expr_with_reloc (exp, nbytes, TC_PARSE_CONS_RETURN_NONE); +} + +void +emit_expr_with_reloc (expressionS *exp, + unsigned int nbytes, + TC_PARSE_CONS_RETURN_TYPE reloc) { operatorT op; char *p; @@ -4226,10 +4140,9 @@ emit_expr (expressionS *exp, unsigned int nbytes) if (need_pass_2) return; - /* Grow the current frag now so that dot_value does not get invalidated - if the frag were to fill up in the frag_more() call below. */ frag_grow (nbytes); dot_value = frag_now_fix (); + dot_frag = frag_now; #ifndef NO_LISTING #ifdef OBJ_ELF @@ -4360,6 +4273,12 @@ emit_expr (expressionS *exp, unsigned int nbytes) p = frag_more ((int) nbytes); + if (reloc != TC_PARSE_CONS_RETURN_NONE) + { + emit_expr_fix (exp, nbytes, frag_now, p, reloc); + return; + } + #ifndef WORKING_DOT_WORD /* If we have the difference of two symbols in a word, save it on the broken_words list. See the code in write.c. */ @@ -4390,7 +4309,7 @@ emit_expr (expressionS *exp, unsigned int nbytes) if (op == O_constant && nbytes > sizeof (valueT)) { extra_digit = exp->X_unsigned ? 0 : -1; - convert_to_bignum (exp); + convert_to_bignum (exp, !exp->X_unsigned); op = O_big; } @@ -4518,23 +4437,41 @@ emit_expr (expressionS *exp, unsigned int nbytes) } } else - emit_expr_fix (exp, nbytes, frag_now, p); + emit_expr_fix (exp, nbytes, frag_now, p, TC_PARSE_CONS_RETURN_NONE); } void -emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p) +emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p, + TC_PARSE_CONS_RETURN_TYPE r ATTRIBUTE_UNUSED) { - memset (p, 0, nbytes); + int offset = 0; + unsigned int size = nbytes; + + memset (p, 0, size); /* Generate a fixS to record the symbol value. */ #ifdef TC_CONS_FIX_NEW - TC_CONS_FIX_NEW (frag, p - frag->fr_literal, nbytes, exp); + TC_CONS_FIX_NEW (frag, p - frag->fr_literal + offset, size, exp, r); #else - { - bfd_reloc_code_real_type r; + if (r != TC_PARSE_CONS_RETURN_NONE) + { + reloc_howto_type *reloc_howto; + + reloc_howto = bfd_reloc_type_lookup (stdoutput, r); + size = bfd_get_reloc_size (reloc_howto); - switch (nbytes) + if (size > nbytes) + { + as_bad (_("%s relocations do not fit in %u bytes\n"), + reloc_howto->name, nbytes); + return; + } + else if (target_big_endian) + offset = nbytes - size; + } + else + switch (size) { case 1: r = BFD_RELOC_8; @@ -4552,13 +4489,11 @@ emit_expr_fix (expressionS *exp, unsigned int nbytes, fragS *frag, char *p) r = BFD_RELOC_64; break; default: - as_bad (_("unsupported BFD relocation size %u"), nbytes); - r = BFD_RELOC_32; - break; + as_bad (_("unsupported BFD relocation size %u"), size); + return; } - fix_new_exp (frag, p - frag->fr_literal, (int) nbytes, exp, - 0, r); - } + fix_new_exp (frag, p - frag->fr_literal + offset, size, + exp, 0, r); #endif } @@ -4667,7 +4602,7 @@ parse_bitfield_cons (exp, nbytes) return; } /* Too complex. */ - value |= ((~(-1 << width) & exp->X_add_number) + value |= ((~(-(1 << width)) & exp->X_add_number) << ((BITS_PER_CHAR * nbytes) - bits_available)); if ((bits_available -= width) == 0 @@ -4684,6 +4619,7 @@ parse_bitfield_cons (exp, nbytes) exp->X_add_number = value; exp->X_op = O_constant; exp->X_unsigned = 1; + exp->X_extrabit = 0; } } @@ -4693,15 +4629,13 @@ parse_bitfield_cons (exp, nbytes) #ifdef TC_M68K static void -parse_mri_cons (exp, nbytes) - expressionS *exp; - unsigned int nbytes; +parse_mri_cons (expressionS *exp, unsigned int nbytes) { if (*input_line_pointer != '\'' && (input_line_pointer[1] != '\'' || (*input_line_pointer != 'A' && *input_line_pointer != 'E'))) - TC_PARSE_CONS_EXPRESSION (exp, nbytes); + (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes); else { unsigned int scan; @@ -5158,7 +5092,7 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size) { /* Sign-extend VAL. */ if (val & (1 << (loaded - 1))) - val |= ~0 << loaded; + val |= ~0U << loaded; if (orig) *p = val & 0x7f; p++; @@ -5216,7 +5150,7 @@ output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign) } /* Generate the appropriate fragments for a given expression to emit a - leb128 value. */ + leb128 value. SIGN is 1 for sleb, 0 for uleb. */ static void emit_leb128_expr (expressionS *exp, int sign) @@ -5243,12 +5177,12 @@ emit_leb128_expr (expressionS *exp, int sign) } else if (op == O_constant && sign - && (exp->X_add_number < 0) != !exp->X_unsigned) + && (exp->X_add_number < 0) == !exp->X_extrabit) { /* We're outputting a signed leb128 and the sign of X_add_number doesn't reflect the sign of the original value. Convert EXP to a correctly-extended bignum instead. */ - convert_to_bignum (exp); + convert_to_bignum (exp, exp->X_extrabit); op = O_big; } @@ -5481,7 +5415,7 @@ next_char_of_string (void) #ifndef NO_STRING_ESCAPES case '\\': - switch (c = *input_line_pointer++) + switch (c = *input_line_pointer++ & CHAR_MASK) { case 'b': c = '\b'; @@ -5532,7 +5466,7 @@ next_char_of_string (void) number = number * 8 + c - '0'; } - c = number & 0xff; + c = number & CHAR_MASK; } --input_line_pointer; break; @@ -5554,7 +5488,7 @@ next_char_of_string (void) number = number * 16 + c - 'a' + 10; c = *input_line_pointer++; } - c = number & 0xff; + c = number & CHAR_MASK; --input_line_pointer; } break; @@ -5933,8 +5867,8 @@ add_include_dir (char *path) { include_dir_count++; include_dirs = - (char **) realloc (include_dirs, - include_dir_count * sizeof (*include_dirs)); + (char **) xrealloc (include_dirs, + include_dir_count * sizeof (*include_dirs)); } include_dirs[include_dir_count - 1] = path; /* New one. */ @@ -6026,11 +5960,10 @@ do_s_func (int end_p, const char *default_prefix) return; } - name = input_line_pointer; - delim1 = get_symbol_end (); + delim1 = get_symbol_name (& name); name = xstrdup (name); *input_line_pointer = delim1; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { if (default_prefix) @@ -6056,10 +5989,9 @@ do_s_func (int end_p, const char *default_prefix) { ++input_line_pointer; SKIP_WHITESPACE (); - label = input_line_pointer; - delim2 = get_symbol_end (); + delim2 = get_symbol_name (& label); label = xstrdup (label); - *input_line_pointer = delim2; + restore_line_pointer (delim2); } if (debug_type == DEBUG_STABS) @@ -6234,7 +6166,7 @@ _find_end_of_line (char *s, int mri_string, int insn ATTRIBUTE_UNUSED, } if (inquote) as_warn (_("missing closing `%c'"), inquote); - if (inescape) + if (inescape && !ignore_input ()) as_warn (_("stray `\\'")); return s; }