File:  [MW Coherent from dump] / coherent / d / bin / strip.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * Object file services.
 * This section is similar to that in nm and size.
 */

#include <stdio.h>
#include <canon.h>

#if COHERENT
#include <n.out.h>
#include <signal.h>
#endif
#if MSDOS
#include <nout.h>
#define	DOEXE	1
#endif
#if GEMDOS
#include <nout.h>
#define	DOPRG	1
#endif

char	*argv0;			/* Command name */
char	*fn;			/* File name */
FILE	*ifp;			/* Input File Pointer */
FILE	*ofp;			/* Output File Pointer */
struct	ldheader	ldh;	/* The l.out.h header */
long	loadsize;		/* Amount of input to copy to output */

/*
 *	Read in the l.out header.
 */
gethdr()
{
	register int i;
	fread((char *)&ldh, 1, sizeof(ldh), ifp);
	canshort(ldh.l_magic);
	canshort(ldh.l_flag);
	canshort(ldh.l_machine);
	if (ldh.l_magic != L_MAGIC)
		return 1;
	if ((ldh.l_flag&LF_32) == 0) {
		canshort(ldh.l_tbase);
		ldh.l_entry = ldh.l_tbase;
		ldh.l_tbase = sizeof(ldh) - 2*sizeof(short);
	} else {
		canshort(ldh.l_tbase);
		canlong(ldh.l_entry);
	}
	loadsize = 0;
	for (i=0; i<NLSEG; i++) {
		canlong(ldh.l_ssize[i]);
		if (i < L_DEBUG && i != L_BSSI && i != L_BSSD)
			loadsize += ldh.l_ssize[i];
	}
	return (0);
}

/*
 * Read the exe header.
 */
#ifndef DOEXE
getexe() { return 1; }
#else
#include "exe.h"


execani(ip)	/* convert from MSDOS exe header byte order to host */
register short *ip;
{
	/* First convert to standard pdp-11 byte order */
	/* Notice, nothing to do to accomplish this    */

	/* Now convert from pdp-11 byte order to host */

	canshort(*ip);
}

getexe()
{
	long daddr;
	exehdr_t exehdr;

	fseek(ifp, 0L, 0);
	fread((char *)&exehdr, 1, sizeof(exehdr), ifp);
	execani(&exehdr.x_magic);
	if (exehdr.x_magic != EXEMAGIC)
		return (1);
	execani(&exehdr.x_sectors);
	execani(&exehdr.x_bytes);
	daddr = (long) exehdr.x_sectors * 512;
	if ( exehdr.x_bytes != 0 )
		daddr += exehdr.x_bytes - 512;
	fseek(ifp, daddr, 0);
	if (gethdr() != 0)
		return 1;
	loadsize = daddr;
	return 0;
}
#endif

/*
 *	Read a gemdos .prg header.
 */
#ifndef DOPRG
getprg() { return 1; }
#else
#include "gemout.h"
/* convert 68000 byte order to pdp11 byte order and vice versa */
#if PDP11
gemcani(ip) register unsigned char *ip;
{
	register t;
	t = ip[0]; ip[0] = ip[1]; ip[1] = t;
}
gemcanl(lp) register unsigned char *lp;
{
	register t;
	t = lp[0]; lp[0] = lp[1]; lp[1] = t;
	t = lp[2]; lp[2] = lp[3]; lp[3] = t;
}
#endif
#if M68000
#define gemcani(i)	/* Nil */
#define gemcanl(l)	/* Nil */
#endif

