xref: /csrg-svn/sys/kern/subr_prf.c (revision 8447)
1*8447Sroot /*	subr_prf.c	4.22	82/10/10	*/
231Sbill 
331Sbill #include "../h/param.h"
431Sbill #include "../h/systm.h"
531Sbill #include "../h/seg.h"
631Sbill #include "../h/buf.h"
731Sbill #include "../h/conf.h"
81184Sbill #include "../h/reboot.h"
92172Swnj #include "../h/vm.h"
102172Swnj #include "../h/msgbuf.h"
112360Skre #include "../h/dir.h"
122360Skre #include "../h/user.h"
132360Skre #include "../h/tty.h"
1431Sbill 
1531Sbill /*
1631Sbill  * In case console is off,
1731Sbill  * panicstr contains argument to last
1831Sbill  * call to panic.
1931Sbill  */
2031Sbill char	*panicstr;
2131Sbill 
2231Sbill /*
2331Sbill  * Scaled down version of C Library printf.
242781Swnj  * Used to print diagnostic information directly on console tty.
252781Swnj  * Since it is not interrupt driven, all system activities are
262781Swnj  * suspended.  Printf should not be used for chit-chat.
272781Swnj  *
282781Swnj  * One additional format: %b is supported to decode error registers.
292781Swnj  * Usage is:
302781Swnj  *	printf("reg=%b\n", regval, "<base><arg>*");
312781Swnj  * Where <base> is the output base expressed as a control character,
322781Swnj  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
332781Swnj  * characters, the first of which gives the bit number to be inspected
342781Swnj  * (origin 1), and the next characters (up to a control character, i.e.
352781Swnj  * a character <= 32), give the name of the register.  Thus
362781Swnj  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
372781Swnj  * would produce output:
382781Swnj  *	reg=2<BITTWO,BITONE>
3931Sbill  */
4031Sbill /*VARARGS1*/
4131Sbill printf(fmt, x1)
422781Swnj 	char *fmt;
432781Swnj 	unsigned x1;
4431Sbill {
45285Sbill 
46285Sbill 	prf(fmt, &x1, 0);
47285Sbill }
48285Sbill 
492377Swnj /*
502781Swnj  * Uprintf prints to the current user's terminal,
512781Swnj  * guarantees not to sleep (so can be called by interrupt routines)
522781Swnj  * and does no watermark checking - (so no verbose messages).
532377Swnj  */
542377Swnj /*VARARGS1*/
552377Swnj uprintf(fmt, x1)
562781Swnj 	char *fmt;
572377Swnj 	unsigned x1;
58285Sbill {
59285Sbill 
602377Swnj 	prf(fmt, &x1, 2);
61285Sbill }
62285Sbill 
632377Swnj prf(fmt, adx, touser)
642781Swnj 	register char *fmt;
652781Swnj 	register u_int *adx;
66285Sbill {
672434Swnj 	register int b, c, i;
6831Sbill 	char *s;
692678Swnj 	int any;
7031Sbill 
7131Sbill loop:
722377Swnj 	while ((c = *fmt++) != '%') {
7331Sbill 		if(c == '\0')
7431Sbill 			return;
752377Swnj 		putchar(c, touser);
7631Sbill 	}
772377Swnj again:
7831Sbill 	c = *fmt++;
792781Swnj 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
802377Swnj 	switch (c) {
812377Swnj 
822377Swnj 	case 'l':
832377Swnj 		goto again;
842377Swnj 	case 'x': case 'X':
852377Swnj 		b = 16;
862377Swnj 		goto number;
872377Swnj 	case 'd': case 'D':
882377Swnj 	case 'u':		/* what a joke */
892377Swnj 		b = 10;
902377Swnj 		goto number;
912377Swnj 	case 'o': case 'O':
922377Swnj 		b = 8;
932377Swnj number:
943101Swnj 		printn((u_long)*adx, b, touser);
952377Swnj 		break;
962377Swnj 	case 'c':
972434Swnj 		b = *adx;
982434Swnj 		for (i = 24; i >= 0; i -= 8)
992434Swnj 			if (c = (b >> i) & 0x7f)
1002434Swnj 				putchar(c, touser);
1012377Swnj 		break;
1022678Swnj 	case 'b':
1032678Swnj 		b = *adx++;
1042678Swnj 		s = (char *)*adx;
1053101Swnj 		printn((u_long)b, *s++, touser);
1062678Swnj 		any = 0;
1072678Swnj 		if (b) {
1082678Swnj 			putchar('<', touser);
1092678Swnj 			while (i = *s++) {
1102678Swnj 				if (b & (1 << (i-1))) {
1112678Swnj 					if (any)
1122678Swnj 						putchar(',', touser);
1132678Swnj 					any = 1;
1142678Swnj 					for (; (c = *s) > 32; s++)
1152678Swnj 						putchar(c, touser);
1162678Swnj 				} else
1172678Swnj 					for (; *s > 32; s++)
1182678Swnj 						;
1192678Swnj 			}
1203878Swnj 			if (any)
1213878Swnj 				putchar('>', touser);
1222678Swnj 		}
1232678Swnj 		break;
1242678Swnj 
1252377Swnj 	case 's':
12631Sbill 		s = (char *)*adx;
127285Sbill 		while (c = *s++)
1282377Swnj 			putchar(c, touser);
1292377Swnj 		break;
1303736Sroot 
1313736Sroot 	case '%':
1323736Sroot 		putchar('%', touser);
1333736Sroot 		break;
13431Sbill 	}
13531Sbill 	adx++;
13631Sbill 	goto loop;
13731Sbill }
13831Sbill 
1392781Swnj /*
1402781Swnj  * Printn prints a number n in base b.
1412781Swnj  * We don't use recursion to avoid deep kernel stacks.
1422781Swnj  */
1432377Swnj printn(n, b, touser)
1443101Swnj 	u_long n;
14531Sbill {
1462434Swnj 	char prbuf[11];
1472377Swnj 	register char *cp;
14831Sbill 
1492377Swnj 	if (b == 10 && (int)n < 0) {
1502377Swnj 		putchar('-', touser);
1512377Swnj 		n = (unsigned)(-(int)n);
15231Sbill 	}
1532434Swnj 	cp = prbuf;
1542377Swnj 	do {
1552377Swnj 		*cp++ = "0123456789abcdef"[n%b];
1562377Swnj 		n /= b;
1572377Swnj 	} while (n);
1582377Swnj 	do
1592377Swnj 		putchar(*--cp, touser);
1602434Swnj 	while (cp > prbuf);
16131Sbill }
16231Sbill 
16331Sbill /*
1641184Sbill  * Panic is called on unresolvable fatal errors.
1652781Swnj  * It prints "panic: mesg", and then reboots.
1662781Swnj  * If we are called twice, then we avoid trying to
1672781Swnj  * sync the disks as this often leads to recursive panics.
16831Sbill  */
16931Sbill panic(s)
1702781Swnj 	char *s;
17131Sbill {
1725416Swnj 	int bootopt = RB_AUTOBOOT;
1732377Swnj 
1745416Swnj 	if (panicstr)
1755416Swnj 		bootopt |= RB_NOSYNC;
17631Sbill 	panicstr = s;
1773285Swnj 	printf("panic: %s\n", s);
1782781Swnj 	boot(RB_PANIC, bootopt);
17931Sbill }
18031Sbill 
18131Sbill /*
1822941Swnj  * Warn that a system table is full.
1832941Swnj  */
1842941Swnj tablefull(tab)
1852941Swnj 	char *tab;
1862941Swnj {
1872941Swnj 
1882941Swnj 	printf("%s: table is full\n", tab);
1892941Swnj }
1902941Swnj 
1912941Swnj /*
1922781Swnj  * Hard error is the preface to plaintive error messages
1932941Swnj  * about failing disk transfers.
1942781Swnj  */
1952941Swnj harderr(bp, cp)
1962678Swnj 	struct buf *bp;
1972941Swnj 	char *cp;
19831Sbill {
19931Sbill 
2002941Swnj 	printf("%s%d%c: hard error sn%d ", cp,
2012941Swnj 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
20231Sbill }
2032781Swnj 
204285Sbill /*
2052377Swnj  * Print a character on console or users terminal.
206285Sbill  * If destination is console then the last MSGBUFS characters
207285Sbill  * are saved in msgbuf for inspection later.
208285Sbill  */
2091785Sbill /*ARGSUSED*/
2102377Swnj putchar(c, touser)
2112377Swnj 	register int c;
212285Sbill {
213285Sbill 
2142377Swnj 	if (touser) {
2152377Swnj 		register struct tty *tp = u.u_ttyp;
2162360Skre 
2175404Swnj 		if (tp && (tp->t_state&TS_CARR_ON)) {
2182377Swnj 			register s = spl6();
2192377Swnj 			if (c == '\n')
2204970Swnj 				(void) ttyoutput('\r', tp);
2214970Swnj 			(void) ttyoutput(c, tp);
2222360Skre 			ttstart(tp);
2232360Skre 			splx(s);
2242360Skre 		}
2252360Skre 		return;
2262360Skre 	}
227*8447Sroot #include "../vax/mtpr.h"		/* XXX */
2282386Swnj 	if (c != '\0' && c != '\r' && c != 0177 && mfpr(MAPEN)) {
2292172Swnj 		if (msgbuf.msg_magic != MSG_MAGIC) {
2302172Swnj 			msgbuf.msg_bufx = 0;
2312172Swnj 			msgbuf.msg_magic = MSG_MAGIC;
2322172Swnj 		}
2332172Swnj 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
2342172Swnj 			msgbuf.msg_bufx = 0;
2352172Swnj 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
236285Sbill 	}
237285Sbill 	if (c == 0)
238285Sbill 		return;
239285Sbill 	cnputc(c);
240285Sbill }
241