1 /* prf.c 4.3 81/05/05 */ 2 3 #include "../h/param.h" 4 #include "../h/cons.h" 5 #include "../h/mtpr.h" 6 7 /* 8 * Scaled down version of C Library printf. 9 * Used to print diagnostic information directly on console tty. 10 * Since it is not interrupt driven, all system activities are 11 * suspended. Printf should not be used for chit-chat. 12 * 13 * One additional format: %b is supported to decode error registers. 14 * Usage is: 15 * printf("reg=%b\n", regval, "<base><arg>*"); 16 * Where <base> is the output base expressed as a control character, 17 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 18 * characters, the first of which gives the bit number to be inspected 19 * (origin 1), and the next characters (up to a control character, i.e. 20 * a character <= 32), give the name of the register. Thus 21 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 22 * would produce output: 23 * reg=2<BITTWO,BITONE> 24 */ 25 /*VARARGS1*/ 26 printf(fmt, x1) 27 char *fmt; 28 unsigned x1; 29 { 30 31 prf(fmt, &x1); 32 } 33 34 prf(fmt, adx) 35 register char *fmt; 36 register u_int *adx; 37 { 38 register int b, c, i; 39 char *s; 40 int any; 41 42 loop: 43 while ((c = *fmt++) != '%') { 44 if(c == '\0') 45 return; 46 putchar(c); 47 } 48 again: 49 c = *fmt++; 50 /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 51 switch (c) { 52 53 case 'l': 54 goto again; 55 case 'x': case 'X': 56 b = 16; 57 goto number; 58 case 'd': case 'D': 59 case 'u': /* what a joke */ 60 b = 10; 61 goto number; 62 case 'o': case 'O': 63 b = 8; 64 number: 65 printn((u_long)*adx, b); 66 break; 67 case 'c': 68 b = *adx; 69 for (i = 24; i >= 0; i -= 8) 70 if (c = (b >> i) & 0x7f) 71 putchar(c); 72 break; 73 case 'b': 74 b = *adx++; 75 s = (char *)*adx; 76 printn((u_long)b, *s++); 77 any = 0; 78 if (b) { 79 putchar('<'); 80 while (i = *s++) { 81 if (b & (1 << (i-1))) { 82 if (any) 83 putchar(','); 84 any = 1; 85 for (; (c = *s) > 32; s++) 86 putchar(c); 87 } else 88 for (; *s > 32; s++) 89 ; 90 } 91 putchar('>'); 92 } 93 break; 94 95 case 's': 96 s = (char *)*adx; 97 while (c = *s++) 98 putchar(c); 99 break; 100 } 101 adx++; 102 goto loop; 103 } 104 105 /* 106 * Printn prints a number n in base b. 107 * We don't use recursion to avoid deep kernel stacks. 108 */ 109 printn(n, b) 110 u_long n; 111 { 112 char prbuf[11]; 113 register char *cp; 114 115 if (b == 10 && (int)n < 0) { 116 putchar('-'); 117 n = (unsigned)(-(int)n); 118 } 119 cp = prbuf; 120 do { 121 *cp++ = "0123456789abcdef"[n%b]; 122 n /= b; 123 } while (n); 124 do 125 putchar(*--cp); 126 while (cp > prbuf); 127 } 128 129 /* 130 * Print a character on console. 131 * Attempts to save and restore device 132 * status. 133 * 134 * Whether or not printing is inhibited, 135 * the last MSGBUFS characters 136 * are saved in msgbuf for inspection later. 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 putchar(c); 172 return(c); 173 } 174 175 gets(buf) 176 char *buf; 177 { 178 register char *lp; 179 register c; 180 181 lp = buf; 182 for (;;) { 183 c = getchar() & 0177; 184 store: 185 switch(c) { 186 case '\n': 187 case '\r': 188 c = '\n'; 189 *lp++ = '\0'; 190 return; 191 case '\b': 192 case '#': 193 lp--; 194 if (lp < buf) 195 lp = buf; 196 continue; 197 case '@': 198 case 'u'&037: 199 lp = buf; 200 putchar('\n'); 201 continue; 202 default: 203 *lp++ = c; 204 } 205 } 206 } 207