Initial revision
This commit is contained in:
parent
8922ff76e3
commit
87f86b4ec6
6 changed files with 3815 additions and 0 deletions
1919
bfd/ieee.c
Normal file
1919
bfd/ieee.c
Normal file
File diff suppressed because it is too large
Load diff
90
bfd/libieee.h
Normal file
90
bfd/libieee.h
Normal file
|
@ -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))
|
||||
|
||||
|
70
bfd/liboasys.h
Normal file
70
bfd/liboasys.h
Normal file
|
@ -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))
|
||||
|
||||
|
||||
|
985
bfd/oasys.c
Normal file
985
bfd/oasys.c
Normal file
|
@ -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 */
|
||||
};
|
335
bfd/obstack.c
Executable file
335
bfd/obstack.c
Executable file
|
@ -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__ */
|
||||
|
||||
|
416
bfd/obstack.h
Executable file
416
bfd/obstack.h
Executable file
|
@ -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__ */
|
||||
|
Loading…
Reference in a new issue