diff options
author | Nick Clifton <nickc@redhat.com> | 2001-07-09 08:19:18 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2001-07-09 08:19:18 +0000 |
commit | 7e005732aa09aad97c790cab88d294aeed06eada (patch) | |
tree | 9411e3103de35962825513144f9ba3b719ddaeda /gas/read.c | |
parent | 46712191470afb32ce078cfa49550f84a774973c (diff) | |
download | fsf-binutils-gdb-7e005732aa09aad97c790cab88d294aeed06eada.zip fsf-binutils-gdb-7e005732aa09aad97c790cab88d294aeed06eada.tar.gz fsf-binutils-gdb-7e005732aa09aad97c790cab88d294aeed06eada.tar.bz2 |
Add .incbin pseudo op
Diffstat (limited to 'gas/read.c')
-rw-r--r-- | gas/read.c | 116 |
1 files changed, 116 insertions, 0 deletions
@@ -349,6 +349,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}, @@ -4900,6 +4901,121 @@ 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, "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, "rb"); + if (binfile != NULL) + break; + } + + if (binfile == NULL) + as_bad (_("file not found: %s"), filename); + } + else + path = xstrdup (filename); + + if (binfile) + { + 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; + } + len = ftell (binfile); + + /* If a count was not specified use the size of the file. */ + if (count == 0) + count = len; + + if (skip + count > len) + { + as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"), + skip, count, 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 |