Interdata732/usr/source/libc/src.a

eabort.sn* abort - force an illegal instruction fault
	entry abort
	pure
abort	equ	*
	dc	h'0'	illegal instruction
	end
alloc.c/*	c storage allocator
*	circular first fit strategy
*/
#define BLOK 512
#define BUSY 01
static char *allocs[2] {
	(int)&allocs[1]+BUSY,
	(int)&allocs[0]+BUSY
};

struct { int word; };
static char **allocp &allocs[1]; 	/* current search pointer */
static char **alloct &allocs[1]; 	/* top of arena (last cell) */

alloc(nbytes) {
	register int nwords;
	register char **p, **q;
	register char **t;

	nwords = (nbytes+(2*sizeof(p)-1))/sizeof(p);

	for(p=allocp;;) {
		do {
			if((p->word&BUSY)==0) {
				/* combine adjancent free blocks */
				while(((q = *p)->word&BUSY)==0)
					*p = *q;
				/* q -> end of current free block */
				if(q >= &p[nwords])
					goto found;
		   }
			q = p;
			p = p->word & ~BUSY;
		} while(q>=allocp || p<allocp);	/*check all blocks form current end around */

		if((*alloct=t=sbrk(BLOK*sizeof(p))) == -1)
			return(-1);
	
		if(t!=alloct+1)		/* only on 1st storage request */
			alloct->word =| BUSY;

		alloct = (*t = &t[BLOK]-1);
		*alloct = allocs;
		alloct->word =| BUSY;
	}
found:
	allocp = &p[nwords];
	if(q>allocp)
		*allocp = *p;	/*ie if only part of a free block reqd*/
	*p = allocp.word|BUSY;
	return(p+1);
}
free(p) 
char **p;
{
	allocp = p-1;
	allocp->word =& ~BUSY;	/* set pointer not busy */
}
oatof.ci_/*
 * Quick-and-dirty floating-poi scanner:
 *	converts a string of digits with optional sign, decimal point, and
 *	signed exponent to a floating-point value
 */

double atof(str)
char *str;
{
	double f;
	register char *s, c;
	register n, exp, neg;
	int expsign;

	/* check leading sign */
	neg = 0;
	if ((c = *(s = str)) == '-') {
		neg = 1;
		str++;
	}
	else if (c == '+')
		str++;
	/* scan digits before decimal pt */
	f = 0.0;
	while ((c = *str++) <= '9' && c >= '0') {
		f =* 10.0;
		f =+ c - '0';
	}
	/* scan digits after decimal pt */
	exp = 0;
	if (c == '.')
		while ((c = *str++) <= '9' && c >= '0') {
			f =* 10.0;
			f =+ c - '0';
			exp--;
		}
	/* scan exponent */
	if (c == 'e' || c == 'E') {
		expsign = 1;
		if ((c = *str) == '-') {
			expsign = -1;
			str++;
		}
		else if (c == '+')
			str++;
		n = 0;
		while ((c = *str++) <= '9' && c >= '0') {
			n =* 10;
			n =+ c - '0';
		}
		exp =+ expsign*n;
	}
	/* combine no. & exponent by inefficient repeated multiplication */
	if (exp) {
		if (exp < 0) do
			f =/ 10.0;
		while (++exp);
		else do
			f =* 10.0;
		while (--exp);
	}

	return(neg? -f : f);
}
'atoi.cߣVatoi(s)
char *s;
{
	register n, neg, c;
	register char *p;

	n = neg = 0;
	for (p = s; (c = *p) == ' ' || c == 'T'; p++) ;
	if (c == '-') {
		neg++;
		p++;
	}
	n = 0;
	while ((c = *p) <= '9' && c >= '0') {
		n =* 10;
		n =+ c - '0';
		p++;
	}
	return(neg? -n : n);
}

crt0.s>Wcrt0	title	unix c library -- runtime initialization
	extrn	main
	extrn	exit
	entry	_exit
r0	equ	0
sp	equ	7
rf	equ	15
	pure
* rearrange args on stack & call main routine
	sis	sp,8
	l	r0,8(sp)
	st	r0,0(sp)
	la	r0,12(sp)
	st	r0,4(sp)
	bal	rf,main
* if main routine returns, exit
	st	r0,0(sp)
	bal	rf,exit
*
_exit	equ	*
	l	r0,0(sp)
	svc	14,1
	end
=crypt.c
U/*
This routine is an exact implementation of Boris Hagelin's
cryptographic machine.  See U. S. Patent #2,089,603.
*/

static int	cagetable[] { 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8, 8, 9, 10, 12, 16,
	16, 17, 18, 20, 24, 32, 32, 33, 34, 36, 40, 48};
static int	warr1[52];
static int	warr2[50];
static int	warr3[46];
static int	warr4[42];
static int	warr5[38];
static int	warr6[34];
static int	*wheel1 warr1;
static int	*wheel2 warr2;
static int	*wheel3 warr3;
static int	*wheel4 warr4;
static int	*wheel5 warr5;
static int	*wheel6 warr6;
static char	key[130];
static int	biti;
static int	bitj;


