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