Maybe some minor changes.
This commit is contained in:
parent
58126396af
commit
d7fb9edfe2
120
h/out.h
Normal file
120
h/out.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/* $Header$ */
|
||||
/*
|
||||
* output format for ACK assemblers
|
||||
*/
|
||||
#ifndef ushort
|
||||
#define ushort unsigned short
|
||||
#endif ushort
|
||||
|
||||
struct outhead {
|
||||
ushort oh_magic; /* magic number */
|
||||
ushort oh_stamp; /* version stamp */
|
||||
ushort oh_flags; /* several format flags */
|
||||
ushort oh_nsect; /* number of outsect structures */
|
||||
ushort oh_nrelo; /* number of outrelo structures */
|
||||
ushort oh_nname; /* number of outname structures */
|
||||
long oh_nemit; /* sum of all os_flen */
|
||||
long oh_nchar; /* size of string area */
|
||||
};
|
||||
|
||||
#define O_MAGIC 0x0201 /* magic number of output file */
|
||||
#define O_STAMP 0 /* version stamp */
|
||||
|
||||
#ifdef JOHAN
|
||||
#define HF_BREV 0x0001 /* high order byte lowest address */
|
||||
#define HF_WREV 0x0002 /* high order word lowest address */
|
||||
#endif JOHAN
|
||||
#define HF_LINK 0x0004 /* unresolved references left */
|
||||
#define HF_8086 0x0008 /* os_base specially encoded */
|
||||
|
||||
struct outsect {
|
||||
long os_base; /* startaddress in machine */
|
||||
long os_size; /* section size in machine */
|
||||
long os_foff; /* startaddress in file */
|
||||
long os_flen; /* section size in file */
|
||||
long os_lign; /* section alignment */
|
||||
};
|
||||
|
||||
struct outrelo {
|
||||
char or_type; /* type of reference */
|
||||
char or_sect; /* referencing section */
|
||||
ushort or_nami; /* referenced symbol index */
|
||||
long or_addr; /* referencing address */
|
||||
};
|
||||
|
||||
struct outname {
|
||||
union {
|
||||
char *on_ptr; /* symbol name (in core) */
|
||||
long on_off; /* symbol name (in file) */
|
||||
} on_u;
|
||||
#define on_mptr on_u.on_ptr
|
||||
#define on_foff on_u.on_off
|
||||
ushort on_type; /* symbol type */
|
||||
ushort on_desc; /* debug info */
|
||||
long on_valu; /* symbol value */
|
||||
};
|
||||
|
||||
/*
|
||||
* relocation type bits
|
||||
*/
|
||||
#define RELSZ 0x07 /* relocation length */
|
||||
#define RELO1 1 /* 1 byte */
|
||||
#define RELO2 2 /* 2 bytes */
|
||||
#define RELO4 4 /* 4 bytes */
|
||||
#define RELPC 0x08 /* pc relative */
|
||||
#ifndef JOHAN
|
||||
#define RELBR 0x10 /* High order byte lowest address. */
|
||||
#define RELWR 0x20 /* High order word lowest address. */
|
||||
#endif JOHAN
|
||||
|
||||
/*
|
||||
* section type bits and fields
|
||||
*/
|
||||
#define S_TYP 0x007F /* undefined, absolute or relative */
|
||||
#define S_EXT 0x0080 /* external flag */
|
||||
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
|
||||
|
||||
/*
|
||||
* S_TYP field values
|
||||
*/
|
||||
#define S_UND 0x0000 /* undefined item */
|
||||
#define S_ABS 0x0001 /* absolute item */
|
||||
#define S_MIN 0x0002 /* first user section */
|
||||
#define S_MAX S_TYP /* last user section */
|
||||
|
||||
/*
|
||||
* S_ETC field values
|
||||
*/
|
||||
#define S_SCT 0x0100 /* section names */
|
||||
#define S_LIN 0x0200 /* hll source line item */
|
||||
#define S_FIL 0x0300 /* hll source file item */
|
||||
#define S_MOD 0x0400 /* ass source file item */
|
||||
#ifndef JOHAN
|
||||
#define S_COM 0x1000 /* Common name. */
|
||||
#endif JOHAN
|
||||
|
||||
/*
|
||||
* structure format strings
|
||||
*/
|
||||
#define SF_HEAD "22222244"
|
||||
#define SF_SECT "44444"
|
||||
#define SF_RELO "1124"
|
||||
#define SF_NAME "4224"
|
||||
|
||||
/*
|
||||
* structure sizes (bytes in file; add digits in SF_*)
|
||||
*/
|
||||
#define SZ_HEAD 20
|
||||
#define SZ_SECT 20
|
||||
#define SZ_RELO 8
|
||||
#define SZ_NAME 12
|
||||
|
||||
/*
|
||||
* file access macros
|
||||
*/
|
||||
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
|
||||
#define OFF_SECT(x) SZ_HEAD
|
||||
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
|
||||
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
|
||||
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
|
||||
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
|
25
h/ranlib.h
Normal file
25
h/ranlib.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* $Header$ */
|
||||
|
||||
#ifndef SYMDEF
|
||||
# define SYMDEF "__.SYMDEF"
|
||||
#endif SYMDEF
|
||||
|
||||
/*
|
||||
* Structure of the SYMDEF table of contents for an archive.
|
||||
* SYMDEF begins with a long giving the number of ranlib
|
||||
* structures that immediately follow, and then continues with a string
|
||||
* table consisting of a long giving the number of bytes of
|
||||
* strings that follow and then the strings themselves.
|
||||
*/
|
||||
struct ranlib {
|
||||
union {
|
||||
char *ran__ptr; /* symbol name (in core) */
|
||||
long ran__off; /* symbol name (in file) */
|
||||
} ran_u;
|
||||
#define ran_ptr ran_u.ran__ptr
|
||||
#define ran_off ran_u.ran__off
|
||||
long ran_pos; /* library member is at this position */
|
||||
};
|
||||
|
||||
#define SZ_RAN 8
|
||||
#define SF_RAN "44"
|
178
util/led/archive.c
Normal file
178
util/led/archive.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "out.h"
|
||||
#include "ranlib.h"
|
||||
#include "const.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define ENDLIB ((long)0)
|
||||
|
||||
extern ind_t hard_alloc();
|
||||
|
||||
static struct ar_hdr arhdr;
|
||||
|
||||
/*
|
||||
* First read a long telling how many ranlib structs there are, then
|
||||
* the structs themselves. Second read a long telling how many chars there are
|
||||
* in the string table, then the string table itself.
|
||||
* We keep only one ranlib table in core, so this table always starts at offset
|
||||
* (ind_t)0 from its base.
|
||||
*/
|
||||
static long
|
||||
getsymdeftable()
|
||||
{
|
||||
register ind_t off;
|
||||
register struct ranlib *ran;
|
||||
register long count;
|
||||
register long nran, nchar;
|
||||
extern long getlong();
|
||||
|
||||
count = nran = getlong();
|
||||
debug("%ld ranlib structs, ", nran, 0, 0, 0);
|
||||
off = hard_alloc(ALLORANL, nran * sizeof(struct ranlib));
|
||||
if (off == BADOFF)
|
||||
fatal("no space for ranlib structs");
|
||||
ran = (struct ranlib *)address(ALLORANL, off);
|
||||
read_table(ran, count);
|
||||
nchar = getlong();
|
||||
debug("%ld ranlib chars\n", nchar, 0, 0, 0);
|
||||
if ((off = hard_alloc(ALLORANL, nchar)) == BADOFF)
|
||||
fatal("no space for ranlib strings");
|
||||
read_char(address(ALLORANL, off), nchar);
|
||||
ran = (struct ranlib *)address(ALLORANL, (ind_t)0);
|
||||
while (count--) {
|
||||
/*
|
||||
* Adjust because names are now in core, not on file.
|
||||
* Note that `ran_off' is measured from the beginning of the
|
||||
* string area, NOT from the beginning of the file.
|
||||
*/
|
||||
if (ran->ran_off >= nchar)
|
||||
fatal("bad ranlib string offset");
|
||||
ran->ran_off += off;
|
||||
ran++;
|
||||
}
|
||||
return nran;
|
||||
}
|
||||
|
||||
extern char *modulname;
|
||||
extern long position;
|
||||
|
||||
/*
|
||||
* Process archive with table of contents. The table of contents tells
|
||||
* of symbols in which module they are defined. We scan the table for
|
||||
* symbols that are known but not yet defined. Then we extract all necessary
|
||||
* information from the corresponding module. This module may need symbols that
|
||||
* were defined in modules located before this one in the archive, so we
|
||||
* scan the table again. We perform these actions as long as new symbols
|
||||
* are defined.
|
||||
*/
|
||||
arch()
|
||||
{
|
||||
long nran;
|
||||
bool resolved;
|
||||
|
||||
nran = getsymdeftable();
|
||||
|
||||
savemagic();
|
||||
do {
|
||||
register ind_t ranindex;
|
||||
register long count;
|
||||
|
||||
debug("(re)scan ranlib table\n", 0, 0, 0, 0);
|
||||
ranindex = (ind_t)0;
|
||||
count = nran;
|
||||
resolved = FALSE;
|
||||
while (count > 0) {
|
||||
register struct ranlib *ran;
|
||||
register char *string;
|
||||
register struct outname *name;
|
||||
register long pos;
|
||||
extern int hash();
|
||||
extern struct outname *searchname();
|
||||
|
||||
ran = (struct ranlib *)address(ALLORANL, ranindex);
|
||||
string = address(ALLORANL, (ind_t)ran->ran_off);
|
||||
name = searchname(string, hash(string));
|
||||
if (name == (struct outname *)0 || !ISUNDEFINED(name)) {
|
||||
ranindex += sizeof(struct ranlib);
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
seek(ran->ran_pos);
|
||||
get_archive_header(&arhdr);
|
||||
modulname = arhdr.ar_name;
|
||||
debug("%s defines %s\n", modulname, string, 0, 0);
|
||||
position = ran->ran_pos + SZ_ARCH;
|
||||
resolved = TRUE;
|
||||
/*
|
||||
* This archive member is going to be linked,
|
||||
* so we don't need to know what else it defines.
|
||||
* Note that we assume that all ranlib information of
|
||||
* one archive member is contiguous.
|
||||
*/
|
||||
pos = ran->ran_pos;
|
||||
do {
|
||||
count--; ran++;
|
||||
ranindex += sizeof(struct ranlib);
|
||||
} while (count > 0 && ran->ran_pos == pos);
|
||||
notelib(pos);
|
||||
savehdr(&arhdr);
|
||||
extract();
|
||||
}
|
||||
} while (resolved);
|
||||
|
||||
dealloc(ALLORANL);
|
||||
notelib(ENDLIB);
|
||||
}
|
||||
|
||||
/*
|
||||
* An archive member that will be loaded is remembered by storing its position
|
||||
* in the archive into the table of positions.
|
||||
*/
|
||||
notelib(pos)
|
||||
long pos;
|
||||
{
|
||||
register ind_t off;
|
||||
|
||||
if ((off = hard_alloc(ALLOARCH, (long)sizeof(long))) == BADOFF)
|
||||
fatal("no space for archive position");
|
||||
*(long *)address(ALLOARCH, off) = pos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Index of position of first archive member of next archive.
|
||||
*/
|
||||
static ind_t posindex = (ind_t)0;
|
||||
|
||||
/*
|
||||
* Process the archive in pass 2.
|
||||
* We walk through the table of positions telling at what byte offset the
|
||||
* archive header + module is located, until this position is ENDLIB, meaning
|
||||
* that we've processed all needed modules in this archive. Each group of
|
||||
* positions of an archive is terminated with ENDLIB.
|
||||
*/
|
||||
arch2()
|
||||
{
|
||||
register long *pos;
|
||||
register ind_t localpos;
|
||||
|
||||
localpos = posindex;
|
||||
for ( pos = (long *)address(ALLOARCH, localpos);
|
||||
*pos != ENDLIB;
|
||||
pos++, localpos += sizeof(long)
|
||||
) {
|
||||
seek(*pos);
|
||||
get_archive_header(&arhdr);
|
||||
modulname = arhdr.ar_name;
|
||||
debug("%s: archive member\n", modulname, 0, 0, 0);
|
||||
position = *pos + SZ_ARCH;
|
||||
finish();
|
||||
}
|
||||
localpos += sizeof(long); /* Skip ENDLIB. */
|
||||
posindex = localpos; /* Remember for next call. */
|
||||
}
|
18
util/led/assert.h
Normal file
18
util/led/assert.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* $Header$ */
|
||||
|
||||
#ifndef lint
|
||||
#ifdef NASSERT
|
||||
|
||||
#define assert(ex)
|
||||
|
||||
#else NASSERT
|
||||
|
||||
#define assert(ex) \
|
||||
{if (!(ex)) fatal("Assertion failed: file %s, line %d", __FILE__, __LINE__);}
|
||||
|
||||
#endif NASSERT
|
||||
#else lint
|
||||
|
||||
#define assert(ex)
|
||||
|
||||
#endif lint
|
90
util/led/byte_order.c
Normal file
90
util/led/byte_order.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif lint
|
||||
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
|
||||
bool bytes_reversed = FALSE;
|
||||
bool words_reversed = FALSE;
|
||||
|
||||
/*
|
||||
* Determine the byte/word order in shorts/longs, assuming the size of a short
|
||||
* is 2 chars, and the size of a long is 4 chars. Not all theoretical
|
||||
* possibilities are tested; only bytes reversed and/or words reversed.
|
||||
*/
|
||||
determine_ordering()
|
||||
{
|
||||
short s;
|
||||
long l;
|
||||
register char *cp;
|
||||
register short *sp;
|
||||
|
||||
cp = (char *)&s;
|
||||
cp[0] = 0x01; cp[1] = 0x02;
|
||||
if (s != 0x01 + (0x02 << 8))
|
||||
bytes_reversed = TRUE;
|
||||
sp = (short *)&l;
|
||||
sp[0] = 0x0001; sp[1] = 0x0002;
|
||||
if (l != 0x0001 + (0x0002 << 16))
|
||||
words_reversed = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* `Format' is a string of digits indicating how many bytes must be taken
|
||||
* from `buf' to form an integer of some type. E.g. if the digit is '2', two
|
||||
* bytes are taken to form a short.
|
||||
*/
|
||||
swap(buf, format)
|
||||
register char *buf;
|
||||
register char *format;
|
||||
{
|
||||
register char savebyte;
|
||||
|
||||
while (*format) {
|
||||
switch (*format++) {
|
||||
case '1':
|
||||
buf += 1;
|
||||
break;
|
||||
case '2':
|
||||
if (bytes_reversed) {
|
||||
savebyte = buf[0];
|
||||
buf[0] = buf[1];
|
||||
buf[1] = savebyte;
|
||||
}
|
||||
buf += 2;
|
||||
break;
|
||||
case '4':
|
||||
/*
|
||||
* Written out to save recursive calls.
|
||||
*/
|
||||
if (bytes_reversed && words_reversed) {
|
||||
savebyte = buf[0];
|
||||
buf[0] = buf[3];
|
||||
buf[3] = savebyte;
|
||||
savebyte = buf[1];
|
||||
buf[1] = buf[2];
|
||||
buf[2] = savebyte;
|
||||
} else if (bytes_reversed) {
|
||||
savebyte = buf[0];
|
||||
buf[0] = buf[1];
|
||||
buf[1] = savebyte;
|
||||
savebyte = buf[2];
|
||||
buf[2] = buf[3];
|
||||
buf[3] = savebyte;
|
||||
} else if (words_reversed) {
|
||||
savebyte = buf[0];
|
||||
buf[0] = buf[2];
|
||||
buf[2] = savebyte;
|
||||
savebyte = buf[1];
|
||||
buf[1] = buf[3];
|
||||
buf[3] = savebyte;
|
||||
}
|
||||
buf += 4;
|
||||
break;
|
||||
default:
|
||||
assert(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
26
util/led/const.h
Normal file
26
util/led/const.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* $Header$ */
|
||||
|
||||
typedef int bool;
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define S_ZER 0x2000 /* Internal use only. */
|
||||
|
||||
#define WIDTH 8 /* Number of bits in a byte. */
|
||||
#define BYTEMASK 0xFF /* Mask to get low order byte. */
|
||||
#define MININT (1 << (sizeof(int) * WIDTH - 1))
|
||||
#define MAXCHUNK (-(MININT + 1)) /* Highest count we write(2). */
|
||||
|
||||
#define RFLAG 0x01 /* -r flag given. */
|
||||
#define SFLAG 0x02 /* -s flag given. */
|
||||
|
||||
#define MAXSECT 64 /* Maximum number of sections. */
|
||||
|
||||
#define PLAIN 0 /* Input file is a normal file. */
|
||||
#define ARCHIVE 1 /* Input file is an archive. */
|
||||
|
||||
#define FIRST 1 /* Pass number. */
|
||||
#define SECOND 2 /* Idem. */
|
||||
|
||||
#define BADOFF ((ind_t)-1)
|
11
util/led/debug.h
Normal file
11
util/led/debug.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* $Header$ */
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
#define debug(s, a1, a2, a3, a4)
|
||||
|
||||
#else
|
||||
|
||||
#define debug(s, a1, a2, a3, a4) printf(s, a1, a2, a3, a4)
|
||||
|
||||
#endif
|
10
util/led/defs.h
Normal file
10
util/led/defs.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* $Header$ */
|
||||
|
||||
/*
|
||||
* We need the S_EXT because we leave locals alone.
|
||||
*/
|
||||
#define ISUNDEFINED(n) (((n)->on_type & (S_TYP | S_EXT)) == (S_UND | S_EXT))
|
||||
#define ISABSOLUTE(n) (((n)->on_type & (S_TYP | S_EXT)) == (S_ABS | S_EXT))
|
||||
#define ISCOMMON(n) (((n)->on_type & (S_COM | S_EXT)) == (S_COM | S_EXT))
|
||||
|
||||
#define mustsavelocal(name) (!((name)->on_type & S_SCT))
|
182
util/led/finish.c
Normal file
182
util/led/finish.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "defs.h"
|
||||
#include "memory.h"
|
||||
#include "orig.h"
|
||||
#include "scan.h"
|
||||
|
||||
extern bool incore;
|
||||
extern int flagword;
|
||||
|
||||
/*
|
||||
* We know all there is to know about the current module.
|
||||
* Now we relocate the values in the emitted bytes and write
|
||||
* those to the final output file. Then we compute the relative origins
|
||||
* for the next module.
|
||||
*/
|
||||
finish()
|
||||
{
|
||||
struct outhead *head;
|
||||
struct outsect *sects;
|
||||
struct outname *names;
|
||||
char *chars;
|
||||
|
||||
get_modul();
|
||||
head = (struct outhead *)modulptr(IND_HEAD);
|
||||
sects = (struct outsect *)modulptr(IND_SECT(*head));
|
||||
names = (struct outname *)modulptr(IND_NAME(*head));
|
||||
chars = (char *)modulptr(IND_CHAR(*head));
|
||||
adjust_names(names, head, chars);
|
||||
handle_relos(head, sects, names);
|
||||
if (!incore && !(flagword & SFLAG)) {
|
||||
put_locals(names, head->oh_nname, sects);
|
||||
#ifdef SYMDBUG
|
||||
put_dbug(OFF_DBUG(*head));
|
||||
#endif SYMDBUG
|
||||
}
|
||||
compute_origins(sects, head->oh_nsect);
|
||||
skip_modul(head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust all local names for the move into core.
|
||||
*/
|
||||
static
|
||||
adjust_names(name, head, chars)
|
||||
register struct outname *name;
|
||||
struct outhead *head;
|
||||
register char *chars;
|
||||
{
|
||||
register int cnt;
|
||||
register ind_t charoff;
|
||||
|
||||
cnt = head->oh_nname;
|
||||
charoff = OFF_CHAR(*head);
|
||||
while (cnt--) {
|
||||
if (name->on_foff != (long)0)
|
||||
name->on_mptr = chars + name->on_foff - charoff;
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If all sections are in core, we can access them randomly, so we need only
|
||||
* scan the relocation table once. Otherwise we must for each section scan
|
||||
* the relocation table again, because the relocation entries of one section
|
||||
* need not be consecutive.
|
||||
*/
|
||||
static
|
||||
handle_relos(head, sects, names)
|
||||
struct outhead *head;
|
||||
struct outsect *sects;
|
||||
struct outname *names;
|
||||
{
|
||||
register struct outrelo *relo;
|
||||
register int sectindex;
|
||||
register int nrelo;
|
||||
register char *emit;
|
||||
extern char *getemit();
|
||||
extern struct outrelo *nextrelo();
|
||||
|
||||
if (incore) {
|
||||
nrelo = head->oh_nrelo; sectindex = -1;
|
||||
startrelo(head); relo = nextrelo();
|
||||
while (nrelo--) {
|
||||
if (sectindex != relo->or_sect - S_MIN) {
|
||||
sectindex = relo->or_sect - S_MIN;
|
||||
emit = getemit(head, sects, sectindex);
|
||||
}
|
||||
relocate(head, emit, names, relo, sects);
|
||||
relo++;
|
||||
}
|
||||
} else {
|
||||
for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
|
||||
emit = getemit(head, sects, sectindex);
|
||||
nrelo = head->oh_nrelo; startrelo(head);
|
||||
while (nrelo--) {
|
||||
relo = nextrelo();
|
||||
if (relo->or_sect - S_MIN == sectindex) {
|
||||
relocate(head,emit,names,relo,sects);
|
||||
/*
|
||||
* Write out the (probably changed)
|
||||
* relocation information.
|
||||
*/
|
||||
if (flagword & RFLAG)
|
||||
wrt_relo(relo);
|
||||
}
|
||||
}
|
||||
wrt_emit(emit, sectindex, sects[sectindex].os_flen);
|
||||
/*
|
||||
* XXX We should be able to free the emitted bytes.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the local names that must be saved.
|
||||
*/
|
||||
static
|
||||
put_locals(name, nnames, sects)
|
||||
register struct outname *name;
|
||||
register ushort nnames;
|
||||
register struct outsect *sects;
|
||||
{
|
||||
while (nnames--) {
|
||||
if ((name->on_type & S_EXT) == 0 && mustsavelocal(name)) {
|
||||
namerelocate(name, sects);
|
||||
addbase(name);
|
||||
wrt_name(name);
|
||||
}
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add all flen's and all (size - flen == zero)'s of preceding sections
|
||||
* with the same number.
|
||||
*/
|
||||
static
|
||||
compute_origins(sect, nsect)
|
||||
register struct outsect *sect;
|
||||
register ushort nsect;
|
||||
{
|
||||
extern struct orig relorig[];
|
||||
register struct orig *orig = relorig;
|
||||
|
||||
while (nsect--) {
|
||||
orig->org_flen += sect->os_flen;
|
||||
orig->org_zero += sect->os_size - sect->os_flen;
|
||||
orig++; sect++;
|
||||
}
|
||||
}
|
||||
#ifdef SYMDBUG
|
||||
|
||||
/*
|
||||
* Write out what is after the string area. This is likely to be
|
||||
* debugging information.
|
||||
*/
|
||||
static
|
||||
put_dbug(offdbug)
|
||||
long offdbug;
|
||||
{
|
||||
char buf[512];
|
||||
register int nbytes;
|
||||
register long dbugsize;
|
||||
extern long objectsize;
|
||||
extern long position;
|
||||
|
||||
dbugsize = objectsize - offdbug;
|
||||
seek(position + offdbug);
|
||||
while (dbugsize) {
|
||||
nbytes = dbugsize > 512 ? 512 : dbugsize;
|
||||
read_char(buf, (long)nbytes);
|
||||
wrt_dbug(buf, nbytes);
|
||||
dbugsize -= nbytes;
|
||||
}
|
||||
}
|
||||
#endif SYMDBUG
|
24
util/led/mach.c
Normal file
24
util/led/mach.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* $Header$
|
||||
*/
|
||||
/*
|
||||
* Values depend on the machine on which this program should run.
|
||||
* Now for Vax 11/750.
|
||||
*/
|
||||
|
||||
#define K 1024
|
||||
|
||||
mems[ALLOEMIT + 0].mem_left = 64 * K;
|
||||
mems[ALLOEMIT + 1].mem_left = 64 * K;
|
||||
mems[ALLORELO].mem_left = 64 * K;
|
||||
mems[ALLOLOCL].mem_left = 64 * K;
|
||||
mems[ALLOGLOB].mem_left = 64 * K;
|
||||
mems[ALLOLCHR].mem_left = 64 * K;
|
||||
mems[ALLOGCHR].mem_left = 64 * K;
|
||||
#ifdef SYMDBUG
|
||||
mems[ALLODBUG].mem_left = 64 * K;
|
||||
#endif SYMDBUG
|
||||
mems[ALLOSYMB].mem_left = 4 * K;
|
||||
mems[ALLOARCH].mem_left = 1 * K;
|
||||
mems[ALLOMODL].mem_left = 3 * 64 * K;
|
||||
mems[ALLORANL].mem_left = 4 * K;
|
|
@ -9,7 +9,6 @@ static char rcsid[] = "$Header$";
|
|||
* is done and pieces after the one that requested the growth are moved up.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
|
@ -19,7 +18,7 @@ static char rcsid[] = "$Header$";
|
|||
struct memory mems[NMEMS];
|
||||
|
||||
bool incore = TRUE; /* TRUE while everything can be kept in core. */
|
||||
off_t core_position = (off_t)0; /* Index of current module. */
|
||||
ind_t core_position = (ind_t)0; /* Index of current module. */
|
||||
|
||||
#define AT_LEAST 2 /* See comment about string areas. */
|
||||
|
||||
|
@ -29,51 +28,18 @@ off_t core_position = (off_t)0; /* Index of current module. */
|
|||
*/
|
||||
init_core()
|
||||
{
|
||||
FILE *ledrc;
|
||||
int piece;
|
||||
off_t left;
|
||||
register char *base;
|
||||
register off_t total_size;
|
||||
register ind_t total_size;
|
||||
register struct memory *mem;
|
||||
extern char *sbrk();
|
||||
|
||||
#ifndef TJALK
|
||||
/*
|
||||
* Read in what should be allocated for each piece initially.
|
||||
* This facilitates testing, but is slower and should not
|
||||
* be done in the final version. XXX
|
||||
*/
|
||||
incore = (ledrc = fopen(".ledrc", "r")) != (FILE *)0;
|
||||
#include "mach.c"
|
||||
|
||||
if (incore) {
|
||||
while (fscanf(ledrc, "%d %d", &piece, &left) == 2)
|
||||
mems[piece].mem_left = left;
|
||||
fclose(ledrc);
|
||||
}
|
||||
#else TJALK
|
||||
mems[ALLOHEAD].mem_left = 20; /*XXX*/
|
||||
mems[ALLOSECT].mem_left = 60; /*XXX*/
|
||||
mems[ALLOEMIT + 0].mem_left = 65536;
|
||||
mems[ALLOEMIT + 1].mem_left = 65536;
|
||||
mems[ALLORELO].mem_left = 65536;
|
||||
mems[ALLOLOCL].mem_left = 65536;
|
||||
mems[ALLOGLOB].mem_left = 65536;
|
||||
mems[ALLOLCHR].mem_left = 65536;
|
||||
mems[ALLOGCHR].mem_left = 65536;
|
||||
#ifdef SYMDBUG
|
||||
mems[ALLODBUG].mem_left = 65536;
|
||||
#endif SYMDBUG
|
||||
mems[ALLOSYMB].mem_left = 4096;
|
||||
mems[ALLOARCH].mem_left = 512;
|
||||
mems[ALLOMODL].mem_left = 196608;
|
||||
mems[ALLORANL].mem_left = 4096;
|
||||
#endif TJALK
|
||||
|
||||
total_size = (off_t)0;/* Will accumulate the sizes. */
|
||||
total_size = (ind_t)0; /* Will accumulate the sizes. */
|
||||
base = sbrk(0); /* First free. */
|
||||
for (mem = mems; mem < &mems[NMEMS]; mem++) {
|
||||
mem->mem_base = base;
|
||||
mem->mem_full = (off_t)0;
|
||||
mem->mem_full = (ind_t)0;
|
||||
base += mem->mem_left; /* Each piece will start after prev. */
|
||||
total_size += mem->mem_left;
|
||||
}
|
||||
|
@ -93,12 +59,11 @@ init_core()
|
|||
mems[ALLOLCHR].mem_full = 1;
|
||||
mems[ALLOGCHR].mem_full = 1;
|
||||
|
||||
if ((int)sbrk(total_size) == -1) {
|
||||
if (total_size != (int)total_size || (int)sbrk((int)total_size) == -1) {
|
||||
incore = FALSE; /* In core strategy failed. */
|
||||
if ((int)sbrk(AT_LEAST) == -1)
|
||||
fatal("no core at all");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -109,13 +74,13 @@ init_core()
|
|||
static bool
|
||||
move_up(piece, incr)
|
||||
register int piece;
|
||||
register off_t incr;
|
||||
register ind_t incr;
|
||||
{
|
||||
register struct memory *mem;
|
||||
extern char *sbrk();
|
||||
|
||||
debug("move_up(%d, %d)\n", piece, (int)incr, 0, 0);
|
||||
if ((int)sbrk(incr) == -1)
|
||||
if (incr != (int)incr || (int)sbrk((int)incr) == -1)
|
||||
return FALSE;
|
||||
|
||||
for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--)
|
||||
|
@ -137,33 +102,33 @@ extern int passnumber;
|
|||
static bool
|
||||
compact(piece, incr)
|
||||
register int piece;
|
||||
register off_t incr;
|
||||
register ind_t incr;
|
||||
{
|
||||
register off_t gain;
|
||||
register ind_t gain;
|
||||
register struct memory *mem;
|
||||
|
||||
debug("compact(%d, %d)\n", piece, (int)incr, 0, 0);
|
||||
gain = mems[0].mem_left;
|
||||
mems[0].mem_left = (off_t)0;
|
||||
mems[0].mem_left = (ind_t)0;
|
||||
for (mem = &mems[1]; mem <= &mems[piece]; mem++) {
|
||||
/* Here memory is inserted before a piece. */
|
||||
assert(passnumber == FIRST || gain == (off_t)0);
|
||||
assert(passnumber == FIRST || gain == (ind_t)0);
|
||||
copy_down(mem, gain);
|
||||
gain += mem->mem_left;
|
||||
mem->mem_left = (off_t)0;
|
||||
mem->mem_left = (ind_t)0;
|
||||
}
|
||||
/*
|
||||
* Note that we already added the left bytes of the piece we want to
|
||||
* enlarge to `gain'.
|
||||
*/
|
||||
if (gain < incr) {
|
||||
register off_t up = (off_t)0;
|
||||
register ind_t up = (ind_t)0;
|
||||
|
||||
for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--) {
|
||||
/* Here memory is appended after a piece. */
|
||||
up += mem->mem_left;
|
||||
copy_up(mem, up);
|
||||
mem->mem_left = (off_t)0;
|
||||
mem->mem_left = (ind_t)0;
|
||||
}
|
||||
gain += up;
|
||||
}
|
||||
|
@ -180,11 +145,11 @@ compact(piece, incr)
|
|||
static
|
||||
copy_down(mem, dist)
|
||||
register struct memory *mem;
|
||||
off_t dist;
|
||||
ind_t dist;
|
||||
{
|
||||
register char *old;
|
||||
register char *new;
|
||||
register off_t size;
|
||||
register ind_t size;
|
||||
|
||||
size = mem->mem_full;
|
||||
old = mem->mem_base;
|
||||
|
@ -203,11 +168,11 @@ copy_down(mem, dist)
|
|||
static
|
||||
copy_up(mem, dist)
|
||||
register struct memory *mem;
|
||||
off_t dist;
|
||||
ind_t dist;
|
||||
{
|
||||
register char *old;
|
||||
register char *new;
|
||||
register off_t size;
|
||||
register ind_t size;
|
||||
|
||||
size = mem->mem_full;
|
||||
old = mem->mem_base + size;
|
||||
|
@ -224,18 +189,20 @@ copy_up(mem, dist)
|
|||
* how many times the area is moved, because of another allocate, this offset
|
||||
* remains valid.
|
||||
*/
|
||||
off_t
|
||||
ind_t
|
||||
alloc(piece, size)
|
||||
register int piece;
|
||||
register off_t size;
|
||||
register long size;
|
||||
{
|
||||
register off_t incr = 0;
|
||||
register off_t left = mems[piece].mem_left;
|
||||
register off_t full = mems[piece].mem_full;
|
||||
register ind_t incr = 0;
|
||||
register ind_t left = mems[piece].mem_left;
|
||||
register ind_t full = mems[piece].mem_full;
|
||||
|
||||
assert(passnumber == FIRST || (!incore && piece == ALLOMODL));
|
||||
if (size == (off_t)0)
|
||||
if (size == (long)0)
|
||||
return full;
|
||||
if (size != (ind_t)size)
|
||||
return BADOFF;
|
||||
|
||||
while (left + incr < size)
|
||||
incr += INCRSIZE;
|
||||
|
@ -254,14 +221,16 @@ alloc(piece, size)
|
|||
* Same as alloc() but for a piece which really needs it. If the first
|
||||
* attempt fails, release the space occupied by other pieces and try again.
|
||||
*/
|
||||
off_t
|
||||
ind_t
|
||||
hard_alloc(piece, size)
|
||||
int piece;
|
||||
off_t size;
|
||||
register int piece;
|
||||
register long size;
|
||||
{
|
||||
off_t ret;
|
||||
register ind_t ret;
|
||||
register int i;
|
||||
|
||||
if (size != (ind_t)size)
|
||||
return BADOFF;
|
||||
if ((ret = alloc(piece, size)) != BADOFF)
|
||||
return ret;
|
||||
|
||||
|
@ -270,8 +239,6 @@ hard_alloc(piece, size)
|
|||
*/
|
||||
for (i = 0; i < NMEMS; i++) {
|
||||
switch (i) {
|
||||
case ALLOHEAD:
|
||||
case ALLOSECT:
|
||||
case ALLOGLOB:
|
||||
case ALLOGCHR:
|
||||
case ALLOSYMB:
|
||||
|
@ -296,7 +263,7 @@ hard_alloc(piece, size)
|
|||
static
|
||||
free_saved_moduls()
|
||||
{
|
||||
register off_t size;
|
||||
register ind_t size;
|
||||
register char *old, *new;
|
||||
register struct memory *mem = &mems[ALLOMODL];
|
||||
|
||||
|
@ -307,7 +274,7 @@ free_saved_moduls()
|
|||
*new++ = *old++;
|
||||
mem->mem_full -= core_position;
|
||||
mem->mem_left += core_position;
|
||||
core_position = (off_t)0;
|
||||
core_position = (ind_t)0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -320,22 +287,20 @@ dealloc(piece)
|
|||
/*
|
||||
* Some pieces need their memory throughout the program.
|
||||
*/
|
||||
assert(piece != ALLOHEAD);
|
||||
assert(piece != ALLOSECT);
|
||||
assert(piece != ALLOGLOB);
|
||||
assert(piece != ALLOGCHR);
|
||||
assert(piece != ALLOSYMB);
|
||||
assert(piece != ALLOARCH);
|
||||
mems[piece].mem_left += mems[piece].mem_full;
|
||||
mems[piece].mem_full = (off_t)0;
|
||||
mems[piece].mem_full = (ind_t)0;
|
||||
}
|
||||
|
||||
char *
|
||||
core_alloc(piece, size)
|
||||
register int piece;
|
||||
register off_t size;
|
||||
register long size;
|
||||
{
|
||||
register off_t off;
|
||||
register ind_t off;
|
||||
|
||||
if ((off = alloc(piece, size)) == BADOFF)
|
||||
return (char *)0;
|
||||
|
@ -350,15 +315,13 @@ freeze_core()
|
|||
{
|
||||
register int i;
|
||||
|
||||
core_position = (off_t)0;
|
||||
core_position = (ind_t)0;
|
||||
|
||||
if (incore)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NMEMS; i++) {
|
||||
switch (i) {
|
||||
case ALLOHEAD:
|
||||
case ALLOSECT:
|
||||
case ALLOGLOB:
|
||||
case ALLOGCHR:
|
||||
case ALLOSYMB:
|
||||
|
@ -369,7 +332,7 @@ freeze_core()
|
|||
break;
|
||||
}
|
||||
}
|
||||
compact(NMEMS - 1, (off_t)0);
|
||||
compact(NMEMS - 1, (ind_t)0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -383,24 +346,24 @@ extern bool words_reversed;
|
|||
*/
|
||||
write_bytes()
|
||||
{
|
||||
register struct outhead *head;
|
||||
ushort nsect, nrelo;
|
||||
long offchar;
|
||||
int fd;
|
||||
register int piece;
|
||||
extern ushort NLocals, NGlobals;
|
||||
extern long NLChars, NGChars;
|
||||
extern int flagword;
|
||||
extern char *outputname;
|
||||
ushort nsect, nrelo;
|
||||
long offchar;
|
||||
int fd;
|
||||
register struct memory *mem;
|
||||
extern ushort NLocals, NGlobals;
|
||||
extern long NLChars, NGChars;
|
||||
extern int flagword;
|
||||
extern struct outhead outhead;
|
||||
extern struct outsect outsect[];
|
||||
extern char *outputname;
|
||||
|
||||
head = (struct outhead *)mems[ALLOHEAD].mem_base;
|
||||
nsect = head->oh_nsect;
|
||||
nrelo = head->oh_nrelo;
|
||||
offchar = OFF_CHAR(*head);
|
||||
nsect = outhead.oh_nsect;
|
||||
nrelo = outhead.oh_nrelo;
|
||||
offchar = OFF_CHAR(outhead);
|
||||
|
||||
if (bytes_reversed || words_reversed) {
|
||||
headswap();
|
||||
sectswap(nsect);
|
||||
swap((char *)&outhead, SF_HEAD);
|
||||
sectswap(outsect, nsect);
|
||||
reloswap(nrelo);
|
||||
}
|
||||
/*
|
||||
|
@ -423,8 +386,10 @@ write_bytes()
|
|||
/*
|
||||
* These pieces must always be written.
|
||||
*/
|
||||
for (piece = ALLOHEAD; piece < ALLORELO; piece++)
|
||||
writelong(fd, mems[piece].mem_base, mems[piece].mem_full);
|
||||
writelong(fd, (char *)&outhead, (ind_t)SZ_HEAD);
|
||||
writelong(fd, (char *)outsect, (ind_t)nsect * SZ_SECT);
|
||||
for (mem = &mems[ALLOEMIT]; mem < &mems[ALLORELO]; mem++)
|
||||
writelong(fd, mem->mem_base, mem->mem_full);
|
||||
/*
|
||||
* The rest depends on the flags.
|
||||
*/
|
||||
|
@ -433,10 +398,10 @@ write_bytes()
|
|||
if (!(flagword & SFLAG)) {
|
||||
writelong(fd, mems[ALLOLOCL].mem_base, mems[ALLOLOCL].mem_full);
|
||||
writelong(fd, mems[ALLOGLOB].mem_base, mems[ALLOGLOB].mem_full);
|
||||
writelong(fd, mems[ALLOLCHR].mem_base + 1, NLChars);
|
||||
writelong(fd, mems[ALLOGCHR].mem_base + 1, NGChars);
|
||||
writelong(fd, mems[ALLOLCHR].mem_base + 1, (ind_t)NLChars);
|
||||
writelong(fd, mems[ALLOGCHR].mem_base + 1, (ind_t)NGChars);
|
||||
#ifdef SYMDBUG
|
||||
writelong(fd, mems[ALLODBUG].mem_base, mems[ALLODBUG].mem_size);
|
||||
writelong(fd, mems[ALLODBUG].mem_base, mems[ALLODBUG].mem_full);
|
||||
#endif SYMDBUG
|
||||
}
|
||||
close(fd);
|
||||
|
@ -446,12 +411,12 @@ static
|
|||
writelong(fd, base, size)
|
||||
register int fd;
|
||||
register char *base;
|
||||
register off_t size;
|
||||
register ind_t size;
|
||||
{
|
||||
register int chunk;
|
||||
|
||||
while (size) {
|
||||
chunk = size > (off_t)MAXCHUNK ? MAXCHUNK : size;
|
||||
chunk = size > (ind_t)MAXCHUNK ? MAXCHUNK : size;
|
||||
write(fd, base, chunk);
|
||||
size -= chunk;
|
||||
base += chunk;
|
||||
|
@ -459,21 +424,10 @@ writelong(fd, base, size)
|
|||
}
|
||||
|
||||
static
|
||||
headswap()
|
||||
{
|
||||
register struct outhead *head;
|
||||
|
||||
head = (struct outhead *)mems[ALLOHEAD].mem_base;
|
||||
swap((char *)head, SF_HEAD);
|
||||
}
|
||||
|
||||
static
|
||||
sectswap(nsect)
|
||||
sectswap(sect, nsect)
|
||||
register struct outsect *sect;
|
||||
register ushort nsect;
|
||||
{
|
||||
register struct outsect *sect;
|
||||
|
||||
sect = (struct outsect *)mems[ALLOSECT].mem_base;
|
||||
while (nsect--)
|
||||
swap((char *)sect++, SF_SECT);
|
||||
}
|
||||
|
|
35
util/led/memory.h
Normal file
35
util/led/memory.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* $Header$ */
|
||||
|
||||
#define ALLOEMIT 0 /* Section contents. */
|
||||
#define ALLORELO (ALLOEMIT + MAXSECT) /* Relocation table. */
|
||||
#define ALLOLOCL (ALLORELO + 1) /* Saved local names. */
|
||||
#define ALLOGLOB (ALLOLOCL + 1) /* Saved global names. */
|
||||
#define ALLOLCHR (ALLOGLOB + 1) /* Strings of local names. */
|
||||
#define ALLOGCHR (ALLOLCHR + 1) /* Strings of global names. */
|
||||
#ifdef SYMDEBUG
|
||||
#define ALLODBUG (ALLOGCHR + 1) /* Symbolic debugging info. */
|
||||
#else SYMDEBUG
|
||||
#define ALLODBUG ALLOGCHR
|
||||
#endif SYMDEBUG
|
||||
#define ALLOSYMB (ALLODBUG + 1) /* Symbol table. */
|
||||
#define ALLOARCH (ALLOSYMB + 1) /* Archive positions. */
|
||||
#define ALLOMODL (ALLOARCH + 1) /* Modules. */
|
||||
#define ALLORANL (ALLOMODL + 1) /* Ranlib information. */
|
||||
#define NMEMS (ALLORANL + 1)
|
||||
|
||||
#define INCRSIZE 1024
|
||||
|
||||
typedef unsigned int ind_t;
|
||||
#define BADOFF ((ind_t)-1)
|
||||
|
||||
struct memory {
|
||||
char *mem_base;
|
||||
ind_t mem_full;
|
||||
ind_t mem_left;
|
||||
};
|
||||
extern struct memory mems[];
|
||||
|
||||
#define address(piece,offset) (mems[(piece)].mem_base+(offset))
|
||||
#define modulptr(offset) (mems[ALLOMODL].mem_base+core_position+(offset))
|
||||
|
||||
extern ind_t core_position;
|
6
util/led/orig.h
Normal file
6
util/led/orig.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* $Header$ */
|
||||
|
||||
struct orig {
|
||||
long org_flen; /* Accumulated length of preceding sections. */
|
||||
long org_zero; /* " " " zeroparts. */
|
||||
};
|
134
util/led/read.c
Normal file
134
util/led/read.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Routines to read in the various parts of the object file.
|
||||
*/
|
||||
|
||||
#include "arch.h"
|
||||
#include "out.h"
|
||||
#include "ranlib.h"
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
|
||||
int infile; /* The current input file. */
|
||||
|
||||
extern bool bytes_reversed;
|
||||
extern bool words_reversed;
|
||||
|
||||
ushort
|
||||
getushort()
|
||||
{
|
||||
ushort ubuf;
|
||||
|
||||
if (read(infile, (char *)&ubuf, 2) != 2)
|
||||
fatal("premature EOF");
|
||||
if (bytes_reversed)
|
||||
swap((char *)&ubuf, "2");
|
||||
return ubuf;
|
||||
}
|
||||
|
||||
long
|
||||
getlong()
|
||||
{
|
||||
long lbuf;
|
||||
|
||||
if (read(infile, (char *)&lbuf, 4) != 4)
|
||||
fatal("premature EOF");
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)&lbuf, "4");
|
||||
return lbuf;
|
||||
}
|
||||
|
||||
read_head(head)
|
||||
register struct outhead *head;
|
||||
{
|
||||
if (read(infile, (char *)head, SZ_HEAD) != SZ_HEAD)
|
||||
fatal("premature EOF");
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)head, SF_HEAD);
|
||||
if (BADMAGIC(*head))
|
||||
fatal("bad magic number");
|
||||
}
|
||||
|
||||
/*
|
||||
* Someone inadvertently misaligned a long, thereby creating a hole.
|
||||
* Therefore we can't read the header in one chunk.
|
||||
*/
|
||||
read_arhdr(arhdr)
|
||||
register struct ar_hdr *arhdr;
|
||||
{
|
||||
if (read(infile, (char *)arhdr, 14) != 14)
|
||||
fatal("premature EOF");
|
||||
if (read(infile, (char *)&arhdr->ar_date, SZ_ARCH - 14) != SZ_ARCH - 14)
|
||||
fatal("premature EOF");
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)&arhdr->ar_date, SF_ARCH);
|
||||
}
|
||||
|
||||
read_table(ran, cnt)
|
||||
register struct ranlib *ran;
|
||||
register long cnt;
|
||||
{
|
||||
read_char((char *)ran, cnt * SZ_RAN);
|
||||
if (bytes_reversed || words_reversed)
|
||||
while (cnt--)
|
||||
swap((char *)ran++, SF_RAN);
|
||||
}
|
||||
|
||||
read_sect(sect, cnt)
|
||||
register struct outsect *sect;
|
||||
register ushort cnt;
|
||||
{
|
||||
if (read(infile, (char *)sect, cnt * SZ_SECT) != cnt * SZ_SECT)
|
||||
fatal("premature EOF");
|
||||
if (bytes_reversed || words_reversed)
|
||||
while (cnt--)
|
||||
swap((char *)sect++, SF_SECT);
|
||||
}
|
||||
|
||||
read_emit(emit, cnt)
|
||||
register char *emit;
|
||||
register long cnt;
|
||||
{
|
||||
read_char(emit, cnt);
|
||||
}
|
||||
|
||||
read_relo(relo, cnt)
|
||||
register struct outrelo *relo;
|
||||
register ushort cnt;
|
||||
{
|
||||
read_char((char *)relo, (long)cnt * SZ_RELO);
|
||||
if (bytes_reversed || words_reversed)
|
||||
while (cnt--)
|
||||
swap((char *)relo++, SF_RELO);
|
||||
}
|
||||
|
||||
read_name(name, cnt)
|
||||
register struct outname *name;
|
||||
register ushort cnt;
|
||||
{
|
||||
read_char((char *)name, (long)cnt * SZ_NAME);
|
||||
if (bytes_reversed || words_reversed)
|
||||
while (cnt--)
|
||||
swap((char *)name++, SF_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
*/
|
||||
read_char(string, cnt)
|
||||
register char *string;
|
||||
register long cnt;
|
||||
{
|
||||
register int n;
|
||||
|
||||
while (cnt) {
|
||||
n = cnt >= MAXCHUNK ? MAXCHUNK : cnt;
|
||||
if (read(infile, string, n) != n)
|
||||
fatal("premature EOF");
|
||||
string += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
256
util/led/relocate.c
Normal file
256
util/led/relocate.c
Normal file
|
@ -0,0 +1,256 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "debug.h"
|
||||
#include "defs.h"
|
||||
#include "orig.h"
|
||||
|
||||
#define UBYTE(x) ((x) & BYTEMASK)
|
||||
|
||||
/*
|
||||
* The bits in type indicate how many bytes the value occupies and what
|
||||
* significance should be attributed to each byte.
|
||||
*/
|
||||
static long
|
||||
getvalu(addr, type)
|
||||
char addr[];
|
||||
char type;
|
||||
{
|
||||
ushort word0, word1;
|
||||
|
||||
switch (type & RELSZ) {
|
||||
case RELO1:
|
||||
return UBYTE(addr[0]);
|
||||
case RELO2:
|
||||
if (type & RELBR)
|
||||
return (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
|
||||
else
|
||||
return (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
|
||||
case RELO4:
|
||||
if (type & RELBR) {
|
||||
word0 = (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]);
|
||||
word1 = (UBYTE(addr[2]) << WIDTH) + UBYTE(addr[3]);
|
||||
} else {
|
||||
word0 = (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]);
|
||||
word1 = (UBYTE(addr[3]) << WIDTH) + UBYTE(addr[2]);
|
||||
}
|
||||
if (type & RELWR)
|
||||
return ((long)word0 << (2 * WIDTH)) + word1;
|
||||
else
|
||||
return ((long)word1 << (2 * WIDTH)) + word0;
|
||||
default:
|
||||
fatal("bad relocation size");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* The bits in type indicate how many bytes the value occupies and what
|
||||
* significance should be attributed to each byte.
|
||||
* We do not check for overflow.
|
||||
*/
|
||||
static
|
||||
putvalu(valu, addr, type)
|
||||
long valu;
|
||||
char addr[];
|
||||
char type;
|
||||
{
|
||||
ushort word0, word1;
|
||||
|
||||
switch (type & RELSZ) {
|
||||
case RELO1:
|
||||
addr[0] = valu;
|
||||
break;
|
||||
case RELO2:
|
||||
if (type & RELBR) {
|
||||
addr[0] = valu >> WIDTH;
|
||||
addr[1] = valu;
|
||||
} else {
|
||||
addr[0] = valu;
|
||||
addr[1] = valu >> WIDTH;
|
||||
}
|
||||
break;
|
||||
case RELO4:
|
||||
if (type & RELWR) {
|
||||
word0 = valu >> (2 * WIDTH);
|
||||
word1 = valu;
|
||||
} else {
|
||||
word0 = valu;
|
||||
word1 = valu >> (2 * WIDTH);
|
||||
}
|
||||
if (type & RELBR) {
|
||||
addr[0] = word0 >> WIDTH;
|
||||
addr[1] = word0;
|
||||
addr[2] = word1 >> WIDTH;
|
||||
addr[3] = word1;
|
||||
} else {
|
||||
addr[0] = word0;
|
||||
addr[1] = word0 >> WIDTH;
|
||||
addr[2] = word1;
|
||||
addr[3] = word1 >> WIDTH;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal("bad relocation size");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether `valu' refers to the zero part of its section.
|
||||
* The address of its zero part (relative to the beginning of the section)
|
||||
* is in `zero_addr'. If `valu' is used in a pc-relative address computation,
|
||||
* we have to do that computation ourselves. A pc-relative address is the
|
||||
* difference between the address of the byte after the value and the "real"
|
||||
* address:
|
||||
* referencing address + its size + pc-relative address == "real" address.
|
||||
*/
|
||||
static bool
|
||||
refers_zero(valu, relo, zero_addr)
|
||||
register long valu;
|
||||
struct outrelo *relo;
|
||||
long zero_addr;
|
||||
{
|
||||
if (relo->or_type & RELPC) {
|
||||
valu += relo->or_addr;
|
||||
/*
|
||||
* Below is a dirty switch-statement. But an even dirtier
|
||||
* statement would be: valu += (relo->or_type & RELSZ),
|
||||
* because in that case you would have to know the values
|
||||
* of the RELO[124] symbols.
|
||||
*/
|
||||
switch (relo->or_type & RELSZ) {
|
||||
case RELO4: valu += 1;
|
||||
valu += 1;
|
||||
case RELO2: valu += 1;
|
||||
case RELO1: valu += 1;
|
||||
}
|
||||
}
|
||||
return valu >= zero_addr;
|
||||
}
|
||||
|
||||
extern ushort NLocals, NGlobals;
|
||||
extern struct outsect outsect[];
|
||||
extern struct orig relorig[];
|
||||
|
||||
/*
|
||||
* There are two cases: `local' is an undefined external or common name,
|
||||
* or `local' is a section name.
|
||||
* First case: if the name has been defined in another module,
|
||||
* its value is known and can be added. Or_nami will be the
|
||||
* index of the name of the section in which this name was
|
||||
* defined. Otherwise we must change or_nami to the index of
|
||||
* this name in the name table of the output file and leave
|
||||
* its value unchanged.
|
||||
* Second case: we must update the value by the change
|
||||
* in position of the section of local.
|
||||
*/
|
||||
static ushort
|
||||
addrelo(relo, names, sects, valu_out)
|
||||
struct outrelo *relo;
|
||||
struct outname *names;
|
||||
struct outsect *sects;
|
||||
long *valu_out; /* Out variable. */
|
||||
{
|
||||
register struct outname *local = &names[relo->or_nami];
|
||||
register ushort index = NLocals;
|
||||
register long valu = *valu_out;
|
||||
|
||||
if (ISUNDEFINED(local) || ISCOMMON(local)) {
|
||||
register struct outname *name;
|
||||
extern int hash();
|
||||
extern struct outname *searchname();
|
||||
extern ushort indexof();
|
||||
|
||||
name = searchname(local->on_mptr, hash(local->on_mptr));
|
||||
if (name == (struct outname *)0)
|
||||
fatal("name %s not found in pass 2", local->on_mptr);
|
||||
if (ISCOMMON(name) || ISUNDEFINED(name)) {
|
||||
debug("can't relocate from %s\n",local->on_mptr,0,0,0);
|
||||
index += indexof(name);
|
||||
} else {
|
||||
valu += name->on_valu;
|
||||
index += NGlobals + (name->on_type & S_TYP) - S_MIN;
|
||||
}
|
||||
} else {
|
||||
register int sectindex = (local->on_type & S_TYP) - S_MIN;
|
||||
|
||||
if (!(local->on_type & S_SCT))
|
||||
fatal("bad relocation index");
|
||||
if (refers_zero(valu, relo, sects[sectindex].os_flen)) {
|
||||
valu -= sects[sectindex].os_flen;
|
||||
valu += outsect[sectindex].os_flen;
|
||||
valu += relorig[sectindex].org_zero;
|
||||
} else {
|
||||
valu += relorig[sectindex].org_flen;
|
||||
}
|
||||
valu += outsect[sectindex].os_base;
|
||||
index += NGlobals + sectindex;
|
||||
}
|
||||
*valu_out = valu;
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine relocates a value in a section pointed to by `emit', of
|
||||
* which the header is pointed to by `head'. Relocation is relative to the
|
||||
* names in `names'; `relo' tells how to relocate.
|
||||
*/
|
||||
relocate(head, emit, names, relo, sects)
|
||||
struct outhead *head;
|
||||
char *emit;
|
||||
struct outname names[];
|
||||
struct outrelo *relo;
|
||||
struct outsect *sects;
|
||||
{
|
||||
long valu;
|
||||
int sectindex = relo->or_sect - S_MIN;
|
||||
extern struct outhead outhead;
|
||||
|
||||
/*
|
||||
* Pick up previous value at location to be relocated.
|
||||
*/
|
||||
valu = getvalu(emit + relo->or_addr, relo->or_type);
|
||||
/*
|
||||
* Or_nami is an index in the name table of the considered module.
|
||||
* The name of which it is an index can be:
|
||||
* - an undefined external or a common name
|
||||
* - a section name
|
||||
* - the first name outside! the name table (argh)
|
||||
*/
|
||||
if (relo->or_nami < head->oh_nname) {
|
||||
/* First two cases. */
|
||||
relo->or_nami = addrelo(relo, names, sects, &valu);
|
||||
} else {
|
||||
/*
|
||||
* Third case: it is absolute. The relocation of absolute
|
||||
* names is always 0. We only need to change the index.
|
||||
*/
|
||||
relo->or_nami = NLocals + NGlobals + outhead.oh_nsect;
|
||||
}
|
||||
|
||||
/*
|
||||
* If relocation is pc-relative, we had to update the value by
|
||||
* the change in distance between the referencING and referencED
|
||||
* section. We already added the origin of the referencED section;
|
||||
* now we subtract the origin of the referencING section.
|
||||
* Note that the the value to be relocated cannot lie within the
|
||||
* zero part.
|
||||
*/
|
||||
if (relo->or_type & RELPC)
|
||||
valu -= relorig[sectindex].org_flen+outsect[sectindex].os_base;
|
||||
|
||||
/*
|
||||
* Now put the value back.
|
||||
*/
|
||||
putvalu(valu, emit + relo->or_addr, relo->or_type);
|
||||
|
||||
/*
|
||||
* We must change the offset within the section of the value to be
|
||||
* relocated to its offset in the new section. `Or_addr' must again be
|
||||
* in the normal part, of course.
|
||||
*/
|
||||
relo->or_addr += relorig[sectindex].org_flen;
|
||||
}
|
104
util/led/save.c
Normal file
104
util/led/save.c
Normal file
|
@ -0,0 +1,104 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If everything is kept in core, we must save some things for the second pass.
|
||||
*/
|
||||
|
||||
#include "arch.h"
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
#include "memory.h"
|
||||
|
||||
extern bool incore;
|
||||
extern char *core_alloc();
|
||||
|
||||
savemagic()
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (!incore)
|
||||
return;
|
||||
|
||||
if ((p = core_alloc(ALLOMODL, (long)sizeof(ushort))) != (char *)0) {
|
||||
*(ushort *)p = ARMAG;
|
||||
core_position += sizeof(ushort);
|
||||
}
|
||||
}
|
||||
|
||||
savehdr(hdr)
|
||||
struct ar_hdr *hdr;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
if (!incore)
|
||||
return;
|
||||
|
||||
if ((p=core_alloc(ALLOMODL,(long)sizeof(struct ar_hdr)))!=(char *)0) {
|
||||
*(struct ar_hdr *)p = *hdr;
|
||||
core_position += sizeof(struct ar_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
long NLChars = 0; /* Size of string area for local names. */
|
||||
long NGChars = 0; /* Idem for global names. */
|
||||
|
||||
/*
|
||||
* Put the string in cp into the block allocated for the string area.
|
||||
* Return its offset in this area. We don't use the first char of the string
|
||||
* area, so that empty strings can be distinguished from the first string.
|
||||
*/
|
||||
ind_t
|
||||
savechar(piece, off)
|
||||
register int piece;
|
||||
register ind_t off;
|
||||
{
|
||||
register long len;
|
||||
register ind_t newoff;
|
||||
extern int strlen();
|
||||
extern ind_t alloc();
|
||||
extern ind_t hard_alloc();
|
||||
extern char *strcpy();
|
||||
|
||||
if (off == (ind_t)0)
|
||||
return 0;
|
||||
|
||||
len = strlen(modulptr(off)) + 1;
|
||||
if (piece == ALLOLCHR) {
|
||||
NLChars += len;
|
||||
if (!incore || (newoff = alloc(piece, len)) == BADOFF)
|
||||
return BADOFF;
|
||||
} else {
|
||||
assert(piece == ALLOGCHR);
|
||||
NGChars += len;
|
||||
if ((newoff = hard_alloc(piece, len)) == BADOFF)
|
||||
return BADOFF;
|
||||
}
|
||||
strcpy(address(piece, newoff), modulptr(off));
|
||||
return newoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the local in `name' in the piece allocated for local names that must
|
||||
* be saved. `Name' points to a private copy, so will not become invalid after
|
||||
* allocation, but the string of which name->on_foff is the offset may be
|
||||
* destroyed, so we save that first.
|
||||
*/
|
||||
savelocal(name)
|
||||
struct outname *name;
|
||||
{
|
||||
ind_t savindex;
|
||||
struct outname *new;
|
||||
|
||||
if ((savindex = savechar(ALLOLCHR, (ind_t)name->on_foff)) == BADOFF)
|
||||
return;
|
||||
|
||||
new = (struct outname *)
|
||||
core_alloc(ALLOLOCL, (long)sizeof(struct outname));
|
||||
if (new != (struct outname *)0) {
|
||||
*new = *name;
|
||||
new->on_foff = savindex;
|
||||
}
|
||||
}
|
524
util/led/scan.c
Normal file
524
util/led/scan.c
Normal file
|
@ -0,0 +1,524 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
#ifdef SYMDBUG
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif SYMDBUG
|
||||
#include "arch.h"
|
||||
#include "out.h"
|
||||
#include "ranlib.h"
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
#include "memory.h"
|
||||
#include "scan.h"
|
||||
|
||||
#define READ 0
|
||||
|
||||
#define IND_EMIT(x) (IND_CHAR(x) + (ind_t)align((x).oh_nchar))
|
||||
#define IND_RELO(x) (IND_EMIT(x) + (x).oh_nsect * sizeof(ind_t))
|
||||
#ifdef SYMDBUG
|
||||
#define IND_DBUG(x) (IND_RELO(x) + sizeof(ind_t))
|
||||
#endif SYMDBUG
|
||||
|
||||
extern long lseek();
|
||||
extern bool incore;
|
||||
extern int infile;
|
||||
extern int passnumber;
|
||||
|
||||
char *archname; /* Name of archive, if reading from archive. */
|
||||
char *modulname; /* Name of object module. */
|
||||
long position; /* Byte offset within cuurent input file. */
|
||||
#ifdef SYMDBUG
|
||||
long objectsize;
|
||||
#endif SYMDBUG
|
||||
|
||||
static long align();
|
||||
static char *modulbase;
|
||||
static long modulsize();
|
||||
|
||||
/*
|
||||
* Open the file with name `filename' (if necessary) and examine the first
|
||||
* few bytes to see if it's a plain file or an archive.
|
||||
* In case of a plain file, the file pointer is repositioned after the
|
||||
* examination. Otherwise it is at the beginning of the table of contents.
|
||||
*/
|
||||
int
|
||||
getfile(filename)
|
||||
char *filename;
|
||||
{
|
||||
struct ar_hdr archive_header;
|
||||
ushort magic_number;
|
||||
#ifdef SYMDBUG
|
||||
struct stat statbuf;
|
||||
extern int fstat();
|
||||
#endif SYMDBUG
|
||||
extern ushort getushort();
|
||||
|
||||
archname = (char *)0;
|
||||
modulname = (char *)0;
|
||||
|
||||
if (passnumber == FIRST || !incore) {
|
||||
if ((infile = open(filename, READ)) < 0)
|
||||
fatal("can't read %s", filename);
|
||||
magic_number = getushort();
|
||||
} else {
|
||||
modulbase = modulptr((ind_t)0);
|
||||
magic_number = *(ushort *)modulbase;
|
||||
}
|
||||
|
||||
switch (magic_number) {
|
||||
case O_MAGIC:
|
||||
#ifdef SYMDBUG
|
||||
if (passnumber == FIRST || !incore) {
|
||||
if (fstat(infile, &statbuf) < 0)
|
||||
fatal("cannot stat");
|
||||
objectsize = statbuf.st_size;
|
||||
}
|
||||
#endif SYMDBUG
|
||||
position = (long)0;
|
||||
seek((long)0);
|
||||
modulname = filename;
|
||||
return PLAIN;
|
||||
case ARMAG:
|
||||
archname = filename;
|
||||
if (passnumber == FIRST) {
|
||||
read_arhdr(&archive_header);
|
||||
if (strcmp(archive_header.ar_name, SYMDEF))
|
||||
fatal("no table of contents");
|
||||
} else if (incore) {
|
||||
modulbase += sizeof(ushort);
|
||||
core_position += sizeof(ushort);
|
||||
}
|
||||
return ARCHIVE;
|
||||
default:
|
||||
fatal("wrong magic number");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
closefile(filename)
|
||||
char *filename;
|
||||
{
|
||||
if (passnumber == FIRST || !incore)
|
||||
close(infile);
|
||||
}
|
||||
|
||||
get_archive_header(archive_header)
|
||||
register struct ar_hdr *archive_header;
|
||||
{
|
||||
if (passnumber == FIRST || !incore) {
|
||||
read_arhdr(archive_header);
|
||||
} else {
|
||||
/* Copy structs. */
|
||||
*archive_header = *(struct ar_hdr *)modulbase;
|
||||
modulbase += sizeof(struct ar_hdr);
|
||||
core_position += sizeof(struct ar_hdr);
|
||||
}
|
||||
#ifdef SYMDBUG
|
||||
objectsize = archive_header.ar_size;
|
||||
#endif SYMDBUG
|
||||
}
|
||||
|
||||
get_modul()
|
||||
{
|
||||
if (passnumber == FIRST) {
|
||||
scan_modul();
|
||||
} else if (!incore) {
|
||||
read_modul();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read module from the current file. If it doesn't fit into core, the strategy
|
||||
* to keep everything in core is abandoned, but we will always put the header,
|
||||
* the section table, and the name and string table into core.
|
||||
*/
|
||||
static
|
||||
scan_modul()
|
||||
{
|
||||
bool space;
|
||||
struct outhead *head;
|
||||
struct outsect *sect;
|
||||
|
||||
space = all_alloc();
|
||||
head = (struct outhead *)modulptr(IND_HEAD);
|
||||
if (space) {
|
||||
sect = (struct outsect *)modulptr(IND_SECT(*head));
|
||||
get_indirect(head, sect);
|
||||
} else {
|
||||
lseek(infile, OFF_NAME(*head) - OFF_EMIT(*head), 1);
|
||||
}
|
||||
read_name((struct outname *)modulptr(IND_NAME(*head)), head->oh_nname);
|
||||
read_char((char *)modulptr(IND_CHAR(*head)), head->oh_nchar);
|
||||
#ifdef SYMDBUG
|
||||
if (space) {
|
||||
get_dbug(*(ind_t *)modulptr(IND_DBUG(*head)),
|
||||
ojectsize - OFF_DBUG(*head)
|
||||
);
|
||||
}
|
||||
#endif SYMDBUG
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for and read in the header and section table.
|
||||
* First get the header. With this we can determine what to allocate
|
||||
* for the rest of the module, and with the rest we can determine what
|
||||
* to allocate for the section contents.
|
||||
* If possible, allocate space for the rest of the module. Return whether
|
||||
* this was possible.
|
||||
*/
|
||||
static bool
|
||||
all_alloc()
|
||||
{
|
||||
struct outhead head;
|
||||
extern ind_t hard_alloc();
|
||||
|
||||
if (hard_alloc(ALLOMODL, (long)sizeof(struct outhead)) == BADOFF)
|
||||
fatal("no space for module header");
|
||||
read_head((struct outhead *)modulptr(IND_HEAD));
|
||||
/*
|
||||
* Copy the header because we need it so often.
|
||||
*/
|
||||
head = *(struct outhead *)modulptr(IND_HEAD);
|
||||
return direct_alloc(&head) && indirect_alloc(&head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the rest of the direct bytes.
|
||||
* First allocate the section table and read it in, then allocate the rest
|
||||
* and return whether this succeeded.
|
||||
*/
|
||||
static bool
|
||||
direct_alloc(head)
|
||||
struct outhead *head;
|
||||
{
|
||||
ind_t sectindex = IND_SECT(*head);
|
||||
ushort nsect = head->oh_nsect;
|
||||
long size, rest;
|
||||
extern ind_t hard_alloc();
|
||||
extern ind_t alloc();
|
||||
|
||||
#ifdef SYMDBUG
|
||||
rest = nsect * sizeof(ind_t) + sizeof(ind_t) + sizeof(ind_t);
|
||||
#else SYMDBUG
|
||||
rest = nsect * sizeof(ind_t) + sizeof(ind_t);
|
||||
#endif SYMDBUG
|
||||
/*
|
||||
* We already allocated space for the header, we now need
|
||||
* the section, name an string table.
|
||||
*/
|
||||
size = modulsize(head) - sizeof(struct outhead) - rest;
|
||||
if (hard_alloc(ALLOMODL, size) == BADOFF)
|
||||
fatal("no space for module");
|
||||
read_sect((struct outsect *)modulptr(sectindex), nsect);
|
||||
|
||||
return incore && alloc(ALLOMODL, rest) != BADOFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the indirectly accessed pieces: the section contents and
|
||||
* the relocation table, and put their indices in the right place.
|
||||
*/
|
||||
static bool
|
||||
indirect_alloc(head)
|
||||
struct outhead *head;
|
||||
{
|
||||
register int allopiece;
|
||||
ushort nsect = head->oh_nsect;
|
||||
ushort nrelo = head->oh_nrelo;
|
||||
ind_t sectindex = IND_SECT(*head);
|
||||
ind_t emitoff = IND_EMIT(*head);
|
||||
ind_t relooff = IND_RELO(*head);
|
||||
#ifdef SYMDBUG
|
||||
ind_t dbugoff = IND_DBUG(*head);
|
||||
extern long objectsize;
|
||||
long dbugsize = objectsize - OFF_DBUG(*head);
|
||||
#endif SYMDBUG
|
||||
|
||||
assert(incore);
|
||||
for (allopiece = ALLOEMIT; allopiece < ALLOEMIT + nsect; allopiece++) {
|
||||
if (!putemitindex(sectindex, emitoff, allopiece))
|
||||
return FALSE;
|
||||
sectindex += sizeof(struct outsect);
|
||||
emitoff += sizeof(ind_t);
|
||||
}
|
||||
#ifdef SYMDBUG
|
||||
return putreloindex(relooff, (long)nrelo * sizeof(struct outrelo))
|
||||
&&
|
||||
putdbugindex(dbugoff, dbugsize);
|
||||
#else SYMDBUG
|
||||
return putreloindex(relooff, (long)nrelo * sizeof(struct outrelo));
|
||||
#endif SYMDBUG
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the contents of the section of which the table entry is
|
||||
* at offset `sectindex'. Put the offset of the allocated piece at offset
|
||||
* `emitoff'.
|
||||
*/
|
||||
static bool
|
||||
putemitindex(sectindex, emitoff, allopiece)
|
||||
ind_t sectindex;
|
||||
ind_t emitoff;
|
||||
int allopiece;
|
||||
{
|
||||
long flen;
|
||||
ind_t emitindex;
|
||||
extern ind_t alloc();
|
||||
|
||||
flen = ((struct outsect *)modulptr(sectindex))->os_flen;
|
||||
if ((emitindex = alloc(allopiece, flen)) != BADOFF) {
|
||||
*(ind_t *)modulptr(emitoff) = emitindex;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for a relocation table with `nrelobytes' bytes, and put the
|
||||
* offset at `relooff'.
|
||||
*/
|
||||
static bool
|
||||
putreloindex(relooff, nrelobytes)
|
||||
ind_t relooff;
|
||||
long nrelobytes;
|
||||
{
|
||||
ind_t reloindex;
|
||||
extern ind_t alloc();
|
||||
|
||||
if ((reloindex = alloc(ALLORELO, nrelobytes)) != BADOFF) {
|
||||
*(ind_t *)modulptr(relooff) = reloindex;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#ifdef SYMDBUG
|
||||
/*
|
||||
* Allocate space for debugging information and put the offset at `dbugoff'.
|
||||
*/
|
||||
static bool
|
||||
putdbugindex(dbugoff, ndbugbytes)
|
||||
ind_t relooff;
|
||||
long ndbugbytes;
|
||||
{
|
||||
ind_t dbugindex;
|
||||
extern ind_t alloc();
|
||||
|
||||
if ((dbugindex = alloc(ALLORELO, ndbugbytes)) != BADOFF) {
|
||||
*(ind_t *)modulptr(dbugoff) = dbugindex;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif SYMDBUG
|
||||
|
||||
/*
|
||||
* Compute addresses and read in. Remember that the contents of the sections
|
||||
* and also the relocation table are accessed indirectly.
|
||||
*/
|
||||
static
|
||||
get_indirect(head, sect)
|
||||
register struct outhead *head;
|
||||
register struct outsect *sect;
|
||||
{
|
||||
register ind_t *emitindex;
|
||||
register int nsect;
|
||||
register int piece;
|
||||
ind_t *reloindex;
|
||||
|
||||
emitindex = (ind_t *)modulptr(IND_EMIT(*head));
|
||||
nsect = head->oh_nsect; piece = ALLOEMIT;
|
||||
while (nsect--) {
|
||||
read_emit(address(piece, *emitindex), sect->os_flen);
|
||||
piece++; emitindex++; sect++;
|
||||
}
|
||||
reloindex = (ind_t *)modulptr(IND_RELO(*head));
|
||||
read_relo((struct outrelo *)address(ALLORELO, *reloindex),
|
||||
head->oh_nrelo
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the file pointer at `pos'.
|
||||
*/
|
||||
seek(pos)
|
||||
long pos;
|
||||
{
|
||||
if (passnumber == FIRST || !incore)
|
||||
lseek(infile, pos, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* A file pointer is advanced automatically when reading, a char pointer
|
||||
* is not. That's why we do it here. If we don't keep everything in core,
|
||||
* we give the space allocated for a module back.
|
||||
*/
|
||||
skip_modul(head)
|
||||
struct outhead *head;
|
||||
{
|
||||
register ind_t skip = modulsize(head);
|
||||
|
||||
if (incore) {
|
||||
core_position += skip;
|
||||
if (passnumber == SECOND)
|
||||
modulbase += skip;
|
||||
} else {
|
||||
dealloc(ALLOMODL);
|
||||
core_position = (ind_t)0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in what we need in pass 2, because we couldn't keep it in core.
|
||||
*/
|
||||
static
|
||||
read_modul()
|
||||
{
|
||||
struct outhead *head;
|
||||
struct outsect *sects;
|
||||
struct outname *names;
|
||||
char *chars;
|
||||
ind_t sectindex, nameindex, charindex;
|
||||
ushort nsect, nname;
|
||||
long size;
|
||||
long nchar;
|
||||
long skip;
|
||||
extern ind_t hard_alloc();
|
||||
|
||||
assert(passnumber == SECOND);
|
||||
assert(!incore);
|
||||
if (hard_alloc(ALLOMODL, (long)sizeof(struct outhead)) == BADOFF)
|
||||
fatal("no space for module header");
|
||||
head = (struct outhead *)modulptr(IND_HEAD);
|
||||
read_head(head);
|
||||
nsect = head->oh_nsect; sectindex = IND_SECT(*head);
|
||||
nname = head->oh_nname; nameindex = IND_NAME(*head);
|
||||
nchar = head->oh_nchar; charindex = IND_CHAR(*head);
|
||||
skip = OFF_NAME(*head) - OFF_EMIT(*head);
|
||||
#ifdef SYMDBUG
|
||||
size = modulsize(head) - (nsect * sizeof(ind_t) + 2 * sizeof(ind_t));
|
||||
#else SYMDBUG
|
||||
size = modulsize(head) - (nsect * sizeof(ind_t) + sizeof(ind_t));
|
||||
#endif SYMDBUG
|
||||
if (hard_alloc(ALLOMODL, size) == BADOFF)
|
||||
fatal("no space for module");
|
||||
|
||||
sects = (struct outsect *)modulptr(sectindex);
|
||||
names = (struct outname *)modulptr(nameindex);
|
||||
chars = modulptr(charindex);
|
||||
|
||||
read_sect(sects, nsect);
|
||||
lseek(infile, skip, 1);
|
||||
read_name(names, nname);
|
||||
read_char(chars, nchar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Align `size' to a multiple of the size of a double.
|
||||
* This is assumed to be a power of 2.
|
||||
*/
|
||||
static long
|
||||
align(size)
|
||||
register long size;
|
||||
{
|
||||
size += sizeof(double) - 1;
|
||||
return size - (size & (sizeof(double) - 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute how many DIRECT bytes must be allocated for a module of which the
|
||||
* header is pointed to by `head':
|
||||
* 0. the header,
|
||||
* 1. the section table,
|
||||
* 2. the name table,
|
||||
* 3. the string table,
|
||||
* 4. for each section the offset of its contents,
|
||||
* 5. the offset of the relocation table.
|
||||
#ifdef SYMDBUG
|
||||
* 6. the offset of the debugging information.
|
||||
#endif SYMDBUG
|
||||
*/
|
||||
static long
|
||||
modulsize(head)
|
||||
register struct outhead *head;
|
||||
{
|
||||
return sizeof(struct outhead) + /* 0 */
|
||||
head->oh_nsect * sizeof(struct outsect) + /* 1 */
|
||||
head->oh_nname * sizeof(struct outname) + /* 2 */
|
||||
align(head->oh_nchar) + /* 3 */
|
||||
head->oh_nsect * sizeof(ind_t) + /* 4 */
|
||||
#ifdef SYMDBUG
|
||||
sizeof(ind_t) + /* 5 */
|
||||
sizeof(ind_t); /* 6 */
|
||||
#else SYMDBUG
|
||||
sizeof(ind_t); /* 5 */
|
||||
#endif SYMDBUG
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Walk through the relocation table of the current module. We must either walk
|
||||
* through core or through file. Startrelo() should be called first.
|
||||
*/
|
||||
|
||||
static struct outrelo *walkrelo;
|
||||
|
||||
startrelo(head)
|
||||
struct outhead *head;
|
||||
{
|
||||
ind_t reloindex;
|
||||
|
||||
if (incore) {
|
||||
reloindex = *(ind_t *)(modulbase + IND_RELO(*head));
|
||||
walkrelo = (struct outrelo *)address(ALLORELO, reloindex);
|
||||
} else
|
||||
lseek(infile, position + OFF_RELO(*head), 0);
|
||||
}
|
||||
|
||||
struct outrelo *
|
||||
nextrelo()
|
||||
{
|
||||
static struct outrelo relobuf;
|
||||
|
||||
if (incore)
|
||||
return walkrelo++;
|
||||
|
||||
read_relo(&relobuf, (ushort)1);
|
||||
return &relobuf;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Get the section contents in core of which the describing struct has index
|
||||
* `sectindex'. `Head' points to the header of the module.
|
||||
*/
|
||||
char *
|
||||
getemit(head, sects, sectindex)
|
||||
struct outhead *head;
|
||||
struct outsect *sects;
|
||||
int sectindex;
|
||||
{
|
||||
char *ret;
|
||||
ind_t off;
|
||||
extern char *core_alloc();
|
||||
|
||||
if (!incore) {
|
||||
ret = core_alloc(ALLOMODL, sects[sectindex].os_flen);
|
||||
if (ret == (char *)0)
|
||||
fatal("no space for section contents");
|
||||
lseek(infile, position + sects[sectindex].os_foff, 0);
|
||||
read_emit(ret, sects[sectindex].os_flen);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* We have an offset in the contents of the final output
|
||||
* "file" where normally the contents would be.
|
||||
*/
|
||||
off = *((ind_t *)(modulbase + IND_EMIT(*head)) + sectindex);
|
||||
return address(ALLOEMIT + sectindex, off);
|
||||
}
|
13
util/led/scan.h
Normal file
13
util/led/scan.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* $Header$ */
|
||||
|
||||
/*
|
||||
* Offsets of the pieces of the input module in core.
|
||||
*/
|
||||
|
||||
#define IND_HEAD ((ind_t)0)
|
||||
#define IND_SECT(x) (IND_HEAD + sizeof(struct outhead))
|
||||
#define IND_NAME(x) (IND_SECT(x) + (x).oh_nsect * sizeof(struct outsect))
|
||||
#define IND_CHAR(x) (IND_NAME(x) + (x).oh_nname * sizeof(struct outname))
|
||||
#ifdef SYMDBUG
|
||||
#define OFF_DBUG(x) (OFF_CHAR(x) + (x).oh_nchar)
|
||||
#endif SYMDBUG
|
132
util/led/sym.c
Normal file
132
util/led/sym.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Symbol table management.
|
||||
*/
|
||||
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "memory.h"
|
||||
|
||||
/*
|
||||
* Symbol table types. Each hash table entry contains the offset of a symbol
|
||||
* struct. `Sy_name' contains the offset the name in the piece of global
|
||||
* names. `Sy_next' contains the offset of the next symbol of which the
|
||||
* corresponding name has the same hash value.
|
||||
*/
|
||||
struct symbol {
|
||||
ind_t sy_name;
|
||||
ind_t sy_next;
|
||||
};
|
||||
|
||||
#define NHASH 256 /* Size of hash table. Should be even. */
|
||||
|
||||
static ind_t hashtable[NHASH];
|
||||
|
||||
/*
|
||||
* Initialize the symbol table. All indices should be noticeably invalid.
|
||||
*/
|
||||
init_symboltable()
|
||||
{
|
||||
register ind_t *rap;
|
||||
|
||||
for (rap = hashtable; rap < &hashtable[NHASH]; rap++)
|
||||
*rap = BADOFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for `string' in the symboltable. The hash value of `string' is in
|
||||
* `hashval'. The linked list belonging to the entry of hashval
|
||||
* in the hash table is followed. If the names match, a pointer to the outname
|
||||
* in this element of the list is returned. When a match cannot be found,
|
||||
* NIL is returned.
|
||||
*/
|
||||
struct outname *
|
||||
searchname(string, hashval)
|
||||
char *string;
|
||||
int hashval;
|
||||
{
|
||||
register char *rcp;
|
||||
register char *namestring;
|
||||
register ind_t symindex;
|
||||
register struct outname *name;
|
||||
register struct symbol *sym;
|
||||
|
||||
symindex = hashtable[hashval];
|
||||
while (symindex != BADOFF) {
|
||||
sym = (struct symbol *)address(ALLOSYMB, symindex);
|
||||
name = (struct outname *)address(ALLOGLOB, sym->sy_name);
|
||||
namestring = address(ALLOGCHR, (ind_t)name->on_foff);
|
||||
rcp = string;
|
||||
while (*rcp == *namestring++)
|
||||
if (*rcp++ == '\0')
|
||||
return name;
|
||||
symindex = sym->sy_next;
|
||||
}
|
||||
/* Not found. */
|
||||
return (struct outname *)0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a new name in the symbol table. We must copy everything to a
|
||||
* new entry. `Name' is a private copy, i.e. the pointer to it will not be
|
||||
* destroyed by allocation. However, the string of which name->on_foff is the
|
||||
* offset can be destroyed, so we save it first.
|
||||
*/
|
||||
entername(name, hashval)
|
||||
struct outname *name;
|
||||
int hashval;
|
||||
{
|
||||
ind_t savindex;
|
||||
ind_t symindex;
|
||||
ind_t namindex;
|
||||
struct symbol *sym;
|
||||
struct outname *newname;
|
||||
extern ind_t savechar();
|
||||
extern ind_t hard_alloc();
|
||||
|
||||
savindex = savechar(ALLOGCHR, (ind_t)name->on_foff);
|
||||
symindex = hard_alloc(ALLOSYMB, (long)sizeof(struct symbol));
|
||||
namindex = hard_alloc(ALLOGLOB, (long)sizeof(struct outname));
|
||||
if (savindex == BADOFF || symindex == BADOFF || namindex == BADOFF)
|
||||
fatal("symbol table overflow");
|
||||
sym = (struct symbol *)address(ALLOSYMB, symindex);
|
||||
sym->sy_name = namindex;
|
||||
newname = (struct outname *)address(ALLOGLOB, namindex);
|
||||
*newname = *name;
|
||||
newname->on_foff = savindex;
|
||||
sym->sy_next = hashtable[hashval];
|
||||
hashtable[hashval] = symindex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the index of `name' in the symbol table in the order in which
|
||||
* it was entered. We need a REAL index, not a byte offset.
|
||||
*/
|
||||
ushort
|
||||
indexof(name)
|
||||
struct outname *name;
|
||||
{
|
||||
return name - (struct outname *)address(ALLOGLOB, (ind_t)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign an integer to the string in p.
|
||||
* 0 <= hash(p) < NHASH, so it can - and will - be used
|
||||
* as index in a hash table.
|
||||
*/
|
||||
int
|
||||
hash(p)
|
||||
register char *p;
|
||||
{
|
||||
register unsigned int h = 0;
|
||||
register int c;
|
||||
|
||||
while (c = *p++) {
|
||||
h <<= 2;
|
||||
h += c;
|
||||
}
|
||||
return h & (NHASH - 1);
|
||||
}
|
297
util/led/write.c
Normal file
297
util/led/write.c
Normal file
|
@ -0,0 +1,297 @@
|
|||
#ifndef lint
|
||||
static char rcsid[] = "$Header$";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* You can choose between two strategies:
|
||||
* - Open the output file several times, once for each logical part, and
|
||||
* write to it in multiple places.
|
||||
* - Open the output file once and seek back and forth to each logical
|
||||
* part. In this case #define OUTSEEK.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "out.h"
|
||||
#include "const.h"
|
||||
#include "assert.h"
|
||||
#include "memory.h"
|
||||
#include "orig.h"
|
||||
|
||||
extern long lseek();
|
||||
|
||||
#define WRITE 1 /* Argument to open(). */
|
||||
|
||||
/*
|
||||
* Parts of the output file.
|
||||
*/
|
||||
#define PARTEMIT 0
|
||||
#define PARTRELO 1
|
||||
#define PARTNAME 2
|
||||
#define PARTCHAR 3
|
||||
#ifdef SYMDBUG
|
||||
#define PARTDBUG 4
|
||||
#else SYMDBUG
|
||||
#define PARTDBUG PARTCHAR
|
||||
#endif SYMDBUG
|
||||
#define NPARTS (PARTDBUG + 1)
|
||||
|
||||
/*
|
||||
* Call OUTPART() with the part you want to write on as argument, before
|
||||
* you call OUTWRITE().
|
||||
*/
|
||||
static int outpart = NPARTS;
|
||||
|
||||
#ifdef OUTSEEK
|
||||
|
||||
static int outfile;
|
||||
static long outseek[NPARTS];
|
||||
|
||||
#define OUTPART(p) \
|
||||
{ if (outpart != (p)) {\
|
||||
outpart = (p);\
|
||||
lseek(outfile, outseek[(p)], 0);\
|
||||
}\
|
||||
}
|
||||
#define OUTSECT(i) \
|
||||
{ outpart = NPARTS;\
|
||||
outseek[PARTEMIT] =\
|
||||
outsect[(i)].os_foff + relorig[(i)].org_flen;\
|
||||
}
|
||||
#define OUTWRITE(b, n) \
|
||||
{ if (write(outfile, (b), (n)) != (n))\
|
||||
fatal("write error");\
|
||||
outseek[outpart] += (n);\
|
||||
}
|
||||
#define BEGINSEEK(p, o) \
|
||||
{ outseek[(p)] = (o);\
|
||||
}
|
||||
|
||||
#else OUTSEEK
|
||||
|
||||
static int outfile[NPARTS];
|
||||
|
||||
#define OUTPART(p) \
|
||||
{ outpart = (p);\
|
||||
}
|
||||
#define OUTSECT(i) \
|
||||
{ lseek( outfile[PARTEMIT],\
|
||||
outsect[(i)].os_foff + relorig[(i)].org_flen,\
|
||||
0\
|
||||
);\
|
||||
}
|
||||
#define OUTWRITE(b, n) \
|
||||
{ if (write(outfile[outpart], (b), (n)) != (n))\
|
||||
fatal("write error");\
|
||||
}
|
||||
#define BEGINSEEK(p, o) \
|
||||
{ lseek(outfile[(p)], (o), 0);\
|
||||
}
|
||||
|
||||
#endif OUTSEEK
|
||||
|
||||
extern struct outhead outhead;
|
||||
extern struct outsect outsect[];
|
||||
extern int flagword;
|
||||
extern struct orig relorig[];
|
||||
extern bool bytes_reversed, words_reversed;
|
||||
extern bool incore;
|
||||
|
||||
|
||||
static long offchar;
|
||||
|
||||
/*
|
||||
* Open the output file according to the chosen strategy.
|
||||
* Write away the header and section table: they will not change anymore.
|
||||
*/
|
||||
begin_write()
|
||||
{
|
||||
register long off;
|
||||
|
||||
openoutput();
|
||||
BEGINSEEK(PARTEMIT, (long)0);
|
||||
wrt_head(&outhead);
|
||||
wrt_sect(outsect, outhead.oh_nsect);
|
||||
|
||||
off = SZ_HEAD + (long)outhead.oh_nsect * SZ_SECT + outhead.oh_nemit;
|
||||
|
||||
if (flagword & RFLAG) {
|
||||
/* A relocation table will be produced. */
|
||||
BEGINSEEK(PARTRELO, off);
|
||||
off += (long)outhead.oh_nrelo * SZ_RELO;
|
||||
}
|
||||
|
||||
if (flagword & SFLAG)
|
||||
return;
|
||||
|
||||
/* A name table will be produced. */
|
||||
BEGINSEEK(PARTNAME, off);
|
||||
off += (long)outhead.oh_nname * SZ_NAME;
|
||||
BEGINSEEK(PARTCHAR, off);
|
||||
offchar = off; /* See wrt_name(). */
|
||||
#ifdef SYMDBUG
|
||||
off += outhead.oh_nchar;
|
||||
BEGINSEEK(PARTDBUG, off);
|
||||
#endif SYMDBUG
|
||||
}
|
||||
|
||||
static
|
||||
openoutput()
|
||||
{
|
||||
#ifndef OUTSEEK
|
||||
register int *fdp;
|
||||
#endif OUTSEEK
|
||||
extern char *outputname;
|
||||
|
||||
close(creat(outputname, 0666));
|
||||
#ifdef OUTSEEK
|
||||
if ((outfile = open(outputname, WRITE)) < 0)
|
||||
fatal("can't write %s", outputname);
|
||||
#else OUTSEEK
|
||||
for (fdp = &outfile[PARTEMIT]; fdp < &outfile[NPARTS]; fdp++)
|
||||
if ((*fdp = open(outputname, WRITE)) < 0)
|
||||
fatal("can't write %s", outputname);
|
||||
#endif OUTSEEK
|
||||
}
|
||||
|
||||
static struct outname *
|
||||
sectname(sectindex)
|
||||
int sectindex;
|
||||
{
|
||||
static struct outname namebuf;
|
||||
|
||||
namebuf.on_foff = (long)0; /* No string name. */
|
||||
namebuf.on_type = (S_MIN + sectindex) | S_SCT;
|
||||
namebuf.on_desc = 0;
|
||||
namebuf.on_valu = outsect[sectindex].os_base;
|
||||
|
||||
return &namebuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the symbol table and the section names.
|
||||
*/
|
||||
end_write()
|
||||
{
|
||||
register ushort cnt;
|
||||
register struct outname *name;
|
||||
register int sectindex;
|
||||
extern ushort NGlobals;
|
||||
|
||||
assert(!incore);
|
||||
assert(!(flagword & SFLAG));
|
||||
cnt = NGlobals;
|
||||
name = (struct outname *)address(ALLOGLOB, (ind_t)0);
|
||||
while (cnt--) {
|
||||
if (name->on_foff != (long)0) {
|
||||
name->on_mptr = address(ALLOGCHR, (ind_t)name->on_foff);
|
||||
} else {
|
||||
name->on_mptr = (char *)0;
|
||||
}
|
||||
wrt_name(name);
|
||||
name++;
|
||||
}
|
||||
|
||||
for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++)
|
||||
wrt_name(sectname(sectindex));
|
||||
}
|
||||
|
||||
static
|
||||
wrt_head(head)
|
||||
register struct outhead *head;
|
||||
{
|
||||
assert(!incore);
|
||||
OUTPART(PARTEMIT);
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)head, SF_HEAD);
|
||||
OUTWRITE((char *)head, SZ_HEAD);
|
||||
/*
|
||||
* Swap back because we will need it again.
|
||||
*/
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)head, SF_HEAD);
|
||||
}
|
||||
|
||||
static
|
||||
wrt_sect(sect, cnt)
|
||||
register struct outsect *sect;
|
||||
register ushort cnt;
|
||||
{
|
||||
assert(!incore);
|
||||
OUTPART(PARTEMIT);
|
||||
while (cnt--) {
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)sect, SF_SECT);
|
||||
OUTWRITE((char *)sect, SZ_SECT);
|
||||
/*
|
||||
* Swap back because we will need it again.
|
||||
*/
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)sect, SF_SECT);
|
||||
sect++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
*/
|
||||
wrt_emit(emit, sectindex, cnt)
|
||||
register char *emit;
|
||||
int sectindex;
|
||||
register long cnt;
|
||||
{
|
||||
register int n;
|
||||
|
||||
assert(!incore);
|
||||
OUTPART(PARTEMIT);
|
||||
OUTSECT(sectindex);
|
||||
while (cnt) {
|
||||
n = cnt >= BUFSIZ ? BUFSIZ : cnt;
|
||||
OUTWRITE(emit, n);
|
||||
emit += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
||||
|
||||
wrt_relo(relo)
|
||||
register struct outrelo *relo;
|
||||
{
|
||||
assert(!incore);
|
||||
assert(flagword & RFLAG);
|
||||
OUTPART(PARTRELO);
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)relo, SF_RELO);
|
||||
OUTWRITE((char *)relo, SZ_RELO);
|
||||
}
|
||||
|
||||
wrt_name(name)
|
||||
register struct outname *name;
|
||||
{
|
||||
assert(!incore);
|
||||
assert(!(flagword & SFLAG));
|
||||
if (name->on_mptr != (char *)0) {
|
||||
register int len = strlen(name->on_mptr) + 1;
|
||||
|
||||
OUTPART(PARTCHAR);
|
||||
OUTWRITE(name->on_mptr, len);
|
||||
name->on_foff = offchar;
|
||||
offchar += len;
|
||||
} else {
|
||||
name->on_foff = (long)0;
|
||||
}
|
||||
OUTPART(PARTNAME);
|
||||
if (bytes_reversed || words_reversed)
|
||||
swap((char *)name, SF_NAME);
|
||||
OUTWRITE((char *)name, SZ_NAME);
|
||||
}
|
||||
#ifdef SYMDBUG
|
||||
|
||||
wrt_dbug(buf, size)
|
||||
char *buf;
|
||||
int size;
|
||||
{
|
||||
assert(!incore);
|
||||
assert(!(flagword & SFLAG));
|
||||
OUTPART(PARTDBUG);
|
||||
OUTWRITE((char *)buf, size);
|
||||
}
|
||||
#endif SYMDBUG
|
Loading…
Reference in a new issue