/*
subroutine to manufacture a wheel
*/

static setup(list,n) int list[];
	{int *lp;
	lp = list;
	while(--n){
		*lp = lp+2;
		lp[1] = getbit();
		lp = lp + 2;
		}
	*lp = list;
	lp[1] = getbit();
	}



/*
subroutine to return the next bit from the main routines
argument
*/

static getbit(){
	  /*  static i,j;   */   
	int b;
	b = (key[bitj] >> biti) & 1;
	if (biti++ > 5) {
		bitj++;
		biti = 0;
		}
	return (b);
	}




crypt(inkey)
char	*inkey;
	{
	static char word[9];
	char *ip, *jp;
	int temp;
	int random;
	int i,j;
	int precious;
	int cage[27];
	int ii;

	biti = 0;
	bitj = 0;

	wheel1 = warr1;
	wheel2 = warr2;
	wheel3 = warr3;
	wheel4 = warr4;
	wheel5 = warr5;
	wheel6 = warr6;




/*
copy input key and pad with clever junk
*/

	jp = key;
	*jp++ = 004;
	*jp++ = 034;
		while (*jp++ = *inkey++);
		jp--;
	ip = key;
	while (jp < key+128) {
		*jp = jp[-1] ^ *ip++;
		jp++;
	}


/*
manufacture six wheels of various length
*/

	setup(wheel1,26);
	setup(wheel2,25);
	setup(wheel3,23);
	setup(wheel4,21);
	setup(wheel5,19);
	setup(wheel6,17);

/*
set up the cage bars from the key area
*/

	jp = key;
	i = 27;
	while (i--){
	cage[i] = cagetable[*jp++ % 28];
	}


/*
the internal settings are now complete
it's time to turn the crank, running the cage
bars against the wheel lugs.
*/


for (ii=0; ii<=7; ii++)  {
	temp = 040*wheel1[1] + 020*wheel2[1] + 010*wheel3[1]
		+ 004*wheel4[1] + 002*wheel5[1] + 001*wheel6[1];
	wheel1 = *wheel1;
	wheel2 = *wheel2;
	wheel3 = *wheel3;
	wheel4 = *wheel4;
	wheel5 = *wheel5;
	wheel6 = *wheel6;

	random = 0;
	i = 27;
	while (i--){
		random = random + ((temp & cage[i]) != 0);
		}
	random =% 26;
	word[ii] = random + 'a';


	}

	return(word);

}
icsignal.s-	title	csignal -- interface to c signal routines
	entry	csignal
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
r5	equ	5
sp	equ	7
rf	equ	15
*
* csignal(sig, func)
*
* note: this routine is *not* strictly reentrant.  if csignal() is 
*   interrupted by a signal routine which itself calls csignal(),
*   the svc may be called incorrectly.
*
nsig	equ	13	* add to brtab if this constant changes *
einval	equ	22
	pure
csignal	equ	*
*
* save previous signal value
*
	l	r1,0(sp)	sig
	bnp	illsig		must be +ve
	chi	r1,nsig		check range
	bp	illsig		too high
	lr	r0,r1		save sig number
	slls	r1,2		offset in sig table
	l	r5,sigtab-adc(r1)	previous value
*
* if func is nonzero and even, it's a function address
*
	l	r2,adc(sp)	func
	st	r2,sigtab-adc(r1)	set into sig table
	bz	nofunc		zero - not an address
	lis	r3,1		check low bit
	nr	r3,r2
	bnz	nofunc		odd - not an address
*
* replace function by branch table address so regs can be saved
*
	lr	r3,r1		signo * 4
	slls	r3,2		offset in branch table
	la	r2,brtab-16(r3)	branch table address
nofunc	equ	*
*
* call signal svc
*
	st	r0,svc.no	set signal number
	st	r2,svc.fn	set function address
	svc	14,0		* signal *
	dc	a(svcsig)
	bc	sigerr		carry bit -- error
*
* return previous signal value
*
	lis	r3,1		check low bit
	nr	r3,r0
	bnzr	rf		odd - signal previously ignored
	lr	r0,r5		return actual func address
	br	rf
*
* error exits
*
illsig	equ	*
	lhi	r0,einval	invalid argument
sigerr	equ	*
	st	r0,errno	set error number
	lcs	r0,1		error return
	br	rf
*
* branch table -- save regs & transfer to actual function address
* note: entries must be 16 bytes long!
*
*
	align	adc
brtab	equ	*	nsig entries
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,0*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,1*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,2*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,3*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,4*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,5*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,6*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,7*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,8*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,9*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,10*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,11*adc(0)
	b	callfunc(0)
*
	shi	sp,16*adc
	stm	r0,0(sp)
	lhi	r1,12*adc(0)
*
* call c function
*
callfunc equ	*
	l	r0,18*adc(sp)	previous sp value
	st	r0,sp*adc(sp)	save it
	l	r1,sigtab(r1)	function address
	bal	rf,0(r1)	call function
	l	r0,sp*adc(sp)	possibly changed sp value
	st	r0,18*adc(sp)	restore it
	st	sp,sp*adc(sp)
	lm	r0,0(sp)	restore regs
	ahi	sp,16*adc	pop stack
