static char rcsid[] = "$Header: header.c,v 10.1 86/07/21 14:56:20 bog Exp $";

/************************************************************************\
**									**
**				Copyright 1986				**
**			VALID LOGIC SYSTEMS INCORPORATED		**
**									**
**	This listing contains confidential proprietary information	**
**	which is not to be disclosed to unauthorized persons without	**
**	written consent of an officer of Valid Logic Systems 		**
**	Incoroporated.							**
**									**
**	The copyright notice appearing above is included to provide	**
**	statutory protection in the event of unauthorized or 		**
**	unintentional public disclosure.				**
**									**
\************************************************************************/

#include "../h/param.h"
#ifdef HEINOUS
#include "../s32/cpu.h"
#endif HEINOUS

/*
 * Watch out for #defining HEINOUS.  It plays with LED's, but may assume
 * that we are running on a 68010.  Or a 68020.  Read the code to see which
 * (the code for orStatusReg() versus what we are doing is the key).
 *
 * - bog
 */

/*
 * Scaled down version of C Library printf.
 * Used to print diagnostic information directly on console tty.
 * Since it is not interrupt driven, all system activities are
 * suspended.  Printf should not be used for chit-chat.
 *
 * One additional format: %b is supported to decode error registers.
 * Usage is:
 *	printf("reg=%b\n", regval, "<base><arg>*");
 * Where <base> is the output base expressed as a control character,
 * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
 * characters, the first of which gives the bit number to be inspected
 * (origin 1), and the next characters (up to a control character, i.e.
 * a character <= 32), give the name of the register.  Thus
 *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
 * would produce output:
 *	reg=2<BITTWO,BITONE>
 */
/*VARARGS1*/
printf(fmt, x1)
	char *fmt;
	unsigned x1;
{

#ifdef HEINOUS
	xorStatusReg(V_REDLED);	/* Turn on night light */
#endif HEINOUS
#ifdef USE_ERM
	prf1(fmt, &x1);
#else  USE_ERM
	prf(fmt, &x1);
#endif USE_ERM
#ifdef HEINOUS
	xorStatusReg(V_REDLED);	/* Turn off night light */
#endif HEINOUS
}

#ifndef USE_ERM
/*
 * Don't need fancy output formats.
 */
prf(fmt, adx)
	register char *fmt;
	register u_int *adx;
{
	register int b, c, i;
	char *s;
	int any;

loop:
	while ((c = *fmt++) != '%') {
#ifdef HEINOUS
	xorStatusReg(V_REDLED);	/* Flash night light */
#endif HEINOUS
		if(c == '\0')
			return;
		putchar(c);
	}
#ifdef HEINOUS
	orStatusReg(getStatusReg()&V_REDLED);	/* Turn off night light */
#endif HEINOUS
again:
	c = *fmt++;
	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
	switch (c) {

	case 'l':
		goto again;
	case 'x': case 'X':
		b = 16;
		goto number;
	case 'd': case 'D':
	case 'u':		/* what a joke */
		b = 10;
		goto number;
	case 'o': case 'O':
		b = 8;
number:
		printn((u_long)*adx, b);
		break;
	case 'c':
		b = *adx;
		for (i = 24; i >= 0; i -= 8)
			if (c = (b >> i) & 0x7f)
				putchar(c);
		break;
	case 'b':
		b = *adx++;
		s = (char *)*adx;
		printn((u_long)b, *s++);
		any = 0;
		if (b) {
			putchar('<');
			while (i = *s++) {
				if (b & (1 << (i-1))) {
					if (any)
						putchar(',');
					any = 1;
					for (; (c = *s) > 32; s++)
						putchar(c);
				} else
					for (; *s > 32; s++)
						;
			}
			putchar('>');
		}
		break;

	case 's':
		s = (char *)*adx;
		while (c = *s++)
			putchar(c);
		break;
	}
	adx++;
	goto loop;
}

#else  USE_ERM

/*
 * Scaled down version of C Library printf.
 *
 * One additional format: %b is supported to decode error registers.
 * Usage is:
 *	printf("reg=%b\n", regval, "<base><arg>*");
 * Where <base> is the output base expressed as a control character,
 * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
 * characters, the first of which gives the bit number to be inspected
 * (origin 1), and the next characters (up to a control character, i.e.
 * a character <= 32), give the name of the register.  Thus
 *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
 * would produce output:
 *	reg=2<BITTWO,BITONE>
 */