getprg()
{
	struct gemohdr ghd;
	register long daddr;
	register int c;
	fseek(ifp, 0L, 0);
	fread((char *)&ghd, 1, sizeof(ghd), ifp);
	gemcani(&ghd.g_magic);
	if (ghd.g_magic != GEMOMAGIC)
		return 1;
	gemcanl(&ghd.g_ssize[0]);
	gemcanl(&ghd.g_ssize[1]);
	gemcanl(&ghd.g_ssize[2]);
	gemcanl(&ghd.g_ssize[3]);
	daddr = sizeof(ghd) + ghd.g_ssize[0] + ghd.g_ssize[1] + ghd.g_ssize[3];
	fseek(ifp, daddr, 0);
	if (getw(ifp) | getw(ifp)) {
		while (c = getc(ifp))
			if (c == EOF)
				return 1;
	}
	daddr = ftell(ifp);
	if (gethdr() != 0)
		return 1;
	loadsize = daddr;
	return 0;
}
#endif

/*
 * Strip specific code.
 * Strip the debug table, the symbol
 * table and the relocation information from a
 * object file.
 * Optionally keep any combination of the three.
 */

char	*tmp;
char	werror[] = "write error";
char	rerror[] = "cannot reopen";
char	xerror[] = "unexpected end of file";
char	oerror[] = "not an object file";
char	usemsg[] = "Usage: %s [-drs] file [ ... ]\n";

int dkeep;
int rkeep;
int skeep;

int notcoh = 1;	/* flag indicative of what object type the file is */
int notexe = 1;
int notprg = 1;

struct	ldheader olh;	/* output file l.out.h header */

int	cleanup();

main(argc, argv)
char *argv[];
{
	register estat, i;
	register char *cp;
	register c;
	extern char *tempnam();

	argv0 = argv[0];
	if (argc < 2)
		usage();
	tmp = tempnam(NULL, "s");
#if COHERENT
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		signal(SIGINT, cleanup);
#endif
	estat = 0;
	for (i=1; i<argc; i++) {
		cp = argv[i];
		if (cp[0] == '-') {
			while ((c = *++cp) != 0)
				if (c == 'd') ++dkeep;
				else if (c == 'r') ++rkeep;
				else if (c == 's') ++skeep;
				else usage();
			continue;
		}
		fn = argv[i];
		estat |= strip();
		if (ifp != NULL) {
			fclose(ifp);
			ifp = NULL;
		}
		if (ofp != NULL) {
			fclose(ofp);
			ofp = NULL;
		}
	}
	cleanup(estat);
}

/*
 * Do all the work.
 * The external variables 'ifp' and 'ofp'
 * will be closed by the mainline. This makes the
 * many error conditions a little easier to
 * deal with.
 */
strip()
{
	int i;
	register long nsize;

	if ((ifp = fopen(fn, "rb")) == NULL) {
		diag("cannot open", fn);
		return(1);
	}
	if ((ofp = fopen(tmp, "wb")) == NULL) {
		diag("cannot create", tmp);
		return(1);
	}
	if ( (notcoh=gethdr()) != 0
	 &&  (notexe=getexe()) != 0
	 &&  (notprg=getprg()) != 0) {
		diag("not an object file", fn);
		return(1);
	}
	olh = ldh;
	if ( ! dkeep) {
		olh.l_ssize[L_DEBUG] = 0;
		olh.l_flag &= ~LF_DEBUG;
	}
	if ( ! rkeep) {
		olh.l_flag |= LF_NRB;
		olh.l_ssize[L_REL] = 0;
	}
	if ( ! skeep)
		olh.l_ssize[L_SYM] = 0;
	if (ldh.l_flag == olh.l_flag
	 && ldh.l_ssize[L_DEBUG] == olh.l_ssize[L_DEBUG]
	 && ldh.l_ssize[L_SYM] == olh.l_ssize[L_SYM]
	 && ldh.l_ssize[L_REL] == olh.l_ssize[L_REL])
		return(0);

	if (writehead() != 0		/* header of output file */
	 || copy(loadsize) != 0		/* all loadable segments */
	 || writelout() != 0) 		/* l.out.h header in exe and prg */
		return(1);

	for (i = L_DEBUG; i < NLSEG; i += 1) {
		nsize = ldh.l_ssize[i];
		if (olh.l_ssize[i] == nsize)
			copy(nsize);
		else
			fseek(ifp, nsize, 1);
	}
	fflush(ofp);
	if (ferror(ofp)) {
		diag(werror, tmp);
		return (1);
	}
	if (ferror(ifp)) {
		diag("read error", fn);
		return 1;
	} else if (feof(ifp)) {
		diag(xerror, fn);
		return 1;
	}
	fclose(ifp);
	ifp = NULL;
	loadsize = ftell(ofp);
	fclose(ofp);
	ofp = NULL;
	if ((ifp = fopen(tmp, "rb")) == NULL) {
		diag(rerror, tmp);
		return (1);
	}
	if ((ofp = fopen(fn, "wb")) == NULL) {
		diag(rerror, fn);
		return (1);
	}
	copy(loadsize);
	fflush(ofp);
	if (ferror(ofp)) {
		diag(werror, fn);
		fprintf(stderr, "%s: file saved in %s\n", argv0, tmp);
		exit(1);
	}
	return (0);
}

