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