xref: /csrg-svn/sys/kern/subr_prf.c (revision 14211)
1 /*	subr_prf.c	6.1	83/07/29	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/seg.h"
6 #include "../h/buf.h"
7 #include "../h/conf.h"
8 #include "../h/reboot.h"
9 #include "../h/vm.h"
10 #include "../h/msgbuf.h"
11 #include "../h/dir.h"
12 #include "../h/user.h"
13 #include "../h/proc.h"
14 #include "../h/tty.h"
15 
16 #ifdef vax
17 #include "../vax/mtpr.h"
18 #endif
19 
20 /*
21  * In case console is off,
22  * panicstr contains argument to last
23  * call to panic.
24  */
25 char	*panicstr;
26 
27 /*
28  * Scaled down version of C Library printf.
29  * Used to print diagnostic information directly on console tty.
30  * Since it is not interrupt driven, all system activities are
31  * suspended.  Printf should not be used for chit-chat.
32  *
33  * One additional format: %b is supported to decode error registers.
34  * Usage is:
35  *	printf("reg=%b\n", regval, "<base><arg>*");
36  * Where <base> is the output base expressed as a control character,
37  * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
38  * characters, the first of which gives the bit number to be inspected
39  * (origin 1), and the next characters (up to a control character, i.e.
40  * a character <= 32), give the name of the register.  Thus
41  *	printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
42  * would produce output:
43  *	reg=2<BITTWO,BITONE>
44  */
45 /*VARARGS1*/
46 printf(fmt, x1)
47 	char *fmt;
48 	unsigned x1;
49 {
50 
51 	prf(fmt, &x1, 0);
52 }
53 
54 /*
55  * Uprintf prints to the current user's terminal,
56  * guarantees not to sleep (so can be called by interrupt routines)
57  * and does no watermark checking - (so no verbose messages).
58  */
59 /*VARARGS1*/
60 uprintf(fmt, x1)
61 	char *fmt;
62 	unsigned x1;
63 {
64 
65 	prf(fmt, &x1, 2);
66 }
67 
68 prf(fmt, adx, touser)
69 	register char *fmt;
70 	register u_int *adx;
71 {
72 	register int b, c, i;
73 	char *s;
74 	int any;
75 
76 loop:
77 	while ((c = *fmt++) != '%') {
78 		if(c == '\0')
79 			return;
80 		putchar(c, touser);
81 	}
82 again:
83 	c = *fmt++;
84 	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
85 	switch (c) {
86 
87 	case 'l':
88 		goto again;
89 	case 'x': case 'X':
90 		b = 16;
91 		goto number;
92 	case 'd': case 'D':
93 	case 'u':		/* what a joke */
94 		b = 10;
95 		goto number;
96 	case 'o': case 'O':
97 		b = 8;
98 number:
99 		printn((u_long)*adx, b, touser);
100 		break;
101 	case 'c':
102 		b = *adx;
103 		for (i = 24; i >= 0; i -= 8)
104 			if (c = (b >> i) & 0x7f)
105 				putchar(c, touser);
106 		break;
107 	case 'b':
108 		b = *adx++;
109 		s = (char *)*adx;
110 		printn((u_long)b, *s++, touser);
111 		any = 0;
112 		if (b) {
113 			putchar('<', touser);
114 			while (i = *s++) {
115 				if (b & (1 << (i-1))) {
116 					if (any)
117 						putchar(',', touser);
118 					any = 1;
119 					for (; (c = *s) > 32; s++)
120 						putchar(c, touser);
121 				} else
122 					for (; *s > 32; s++)
123 						;
124 			}
125 			if (any)
126 				putchar('>', touser);
127 		}
128 		break;
129 
130 	case 's':
131 		s = (char *)*adx;
132 		while (c = *s++)
133 			putchar(c, touser);
134 		break;
135 
136 	case '%':
137 		putchar('%', touser);
138 		break;
139 	}
140 	adx++;
141 	goto loop;
142 }
143 
144 /*
145  * Printn prints a number n in base b.
146  * We don't use recursion to avoid deep kernel stacks.
147  */
148 printn(n, b, touser)
149 	u_long n;
150 {
151 	char prbuf[11];
152 	register char *cp;
153 
154 	if (b == 10 && (int)n < 0) {
155 		putchar('-', touser);
156 		n = (unsigned)(-(int)n);
157 	}
158 	cp = prbuf;
159 	do {
160 		*cp++ = "0123456789abcdef"[n%b];
161 		n /= b;
162 	} while (n);
163 	do
164 		putchar(*--cp, touser);
165 	while (cp > prbuf);
166 }
167 
168 /*
169  * Panic is called on unresolvable fatal errors.
170  * It prints "panic: mesg", and then reboots.
171  * If we are called twice, then we avoid trying to
172  * sync the disks as this often leads to recursive panics.
173  */
174 panic(s)
175 	char *s;
176 {
177 	int bootopt = RB_AUTOBOOT;
178 
179 	if (panicstr)
180 		bootopt |= RB_NOSYNC;
181 	else {
182 		panicstr = s;
183 	}
184 	printf("panic: %s\n", s);
185 	boot(RB_PANIC, bootopt);
186 }
187 
188 /*
189  * Warn that a system table is full.
190  */
191 tablefull(tab)
192 	char *tab;
193 {
194 
195 	printf("%s: table is full\n", tab);
196 }
197 
198 /*
199  * Hard error is the preface to plaintive error messages
200  * about failing disk transfers.
201  */
202 harderr(bp, cp)
203 	struct buf *bp;
204 	char *cp;
205 {
206 
207 	printf("%s%d%c: hard error sn%d ", cp,
208 	    dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno);
209 }
210 
211 /*
212  * Print a character on console or users terminal.
213  * If destination is console then the last MSGBUFS characters
214  * are saved in msgbuf for inspection later.
215  */
216 /*ARGSUSED*/
217 putchar(c, touser)
218 	register int c;
219 {
220 
221 	if (touser) {
222 		register struct tty *tp = u.u_ttyp;
223 
224 		if (tp && (tp->t_state&TS_CARR_ON)) {
225 			register s = spl6();
226 			if (c == '\n')
227 				(void) ttyoutput('\r', tp);
228 			(void) ttyoutput(c, tp);
229 			ttstart(tp);
230 			splx(s);
231 		}
232 		return;
233 	}
234 	if (c != '\0' && c != '\r' && c != 0177
235 #ifdef vax
236 	    && mfpr(MAPEN)
237 #endif
238 	    ) {
239 		if (msgbuf.msg_magic != MSG_MAGIC) {
240 			register int i;
241 
242 			msgbuf.msg_bufx = 0;
243 			msgbuf.msg_magic = MSG_MAGIC;
244 			for (i=0; i < MSG_BSIZE; i++)
245 				msgbuf.msg_bufc[i] = 0;
246 		}
247 		if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
248 			msgbuf.msg_bufx = 0;
249 		msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
250 	}
251 	if (c == 0)
252 		return;
253 	cnputc(c);
254 }
255