/*
 * Convert the l.out header structure
 * in the buffer 'lh' to and from standard
 * ordering.
 */
canlh(ldhp)
register struct ldheader *ldhp;
{
	register i;

	canshort(ldhp->l_magic);
	canshort(ldhp->l_flag);
	canshort(ldhp->l_machine);
	canshort(ldhp->l_tbase);
	for (i=0; i<NLSEG; ++i)
		canlong(ldhp->l_ssize[i]);
	canlong(ldhp->l_entry);
}

/*
 *	Writes the header at the beginning of the output file
 *	References flags: notcoh, notexe, and notprg.
 */
writehead()
{
	if ( !notcoh ) {
		register int size;
		if ((size = olh.l_tbase) < sizeof olh)
			olh.l_tbase = olh.l_entry;
		canlh(&olh);
		if (fwrite(&olh, size, 1, ofp) != 1) {
			diag(werror, tmp);
			return (1);
		}
		canlh(&olh);
		if (size < sizeof olh) {
			olh.l_entry = olh.l_tbase;	
			olh.l_tbase = size;
			fseek(ifp, (long)-2*sizeof(short), 1);
		}
	} else
		fseek(ifp, 0l, 0);
	return(0);
}

/*
 * Copy nbytes from ifp to ofp.
 */
copy(nbytes) long nbytes;
{
	register int n;
	static char buff[16*1024];

	while (nbytes > 0) {
		n = nbytes > sizeof buff ? sizeof buff : nbytes;
		if (fread(buff, 1, n, ifp) != n)
			return 1;
		if (fwrite(buff, 1, n, ofp) != n)
			return 1;
		nbytes -= n;
	}
	return 0;
}

/*
 *	Write the l.out.h header in the middle of the file for
 *	MS-DOS .exe and GEMDOS .prg
 *	Leave ifp at the beginning of L_DEBUG.
 */
writelout()
{
	if ( !notcoh )
		return(0);

	canlh(&olh);
	if (fwrite(&olh, sizeof(olh), 1, ofp) != 1) {
		diag(werror, tmp);
		return(1);
	}
	canlh(&olh);
	fseek(ifp, (long)sizeof(ldh), 1);
	return(0);
}

	
/*
 * Print diagnostics.
 */
diag(s, fn)
char *s;
char *fn;
{
	fprintf(stderr, "%s: ", argv0);
	if (fn != NULL)
		fprintf(stderr, "%s: ", fn);
	fprintf(stderr, "%s\n", s);
}

/*
 * Cleanup tempfile and exit.
 * The status is the exit status.
 * When a signal occurs, it is the signal
 * number which is non-zero so
 * this will be an acceptable exit status.
 */
cleanup(s)
{
	unlink(tmp);
	exit(s);
}

/*
 * Print usage message.
 */
usage()
{
	fprintf(stderr, usemsg, argv0);
	exit(1);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.