331 lines
6 KiB
C
331 lines
6 KiB
C
/* $Header$ */
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
/*
|
|
* 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 <out.h>
|
|
#include "object.h"
|
|
|
|
extern long lseek();
|
|
|
|
/*
|
|
* Parts of the output file.
|
|
*/
|
|
#define PARTEMIT 0
|
|
#define PARTRELO 1
|
|
#define PARTNAME 2
|
|
#define PARTCHAR 3
|
|
#ifdef SYMDBUG
|
|
#define PARTDBUG 4
|
|
#else
|
|
#define PARTDBUG 3
|
|
#endif
|
|
#define NPARTS (PARTDBUG + 1)
|
|
|
|
static long offset[MAXSECT];
|
|
|
|
#ifdef OUTSEEK
|
|
static int outfile;
|
|
static long outseek[NPARTS];
|
|
static long currpos;
|
|
#define OUTSECT(i) \
|
|
(outseek[PARTEMIT] = offset[i])
|
|
static
|
|
OUTWRITE(p, b, n) {
|
|
char *b;
|
|
long n;
|
|
{
|
|
register long l = outseek[p];
|
|
|
|
if (currpos != l) {
|
|
lseek(outfile, l, 0);
|
|
}
|
|
wr_bytes(outfile, b, n);
|
|
currpos = l + n;
|
|
outseek[p] = currpos;
|
|
}
|
|
|
|
#define BEGINSEEK(p, o) \
|
|
(outseek[(p)] = (o))
|
|
|
|
#else OUTSEEK
|
|
|
|
static int outfile[NPARTS];
|
|
static long currpos[NPARTS];
|
|
#define OUTSECT(i) \
|
|
(currpos[PARTEMIT] == offset[(i)] ?\
|
|
0 :\
|
|
(currpos[PARTEMIT] = offset[(i)],\
|
|
lseek(outfile[PARTEMIT], currpos[PARTEMIT], 0)))
|
|
#define OUTWRITE(p, b, n) \
|
|
(wr_bytes(outfile[(p)], (b), (n)), currpos[(p)] += (n))
|
|
#define BEGINSEEK(p, o) \
|
|
(currpos[(p)] = lseek(outfile[(p)], (o), 0))
|
|
|
|
#endif OUTSEEK
|
|
|
|
int _ocnt;
|
|
char *_pbuf;
|
|
static int sectionnr;
|
|
static int offcnt;
|
|
|
|
/*
|
|
* Open the output file according to the chosen strategy.
|
|
*/
|
|
int
|
|
wr_open(f)
|
|
char *f;
|
|
{
|
|
#ifndef OUTSEEK
|
|
register int *fdp;
|
|
#endif OUTSEEK
|
|
|
|
close(creat(f, 0666));
|
|
#ifdef OUTSEEK
|
|
if ((outfile = open(f, 1)) < 0)
|
|
return 0;
|
|
currpos = 0;
|
|
#else OUTSEEK
|
|
for (fdp = &outfile[PARTEMIT]; fdp < &outfile[NPARTS]; fdp++)
|
|
if ((*fdp = open(f, 1)) < 0)
|
|
return 0;
|
|
#endif OUTSEEK
|
|
offcnt = 0;
|
|
return 1;
|
|
}
|
|
|
|
wr_close()
|
|
{
|
|
#ifndef OUTSEEK
|
|
register int *fdp;
|
|
#endif not OUTSEEK
|
|
|
|
if (_ocnt) {
|
|
wr_flush();
|
|
}
|
|
#ifdef OUTSEEK
|
|
close(outfile);
|
|
outfile = -1;
|
|
#else not OUTSEEK
|
|
for (fdp = &outfile[PARTEMIT]; fdp < &outfile[NPARTS]; fdp++) {
|
|
close(*fdp);
|
|
*fdp = -1;
|
|
}
|
|
#endif not OUTSEEK
|
|
}
|
|
|
|
wr_fd()
|
|
{
|
|
#ifdef OUTSEEK
|
|
return outfile;
|
|
#else
|
|
return outfile[PARTEMIT];
|
|
#endif
|
|
}
|
|
|
|
wr_ohead(head)
|
|
register struct outhead *head;
|
|
{
|
|
register long off = OFF_RELO(*head);
|
|
|
|
BEGINSEEK(PARTEMIT, 0L);
|
|
BEGINSEEK(PARTRELO, off);
|
|
off += (long) head->oh_nrelo * SZ_RELO;
|
|
BEGINSEEK(PARTNAME, off);
|
|
off += (long) head->oh_nname * SZ_NAME;
|
|
BEGINSEEK(PARTCHAR, off);
|
|
#ifdef SYMDBUG
|
|
off += head->oh_nchar;
|
|
BEGINSEEK(PARTDBUG, off);
|
|
#endif
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outhead) != SZ_HEAD)
|
|
#endif
|
|
{
|
|
char buf[SZ_HEAD];
|
|
register char *c = buf;
|
|
|
|
put2(head->oh_magic, c); c += 2;
|
|
put2(head->oh_stamp, c); c += 2;
|
|
put2(head->oh_flags, c); c += 2;
|
|
put2(head->oh_nsect, c); c += 2;
|
|
put2(head->oh_nrelo, c); c += 2;
|
|
put2(head->oh_nname, c); c += 2;
|
|
put4(head->oh_nemit, c); c += 4;
|
|
put4(head->oh_nchar, c);
|
|
OUTWRITE(PARTEMIT, buf, (long) SZ_HEAD);
|
|
}
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
else OUTWRITE(PARTEMIT, (char *) head, (long) SZ_HEAD);
|
|
#endif
|
|
}
|
|
|
|
wr_sect(sect, cnt1)
|
|
register struct outsect *sect;
|
|
unsigned int cnt1;
|
|
{
|
|
char buf[MAXSECT * SZ_SECT];
|
|
register char *c = buf;
|
|
register unsigned int cnt = cnt1;
|
|
|
|
while (cnt--) {
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outsect) != SZ_SECT)
|
|
#endif
|
|
{
|
|
put4(sect->os_base, c); c += 4;
|
|
put4(sect->os_size, c); c += 4;
|
|
put4(sect->os_foff, c); c += 4;
|
|
}
|
|
offset[offcnt++] = sect->os_foff;
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outsect) != SZ_SECT)
|
|
#endif
|
|
{
|
|
put4(sect->os_flen, c); c += 4;
|
|
put4(sect->os_lign, c); c += 4;
|
|
}
|
|
sect++;
|
|
}
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outsect) != SZ_SECT)
|
|
#endif
|
|
OUTWRITE(PARTEMIT, buf, (long) cnt1 * SZ_SECT);
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
else
|
|
OUTWRITE(PARTEMIT, (char *) (sect - cnt1), (long) cnt1 * SZ_SECT);
|
|
#endif
|
|
}
|
|
|
|
wr_flush()
|
|
{
|
|
OUTWRITE(PARTEMIT, _pbuf, (long) _ocnt);
|
|
offset[sectionnr] += _ocnt;
|
|
_ocnt = 0;
|
|
}
|
|
|
|
wr_outsect(s)
|
|
{
|
|
if (s != sectionnr) {
|
|
if (_ocnt) {
|
|
wr_flush();
|
|
}
|
|
sectionnr = s;
|
|
OUTSECT(s);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We don't have to worry about byte order here.
|
|
*/
|
|
wr_emit(emit, cnt)
|
|
char *emit;
|
|
long cnt;
|
|
{
|
|
if (_ocnt) wr_flush();
|
|
OUTWRITE(PARTEMIT, emit, cnt);
|
|
offset[sectionnr] += cnt;
|
|
}
|
|
|
|
wr_relo(relo, cnt)
|
|
register struct outrelo *relo;
|
|
register unsigned int cnt;
|
|
{
|
|
long l;
|
|
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outrelo) != SZ_RELO)
|
|
#endif
|
|
{
|
|
char buf[100 * SZ_RELO];
|
|
register char *c = buf;
|
|
register int i = 0;
|
|
|
|
while (cnt--) {
|
|
*c++ = relo->or_type;
|
|
*c++ = relo->or_sect;
|
|
put2(relo->or_nami, c); c += 2;
|
|
put4(relo->or_addr, c); c += 4;
|
|
relo++;
|
|
i++;
|
|
if (i == 100 || cnt == 0) {
|
|
c = buf;
|
|
l = (long) (i * SZ_RELO);
|
|
OUTWRITE(PARTRELO, c, l);
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
else {
|
|
l = (long) cnt * SZ_RELO;
|
|
OUTWRITE(PARTRELO, (char *) relo, l);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
wr_name(name, cnt)
|
|
register struct outname *name;
|
|
register unsigned int cnt;
|
|
{
|
|
long l;
|
|
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
if (sizeof(struct outname) != SZ_NAME)
|
|
#endif
|
|
{
|
|
char buf[100 * SZ_NAME];
|
|
register char *c = buf;
|
|
register int i = 0;
|
|
|
|
while (cnt--) {
|
|
put4(name->on_foff,c); c += 4;
|
|
put2(name->on_type,c); c += 2;
|
|
put2(name->on_desc,c); c += 2;
|
|
put4(name->on_valu,c); c += 4;
|
|
name++;
|
|
i++;
|
|
if (i == 100 || !cnt) {
|
|
c = buf;
|
|
l = (long) (i * SZ_NAME);
|
|
OUTWRITE(PARTNAME, c, l);
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
|
else {
|
|
l = (long)cnt * SZ_NAME;
|
|
OUTWRITE(PARTNAME, (char *) name, l);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
wr_string(addr, len)
|
|
char *addr;
|
|
long len;
|
|
{
|
|
|
|
OUTWRITE(PARTCHAR, addr, len);
|
|
}
|
|
|
|
#ifdef SYMDBUG
|
|
|
|
wr_dbug(buf, size)
|
|
char *buf;
|
|
long size;
|
|
{
|
|
OUTWRITE(PARTDBUG, buf, size);
|
|
}
|
|
|
|
#endif SYMDBUG
|