297 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#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
 |