1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)prf.c 7.3 (Berkeley) 01/28/88 7 */ 8 9 #include "param.h" 10 11 #include "../vax/mtpr.h" 12 #include "../vax/cons.h" 13 14 /* 15 * Scaled down version of C Library printf. 16 * Used to print diagnostic information directly on console tty. 17 * Since it is not interrupt driven, all system activities are 18 * suspended. Printf should not be used for chit-chat. 19 * 20 * One additional format: %b is supported to decode error registers. 21 * Usage is: 22 * printf("reg=%b\n", regval, "<base><arg>*"); 23 * Where <base> is the output base expressed as a control character, 24 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 25 * characters, the first of which gives the bit number to be inspected 26 * (origin 1), and the next characters (up to a control character, i.e. 27 * a character <= 32), give the name of the register. Thus 28 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 29 * would produce output: 30 * reg=2<BITTWO,BITONE> 31 */ 32 /*VARARGS1*/ 33 printf(fmt, x1) 34 char *fmt; 35 unsigned x1; 36 { 37 38 prf(fmt, &x1); 39 } 40 41 prf(fmt, adx) 42 register char *fmt; 43 register u_int *adx; 44 { 45 register int b, c, i; 46 char *s; 47 int any; 48 49 loop: 50 while ((c = *fmt++) != '%') { 51 if(c == '\0') 52 return; 53 putchar(c); 54 } 55 again: 56 c = *fmt++; 57 /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 58 switch (c) { 59 60 case 'l': 61 goto again; 62 case 'x': case 'X': 63 b = 16; 64 goto number; 65 case 'd': case 'D': 66 case 'u': /* what a joke */ 67 b = 10; 68 goto number; 69 case 'o': case 'O': 70 b = 8; 71 number: 72 printn((u_long)*adx, b); 73 break; 74 case 'c': 75 b = *adx; 76 for (i = 24; i >= 0; i -= 8) 77 if (c = (b >> i) & 0x7f) 78 putchar(c); 79 break; 80 case 'b': 81 b = *adx++; 82 s = (char *)*adx; 83 printn((u_long)b, *s++); 84 any = 0; 85 if (b) { 86 while (i = *s++) { 87 if (b & (1 << (i-1))) { 88 putchar(any? ',' : '<'); 89 any = 1; 90 for (; (c = *s) > 32; s++) 91 putchar(c); 92 } else 93 for (; *s > 32; s++) 94 ; 95 } 96 if (any) 97 putchar('>'); 98 } 99 break; 100 101 case 's': 102 s = (char *)*adx; 103 while (c = *s++) 104 putchar(c); 105 break; 106 } 107 adx++; 108 goto loop; 109 } 110 111 /* 112 * Printn prints a number n in base b. 113 * We don't use recursion to avoid deep kernel stacks. 114 */ 115 printn(n, b) 116 u_long n; 117 { 118 char prbuf[11]; 119 register char *cp; 120 121 if (b == 10 && (int)n < 0) { 122 putchar('-'); 123 n = (unsigned)(-(int)n); 124 } 125 cp = prbuf; 126 do { 127 *cp++ = "0123456789abcdef"[n%b]; 128 n /= b; 129 } while (n); 130 do 131 putchar(*--cp); 132 while (cp > prbuf); 133 } 134 135 /* 136 * Print a character on console. 137 */ 138 putchar(c) 139 register c; 140 { 141 register s, timo; 142 143 timo = 30000; 144 /* 145 * Try waiting for the console tty to come ready, 146 * otherwise give up after a reasonable time. 147 */ 148 while((mfpr(TXCS)&TXCS_RDY) == 0) 149 if(--timo == 0) 150 break; 151 if(c == 0) 152 return; 153 s = mfpr(TXCS); 154 mtpr(TXCS,0); 155 mtpr(TXDB, c&0xff); 156 if(c == '\n') 157 putchar('\r'); 158 putchar(0); 159 mtpr(TXCS, s); 160 } 161 162 getchar() 163 { 164 register c; 165 166 while((mfpr(RXCS)&RXCS_DONE) == 0) 167 ; 168 c = mfpr(RXDB)&0177; 169 if (c=='\r') 170 c = '\n'; 171 if (c != '\b' && c != '\177') 172 putchar(c); 173 return(c); 174 } 175 176 gets(buf) 177 char *buf; 178 { 179 register char *lp; 180 register c; 181 182 lp = buf; 183 for (;;) { 184 c = getchar() & 0177; 185 switch(c) { 186 case '\n': 187 case '\r': 188 c = '\n'; 189 *lp++ = '\0'; 190 return; 191 case '\b': 192 if (lp > buf) { 193 lp--; 194 putchar('\b'); 195 putchar(' '); 196 putchar('\b'); 197 } 198 continue; 199 case '#': 200 case '\177': 201 lp--; 202 if (lp < buf) 203 lp = buf; 204 continue; 205 case '@': 206 case 'u'&037: 207 lp = buf; 208 putchar('\n'); 209 continue; 210 default: 211 *lp++ = c; 212 } 213 } 214 } 215