*
* return from interrupt
*
	svc	14,48		* signal 0 *
	dc	0
	impur
*
* signal svc
*
svcsig	equ	*
	svc	14,48		* signal *
svc.no	dc	0		signal number
svc.fn	dc	0		function address
*
* sig table - func value for each signal
*
sigtab	equ	*
	do	nsig
	dc	0

errno	comn
	das	1
	ends
	end
lctime.cxC#
/*
 * This routine converts time as follows.
 * The epoch is 0000 Jan 1 1970 GMT.
 * The argument time is in seconds since then.
 * The localtime(t) entry returns a pointer to an array
 * containing
 *  seconds (0-59)
 *  minutes (0-59)
 *  hours (0-23)
 *  day of month (1-31)
 *  month (0-11)
 *  year-1970
 *  weekday (0-6, Sun is 0)
 *  day of the year
 *  daylight savings flag
 *
 * The routine corrects for daylight saving
 * time and will work in any time zone provided
 * "timezone" is adjusted to the difference between
 * Greenwich and local standard time (measured in seconds).
 * In places like Michigan "daylight" must
 * be initialized to 0 to prevent the conversion
 * to daylight time.
 * There is a table which accounts for the peculiarities
 * undergone by daylight time in 1974-1975.
 *
 * The routine does not work
 * in Saudi Arabia which runs on Solar time.
 *
 * asctime(tvec))
 * where tvec is produced by localtime
 * returns a ptr to a character string
 * that has the ascii time in the form
 *	Thu Jan 01 00:00:00 1970n0\\
 *	01234567890123456789012345
 *	0	  1	    2
 *
 * ctime(t) just calls localtime, then asctime.
 */
char	cbuf[26];
int	dmsize[12]
{
	31,
	28,
	31,
	30,
	31,
	30,
	31,
	31,
	30,
	31,
	30,
	31
};

int timezone	-8*60*60;		/*** Australian EST ***/
int tzname[]
{
	"EST",
	"EDT",
};
int	daylight 0;	/* No daylight conversion */
/*
 * The following table is used for 1974 and 1975 and
 * gives the day number of the first day after the Sunday of the
 * change.
 */
static struct {
	int	daylb;
	int	dayle;
} daytab[] {
	5,	333,	/* 1974: Jan 6 - last Sun. in Nov */
	58,	303,	/* 1975: Last Sun. in Feb - last Sun in Oct */
};

#define	SEC	0
#define	MIN	1
#define	HOUR	2
#define	MDAY	3
#define	MON	4
#define	YEAR	5
#define	WDAY	6
#define	YDAY	7
#define	ISDAY	8

ctime(at)
int *at;
{
	return(asctime(localtime(at)));
}

localtime(tim)
int tim[];
{
	register int *t, *ct, dayno;
	int daylbegin, daylend;
	int copyt[2];

	t = copyt;
	t[0] = tim[0];
	t[1] = tim[1];
	dpadd(t, -timezone);
	ct = gmtime(t);
	dayno = ct[YDAY];
	daylbegin = 119;	/* last Sun in Apr */
	daylend = 303;		/* Last Sun in Oct */
	if (ct[YEAR]==74 || ct[YEAR]==75) {
		daylbegin = daytab[ct[YEAR]-74].daylb;
		daylend = daytab[ct[YEAR]-74].dayle;
	}
	daylbegin = sunday(ct, daylbegin);
	daylend = sunday(ct, daylend);
	if (daylight &&
	    (dayno>daylbegin || (dayno==daylbegin && ct[HOUR]>=2)) &&
	    (dayno<daylend || (dayno==daylend && ct[HOUR]<1))) {
		dpadd(t, 1*60*60);
		ct = gmtime(t);
		ct[ISDAY]++;
	}
	return(ct);
}

/*
 * The argument is a 0-origin day number.
 * The value is the day number of the first
 * Sunday on or after the day.
 */
static sunday(at, ad)
int *at;
{
	register int *t, d;

	t = at;
	d = ad;
	if (d >= 58)
		d =+ dysize(t[YEAR]) - 365;
	return(d - (d - t[YDAY] + t[WDAY] + 700) % 7);
}

gmtime(tim)
int tim[];
{
	register int d0, d1;
	register *tp;
	static xtime[9];
	extern int ldivr;

	/*
	 * break initial number into
	 * multiples of 8 hours.
	 * (28800 = 60*60*8)
	 */

	d0 = ldiv(tim[0], tim[1], 28800);
	d1 = ldivr;
	tp = &xtime[0];

	/*
	 * generate hours:minutes:seconds
	 */

	*tp++ = d1%60;
	d1 =/ 60;
	*tp++ = d1%60;
	d1 =/ 60;
	d1 =+ (d0%3)*8;
	d0 =/ 3;
	*tp++ = d1;

	/*
	 * d0 is the day number.
	 * generate day of the week.
	 */

	xtime[WDAY] = (d0+4)%7;

	/*
	 * year number
	 */
	for(d1=70; d0 >= dysize(d1); d1++)
		d0 =- dysize(d1);
	xtime[YEAR] = d1;
	xtime[YDAY] = d0;

	/*
	 * generate month
	 */

	if (dysize(d1)==366)
		dmsize[1] = 29;
	for(d1=0; d0 >= dmsize[d1]; d1++)
		d0 =- dmsize[d1];
	dmsize[1] = 28;
	*tp++ = d0+1;
	*tp++ = d1;
	xtime[ISDAY] = 0;
	return(xtime);
}

