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
 |