diff options
Diffstat (limited to 'contrib/binutils/gas/read.c')
-rw-r--r-- | contrib/binutils/gas/read.c | 346 |
1 files changed, 258 insertions, 88 deletions
diff --git a/contrib/binutils/gas/read.c b/contrib/binutils/gas/read.c index 32050c4..b0446c8d 100644 --- a/contrib/binutils/gas/read.c +++ b/contrib/binutils/gas/read.c @@ -1,6 +1,6 @@ /* read.c - read a source file - Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -35,10 +35,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* Routines that read assembler source text to build spagetti in memory. Another group of these functions is in the expr.c module. */ -/* For isdigit (). */ -#include <ctype.h> - #include "as.h" +#include "safe-ctype.h" #include "subsegs.h" #include "sb.h" #include "macro.h" @@ -317,6 +315,7 @@ static const pseudo_typeS potable[] = { {"endc", s_endif, 0}, {"endfunc", s_func, 1}, {"endif", s_endif, 0}, + {"endr", s_bad_endr, 0}, /* endef */ {"equ", s_set, 0}, {"equiv", s_set, 1}, @@ -349,6 +348,7 @@ static const pseudo_typeS potable[] = { {"ifne", s_if, (int) O_ne}, {"ifnes", s_ifeqs, 1}, {"ifnotdef", s_ifdef, 1}, + {"incbin", s_incbin, 0}, {"include", s_include, 0}, {"int", cons, 4}, {"irp", s_irp, 0}, @@ -738,8 +738,7 @@ read_a_source_file (name) while (*s2) { - if (isupper ((unsigned char) *s2)) - *s2 = tolower (*s2); + *s2 = TOLOWER (*s2); s2++; } } @@ -799,7 +798,7 @@ read_a_source_file (name) /* Print the error msg now, while we still can. */ if (pop == NULL) { - as_bad (_("Unknown pseudo-op: `%s'"), s); + as_bad (_("unknown pseudo-op: `%s'"), s); *input_line_pointer = c; s_ignore (0); continue; @@ -906,8 +905,7 @@ read_a_source_file (name) if (is_end_of_line[(unsigned char) c]) continue; - if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) - && isdigit ((unsigned char) c)) + if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c)) { /* local label ("4:") */ char *backup = input_line_pointer; @@ -917,7 +915,7 @@ read_a_source_file (name) temp = c - '0'; /* Read the whole number. */ - while (isdigit ((unsigned char) *input_line_pointer)) + while (ISDIGIT (*input_line_pointer)) { temp = (temp * 10) + *input_line_pointer - '0'; ++input_line_pointer; @@ -1052,8 +1050,8 @@ read_a_source_file (name) if (tc_unrecognized_line (c)) continue; #endif - /* as_warn (_("Junk character %d."),c); Now done by ignore_rest. */ - input_line_pointer--; /* Report unknown char as ignored. */ + input_line_pointer--; + /* Report unknown char as ignored. */ ignore_rest_of_line (); } @@ -1165,6 +1163,19 @@ do_align (n, fill, len, max) int len; int max; { + if (now_seg == absolute_section) + { + if (fill != NULL) + while (len-- > 0) + if (*fill++ != '\0') + { + as_warn (_("ignoring fill value in absolute section")); + break; + } + fill = NULL; + len = 0; + } + #ifdef md_do_align md_do_align (n, fill, len, max, just_record_alignment); #endif @@ -1235,7 +1246,7 @@ s_align (arg, bytes_p) for (i = 0; (align & 1) == 0; align >>= 1, ++i) ; if (align != 1) - as_bad (_("Alignment not a power of 2")); + as_bad (_("alignment not a power of 2")); align = i; } @@ -1244,7 +1255,7 @@ s_align (arg, bytes_p) if (align > 15) { align = 15; - as_bad (_("Alignment too large: %u assumed"), align); + as_warn (_("alignment too large: %u assumed"), align); } if (*input_line_pointer != ',') @@ -1351,11 +1362,21 @@ s_comm (ignore) /* Just after name is now '\0'. */ p = input_line_pointer; *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); if (*input_line_pointer != ',') { - as_bad (_("Expected comma after symbol-name: rest of line ignored.")); + *p = 0; + as_bad (_("expected comma after \"%s\""), name); + *p = c; ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); @@ -1366,7 +1387,7 @@ s_comm (ignore) if ((temp = get_absolute_expression ()) < 0) { - as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp); + as_warn (_(".COMMon length (%ld) < 0 ignored"), (long) temp); ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); @@ -1379,7 +1400,7 @@ s_comm (ignore) if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP)) { - as_bad (_("Ignoring attempt to re-define symbol `%s'."), + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); ignore_rest_of_line (); if (flag_mri) @@ -1390,7 +1411,7 @@ s_comm (ignore) if (S_GET_VALUE (symbolP)) { if (S_GET_VALUE (symbolP) != (valueT) temp) - as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."), + as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"), S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) temp); @@ -1442,7 +1463,7 @@ s_mri_common (small) SKIP_WHITESPACE (); name = input_line_pointer; - if (!isdigit ((unsigned char) *name)) + if (!ISDIGIT (*name)) c = get_symbol_end (); else { @@ -1450,7 +1471,7 @@ s_mri_common (small) { ++input_line_pointer; } - while (isdigit ((unsigned char) *input_line_pointer)); + while (ISDIGIT (*input_line_pointer)); c = *input_line_pointer; *input_line_pointer = '\0'; @@ -1480,7 +1501,7 @@ s_mri_common (small) if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym)) { - as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym)); + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym)); ignore_rest_of_line (); mri_comment_end (stop, stopc); return; @@ -1604,7 +1625,7 @@ s_app_line (ignore) if (l < 0) /* Some of the back ends can't deal with non-positive line numbers. Besides, it's silly. */ - as_warn (_("Line numbers must be positive; line number %d rejected."), + as_warn (_("line numbers must be positive; line number %d rejected"), l + 1); else { @@ -1700,18 +1721,18 @@ s_fill (ignore) #define BSD_FILL_SIZE_CROCK_8 (8) if (size > BSD_FILL_SIZE_CROCK_8) { - as_warn (_(".fill size clamped to %d."), BSD_FILL_SIZE_CROCK_8); + as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8); size = BSD_FILL_SIZE_CROCK_8; } if (size < 0) { - as_warn (_("Size negative: .fill ignored.")); + as_warn (_("size negative; .fill ignored")); size = 0; } else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0) { if (rep_exp.X_add_number < 0) - as_warn (_("Repeat < 0, .fill ignored")); + as_warn (_("repeat < 0; .fill ignored")); size = 0; } @@ -1753,10 +1774,10 @@ s_fill (ignore) memset (p, 0, (unsigned int) size); /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX - flavoured AS. The following bizzare behaviour is to be + flavoured AS. The following bizarre behaviour is to be compatible with above. I guess they tried to take up to 8 bytes from a 4-byte expression and they forgot to sign - extend. Un*x Sux. */ + extend. */ #define BSD_FILL_SIZE_CROCK_4 (4) md_number_to_chars (p, (valueT) fill, (size > BSD_FILL_SIZE_CROCK_4 @@ -1797,7 +1818,7 @@ s_globl (ignore) { input_line_pointer++; SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') + if (is_end_of_line[(unsigned char) *input_line_pointer]) c = '\n'; } } @@ -1941,6 +1962,14 @@ s_lcomm_internal (needs_align, bytes_p) 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 @@ -1951,15 +1980,15 @@ s_lcomm_internal (needs_align, bytes_p) SKIP_WHITESPACE (); } - if (*input_line_pointer == '\n') + if (is_end_of_line[(unsigned char) *input_line_pointer]) { - as_bad (_("Missing size expression")); + as_bad (_("missing size expression")); return; } if ((temp = get_absolute_expression ()) < 0) { - as_warn (_("BSS length (%d.) <0! Ignored."), temp); + as_warn (_("BSS length (%d) < 0 ignored"), temp); ignore_rest_of_line (); return; } @@ -1969,7 +1998,7 @@ s_lcomm_internal (needs_align, bytes_p) || OUTPUT_FLAVOR == bfd_target_elf_flavour) { /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */ - if (temp <= bfd_get_gp_size (stdoutput)) + if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) { bss_seg = subseg_new (".sbss", 1); seg_info (bss_seg)->bss = 1; @@ -1998,7 +2027,7 @@ s_lcomm_internal (needs_align, bytes_p) if (*input_line_pointer != ',') { - as_bad (_("Expected comma after size")); + as_bad (_("expected comma after size")); ignore_rest_of_line (); return; } @@ -2006,9 +2035,9 @@ s_lcomm_internal (needs_align, bytes_p) input_line_pointer++; SKIP_WHITESPACE (); - if (*input_line_pointer == '\n') + if (is_end_of_line[(unsigned char) *input_line_pointer]) { - as_bad (_("Missing alignment")); + as_bad (_("missing alignment")); return; } @@ -2024,7 +2053,7 @@ s_lcomm_internal (needs_align, bytes_p) for (i = 0; (align & 1) == 0; align >>= 1, ++i) ; if (align != 1) - as_bad (_("Alignment not a power of 2")); + as_bad (_("alignment not a power of 2")); align = i; } } @@ -2032,12 +2061,12 @@ s_lcomm_internal (needs_align, bytes_p) if (align > max_alignment) { align = max_alignment; - as_warn (_("Alignment too large: %d. assumed."), align); + as_warn (_("alignment too large; %d assumed"), align); } else if (align < 0) { align = 0; - as_warn (_("Alignment negative. 0 assumed.")); + as_warn (_("alignment negative; 0 assumed")); } record_alignment (bss_seg, align); @@ -2105,8 +2134,7 @@ s_lcomm_internal (needs_align, bytes_p) #endif } else - as_bad (_("Ignoring attempt to re-define symbol `%s'."), - S_GET_NAME (symbolP)); + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); subseg_set (current_seg, current_subseg); @@ -2142,12 +2170,20 @@ s_lsym (ignore) 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 (); if (*input_line_pointer != ',') { *p = 0; - as_bad (_("Expected comma after name \"%s\""), name); + as_bad (_("expected comma after \"%s\""), name); *p = c; ignore_rest_of_line (); return; @@ -2187,7 +2223,7 @@ s_lsym (ignore) } else { - as_bad (_("Symbol %s already defined"), name); + as_bad (_("symbol `%s' is already defined"), name); } *p = c; @@ -2362,8 +2398,7 @@ do_org (segment, exp, fill) int fill; { if (segment != now_seg && segment != absolute_section) - as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"), - segment_name (segment), segment_name (now_seg)); + as_bad (_("invalid segment \"%s\""), segment_name (segment)); if (now_seg == absolute_section) { @@ -2463,7 +2498,7 @@ s_mri_sect (type) SKIP_WHITESPACE (); name = input_line_pointer; - if (!isdigit ((unsigned char) *name)) + if (!ISDIGIT (*name)) c = get_symbol_end (); else { @@ -2471,7 +2506,7 @@ s_mri_sect (type) { ++input_line_pointer; } - while (isdigit ((unsigned char) *input_line_pointer)); + while (ISDIGIT (*input_line_pointer)); c = *input_line_pointer; *input_line_pointer = '\0'; @@ -2496,7 +2531,7 @@ s_mri_sect (type) if (*input_line_pointer == ',') { c = *++input_line_pointer; - c = toupper ((unsigned char) c); + c = TOUPPER (c); if (c == 'C' || c == 'D' || c == 'M' || c == 'R') *type = c; else @@ -2660,6 +2695,16 @@ s_purgem (ignore) /* Handle the .rept pseudo-op. */ void +s_bad_endr (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp")); + demand_empty_rest_of_line (); +} + +/* Handle the .rept pseudo-op. */ + +void s_rept (ignore) int ignore ATTRIBUTE_UNUSED; { @@ -2737,12 +2782,20 @@ s_set (equiv) delim = get_symbol_end (); end_name = input_line_pointer; *end_name = delim; + + if (name == end_name) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + SKIP_WHITESPACE (); if (*input_line_pointer != ',') { *end_name = 0; - as_bad (_("Expected comma after name \"%s\""), name); + as_bad (_("expected comma after \"%s\""), name); *end_name = delim; ignore_rest_of_line (); return; @@ -2800,7 +2853,7 @@ s_set (equiv) if (equiv && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section) - as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); pseudo_set (symbolP); demand_empty_rest_of_line (); @@ -2886,7 +2939,7 @@ s_space (mult) || (mult != 0 && mult != 1 && val.X_add_number != 0)) { if (exp.X_op != O_constant) - as_bad (_("Unsupported variable size or fill value")); + as_bad (_("unsupported variable size or fill value")); else { offsetT i; @@ -3011,7 +3064,7 @@ s_float_space (float_type) /* Skip any 0{letter} that may be present. Don't even check if the * letter is legal. */ if (input_line_pointer[0] == '0' - && isalpha ((unsigned char) input_line_pointer[1])) + && ISALPHA (input_line_pointer[1])) input_line_pointer += 2; /* Accept :xxxx, where the x's are hex digits, for a floating point @@ -3036,7 +3089,7 @@ s_float_space (float_type) know (flen > 0); if (err) { - as_bad (_("Bad floating literal: %s"), err); + as_bad (_("bad floating literal: %s"), err); ignore_rest_of_line (); if (flag_mri) mri_comment_end (stop, stopc); @@ -3108,12 +3161,12 @@ ignore_rest_of_line () /* For suspect lines: gives warning. */ if (!is_end_of_line[(unsigned char) *input_line_pointer]) { - if (isprint ((unsigned char) *input_line_pointer)) - as_bad (_("Rest of line ignored. First ignored character is `%c'."), - *input_line_pointer); + if (ISPRINT (*input_line_pointer)) + as_warn (_("rest of line ignored; first ignored character is `%c'"), + *input_line_pointer); else - as_bad (_("Rest of line ignored. First ignored character valued 0x%x."), - *input_line_pointer); + as_warn (_("rest of line ignored; first ignored character valued 0x%x"), + *input_line_pointer); while (input_line_pointer < buffer_limit && !is_end_of_line[(unsigned char) *input_line_pointer]) @@ -3163,15 +3216,15 @@ pseudo_set (symbolP) (void) expression (&exp); if (exp.X_op == O_illegal) - as_bad (_("illegal expression; zero assumed")); + as_bad (_("illegal expression")); else if (exp.X_op == O_absent) - as_bad (_("missing expression; zero assumed")); + as_bad (_("missing expression")); else if (exp.X_op == O_big) { if (exp.X_add_number > 0) - as_bad (_("bignum invalid; zero assumed")); + as_bad (_("bignum invalid")); else - as_bad (_("floating point number invalid; zero assumed")); + as_bad (_("floating point number invalid")); } else if (exp.X_op == O_subtract && (S_GET_SEGMENT (exp.X_add_symbol) @@ -3216,7 +3269,7 @@ pseudo_set (symbolP) || exp.X_add_number != 0) symbol_set_value_expression (symbolP, &exp); else if (symbol_section_p (symbolP)) - as_bad ("invalid attempt to set value of section symbol"); + as_bad ("attempt to set value of section symbol"); else { symbolS *s = exp.X_add_symbol; @@ -3504,7 +3557,7 @@ emit_expr (exp, nbytes) } else if (op == O_big && exp->X_add_number <= 0) { - as_bad (_("floating point number invalid; zero assumed")); + as_bad (_("floating point number invalid")); exp->X_add_number = 0; op = O_constant; } @@ -3600,7 +3653,7 @@ emit_expr (exp, nbytes) && ((get & mask) != mask || (get & hibit) == 0)) { /* Leading bits contain both 0s & 1s. */ - as_warn (_("Value 0x%lx truncated to 0x%lx."), + as_warn (_("value 0x%lx truncated to 0x%lx"), (unsigned long) get, (unsigned long) use); } /* Put bytes in right order. */ @@ -3616,7 +3669,7 @@ emit_expr (exp, nbytes) size = exp->X_add_number * CHARS_PER_LITTLENUM; if (nbytes < size) { - as_warn (_("Bignum truncated to %d bytes"), nbytes); + as_warn (_("bignum truncated to %d bytes"), nbytes); size = nbytes; } @@ -3630,7 +3683,7 @@ emit_expr (exp, nbytes) } nums = generic_bignum + size / CHARS_PER_LITTLENUM; - while (size > 0) + while (size >= CHARS_PER_LITTLENUM) { --nums; md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); @@ -3641,7 +3694,7 @@ emit_expr (exp, nbytes) else { nums = generic_bignum; - while (size > 0) + while (size >= CHARS_PER_LITTLENUM) { md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); ++nums; @@ -3650,7 +3703,7 @@ emit_expr (exp, nbytes) nbytes -= CHARS_PER_LITTLENUM; } - while (nbytes > 0) + while (nbytes >= CHARS_PER_LITTLENUM) { md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM); nbytes -= CHARS_PER_LITTLENUM; @@ -3947,7 +4000,7 @@ parse_repeat_cons (exp, nbytes) if (count.X_op != O_constant || count.X_add_number <= 0) { - as_warn (_("Unresolvable or nonpositive repeat count; using 1")); + as_warn (_("unresolvable or nonpositive repeat count; using 1")); return; } @@ -3998,7 +4051,7 @@ hex_float (float_type, bytes) break; default: - as_bad (_("Unknown floating type type '%c'"), float_type); + as_bad (_("unknown floating type type '%c'"), float_type); return -1; } @@ -4020,7 +4073,7 @@ hex_float (float_type, bytes) if (i >= length) { - as_warn (_("Floating point constant too large")); + as_warn (_("floating point constant too large")); return -1; } d = hex_value (*input_line_pointer) << 4; @@ -4097,7 +4150,7 @@ float_cons (float_type) has no use for such information. Lusers beware: you get diagnostics if your input is ill-conditioned. */ if (input_line_pointer[0] == '0' - && isalpha ((unsigned char) input_line_pointer[1])) + && ISALPHA (input_line_pointer[1])) input_line_pointer += 2; /* Accept :xxxx, where the x's are hex digits, for a floating @@ -4119,7 +4172,7 @@ float_cons (float_type) know (length > 0); if (err) { - as_bad (_("Bad floating literal: %s"), err); + as_bad (_("bad floating literal: %s"), err); ignore_rest_of_line (); return; } @@ -4403,7 +4456,7 @@ emit_leb128_expr (exp, sign) } else if (op == O_big && exp->X_add_number <= 0) { - as_bad (_("floating point number invalid; zero assumed")); + as_bad (_("floating point number invalid")); exp->X_add_number = 0; op = O_constant; } @@ -4551,7 +4604,7 @@ stringer (append_zero) /* Worker to do .ascii etc statements. */ FRAG_APPEND_1_CHAR (c); if (*input_line_pointer != '>') { - as_bad (_("Expected <nn>")); + as_bad (_("expected <nn>")); } input_line_pointer++; break; @@ -4584,7 +4637,7 @@ next_char_of_string () break; case '\n': - as_warn (_("Unterminated string: Newline inserted.")); + as_warn (_("unterminated string; newline inserted")); bump_line_counters (); break; @@ -4635,7 +4688,7 @@ next_char_of_string () int i; for (i = 0, number = 0; - isdigit (c) && i < 3; + ISDIGIT (c) && i < 3; c = *input_line_pointer++, i++) { number = number * 8 + c - '0'; @@ -4653,11 +4706,11 @@ next_char_of_string () number = 0; c = *input_line_pointer++; - while (isxdigit (c)) + while (ISXDIGIT (c)) { - if (isdigit (c)) + if (ISDIGIT (c)) number = number * 16 + c - '0'; - else if (isupper (c)) + else if (ISUPPER (c)) number = number * 16 + c - 'A' + 10; else number = number * 16 + c - 'a' + 10; @@ -4670,7 +4723,7 @@ next_char_of_string () case '\n': /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */ - as_warn (_("Unterminated string: Newline inserted.")); + as_warn (_("unterminated string; newline inserted")); c = '\n'; bump_line_counters (); break; @@ -4678,7 +4731,7 @@ next_char_of_string () default: #ifdef ONLY_STANDARD_ESCAPES - as_bad (_("Bad escaped character in string, '?' assumed")); + as_bad (_("bad escaped character in string")); c = '?'; #endif /* ONLY_STANDARD_ESCAPES */ @@ -4704,7 +4757,7 @@ get_segmented_expression (expP) || expP->X_op == O_absent || expP->X_op == O_big) { - as_bad (_("expected address expression; zero assumed")); + as_bad (_("expected address expression")); expP->X_op = O_constant; expP->X_add_number = 0; retval = absolute_section; @@ -4745,7 +4798,7 @@ get_absolute_expression () if (exp.X_op != O_constant) { if (exp.X_op != O_absent) - as_bad (_("bad or irreducible absolute expression; zero assumed")); + as_bad (_("bad or irreducible absolute expression")); exp.X_add_number = 0; } return exp.X_add_number; @@ -4780,7 +4833,7 @@ demand_copy_C_string (len_pointer) s = 0; len = 1; *len_pointer = 0; - as_bad (_("This string may not contain \'\\0\'")); + as_bad (_("this string may not contain \'\\0\'")); } } } @@ -4817,7 +4870,7 @@ demand_copy_string (lenP) } else { - as_warn (_("Missing string")); + as_warn (_("missing string")); retval = NULL; ignore_rest_of_line (); } @@ -4881,7 +4934,7 @@ equals (sym_name, reassign) if (!reassign && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section) - as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP)); + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); #ifdef OBJ_COFF /* "set" symbols are local unless otherwise specified. */ @@ -4900,6 +4953,123 @@ equals (sym_name, reassign) } } +/* .incbin -- include a file verbatim at the current location. */ + +void +s_incbin (x) + int x ATTRIBUTE_UNUSED; +{ + FILE * binfile; + char * path; + char * filename; + char * binfrag; + long skip = 0; + long count = 0; + long bytes; + int len; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + SKIP_WHITESPACE (); + filename = demand_copy_string (& len); + if (filename == NULL) + return; + + SKIP_WHITESPACE (); + + /* Look for optional skip and count. */ + if (* input_line_pointer == ',') + { + ++ input_line_pointer; + skip = get_absolute_expression (); + + SKIP_WHITESPACE (); + + if (* input_line_pointer == ',') + { + ++ input_line_pointer; + + count = get_absolute_expression (); + if (count == 0) + as_warn (_(".incbin count zero, ignoring `%s'"), filename); + + SKIP_WHITESPACE (); + } + } + + demand_empty_rest_of_line (); + + /* Try opening absolute path first, then try include dirs. */ + binfile = fopen (filename, FOPEN_RB); + if (binfile == NULL) + { + int i; + + path = xmalloc ((unsigned long) len + include_dir_maxlen + 5); + + for (i = 0; i < include_dir_count; i++) + { + sprintf (path, "%s/%s", include_dirs[i], filename); + + binfile = fopen (path, FOPEN_RB); + if (binfile != NULL) + break; + } + + if (binfile == NULL) + as_bad (_("file not found: %s"), filename); + } + else + path = xstrdup (filename); + + if (binfile) + { + long file_len; + + register_dependency (path); + + /* Compute the length of the file. */ + if (fseek (binfile, 0, SEEK_END) != 0) + { + as_bad (_("seek to end of .incbin file failed `%s'"), path); + goto done; + } + file_len = ftell (binfile); + + /* If a count was not specified use the size of the file. */ + if (count == 0) + count = file_len; + + if (skip + count > file_len) + { + as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"), + skip, count, file_len); + goto done; + } + + if (fseek (binfile, skip, SEEK_SET) != 0) + { + as_bad (_("could not skip to %ld in file `%s'"), skip, path); + goto done; + } + + /* Allocate frag space and store file contents in it. */ + binfrag = frag_more (count); + + bytes = fread (binfrag, 1, count, binfile); + if (bytes < count) + as_warn (_("truncated file `%s', %ld of %ld bytes read"), + path, bytes, count); + } +done: + if (binfile != NULL) + fclose (binfile); + if (path) + free (path); +} + /* .include -- include a file at this point. */ void @@ -4948,7 +5118,7 @@ s_include (arg) strcpy (path, include_dirs[i]); strcat (path, "/"); strcat (path, filename); - if (0 != (try = fopen (path, "r"))) + if (0 != (try = fopen (path, FOPEN_RT))) { fclose (try); goto gotit; |