summaryrefslogtreecommitdiffstats
path: root/bfd
diff options
context:
space:
mode:
authorDavid Henkel-Wallace <gumby@cygnus>1991-04-04 02:12:28 +0000
committerDavid Henkel-Wallace <gumby@cygnus>1991-04-04 02:12:28 +0000
commit87f86b4ec66450e49987cc9cbc1b21e5fde8070c (patch)
tree661fb9ede4de8d1053a6c6b47d255f60cd8e5c04 /bfd
parent8922ff76e39b06f63229f60db8c790d57f249b80 (diff)
downloadppe42-binutils-87f86b4ec66450e49987cc9cbc1b21e5fde8070c.tar.gz
ppe42-binutils-87f86b4ec66450e49987cc9cbc1b21e5fde8070c.zip
Initial revision
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ieee.c1919
-rw-r--r--bfd/libieee.h90
-rw-r--r--bfd/liboasys.h70
-rw-r--r--bfd/oasys.c985
-rwxr-xr-xbfd/obstack.c335
-rwxr-xr-xbfd/obstack.h416
6 files changed, 3815 insertions, 0 deletions
diff --git a/bfd/ieee.c b/bfd/ieee.c
new file mode 100644
index 0000000000..f69adbde3c
--- /dev/null
+++ b/bfd/ieee.c
@@ -0,0 +1,1919 @@
+/*
+
+ bfd backend for ieee objects.
+
+ IEEE format is a stream of records, which we parse using a simple one
+ token (which is one byte in this lexicon) lookahead recursive decent
+ parser.
+
+ On output, this module creates files with the parts in this order:
+ header
+ external_part,
+ data_part,
+ section_part,
+
+
+
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "ieee.h"
+#include "libieee.h"
+
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+typedef void generic_symbol_type;
+static bfd_byte current_c;
+
+/***************************************************************************
+ Functions for writing to ieee files in the strange way that the
+ standard requires:
+*/
+
+
+static void
+ieee_write_byte(abfd, byte)
+bfd *abfd;
+bfd_byte byte;
+{
+ bfd_write(&byte, 1, 1, abfd);
+}
+
+
+static void
+ieee_write_2bytes(abfd, bytes)
+bfd *abfd;
+int bytes;
+{
+ bfd_byte buffer[2];
+ buffer[0] = bytes >> 8;
+ buffer[1] = bytes & 0xff;
+
+ bfd_write(buffer, 1, 2, abfd);
+}
+
+static void
+ieee_write_int(abfd, value)
+bfd *abfd;
+bfd_vma value;
+{
+ if (value >= 0 && value <= 127) {
+ ieee_write_byte(abfd, value);
+ }
+ else {
+ unsigned int length;
+ /* How many significant bytes ? */
+ /* FIXME FOR LONGER INTS */
+ if (value & 0xff000000) {
+ length = 4;
+ }
+ else if (value & 0x00ff0000) {
+ length = 3;
+ }
+ else if (value & 0x0000ff00) {
+ length = 2;
+ }
+ else length = 1;
+
+ ieee_write_byte(abfd, ieee_number_repeat_start_enum + length);
+ switch (length) {
+ case 4:
+ ieee_write_byte(abfd, value >> 24);
+ case 3:
+ ieee_write_byte(abfd, value >> 16);
+ case 2:
+ ieee_write_byte(abfd, value >> 8);
+ case 1:
+ ieee_write_byte(abfd, value);
+ }
+ }
+}
+
+static void
+ieee_write_id(abfd, id)
+bfd *abfd;
+char *id;
+{
+ size_t length = strlen(id);
+ if (length >= 0 && length <= 127) {
+ ieee_write_byte(abfd, length);
+ }
+ else if (length < 255) {
+ ieee_write_byte(abfd, ieee_extension_length_1_enum);
+ ieee_write_byte(abfd, length);
+ }
+ else if (length < 65535) {
+ ieee_write_byte(abfd, ieee_extension_length_2_enum);
+ ieee_write_byte(abfd, length >> 8);
+ ieee_write_byte(abfd, length & 0xff);
+ }
+ else {
+ BFD_FAIL();
+ }
+ bfd_write((bfd_byte *)id, 1, length, abfd);
+}
+/***************************************************************************
+Functions for reading from ieee files in the strange way that the
+standard requires:
+*/
+static bfd_byte
+this_byte(abfd)
+bfd *abfd;
+{
+ return current_c;
+}
+
+static void
+next_byte(abfd)
+bfd *abfd;
+{
+ if ( bfd_read(&current_c, 1, 1, abfd) != 1) {
+ BFD_FAIL();
+ }
+
+}
+
+
+static bfd_byte this_byte_and_next(abfd)
+bfd *abfd;
+{
+ bfd_byte r = this_byte(abfd);
+ next_byte(abfd);
+ return r;
+}
+
+
+
+static unsigned short read_2bytes(abfd)
+bfd *abfd;
+{
+ unsigned char c1 = this_byte_and_next(abfd);
+ unsigned char c2 = this_byte_and_next(abfd);
+ return (c1<<8 ) | c2;
+
+}
+
+static void
+bfd_get_string(abfd, string, length)
+bfd *abfd;
+char *string;
+size_t length;
+{
+ size_t i;
+ for (i= 0; i < length; i++) {
+ string[i] = this_byte_and_next(abfd);
+ }
+}
+
+static char *read_id(abfd)
+bfd *abfd;
+{
+ size_t length;
+ char *string;
+ length = this_byte_and_next(abfd);
+ if (length >= 0x00 && length <= 0x7f) {
+ /* Simple string of length 0 to 127 */
+ }
+ else if (length == 0xde) {
+ /* Length is next byte, allowing 0..255 */
+ length = this_byte_and_next(abfd);
+ }
+ else if (length == 0xdf) {
+ /* Length is next two bytes, allowing 0..65535 */
+ length = this_byte_and_next(abfd) ;
+ length = (length * 256) + this_byte_and_next(abfd);
+ }
+ /* Buy memory and read string */
+ string = malloc(length+1);
+ bfd_get_string(abfd, string, length);
+ string[length] = 0;
+ return string;
+}
+
+static void
+ieee_write_expression(abfd, value, section, symbol)
+bfd*abfd;
+bfd_vma value;
+asection *section;
+asymbol *symbol;
+{
+ unsigned int plus_count = 0;
+ ieee_write_int(abfd, value);
+ if (section != (asection *)NULL) {
+ plus_count++;
+ ieee_write_byte(abfd, ieee_variable_L_enum);
+ ieee_write_byte(abfd, section->index +IEEE_SECTION_NUMBER_BASE);
+ }
+
+ if (symbol != (asymbol *)NULL) {
+ plus_count++;
+ if ((symbol->flags & BSF_UNDEFINED ) ||
+ (symbol->flags & BSF_FORT_COMM)) {
+ ieee_write_byte(abfd, ieee_variable_X_enum);
+ ieee_write_int(abfd, symbol->value);
+ }
+ else if (symbol->flags & BSF_GLOBAL) {
+ ieee_write_byte(abfd, ieee_variable_I_enum);
+ ieee_write_int(abfd, symbol->value);
+ }
+ else {
+ BFD_FAIL();
+ }
+ }
+
+ while (plus_count != 0) {
+ ieee_write_byte(abfd, ieee_function_plus_enum);
+ plus_count--;
+ }
+
+}
+
+
+
+
+
+
+
+
+
+/*****************************************************************************/
+
+/*
+writes any integer into the buffer supplied and always takes 5 bytes
+*/
+static void
+ieee_write_int5(buffer, value)
+bfd_byte*buffer;
+bfd_vma value;
+{
+ buffer[0] = ieee_number_repeat_4_enum;
+ buffer[1] = (value >> 24 ) & 0xff;
+ buffer[2] = (value >> 16 ) & 0xff;
+ buffer[3] = (value >> 8 ) & 0xff;
+ buffer[4] = (value >> 4 ) & 0xff;
+}
+
+
+
+static boolean
+parse_int(abfd, value_ptr)
+bfd *abfd;
+bfd_vma *value_ptr;
+{
+ int value = this_byte(abfd);
+ int result;
+ if (value >= 0 && value <= 127) {
+ *value_ptr = value;
+ next_byte(abfd);
+ return true;
+ }
+ else if (value >= 0x80 && value <= 0x88) {
+ unsigned int count = value & 0xf;
+ result = 0;
+ next_byte(abfd);
+ while (count) {
+ result =(result << 8) | this_byte_and_next(abfd);
+ count--;
+ }
+ *value_ptr = result;
+ return true;
+ }
+ return false;
+}
+static int parse_i(abfd, ok)
+bfd *abfd;
+boolean *ok;
+{
+ bfd_vma x;
+ *ok = parse_int(abfd, &x);
+ return x;
+}
+
+static bfd_vma must_parse_int(abfd)
+bfd *abfd;
+{
+ bfd_vma result;
+ BFD_ASSERT(parse_int(abfd, &result) == true);
+ return result;
+}
+
+typedef struct
+{
+ bfd_vma value;
+ asection *section;
+ ieee_symbol_index_type symbol;
+} ieee_value_type;
+
+
+static
+reloc_howto_type abs32_howto
+ = {1,0,2,32,0,0,0,true,0,"abs32",false,0xffffffff};
+static
+reloc_howto_type abs16_howto
+ = {1,0,1,16,0,0,0,true,0,"abs16",false,0x0000ffff};
+
+static ieee_symbol_index_type NOSYMBOL = { 0, 0};
+
+
+void
+frob(abfd, value, section, symbol, pcrel, extra)
+bfd *abfd;
+bfd_vma *value;
+asection **section;
+ieee_symbol_index_type *symbol;
+boolean *pcrel;
+unsigned int *extra;
+{
+#define POS sp[1]
+#define TOS sp[0]
+#define NOS sp[-1]
+#define INC sp++;
+#define DEC sp--;
+
+ boolean loop = true;
+ ieee_value_type stack[10];
+
+ /* The stack pointer always points to the next unused location */
+#define PUSH(x,y,z) TOS.symbol=x;TOS.section=y;TOS.value=z;INC;
+#define POP(x,y,z) DEC;x=TOS.symbol;y=TOS.section;z=TOS.value;
+ ieee_value_type *sp = stack;
+
+ while (loop) {
+ switch (this_byte(abfd))
+ {
+ case ieee_variable_P_enum:
+ /* P variable, current program counter for section n */
+ {
+ int section_n ;
+ next_byte(abfd);
+ section_n = must_parse_int(abfd);
+ PUSH(NOSYMBOL, 0,
+ TOS.value = ieee_data(abfd)->section_table[section_n]->vma +
+ ieee_per_section(ieee_data(abfd)->section_table[section_n])->pc);
+ break;
+ }
+ case ieee_variable_L_enum:
+ /* L variable address of section N */
+ next_byte(abfd);
+ PUSH(NOSYMBOL,ieee_data(abfd)->section_table[must_parse_int(abfd)],0);
+ break;
+ case ieee_variable_R_enum:
+ /* R variable, logical address of section module */
+ /* FIXME, this should be different to L */
+ next_byte(abfd);
+ PUSH(NOSYMBOL,ieee_data(abfd)->section_table[must_parse_int(abfd)],0);
+ break;
+ case ieee_variable_S_enum:
+ /* S variable, size in MAUS of section module */
+ next_byte(abfd);
+ PUSH(NOSYMBOL,
+ 0,
+ ieee_data(abfd)->section_table[must_parse_int(abfd)]->size);
+ break;
+
+ case ieee_variable_X_enum:
+ /* Push the address of external variable n */
+ {
+ ieee_symbol_index_type sy;
+ next_byte(abfd);
+ sy.index = (int)(must_parse_int(abfd)) ;
+ sy.letter = 'X';
+
+ PUSH(sy, 0, 0);
+ }
+ break;
+ case ieee_function_minus_enum:
+ {
+ bfd_vma value1, value2;
+ asection *section;
+ ieee_symbol_index_type sy;
+ next_byte(abfd);
+
+ POP(sy, section, value1);
+ POP(sy, section, value2);
+ PUSH(NOSYMBOL, 0, value1-value2);
+ }
+ break;
+ case ieee_function_plus_enum:
+ {
+ bfd_vma value1, value2;
+ asection *section1;
+ asection *section2;
+ ieee_symbol_index_type sy;
+ next_byte(abfd);
+
+ POP(sy, section1, value1);
+ POP(sy, section2, value2);
+ PUSH(NOSYMBOL, section1 ? section1: section2, value1+value2);
+ }
+ break;
+ default:
+ {
+ bfd_vma va;
+ BFD_ASSERT(this_byte(abfd) < ieee_variable_A_enum
+ || this_byte(abfd) > ieee_variable_Z_enum);
+ if (parse_int(abfd, &va))
+ {
+ PUSH(NOSYMBOL,0, va);
+ }
+ else {
+ /*
+ Thats all that we can understand. As far as I can see
+ there is a bug in the Microtec IEEE output which I'm
+ using to scan, whereby the comma operator is ommited
+ sometimes in an expression, giving expressions with too
+ many terms. We can tell if that's the case by ensuring
+ that sp == stack here. If not, then we've pushed
+ something too far. -
+ */
+
+ POP(*symbol, *section, *value);
+ if (sp != stack) {
+ BFD_ASSERT(*section == 0);
+ *extra = *value;
+ /* Get what should be returned */
+ POP(*symbol, *section, *value);
+ }
+ else {
+ *extra = 0;
+ }
+ loop = false;
+ }
+ }
+
+ }
+ }
+}
+
+static void
+ieee_seek(abfd, offset, rel)
+bfd *abfd;
+file_ptr offset;
+boolean rel;
+{
+ (void) bfd_seek(abfd, offset, rel);
+ /* Prime look ahead token */
+ next_byte(abfd);
+}
+
+static void
+ieee_slurp_external_symbols(abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee = ieee_data(abfd);
+ file_ptr offset = ieee->w.r.external_part;
+
+ ieee_symbol_type **prev_symbols_ptr = &ieee->external_symbols;
+ ieee_symbol_type **prev_reference_ptr = &ieee->external_reference;
+ ieee_symbol_type *symbol;
+ unsigned int symbol_count = 0;
+ boolean loop = true;
+
+ ieee->symbol_table_full = true;
+
+ ieee_seek(abfd, offset ,false);
+
+ while (loop) {
+ switch (this_byte(abfd)) {
+ case ieee_external_symbol_enum:
+ next_byte(abfd);
+ symbol = (ieee_symbol_type *)malloc(sizeof(ieee_symbol_type));
+
+ *prev_symbols_ptr = symbol;
+ prev_symbols_ptr= &symbol->next;
+ symbol->index = must_parse_int(abfd);
+ if (symbol->index > ieee->external_symbol_max_index) {
+ ieee->external_symbol_max_index = symbol->index;
+ }
+ BFD_ASSERT (symbol->index >= ieee->external_symbol_min_index);
+ symbol_count++;
+ symbol->symbol.the_bfd = abfd;
+ symbol->symbol.name = read_id(abfd);
+ symbol->symbol.udata = (void *)NULL;
+ symbol->symbol.flags = BSF_NO_FLAGS;
+ break;
+ case ieee_attribute_record_enum >> 8:
+ {
+ unsigned int symbol_name_index;
+ unsigned int symbol_type_index;
+ unsigned int symbol_attribute_def;
+ bfd_vma value;
+ next_byte(abfd); /* Skip prefix */
+ next_byte(abfd);
+ symbol_name_index = must_parse_int(abfd);
+ symbol_type_index = must_parse_int(abfd);
+ symbol_attribute_def = must_parse_int(abfd);
+
+ parse_int(abfd,&value);
+
+ }
+ break;
+ case ieee_value_record_enum >> 8:
+ {
+ unsigned int symbol_name_index;
+ ieee_symbol_index_type symbol_ignore;
+ boolean *pcrel_ignore;
+ unsigned int extra_ignore;
+ next_byte(abfd);
+ next_byte(abfd);
+
+ symbol_name_index = must_parse_int(abfd);
+ frob(abfd,
+ &symbol->symbol.value,
+ &symbol->symbol.section,
+ &symbol_ignore,
+ &pcrel_ignore,
+ &extra_ignore);
+ if (symbol->symbol.section != (asection *)NULL) {
+ symbol->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+ }
+ else {
+ symbol->symbol.flags = BSF_GLOBAL | BSF_EXPORT | BSF_ABSOLUTE;
+ }
+ }
+ break;
+ case ieee_weak_external_reference_enum:
+ { bfd_vma size;
+ bfd_vma value ;
+ next_byte(abfd);
+ /* Throw away the external reference index */
+ (void)must_parse_int(abfd);
+ /* Fetch the default size if not resolved */
+ size = must_parse_int(abfd);
+ /* Fetch the defautlt value if available */
+ if ( parse_int(abfd, &value) == false) {
+ value = 0;
+ }
+ /* This turns into a common */
+ symbol->symbol.flags = BSF_FORT_COMM;
+ symbol->symbol.value = size;
+ }
+ break;
+
+ case ieee_external_reference_enum:
+ next_byte(abfd);
+ symbol = (ieee_symbol_type *)malloc(sizeof(ieee_symbol_type));
+ symbol_count++;
+ *prev_reference_ptr = symbol;
+ prev_reference_ptr = &symbol->next;
+ symbol->index = must_parse_int(abfd);
+ symbol->symbol.the_bfd = abfd;
+ symbol->symbol.name = read_id(abfd);
+ symbol->symbol.udata = (void *)NULL;
+ symbol->symbol.section = (asection *)NULL;
+ symbol->symbol.value = (bfd_vma)0;
+ symbol->symbol.flags = BSF_UNDEFINED;
+ if (symbol->index > ieee->external_reference_max_index) {
+ ieee->external_reference_max_index = symbol->index;
+ }
+ BFD_ASSERT (symbol->index >= ieee->external_reference_min_index);
+ break;
+
+ default:
+ loop = false;
+ }
+ }
+
+ if (ieee->external_symbol_max_index != 0) {
+ ieee->external_symbol_count =
+ ieee->external_symbol_max_index -
+ ieee->external_symbol_min_index + 1 ;
+ }
+ else {
+ ieee->external_symbol_count = 0;
+ }
+
+
+ if(ieee->external_reference_max_index != 0) {
+ ieee->external_reference_count =
+ ieee->external_reference_max_index -
+ ieee->external_reference_min_index + 1;
+ }
+ else {
+ ieee->external_reference_count = 0;
+ }
+
+ abfd->symcount =
+ ieee->external_reference_count + ieee->external_symbol_count;
+
+ if (symbol_count != abfd->symcount) {
+ /* There are gaps in the table -- */
+ ieee->symbol_table_full = false;
+ }
+ *prev_symbols_ptr = (ieee_symbol_type *)NULL;
+ *prev_reference_ptr = (ieee_symbol_type *)NULL;
+}
+
+static void
+ieee_slurp_symbol_table(abfd)
+bfd *abfd;
+{
+ if (ieee_data(abfd)->read_symbols == false) {
+ ieee_slurp_external_symbols(abfd);
+ ieee_data(abfd)->read_symbols= true;
+ }
+}
+
+size_t
+ieee_get_symtab_upper_bound (abfd)
+bfd *abfd;
+{
+ ieee_slurp_symbol_table (abfd);
+
+ return (abfd->symcount != 0) ?
+ (abfd->symcount+1) * (sizeof (ieee_symbol_type *)) : 0;
+}
+
+/*
+Move from our internal lists to the canon table, and insert in
+symbol index order
+*/
+
+extern bfd_target ieee_vec;
+unsigned int
+ieee_get_symtab (abfd, location)
+bfd *abfd;
+asymbol **location;
+{
+ ieee_symbol_type *symp;
+ static bfd dummy_bfd;
+ static asymbol empty_symbol =
+ { &dummy_bfd," ieee empty",(symvalue)0,BSF_DEBUGGING | BSF_FAKE};
+
+ ieee_data_type *ieee = ieee_data(abfd);
+ dummy_bfd.xvec= &ieee_vec;
+ ieee_slurp_symbol_table(abfd);
+
+ if (ieee->symbol_table_full == false) {
+ /* Arrgh - there are gaps in the table, run through and fill them */
+ /* up with pointers to a null place */
+ unsigned int i;
+ for (i= 0; i < abfd->symcount; i++) {
+ location[i] = &empty_symbol;
+ }
+ }
+
+
+ ieee->external_symbol_base_offset= - ieee->external_symbol_min_index;
+ for (symp = ieee_data(abfd)->external_symbols;
+ symp != (ieee_symbol_type *)NULL;
+ symp = symp->next) {
+ /* Place into table at correct index locations */
+ location[symp->index + ieee->external_symbol_base_offset] = &symp->symbol;
+
+ }
+
+ /* The external refs are indexed in a bit */
+ ieee->external_reference_base_offset =
+ - ieee->external_reference_min_index +ieee->external_symbol_count ;
+
+ for (symp = ieee_data(abfd)->external_reference;
+ symp != (ieee_symbol_type *)NULL;
+ symp = symp->next) {
+ location[symp->index + ieee->external_reference_base_offset] =
+ &symp->symbol;
+
+ }
+
+
+
+ location[abfd->symcount] = (asymbol *)NULL;
+
+ return abfd->symcount;
+}
+
+
+static void
+ieee_slurp_sections(abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee = ieee_data(abfd);
+ file_ptr offset = ieee->w.r.section_part;
+
+ asection *section = (asection *)NULL;
+
+ if (offset != 0) {
+ bfd_byte section_type[3];
+ ieee_seek(abfd, offset, false);
+ while (true) {
+ switch (this_byte(abfd)) {
+ case ieee_section_type_enum:
+ {
+ unsigned int section_index ;
+ next_byte(abfd);
+ section_index = must_parse_int(abfd);
+ /* Fixme to be nice about a silly number of sections */
+ BFD_ASSERT(section_index < NSECTIONS);
+
+ section = bfd_make_section(abfd, " tempname");
+ ieee->section_table[section_index] = section;
+ section->flags = SEC_NO_FLAGS;
+ section->target_index = section_index;
+ section_type[0] = this_byte_and_next(abfd);
+ switch (section_type[0]) {
+ case 0xC3:
+ section_type[1] = this_byte(abfd);
+ section->flags = SEC_LOAD;
+ switch (section_type[1]) {
+ case 0xD0:
+ /* Normal code */
+ next_byte(abfd);
+ section->flags |= SEC_LOAD | SEC_CODE;
+ break;
+ case 0xC4:
+ next_byte(abfd);
+ section->flags |= SEC_LOAD | SEC_DATA;
+ /* Normal data */
+ break;
+ case 0xD2:
+ next_byte(abfd);
+ /* Normal rom data */
+ section->flags |= SEC_LOAD | SEC_ROM | SEC_DATA;
+ break;
+ default:
+ break;
+ }
+ }
+ section->name = read_id(abfd);
+ { bfd_vma parent, brother, context;
+ parse_int(abfd, &parent);
+ parse_int(abfd, &brother);
+ parse_int(abfd, &context);
+ }
+
+
+ }
+ break;
+ case ieee_section_alignment_enum:
+ {
+ unsigned int section_index;
+ bfd_vma value;
+ next_byte(abfd);
+ section_index = must_parse_int(abfd);
+ if (section_index > ieee->section_count) {
+ ieee->section_count = section_index;
+ }
+ ieee->section_table[section_index]->alignment_power =
+ bfd_log2(must_parse_int(abfd));
+ (void)parse_int(abfd, & value);
+ }
+ break;
+ case ieee_e2_first_byte_enum:
+ {
+ ieee_record_enum_type t = read_2bytes(abfd);
+ switch (t) {
+ case ieee_section_size_enum:
+ section = ieee->section_table[must_parse_int(abfd)];
+ section->size = must_parse_int(abfd);
+ break;
+ case ieee_physical_region_size_enum:
+ section = ieee->section_table[must_parse_int(abfd)];
+ section->size = must_parse_int(abfd);
+ break;
+ case ieee_region_base_address_enum:
+ section = ieee->section_table[must_parse_int(abfd)];
+ section->vma = must_parse_int(abfd);
+ break;
+ case ieee_mau_size_enum:
+ must_parse_int(abfd);
+ must_parse_int(abfd);
+ break;
+ case ieee_m_value_enum:
+ must_parse_int(abfd);
+ must_parse_int(abfd);
+ break;
+ case ieee_section_base_address_enum:
+ section = ieee->section_table[must_parse_int(abfd)];
+ section->vma = must_parse_int(abfd);
+ break;
+ case ieee_section_offset_enum:
+ (void) must_parse_int(abfd);
+ (void) must_parse_int(abfd);
+ break;
+ default:
+ return;
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ }
+ }
+}
+
+/***********************************************************************
+* archive stuff
+*/
+bfd_target *
+ieee_archive_p(abfd)
+bfd *abfd;
+{
+ char *library;
+ boolean loop;
+ ieee_ar_data_type *ar;
+ unsigned int i;
+ ieee_seek(abfd, (file_ptr) 0, false);
+ if (this_byte(abfd) != Module_Beginning) return (bfd_target*)NULL;
+ next_byte(abfd);
+ library= read_id(abfd);
+ if (strcmp(library , "LIBRARY") != 0) {
+ free(library);
+ return (bfd_target *)NULL;
+ }
+ /* Throw away the filename */
+ free( read_id(abfd));
+ /* This must be an IEEE archive, so we'll buy some space to do
+ things */
+ ar = (ieee_ar_data_type *) malloc(sizeof(ieee_ar_data_type));
+ ieee_ar_data(abfd) = ar;
+ ar->element_count = 0;
+ ar->element_index = 0;
+ obstack_init(&ar->element_obstack);
+
+ next_byte(abfd); /* Drop the ad part */
+ must_parse_int(abfd); /* And the two dummy numbers */
+ must_parse_int(abfd);
+
+ loop = true;
+ /* Read the index of the BB table */
+ while (loop) {
+ ieee_ar_obstack_type t;
+ int rec =read_2bytes(abfd);
+ if (rec ==ieee_assign_value_to_variable_enum) {
+ int record_number = must_parse_int(abfd);
+ t.file_offset = must_parse_int(abfd);
+ t.abfd = (bfd *)NULL;
+ ar->element_count++;
+ obstack_grow(&ar->element_obstack, &t, sizeof(t));
+ }
+ else loop = false;
+ }
+ ar->elements = (ieee_ar_obstack_type *)obstack_base(&ar->element_obstack);
+
+ /* Now scan the area again, and replace BB offsets with file */
+ /* offsets */
+
+
+ for (i = 2; i < ar->element_count; i++) {
+ ieee_seek(abfd, ar->elements[i].file_offset, false);
+ next_byte(abfd); /* Drop F8 */
+ next_byte(abfd); /* Drop 14 */
+ must_parse_int(abfd); /* Drop size of block */
+ if (must_parse_int(abfd) != 0) {
+ /* This object has been deleted */
+ ar->elements[i].file_offset = 0;
+ }
+ else {
+ ar->elements[i].file_offset = must_parse_int(abfd);
+ }
+ }
+
+ obstack_finish(&ar->element_obstack);
+ return abfd->xvec;
+}
+
+bfd_target *
+ieee_object_p (abfd)
+bfd *abfd;
+{
+ char *processor;
+ unsigned int part;
+ ieee_data_type ieee;
+ ieee_seek(abfd, (file_ptr)0, false);
+
+
+ if (this_byte(abfd) != Module_Beginning) return (bfd_target*)NULL;
+
+ next_byte(abfd);
+
+ ieee.read_symbols= false;
+ ieee.read_data= false;
+ ieee.section_count = 0;
+ ieee.external_symbol_max_index = 0;
+ ieee.external_symbol_min_index = IEEE_PUBLIC_BASE;
+ ieee.external_reference_min_index =IEEE_REFERENCE_BASE;
+ ieee.external_reference_max_index = 0;
+ memset((PTR)ieee.section_table, 0, sizeof(ieee.section_table));
+
+ processor = ieee.mb.processor = read_id(abfd);
+ if (strcmp(processor,"LIBRARY") == 0) return (bfd_target *)NULL;
+ ieee.mb.module_name = read_id(abfd);
+ if (abfd->filename == (char *)NULL) {
+ abfd->filename = ieee.mb.module_name;
+ }
+ /* Determine the architecture and machine type of the object file. */
+ bfd_scan_arch_mach(processor, &abfd->obj_arch, &abfd->obj_machine);
+
+ if (this_byte(abfd) != ieee_address_descriptor_enum) {
+ return (bfd_target *)NULL;
+ }
+ next_byte(abfd);
+
+ if (parse_int(abfd, &ieee.ad.number_of_bits_mau) == false) {
+ return (bfd_target *)NULL;
+ }
+ if(parse_int(abfd, &ieee.ad.number_of_maus_in_address) == false) {
+ return (bfd_target *)NULL;
+ }
+
+ /* If there is a byte order info, take it */
+ if (this_byte(abfd) == ieee_variable_L_enum ||
+ this_byte(abfd) == ieee_variable_M_enum)
+ next_byte(abfd);
+
+
+ for (part = 0; part < N_W_VARIABLES; part++) {
+ boolean ok;
+ if (read_2bytes(abfd) != ieee_assign_value_to_variable_enum) {
+ return (bfd_target *)NULL;
+ }
+ if (this_byte_and_next(abfd) != part) {
+ return (bfd_target *)NULL;
+ }
+
+
+ ieee.w.offset[part] = parse_i(abfd, &ok);
+ if (ok==false) {
+ return (bfd_target *)NULL;
+ }
+
+ }
+ abfd->flags = HAS_SYMS;
+
+ /* Read in the section info */
+ ieee_data(abfd) = (ieee_data_type *)(malloc(sizeof(ieee_data_type)));
+ memcpy(ieee_data(abfd), &ieee, sizeof(ieee));
+ ieee_slurp_sections(abfd);
+ return abfd->xvec;
+}
+
+
+void
+ieee_print_symbol(ignore_abfd, file, symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+
+ switch (how) {
+ case bfd_print_symbol_name_enum:
+ fprintf(file,"%s", symbol->name);
+ break;
+ case bfd_print_symbol_type_enum:
+#if 0
+ fprintf(file,"%4x %2x",aout_symbol(symbol)->desc & 0xffff,
+ aout_symbol(symbol)->other & 0xff);
+#endif
+ BFD_FAIL();
+ break;
+ case bfd_print_symbol_all_enum:
+ {
+ char *section_name = symbol->section == (asection *)NULL ?
+ "*abs" : symbol->section->name;
+
+ bfd_print_symbol_vandf((void *)file,symbol);
+
+ fprintf(file," %-5s %04x %02x %s",
+ section_name,
+ (unsigned) ieee_symbol(symbol)->index,
+ (unsigned) 0, /*
+ aout_symbol(symbol)->desc & 0xffff,
+ aout_symbol(symbol)->other & 0xff,*/
+ symbol->name);
+ }
+ break;
+ }
+}
+
+
+
+/* Read in all the section data and relocation stuff too */
+static boolean ieee_slurp_section_data(abfd)
+bfd *abfd;
+{
+ bfd_byte *location_ptr ;
+ ieee_data_type *ieee = ieee_data(abfd);
+ unsigned int section_number ;
+
+ ieee_per_section_type *current_map;
+ asection *s;
+ /* Seek to the start of the data area */
+ if (ieee->read_data== true) return true;
+ ieee->read_data = true;
+ ieee_seek(abfd, ieee->w.r.data_part, false);
+
+ /* Allocate enough space for all the section contents */
+
+
+ for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+ ieee_per_section_type *per = s->used_by_bfd;
+ per->data = (bfd_byte *) malloc(s->size);
+ /*SUPPRESS 68*/
+ obstack_init( &per->reloc_obstack);
+ per->reloc_tail_ptr =
+ (ieee_reloc_type **)&(s->relocation);
+ }
+
+
+
+ while (true) {
+ switch (this_byte(abfd))
+ {
+ /* IF we see anything strange then quit */
+ default:
+ return true;
+
+ case ieee_set_current_section_enum:
+ next_byte(abfd);
+ section_number = must_parse_int(abfd);
+ s = ieee->section_table[section_number];
+ current_map = s->used_by_bfd;
+ location_ptr = current_map->data - s->vma;
+ /* The document I have says that Microtec's compilers reset */
+ /* this after a sec section, even though the standard says not */
+ /* to. SO .. */
+ current_map->pc =s->vma;
+ break;
+
+ case ieee_load_constant_bytes_enum:
+ {
+ unsigned int number_of_maus;
+ unsigned int i;
+ next_byte(abfd);
+ number_of_maus = must_parse_int(abfd);
+
+ for (i = 0; i < number_of_maus; i++) {
+ location_ptr[current_map->pc++]= this_byte(abfd);
+ next_byte(abfd);
+ }
+ }
+ break;
+
+ case ieee_e2_first_byte_enum:
+ next_byte(abfd);
+ switch (this_byte(abfd))
+ {
+ case ieee_set_current_pc_enum & 0xff:
+ {
+ bfd_vma value;
+ asection *dsection;
+ ieee_symbol_index_type symbol;
+ unsigned int extra;
+ boolean pcrel;
+ next_byte(abfd);
+ must_parse_int(abfd); /* Thow away section #*/
+ frob(abfd, &value, &dsection, &symbol, &pcrel, &extra);
+ current_map->pc = value;
+ BFD_ASSERT((unsigned)(value - s->vma) < s->size);
+ }
+ break;
+
+ case ieee_value_starting_address_enum & 0xff:
+ /* We've got to the end of the data now - */
+ return true;
+ break;
+ default:
+ BFD_FAIL();
+ return true;
+ }
+ break;
+ case ieee_load_with_relocation_enum:
+ {
+ boolean loop = true;
+ next_byte(abfd);
+ while (loop)
+ {
+ switch (this_byte(abfd))
+ {
+ case ieee_variable_R_enum:
+
+ case ieee_function_signed_open_b_enum:
+ case ieee_function_unsigned_open_b_enum:
+ case ieee_function_either_open_b_enum:
+ {
+ unsigned int extra;
+ boolean pcrel;
+
+ ieee_reloc_type *r =
+ (ieee_reloc_type *)
+ obstack_alloc( &current_map->reloc_obstack,
+ sizeof(ieee_reloc_type));
+
+ *(current_map->reloc_tail_ptr) = r;
+ current_map->reloc_tail_ptr= &r->next;
+ r->next = (ieee_reloc_type *)NULL;
+ next_byte(abfd);
+ frob(abfd,
+ &r->relent.addend,
+ &r->relent.section,
+ &r->symbol,
+ &pcrel,
+ &extra);
+ r->relent.address = current_map->pc;
+ s->reloc_count++;
+ switch (this_byte(abfd)) {
+ case ieee_function_signed_close_b_enum:
+ next_byte(abfd);
+ break;
+ case ieee_function_unsigned_close_b_enum:
+ next_byte(abfd);
+ break;
+ case ieee_function_either_close_b_enum:
+ next_byte(abfd);
+ break;
+ default:
+ break;
+ }
+ /* Build a relocation entry for this type */
+ if (this_byte(abfd) == ieee_comma) {
+
+ next_byte(abfd);
+ /* Fetch number of bytes to pad */
+ extra = must_parse_int(abfd);
+ BFD_FAIL();
+ }
+ switch (extra) {
+ case 0:
+ case 4:
+ location_ptr[current_map->pc++] = 0;
+ location_ptr[current_map->pc++] = 0;
+ location_ptr[current_map->pc++] = 0;
+ location_ptr[current_map->pc++] = 0;
+ r->relent.howto = &abs32_howto;
+ break;
+ case 2:
+ location_ptr[current_map->pc++] = 0;
+ location_ptr[current_map->pc++] = 0;
+ r->relent.howto = &abs16_howto;
+ break;
+
+ default:
+ BFD_FAIL();
+ break;
+ }
+ }
+ break;
+ default:
+ {
+ bfd_vma this_size ;
+ if (parse_int(abfd, &this_size) == true) {
+ unsigned int i;
+ for (i = 0; i < this_size; i++) {
+ location_ptr[current_map->pc ++] = this_byte(abfd);
+ next_byte(abfd);
+ }
+ }
+ else {
+ loop = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+boolean
+ieee_new_section_hook (abfd, newsect)
+bfd *abfd;
+asection *newsect;
+{
+ newsect->used_by_bfd = (ieee_per_section_type *)
+ malloc(sizeof(ieee_per_section_type));
+ ieee_per_section( newsect)->data = (bfd_byte *)NULL;
+ ieee_per_section(newsect)->section = newsect;
+ return true;
+}
+
+
+unsigned int
+ieee_get_reloc_upper_bound (abfd, asect)
+bfd *abfd;
+sec_ptr asect;
+{
+ ieee_slurp_section_data(abfd);
+ return (asect->reloc_count+1) * sizeof(arelent *);
+}
+
+static boolean
+ieee_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void *location;
+file_ptr offset;
+unsigned int count;
+{
+ ieee_per_section_type *p = section->used_by_bfd;
+ ieee_slurp_section_data(abfd);
+ (void) memcpy(location, p->data + offset, count);
+ return true;
+}
+
+
+unsigned int
+ieee_canonicalize_reloc (abfd, section, relptr, symbols)
+bfd *abfd;
+sec_ptr section;
+arelent **relptr;
+asymbol **symbols;
+{
+ ieee_per_section_type *p = section->used_by_bfd;
+ ieee_reloc_type *src = (ieee_reloc_type *)(section->relocation);
+ ieee_data_type *ieee = ieee_data(abfd);
+
+ while (src != (ieee_reloc_type *)NULL) {
+ /* Work out which symbol to attatch it this reloc to */
+ switch (src->symbol.letter) {
+ case 'X':
+ src->relent.sym_ptr_ptr =
+ symbols + src->symbol.index + ieee->external_reference_base_offset;
+ break;
+ case 0:
+ src->relent.sym_ptr_ptr = (asymbol **)NULL;
+ break;
+ default:
+
+ BFD_FAIL();
+ }
+ *relptr++ = &src->relent;
+ src = src->next;
+ }
+ *relptr = (arelent *)NULL;
+ return section->reloc_count;
+}
+
+boolean
+ieee_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+ abfd->obj_arch = arch;
+ abfd->obj_machine = machine;
+ return true;
+}
+
+boolean
+ieee_mkobject(abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee = (ieee_data_type *) malloc(sizeof(ieee_data_type));
+ ieee_data(abfd) = ieee;
+ if (ieee == (ieee_data_type *)NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ return true;
+}
+
+
+static int comp(ap, bp)
+arelent **ap;
+arelent **bp;
+{
+ arelent *a = *ap;
+ arelent *b = *bp;
+ return a->address - b->address;
+}
+/*
+Write the section headers
+*/
+
+static void
+ieee_write_section_part(abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee = ieee_data(abfd);
+ asection *s;
+ ieee->w.r.section_part = bfd_tell(abfd);
+ for (s = abfd->sections; s != (asection *)NULL; s=s->next) {
+ ieee_write_byte(abfd, ieee_section_type_enum);
+ ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+
+ switch (s->flags & (SEC_LOAD | SEC_CODE | SEC_DATA | SEC_ROM)) {
+ case SEC_LOAD | SEC_CODE:
+ /* Normal named section, code */
+ ieee_write_byte(abfd, ieee_variable_C_enum);
+ ieee_write_byte(abfd, ieee_variable_P_enum);
+ break;
+ case SEC_LOAD | SEC_DATA:
+ /* Normal named section, data */
+ ieee_write_byte(abfd, ieee_variable_C_enum);
+ ieee_write_byte(abfd, ieee_variable_D_enum);
+ break;
+ case SEC_LOAD | SEC_DATA | SEC_ROM:
+ /* Normal named section, data rom */
+ ieee_write_byte(abfd, ieee_variable_C_enum);
+ ieee_write_byte(abfd, ieee_variable_R_enum);
+ break;
+ default:
+ ieee_write_byte(abfd, ieee_variable_C_enum);
+ break;
+ }
+
+ ieee_write_id(abfd, s->name);
+ ieee_write_int(abfd, 0); /* Parent */
+ ieee_write_int(abfd, 0); /* Brother */
+ ieee_write_int(abfd, 0); /* Context */
+
+ /* Alignment */
+ ieee_write_byte(abfd, ieee_section_alignment_enum);
+ ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+ ieee_write_int(abfd, 1 << s->alignment_power);
+
+ /* Size */
+ ieee_write_2bytes(abfd, ieee_section_size_enum);
+ ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+ ieee_write_int(abfd, s->size);
+
+ /* Vma */
+ ieee_write_2bytes(abfd, ieee_region_base_address_enum);
+ ieee_write_byte(abfd, s->index + IEEE_SECTION_NUMBER_BASE);
+ ieee_write_int(abfd, s->vma);
+
+ }
+}
+
+
+
+/* write the data in an ieee way */
+static void
+ieee_write_data_part(abfd)
+bfd *abfd;
+{
+ asection *s;
+ ieee_data_type *ieee = ieee_data(abfd);
+ ieee->w.r.data_part = bfd_tell(abfd);
+ for (s = abfd->sections; s != (asection *)NULL; s = s->next)
+ {
+ bfd_byte header[11];
+ bfd_byte *stream = ieee_per_section(s)->data;
+ arelent **p = s->orelocation;
+ size_t current_byte_index = 0;
+ /* Sort the reloc records so we can insert them in the correct places */
+ if (s->reloc_count != 0) {
+ qsort(s->orelocation,
+ s->reloc_count,
+ sizeof(arelent **),
+ comp);
+ }
+
+
+ /* Output the section preheader */
+ header[0] =ieee_set_current_section_enum;
+ header[1] = s->index + IEEE_SECTION_NUMBER_BASE;
+
+ header[2] = ieee_set_current_pc_enum >> 8;
+ header[3]= ieee_set_current_pc_enum & 0xff;
+ header[4] = s->index + IEEE_SECTION_NUMBER_BASE;
+ ieee_write_int5(header+5, s->vma );
+ header[10] = ieee_load_with_relocation_enum;
+ bfd_write(header, 1, sizeof(header), abfd);
+
+ /* Output the data stream as the longest sequence of bytes possible, */
+ /* allowing for the a reasonable packet size and relocation stuffs */
+ if (stream == (void *)NULL) {
+ stream = (bfd_byte *)"UNINITIALIZED AREA! ";
+ s->size = strlen(stream);
+ }
+ while (current_byte_index < s->size) {
+ size_t run;
+ unsigned int MAXRUN = 32;
+ if (p && *p) {
+ run = (*p)->address - current_byte_index;
+ }
+ else {
+ run = MAXRUN;
+ }
+ if (run > s->size - current_byte_index) {
+ run = s->size - current_byte_index;
+ }
+
+ if (run != 0) {
+ /* Output a stream of bytes */
+ bfd_byte header[1] ;
+ header[0]= run;
+ bfd_write(header, 1, sizeof(header), abfd);
+ bfd_write(stream + current_byte_index,
+ 1,
+ run,
+ abfd);
+ current_byte_index += run;
+ }
+ /* Output any relocations here */
+ if (p && (*p) && (*p)->address == current_byte_index) {
+ while ((*p) && (*p)->address == current_byte_index) {
+
+ arelent *r = *p;
+ ieee_write_byte(abfd, ieee_function_either_open_b_enum);
+ if (r->sym_ptr_ptr != (asymbol **)NULL) {
+ ieee_write_expression(abfd, r->addend,
+ r->section,
+ *(r->sym_ptr_ptr));
+ }
+ else {
+ ieee_write_expression(abfd, r->addend,
+ r->section,
+ (asymbol *)NULL);
+ }
+ ieee_write_byte(abfd, ieee_function_either_close_b_enum);
+ p++;
+ }
+ /* FIXME !! Are all relocations 4 bytes ? */
+ current_byte_index += 4;
+ }
+ }
+ }
+}
+
+
+
+
+
+
+static void
+init_for_output(abfd)
+bfd *abfd;
+{
+ asection *s;
+ for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+ if (s->size != 0) {
+ ieee_per_section(s)->data = (bfd_byte *)(malloc(s->size));
+ }
+ }
+}
+
+/** exec and core file sections */
+
+/* set section contents is complicated with IEEE since the format is
+* not a byte image, but a record stream.
+*/
+boolean
+ieee_set_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int count;
+{
+ if (ieee_per_section(section)->data == (bfd_byte *)NULL) {
+ init_for_output(abfd);
+ }
+ (void) memcpy(ieee_per_section(section)->data + offset, location, count);
+ return true;
+}
+
+/*
+write the external symbols of a file, IEEE considers two sorts of
+external symbols, public, and referenced. It uses to internal forms
+to index them as well. When we write them out we turn their symbol
+values into indexes from the right base.
+*/
+static void
+ieee_write_external_part(abfd)
+bfd *abfd;
+{
+ asymbol **q;
+ ieee_data_type *ieee = ieee_data(abfd);
+
+ unsigned int reference_index = IEEE_REFERENCE_BASE;
+ unsigned int public_index = IEEE_PUBLIC_BASE;
+ ieee->w.r.external_part = bfd_tell(abfd);
+ if (abfd->outsymbols != (asymbol **)NULL) {
+ for (q = abfd->outsymbols; *q != (asymbol *)NULL; q++) {
+ asymbol *p = *q;
+ if (p->flags & BSF_UNDEFINED) {
+ /* This must be a symbol reference .. */
+ ieee_write_byte(abfd, ieee_external_reference_enum);
+ ieee_write_int(abfd, reference_index);
+ ieee_write_id(abfd, p->name);
+ p->value = reference_index;
+ reference_index++;
+ }
+ else if(p->flags & BSF_FORT_COMM) {
+ /* This is a weak reference */
+ ieee_write_byte(abfd, ieee_external_reference_enum);
+ ieee_write_int(abfd, reference_index);
+ ieee_write_id(abfd, p->name);
+ ieee_write_byte(abfd, ieee_weak_external_reference_enum);
+ ieee_write_int(abfd, reference_index);
+ ieee_write_int(abfd, p->value);
+ ieee_write_int(abfd, BFD_FORT_COMM_DEFAULT_VALUE);
+ p->value = reference_index;
+ reference_index++;
+ }
+ else if(p->flags & BSF_GLOBAL) {
+ /* This must be a symbol definition */
+
+ ieee_write_byte(abfd, ieee_external_symbol_enum);
+ ieee_write_int(abfd, public_index );
+ ieee_write_id(abfd, p->name);
+
+ /* Write out the value */
+ ieee_write_2bytes(abfd, ieee_value_record_enum);
+ ieee_write_int(abfd, public_index);
+ if (p->section != (asection *)NULL)
+ {
+ ieee_write_expression(abfd,
+ p->value + p->section->output_offset,
+ p->section->output_section,
+ (asymbol *)NULL);
+ }
+ else
+ {
+ ieee_write_expression(abfd,
+ p->value,
+ (asection *)NULL,
+ (asymbol *)NULL);
+ }
+ p->value = public_index;
+ public_index++;
+ }
+ else {
+ /* This can happen - when there are gaps in the symbols read */
+ /* from an input ieee file */
+ }
+ }
+ }
+
+}
+
+static
+void ieee_write_me_part(abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee= ieee_data(abfd);
+ ieee->w.r.me_record = bfd_tell(abfd);
+
+ ieee_write_2bytes(abfd, ieee_value_starting_address_enum);
+ ieee_write_int(abfd, abfd->start_address);
+ ieee_write_byte(abfd, ieee_module_end_enum);
+
+}
+boolean
+ieee_write_object_contents (abfd)
+bfd *abfd;
+{
+ ieee_data_type *ieee = ieee_data(abfd);
+ unsigned int i;
+
+ /* Make a guess about the size of the header */
+ bfd_seek(abfd, 100, false);
+ /*
+ First write the symbols, this changes their values into table
+ indeces so we cant use it after this point
+ */
+ ieee_write_external_part(abfd);
+ ieee_write_byte(abfd, ieee_record_seperator_enum);
+
+ ieee_write_section_part(abfd);
+ ieee_write_byte(abfd, ieee_record_seperator_enum);
+ /*
+ Can only write the data once the symbols have been written since
+ the data contains relocation information which points to the
+ symbols
+ */
+ ieee_write_data_part(abfd);
+ ieee_write_byte(abfd, ieee_record_seperator_enum);
+
+ /*
+ At the end we put the end !
+ */
+ ieee_write_me_part(abfd);
+ /* Now write the header */
+ /* Generate the header */
+ bfd_seek(abfd, (file_ptr)0, false);
+
+
+ ieee_write_byte(abfd, ieee_module_beginning_enum);
+
+ ieee_write_id(abfd, bfd_printable_arch_mach(abfd->obj_arch,
+ abfd->obj_machine));
+ ieee_write_id(abfd, abfd->filename);
+ ieee_write_byte(abfd, ieee_address_descriptor_enum);
+ ieee_write_byte(abfd, 8); /* Bits per MAU */
+ ieee_write_byte(abfd, 4); /* MAU's per address */
+
+
+ for (i= 0; i < N_W_VARIABLES; i++) {
+ ieee_write_2bytes(abfd,ieee_assign_value_to_variable_enum);
+ ieee_write_byte(abfd, i);
+ ieee_write_int(abfd, ieee->w.offset[i]);
+ }
+ return true;
+}
+
+
+
+
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+function exits. We read the strings into a buffer large enough to
+hold them all plus all the cached symbol entries. */
+
+asymbol *
+ieee_make_empty_symbol (abfd)
+bfd *abfd;
+{
+
+ ieee_symbol_type *new =
+ (ieee_symbol_type *)zalloc (sizeof (ieee_symbol_type));
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+
+}
+
+void
+ieee_reclaim_symbol_table (abfd)
+bfd *abfd;
+{
+#if 0
+ asection *section;
+
+ if (!bfd_get_symcount (abfd)) return;
+
+ for (section = abfd->sections; section != NULL; section = section->next)
+ if (section->relocation) {
+ free ((void *)section->relocation);
+ section->relocation = NULL;
+ section->reloc_count = 0;
+ }
+
+ bfd_get_symcount (abfd) = 0;
+ free ((void *)obj_aout_symbols (abfd));
+ obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+#endif
+}
+
+
+
+
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+ieee_get_symcount_upper_bound (abfd)
+bfd *abfd;
+{
+#if 0
+ /* In case we're doing an output file or something...? */
+ if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+ return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+#endif
+return 0;
+}
+
+symindex
+ieee_get_first_symbol (ignore_abfd)
+bfd * ignore_abfd;
+{
+ return 0;
+}
+
+symindex
+ieee_get_next_symbol (abfd, oidx)
+bfd *abfd;
+symindex oidx;
+{
+#if 0
+ if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+ return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS :
+ oidx;
+#endif
+return 0;
+}
+
+char *
+ieee_symbol_name (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ return (obj_aout_symbols (abfd) + idx)->symbol.name;
+#endif
+return 0;
+}
+
+long
+ieee_symbol_value (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ return (obj_aout_symbols (abfd) + idx)->symbol.value;
+#endif
+return 0;
+}
+
+symclass
+ieee_classify_symbol (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+ if ((sym->symbol.flags & BSF_FORT_COMM) != 0) return bfd_symclass_fcommon;
+ if ((sym->symbol.flags & BSF_GLOBAL) != 0) return bfd_symclass_global;
+ if ((sym->symbol.flags & BSF_DEBUGGING) != 0) return bfd_symclass_debugger;
+ if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+#endif
+ return bfd_symclass_unknown;
+}
+
+boolean
+ieee_symbol_hasclass (abfd, idx, class)
+bfd *abfd;
+symindex idx;
+symclass class;
+{
+#if 0
+ aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+ switch (class) {
+ case bfd_symclass_fcommon:
+ return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+ case bfd_symclass_global:
+ return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+ case bfd_symclass_debugger:
+ return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+ case bfd_symclass_undefined:
+ return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+ default: return false;
+ }
+#endif
+return 0;
+}
+
+
+void
+ieee_reclaim_reloc (ignore_abfd, section)
+bfd *ignore_abfd;
+sec_ptr section;
+{
+#if 0
+ if (section->relocation) {
+ free (section->relocation);
+ section->relocation = NULL;
+ section->reloc_count = 0;
+ }
+#endif
+}
+
+boolean
+ieee_close_and_cleanup (abfd)
+bfd *abfd;
+{
+ if (bfd_read_p (abfd) == false)
+ switch (abfd->format) {
+ case bfd_archive:
+ if (!_bfd_write_archive_contents (abfd)) {
+ return false;
+ }
+ break;
+ case bfd_object:
+ if (!ieee_write_object_contents (abfd)) {
+ return false;
+ }
+ break;
+ default:
+ bfd_error = invalid_operation;
+ return false;
+ }
+
+
+ if (ieee_data(abfd) != (ieee_data_type *)NULL) {
+ /* FIXME MORE LEAKS */
+
+ }
+
+ return true;
+}
+
+static bfd *
+ieee_openr_next_archived_file(arch, prev)
+bfd *arch;
+bfd *prev;
+{
+ ieee_ar_data_type *ar = ieee_ar_data(arch);
+ /* take the next one from the arch state, or reset */
+ if (prev == (bfd *)NULL) {
+ /* Reset the index - the first two entries are bogus*/
+ ar->element_index = 2;
+ }
+ while (true) {
+ ieee_ar_obstack_type *p = ar->elements + ar->element_index;
+ ar->element_index++;
+ if (ar->element_index <= ar->element_count) {
+ if (p->file_offset != (file_ptr)0) {
+ if (p->abfd == (bfd *)NULL) {
+ p->abfd = _bfd_create_empty_archive_element_shell(arch);
+ p->abfd->origin = p->file_offset;
+ }
+ return p->abfd;
+ }
+ }
+ else {
+ return (bfd *)NULL;
+ }
+
+ }
+}
+
+static boolean
+ieee_find_nearest_line(abfd,
+ section,
+ symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+ return false;
+
+}
+/*SUPPRESS 460 */
+bfd_target ieee_vec =
+{
+ "ieee", /* name */
+ bfd_target_ieee_flavour_enum,
+ true, /* target byte order */
+ true, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_CODE|SEC_DATA|SEC_ROM
+ |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* valid reloc types */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ ieee_close_and_cleanup, /* _close_and_cleanup */
+ ieee_set_section_contents, /* bfd_set_section_contents */
+ ieee_get_section_contents,
+ ieee_new_section_hook, /* new_section_hook */
+ 0, /* _core_file_failing_command */
+ 0, /* _core_file_failing_signal */
+ 0, /* _core_file_matches_ex...p */
+
+ 0, /* bfd_slurp_bsd_armap, bfd_slurp_armap */
+ bfd_true, /* bfd_slurp_extended_name_table */
+ bfd_bsd_truncate_arname, /* bfd_truncate_arname */
+
+ ieee_get_symtab_upper_bound, /* get_symtab_upper_bound */
+ ieee_get_symtab, /* canonicalize_symtab */
+ 0, /* ieee_reclaim_symbol_table, bfd_reclaim_symbol_table */
+ ieee_get_reloc_upper_bound, /* get_reloc_upper_bound */
+ ieee_canonicalize_reloc, /* bfd_canonicalize_reloc */
+ 0, /* ieee_reclaim_reloc, bfd_reclaim_reloc */
+ 0, /* ieee_get_symcount_upper_bound, bfd_get_symcount_upper_bound */
+ 0, /* ieee_get_first_symbol, bfd_get_first_symbol */
+ 0, /* ieee_get_next_symbol, bfd_get_next_symbol */
+ 0, /* ieee_classify_symbol, bfd_classify_symbol */
+ 0, /* ieee_symbol_hasclass, bfd_symbol_hasclass */
+ 0, /* ieee_symbol_name, bfd_symbol_name */
+ 0, /* ieee_symbol_value, bfd_symbol_value */
+
+ _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+ _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+ {_bfd_dummy_target,
+ ieee_object_p, /* bfd_check_format */
+ ieee_archive_p,
+ bfd_false
+ },
+ {
+ bfd_false,
+ ieee_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ ieee_make_empty_symbol,
+ ieee_print_symbol,
+ bfd_false, /* ieee_get_lineno,*/
+ ieee_set_arch_mach, /* bfd_set_arch_mach,*/
+ bfd_false,
+ ieee_openr_next_archived_file,
+ ieee_find_nearest_line, /* bfd_find_nearest_line */
+};
diff --git a/bfd/libieee.h b/bfd/libieee.h
new file mode 100644
index 0000000000..aefc5fdbb7
--- /dev/null
+++ b/bfd/libieee.h
@@ -0,0 +1,90 @@
+typedef struct {
+ unsigned int index:24;
+ char letter;
+} ieee_symbol_index_type;
+
+typedef struct ieee_symbol_struct {
+ asymbol symbol;
+ struct ieee_symbol_struct *next;
+
+unsigned int index;
+} ieee_symbol_type;
+
+
+typedef struct ieee_reloc_struct {
+ arelent relent;
+ struct ieee_reloc_struct *next;
+ ieee_symbol_index_type symbol;
+
+} ieee_reloc_type;
+
+#define ieee_symbol(x) ((ieee_symbol_type *)(x))
+
+typedef struct ieee_per_section_struct
+{
+ asection *section;
+ bfd_byte *data;
+ bfd_vma offset;
+ struct obstack reloc_obstack;
+ ieee_reloc_type **reloc_tail_ptr;
+bfd_vma pc;
+ /* For output */
+ file_ptr current_pos;
+ unsigned int current_byte;
+ boolean initialized;
+} ieee_per_section_type;
+
+#define ieee_per_section(x) ((ieee_per_section_type *)((x)->used_by_bfd))
+#define NSECTIONS 10
+
+
+
+typedef struct {
+ boolean read_symbols;
+boolean read_data;
+ file_ptr output_cursor;
+ /* Map of section indexes to section ptrs */
+ asection * section_table[NSECTIONS];
+ ieee_address_descriptor_type ad;
+ ieee_module_begin_type mb;
+ ieee_w_variable_type w;
+
+ unsigned int section_count;
+
+ unsigned int map_idx;
+ /* List of GLOBAL EXPORT symbols */
+ ieee_symbol_type *external_symbols;
+ /* List of UNDEFINED symbols */
+ ieee_symbol_type *external_reference;
+
+/* When the symbols have been canonicalized, they are in a
+ * special order, we remember various bases here.. */
+ unsigned int external_symbol_max_index;
+ unsigned int external_symbol_min_index;
+ unsigned int external_symbol_count;
+ int external_symbol_base_offset;
+
+ unsigned int external_reference_max_index;
+ unsigned int external_reference_min_index;
+ unsigned int external_reference_count;
+ int external_reference_base_offset;
+
+
+boolean symbol_table_full;
+} ieee_data_type;
+
+typedef struct {
+ file_ptr file_offset;
+ bfd *abfd;
+} ieee_ar_obstack_type;
+
+typedef struct {
+ ieee_ar_obstack_type *elements;
+ struct obstack element_obstack;
+ unsigned int element_index ;
+ unsigned int element_count;
+} ieee_ar_data_type;
+#define ieee_data(abfd) ((ieee_data_type *)((abfd)->tdata))
+#define ieee_ar_data(abfd) ((ieee_ar_data_type *)((abfd)->tdata))
+
+
diff --git a/bfd/liboasys.h b/bfd/liboasys.h
new file mode 100644
index 0000000000..59e4a89401
--- /dev/null
+++ b/bfd/liboasys.h
@@ -0,0 +1,70 @@
+
+
+typedef struct {
+ asymbol symbol;
+} oasys_symbol_type;
+
+typedef struct oasys_reloc_struct {
+ arelent relent;
+ struct oasys_reloc_struct *next;
+ unsigned int symbol;
+} oasys_reloc_type;
+
+
+#define oasys_symbol(x) ((oasys_symbol_type *)(x))
+#define oasys_per_section(x) ((oasys_per_section_type *)(x->used_by_bfd))
+typedef struct oasys_per_section_struct
+{
+ asection *section;
+ bfd_byte *data;
+ bfd_vma offset;
+
+ oasys_reloc_type **reloc_tail_ptr;
+ bfd_vma pc;
+ /* For output */
+ struct obstack reloc_obstack;
+ file_ptr current_pos;
+ unsigned int current_byte;
+ boolean initialized;
+} oasys_per_section_type;
+
+#define NSECTIONS 10
+
+
+
+
+
+typedef struct {
+ file_ptr file_offset;
+ bfd *abfd;
+} oasys_ar_obstack_type;
+
+
+typedef struct {
+ file_ptr pos;
+ unsigned int size;
+ bfd *abfd;
+char *name;
+
+} oasys_module_info_type;
+
+typedef struct {
+ oasys_module_info_type *module;
+ unsigned int module_count;
+ unsigned int module_index;
+} oasys_ar_data_type;
+
+typedef struct {
+
+ char *strings;
+ asymbol *symbols;
+ unsigned int symbol_string_length;
+ asection *sections[OASYS_MAX_SEC_COUNT];
+ file_ptr first_data_record;
+} oasys_data_type;
+
+#define oasys_data(abfd) ((oasys_data_type *)((abfd)->tdata))
+#define oasys_ar_data(abfd) ((oasys_ar_data_type *)((abfd)->tdata))
+
+
+
diff --git a/bfd/oasys.c b/bfd/oasys.c
new file mode 100644
index 0000000000..c68ce0704e
--- /dev/null
+++ b/bfd/oasys.c
@@ -0,0 +1,985 @@
+/*
+
+ bfd backend for oasys objects.
+
+
+ Object files contain records in order:
+
+ optional header
+ symbol records
+ section records
+ data records
+ debugging records
+ end record
+
+
+
+ Written by Steve Chamberlain
+ steve@cygnus.com
+
+
+
+ */
+
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "oasys.h"
+#include "liboasys.h"
+
+
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+typedef void generic_symbol_type;
+
+
+void DEFUN(oasys_read_record,(abfd, record),
+ bfd *abfd AND
+ oasys_record_union_type *record)
+{
+
+ bfd_read(record, 1, sizeof(record->header), abfd);
+
+ bfd_read(((char *)record )+ sizeof(record->header),
+ 1, record->header.length - sizeof(record->header),
+ abfd);
+}
+static size_t
+oasys_string_length(record)
+oasys_record_union_type *record;
+{
+return record->header.length
+ - ((char *)record->symbol.name - (char *)record);
+}
+
+/*****************************************************************************/
+
+/*
+
+Slurp the symbol table by reading in all the records at the start file
+till we get to the first section record.
+
+We'll sort the symbols into two lists, defined and undefined. The
+undefined symbols will also be sorted by refno. We do this by placing
+all undefined symbols at the front of the table moving in, and the
+defined symbols at the end of the table moving back.
+
+*/
+
+static boolean
+oasys_slurp_symbol_table(abfd)
+bfd *abfd;
+{
+ oasys_record_union_type record;
+ oasys_data_type *data = oasys_data(abfd);
+ boolean loop = true;
+ asymbol *dest_undefined;
+ asymbol *dest_defined;
+ asymbol *dest;
+ char *string_ptr;
+
+
+ if (data->symbols != (asymbol *)NULL) {
+ return true;
+ }
+ /* Buy enough memory for all the symbols and all the names */
+ data->symbols =
+ (asymbol *)malloc(sizeof(asymbol) * abfd->symcount);
+ data->strings = malloc(data->symbol_string_length);
+
+ dest_undefined = data->symbols;
+ dest_defined = data->symbols + abfd->symcount -1;
+
+ string_ptr = data->strings;
+ bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+ while (loop) {
+ oasys_read_record(abfd, &record);
+ switch (record.header.type) {
+ case oasys_record_is_header_enum:
+ break;
+ case oasys_record_is_local_enum:
+ case oasys_record_is_symbol_enum:
+ {
+ size_t length = oasys_string_length(&record);
+ switch (record.symbol.relb[0] & RELOCATION_TYPE_BITS) {
+ case RELOCATION_TYPE_ABS:
+ dest = dest_defined--;
+ dest->section = 0;
+ dest->flags = BSF_ABSOLUTE | BSF_EXPORT | BSF_GLOBAL;
+ dest_defined--;
+ break;
+ case RELOCATION_TYPE_REL:
+ dest = dest_defined--;
+ dest->section =
+ oasys_data(abfd)->sections[record.symbol.relb[0] &
+ RELOCATION_SECT_BITS];
+ if (record.header.type == oasys_record_is_local_enum)
+ {
+ dest->flags = BSF_LOCAL;
+ }
+ else {
+
+ dest->flags = BSF_EXPORT | BSF_GLOBAL;
+ }
+ break;
+ case RELOCATION_TYPE_UND:
+ dest = dest_undefined++;
+ dest->section = (asection *)NULL;
+ dest->flags = BSF_UNDEFINED;
+ break;
+ case RELOCATION_TYPE_COM:
+ dest = dest_defined--;
+ dest->name = string_ptr;
+ dest->the_bfd = abfd;
+
+ dest->section = (asection *)NULL;
+ dest->flags = BSF_FORT_COMM;
+ break;
+ }
+ dest->name = string_ptr;
+ dest->the_bfd = abfd;
+
+ dest->value = bfd_h_getlong(abfd, &record.symbol.value);
+ memcpy(string_ptr, record.symbol.name, length);
+ string_ptr[length] =0;
+ string_ptr += length +1;
+ }
+ break;
+ default:
+ loop = false;
+ }
+ }
+ return true;
+
+}
+
+size_t
+oasys_get_symtab_upper_bound (abfd)
+bfd *abfd;
+{
+ oasys_slurp_symbol_table (abfd);
+
+ return (abfd->symcount != 0) ?
+ (abfd->symcount+1) * (sizeof (oasys_symbol_type *)) : 0;
+}
+
+/*
+*/
+
+extern bfd_target oasys_vec;
+
+unsigned int
+oasys_get_symtab (abfd, location)
+bfd *abfd;
+asymbol **location;
+{
+ asymbol *symbase ;
+ unsigned int counter ;
+ if (oasys_slurp_symbol_table(abfd) == false) {
+ return 0;
+ }
+ symbase = oasys_data(abfd)->symbols;
+ for (counter = 0; counter < abfd->symcount; counter++) {
+ *(location++) = symbase++;
+ }
+ *location = 0;
+ return abfd->symcount;
+}
+
+/***********************************************************************
+* archive stuff
+*/
+#define swap(x) x = bfd_h_get_x(abfd, &x);
+bfd_target *
+oasys_archive_p(abfd)
+bfd *abfd;
+{
+ oasys_archive_header_type header;
+ unsigned int i;
+
+ bfd_seek(abfd, (file_ptr) 0, false);
+
+
+ bfd_read(&header, 1, sizeof(header), abfd);
+
+
+ swap(header.version);
+ swap(header.mod_count);
+ swap(header.mod_tbl_offset);
+ swap(header.sym_tbl_size);
+ swap(header.sym_count);
+ swap(header.sym_tbl_offset);
+ swap(header.xref_count);
+ swap(header.xref_lst_offset);
+
+ /*
+ There isn't a magic number in an Oasys archive, so the best we
+ can do to verify reasnableness is to make sure that the values in
+ the header are too weird
+ */
+
+ if (header.version>10000 ||
+ header.mod_count>10000 ||
+ header.sym_count>100000 ||
+ header.xref_count > 100000) return (bfd_target *)NULL;
+
+ /*
+ That all worked, lets buy the space for the header and read in
+ the headers.
+ */
+ {
+ oasys_ar_data_type *ar =
+ (oasys_ar_data_type*) malloc(sizeof(oasys_ar_data_type));
+
+
+ oasys_module_info_type *module =
+ (oasys_module_info_type*)
+ malloc(sizeof(oasys_module_info_type) * header.mod_count);
+
+ oasys_module_table_type record;
+
+ oasys_ar_data(abfd) =ar;
+ ar->module = module;
+ ar->module_count = header.mod_count;
+
+ bfd_seek(abfd , header.mod_tbl_offset, SEEK_SET);
+ for (i = 0; i < header.mod_count; i++) {
+
+ bfd_read(&record, 1, sizeof(record), abfd);
+ swap(record.mod_size);
+ swap(record.file_offset);
+ swap(record.mod_name_length);
+ module[i].name = malloc(record.mod_name_length+1);
+
+ bfd_read(module[i].name, 1, record.mod_name_length +1, abfd);
+ /* SKip some stuff */
+ bfd_seek(abfd, record.dep_count * sizeof(int32_type),
+ SEEK_CUR);
+
+ module[i].size = record.mod_size;
+ module[i].pos = record.file_offset;
+ }
+
+ }
+ return abfd->xvec;
+}
+
+#define MAX_SECS 16
+bfd_target *
+oasys_object_p (abfd)
+bfd *abfd;
+{
+ oasys_data_type *oasys;
+ oasys_data_type static_data;
+
+ boolean loop = true;
+
+
+ boolean had_usefull = false;
+
+ memset((PTR)static_data.sections, 0xff, sizeof(static_data.sections));
+
+ /* Point to the start of the file */
+ bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+ static_data.symbol_string_length = 0;
+ /* Inspect the records, but only keep the section info -
+ remember the size of the symbols
+ */
+ while (loop) {
+ oasys_record_union_type record;
+ oasys_read_record(abfd, &record);
+
+
+ switch ((oasys_record_enum_type)(record.header.type)) {
+ case oasys_record_is_header_enum:
+ had_usefull = true;
+ break;
+ case oasys_record_is_symbol_enum:
+ case oasys_record_is_local_enum:
+ /* Count symbols and remember their size for a future malloc */
+ abfd->symcount++;
+ static_data.symbol_string_length += 1 + oasys_string_length(&record);
+ had_usefull = true;
+ break;
+ case oasys_record_is_section_enum:
+ {
+ asection *s;
+ char *buffer;
+ unsigned int section_number;
+ if (record.section.header.length != sizeof(record.section))
+ {
+ return (bfd_target *)NULL;
+ }
+ buffer = malloc(3);
+ section_number= record.section.relb & RELOCATION_SECT_BITS;
+ sprintf(buffer,"%u", section_number);
+ s = bfd_make_section(abfd,buffer);
+ static_data.sections[section_number] = s;
+ switch (record.section.relb & RELOCATION_TYPE_BITS) {
+ case RELOCATION_TYPE_ABS:
+ case RELOCATION_TYPE_REL:
+ break;
+ case RELOCATION_TYPE_UND:
+ case RELOCATION_TYPE_COM:
+ BFD_FAIL();
+ }
+
+
+ s->size = bfd_h_getlong(abfd, & record.section.value) ;
+ s->vma = bfd_h_getlong(abfd, &record.section.vma);
+ s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
+ had_usefull = true;
+ }
+ break;
+ case oasys_record_is_data_enum:
+ static_data.first_data_record = bfd_tell(abfd) - record.header.length;
+ case oasys_record_is_debug_enum:
+ case oasys_record_is_module_enum:
+ case oasys_record_is_named_section_enum:
+ case oasys_record_is_end_enum:
+ if (had_usefull == false) return (bfd_target *)NULL;
+ loop = false;
+ break;
+ default:
+ return (bfd_target *)NULL;
+ }
+ }
+ oasys_data(abfd) = (oasys_data_type
+ *)malloc(sizeof(oasys_data_type));
+ oasys = oasys_data(abfd);
+ * oasys = static_data;
+
+ oasys->symbols = (asymbol *)NULL;
+ /*
+ Oasys support several architectures, but I can't see a simple way
+ to discover which one is in a particular file - we'll guess
+ */
+ abfd->obj_arch = bfd_arch_m68k;
+ abfd->obj_machine =0;
+ if (abfd->symcount != 0) {
+ abfd->flags |= HAS_SYMS;
+ }
+ return abfd->xvec;
+}
+
+
+void
+oasys_print_symbol(ignore_abfd, file, symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+ switch (how) {
+ case bfd_print_symbol_name_enum:
+ case bfd_print_symbol_type_enum:
+ fprintf(file,"%s", symbol->name);
+ break;
+ case bfd_print_symbol_all_enum:
+ {
+ char *section_name = symbol->section == (asection *)NULL ?
+ "*abs" : symbol->section->name;
+
+ bfd_print_symbol_vandf((void *)file,symbol);
+
+ fprintf(file," %-5s %s",
+ section_name,
+ symbol->name);
+ }
+ break;
+ }
+}
+/*
+ The howto table is build using the top two bits of a reloc byte to
+ index into it. The bits are PCREL,WORD/LONG
+*/
+static reloc_howto_type howto_table[]=
+{
+/* T rs size bsz pcrel bitpos abs ovr sf name partial inplace mask */
+
+{ 0, 0, 1, 16, false,0, true,true,0,"abs16",true,0x0000ffff},
+{ 0, 0, 2, 32, false,0, true,true,0,"abs32",true,0xffffffff},
+{ 0, 0, 1, 16, true,0, true,true,0,"pcrel16",true,0x0000ffff},
+{ 0, 0, 2, 32, true,0, true,true,0,"pcrel32",true,0xffffffff}
+};
+
+/* Read in all the section data and relocation stuff too */
+static boolean oasys_slurp_section_data(abfd)
+bfd *abfd;
+{
+ oasys_record_union_type record;
+ oasys_data_type *data = oasys_data(abfd);
+ boolean loop = true;
+
+ oasys_per_section_type *per ;
+
+ asection *s;
+
+ /* Buy enough memory for all the section data and relocations */
+ for (s = abfd->sections; s != (asection *)NULL; s= s->next) {
+ per = oasys_per_section(s);
+ if (per->data != (bfd_byte*)NULL) return true;
+ per->data = (bfd_byte *) malloc(s->size);
+ obstack_init(&per->reloc_obstack);
+ per->reloc_tail_ptr = (oasys_reloc_type **)&(s->relocation);
+ }
+
+ bfd_seek(abfd, data->first_data_record, SEEK_SET);
+ while (loop) {
+ oasys_read_record(abfd, &record);
+ switch (record.header.type) {
+ case oasys_record_is_header_enum:
+ break;
+ case oasys_record_is_data_enum:
+ {
+
+ uint8e_type *src = record.data.data;
+ uint8e_type *end_src = ((uint8e_type *)&record) + record.header.length;
+ unsigned int relbit;
+ bfd_byte *dst_ptr ;
+ bfd_byte *dst_base_ptr ;
+ asection *section;
+ unsigned int count;
+
+ bfd_vma dst_offset = bfd_h_getlong(abfd, record.data.addr);
+ section = data->sections[record.data.relb & RELOCATION_SECT_BITS];
+ per = oasys_per_section(section);
+dst_base_ptr = dst_ptr = oasys_per_section(section)->data + dst_offset;
+
+ while (src < end_src) {
+ uint8e_type mod_byte = *src++;
+ count = 8;
+
+ for (relbit = 1; count-- != 0; relbit <<=1)
+ {
+ if (relbit & mod_byte)
+ {
+ uint8e_type reloc = *src;
+ /* This item needs to be relocated */
+ switch (reloc & RELOCATION_TYPE_BITS) {
+ case RELOCATION_TYPE_ABS:
+
+ break;
+
+ case RELOCATION_TYPE_REL:
+ {
+ /* Relocate the item relative to the section */
+ oasys_reloc_type *r =
+ (oasys_reloc_type *)
+ obstack_alloc(&per->reloc_obstack,
+ sizeof(oasys_reloc_type));
+ *(per->reloc_tail_ptr) = r;
+ per->reloc_tail_ptr = &r->next;
+ r->next= (oasys_reloc_type *)NULL;
+ /* Reference to undefined symbol */
+ src++;
+ /* There is no symbol */
+ r->symbol = 0;
+ /* Work out the howto */
+ r->relent.section =
+ data->sections[reloc & RELOCATION_SECT_BITS];
+ r->relent.addend = 0;
+ r->relent.address = dst_ptr - dst_base_ptr;
+ r->relent.howto = &howto_table[reloc>>6];
+ section->reloc_count++;
+
+ }
+ break;
+
+
+ case RELOCATION_TYPE_UND:
+ {
+ oasys_reloc_type *r =
+ (oasys_reloc_type *)
+ obstack_alloc(&per->reloc_obstack,
+ sizeof(oasys_reloc_type));
+ *(per->reloc_tail_ptr) = r;
+ per->reloc_tail_ptr = &r->next;
+ r->next= (oasys_reloc_type *)NULL;
+ /* Reference to undefined symbol */
+ src++;
+ /* Get symbol number */
+ r->symbol = (src[0]<<8) | src[1];
+ /* Work out the howto */
+ r->relent.section = (asection *)NULL;
+ r->relent.addend = 0;
+ r->relent.address = dst_ptr - dst_base_ptr;
+ r->relent.howto = &howto_table[reloc>>6];
+
+ section->reloc_count++;
+ src+=2;
+ }
+ break;
+ case RELOCATION_TYPE_COM:
+ BFD_FAIL();
+ }
+ }
+ *dst_ptr++ = *src++;
+ }
+ }
+ }
+ break;
+ case oasys_record_is_local_enum:
+ case oasys_record_is_symbol_enum:
+ case oasys_record_is_section_enum:
+ break;
+ default:
+ loop = false;
+ }
+ }
+ return true;
+
+}
+
+
+
+
+
+boolean
+oasys_new_section_hook (abfd, newsect)
+bfd *abfd;
+asection *newsect;
+{
+ newsect->used_by_bfd = (oasys_per_section_type *)
+ malloc(sizeof(oasys_per_section_type));
+ oasys_per_section( newsect)->data = (bfd_byte *)NULL;
+ oasys_per_section(newsect)->section = newsect;
+ oasys_per_section(newsect)->offset = 0;
+ return true;
+}
+
+
+unsigned int
+oasys_get_reloc_upper_bound (abfd, asect)
+bfd *abfd;
+sec_ptr asect;
+{
+ oasys_slurp_section_data(abfd);
+ return (asect->reloc_count+1) * sizeof(arelent *);
+}
+
+static boolean
+oasys_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void *location;
+file_ptr offset;
+unsigned int count;
+{
+ oasys_per_section_type *p = section->used_by_bfd;
+ oasys_slurp_section_data(abfd);
+ (void) memcpy(location, p->data + offset, count);
+ return true;
+}
+
+
+unsigned int
+oasys_canonicalize_reloc (abfd, section, relptr, symbols)
+bfd *abfd;
+sec_ptr section;
+arelent **relptr;
+asymbol **symbols;
+{
+ oasys_reloc_type *src = (oasys_reloc_type *)(section->relocation);
+ while (src != (oasys_reloc_type *)NULL) {
+ if (src->relent.section == (asection *)NULL) {
+ src->relent.sym_ptr_ptr = symbols + src->symbol;
+ }
+ *relptr ++ = &src->relent;
+ src = src->next;
+ }
+ *relptr = (arelent *)NULL;
+ return section->reloc_count;
+}
+
+boolean
+oasys_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+ abfd->obj_arch = arch;
+ abfd->obj_machine = machine;
+ return true;
+}
+
+boolean
+oasys_mkobject(abfd)
+bfd *abfd;
+{
+ oasys_data_type *oasys =
+ (oasys_data_type *) malloc(sizeof(oasys_data_type));
+ oasys_data(abfd) = oasys;
+ if (oasys == (oasys_data_type *)NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+static void
+init_for_output(abfd)
+bfd *abfd;
+{
+ asection *s;
+ for (s = abfd->sections; s != (asection *)NULL; s = s->next) {
+ if (s->size != 0) {
+ oasys_per_section(s)->data = (bfd_byte *)(malloc(s->size));
+ }
+ }
+}
+
+/** exec and core file sections */
+
+/* set section contents is complicated with OASYS since the format is
+* not a byte image, but a record stream.
+*/
+boolean
+oasys_set_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int count;
+{
+ if (oasys_per_section(section)->data == (bfd_byte *)NULL) {
+ init_for_output(abfd);
+ }
+ (void) memcpy(oasys_per_section(section)->data + offset, location, count);
+ return true;
+}
+
+
+
+
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+function exits. We read the strings into a buffer large enough to
+hold them all plus all the cached symbol entries. */
+
+asymbol *
+oasys_make_empty_symbol (abfd)
+bfd *abfd;
+{
+
+ oasys_symbol_type *new =
+ (oasys_symbol_type *)zalloc (sizeof (oasys_symbol_type));
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+
+}
+
+void
+oasys_reclaim_symbol_table (abfd)
+bfd *abfd;
+{
+#if 0
+ asection *section;
+
+ if (!bfd_get_symcount (abfd)) return;
+
+ for (section = abfd->sections; section != NULL; section = section->next)
+ if (section->relocation) {
+ free ((void *)section->relocation);
+ section->relocation = NULL;
+ section->reloc_count = 0;
+ }
+
+ bfd_get_symcount (abfd) = 0;
+ free ((void *)obj_aout_symbols (abfd));
+ obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+#endif
+}
+
+
+
+
+/* Obsbolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+oasys_get_symcount_upper_bound (abfd)
+bfd *abfd;
+{
+#if 0
+ /* In case we're doing an output file or something...? */
+ if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+ return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+#endif
+}
+
+symindex
+oasys_get_first_symbol (ignore_abfd)
+bfd * ignore_abfd;
+{
+ return 0;
+}
+
+symindex
+oasys_get_next_symbol (abfd, oidx)
+bfd *abfd;
+symindex oidx;
+{
+#if 0
+ if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+ return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS :
+ oidx;
+#endif
+}
+
+char *
+oasys_symbol_name (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ return (obj_aout_symbols (abfd) + idx)->symbol.name;
+#endif
+}
+
+long
+oasys_symbol_value (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ return (obj_aout_symbols (abfd) + idx)->symbol.value;
+#endif
+}
+
+symclass
+oasys_classify_symbol (abfd, idx)
+bfd *abfd;
+symindex idx;
+{
+#if 0
+ aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+ if ((sym->symbol.flags & BSF_FORT_COMM) != 0) return bfd_symclass_fcommon;
+ if ((sym->symbol.flags & BSF_GLOBAL) != 0) return bfd_symclass_global;
+ if ((sym->symbol.flags & BSF_DEBUGGING) != 0) return bfd_symclass_debugger;
+ if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+#endif
+ return bfd_symclass_unknown;
+}
+
+boolean
+oasys_symbol_hasclass (abfd, idx, class)
+bfd *abfd;
+symindex idx;
+symclass class;
+{
+#if 0
+ aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+ switch (class) {
+ case bfd_symclass_fcommon:
+ return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+ case bfd_symclass_global:
+ return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+ case bfd_symclass_debugger:
+ return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+ case bfd_symclass_undefined:
+ return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+ default: return false;
+ }
+#endif
+}
+
+
+void
+oasys_reclaim_reloc (ignore_abfd, section)
+bfd *ignore_abfd;
+sec_ptr section;
+{
+#if 0
+ if (section->relocation) {
+ free (section->relocation);
+ section->relocation = NULL;
+ section->reloc_count = 0;
+ }
+#endif
+}
+
+boolean
+oasys_close_and_cleanup (abfd)
+bfd *abfd;
+{
+ if (bfd_read_p (abfd) == false)
+ switch (abfd->format) {
+ case bfd_archive:
+ if (!_bfd_write_archive_contents (abfd)) {
+ return false;
+ }
+ break;
+ case bfd_object:
+/* if (!oasys_write_object_contents (abfd)) */{
+ return false;
+ }
+ break;
+ default:
+ bfd_error = invalid_operation;
+ return false;
+ }
+
+
+ if (oasys_data(abfd) != (oasys_data_type *)NULL) {
+ /* FIXME MORE LEAKS */
+
+ }
+
+ return true;
+}
+
+static bfd *
+oasys_openr_next_archived_file(arch, prev)
+bfd *arch;
+bfd *prev;
+{
+ oasys_ar_data_type *ar = oasys_ar_data(arch);
+ oasys_module_info_type *p;
+ /* take the next one from the arch state, or reset */
+ if (prev == (bfd *)NULL) {
+ /* Reset the index - the first two entries are bogus*/
+ ar->module_index = 0;
+ }
+
+ p = ar->module + ar->module_index;
+ ar->module_index++;
+
+ if (ar->module_index <= ar->module_count) {
+ if (p->abfd == (bfd *)NULL) {
+ p->abfd = _bfd_create_empty_archive_element_shell(arch);
+ p->abfd->origin = p->pos;
+ p->abfd->filename = p->name;
+
+ /* Fixup a pointer to this element for the member */
+ p->abfd->arelt_data = (void *)p;
+ }
+ return p->abfd;
+ }
+ else {
+ bfd_error = no_more_archived_files;
+ return (bfd *)NULL;
+ }
+}
+
+static boolean
+oasys_find_nearest_line(abfd,
+ section,
+ symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+ return false;
+
+}
+
+static int
+oasys_stat_arch_elt(abfd, buf)
+bfd *abfd;
+struct stat *buf;
+{
+ oasys_module_info_type *mod = abfd->arelt_data;
+ if (mod == (oasys_module_info_type *)NULL) {
+ bfd_error = invalid_operation;
+ return -1;
+ }
+ else {
+ buf->st_size = mod->size;
+ buf->st_mode = 0666;
+ return 0;
+ }
+
+
+}
+
+
+/*SUPPRESS 460 */
+bfd_target oasys_vec =
+{
+ "oasys", /* name */
+ bfd_target_oasys_flavour_enum,
+ true, /* target byte order */
+ true, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
+ |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* valid reloc types */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ oasys_close_and_cleanup, /* _close_and_cleanup */
+ oasys_set_section_contents, /* bfd_set_section_contents */
+ oasys_get_section_contents,
+ oasys_new_section_hook, /* new_section_hook */
+ 0, /* _core_file_failing_command */
+ 0, /* _core_file_failing_signal */
+ 0, /* _core_file_matches_ex...p */
+
+ 0, /* bfd_slurp_bsd_armap, bfd_slurp_armap */
+ bfd_true, /* bfd_slurp_extended_name_table */
+ bfd_bsd_truncate_arname, /* bfd_truncate_arname */
+
+ oasys_get_symtab_upper_bound, /* get_symtab_upper_bound */
+ oasys_get_symtab, /* canonicalize_symtab */
+ 0, /* oasys_reclaim_symbol_table, bfd_reclaim_symbol_table */
+ oasys_get_reloc_upper_bound, /* get_reloc_upper_bound */
+ oasys_canonicalize_reloc, /* bfd_canonicalize_reloc */
+ 0, /* oasys_reclaim_reloc, bfd_reclaim_reloc */
+ 0, /* oasys_get_symcount_upper_bound, bfd_get_symcount_upper_bound */
+ 0, /* oasys_get_first_symbol, bfd_get_first_symbol */
+ 0, /* oasys_get_next_symbol, bfd_get_next_symbol */
+ 0, /* oasys_classify_symbol, bfd_classify_symbol */
+ 0, /* oasys_symbol_hasclass, bfd_symbol_hasclass */
+ 0, /* oasys_symbol_name, bfd_symbol_name */
+ 0, /* oasys_symbol_value, bfd_symbol_value */
+
+ _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+ _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+ {_bfd_dummy_target,
+ oasys_object_p, /* bfd_check_format */
+ oasys_archive_p,
+ bfd_false
+ },
+ {
+ bfd_false,
+ oasys_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ oasys_make_empty_symbol,
+ oasys_print_symbol,
+ bfd_false, /* oasys_get_lineno,*/
+ oasys_set_arch_mach, /* bfd_set_arch_mach,*/
+ bfd_false,
+ oasys_openr_next_archived_file,
+ oasys_find_nearest_line, /* bfd_find_nearest_line */
+ oasys_stat_arch_elt, /* bfd_stat_arch_elt */
+};
diff --git a/bfd/obstack.c b/bfd/obstack.c
new file mode 100755
index 0000000000..52258d36e8
--- /dev/null
+++ b/bfd/obstack.c
@@ -0,0 +1,335 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program 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 1, or (at your option) any
+later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them. */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+
+ chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (h->chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one.
+
+ The function must be "int" so it can be used in non-ANSI C
+ compilers in a : expression. */
+
+int
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk* old_chunk = h->chunk;
+ register struct _obstack_chunk* new_chunk;
+ register long new_size;
+ register int obj_size = h->next_free - h->object_base;
+ register int i;
+ int already;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (new_size);
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ new_chunk->contents[i] = h->object_base[i];
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+return 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+#ifdef __STDC__
+#undef obstack_free
+void
+obstack_free (struct obstack *h, POINTER obj)
+#else
+int
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+#endif
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ (*h->freefun) ((POINTER) lp);
+ lp = plp;
+ }
+ if (lp)
+ {
+ (h)->object_base = (h)->next_free = (char *)(obj);
+ (h)->chunk_limit = lp->limit;
+ (h)->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* Let same .o link with output of gcc and other compilers. */
+
+#ifdef __STDC__
+int
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ obstack_free (h, obj);
+ return 0;
+}
+#endif
+
+/* #if 0 */
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+
diff --git a/bfd/obstack.h b/bfd/obstack.h
new file mode 100755
index 0000000000..0f3b37c4e0
--- /dev/null
+++ b/bfd/obstack.h
@@ -0,0 +1,416 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program 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 1, or (at your option) any
+later version.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+[Gosper's immortal quote from HAKMEM item 154, out of context] you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' a obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#ifndef __OBSTACKS__
+#define __OBSTACKS__
+
+/* We use subtraction of (char *)0 instead of casting to int
+ because on word-addressable machines a simple cast to int
+ may ignore the byte-within-word field of the pointer. */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ int temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+#ifdef __STDC__
+ void *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+#else
+ char *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+#endif
+ void (*freefun) (); /* User's function to free a chunk. */
+};
+
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+ but before defining the macros. */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+ so we do not declare them. */
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+ Note that this might not be the final address of the object
+ because a new chunk might be needed to hold the final size. */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#define obstack_next_free(h) ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#if defined (__GNUC__) && defined (__STDC__)
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+#define obstack_object_size(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ bcopy (where, __o->next_free, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len + 1) : 0), \
+ bcopy (where, __o->next_free, __len), \
+ __o->next_free += __len, \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, 1) : 0), \
+ *(__o->next_free)++ = (datum); \
+ (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+ and that the data added so far to the current object
+ shares that much alignment. */
+
+#define obstack_ptr_grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, sizeof (void *)) : 0), \
+ *((void **)__o->next_free)++ = ((void *)datum); \
+ (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (int) > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, sizeof (int)) : 0), \
+ *((int *)__o->next_free)++ = ((int)datum); \
+ (void) 0; })
+
+#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->chunk_limit - __o->next_free < __len) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_alloc(OBSTACK,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_finish(OBSTACK) \
+({ struct obstack *__o = (OBSTACK); \
+ void *value = (void *) __o->object_base; \
+ __o->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
+ & ~ (__o->alignment_mask)); \
+ ((__o->next_free - (char *)__o->chunk \
+ > __o->chunk_limit - (char *)__o->chunk) \
+ ? (__o->next_free = __o->chunk_limit) : 0); \
+ __o->object_base = __o->next_free; \
+ value; })
+
+#define obstack_free(OBSTACK, OBJ) \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = __obj; \
+ else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+#define obstack_room(h) \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp + 1) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), 1) : 0), \
+ *((h)->next_free)++ = (datum))
+
+#define obstack_ptr_grow(h,datum) \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), sizeof (char *)) : 0), \
+ *((char **)(h)->next_free)++ = ((char *)datum))
+
+#define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), sizeof (int)) : 0), \
+ *((int *)(h)->next_free)++ = ((int)datum))
+
+#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h) \
+( (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *)(h)->chunk \
+ > (h)->chunk_limit - (char *)(h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#else
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+#ifdef __STDC__
+ extern int _obstack_newchunk (struct obstack *h, int length);
+ extern int _obstack_free (struct obstack *h, void *obj);
+ extern void _obstack_begin (struct obstack *h, int size, int alignment,
+ void *(*chunkfun) (), void (*freefun) ());
+#else
+ extern int _obstack_newchunk ();
+ extern int _obstack_free ();
+ extern void _obstack_begin ();
+#endif
+
+#endif /* not __OBSTACKS__ */
+
OpenPOWER on IntegriCloud