prf1(fmt, adx)
register char *fmt;
register u_int *adx;
{
	register int b, c, i;
	register width;
	int right;
	int zero;
	int usigned;
	char *s;
	int any;

loop:
	while ((c = *fmt++) != '%') {
		if(c == '\0')
			return;
		putchar(c);
	}
	usigned = 0;
	zero = 0;
	width = 0;
	right = 0;
again:
	c = *fmt++;
	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
	switch (c) {

	case '0':
		if (!width)
			zero = 1;
	case '1': case '2': case '3':
	case '4': case '5': case '6':
	case '7': case '8': case '9':
		width = width*10 + c - '0';
		goto again;
	case 'l':
		goto again;
	case 'x': case 'X':
		b = 16;
		goto number;
	case 'u':
		usigned = 1;
	case 'd': case 'D':
		b = 10;
		goto number;
	case 'o': case 'O':
		b = 8;
number:
		printn((u_long)*adx, b, width, zero, right, usigned);
		break;
	case 'c':
		b = *adx;
		for (i = 24; i >= 0; i -= 8)
			if (c = (b >> i) & 0x7f)
				putchar(c);
		break;
	case 'b':
		b = *adx++;
		s = (char *)*adx;
		printn((u_long)b, *s++, width, zero, right, 0);
		any = 0;
		if (b) {
			putchar('<');
			while (i = *s++) {
				if (b & (1 << (i-1))) {
					if (any)
						putchar(',');
					any = 1;
					for (; (c = *s) > 32; s++)
						putchar(c);
				} else
					for (; *s > 32; s++)
						;
			}
			if (any)
				putchar('>');
		}
		break;

	case 's':
		s = (char *)*adx;
		while (*s++)
			width--;
		s = (char *)*adx;
		if (!right) while (width-- > 0)
			putchar(' ');
		while (c = *s++)
			putchar(c);
		if (right) while (width-- > 0)
			putchar(' ');
		break;

	case '%':
		putchar('%');
		goto loop;
	case '*':
		width = *adx++;
		goto again;
	case '-':
		right = 1;
		goto again;
	}
	adx++;
	goto loop;
}

#endif  USE_ERM

/*
 * Printn prints a number n in base b.
 * We don't use recursion to avoid deep kernel stacks.
 */
printn(n, b)
	u_long n;
{
	char prbuf[11];
	register char *cp;

	if (b == 10 && (int)n < 0) {
		putchar('-');
		n = (unsigned)(-(int)n);
	}
	cp = prbuf;
	do {
		*cp++ = "0123456789ABCDEF"[n%b];
		n /= b;
	} while (n);
	do
		putchar(*--cp);
	while (cp > prbuf);
}
#ifdef IN_OTHER_FILE
/*
 * Print a character on console.
 * Attempts to save and restore device
 * status.
 *
 * Whether or not printing is inhibited,
 * the last MSGBUFS characters
 * are saved in msgbuf for inspection later.
 */
XXputchar(c)
	register c;
{
	register s, timo;

	timo = 30000;
	/*
	 * Try waiting for the console tty to come ready,
	 * otherwise give up after a reasonable time.
	 */
	while((mfpr(TXCS)&TXCS_RDY) == 0)
		if(--timo == 0)
			break;
	if(c == 0)
		return;
	s = mfpr(TXCS);
	mtpr(TXCS,0);
	mtpr(TXDB, c&0xff);
	if(c == '\n')
		putchar('\r');
	putchar(0);
	mtpr(TXCS, s);
}

getchar()
{
	register c;

	while((mfpr(RXCS)&RXCS_DONE) == 0)
		;
	c = mfpr(RXDB)&0177;
	if (c=='\r')
		c = '\n';
	putchar(c);
	return(c);
}
#endif

puts(buf)
	char *buf;
{
	register char *lp;

	lp = buf;
	while (*lp) putchar (*lp++);
	putchar ('\n');
}

gets(buf)
	char *buf;
{
	register char *lp;
	register c;

	lp = buf;
	for (;;) {
		c = getchar() & 0177;
	store:
		switch(c) {
		case '\n':
		case '\r':
			c = '\n';
			*lp++ = '\0';
			return;
		case '#':
			putchar('\b');
			putchar(' ');
			putchar('\b');
			putchar('\b');
		case '\b':
			if (lp > buf) {
				lp--;
				putchar(' ');
				putchar('\b');
			}
			continue;
		case '@':
		case 'u'&037:
			lp = buf;
			putchar('\n');
			continue;
		default:
			*lp++ = c;
		}
	}
}

fgets(buf, size, fd)
	char *buf;
{
	register char *lp;
	register c;
	register cnt = 0;

	lp = buf;
	for (;;) {
		c = getc(fd) & 0177;
	store:
		switch(c) {
		case '\n':
		case '\r':
			c = '\n';
			*lp++ = '\0';
			return cnt;
		case '#':
		case '\b':
			if (lp > buf) {
				lp--;
				cnt --;
			}
			continue;
		case '@':
		case 'u'&037:
			lp = buf;
			cnt = 0;
			continue;
		default:
			if (cnt++ >= size)
				return 0;
			*lp++ = c;
		}
	}
}

#ifdef A45J
strcmp (a, b)
register char *a, *b;
{
	while (*a && *b && *a == *b) a++, b++;
	return *a | *b;
}
#endif