static asctime(t)
int *t;
{
	register char *cp, *ncp;
	register int *tp;

	cp = cbuf;
	for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
	ncp = &"SunMonTueWedThuFriSat"[3*t[6]];
	cp = cbuf;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	cp++;
	tp = &t[4];
	ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	*cp++ = *ncp++;
	cp = ct_numb(cp, *--tp);
	cp = ct_numb(cp, *--tp+100);
	cp = ct_numb(cp, *--tp+100);
	cp = ct_numb(cp, *--tp+100);
	cp =+ 2;
	cp = ct_numb(cp, t[YEAR]);
	return(cbuf);
}

dysize(y)
{
	if((y%4) == 0)
		return(366);
	return(365);
}

static ct_numb(acp, n)
{
	register char *cp;

	cp = acp;
	cp++;
	if (n>=10)
		*cp++ = (n/10)%10 + '0';
	else
		*cp++ = ' ';
	*cp++ = n%10 + '0';
	return(cp);
}
tdpadd.s.	title	unix double-precision integer arithmetic subroutines
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
r5	equ	5
r6	equ	6
sp	equ	7
re	equ	14
rf	equ	15
	entry	dpadd
*
* dpadd(long, addend)
*   int long[2], addend;
*
*	- add integer addend to double-integer long
*
	pure
dpadd	equ	*
	l	r1,0(sp)	ptr to first operand
	l	r0,4(sp)	second operand
	bnm	dpa.pos		negative ?
	lcs	r2,1		yes - propagate sign bit
	am	r2,0(r1)
dpa.pos	equ	*
	am	r0,4(r1)	add to low-order part
	bncr	rf		no carry - return
	lis	r0,1		add carry to high-order part
	am	r0,0(r1)
	br	rf
	end
errlst.cchar	*sys_errlist[] {
	"Error 0",
	"Not super-user",
	"No such file or directory",
	"No such process",
	"Interrupted system call",
	"I/O error",
	"No such device or address",
	"Arg list too long",
	"Exec format error",
	"Bad file number",
	"No children",
	"No more processes",
	"Not enough core",
	"Permission denied",
	"Error 14",
	"Block device required",
	"Mount device busy",
	"File exists",
	"Cross-device link",
	"No such device",
	"Not a directory",
	"Is a directory",
	"Invalid argument",
	"File table overflow",
	"Too many open files",
	"Not a typewriter",
	"Text file busy",
	"File too large",
	"No space left on device",
	"Illegal seek",
	"Read-only file system",
	"Too many links",
	"Broken Pipe",
};
int	sys_nerr { sizeof sys_errlist/sizeof sys_errlist[0] };
exit.s$Xzexit	title	unix c svc library -- exit
	entry	exit
	extrn	_exit
	pure
* go to real exit (in crt0)
exit	equ	*
	b	_exit
	end
fcreat.cߢ#include "iobuf.h"

fcreat(filename, iobuf)
struct iobuf *iobuf;

{
	register fd;

	if ((fd=creat(filename, 0666)) >= 0) {
		iobuf->fildes = fd;
		iobuf->left = iobuf->next = 0;
	}

	return(fd);
}

fflush.c߆3struct iobuf {
	int fd;
	int left;
	char *next;
	char buff[512];
};

fflush(buf)
struct iobuf *buf;
{
	register struct iobuf *bp;
	register len;

	bp = buf;
	if ((len = bp->next - bp->buff) > 0 && bp->left >= 0)
		write(bp->fd, bp->buff, len);
	bp->next = bp->left = 0;
}
fftoa.c/*
 * Fake version of ftoa for programs with no floating pt
 */
ftoa(x, str, prec, format)
float x;
char *str;
{
	str[0] = '?';
	str[1] = '\0';
}
flush.cߢS#include "iobuf.h"

extern struct iobuf fout;

flush()
{
	return(fflush(&fout));
}
ffopen.c*fopen(file, iobuf)
char *file;
int *iobuf;
{
	register fd;
	register int *buf;

	buf = iobuf;
	buf[0] = fd = open(file, 0);
	buf[1] = buf[2] = 0;
	return( fd < 0? -1 : 0);
}
ftoa.c?/*
 * Floating-point to ASCII conversion
 */

int	fltused	0;	/* forces loading if floating pt used in C program */

