#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "version.h"
#include "intl.h"
#ifndef __SABER__
#define saber_stop()
#endif
#include "getopt.h"
#ifndef __LINE__
#define __LINE__ 0
#endif
#if defined(__OSF1__) || defined(__OSF__) || defined(__osf__)
#define Size_t long unsigned int
#else
#define Size_t unsigned int
#endif
#define Ptrdiff_t long
extern void pfatal_with_name (const char *) ATTRIBUTE_NORETURN;
extern void botch (const char *) ATTRIBUTE_NORETURN;
extern void fatal (const char *format, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
extern void error (const char *format, ...) ATTRIBUTE_PRINTF_1;
#ifndef MIPS_DEBUGGING_INFO
static int line_number;
static int cur_line_start;
static int debug;
static int had_errors;
static const char *progname;
static const char *input_name;
int
main (void)
{
fprintf (stderr, "Mips-tfile should only be run on a MIPS computer!\n");
exit (1);
}
#else
#undef index
#include <signal.h>
#ifndef CROSS_DIRECTORY_STRUCTURE
#include <a.out.h>
#else
#include "mips/a.out.h"
#endif
#include "gstab.h"
#define STAB_CODE_TYPE enum __stab_debug_code
#ifndef MALLOC_CHECK
#ifdef __SABER__
#define MALLOC_CHECK
#endif
#endif
#define IS_ASM_IDENT(ch) \
(ISIDNUM (ch) || (ch) == '.' || (ch) == '$')
typedef enum sc {
sc_Nil = scNil,
sc_Text = scText,
sc_Data = scData,
sc_Bss = scBss,
sc_Register = scRegister,
sc_Abs = scAbs,
sc_Undefined = scUndefined,
sc_CdbLocal = scCdbLocal,
sc_Bits = scBits,
sc_CdbSystem = scCdbSystem,
sc_RegImage = scRegImage,
sc_Info = scInfo,
sc_UserStruct = scUserStruct,
sc_SData = scSData,
sc_SBss = scSBss,
sc_RData = scRData,
sc_Var = scVar,
sc_Common = scCommon,
sc_SCommon = scSCommon,
sc_VarRegister = scVarRegister,
sc_Variant = scVariant,
sc_SUndefined = scSUndefined,
sc_Init = scInit,
sc_Max = scMax
} sc_t;
typedef enum st {
st_Nil = stNil,
st_Global = stGlobal,
st_Static = stStatic,
st_Param = stParam,
st_Local = stLocal,
st_Label = stLabel,
st_Proc = stProc,
st_Block = stBlock,
st_End = stEnd,
st_Member = stMember,
st_Typedef = stTypedef,
st_File = stFile,
st_RegReloc = stRegReloc,
st_Forward = stForward,
st_StaticProc = stStaticProc,
st_Constant = stConstant,
st_Str = stStr,
st_Number = stNumber,
st_Expr = stExpr,
st_Type = stType,
st_Max = stMax
} st_t;
typedef enum tq {
tq_Nil = tqNil,
tq_Ptr = tqPtr,
tq_Proc = tqProc,
tq_Array = tqArray,
tq_Far = tqFar,
tq_Vol = tqVol,
tq_Max = tqMax
} tq_t;
typedef enum bt {
bt_Nil = btNil,
bt_Adr = btAdr,
bt_Char = btChar,
bt_UChar = btUChar,
bt_Short = btShort,
bt_UShort = btUShort,
bt_Int = btInt,
bt_UInt = btUInt,
bt_Long = btLong,
bt_ULong = btULong,
bt_Float = btFloat,
bt_Double = btDouble,
bt_Struct = btStruct,
bt_Union = btUnion,
bt_Enum = btEnum,
bt_Typedef = btTypedef,
bt_Range = btRange,
bt_Set = btSet,
bt_Complex = btComplex,
bt_DComplex = btDComplex,
bt_Indirect = btIndirect,
bt_FixedDec = btFixedDec,
bt_FloatDec = btFloatDec,
bt_String = btString,
bt_Bit = btBit,
bt_Picture = btPicture,
#ifdef btVoid
bt_Void = btVoid,
#else
#define bt_Void bt_Nil
#endif
bt_Max = btMax
} bt_t;
enum coff_storage {
C_EFCN = -1,
C_NULL = 0,
C_AUTO = 1,
C_EXT = 2,
C_STAT = 3,
C_REG = 4,
C_EXTDEF = 5,
C_LABEL = 6,
C_ULABEL = 7,
C_MOS = 8,
C_ARG = 9,
C_STRTAG = 10,
C_MOU = 11,
C_UNTAG = 12,
C_TPDEF = 13,
C_USTATIC = 14,
C_ENTAG = 15,
C_MOE = 16,
C_REGPARM = 17,
C_FIELD = 18,
C_BLOCK = 100,
C_FCN = 101,
C_EOS = 102,
C_FILE = 103,
C_LINE = 104,
C_ALIAS = 105,
C_HIDDEN = 106,
C_MAX = 107
} coff_storage_t;
typedef enum coff_type {
T_NULL = 0,
T_ARG = 1,
T_CHAR = 2,
T_SHORT = 3,
T_INT = 4,
T_LONG = 5,
T_FLOAT = 6,
T_DOUBLE = 7,
T_STRUCT = 8,
T_UNION = 9,
T_ENUM = 10,
T_MOE = 11,
T_UCHAR = 12,
T_USHORT = 13,
T_UINT = 14,
T_ULONG = 15,
T_MAX = 16
} coff_type_t;
typedef enum coff_dt {
DT_NON = 0,
DT_PTR = 1,
DT_FCN = 2,
DT_ARY = 3,
DT_MAX = 4
} coff_dt_t;
#define N_BTMASK 017
#define N_TMASK 003
#define N_BT_SHIFT 4
#define N_TQ_SHIFT 2
#define N_TQ 6
typedef enum hash_state {
hash_no = 0,
hash_yes = 1,
hash_record = 2
} hash_state_t;
enum alloc_type {
alloc_type_none,
alloc_type_scope,
alloc_type_vlinks,
alloc_type_shash,
alloc_type_thash,
alloc_type_tag,
alloc_type_forward,
alloc_type_thead,
alloc_type_varray,
alloc_type_last
};
#define WORD_ALIGN(x) (((x) + (sizeof (long) - 1)) & ~ (sizeof (long) - 1))
#define DWORD_ALIGN(x) (((x) + 7) & ~7)
#ifndef PAGE_SIZE
#define PAGE_SIZE 32768
#endif
#define PAGE_USIZE ((Size_t) PAGE_SIZE)
#ifndef MAX_CLUSTER_PAGES
#ifndef USE_MALLOC
#define MAX_CLUSTER_PAGES 64
#else
#define MAX_CLUSTER_PAGES 63
#endif
#endif
typedef struct vlinks {
struct vlinks *prev;
struct vlinks *next;
union page *datum;
unsigned long start_index;
} vlinks_t;
typedef struct varray {
vlinks_t *first;
vlinks_t *last;
unsigned long num_allocated;
unsigned short object_size;
unsigned short objects_per_page;
unsigned short objects_last_page;
} varray_t;
#ifndef MALLOC_CHECK
#define OBJECTS_PER_PAGE(type) (PAGE_SIZE / sizeof (type))
#else
#define OBJECTS_PER_PAGE(type) ((sizeof (type) > 1) ? 1 : PAGE_SIZE)
#endif
#define INIT_VARRAY(type) { \
(vlinks_t *) 0, \
(vlinks_t *) 0, \
0, \
sizeof (type), \
OBJECTS_PER_PAGE (type), \
OBJECTS_PER_PAGE (type), \
}
#define INITIALIZE_VARRAY(x,type) \
do { \
(x)->object_size = sizeof (type); \
(x)->objects_per_page = OBJECTS_PER_PAGE (type); \
(x)->objects_last_page = OBJECTS_PER_PAGE (type); \
} while (0)
typedef unsigned long symint_t;
typedef struct scope {
struct scope *prev;
struct scope *free;
SYMR *lsym;
symint_t lnumber;
st_t type;
} scope_t;
typedef struct forward {
struct forward *next;
struct forward *free;
AUXU *ifd_ptr;
AUXU *index_ptr;
AUXU *type_ptr;
} forward_t;
typedef struct tag {
struct tag *free;
struct shash *hash_ptr;
struct tag *same_name;
struct tag *same_block;
struct forward *forward_ref;
bt_t basic_type;
symint_t ifd;
symint_t indx;
} tag_t;
typedef struct thead {
struct thead *prev;
struct thead *free;
struct tag *first_tag;
} thead_t;
typedef union small_free {
scope_t *f_scope;
thead_t *f_thead;
tag_t *f_tag;
forward_t *f_forward;
} small_free_t;
#ifndef SHASH_SIZE
#define SHASH_SIZE 1009
#endif
#define HASH_LEN_MAX ((1 << 12) - 1)
typedef struct shash {
struct shash *next;
char *string;
symint_t len;
symint_t indx;
EXTR *esym_ptr;
SYMR *sym_ptr;
SYMR *end_ptr;
tag_t *tag_ptr;
PDR *proc_ptr;
} shash_t;
#ifndef THASH_SIZE
#define THASH_SIZE 113
#endif
typedef struct thash {
struct thash *next;
AUXU type;
symint_t indx;
} thash_t;
typedef struct efdr {
FDR fdr;
FDR *orig_fdr;
char *name;
int name_len;
symint_t void_type;
symint_t int_type;
scope_t *cur_scope;
symint_t file_index;
int nested_scopes;
varray_t strings;
varray_t symbols;
varray_t procs;
varray_t aux_syms;
struct efdr *next_file;
shash_t **shash_head;
thash_t *thash_head[THASH_SIZE];
} efdr_t;
static int init_file_initialized = 0;
static efdr_t init_file;
static efdr_t *first_file;
static efdr_t **last_file_ptr = &first_file;
typedef union page {
char byte [ PAGE_SIZE ];
unsigned char ubyte [ PAGE_SIZE ];
efdr_t file [ PAGE_SIZE / sizeof (efdr_t) ];
FDR ofile [ PAGE_SIZE / sizeof (FDR) ];
PDR proc [ PAGE_SIZE / sizeof (PDR) ];
SYMR sym [ PAGE_SIZE / sizeof (SYMR) ];
EXTR esym [ PAGE_SIZE / sizeof (EXTR) ];
AUXU aux [ PAGE_SIZE / sizeof (AUXU) ];
DNR dense [ PAGE_SIZE / sizeof (DNR) ];
scope_t scope [ PAGE_SIZE / sizeof (scope_t) ];
vlinks_t vlinks [ PAGE_SIZE / sizeof (vlinks_t) ];
shash_t shash [ PAGE_SIZE / sizeof (shash_t) ];
thash_t thash [ PAGE_SIZE / sizeof (thash_t) ];
tag_t tag [ PAGE_SIZE / sizeof (tag_t) ];
forward_t forward [ PAGE_SIZE / sizeof (forward_t) ];
thead_t thead [ PAGE_SIZE / sizeof (thead_t) ];
} page_t;
typedef struct alloc_info {
const char *alloc_name;
page_t *cur_page;
small_free_t free_list;
int unallocated;
int total_alloc;
int total_free;
int total_pages;
} alloc_info_t;
typedef struct type_info {
bt_t basic_type;
coff_type_t orig_type;
int num_tq;
int num_dims;
int num_sizes;
int extra_sizes;
tag_t * tag_ptr;
int bitfield;
int unknown_tag;
tq_t type_qualifiers[N_TQ];
symint_t dimensions [N_TQ];
symint_t sizes [N_TQ+2];
} type_info_t;
static type_info_t type_info_init = {
bt_Nil,
T_NULL,
0,
0,
0,
0,
NULL,
0,
0,
{
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
tq_Nil,
},
{
0,
0,
0,
0,
0,
0
},
{
0,
0,
0,
0,
0,
0,
0,
0,
},
};
static varray_t file_desc = INIT_VARRAY (efdr_t);
static varray_t dense_num = INIT_VARRAY (DNR);
static varray_t tag_strings = INIT_VARRAY (char);
static varray_t ext_strings = INIT_VARRAY (char);
static varray_t ext_symbols = INIT_VARRAY (EXTR);
static shash_t *orig_str_hash[SHASH_SIZE];
static shash_t *ext_str_hash [SHASH_SIZE];
static shash_t *tag_hash [SHASH_SIZE];
static type_info_t int_type_info;
static type_info_t void_type_info;
static type_info_t last_func_type_info;
static EXTR *last_func_eptr;
static const bt_t map_coff_types[ (int) T_MAX ] = {
bt_Nil,
bt_Nil,
bt_Char,
bt_Short,
bt_Int,
bt_Long,
bt_Float,
bt_Double,
bt_Struct,
bt_Union,
bt_Enum,
bt_Enum,
bt_UChar,
bt_UShort,
bt_UInt,
bt_ULong
};
static const sc_t map_coff_storage[ (int) C_MAX ] = {
sc_Nil,
sc_Abs,
sc_Undefined,
sc_Data,
sc_Register,
sc_Undefined,
sc_Text,
sc_Text,
sc_Info,
sc_Abs,
sc_Info,
sc_Info,
sc_Info,
sc_Info,
sc_Data,
sc_Info,
sc_Info,
sc_Register,
sc_Bits,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Text,
sc_Text,
sc_Info,
sc_Nil,
sc_Nil,
sc_Nil,
sc_Nil,
};
static const st_t map_coff_sym_type[ (int) C_MAX ] = {
st_Nil,
st_Local,
st_Global,
st_Static,
st_Local,
st_Global,
st_Label,
st_Label,
st_Member,
st_Param,
st_Block,
st_Member,
st_Block,
st_Typedef,
st_Static,
st_Block,
st_Member,
st_Param,
st_Member,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Nil,
st_Block,
st_Proc,
st_End,
st_File,
st_Nil,
st_Nil,
st_Nil,
};
static const tq_t map_coff_derived_type[ (int) DT_MAX ] = {
tq_Nil,
tq_Ptr,
tq_Proc,
tq_Array,
};
static alloc_info_t alloc_counts[ (int) alloc_type_last ];
static struct filehdr orig_file_header;
static HDRR orig_sym_hdr;
static char *orig_linenum;
static DNR *orig_dense;
static PDR *orig_procs;
static SYMR *orig_local_syms;
static OPTR *orig_opt_syms;
static AUXU *orig_aux_syms;
static char *orig_local_strs;
static char *orig_ext_strs;
static FDR *orig_files;
static symint_t *orig_rfds;
static EXTR *orig_ext_syms;
#define CHECK(num,max,str) \
(((unsigned long) num > (unsigned long) max) ? out_of_bounds (num, max, str, __LINE__) : 0)
#define ORIG_LINENUM(indx) (CHECK ((indx), orig_sym_hdr.cbLine, "line#"), (indx) + orig_linenum)
#define ORIG_DENSE(indx) (CHECK ((indx), orig_sym_hdr.idnMax, "dense"), (indx) + orig_dense)
#define ORIG_PROCS(indx) (CHECK ((indx), orig_sym_hdr.ipdMax, "procs"), (indx) + orig_procs)
#define ORIG_FILES(indx) (CHECK ((indx), orig_sym_hdr.ifdMax, "funcs"), (indx) + orig_files)
#define ORIG_LSYMS(indx) (CHECK ((indx), orig_sym_hdr.isymMax, "lsyms"), (indx) + orig_local_syms)
#define ORIG_LSTRS(indx) (CHECK ((indx), orig_sym_hdr.issMax, "lstrs"), (indx) + orig_local_strs)
#define ORIG_ESYMS(indx) (CHECK ((indx), orig_sym_hdr.iextMax, "esyms"), (indx) + orig_ext_syms)
#define ORIG_ESTRS(indx) (CHECK ((indx), orig_sym_hdr.issExtMax, "estrs"), (indx) + orig_ext_strs)
#define ORIG_OPT(indx) (CHECK ((indx), orig_sym_hdr.ioptMax, "opt"), (indx) + orig_opt_syms)
#define ORIG_AUX(indx) (CHECK ((indx), orig_sym_hdr.iauxMax, "aux"), (indx) + orig_aux_syms)
#define ORIG_RFDS(indx) (CHECK ((indx), orig_sym_hdr.crfd, "rfds"), (indx) + orig_rfds)
static HDRR symbolic_header;
static efdr_t *cur_file_ptr = (efdr_t *) 0;
static PDR *cur_proc_ptr = (PDR *) 0;
static SYMR *cur_oproc_begin = (SYMR *) 0;
static SYMR *cur_oproc_end = (SYMR *) 0;
static PDR *cur_oproc_ptr = (PDR *) 0;
static thead_t *cur_tag_head = (thead_t *) 0;
static unsigned long file_offset = 0;
static unsigned long max_file_offset = 0;
static FILE *object_stream = (FILE *) 0;
static FILE *obj_in_stream = (FILE *) 0;
static char *progname = (char *) 0;
static const char *input_name = "stdin";
static char *object_name = (char *) 0;
static char *obj_in_name = (char *) 0;
static char *cur_line_start = (char *) 0;
static char *cur_line_ptr = (char *) 0;
static unsigned cur_line_nbytes = 0;
static unsigned cur_line_alloc = 0;
static long line_number = 0;
static int debug = 0;
static int version = 0;
static int verbose = 0;
static int had_errors = 0;
static int rename_output = 0;
static int delete_input = 0;
static int stabs_seen = 0;
#ifndef STABS_SYMBOL
#define STABS_SYMBOL "@stabs"
#endif
static const char stabs_symbol[] = STABS_SYMBOL;
#ifndef STATIC
#define STATIC static
#endif
STATIC int out_of_bounds (symint_t, symint_t, const char *, int);
STATIC shash_t *hash_string (const char *, Ptrdiff_t, shash_t **, symint_t *);
STATIC symint_t add_string (varray_t *, shash_t **, const char *, const char *,
shash_t **);
STATIC symint_t add_local_symbol (const char *, const char *, st_t, sc_t,
symint_t, symint_t);
STATIC symint_t add_ext_symbol (EXTR *, int);
STATIC symint_t add_aux_sym_symint (symint_t);
STATIC symint_t add_aux_sym_rndx (int, symint_t);
STATIC symint_t add_aux_sym_tir (type_info_t *, hash_state_t, thash_t **);
STATIC tag_t * get_tag (const char *, const char *, symint_t, bt_t);
STATIC void add_unknown_tag (tag_t *);
STATIC void add_procedure (const char *, const char *);
STATIC void initialize_init_file (void);
STATIC void add_file (const char *, const char *);
STATIC void add_bytes (varray_t *, char *, Size_t);
STATIC void add_varray_page (varray_t *);
STATIC void update_headers (void);
STATIC void write_varray (varray_t *, off_t, const char *);
STATIC void write_object (void);
STATIC const char *st_to_string (st_t);
STATIC const char *sc_to_string (sc_t);
STATIC char *read_line (void);
STATIC void parse_input (void);
STATIC void mark_stabs (const char *);
STATIC void parse_begin (const char *);
STATIC void parse_bend (const char *);
STATIC void parse_def (const char *);
STATIC void parse_end (const char *);
STATIC void parse_ent (const char *);
STATIC void parse_file (const char *);
STATIC void parse_stabs_common (const char *, const char *, const char *);
STATIC void parse_stabs (const char *);
STATIC void parse_stabn (const char *);
STATIC page_t *read_seek (Size_t, off_t, const char *);
STATIC void copy_object (void);
STATIC void catch_signal (int) ATTRIBUTE_NORETURN;
STATIC page_t *allocate_page (void);
STATIC page_t *allocate_multiple_pages (Size_t);
STATIC void free_multiple_pages (page_t *, Size_t);
#ifndef MALLOC_CHECK
STATIC page_t *allocate_cluster (Size_t);
#endif
STATIC forward_t *allocate_forward (void);
STATIC scope_t *allocate_scope (void);
STATIC shash_t *allocate_shash (void);
STATIC tag_t *allocate_tag (void);
STATIC thash_t *allocate_thash (void);
STATIC thead_t *allocate_thead (void);
STATIC vlinks_t *allocate_vlinks (void);
STATIC void free_forward (forward_t *);
STATIC void free_scope (scope_t *);
STATIC void free_tag (tag_t *);
STATIC void free_thead (thead_t *);
extern char *optarg;
extern int optind;
extern int opterr;
typedef struct _pseudo_ops {
const char *const name;
const int len;
void (*const func) (const char *);
} pseudo_ops_t;
static const pseudo_ops_t pseudo_ops[] = {
{ "#.def", sizeof("#.def")-1, parse_def },
{ "#.begin", sizeof("#.begin")-1, parse_begin },
{ "#.bend", sizeof("#.bend")-1, parse_bend },
{ ".end", sizeof(".end")-1, parse_end },
{ ".ent", sizeof(".ent")-1, parse_ent },
{ ".file", sizeof(".file")-1, parse_file },
{ "#.stabs", sizeof("#.stabs")-1, parse_stabs },
{ "#.stabn", sizeof("#.stabn")-1, parse_stabn },
{ ".stabs", sizeof(".stabs")-1, parse_stabs },
{ ".stabn", sizeof(".stabn")-1, parse_stabn },
{ "#@stabs", sizeof("#@stabs")-1, mark_stabs },
};
static const struct option options[] =
{
{ "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' },
{ 0, 0, 0, 0 }
};
STATIC void
add_varray_page (varray_t *vp)
{
vlinks_t *new_links = allocate_vlinks ();
#ifdef MALLOC_CHECK
if (vp->object_size > 1)
new_links->datum = xcalloc (1, vp->object_size);
else
#endif
new_links->datum = allocate_page ();
alloc_counts[ (int) alloc_type_varray ].total_alloc++;
alloc_counts[ (int) alloc_type_varray ].total_pages++;
new_links->start_index = vp->num_allocated;
vp->objects_last_page = 0;
if (vp->first == (vlinks_t *) 0)
vp->first = vp->last = new_links;
else
{
new_links->prev = vp->last;
vp->last->next = new_links;
vp->last = new_links;
}
}
#define HASHBITS 30
STATIC shash_t *
hash_string (const char *text, Ptrdiff_t hash_len, shash_t **hash_tbl,
symint_t *ret_hash_index)
{
unsigned long hi;
Ptrdiff_t i;
shash_t *ptr;
int first_ch = *text;
hi = hash_len;
for (i = 0; i < hash_len; i++)
hi = ((hi & 0x003fffff) * 613) + (text[i] & 0xff);
hi &= (1 << HASHBITS) - 1;
hi %= SHASH_SIZE;
if (ret_hash_index != (symint_t *) 0)
*ret_hash_index = hi;
for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
if ((symint_t) hash_len == ptr->len
&& first_ch == ptr->string[0]
&& memcmp (text, ptr->string, hash_len) == 0)
break;
return ptr;
}
STATIC symint_t
add_string (varray_t *vp, shash_t **hash_tbl, const char *start,
const char *end_p1, shash_t **ret_hash)
{
Ptrdiff_t len = end_p1 - start;
shash_t *hash_ptr;
symint_t hi;
if (len >= (Ptrdiff_t) PAGE_USIZE)
fatal ("string too big (%ld bytes)", (long) len);
hash_ptr = hash_string (start, len, hash_tbl, &hi);
if (hash_ptr == (shash_t *) 0)
{
char *p;
if (vp->objects_last_page + len >= (long) PAGE_USIZE)
{
vp->num_allocated
= ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
add_varray_page (vp);
}
hash_ptr = allocate_shash ();
hash_ptr->next = hash_tbl[hi];
hash_tbl[hi] = hash_ptr;
hash_ptr->len = len;
hash_ptr->indx = vp->num_allocated;
hash_ptr->string = p = & vp->last->datum->byte[ vp->objects_last_page ];
vp->objects_last_page += len+1;
vp->num_allocated += len+1;
while (len-- > 0)
*p++ = *start++;
*p = '\0';
}
if (ret_hash != (shash_t **) 0)
*ret_hash = hash_ptr;
return hash_ptr->indx;
}
STATIC symint_t
add_local_symbol (const char *str_start, const char *str_end_p1, st_t type,
sc_t storage, symint_t value, symint_t indx)
{
symint_t ret;
SYMR *psym;
scope_t *pscope;
thead_t *ptag_head;
tag_t *ptag;
tag_t *ptag_next;
varray_t *vp = &cur_file_ptr->symbols;
int scope_delta = 0;
shash_t *hash_ptr = (shash_t *) 0;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
psym->value = value;
psym->st = (unsigned) type;
psym->sc = (unsigned) storage;
psym->index = indx;
psym->iss = (str_start == (const char *) 0)
? 0
: add_string (&cur_file_ptr->strings,
&cur_file_ptr->shash_head[0],
str_start,
str_end_p1,
&hash_ptr);
ret = vp->num_allocated++;
if (MIPS_IS_STAB (psym))
return ret;
if (hash_ptr != (shash_t *) 0
&& (type == st_Global || type == st_Static || type == st_Label
|| type == st_Proc || type == st_StaticProc))
hash_ptr->sym_ptr = psym;
switch (type)
{
default:
break;
case st_File:
case st_Proc:
case st_StaticProc:
case st_Block:
pscope = allocate_scope ();
pscope->prev = cur_file_ptr->cur_scope;
pscope->lsym = psym;
pscope->lnumber = ret;
pscope->type = type;
cur_file_ptr->cur_scope = pscope;
if (type != st_File)
scope_delta = 1;
if (type != st_File && storage != sc_Info)
{
ptag_head = allocate_thead ();
ptag_head->first_tag = 0;
ptag_head->prev = cur_tag_head;
cur_tag_head = ptag_head;
}
break;
case st_End:
pscope = cur_file_ptr->cur_scope;
if (pscope == (scope_t *) 0)
error ("internal error, too many st_End's");
else
{
st_t begin_type = (st_t) pscope->lsym->st;
if (begin_type != st_File)
scope_delta = -1;
if (begin_type != st_File && storage != sc_Info)
{
ptag_head = cur_tag_head;
cur_tag_head = ptag_head->prev;
for (ptag = ptag_head->first_tag;
ptag != (tag_t *) 0;
ptag = ptag_next)
{
if (ptag->forward_ref != (forward_t *) 0)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
ptag->hash_ptr->tag_ptr = ptag->same_name;
free_tag (ptag);
}
free_thead (ptag_head);
}
cur_file_ptr->cur_scope = pscope->prev;
psym->index = pscope->lnumber;
if (storage != sc_Info)
psym->iss = pscope->lsym->iss;
if (begin_type == st_File || begin_type == st_Block)
pscope->lsym->index = ret+1;
else
{
symint_t type;
pscope->lsym->index = add_aux_sym_symint (ret+1);
type = add_aux_sym_tir (&last_func_type_info,
hash_no,
&cur_file_ptr->thash_head[0]);
if (last_func_eptr)
{
last_func_eptr->ifd = cur_file_ptr->file_index;
last_func_eptr->asym.index = psym->index;
}
}
free_scope (pscope);
}
}
cur_file_ptr->nested_scopes += scope_delta;
if (debug && type != st_File
&& (debug > 2 || type == st_Block || type == st_End
|| type == st_Proc || type == st_StaticProc))
{
const char *sc_str = sc_to_string (storage);
const char *st_str = st_to_string (type);
int depth = cur_file_ptr->nested_scopes + (scope_delta < 0);
fprintf (stderr,
"\tlsym\tv= %10ld, depth= %2d, sc= %-12s",
value, depth, sc_str);
if (str_start && str_end_p1 - str_start > 0)
fprintf (stderr, " st= %-11s name= %.*s\n",
st_str, (int) (str_end_p1 - str_start), str_start);
else
{
Size_t len = strlen (st_str);
fprintf (stderr, " st= %.*s\n", (int) (len-1), st_str);
}
}
return ret;
}
STATIC symint_t
add_ext_symbol (EXTR *esym, int ifd)
{
const char *str_start;
const char *str_end_p1;
EXTR *psym;
varray_t *vp = &ext_symbols;
shash_t *hash_ptr = (shash_t *) 0;
str_start = ORIG_ESTRS (esym->asym.iss);
str_end_p1 = str_start + strlen (str_start);
if (debug > 1)
{
long value = esym->asym.value;
const char *sc_str = sc_to_string (esym->asym.sc);
const char *st_str = st_to_string (esym->asym.st);
fprintf (stderr,
"\tesym\tv= %10ld, ifd= %2d, sc= %-12s",
value, ifd, sc_str);
if (str_start && str_end_p1 - str_start > 0)
fprintf (stderr, " st= %-11s name= %.*s\n",
st_str, (int) (str_end_p1 - str_start), str_start);
else
fprintf (stderr, " st= %s\n", st_str);
}
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
psym = &vp->last->datum->esym[ vp->objects_last_page++ ];
*psym = *esym;
psym->ifd = ifd;
psym->asym.index = indexNil;
psym->asym.iss = (str_start == (const char *) 0)
? 0
: add_string (&ext_strings,
&ext_str_hash[0],
str_start,
str_end_p1,
&hash_ptr);
hash_ptr->esym_ptr = psym;
return vp->num_allocated++;
}
STATIC symint_t
add_aux_sym_symint (symint_t aux_word)
{
AUXU *aux_ptr;
efdr_t *file_ptr = cur_file_ptr;
varray_t *vp = &file_ptr->aux_syms;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
aux_ptr->isym = aux_word;
return vp->num_allocated++;
}
STATIC symint_t
add_aux_sym_rndx (int file_index, symint_t sym_index)
{
AUXU *aux_ptr;
efdr_t *file_ptr = cur_file_ptr;
varray_t *vp = &file_ptr->aux_syms;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
aux_ptr->rndx.rfd = file_index;
aux_ptr->rndx.index = sym_index;
return vp->num_allocated++;
}
STATIC symint_t
add_aux_sym_tir (type_info_t *t, hash_state_t state, thash_t **hash_tbl)
{
AUXU *aux_ptr;
efdr_t *file_ptr = cur_file_ptr;
varray_t *vp = &file_ptr->aux_syms;
static AUXU init_aux;
symint_t ret;
int i;
AUXU aux;
aux = init_aux;
aux.ti.bt = (int) t->basic_type;
aux.ti.continued = 0;
aux.ti.fBitfield = t->bitfield;
aux.ti.tq0 = (int) t->type_qualifiers[0];
aux.ti.tq1 = (int) t->type_qualifiers[1];
aux.ti.tq2 = (int) t->type_qualifiers[2];
aux.ti.tq3 = (int) t->type_qualifiers[3];
aux.ti.tq4 = (int) t->type_qualifiers[4];
aux.ti.tq5 = (int) t->type_qualifiers[5];
if (state != hash_no
&& (t->type_qualifiers[0] == tq_Array
|| t->type_qualifiers[1] == tq_Array
|| t->type_qualifiers[2] == tq_Array
|| t->type_qualifiers[3] == tq_Array
|| t->type_qualifiers[4] == tq_Array
|| t->type_qualifiers[5] == tq_Array
|| t->basic_type == bt_Struct
|| t->basic_type == bt_Union
|| t->basic_type == bt_Enum
|| t->bitfield
|| t->num_dims > 0))
state = hash_no;
if (state != hash_no)
{
thash_t *hash_ptr;
symint_t hi;
hi = aux.isym & ((1 << HASHBITS) - 1);
hi %= THASH_SIZE;
for (hash_ptr = hash_tbl[hi];
hash_ptr != (thash_t *) 0;
hash_ptr = hash_ptr->next)
{
if (aux.isym == hash_ptr->type.isym)
break;
}
if (hash_ptr != (thash_t *) 0 && state == hash_yes)
return hash_ptr->indx;
if (hash_ptr == (thash_t *) 0)
{
hash_ptr = allocate_thash ();
hash_ptr->next = hash_tbl[hi];
hash_ptr->type = aux;
hash_ptr->indx = vp->num_allocated;
hash_tbl[hi] = hash_ptr;
}
}
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
aux_ptr = &vp->last->datum->aux[ vp->objects_last_page++ ];
*aux_ptr = aux;
ret = vp->num_allocated++;
if (t->bitfield)
(void) add_aux_sym_symint ((symint_t) t->sizes[t->num_sizes-1]);
if (t->basic_type == bt_Struct
|| t->basic_type == bt_Union
|| t->basic_type == bt_Enum)
{
symint_t file_index = t->tag_ptr->ifd;
symint_t sym_index = t->tag_ptr->indx;
if (t->unknown_tag)
{
(void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
(void) add_aux_sym_symint ((symint_t)-1);
}
else if (sym_index != indexNil)
{
(void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
(void) add_aux_sym_symint (file_index);
}
else
{
forward_t *forward_ref = allocate_forward ();
forward_ref->type_ptr = aux_ptr;
forward_ref->next = t->tag_ptr->forward_ref;
t->tag_ptr->forward_ref = forward_ref;
(void) add_aux_sym_rndx (ST_RFDESCAPE, sym_index);
forward_ref->index_ptr
= &vp->last->datum->aux[ vp->objects_last_page - 1];
(void) add_aux_sym_symint (file_index);
forward_ref->ifd_ptr
= &vp->last->datum->aux[ vp->objects_last_page - 1];
}
}
for (i = 0; i < t->num_dims; i++)
{
(void) add_aux_sym_rndx (ST_RFDESCAPE,
cur_file_ptr->int_type);
(void) add_aux_sym_symint (cur_file_ptr->file_index);
(void) add_aux_sym_symint ((symint_t) 0);
(void) add_aux_sym_symint (t->dimensions[i] - 1);
(void) add_aux_sym_symint ((t->dimensions[i] == 0)
? 0
: (t->sizes[i] * 8) / t->dimensions[i]);
};
return ret;
}
STATIC tag_t *
get_tag (const char *tag_start,
const char *tag_end_p1,
symint_t indx,
bt_t basic_type)
{
shash_t *hash_ptr;
tag_t *tag_ptr;
hash_ptr = hash_string (tag_start,
tag_end_p1 - tag_start,
&tag_hash[0],
(symint_t *) 0);
if (hash_ptr != (shash_t *) 0
&& hash_ptr->tag_ptr != (tag_t *) 0)
{
tag_ptr = hash_ptr->tag_ptr;
if (indx != indexNil)
{
tag_ptr->basic_type = basic_type;
tag_ptr->ifd = cur_file_ptr->file_index;
tag_ptr->indx = indx;
}
return tag_ptr;
}
(void) add_string (&tag_strings,
&tag_hash[0],
tag_start,
tag_end_p1,
&hash_ptr);
tag_ptr = allocate_tag ();
tag_ptr->forward_ref = (forward_t *) 0;
tag_ptr->hash_ptr = hash_ptr;
tag_ptr->same_name = hash_ptr->tag_ptr;
tag_ptr->basic_type = basic_type;
tag_ptr->indx = indx;
tag_ptr->ifd = (indx == indexNil
? (symint_t) -1 : cur_file_ptr->file_index);
tag_ptr->same_block = cur_tag_head->first_tag;
cur_tag_head->first_tag = tag_ptr;
hash_ptr->tag_ptr = tag_ptr;
return tag_ptr;
}
STATIC void
add_unknown_tag (tag_t *ptag)
{
shash_t *hash_ptr = ptag->hash_ptr;
char *name_start = hash_ptr->string;
char *name_end_p1 = name_start + hash_ptr->len;
forward_t *f_next = ptag->forward_ref;
forward_t *f_cur;
int sym_index;
int file_index = cur_file_ptr->file_index;
if (debug > 1)
{
const char *agg_type = "{unknown aggregate type}";
switch (ptag->basic_type)
{
case bt_Struct: agg_type = "struct"; break;
case bt_Union: agg_type = "union"; break;
case bt_Enum: agg_type = "enum"; break;
default: break;
}
fprintf (stderr, "unknown %s %.*s found\n",
agg_type, (int) hash_ptr->len, name_start);
}
sym_index = add_local_symbol (name_start,
name_end_p1,
st_Block,
sc_Info,
(symint_t) 0,
(symint_t) 0);
(void) add_local_symbol (name_start,
name_end_p1,
st_End,
sc_Info,
(symint_t) 0,
(symint_t) 0);
while (f_next != (forward_t *) 0)
{
f_cur = f_next;
f_next = f_next->next;
f_cur->ifd_ptr->isym = file_index;
f_cur->index_ptr->rndx.index = sym_index;
free_forward (f_cur);
}
return;
}
STATIC void
add_procedure (const char *func_start,
const char *func_end_p1)
{
PDR *new_proc_ptr;
efdr_t *file_ptr = cur_file_ptr;
varray_t *vp = &file_ptr->procs;
symint_t value = 0;
st_t proc_type = st_Proc;
shash_t *shash_ptr = hash_string (func_start,
func_end_p1 - func_start,
&orig_str_hash[0],
(symint_t *) 0);
if (debug)
fputc ('\n', stderr);
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
cur_proc_ptr = new_proc_ptr = &vp->last->datum->proc[ vp->objects_last_page++ ];
vp->num_allocated++;
cur_oproc_ptr = (PDR *) 0;
if (shash_ptr != (shash_t *) 0)
{
PDR *old_proc_ptr = shash_ptr->proc_ptr;
SYMR *sym_ptr = shash_ptr->sym_ptr;
if (old_proc_ptr != (PDR *) 0
&& sym_ptr != (SYMR *) 0
&& ((st_t) sym_ptr->st == st_Proc || (st_t) sym_ptr->st == st_StaticProc))
{
cur_oproc_begin = sym_ptr;
cur_oproc_end = shash_ptr->end_ptr;
value = sym_ptr->value;
cur_oproc_ptr = old_proc_ptr;
proc_type = (st_t) sym_ptr->st;
*new_proc_ptr = *old_proc_ptr;
}
}
if (cur_oproc_ptr == (PDR *) 0)
error ("did not find a PDR block for %.*s",
(int) (func_end_p1 - func_start), func_start);
new_proc_ptr->isym = file_ptr->symbols.num_allocated;
(void) add_local_symbol (func_start, func_end_p1,
proc_type, sc_Text,
value,
(symint_t) 0);
}
STATIC void
initialize_init_file (void)
{
memset (&init_file, 0, sizeof (init_file));
init_file.fdr.lang = langC;
init_file.fdr.fMerge = 1;
init_file.fdr.glevel = GLEVEL_2;
#ifdef HOST_WORDS_BIG_ENDIAN
init_file.fdr.fBigendian = 1;
#endif
INITIALIZE_VARRAY (&init_file.strings, char);
INITIALIZE_VARRAY (&init_file.symbols, SYMR);
INITIALIZE_VARRAY (&init_file.procs, PDR);
INITIALIZE_VARRAY (&init_file.aux_syms, AUXU);
init_file_initialized = 1;
}
STATIC void
add_file (const char *file_start,
const char *file_end_p1)
{
static char zero_bytes[2] = { '\0', '\0' };
Ptrdiff_t len = file_end_p1 - file_start;
int first_ch = *file_start;
efdr_t *file_ptr;
if (debug)
fprintf (stderr, "\tfile\t%.*s\n", (int) len, file_start);
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
if (first_ch == file_ptr->name[0]
&& file_ptr->name[len] == '\0'
&& memcmp (file_start, file_ptr->name, len) == 0)
{
cur_file_ptr = file_ptr;
break;
}
}
if (file_ptr == (efdr_t *) 0)
{
if (file_desc.objects_last_page == file_desc.objects_per_page)
add_varray_page (&file_desc);
if (! init_file_initialized)
initialize_init_file ();
file_ptr = cur_file_ptr
= &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
*file_ptr = init_file;
file_ptr->file_index = file_desc.num_allocated++;
file_ptr->shash_head = (shash_t **) allocate_page ();
add_string (&file_ptr->strings,
&file_ptr->shash_head[0],
&zero_bytes[0],
&zero_bytes[0],
(shash_t **) 0);
if (file_end_p1 - file_start > (long) PAGE_USIZE-2)
fatal ("filename goes over one page boundary");
(void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
(symint_t) 0, (symint_t) 0);
file_ptr->fdr.rss = 1;
file_ptr->name = &file_ptr->strings.last->datum->byte[1];
file_ptr->name_len = file_end_p1 - file_start;
*last_file_ptr = file_ptr;
last_file_ptr = &file_ptr->next_file;
file_ptr->void_type = add_aux_sym_tir (&void_type_info,
hash_yes,
&cur_file_ptr->thash_head[0]);
file_ptr->int_type = add_aux_sym_tir (&int_type_info,
hash_yes,
&cur_file_ptr->thash_head[0]);
}
}
STATIC void
add_bytes (varray_t *vp,
char *input_ptr,
Size_t nitems)
{
Size_t move_items;
Size_t move_bytes;
char *ptr;
while (nitems > 0)
{
if (vp->objects_last_page >= vp->objects_per_page)
add_varray_page (vp);
ptr = &vp->last->datum->byte[ vp->objects_last_page * vp->object_size ];
move_items = vp->objects_per_page - vp->objects_last_page;
if (move_items > nitems)
move_items = nitems;
move_bytes = move_items * vp->object_size;
nitems -= move_items;
if (move_bytes >= 32)
{
(void) memcpy (ptr, input_ptr, move_bytes);
input_ptr += move_bytes;
}
else
{
while (move_bytes-- > 0)
*ptr++ = *input_ptr++;
}
}
}
STATIC const char *
sc_to_string (sc_t storage_class)
{
switch (storage_class)
{
case sc_Nil: return "Nil,";
case sc_Text: return "Text,";
case sc_Data: return "Data,";
case sc_Bss: return "Bss,";
case sc_Register: return "Register,";
case sc_Abs: return "Abs,";
case sc_Undefined: return "Undefined,";
case sc_CdbLocal: return "CdbLocal,";
case sc_Bits: return "Bits,";
case sc_CdbSystem: return "CdbSystem,";
case sc_RegImage: return "RegImage,";
case sc_Info: return "Info,";
case sc_UserStruct: return "UserStruct,";
case sc_SData: return "SData,";
case sc_SBss: return "SBss,";
case sc_RData: return "RData,";
case sc_Var: return "Var,";
case sc_Common: return "Common,";
case sc_SCommon: return "SCommon,";
case sc_VarRegister: return "VarRegister,";
case sc_Variant: return "Variant,";
case sc_SUndefined: return "SUndefined,";
case sc_Init: return "Init,";
case sc_Max: return "Max,";
}
return "???,";
}
STATIC const char *
st_to_string (st_t symbol_type)
{
switch (symbol_type)
{
case st_Nil: return "Nil,";
case st_Global: return "Global,";
case st_Static: return "Static,";
case st_Param: return "Param,";
case st_Local: return "Local,";
case st_Label: return "Label,";
case st_Proc: return "Proc,";
case st_Block: return "Block,";
case st_End: return "End,";
case st_Member: return "Member,";
case st_Typedef: return "Typedef,";
case st_File: return "File,";
case st_RegReloc: return "RegReloc,";
case st_Forward: return "Forward,";
case st_StaticProc: return "StaticProc,";
case st_Constant: return "Constant,";
case st_Str: return "String,";
case st_Number: return "Number,";
case st_Expr: return "Expr,";
case st_Type: return "Type,";
case st_Max: return "Max,";
}
return "???,";
}
STATIC char *
read_line (void)
{
static int line_split_p = 0;
int string_p = 0;
int comment_p = 0;
int ch;
char *ptr;
if (cur_line_start == (char *) 0)
{
cur_line_start = (char *) allocate_page ();
cur_line_alloc = PAGE_SIZE;
}
if (!line_split_p)
line_number++;
line_split_p = 0;
cur_line_nbytes = 0;
for (ptr = cur_line_start; (ch = getchar ()) != EOF; *ptr++ = ch)
{
if (++cur_line_nbytes >= cur_line_alloc-1)
{
int num_pages = cur_line_alloc / PAGE_SIZE;
char *old_buffer = cur_line_start;
cur_line_alloc += PAGE_SIZE;
cur_line_start = (char *) allocate_multiple_pages (num_pages+1);
memcpy (cur_line_start, old_buffer, num_pages * PAGE_SIZE);
ptr = cur_line_start + cur_line_nbytes - 1;
}
if (ch == '\n')
{
*ptr++ = '\n';
*ptr = '\0';
cur_line_ptr = cur_line_start;
return cur_line_ptr;
}
else if (ch == '\0')
error ("null character found in input");
else if (!comment_p)
{
if (ch == '"')
string_p = !string_p;
else if (ch == '#')
comment_p++;
else if (ch == ';' && !string_p)
{
line_split_p = 1;
*ptr++ = '\n';
*ptr = '\0';
cur_line_ptr = cur_line_start;
return cur_line_ptr;
}
}
}
if (ferror (stdin))
pfatal_with_name (input_name);
cur_line_ptr = (char *) 0;
return (char *) 0;
}
STATIC void
parse_begin (const char *start)
{
const char *end_p1;
int ch;
shash_t *hash_ptr;
if (cur_file_ptr == (efdr_t *) 0)
{
error ("#.begin directive without a preceding .file directive");
return;
}
if (cur_proc_ptr == (PDR *) 0)
{
error ("#.begin directive without a preceding .ent directive");
return;
}
for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
;
hash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
(symint_t *) 0);
if (hash_ptr == (shash_t *) 0)
{
error ("label %.*s not found for #.begin",
(int) (end_p1 - start), start);
return;
}
if (cur_oproc_begin == (SYMR *) 0)
{
error ("procedure table %.*s not found for #.begin",
(int) (end_p1 - start), start);
return;
}
(void) add_local_symbol ((const char *) 0, (const char *) 0,
st_Block, sc_Text,
(symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
(symint_t) 0);
}
STATIC void
parse_bend (const char *start)
{
const char *end_p1;
int ch;
shash_t *hash_ptr;
if (cur_file_ptr == (efdr_t *) 0)
{
error ("#.begin directive without a preceding .file directive");
return;
}
if (cur_proc_ptr == (PDR *) 0)
{
error ("#.bend directive without a preceding .ent directive");
return;
}
for (end_p1 = start; (ch = *end_p1) != '\0' && !ISSPACE (ch); end_p1++)
;
hash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
(symint_t *) 0);
if (hash_ptr == (shash_t *) 0)
{
error ("label %.*s not found for #.bend", (int) (end_p1 - start), start);
return;
}
if (cur_oproc_begin == (SYMR *) 0)
{
error ("procedure table %.*s not found for #.bend",
(int) (end_p1 - start), start);
return;
}
(void) add_local_symbol ((const char *) 0, (const char *) 0,
st_End, sc_Text,
(symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
(symint_t) 0);
}
STATIC void
parse_def (const char *name_start)
{
const char *dir_start;
const char *dir_end_p1;
const char *arg_start;
const char *arg_end_p1;
const char *name_end_p1;
const char *tag_start = 0;
const char *tag_end_p1 = 0;
sc_t storage_class = sc_Nil;
st_t symbol_type = st_Nil;
type_info_t t;
EXTR *eptr = (EXTR *) 0;
int is_function = 0;
symint_t value = 0;
symint_t indx = cur_file_ptr->void_type;
int error_line = 0;
symint_t arg_number;
symint_t temp_array[ N_TQ ];
int arg_was_number;
int ch, i;
Ptrdiff_t len;
static int inside_enumeration = 0;
t = type_info_init;
for (name_end_p1 = name_start; (ch = *name_end_p1) != ';' && ch != '\0'; name_end_p1++)
;
if (ch == '\0')
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
dir_start = name_end_p1+1;
for (;;)
{
while ((ch = *dir_start) == ' ' || ch == '\t')
++dir_start;
if (ch != '.')
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
if (dir_start[1] == 'e'
&& memcmp (dir_start, ".endef", sizeof (".endef")-1) == 0)
break;
for (dir_end_p1 = dir_start+1;
(ch = *dir_end_p1) != ' ' && ch != '\t';
dir_end_p1++)
{
if (ch == '\0' || ISSPACE (ch))
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
}
arg_was_number = arg_number = 0;
arg_end_p1 = 0;
arg_start = dir_end_p1+1;
ch = *arg_start;
while (ch == ' ' || ch == '\t')
ch = *++arg_start;
if (ISDIGIT (ch) || ch == '-' || ch == '+')
{
int ch2;
arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
if (arg_end_p1 != arg_start || ((ch2 = *arg_end_p1) != ';') || ch2 != ',')
arg_was_number++;
}
else if (ch == '\0' || ISSPACE (ch))
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
if (!arg_was_number)
{
for (arg_end_p1 = arg_start+1;
(ch = *arg_end_p1) != ';' && ch != '\0';
arg_end_p1++)
;
if (ch == '\0')
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
}
len = dir_end_p1 - dir_start;
switch (dir_start[1])
{
default:
error_line = __LINE__;
saber_stop ();
goto bomb_out;
case 'd':
if (len == sizeof (".dim")-1
&& memcmp (dir_start, ".dim", sizeof (".dim")-1) == 0
&& arg_was_number)
{
symint_t *t_ptr = &temp_array[ N_TQ-1 ];
*t_ptr = arg_number;
while (*arg_end_p1 == ',' && arg_was_number)
{
arg_start = arg_end_p1+1;
ch = *arg_start;
while (ch == ' ' || ch == '\t')
ch = *++arg_start;
arg_was_number = 0;
if (ISDIGIT (ch) || ch == '-' || ch == '+')
{
int ch2;
arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
if (arg_end_p1 != arg_start || ((ch2 = *arg_end_p1) != ';') || ch2 != ',')
arg_was_number++;
if (t_ptr == &temp_array[0])
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
*--t_ptr = arg_number;
}
}
while (t_ptr <= &temp_array[ N_TQ-1 ])
{
if (t.num_dims >= N_TQ-1)
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
t.dimensions[ t.num_dims++ ] = *t_ptr++;
}
break;
}
else
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
case 's':
if (len == sizeof (".scl")-1
&& memcmp (dir_start, ".scl", sizeof (".scl")-1) == 0
&& arg_was_number
&& arg_number < ((symint_t) C_MAX))
{
if (symbol_type == st_Nil)
{
symbol_type = map_coff_sym_type[arg_number];
storage_class = map_coff_storage [arg_number];
}
break;
}
else if (len == sizeof (".size")-1
&& memcmp (dir_start, ".size", sizeof (".size")-1) == 0
&& arg_was_number)
{
symint_t *t_ptr = &temp_array[ N_TQ-1 ];
*t_ptr = arg_number;
while (*arg_end_p1 == ',' && arg_was_number)
{
arg_start = arg_end_p1+1;
ch = *arg_start;
while (ch == ' ' || ch == '\t')
ch = *++arg_start;
arg_was_number = 0;
if (ISDIGIT (ch) || ch == '-' || ch == '+')
{
int ch2;
arg_number = strtol (arg_start, (char **) &arg_end_p1, 0);
if (arg_end_p1 != arg_start || ((ch2 = *arg_end_p1) != ';') || ch2 != ',')
arg_was_number++;
if (t_ptr == &temp_array[0])
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
*--t_ptr = arg_number;
}
}
while (t_ptr <= &temp_array[ N_TQ-1 ])
{
if (t.num_sizes >= N_TQ-1)
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
t.sizes[ t.num_sizes++ ] = *t_ptr++;
}
break;
}
else
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
case 't':
if (len == sizeof (".type")-1
&& memcmp (dir_start, ".type", sizeof (".type")-1) == 0
&& arg_was_number)
{
tq_t *tq_ptr = &t.type_qualifiers[0];
t.orig_type = (coff_type_t) (arg_number & N_BTMASK);
t.basic_type = map_coff_types [(int) t.orig_type];
for (i = N_TQ-1; i >= 0; i--)
{
int dt = (arg_number >> ((i * N_TQ_SHIFT) + N_BT_SHIFT)
& N_TMASK);
if (dt != (int) DT_NON)
*tq_ptr++ = map_coff_derived_type [dt];
}
if (tq_ptr != &t.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
{
is_function = 1;
tq_ptr[-1] = tq_Nil;
}
break;
}
else if (len == sizeof (".tag")-1
&& memcmp (dir_start, ".tag", sizeof (".tag")-1) == 0)
{
tag_start = arg_start;
tag_end_p1 = arg_end_p1;
break;
}
else
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
case 'v':
if (len == sizeof (".val")-1
&& memcmp (dir_start, ".val", sizeof (".val")-1) == 0)
{
if (arg_was_number)
value = arg_number;
else
{
shash_t *orig_hash_ptr;
shash_t *ext_hash_ptr;
ext_hash_ptr = hash_string (arg_start,
arg_end_p1 - arg_start,
&ext_str_hash[0],
(symint_t *) 0);
if (ext_hash_ptr != (shash_t *) 0
&& ext_hash_ptr->esym_ptr != (EXTR *) 0)
eptr = ext_hash_ptr->esym_ptr;
orig_hash_ptr = hash_string (arg_start,
arg_end_p1 - arg_start,
&orig_str_hash[0],
(symint_t *) 0);
if ((orig_hash_ptr == (shash_t *) 0
|| orig_hash_ptr->sym_ptr == (SYMR *) 0)
&& eptr == (EXTR *) 0)
{
fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
(int) (arg_end_p1 - arg_start),
arg_start);
value = 0;
}
else
{
SYMR *ptr = (orig_hash_ptr != (shash_t *) 0
&& orig_hash_ptr->sym_ptr != (SYMR *) 0)
? orig_hash_ptr->sym_ptr
: &eptr->asym;
symbol_type = (st_t) ptr->st;
storage_class = (sc_t) ptr->sc;
value = ptr->value;
}
}
break;
}
else
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
}
dir_start = arg_end_p1 + 1;
}
if (storage_class == sc_Bits)
{
t.bitfield = 1;
t.extra_sizes = 1;
}
else
t.extra_sizes = 0;
if (t.num_dims > 0)
{
int num_real_sizes = t.num_sizes - t.extra_sizes;
int diff = t.num_dims - num_real_sizes;
int i = t.num_dims - 1;
int j;
if (num_real_sizes != 1 || diff < 0)
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
if (diff)
{
for (j = ARRAY_SIZE (t.sizes) - 1; j >= 0; j--)
t.sizes[ j ] = ((j-diff) >= 0) ? t.sizes[ j-diff ] : 0;
t.num_sizes = i + 1;
for ( i--; i >= 0; i-- )
{
if (t.dimensions[ i+1 ])
t.sizes[ i ] = t.sizes[ i+1 ] / t.dimensions[ i+1 ];
else
t.sizes[ i ] = t.sizes[ i+1 ];
}
}
}
if (symbol_type == st_Block || symbol_type == st_End)
indx = 0;
else if (inside_enumeration)
indx = cur_file_ptr->void_type;
else
{
if (t.basic_type == bt_Struct
|| t.basic_type == bt_Union
|| t.basic_type == bt_Enum)
{
if (tag_start == (char *) 0)
{
error ("no tag specified for %.*s",
(int) (name_end_p1 - name_start),
name_start);
return;
}
t.tag_ptr = get_tag (tag_start, tag_end_p1, (symint_t) indexNil,
t.basic_type);
}
if (is_function)
{
last_func_type_info = t;
last_func_eptr = eptr;
return;
}
indx = add_aux_sym_tir (&t,
hash_yes,
&cur_file_ptr->thash_head[0]);
}
if (eptr != (EXTR *) 0
&& (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *) 0))
{
eptr->ifd = cur_file_ptr->file_index;
eptr->asym.index = indx;
}
switch (symbol_type)
{
default:
break;
case st_Block:
if (t.num_sizes - t.num_dims - t.extra_sizes != 1)
{
error_line = __LINE__;
saber_stop ();
goto bomb_out;
}
else
value = t.sizes[0];
inside_enumeration = (t.orig_type == T_ENUM);
break;
case st_End:
name_start = name_end_p1 = 0;
value = inside_enumeration = 0;
break;
case st_Member:
if (!t.bitfield && !inside_enumeration)
value *= 8;
break;
}
if (eptr == (EXTR *) 0
|| eptr->asym.st == (int) st_Nil
|| cur_proc_ptr != (PDR *) 0)
{
symint_t isym = add_local_symbol (name_start, name_end_p1,
symbol_type, storage_class,
value,
indx);
if (symbol_type == st_Block)
{
tag_t *tag_ptr = get_tag (name_start,
name_end_p1,
isym,
t.basic_type);
symint_t file_index = cur_file_ptr->file_index;
forward_t *f_next = tag_ptr->forward_ref;
forward_t *f_cur;
while (f_next != (forward_t *) 0)
{
f_cur = f_next;
f_next = f_next->next;
f_cur->ifd_ptr->isym = file_index;
f_cur->index_ptr->rndx.index = isym;
free_forward (f_cur);
}
tag_ptr->forward_ref = (forward_t *) 0;
}
}
return;
bomb_out:
if (error_line)
error ("compiler error, badly formed #.def (internal line # = %d)", error_line);
else
error ("compiler error, badly formed #.def");
return;
}
STATIC void
parse_end (const char *start)
{
const char *start_func, *end_func_p1;
int ch;
symint_t value;
FDR *orig_fdr;
if (cur_file_ptr == (efdr_t *) 0)
{
error (".end directive without a preceding .file directive");
return;
}
if (cur_proc_ptr == (PDR *) 0)
{
error (".end directive without a preceding .ent directive");
return;
}
for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
;
ch = *start_func;
if (!IS_ASM_IDENT (ch))
{
error (".end directive has no name");
return;
}
for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
;
orig_fdr = cur_file_ptr->orig_fdr;
value = 0;
if (orig_fdr != (FDR *) 0 && cur_oproc_end != (SYMR *) 0)
value = cur_oproc_end->value;
else
error ("cannot find .end block for %.*s",
(int) (end_func_p1 - start_func), start_func);
(void) add_local_symbol (start_func, end_func_p1,
st_End, sc_Text,
value,
(symint_t) 0);
cur_proc_ptr = cur_oproc_ptr = (PDR *) 0;
}
STATIC void
parse_ent (const char *start)
{
const char *start_func, *end_func_p1;
int ch;
if (cur_file_ptr == (efdr_t *) 0)
{
error (".ent directive without a preceding .file directive");
return;
}
if (cur_proc_ptr != (PDR *) 0)
{
error ("second .ent directive found before .end directive");
return;
}
for (start_func = start; ISSPACE ((unsigned char)*start_func); start_func++)
;
ch = *start_func;
if (!IS_ASM_IDENT (ch))
{
error (".ent directive has no name");
return;
}
for (end_func_p1 = start_func; IS_ASM_IDENT (ch); ch = *++end_func_p1)
;
(void) add_procedure (start_func, end_func_p1);
}
STATIC void
parse_file (const char *start)
{
char *p;
char *start_name, *end_name_p1;
(void) strtol (start, &p, 0);
if (start == p
|| (start_name = strchr (p, '"')) == (char *) 0
|| (end_name_p1 = strrchr (++start_name, '"')) == (char *) 0)
{
error ("invalid .file directive");
return;
}
if (cur_proc_ptr != (PDR *) 0)
{
error ("no way to handle .file within .ent/.end section");
return;
}
add_file (start_name, end_name_p1);
}
static void
mark_stabs (const char *start ATTRIBUTE_UNUSED)
{
if (!stabs_seen)
{
stabs_seen = 1;
(void) add_local_symbol (stabs_symbol,
stabs_symbol + sizeof (stabs_symbol),
stNil, scInfo, -1, MIPS_MARK_STAB (0));
}
}
STATIC void
parse_stabs_common (const char *string_start,
const char *string_end,
const char *rest)
{
efdr_t *save_file_ptr = cur_file_ptr;
symint_t code;
symint_t value;
char *p;
st_t st;
sc_t sc;
int ch;
if (stabs_seen == 0)
mark_stabs ("");
if (!ISDIGIT (*rest))
{
error ("invalid .stabs/.stabn directive, code is non-numeric");
return;
}
code = strtol (rest, &p, 0);
if (code == (int) N_SLINE)
{
SYMR *sym_ptr, dummy_symr;
shash_t *shash_ptr;
if (p[0] != ',' || p[1] != '0' || p[2] != ',' || !ISDIGIT (p[3]))
{
error ("invalid line number .stabs/.stabn directive");
return;
}
code = strtol (p+3, &p, 0);
ch = *++p;
if (p[-1] != ',' || ISDIGIT (ch) || !IS_ASM_IDENT (ch))
{
error ("invalid line number .stabs/.stabn directive");
return;
}
dummy_symr.index = code;
if (dummy_symr.index != code)
{
error ("line number (%lu) for .stabs/.stabn directive cannot fit in index field (20 bits)",
code);
return;
}
shash_ptr = hash_string (p,
strlen (p) - 1,
&orig_str_hash[0],
(symint_t *) 0);
if (shash_ptr == (shash_t *) 0
|| (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
{
error ("invalid .stabs/.stabn directive, value not found");
return;
}
if ((st_t) sym_ptr->st != st_Label)
{
error ("invalid line number .stabs/.stabn directive");
return;
}
st = st_Label;
sc = (sc_t) sym_ptr->sc;
value = sym_ptr->value;
}
else
{
if (*p++ != ',')
goto failure;
for (; ISDIGIT (*p); p++)
;
if (*p++ != ',')
goto failure;
for (; ISDIGIT (*p); p++)
;
if (*p++ != ',')
goto failure;
ch = *p;
if (!IS_ASM_IDENT (ch) && ch != '-')
{
failure:
error ("invalid .stabs/.stabn directive, bad character");
return;
}
if (ISDIGIT (ch) || ch == '-')
{
st = st_Nil;
sc = sc_Nil;
value = strtol (p, &p, 0);
if (*p != '\n')
{
error ("invalid .stabs/.stabn directive, stuff after numeric value");
return;
}
}
else if (!IS_ASM_IDENT (ch))
{
error ("invalid .stabs/.stabn directive, bad character");
return;
}
else
{
SYMR *sym_ptr;
shash_t *shash_ptr;
const char *start, *end_p1;
start = p;
if ((end_p1 = strchr (start, '+')) == (char *) 0)
{
if ((end_p1 = strchr (start, '-')) == (char *) 0)
end_p1 = start + strlen (start) - 1;
}
shash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
(symint_t *) 0);
if (shash_ptr == (shash_t *) 0
|| (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
{
shash_ptr = hash_string (start,
end_p1 - start,
&ext_str_hash[0],
(symint_t *) 0);
if (shash_ptr == (shash_t *) 0
|| shash_ptr->esym_ptr == (EXTR *) 0)
{
error ("invalid .stabs/.stabn directive, value not found");
return;
}
else
sym_ptr = &(shash_ptr->esym_ptr->asym);
}
if (code == (int) N_LBRAC || code == (int) N_RBRAC)
{
sc = scNil;
st = stNil;
}
else
{
sc = (sc_t) sym_ptr->sc;
st = (st_t) sym_ptr->st;
}
value = sym_ptr->value;
ch = *end_p1++;
if (ch != '\n')
{
if (((!ISDIGIT (*end_p1)) && (*end_p1 != '-'))
|| ((ch != '+') && (ch != '-')))
{
error ("invalid .stabs/.stabn directive, badly formed value");
return;
}
if (ch == '+')
value += strtol (end_p1, &p, 0);
else if (ch == '-')
value -= strtol (end_p1, &p, 0);
if (*p != '\n')
{
error ("invalid .stabs/.stabn directive, stuff after numeric value");
return;
}
}
}
code = MIPS_MARK_STAB (code);
}
(void) add_local_symbol (string_start, string_end, st, sc, value, code);
cur_file_ptr = save_file_ptr;
}
STATIC void
parse_stabs (const char *start)
{
const char *end = strchr (start+1, '"');
if (*start != '"' || end == (const char *) 0 || end[1] != ',')
{
error ("invalid .stabs directive, no string");
return;
}
parse_stabs_common (start+1, end, end+2);
}
STATIC void
parse_stabn (const char *start)
{
parse_stabs_common ((const char *) 0, (const char *) 0, start);
}
STATIC void
parse_input (void)
{
char *p;
Size_t i;
thead_t *ptag_head;
tag_t *ptag;
tag_t *ptag_next;
if (debug)
fprintf (stderr, "\tinput\n");
ptag_head = allocate_thead ();
ptag_head->first_tag = 0;
ptag_head->prev = cur_tag_head;
cur_tag_head = ptag_head;
while ((p = read_line ()) != (char *) 0)
{
while (ISSPACE ((unsigned char)*p))
p++;
for (i = 0; i < ARRAY_SIZE (pseudo_ops); i++)
if (memcmp (p, pseudo_ops[i].name, pseudo_ops[i].len) == 0
&& ISSPACE ((unsigned char)(p[pseudo_ops[i].len])))
{
p += pseudo_ops[i].len;
while (ISSPACE ((unsigned char)*p))
p++;
(*pseudo_ops[i].func)( p );
break;
}
}
ptag_head = cur_tag_head;
cur_tag_head = ptag_head->prev;
for (ptag = ptag_head->first_tag;
ptag != (tag_t *) 0;
ptag = ptag_next)
{
if (ptag->forward_ref != (forward_t *) 0)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
ptag->hash_ptr->tag_ptr = ptag->same_name;
free_tag (ptag);
}
free_thead (ptag_head);
}
STATIC void
update_headers (void)
{
symint_t i;
efdr_t *file_ptr;
file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
symbolic_header.magic = orig_sym_hdr.magic;
symbolic_header.vstamp = orig_sym_hdr.vstamp;
symbolic_header.issExtMax = ext_strings.num_allocated;
symbolic_header.idnMax = dense_num.num_allocated;
symbolic_header.ifdMax = file_desc.num_allocated;
symbolic_header.iextMax = ext_symbols.num_allocated;
symbolic_header.ilineMax = orig_sym_hdr.ilineMax;
symbolic_header.ioptMax = orig_sym_hdr.ioptMax;
symbolic_header.cbLine = orig_sym_hdr.cbLine;
symbolic_header.crfd = orig_sym_hdr.crfd;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
SYMR *sym_start;
SYMR *sym;
SYMR *sym_end_p1;
FDR *fd_ptr = file_ptr->orig_fdr;
cur_file_ptr = file_ptr;
sym_start = ORIG_LSYMS (fd_ptr->isymBase);
sym_end_p1 = sym_start + fd_ptr->csym;
for (sym = sym_start; sym < sym_end_p1; sym++)
{
if ((st_t) sym->st == st_Static)
{
char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
Size_t len = strlen (str);
shash_t *hash_ptr;
if (str[0] == '$' && str[1] == 'L')
continue;
hash_ptr = hash_string (str,
(Ptrdiff_t) len,
&file_ptr->shash_head[0],
(symint_t *) 0);
if (hash_ptr == (shash_t *) 0)
{
(void) add_local_symbol (str, str + len,
(st_t) sym->st, (sc_t) sym->sc,
(symint_t) sym->value,
(symint_t) indexNil);
}
}
}
(void) add_local_symbol ((const char *) 0, (const char *) 0,
st_End, sc_Text,
(symint_t) 0,
(symint_t) 0);
file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
symbolic_header.ipdMax += file_ptr->fdr.cpd;
file_ptr->fdr.csym = file_ptr->symbols.num_allocated;
file_ptr->fdr.isymBase = symbolic_header.isymMax;
symbolic_header.isymMax += file_ptr->fdr.csym;
file_ptr->fdr.caux = file_ptr->aux_syms.num_allocated;
file_ptr->fdr.iauxBase = symbolic_header.iauxMax;
symbolic_header.iauxMax += file_ptr->fdr.caux;
file_ptr->fdr.cbSs = file_ptr->strings.num_allocated;
file_ptr->fdr.issBase = symbolic_header.issMax;
symbolic_header.issMax += file_ptr->fdr.cbSs;
}
#ifndef ALIGN_SYMTABLE_OFFSET
#define ALIGN_SYMTABLE_OFFSET(OFFSET) (OFFSET)
#endif
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
i = WORD_ALIGN (symbolic_header.cbLine);
if (i > 0)
{
symbolic_header.cbLineOffset = file_offset;
file_offset += i;
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.ioptMax;
if (((long) i) > 0)
{
symbolic_header.cbOptOffset = file_offset;
file_offset += i * sizeof (OPTR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.idnMax;
if (i > 0)
{
symbolic_header.cbDnOffset = file_offset;
file_offset += i * sizeof (DNR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.ipdMax;
if (i > 0)
{
symbolic_header.cbPdOffset = file_offset;
file_offset += i * sizeof (PDR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.isymMax;
if (i > 0)
{
symbolic_header.cbSymOffset = file_offset;
file_offset += i * sizeof (SYMR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.iauxMax;
if (i > 0)
{
symbolic_header.cbAuxOffset = file_offset;
file_offset += i * sizeof (TIR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = WORD_ALIGN (symbolic_header.issMax);
if (i > 0)
{
symbolic_header.cbSsOffset = file_offset;
file_offset += i;
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = WORD_ALIGN (symbolic_header.issExtMax);
if (i > 0)
{
symbolic_header.cbSsExtOffset = file_offset;
file_offset += i;
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.ifdMax;
if (i > 0)
{
symbolic_header.cbFdOffset = file_offset;
file_offset += i * sizeof (FDR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.crfd;
if (i > 0)
{
symbolic_header.cbRfdOffset = file_offset;
file_offset += i * sizeof (symint_t);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
i = symbolic_header.iextMax;
if (i > 0)
{
symbolic_header.cbExtOffset = file_offset;
file_offset += i * sizeof (EXTR);
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
}
STATIC void
write_varray (varray_t *vp,
off_t offset,
const char *str)
{
int num_write, sys_write;
vlinks_t *ptr;
if (vp->num_allocated == 0)
return;
if (debug)
fprintf (stderr, "\twarray\tvp = " HOST_PTR_PRINTF
", offset = %7lu, size = %7lu, %s\n",
(void *) vp, (unsigned long) offset,
vp->num_allocated * vp->object_size, str);
if (file_offset != (unsigned long) offset
&& fseek (object_stream, (long) offset, SEEK_SET) < 0)
pfatal_with_name (object_name);
for (ptr = vp->first; ptr != (vlinks_t *) 0; ptr = ptr->next)
{
num_write = (ptr->next == (vlinks_t *) 0)
? vp->objects_last_page * vp->object_size
: vp->objects_per_page * vp->object_size;
sys_write = fwrite (ptr->datum, 1, num_write, object_stream);
if (sys_write <= 0)
pfatal_with_name (object_name);
else if (sys_write != num_write)
fatal ("wrote %d bytes to %s, system returned %d",
num_write,
object_name,
sys_write);
file_offset += num_write;
}
}
STATIC void
write_object (void)
{
int sys_write;
efdr_t *file_ptr;
off_t offset;
if (debug)
fprintf (stderr, "\n\twrite\tvp = " HOST_PTR_PRINTF
", offset = %7u, size = %7lu, %s\n",
(void *) &symbolic_header, 0,
(unsigned long) sizeof (symbolic_header), "symbolic header");
sys_write = fwrite (&symbolic_header,
1,
sizeof (symbolic_header),
object_stream);
if (sys_write < 0)
pfatal_with_name (object_name);
else if (sys_write != sizeof (symbolic_header))
fatal ("wrote %d bytes to %s, system returned %d",
(int) sizeof (symbolic_header),
object_name,
sys_write);
file_offset = sizeof (symbolic_header) + orig_file_header.f_symptr;
if (symbolic_header.cbLine > 0)
{
long sys_write;
if (file_offset != (unsigned long) symbolic_header.cbLineOffset
&& fseek (object_stream, symbolic_header.cbLineOffset, SEEK_SET) != 0)
pfatal_with_name (object_name);
if (debug)
fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
", offset = %7lu, size = %7lu, %s\n",
(void *) &orig_linenum, (long) symbolic_header.cbLineOffset,
(long) symbolic_header.cbLine, "Line numbers");
sys_write = fwrite (orig_linenum,
1,
symbolic_header.cbLine,
object_stream);
if (sys_write <= 0)
pfatal_with_name (object_name);
else if (sys_write != symbolic_header.cbLine)
fatal ("wrote %ld bytes to %s, system returned %ld",
(long) symbolic_header.cbLine,
object_name,
sys_write);
file_offset = symbolic_header.cbLineOffset + symbolic_header.cbLine;
}
if (symbolic_header.ioptMax > 0)
{
long sys_write;
long num_write = symbolic_header.ioptMax * sizeof (OPTR);
if (file_offset != (unsigned long) symbolic_header.cbOptOffset
&& fseek (object_stream, symbolic_header.cbOptOffset, SEEK_SET) != 0)
pfatal_with_name (object_name);
if (debug)
fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
", offset = %7lu, size = %7lu, %s\n",
(void *) &orig_opt_syms, (long) symbolic_header.cbOptOffset,
num_write, "Optimizer symbols");
sys_write = fwrite (orig_opt_syms,
1,
num_write,
object_stream);
if (sys_write <= 0)
pfatal_with_name (object_name);
else if (sys_write != num_write)
fatal ("wrote %ld bytes to %s, system returned %ld",
num_write,
object_name,
sys_write);
file_offset = symbolic_header.cbOptOffset + num_write;
}
if (symbolic_header.idnMax > 0)
write_varray (&dense_num, (off_t) symbolic_header.cbDnOffset, "Dense numbers");
if (symbolic_header.ipdMax > 0)
{
offset = symbolic_header.cbPdOffset;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->procs, offset, "Procedure tables");
offset = file_offset;
}
}
if (symbolic_header.isymMax > 0)
{
offset = symbolic_header.cbSymOffset;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->symbols, offset, "Local symbols");
offset = file_offset;
}
}
if (symbolic_header.iauxMax > 0)
{
offset = symbolic_header.cbAuxOffset;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
offset = file_offset;
}
}
if (symbolic_header.issMax > 0)
{
offset = symbolic_header.cbSsOffset;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->strings, offset, "Local strings");
offset = file_offset;
}
}
if (symbolic_header.issExtMax > 0)
write_varray (&ext_strings, symbolic_header.cbSsExtOffset, "External strings");
if (symbolic_header.ifdMax > 0)
{
offset = symbolic_header.cbFdOffset;
if (file_offset != (unsigned long) offset
&& fseek (object_stream, (long) offset, SEEK_SET) < 0)
pfatal_with_name (object_name);
file_offset = offset;
for (file_ptr = first_file;
file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
if (debug)
fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
", offset = %7lu, size = %7lu, %s\n",
(void *) &file_ptr->fdr, file_offset,
(unsigned long) sizeof (FDR), "File header");
sys_write = fwrite (&file_ptr->fdr,
1,
sizeof (FDR),
object_stream);
if (sys_write < 0)
pfatal_with_name (object_name);
else if (sys_write != sizeof (FDR))
fatal ("wrote %d bytes to %s, system returned %d",
(int) sizeof (FDR),
object_name,
sys_write);
file_offset = offset += sizeof (FDR);
}
}
if (symbolic_header.crfd > 0)
{
long sys_write;
symint_t num_write = symbolic_header.crfd * sizeof (symint_t);
if (file_offset != (unsigned long) symbolic_header.cbRfdOffset
&& fseek (object_stream, symbolic_header.cbRfdOffset, SEEK_SET) != 0)
pfatal_with_name (object_name);
if (debug)
fprintf (stderr, "\twrite\tvp = " HOST_PTR_PRINTF
", offset = %7lu, size = %7lu, %s\n",
(void *) &orig_rfds, (long) symbolic_header.cbRfdOffset,
num_write, "Relative file descriptors");
sys_write = fwrite (orig_rfds,
1,
num_write,
object_stream);
if (sys_write <= 0)
pfatal_with_name (object_name);
else if (sys_write != (long) num_write)
fatal ("wrote %lu bytes to %s, system returned %ld",
num_write,
object_name,
sys_write);
file_offset = symbolic_header.cbRfdOffset + num_write;
}
if (symbolic_header.issExtMax > 0)
write_varray (&ext_symbols, (off_t) symbolic_header.cbExtOffset, "External symbols");
if (fclose (object_stream) != 0)
pfatal_with_name (object_name);
}
STATIC page_t *
read_seek (Size_t size,
off_t offset,
const char *str)
{
page_t *ptr;
long sys_read = 0;
if (size == 0)
return (page_t *) 0;
if (debug)
fprintf (stderr,
"\trseek\tsize = %7lu, offset = %7lu, currently at %7lu, %s\n",
(unsigned long) size, (unsigned long) offset, file_offset, str);
#ifndef MALLOC_CHECK
ptr = allocate_multiple_pages ((size + PAGE_USIZE - 1) / PAGE_USIZE);
#else
ptr = xcalloc (1, size);
#endif
if (file_offset != (unsigned long) offset)
{
symint_t difference = offset - file_offset;
if (difference < 8)
{
char small_buffer[8];
sys_read = fread (small_buffer, 1, difference, obj_in_stream);
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
if ((symint_t) sys_read != difference)
fatal ("wanted to read %lu bytes from %s, system returned %ld",
(unsigned long) size,
obj_in_name,
sys_read);
}
else if (fseek (obj_in_stream, offset, SEEK_SET) < 0)
pfatal_with_name (obj_in_name);
}
sys_read = fread (ptr, 1, size, obj_in_stream);
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
if (sys_read != (long) size)
fatal ("wanted to read %lu bytes from %s, system returned %ld",
(unsigned long) size,
obj_in_name,
sys_read);
file_offset = offset + size;
if (file_offset > max_file_offset)
max_file_offset = file_offset;
return ptr;
}
STATIC void
copy_object (void)
{
char buffer[ PAGE_SIZE ];
int sys_read;
int remaining;
int num_write;
int sys_write;
int fd, es;
int delete_ifd = 0;
int *remap_file_number;
struct stat stat_buf;
if (debug)
fprintf (stderr, "\tcopy\n");
if (fstat (fileno (obj_in_stream), &stat_buf) != 0
|| fseek (obj_in_stream, 0L, SEEK_SET) != 0)
pfatal_with_name (obj_in_name);
sys_read = fread (&orig_file_header,
1,
sizeof (struct filehdr),
obj_in_stream);
if (sys_read < 0)
pfatal_with_name (obj_in_name);
else if (sys_read == 0 && feof (obj_in_stream))
return;
else if (sys_read < (int) sizeof (struct filehdr))
fatal ("wanted to read %d bytes from %s, system returned %d",
(int) sizeof (struct filehdr),
obj_in_name,
sys_read);
if (orig_file_header.f_nsyms != sizeof (HDRR))
fatal ("%s symbolic header wrong size (%ld bytes, should be %ld)",
input_name, (long) orig_file_header.f_nsyms, (long) sizeof (HDRR));
if (fseek (obj_in_stream, (long) orig_file_header.f_symptr, SEEK_SET) != 0)
pfatal_with_name (input_name);
sys_read = fread (&orig_sym_hdr,
1,
sizeof (orig_sym_hdr),
obj_in_stream);
if (sys_read < 0)
pfatal_with_name (object_name);
else if (sys_read < (int) sizeof (struct filehdr))
fatal ("wanted to read %d bytes from %s, system returned %d",
(int) sizeof (struct filehdr),
obj_in_name,
sys_read);
file_offset = orig_file_header.f_symptr + sizeof (struct filehdr);
if (orig_sym_hdr.cbLine > 0)
orig_linenum = (char *) read_seek (orig_sym_hdr.cbLine,
orig_sym_hdr.cbLineOffset,
"Line numbers");
if (orig_sym_hdr.ipdMax > 0)
orig_procs = (PDR *) read_seek (orig_sym_hdr.ipdMax * sizeof (PDR),
orig_sym_hdr.cbPdOffset,
"Procedure tables");
if (orig_sym_hdr.isymMax > 0)
orig_local_syms = (SYMR *) read_seek (orig_sym_hdr.isymMax * sizeof (SYMR),
orig_sym_hdr.cbSymOffset,
"Local symbols");
if (orig_sym_hdr.iauxMax > 0)
orig_aux_syms = (AUXU *) read_seek (orig_sym_hdr.iauxMax * sizeof (AUXU),
orig_sym_hdr.cbAuxOffset,
"Aux. symbols");
if (orig_sym_hdr.issMax > 0)
orig_local_strs = (char *) read_seek (orig_sym_hdr.issMax,
orig_sym_hdr.cbSsOffset,
"Local strings");
if (orig_sym_hdr.issExtMax > 0)
orig_ext_strs = (char *) read_seek (orig_sym_hdr.issExtMax,
orig_sym_hdr.cbSsExtOffset,
"External strings");
if (orig_sym_hdr.ifdMax > 0)
orig_files = (FDR *) read_seek (orig_sym_hdr.ifdMax * sizeof (FDR),
orig_sym_hdr.cbFdOffset,
"File tables");
if (orig_sym_hdr.crfd > 0)
orig_rfds = (symint_t *) read_seek (orig_sym_hdr.crfd * sizeof (symint_t),
orig_sym_hdr.cbRfdOffset,
"Relative file descriptors");
if (orig_sym_hdr.issExtMax > 0)
orig_ext_syms = (EXTR *) read_seek (orig_sym_hdr.iextMax * sizeof (EXTR),
orig_sym_hdr.cbExtOffset,
"External symbols");
if (orig_sym_hdr.idnMax > 0)
{
orig_dense = (DNR *) read_seek (orig_sym_hdr.idnMax * sizeof (DNR),
orig_sym_hdr.cbDnOffset,
"Dense numbers");
add_bytes (&dense_num, (char *) orig_dense, orig_sym_hdr.idnMax);
}
if (orig_sym_hdr.ioptMax > 0)
orig_opt_syms = (OPTR *) read_seek (orig_sym_hdr.ioptMax * sizeof (OPTR),
orig_sym_hdr.cbOptOffset,
"Optimizer symbols");
if (max_file_offset != (unsigned long) stat_buf.st_size)
fatal ("symbol table is not last (symbol table ends at %ld, .o ends at %ld",
max_file_offset,
(long) stat_buf.st_size);
if (orig_sym_hdr.ifdMax > 1
&& orig_files->csym == 2
&& orig_files->caux == 0)
{
char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
char *suffix = strrchr (filename, '.');
if (suffix != (char *) 0 && strcmp (suffix, ".s") == 0)
delete_ifd = 1;
}
remap_file_number = alloca (sizeof (int) * orig_sym_hdr.ifdMax);
for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
{
FDR *fd_ptr = ORIG_FILES (fd);
char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
add_file (filename, filename + strlen (filename));
remap_file_number[fd] = cur_file_ptr->file_index;
}
if (delete_ifd > 0)
remap_file_number[0] = remap_file_number[1];
if (debug)
fprintf (stderr, "\tehash\n");
for (es = 0; es < orig_sym_hdr.iextMax; es++)
{
EXTR *eptr = orig_ext_syms + es;
int ifd = eptr->ifd;
(void) add_ext_symbol (eptr, ((long) ifd < orig_sym_hdr.ifdMax)
? remap_file_number[ ifd ] : ifd );
}
for (fd = delete_ifd; fd < orig_sym_hdr.ifdMax; fd++)
{
FDR *fd_ptr = ORIG_FILES (fd);
char *filename = ORIG_LSTRS (fd_ptr->issBase + fd_ptr->rss);
SYMR *sym_start;
SYMR *sym;
SYMR *sym_end_p1;
PDR *proc_start;
PDR *proc;
PDR *proc_end_p1;
add_file (filename, filename + strlen (filename));
cur_file_ptr->orig_fdr = fd_ptr;
cur_file_ptr->fdr.adr = fd_ptr->adr;
cur_file_ptr->fdr.ilineBase = fd_ptr->ilineBase;
cur_file_ptr->fdr.cline = fd_ptr->cline;
cur_file_ptr->fdr.rfdBase = fd_ptr->rfdBase;
cur_file_ptr->fdr.crfd = fd_ptr->crfd;
cur_file_ptr->fdr.cbLineOffset = fd_ptr->cbLineOffset;
cur_file_ptr->fdr.cbLine = fd_ptr->cbLine;
cur_file_ptr->fdr.fMerge = fd_ptr->fMerge;
cur_file_ptr->fdr.fReadin = fd_ptr->fReadin;
cur_file_ptr->fdr.glevel = fd_ptr->glevel;
if (debug)
fprintf (stderr, "\thash\tstart, filename %s\n", filename);
sym_start = ORIG_LSYMS (fd_ptr->isymBase);
sym_end_p1 = sym_start + fd_ptr->csym;
for (sym = sym_start; sym < sym_end_p1; sym++)
{
switch ((st_t) sym->st)
{
default:
break;
case st_Global:
case st_Static:
case st_Label:
case st_Proc:
case st_StaticProc:
{
auto symint_t hash_index;
char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
Size_t len = strlen (str);
shash_t *shash_ptr = hash_string (str,
(Ptrdiff_t) len,
&orig_str_hash[0],
&hash_index);
if (shash_ptr != (shash_t *) 0)
error ("internal error, %s is already in original symbol table", str);
else
{
shash_ptr = allocate_shash ();
shash_ptr->next = orig_str_hash[hash_index];
orig_str_hash[hash_index] = shash_ptr;
shash_ptr->len = len;
shash_ptr->indx = indexNil;
shash_ptr->string = str;
shash_ptr->sym_ptr = sym;
}
}
break;
case st_End:
if ((sc_t) sym->sc == sc_Text)
{
char *str = ORIG_LSTRS (fd_ptr->issBase + sym->iss);
if (*str != '\0')
{
Size_t len = strlen (str);
shash_t *shash_ptr = hash_string (str,
(Ptrdiff_t) len,
&orig_str_hash[0],
(symint_t *) 0);
if (shash_ptr != (shash_t *) 0)
shash_ptr->end_ptr = sym;
}
}
break;
}
}
if (debug)
{
fprintf (stderr, "\thash\tdone, filename %s\n", filename);
fprintf (stderr, "\tproc\tstart, filename %s\n", filename);
}
proc_start = ORIG_PROCS (fd_ptr->ipdFirst);
proc_end_p1 = proc_start + fd_ptr->cpd;
for (proc = proc_start; proc < proc_end_p1; proc++)
{
SYMR *proc_sym = ORIG_LSYMS (fd_ptr->isymBase + proc->isym);
char *str = ORIG_LSTRS (fd_ptr->issBase + proc_sym->iss);
Size_t len = strlen (str);
shash_t *shash_ptr = hash_string (str,
(Ptrdiff_t) len,
&orig_str_hash[0],
(symint_t *) 0);
if (shash_ptr == (shash_t *) 0)
error ("internal error, function %s is not in original symbol table", str);
else
shash_ptr->proc_ptr = proc;
}
if (debug)
fprintf (stderr, "\tproc\tdone, filename %s\n", filename);
}
cur_file_ptr = first_file;
if (fseek (obj_in_stream, (long) 0, SEEK_SET) != 0)
pfatal_with_name (obj_in_name);
if (fseek (object_stream, (long) 0, SEEK_SET) != 0)
pfatal_with_name (object_name);
for (remaining = orig_file_header.f_symptr;
remaining > 0;
remaining -= num_write)
{
num_write
= (remaining <= (int) sizeof (buffer))
? remaining : (int) sizeof (buffer);
sys_read = fread (buffer, 1, num_write, obj_in_stream);
if (sys_read <= 0)
pfatal_with_name (obj_in_name);
else if (sys_read != num_write)
fatal ("wanted to read %d bytes from %s, system returned %d",
num_write,
obj_in_name,
sys_read);
sys_write = fwrite (buffer, 1, num_write, object_stream);
if (sys_write <= 0)
pfatal_with_name (object_name);
else if (sys_write != num_write)
fatal ("wrote %d bytes to %s, system returned %d",
num_write,
object_name,
sys_write);
}
}
extern int main (int, char **);
int
main (int argc, char **argv)
{
int iflag = 0;
char *p = strrchr (argv[0], '/');
char *num_end;
int option;
int i;
progname = (p != 0) ? p+1 : argv[0];
(void) signal (SIGSEGV, catch_signal);
(void) signal (SIGBUS, catch_signal);
(void) signal (SIGABRT, catch_signal);
#if !defined(__SABER__) && !defined(lint)
if (sizeof (efdr_t) > PAGE_USIZE)
fatal ("efdr_t has a sizeof %d bytes, when it should be less than %d",
(int) sizeof (efdr_t),
(int) PAGE_USIZE);
if (sizeof (page_t) != PAGE_USIZE)
fatal ("page_t has a sizeof %d bytes, when it should be %d",
(int) sizeof (page_t),
(int) PAGE_USIZE);
#endif
alloc_counts[ alloc_type_none ].alloc_name = "none";
alloc_counts[ alloc_type_scope ].alloc_name = "scope";
alloc_counts[ alloc_type_vlinks ].alloc_name = "vlinks";
alloc_counts[ alloc_type_shash ].alloc_name = "shash";
alloc_counts[ alloc_type_thash ].alloc_name = "thash";
alloc_counts[ alloc_type_tag ].alloc_name = "tag";
alloc_counts[ alloc_type_forward ].alloc_name = "forward";
alloc_counts[ alloc_type_thead ].alloc_name = "thead";
alloc_counts[ alloc_type_varray ].alloc_name = "varray";
int_type_info = type_info_init;
int_type_info.basic_type = bt_Int;
void_type_info = type_info_init;
void_type_info.basic_type = bt_Void;
while ((option = getopt_long (argc, argv, "d:i:I:o:v", options, NULL)) != -1)
switch (option)
{
default:
had_errors++;
break;
case 'd':
debug = strtol (optarg, &num_end, 0);
if ((unsigned) debug > 4 || num_end == optarg)
had_errors++;
break;
case 'I':
if (rename_output || obj_in_name != (char *) 0)
had_errors++;
else
rename_output = 1;
case 'i':
if (obj_in_name == (char *) 0)
{
obj_in_name = optarg;
iflag++;
}
else
had_errors++;
break;
case 'o':
if (object_name == (char *) 0)
object_name = optarg;
else
had_errors++;
break;
case 'v':
verbose++;
break;
case 'V':
version++;
break;
}
if (version)
{
printf (_("mips-tfile (GCC) %s\n"), version_string);
fputs ("Copyright (C) 2004 Free Software Foundation, Inc.\n", stdout);
fputs (_("This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
stdout);
exit (0);
}
if (obj_in_name == (char *) 0 && optind <= argc - 2)
obj_in_name = argv[--argc];
if (object_name == (char *) 0 && optind <= argc - 2)
object_name = argv[--argc];
if (obj_in_name == (char *) 0 && object_name != (char *) 0)
{
obj_in_name = object_name;
delete_input = 1;
}
if (optind != argc - 1)
had_errors++;
if (verbose || had_errors)
{
fprintf (stderr, _("mips-tfile (GCC) %s"), version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
fputc ('\n', stderr);
}
if (object_name == (char *) 0 || had_errors)
{
fprintf (stderr, _("Calling Sequence:\n"));
fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] [-I <o-in-file>] -o <o-out-file> <s-file> (or)\n"));
fprintf (stderr, _("\tmips-tfile [-d <num>] [-v] <s-file> <o-in-file> <o-out-file>\n"));
fprintf (stderr, "\n");
fprintf (stderr, _("Debug levels are:\n"));
fprintf (stderr, _(" 1\tGeneral debug + trace functions/blocks.\n"));
fprintf (stderr, _(" 2\tDebug level 1 + trace externals.\n"));
fprintf (stderr, _(" 3\tDebug level 2 + trace all symbols.\n"));
fprintf (stderr, _(" 4\tDebug level 3 + trace memory allocations.\n"));
return 1;
}
if (obj_in_name == (char *) 0)
obj_in_name = object_name;
if (rename_output && rename (object_name, obj_in_name) != 0)
{
char *buffer = (char *) allocate_multiple_pages (4);
int len;
int len2;
int in_fd;
int out_fd;
in_fd = open (object_name, O_RDONLY, 0666);
if (in_fd < 0)
pfatal_with_name (object_name);
out_fd = open (obj_in_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (out_fd < 0)
pfatal_with_name (obj_in_name);
while ((len = read (in_fd, buffer, 4*PAGE_SIZE)) > 0)
{
len2 = write (out_fd, buffer, len);
if (len2 < 0)
pfatal_with_name (object_name);
if (len != len2)
fatal ("wrote %d bytes to %s, expected to write %d", len2, obj_in_name, len);
}
free_multiple_pages ((page_t *) buffer, 4);
if (len < 0)
pfatal_with_name (object_name);
if (close (in_fd) < 0)
pfatal_with_name (object_name);
if (close (out_fd) < 0)
pfatal_with_name (obj_in_name);
}
obj_in_stream = fopen (obj_in_name, "r");
if (obj_in_stream == (FILE *) 0)
pfatal_with_name (obj_in_name);
if (delete_input && unlink (obj_in_name) != 0)
pfatal_with_name (obj_in_name);
object_stream = fopen (object_name, "w");
if (object_stream == (FILE *) 0)
pfatal_with_name (object_name);
if (strcmp (argv[optind], "-") != 0)
{
input_name = argv[optind];
if (freopen (argv[optind], "r", stdin) != stdin)
pfatal_with_name (argv[optind]);
}
copy_object ();
parse_input ();
update_headers ();
write_object ();
if (debug)
{
fprintf (stderr, "\n\tAllocation summary:\n\n");
for (i = (int) alloc_type_none; i < (int) alloc_type_last; i++)
if (alloc_counts[i].total_alloc)
{
fprintf (stderr,
"\t%s\t%5d allocation(s), %5d free(s), %2d page(s)\n",
alloc_counts[i].alloc_name,
alloc_counts[i].total_alloc,
alloc_counts[i].total_free,
alloc_counts[i].total_pages);
}
}
return (had_errors) ? 1 : 0;
}
STATIC void
catch_signal (int signum)
{
(void) signal (signum, SIG_DFL);
fatal ("%s", strsignal (signum));
}
void
pfatal_with_name (const char *msg)
{
int save_errno = errno;
if (line_number > 0)
fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
else
fprintf (stderr, "%s:", progname);
errno = save_errno;
if (errno == 0)
fprintf (stderr, "[errno = 0] %s\n", msg);
else
perror (msg);
exit (1);
}
static int
out_of_bounds (symint_t indx,
symint_t max,
const char *str,
int prog_line)
{
if (indx < max)
return 0;
fprintf (stderr, "%s, %s:%ld index %lu is out of bounds for %s, max is %lu, mips-tfile.c line# %d\n",
progname, input_name, line_number, indx, str, max, prog_line);
exit (1);
return 0;
}
#ifndef MALLOC_CHECK
#ifdef USE_MALLOC
STATIC page_t *
allocate_cluster (Size_t npages)
{
page_t *value = xcalloc (npages, PAGE_USIZE);
if (debug > 3)
fprintf (stderr, "\talloc\tnpages = %d, value = 0x%.8x\n", npages, value);
return value;
}
#else
STATIC page_t *
allocate_cluster (Size_t npages)
{
page_t *ptr = (page_t *) sbrk (0);
unsigned long offset = ((unsigned long) ptr) & (PAGE_SIZE - 1);
if (offset != 0)
{
if (sbrk (PAGE_USIZE - offset) == (char *)-1)
pfatal_with_name ("allocate_cluster");
ptr = (page_t *) (((char *) ptr) + PAGE_SIZE - offset);
}
if (sbrk (npages * PAGE_USIZE) == (char *) -1)
pfatal_with_name ("allocate_cluster");
if (debug > 3)
fprintf (stderr, "\talloc\tnpages = %lu, value = " HOST_PTR_PRINTF "\n",
(unsigned long) npages, (void *) ptr);
return ptr;
}
#endif
static page_t *cluster_ptr = NULL;
static unsigned pages_left = 0;
#endif
STATIC page_t *
allocate_multiple_pages (Size_t npages)
{
#ifndef MALLOC_CHECK
if (pages_left == 0 && npages < MAX_CLUSTER_PAGES)
{
pages_left = MAX_CLUSTER_PAGES;
cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
}
if (npages <= pages_left)
{
page_t *ptr = cluster_ptr;
cluster_ptr += npages;
pages_left -= npages;
return ptr;
}
return allocate_cluster (npages);
#else
return xcalloc (npages, PAGE_SIZE);
#endif
}
STATIC void
free_multiple_pages (page_t *page_ptr, Size_t npages)
{
#ifndef MALLOC_CHECK
if (pages_left == 0)
{
cluster_ptr = page_ptr;
pages_left = npages;
}
else if ((page_ptr + npages) == cluster_ptr)
{
cluster_ptr -= npages;
pages_left += npages;
}
#else
free (page_ptr);
#endif
}
STATIC page_t *
allocate_page (void)
{
#ifndef MALLOC_CHECK
if (pages_left == 0)
{
pages_left = MAX_CLUSTER_PAGES;
cluster_ptr = allocate_cluster (MAX_CLUSTER_PAGES);
}
pages_left--;
return cluster_ptr++;
#else
return xcalloc (1, PAGE_SIZE);
#endif
}
STATIC scope_t *
allocate_scope (void)
{
scope_t *ptr;
static scope_t initial_scope;
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
if (ptr != (scope_t *) 0)
alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr->free;
else
{
int unallocated = alloc_counts[ (int) alloc_type_scope ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_scope ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (scope_t);
alloc_counts[ (int) alloc_type_scope ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_scope ].total_pages++;
}
ptr = &cur_page->scope[ --unallocated ];
alloc_counts[ (int) alloc_type_scope ].unallocated = unallocated;
}
#else
ptr = xmalloc (sizeof (scope_t));
#endif
alloc_counts[ (int) alloc_type_scope ].total_alloc++;
*ptr = initial_scope;
return ptr;
}
STATIC void
free_scope (scope_t *ptr)
{
alloc_counts[ (int) alloc_type_scope ].total_free++;
#ifndef MALLOC_CHECK
ptr->free = alloc_counts[ (int) alloc_type_scope ].free_list.f_scope;
alloc_counts[ (int) alloc_type_scope ].free_list.f_scope = ptr;
#else
free (ptr);
#endif
}
STATIC vlinks_t *
allocate_vlinks (void)
{
vlinks_t *ptr;
static vlinks_t initial_vlinks;
#ifndef MALLOC_CHECK
int unallocated = alloc_counts[ (int) alloc_type_vlinks ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_vlinks ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (vlinks_t);
alloc_counts[ (int) alloc_type_vlinks ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_vlinks ].total_pages++;
}
ptr = &cur_page->vlinks[ --unallocated ];
alloc_counts[ (int) alloc_type_vlinks ].unallocated = unallocated;
#else
ptr = xmalloc (sizeof (vlinks_t));
#endif
alloc_counts[ (int) alloc_type_vlinks ].total_alloc++;
*ptr = initial_vlinks;
return ptr;
}
STATIC shash_t *
allocate_shash (void)
{
shash_t *ptr;
static shash_t initial_shash;
#ifndef MALLOC_CHECK
int unallocated = alloc_counts[ (int) alloc_type_shash ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_shash ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (shash_t);
alloc_counts[ (int) alloc_type_shash ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_shash ].total_pages++;
}
ptr = &cur_page->shash[ --unallocated ];
alloc_counts[ (int) alloc_type_shash ].unallocated = unallocated;
#else
ptr = xmalloc (sizeof (shash_t));
#endif
alloc_counts[ (int) alloc_type_shash ].total_alloc++;
*ptr = initial_shash;
return ptr;
}
STATIC thash_t *
allocate_thash (void)
{
thash_t *ptr;
static thash_t initial_thash;
#ifndef MALLOC_CHECK
int unallocated = alloc_counts[ (int) alloc_type_thash ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_thash ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (thash_t);
alloc_counts[ (int) alloc_type_thash ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_thash ].total_pages++;
}
ptr = &cur_page->thash[ --unallocated ];
alloc_counts[ (int) alloc_type_thash ].unallocated = unallocated;
#else
ptr = xmalloc (sizeof (thash_t));
#endif
alloc_counts[ (int) alloc_type_thash ].total_alloc++;
*ptr = initial_thash;
return ptr;
}
STATIC tag_t *
allocate_tag (void)
{
tag_t *ptr;
static tag_t initial_tag;
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
if (ptr != (tag_t *) 0)
alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr->free;
else
{
int unallocated = alloc_counts[ (int) alloc_type_tag ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_tag ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (tag_t);
alloc_counts[ (int) alloc_type_tag ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_tag ].total_pages++;
}
ptr = &cur_page->tag[ --unallocated ];
alloc_counts[ (int) alloc_type_tag ].unallocated = unallocated;
}
#else
ptr = xmalloc (sizeof (tag_t));
#endif
alloc_counts[ (int) alloc_type_tag ].total_alloc++;
*ptr = initial_tag;
return ptr;
}
STATIC void
free_tag (tag_t *ptr)
{
alloc_counts[ (int) alloc_type_tag ].total_free++;
#ifndef MALLOC_CHECK
ptr->free = alloc_counts[ (int) alloc_type_tag ].free_list.f_tag;
alloc_counts[ (int) alloc_type_tag ].free_list.f_tag = ptr;
#else
free (ptr);
#endif
}
STATIC forward_t *
allocate_forward (void)
{
forward_t *ptr;
static forward_t initial_forward;
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
if (ptr != (forward_t *) 0)
alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr->free;
else
{
int unallocated = alloc_counts[ (int) alloc_type_forward ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_forward ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (forward_t);
alloc_counts[ (int) alloc_type_forward ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_forward ].total_pages++;
}
ptr = &cur_page->forward[ --unallocated ];
alloc_counts[ (int) alloc_type_forward ].unallocated = unallocated;
}
#else
ptr = xmalloc (sizeof (forward_t));
#endif
alloc_counts[ (int) alloc_type_forward ].total_alloc++;
*ptr = initial_forward;
return ptr;
}
STATIC void
free_forward (forward_t *ptr)
{
alloc_counts[ (int) alloc_type_forward ].total_free++;
#ifndef MALLOC_CHECK
ptr->free = alloc_counts[ (int) alloc_type_forward ].free_list.f_forward;
alloc_counts[ (int) alloc_type_forward ].free_list.f_forward = ptr;
#else
free (ptr);
#endif
}
STATIC thead_t *
allocate_thead (void)
{
thead_t *ptr;
static thead_t initial_thead;
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
if (ptr != (thead_t *) 0)
alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr->free;
else
{
int unallocated = alloc_counts[ (int) alloc_type_thead ].unallocated;
page_t *cur_page = alloc_counts[ (int) alloc_type_thead ].cur_page;
if (unallocated == 0)
{
unallocated = PAGE_SIZE / sizeof (thead_t);
alloc_counts[ (int) alloc_type_thead ].cur_page = cur_page = allocate_page ();
alloc_counts[ (int) alloc_type_thead ].total_pages++;
}
ptr = &cur_page->thead[ --unallocated ];
alloc_counts[ (int) alloc_type_thead ].unallocated = unallocated;
}
#else
ptr = xmalloc (sizeof (thead_t));
#endif
alloc_counts[ (int) alloc_type_thead ].total_alloc++;
*ptr = initial_thead;
return ptr;
}
STATIC void
free_thead (thead_t *ptr)
{
alloc_counts[ (int) alloc_type_thead ].total_free++;
#ifndef MALLOC_CHECK
ptr->free = (thead_t *) alloc_counts[ (int) alloc_type_thead ].free_list.f_thead;
alloc_counts[ (int) alloc_type_thead ].free_list.f_thead = ptr;
#else
free (ptr);
#endif
}
#endif
void
fatal (const char *format, ...)
{
va_list ap;
va_start (ap, format);
if (line_number > 0)
fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
else
fprintf (stderr, "%s:", progname);
vfprintf (stderr, format, ap);
va_end (ap);
fprintf (stderr, "\n");
if (line_number > 0)
fprintf (stderr, "line:\t%s\n", cur_line_start);
saber_stop ();
exit (1);
}
void
error (const char *format, ...)
{
va_list ap;
va_start (ap, format);
if (line_number > 0)
fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
else
fprintf (stderr, "%s:", progname);
vfprintf (stderr, format, ap);
fprintf (stderr, "\n");
if (line_number > 0)
fprintf (stderr, "line:\t%s\n", cur_line_start);
had_errors++;
va_end (ap);
saber_stop ();
}
void
fancy_abort (const char *file, int line, const char *func)
{
fatal ("abort in %s, at %s:%d", func, file, line);
}
void
botch (const char *s)
{
fatal ("%s", s);
}