Maybe some minor changes.
authorduk <none@none>
Thu, 10 Jan 1985 13:35:39 +0000 (13:35 +0000)
committerduk <none@none>
Thu, 10 Jan 1985 13:35:39 +0000 (13:35 +0000)
20 files changed:
h/out.h [new file with mode: 0644]
h/ranlib.h [new file with mode: 0644]
util/led/archive.c [new file with mode: 0644]
util/led/assert.h [new file with mode: 0644]
util/led/byte_order.c [new file with mode: 0644]
util/led/const.h [new file with mode: 0644]
util/led/debug.h [new file with mode: 0644]
util/led/defs.h [new file with mode: 0644]
util/led/finish.c [new file with mode: 0644]
util/led/mach.c [new file with mode: 0644]
util/led/memory.c
util/led/memory.h [new file with mode: 0644]
util/led/orig.h [new file with mode: 0644]
util/led/read.c [new file with mode: 0644]
util/led/relocate.c [new file with mode: 0644]
util/led/save.c [new file with mode: 0644]
util/led/scan.c [new file with mode: 0644]
util/led/scan.h [new file with mode: 0644]
util/led/sym.c [new file with mode: 0644]
util/led/write.c [new file with mode: 0644]

diff --git a/h/out.h b/h/out.h
new file mode 100644 (file)
index 0000000..6bcceaa
--- /dev/null
+++ b/h/out.h
@@ -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))
diff --git a/h/ranlib.h b/h/ranlib.h
new file mode 100644 (file)
index 0000000..cf76a86
--- /dev/null
@@ -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"
diff --git a/util/led/archive.c b/util/led/archive.c
new file mode 100644 (file)
index 0000000..f453256
--- /dev/null
@@ -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. */
+}
diff --git a/util/led/assert.h b/util/led/assert.h
new file mode 100644 (file)
index 0000000..9ff3ae9
--- /dev/null
@@ -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
diff --git a/util/led/byte_order.c b/util/led/byte_order.c
new file mode 100644 (file)
index 0000000..0172ec3
--- /dev/null
@@ -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;
+               }
+       }
+}
diff --git a/util/led/const.h b/util/led/const.h
new file mode 100644 (file)
index 0000000..6c70358
--- /dev/null
@@ -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)
diff --git a/util/led/debug.h b/util/led/debug.h
new file mode 100644 (file)
index 0000000..16fff03
--- /dev/null
@@ -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
diff --git a/util/led/defs.h b/util/led/defs.h
new file mode 100644 (file)
index 0000000..721986a
--- /dev/null
@@ -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))
diff --git a/util/led/finish.c b/util/led/finish.c
new file mode 100644 (file)
index 0000000..00125f6
--- /dev/null
@@ -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
diff --git a/util/led/mach.c b/util/led/mach.c
new file mode 100644 (file)
index 0000000..e17bf12
--- /dev/null
@@ -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;
index 7cb22f1..8069af1 100644 (file)
@@ -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;
-
-       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;
        }
@@ -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);
 }
diff --git a/util/led/memory.h b/util/led/memory.h
new file mode 100644 (file)
index 0000000..e78b065
--- /dev/null
@@ -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;
diff --git a/util/led/orig.h b/util/led/orig.h
new file mode 100644 (file)
index 0000000..0fed9e9
--- /dev/null
@@ -0,0 +1,6 @@
+/* $Header$ */
+
+struct orig {
+       long    org_flen;       /* Accumulated length of preceding sections. */
+       long    org_zero;       /*      "         "          "    zeroparts. */
+};
diff --git a/util/led/read.c b/util/led/read.c
new file mode 100644 (file)
index 0000000..f888a71
--- /dev/null
@@ -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;
+       }
+}
diff --git a/util/led/relocate.c b/util/led/relocate.c
new file mode 100644 (file)
index 0000000..05d6048
--- /dev/null
@@ -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;
+}
diff --git a/util/led/save.c b/util/led/save.c
new file mode 100644 (file)
index 0000000..807c79e
--- /dev/null
@@ -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;
+       }
+}
diff --git a/util/led/scan.c b/util/led/scan.c
new file mode 100644 (file)
index 0000000..32ed1ef
--- /dev/null
@@ -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);
+}
diff --git a/util/led/scan.h b/util/led/scan.h
new file mode 100644 (file)
index 0000000..a35b015
--- /dev/null
@@ -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
diff --git a/util/led/sym.c b/util/led/sym.c
new file mode 100644 (file)
index 0000000..b257fba
--- /dev/null
@@ -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);
+}
diff --git a/util/led/write.c b/util/led/write.c
new file mode 100644 (file)
index 0000000..bb4014d
--- /dev/null
@@ -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