ftoa (x, str, prec, format)
float x;
char *str;
{
	/* converts a floating point number to an ascii string */
	/* x is stored into str, which should be at least 30 chars long */
	int ie, i, k, ndig, fstyle;
	double y;
	ndig= ( prec<=0) ? 7 : (prec > 22 ? 23 : prec+1);
	if  (format == 'f' || format == 'F')
		fstyle = 1;
	else
		fstyle = 0;
	/* print in eformat unless last arg is 'f' */
	ie = 0;
	/* if x negative, write minus and reverse */
	if ( x < 0)
		{
		*str++ = '-';
		x = -x;
		}
	
	/* put x in range 1 <= x < 10 */
	if (x > 0.0) while (x < 1.0)
		{
		x =* 10.0;
		ie--;
		}
	while (x >= 10.0)
		{
		x = x/10.0;
		ie++;
		}
	
	/* in f format, number of digits is related to size */
	if (fstyle) ndig =+ ie;
	
	/* round. x is between 1 and 10 and ndig will be printed to
			right of decimal point so rounding is ... */
	for (y = i = 1; i < ndig; i++)
		y = y/10.;
	x =+ y/2.;
	if (x >= 10.0) {x = 1.0; ie++;} /* repair rounding disasters */
	/* now loop.  put out a digit (obtain by multiplying by
		10, truncating, subtracting) until enough digits out */
	/* if fstyle, and leading zeros, they go out special */
	if (fstyle && ie<0)
		{
		*str++ = '0'; *str++ = '.';
		if (ndig < 0) ie = ie-ndig; /* limit zeros if underflow */
		for (i = -1; i > ie; i--)
		*str++ = '0';
		}
	for (i=0; i < ndig; i++)
		{
		k = x;
		*str++ = k + '0';
		if (i == (fstyle ? ie : 0)) /* where is decimal point */
			*str++ = '.';
		x =- (y=k);
		x =* 10.0;
		}
	
	/* now, in estyle,  put out exponent if not zero */
	if (!fstyle && ie!= 0)
		{
		*str++ = 'E';
		if (ie < 0)
			{
			ie = -ie;
			*str++ = '-';
			}
		for (k=100; k > ie; k =/10);
		for (; k >0; k =/10)
				{
				*str++ = ie/k + '0';
				ie = ie%k;
				}
		}
	*str = '\0';
	return;
}
egetc.cߣ#include "iobuf.h"

getc(iobuf)
struct iobuf *iobuf;

/* buffered input:
	-get a character from the user's buffer <iobuf>
	-if the buffer is empty, read the next record
	-returns the character, or -1 for error or end-of-file
*/

{
	register struct iobuf *io;
	register char c;

	io = iobuf;

	if (--io->left < 0) {
		io->left = c = read(io->fildes, io->buff, BLKSIZE)-1;
		if (c < 0)
			return(-1);
		io->next = io->buff;
	}

	return(*io->next++);

}
ygetchr.ck#include "iobuf.h"

struct iobuf fin;

getchar()
{
	register char c;

	return((c=getc(&fin))<0 ? 0 : c);
}
bgetpw.c⸆fgetpw(uid, buf)
int uid;
char buf[];
{
	static pbuf[131];		/***/
	static pwf;
	register n, c;
	register char *bp;

	if(pwf == 0)
		pwf = open("/etc/passwd", 0);
	if(pwf < 0)
		return(1);
	seek(pwf, 0, 0);
	pbuf[0] = pwf;
	pbuf[1] = 0;
	pbuf[2] = 0;
	uid =& 0377;

	for (;;) {
		bp = buf;
		while((c=getc(pbuf)) != '\n') {
			if(c <= 0)
				return(1);
			*bp++ = c;
		}
		*bp++ = '\0';
		bp = buf;
		n = 3;
		while(--n)
		while((c = *bp++) != ':')
			if(c == '\n')
				return(1);
		while((c = *bp++) != ':') {
			if(c<'0' || c>'9')
				continue;
			n = n*10+c-'0';
		}
		if(n == uid)
			return(0);
	}
	return(1);
}
getw.cstruct	{ char byte[];	};
getw(buf)
{
	int word;
	register i;

	for (i=0; i<sizeof word; i++)
		word.byte[i] = getc(buf);
	return(word);
}
itol.cˠ/*
 * Make a LONG from two INTs
 *
 * On the X/32 this returns the second int, since LONGs are one word
 */
long itol(arg)
union {
	long	larg;
	int	iarg[2];
} arg;
{
	return(arg.iarg[1]);
}
ldiv.sldiv	prog	unix c library -- double-integer division
	entry	ldiv
	entry ldivr
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
r5	equ	5
r6	equ	6
sp	equ	7
re	equ	14
rf	equ	15
*
* ldiv (hidividend, lodividend, divisor)
*
*	- divide double integer dividend by signed divisor
*
	pure
ldiv	equ	*
	l	r0,0(sp)	high order dividend
	l	r1,adc(sp)	low order dividend
	d	r0,2*adc(sp)	divide
	st	r0,ldivr	save remainder
	lr	r0,r1		return quotient
	br	rf
*
* remainder from long division
*
ldivr	comn
	das	1
	ends
	end
