!	RMSYM -- strip symbolic information from X.OUT executables
!	Copyright (C) 1998,2000 Nils M Holm
!	See the file LICENSE for conditions of use.

#r5;

interface	readpacked(3) = 11,
		writepacked(3),
		reposition(4),
		rename(2),
		memcopy(3),
		memcomp(3);

!-------------------- IOSTREAM DEFINITIONS START --------------------!
struct IOS =	IOS_FD,
		IOS_BUFFER,
		IOS_FLAGS,
		IOS_LEN,
		IOS_PTR,
		IOS_END;

const		IOF_READ	= 00001,
		IOF_WRITE	= 00002,
		IOF_EOF		= 00004;

const		SEEK_SET	= 0,
		SEEK_REL	= 1,
		SEEK_END	= 2;


ios_create(iostream, fd, buffer, len, mode) do
	iostream[IOS_FD] := fd;
	iostream[IOS_BUFFER] := buffer;
	iostream[IOS_FLAGS] := mode;
	iostream[IOS_LEN] := len;
	iostream[IOS_PTR] := 0;
	iostream[IOS_END] := 0;
	return iostream;
end


ios_flush(iostream) do
	var	k;

	if (iostream[IOS_FLAGS] & IOF_WRITE) do
		k := writepacked(iostream[IOS_FD], iostream[IOS_BUFFER],
			iostream[IOS_PTR]);
		if (k \= iostream[IOS_PTR]) return %1;
	end
	iostream[IOS_PTR] := 0;
	iostream[IOS_END] := 0;
	return 0;
end


ios_close(iostream) do
	if (ios_flush(iostream) < 0) return %1;
	close(iostream[IOS_FD]);
	iostream[IOS_FLAGS] := 0;
	return 0;
end


ios_wrch(iostream, ch) do
	if (	iostream[IOS_PTR] >= iostream[IOS_LEN] /\
		ios_flush(iostream) < 0
	)
		return %1;
	iostream[IOS_BUFFER]::iostream[IOS_PTR] := ch;
	iostream[IOS_PTR] := iostream[IOS_PTR]+1;
	return ch;
end


ios_write(iostream, buffer, len) do
	var	i, p, l, b;

	i := 0;
	p := iostream[IOS_PTR];
	l := iostream[IOS_LEN];
	b := iostream[IOS_BUFFER];
	while (len) do
		if (p >= l) do
			iostream[IOS_PTR] := p;
			if (ios_flush(iostream) < 0) return %1;
			p := iostream[IOS_PTR];
			l := iostream[IOS_LEN];
		end
		b::p := buffer::i;
		p := p+1;
		i := i+1;
		len := len-1;
	end
	iostream[IOS_PTR] := p;
	return i;
end


ios_more(iostream) do
	var	k;

	if (iostream[IOS_FLAGS] & IOF_READ) do
		k := readpacked(iostream[IOS_FD], iostream[IOS_BUFFER],
			iostream[IOS_LEN]);
		if (k < 0) return %1;
		if (k = 0)
			iostream[IOS_FLAGS] := iostream[IOS_FLAGS] | IOF_EOF;
		iostream[IOS_END] := k;
		iostream[IOS_PTR] := 0;
	end
	return k;
end


ios_rdch(iostream) do
	var	c;

	if (iostream[IOS_FLAGS] & IOF_EOF) return %1;
	if (	iostream[IOS_PTR] >= iostream[IOS_END] /\
		ios_more(iostream) < 1
	)
		return %1;
	c := iostream[IOS_BUFFER]::iostream[IOS_PTR];
	iostream[IOS_PTR] := iostream[IOS_PTR]+1;
	return c;
end


ios__read(iostream, buffer, len, ckln) do
	var	i, p, e, b;

	i := 0;
	p := iostream[IOS_PTR];
	e := iostream[IOS_END];
	b := iostream[IOS_BUFFER];
	while (len) do
		if (p >= e) do
			iostream[IOS_PTR] := p;
			if (ios_more(iostream) < 1) leave;
			p := iostream[IOS_PTR];
			e := iostream[IOS_END];
		end
		buffer::i := b::p;
		p := p+1;
		i := i+1;
		len := len-1;
		if (ckln /\ buffer::(i-1) = '\n') leave;
	end
	if (ckln) buffer::i := 0;
	iostream[IOS_PTR] := p;
	iostream[IOS_END] := e;
	return i;
end


ios_read(iostream, buffer, len) return ios__read(iostream, buffer, len, 0);


ios_eof(iostream) return (iostream[IOS_FLAGS] & IOF_EOF) -> %1: 0;
!-------------------- IOSTREAM DEFINITIONS END --------------------!


const	BUFLEN =	1024;

const	EXECMAGIC_HI=	6514,
	EXECMAGIC_LO=	1060;

const	XHMAGIC = 0, XLMAGIC = 1, XFLAGS = 2, XLTEXT = 3, XLDATA = 4,
	XLBSS = 5, XLSYM = 6, XHDR = 8;


error(s) do
	select(1, 2);
	writes("RMSYM: ");
	writes(s);
	newline();
	halt;
end


rdwrd(s) return ios_rdch(s) | (ios_rdch(s) << 8);


wrwrd(s, n) do
	ios_wrch(s, n & 255);
	return ios_wrch(s, n>>8);
end


copy(in, out, len) do
	var	buffer::1024;
	var	m, k;

	while (len) do
		m := len>1024-> 1024: len;
		k := ios_read(in, buffer, m);
		if (k \= m) error("file read error");
		if (ios_write(out, buffer, k) \= k)
			error("file write error");
		len := len - m;
	end
end


do
	var	hdr[XHDR], i;
	var	in[IOS], inbuf::BUFLEN, out[IOS], outbuf::BUFLEN;

	if (ios_create(in, 0, inbuf, BUFLEN, IOF_READ) = %1)
		error("cannot open input stream");
	if (ios_create(out, 1, outbuf, BUFLEN, IOF_WRITE) = %1)
		error("cannot open output stream");
	for (i=0, XHDR) hdr[i] := rdwrd(in);
	if (ios_eof(in)) error("short file");
	if (hdr[XLMAGIC] \= EXECMAGIC_LO) error("magic match failed");
	if (hdr[XHMAGIC] \= EXECMAGIC_HI) error("magic match failed");
	hdr[XLSYM] := 0;
	for (i=0, XHDR) wrwrd(out, hdr[i]);
	copy(in, out, hdr[XLTEXT]);
	copy(in, out, hdr[XLDATA]);
	ios_close(in);
	ios_close(out);
end

