--- /dev/null
+/* $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))
--- /dev/null
+/* $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"
--- /dev/null
+#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. */
+}
--- /dev/null
+/* $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
--- /dev/null
+#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;
+ }
+ }
+}
--- /dev/null
+/* $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)
--- /dev/null
+/* $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
--- /dev/null
+/* $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))
--- /dev/null
+#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
--- /dev/null
+/*
+ * $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;
* 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"
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. */
*/
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;
-
- 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
+#include "mach.c"
- 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;
}
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");
}
-
}
/*
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--)
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;
}
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;
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;
* 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;
* 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;
*/
for (i = 0; i < NMEMS; i++) {
switch (i) {
- case ALLOHEAD:
- case ALLOSECT:
case ALLOGLOB:
case ALLOGCHR:
case ALLOSYMB:
static
free_saved_moduls()
{
- register off_t size;
+ register ind_t size;
register char *old, *new;
register struct memory *mem = &mems[ALLOMODL];
*new++ = *old++;
mem->mem_full -= core_position;
mem->mem_left += core_position;
- core_position = (off_t)0;
+ core_position = (ind_t)0;
}
/*
/*
* 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;
{
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:
break;
}
}
- compact(NMEMS - 1, (off_t)0);
+ compact(NMEMS - 1, (ind_t)0);
}
/* ------------------------------------------------------------------------- */
*/
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);
}
/*
/*
* 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.
*/
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);
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;
}
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);
}
--- /dev/null
+/* $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;
--- /dev/null
+/* $Header$ */
+
+struct orig {
+ long org_flen; /* Accumulated length of preceding sections. */
+ long org_zero; /* " " " zeroparts. */
+};
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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);
+}
--- /dev/null
+/* $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
--- /dev/null
+#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);
+}
--- /dev/null
+#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