lrem.sBlrem	prog	unix c library -- double-integer remainder
	entry	lrem
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
r5	equ	5
r6	equ	6
sp	equ	7
re	equ	14
rf	equ	15
*
* lrem (hidividend, lodividend, divisor)
*
*	- divide double integer dividend by signed divisor
*	- return remainder
*
	pure
lrem	equ	*
	l	r0,0(sp)	high order dividend
	l	r1,adc(sp)	low order dividend
	d	r0,2*adc(sp)	divide
	br	rf		remainder is in r0
	end
tlsub.sKulsub	title	unix c svc library -- double-integer subtract
*
*	lsub(remainder, subtrahend, minuend)
*	long *remainder, *subtrahend, *minuend;
*
	entry	lsub
r0	equ	0
r1	equ	1
r2	equ	2
r3	equ	3
r4	equ	4
sp	equ	7
rf	equ	15
*
lsub	equ	*
	l	r1,0(sp)	&remainder
	l	r2,adc(sp)	&subtrahend
	l	r3,2*adc(sp)	&minuend
*
	lis	r4,0		clear carry
	l	r0,adc(r2)	low-order sub
	s	r0,adc(r3)	subtract low-order min
	bnc	nocarry		if carry ...
	lis	r4,1		... borrow 1
nocarry	equ	*
	st	r0,adc(r1)	low-order rem
	l	r0,0(r2)	high-order sub
	s	r0,0(r3)	subtract high-order min
	sr	r0,r4		subtract carry if present
	st	r0,0(r1)	high-order rem
	br	rf
	end
*mcount.sD* mcount -- count subroutine calls during profiling

* called at function entry (after the save sequence) by
*	la	r1,LABEL
*	bal	rf,mcount
* where LABEL is a word in the bss segment pointing to the function's
* entry in the count buffer
* each count buffer entry is two words: a pointer to the function entry
* point (actually pointing after the 'bal' to mcount, and initialized
* at the first call of mcount), and the count of calls

	entry	mcount
r0	equ	0
r1	equ	1
r2	equ	2
rf	equ	15

countbase comn		next available count buffer entry
	das	1
	ends

mcount	equ	*
	l	r2,0(r1)	pointer to count buffer entry
	bnz	mc1		skip if already initialized
	l	r2,countbase
	bzr	rf		no buffer - give up
	lr	r0,r2
	ais	r0,8		allocate buffer entry for this function
	st	r0,countbase
	st	rf,0(r2)	set back pointer to function
	ais	r2,4
	st	r2,0(r1)	set forward pointer to count buffer entry
mc1	equ	*
	lis	r0,1
	am	r0,0(r2)
	br	rf
	end
tmcrt0.smcrt0	title	unix c library -- runtime initialization with monitor
	entry	_exit
	extrn	exit
	entry	countbas
	extrn	main
	extrn	etext,sbrk,monitor
*
r0	equ	0
r1	equ	1
r2	equ	2
sp	equ	7
rf	equ	15
*
write	equ	4	write svc
cbufs	equ	100	no. of words in call-count buffer
*
countbas	dc	0	next available call-count buffer entry
*
	pure
start	equ	*
* rearrange args on stack
	sis	sp,8
	l	r0,8(sp)
	st	r0,0(sp)
	la	r0,12(sp)
	st	r0,4(sp)
* profile buffer size = program text size / 4
	la	r1,etext
	si	r1,eprol
	ais	r1,15
	srls	r1,4
* get storage for profile buffer
	shi	sp,5*adc
	lhi	r2,cbufs
	st	r2,4*adc(sp)
	slls	r2,1
	ais	r2,3
	ar	r1,r2
	st	r1,3*adc(sp)
	slls	r1,2
	st	r1,0(sp)
	bal	rf,sbrk
	chi	r0,-1
	be	nocore
* start profiling
	st	r0,2*adc(sp)
	ais	r0,3*adc
	st	r0,countbas
	la	r0,etext
	st	r0,1*adc(sp)
	la	r0,eprol
	st	r0,0(sp)
	bal	rf,monitor
	ahi	sp,5*adc
* call main program
	bal	rf,main
* if main routine returns, exit 
	st	r0,0(sp)
	bal	rf,exit
	b	_exit
*
* no core for monitor buffer
*
nocore	equ	*
	lis	r0,2
	svc	14,write
	dc	mesg
	dc	emesg-mesg
	svc	14,1
mesg	db	c'No space for monitor buffer',x'0a'
emesg	equ	*
	align	2
*
* Exit routine -- write out mon.out file and exit
*
_exit	equ	*
	sis	sp,adc
	lis	r0,0
	st	r0,0(sp)
	bal	rf,monitor
	l	r0,adc(sp)
	svc	14,1
* end of prologue
eprol	equ	*
	end
*mktemp.cߍmktemp(name)
char *name;
{
	int stbuf[18];
	register char *p;
	register n, c;

	for (p = name; *p; p++)
		;
	n = getpid();
	while ((c = *--p) == 'X') {
		*p = (n&07)+'0';
		n =>> 3;
	}
	while (stat(name, stbuf) >= 0) {
		if (c >= 'z')
			return(-1);
		*p = ++c;
	}
	return(name);
}
mon.cklmonitor(lowpc, highpc, buf, bufsiz, cntsiz)
char *lowpc, *highpc;
int *buf, bufsiz;
{
	register char *o;
	static *sbuf, ssiz;

	if (lowpc == 0) {
		profil(0, 0, 0, 0);
		o = creat("mon.out", 0666);
		write(o, sbuf, ssiz*(sizeof *sbuf));
		close(o);
		return;
	}
/***
	if (nargs() <= 4)
		cntsiz = 0;
***/
	ssiz = bufsiz;
	buf[0] = lowpc;
	buf[1] = highpc;
	buf[2] = cntsiz;
	sbuf = buf;
	buf =+ 2*cntsiz + 3;
	bufsiz =- (2*cntsiz + 3);
	if (bufsiz<=0)
		return;
	o = (highpc - lowpc)/(sizeof *buf);
	if(bufsiz < o)
		o = ldiv(bufsiz, 0, (o<<1)); else
		o = 0x7fffffff;
	profil(buf, bufsiz*(sizeof *buf), lowpc, o<<1);
}
perror.cperror(mesg)
char *mesg;
{
	extern errno, sys_nerr;
	extern char *sys_errlist[];

	printf("%s: ", mesg);
	if (errno > sys_nerr)
		printf("%d error\n", errno);
	else
		printf("%s\n", sys_errlist[errno]);
}
(printf.cm/*
 * Printf:
 *	Print formatted data to standard output file.
 *	For external description, see man(iii).
 *
 */


static int prfwidth, prfprec;		/* Width & precision */

printf(afmt, args)
char *afmt;
{
	register char *fmt;
	register int *argp, left, c, n;

	/*
	 * argp is used to step along list of arguments, since
	 * the number of args is not known in advance.
	 */
	argp = &args;

	for (fmt = afmt; c = *fmt; fmt++) {
		/*
		 * Copy format string to output string until
		 * escape character is encountered.
		 */
		if (c != '%') {
			putchar(c);
			continue;
		}
		/* '-' means left-justification of field. */
		left = 0;
		if ((c = *++fmt) == '-') {
			left++;
			fmt++;
		}
		/* Convert width field if present. */
		n = 0;
		while ((c = *fmt) <= '9' && c >= '0') {
			n =* 10;
			n =+ c - '0';
			fmt++;
		}
		prfwidth = n;
		/* Convert precision field if present. */
		n = 0;
		if (c == '.')
			while ((c = *++fmt) <= '9' && c >= '0') {
				n =* 10;
				n =+ c - '0';
			}
		prfprec = n;
		/*
		 * Print the argument in the requested format.
		 * If prf1() returns <0, an unknown character followed
		 * the '%', so the argument was not used. Otherwise,
		 * step to the next argument.
		 */
		if (prf1(c, *argp, left) >= 0)
			argp++;
	}
}

/*
 * Print a single argument according to the given format character.
 * Left-justify if left == 1.
 */

static char prfhex[]	{ "0123456789ABCDEF" };		/* Hexadecimal digits */

static prf1(fmt, arg, left)
{
	register int x, len, c;
	register char *p, *lastc;
	static char buff[32];

	/* Initialize pointers to first & last+1 char in buffer. */
	x = arg;
	lastc = p = &buff[32];

	switch (fmt) {

	/* Unknown character: just print the format char. */
	default:
		*--p = fmt;
		fmt = -1;
		break;

	/* Single character */
	case 'c': case 'C':
		if (x)
			*--p = x;
		break;

	/* String: set pointers to first & last+1 char. */
	case 's': case 'S':
		p = lastc = x;
		while (*lastc)
			lastc++;
		break;

	/* Octal */
	case 'o': case 'O':
		do
			*--p = (x & 07) + '0';
		while (x =>> 3);
		break;

	/* Hexadecimal */
	case 'x': case 'X':
		do
			*--p = prfhex[x & 017];
		while (x =>> 4);
		break;

	/* Signed decimal */
	case 'd': case 'D':
		if (x < 0)
			x = -arg;

	/* Unsigned decimal */
	case 'l': case 'L':
		do
			*--p = ((unsigned)x % 10) + '0';
		while ((unsigned)x =/ 10);
		if (arg < 0 && (fmt == 'd' || fmt == 'D'))
			*--p = '-';
		break;

	/* Floating point */
	case 'f': case 'F':
	case 'e': case 'E':
		p = lastc = buff;
		ftoa(x, p, prfprec, fmt);
		while (*lastc)
			lastc++;
		prfprec = 0;
		break;

	}

	/* Compute len = -(no. of pad chars needed to fill width) */

	len = lastc - p;
	if (prfprec && len > prfprec) {
		len = prfprec;
		lastc = p + len;
	}
	len =- prfwidth;

	/* Pad to left if right-justified */
	if (!left)
		while (len++ < 0)
			putchar(' ');
	/*
	 * Print converted string -- terminated by lastc.
	 */
	while (p < lastc)
		putchar(*p++);

	/* Pad to right if left-justified */
	while (len++ < 0)
		putchar(' ');

	/* Returned value >=0 asks printf to step to next argument. */

	return(fmt);
}

putc.cߣ#include "iobuf.h"

putc(c, iobuf)
struct iobuf *iobuf;

/* buffered output:
	-put a character into the user's buffer <iobuf>
	-if the buffer is full, write the  record
	-returns the argument character, or -1 for error 
*/

{
	register struct iobuf *io;
	register char ch, len;

	io = iobuf;
	ch = c;

	if (--io->left < 0) {
		if (io->next) {
			len = write(io->fildes, io->buff, io->next-io->buff);
			if (len <= 0)
				return(-1);
		}
		io->next = io->buff;
		io->left = BLKSIZE-1;
	}

	*io->next++ = ch;


	return(c);

}
putchr.cj#include "iobuf.h"

struct iobuf fout {
	1		/* standard output file */
};

putchar(ch)
{
	char c;

/*
 * if standard output <= 2, output is character-by-character.
 * otherwise it is buffered using the standard iobuf 'fout'.
 */
	if (fout.fildes <= 2) {
		if (c = ch&0377)
			write (fout.fildes, &c, 1);
		return(c);
	}
	return((c=putc(ch, &fout))<0 ? 0 : c);
}
putw.c;struct	{ char byte[];	};

putw(word, buf)
{
	register i;

	for (i=0; i<sizeof word; i++)
		putc(word.byte[i], buf);
	return(0);
}
qsort.cnNstatic int	(*qscmp)();
static int	qses;

qsort(a, n, es, fc)
char *a;
int n, es;
int (*fc)();
{
	qscmp = fc;
	qses = es;
	qs1(a, a+n*es);
}

static qs1(a, l)
char *a, *l;
{
	register char *i, *j, *es;
	char *lp, *hp;
	int n, c;


	es = qses;

start:
	if((n=l-a) <= es)
		return;


	n = ((n/(2*es))*es) & 077777;
	hp = lp = a+n;
	i = a;
	j = l-es;


	for(;;) {
		if(i < lp) {
			if((c = (*qscmp)(i, lp)) == 0) {
				qsexc(i, lp =- es);
				continue;
			}
			if(c < 0) {
				i =+ es;
				continue;
			}
		}

loop:
		if(j > hp) {
			if((c = (*qscmp)(hp, j)) == 0) {
				qsexc(hp =+ es, j);
				goto loop;
			}
			if(c > 0) {
				if(i == lp) {
					qstexc(i, hp =+ es, j);
					i = lp =+ es;
					goto loop;
				}
				qsexc(i, j);
				j =- es;
				i =+ es;
				continue;
			}
			j =- es;
			goto loop;
		}


		if(i == lp) {
			if(lp-a >= l-hp) {
				qs1(hp+es, l);
				l = lp;
			} else {
				qs1(a, lp);
				a = hp+es;
			}
			goto start;
		}


		qstexc(j, lp =- es, i);
		j = hp =- es;
	}
}

static qsexc(i, j)
char *i, *j;
{
	register char *ri, *rj, c;
	int n;

	n = qses;
	ri = i;
	rj = j;
	do {
		c = *ri;
		*ri++ = *rj;
		*rj++ = c;
	} while(--n);
}

static qstexc(i, j, k)
char *i, *j, *k;
{
	register char *ri, *rj, *rk;
	char	c;
	int	n;

	n = qses;
	ri = i;
	rj = j;
	rk = k;
	do {
		c = *ri;
		*ri++ = *rk;
		*rk++ = *rj;
		*rj++ = c;
	} while(--n);
}
reset.sQreset	prog c library -- setexit and reset
	entry reset,setexit
*
* setexit()
*
*	- saves current status of stack & registers
*
* reset()
*
*	- restores saved status, simulating a return from the most
*	recent setexit()
*
r0	equ	0
sp	equ	7
rf	equ	15
	pure
setexit	equ	*
	stm	sp,saveregs	save current regs
	lis	r0,0	clear ret code
	br	rf
*
reset	equ	*
	lm	sp,saveregs	restore saved regs
	lis	r0,0	clear ret code
	br	rf
*
	bss
saveregs equ	*	space for regs sp & up
	das	rf-sp+1
	end
rti.s	title	rti -- 7/32 unix return-from-interrupt routine
	entry	rti
	pure
rti	equ	*
*
* 'signal 0' means return from signal routine
*
* ps, pc & sp will be popped off stack
*
	svc	14,48
	dc	0
	end
ttyn.cߣ1/*
 * Return name of tty associated with given filedescriptor
 *	- direct translation of original pdp-11 assembler version
 */

ttyn(fd)
{
	int buf[18];
	register inode, dir;
	register char *p;

	if (fstat(fd, buf) < 0
	 || (dir = open("/dev", 0)) < 0)
		return('x');
	inode = buf[1];

	while (read(dir, buf, 16) == 16) {
		p = buf;
		if ((p[0]<<8) + p[1] == inode
		 && p[2] == 't' && p[3] == 't' && p[4] == 'y'
		 && p[5] != '\0' && p[6] == '\0')
			return(p[5]);
	}
	return('x');
}
q