UbixOS  2.0
kprintf.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2002-2018 The UbixOS Project.
3  * All rights reserved.
4  *
5  * This was developed by Christopher W. Olsen for the UbixOS Project.
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are permitted
8  * provided that the following conditions are met:
9  *
10  * 1) Redistributions of source code must retain the above copyright notice, this list of
11  * conditions, the following disclaimer and the list of authors.
12  * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13  * conditions, the following disclaimer and the list of authors in the documentation and/or
14  * other materials provided with the distribution.
15  * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16  * endorse or promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <lib/kprintf.h>
30 #include <string.h>
31 #include <sys/video.h>
32 #include <ubixos/kpanic.h>
33 
34 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper);
35 
36 static __inline int imax(int a, int b) {
37  return (a > b ? a : b);
38 }
39 
40 union uu {
41  quad_t q; /* as a (signed) quad */
42  quad_t uq; /* as an unsigned quad */
43  long sl[2]; /* as two signed longs */
44  u_long ul[2]; /* as two unsigned longs */
45 };
46 
47 static void __shl(register digit *p, register int len, register int sh) {
48  register int i;
49 
50  for (i = 0; i < len; i++)
51  p[i] = LHALF( p[i] << sh ) | (p[i + 1] >> (HALF_BITS - sh));
52 
53  p[i] = LHALF(p[i] << sh);
54 }
55 
57  union uu tmp;
58  digit *u, *v, *q;
59  register digit v1, v2;
60  u_long qhat, rhat, t;
61  int m, n, d, j, i;
62  digit uspace[5], vspace[5], qspace[5];
63 
64  /*
65  * Take care of special cases: divide by zero, and u < v.
66  */
67  if (vq == 0) {
68  /* divide by zero. */
69  static const volatile unsigned int zero = 0;
70 
71  tmp.ul[H] = tmp.ul[L] = 1 / zero;
72  if (arq)
73  *arq = uq;
74  return (tmp.q);
75  }
76  if (uq < vq) {
77  if (arq)
78  *arq = uq;
79  return (0);
80  }
81  u = &uspace[0];
82  v = &vspace[0];
83  q = &qspace[0];
84 
85  /*
86  * Break dividend and divisor into digits in base B, then
87  * count leading zeros to determine m and n. When done, we
88  * will have:
89  * u = (u[1]u[2]...u[m+n]) sub B
90  * v = (v[1]v[2]...v[n]) sub B
91  * v[1] != 0
92  * 1 < n <= 4 (if n = 1, we use a different division algorithm)
93  * m >= 0 (otherwise u < v, which we already checked)
94  * m + n = 4
95  * and thus
96  * m = 4 - n <= 2
97  */
98  tmp.uq = uq;
99  u[0] = 0;
100  u[1] = HHALF(tmp.ul[H]);
101  u[2] = LHALF(tmp.ul[H]);
102  u[3] = HHALF(tmp.ul[L]);
103  u[4] = LHALF(tmp.ul[L]);
104  tmp.uq = vq;
105  v[1] = HHALF(tmp.ul[H]);
106  v[2] = LHALF(tmp.ul[H]);
107  v[3] = HHALF(tmp.ul[L]);
108  v[4] = LHALF(tmp.ul[L]);
109  for (n = 4; v[1] == 0; v++) {
110  if (--n == 1) {
111  u_long rbj; /* r*B+u[j] (not root boy jim) */
112  digit q1, q2, q3, q4;
113 
114  /*
115  * Change of plan, per exercise 16.
116  * r = 0;
117  * for j = 1..4:
118  * q[j] = floor((r*B + u[j]) / v),
119  * r = (r*B + u[j]) % v;
120  * We unroll this completely here.
121  */
122  t = v[2]; /* nonzero, by definition */
123  q1 = u[1] / t;
124  rbj = COMBINE(u[1] % t, u[2]);
125  q2 = rbj / t;
126  rbj = COMBINE(rbj % t, u[3]);
127  q3 = rbj / t;
128  rbj = COMBINE(rbj % t, u[4]);
129  q4 = rbj / t;
130  if (arq)
131  *arq = rbj % t;
132  tmp.ul[H] = COMBINE(q1, q2);
133  tmp.ul[L] = COMBINE(q3, q4);
134  return (tmp.q);
135  }
136  }
137  /*
138  * By adjusting q once we determine m, we can guarantee that
139  * there is a complete four-digit quotient at &qspace[1] when
140  * we finally stop.
141  */
142  for (m = 4 - n; u[1] == 0; u++)
143  m--;
144  for (i = 4 - m; --i >= 0;)
145  q[i] = 0;
146  q += 4 - m;
147 
148  /*
149  * Here we run Program D, translated from MIX to C and acquiring
150  * a few minor changes.
151  *
152  * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
153  */
154  d = 0;
155  for (t = v[1]; t < B / 2; t <<= 1)
156  d++;
157  if (d > 0) {
158  __shl(&u[0], m + n, d); /* u <<= d */
159  __shl(&v[1], n - 1, d); /* v <<= d */
160  }
161  /*
162  * D2: j = 0.
163  */
164  j = 0;
165  v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
166  v2 = v[2]; /* for D3 */
167  do {
168  register digit uj0, uj1, uj2;
169 
170  /*
171  * D3: Calculate qhat (\^q, in TeX notation).
172  * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
173  * let rhat = (u[j]*B + u[j+1]) mod v[1].
174  * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
175  * decrement qhat and increase rhat correspondingly.
176  * Note that if rhat >= B, v[2]*qhat < rhat*B.
177  */
178  uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
179  uj1 = u[j + 1]; /* for D3 only */
180  uj2 = u[j + 2]; /* for D3 only */
181  if (uj0 == v1) {
182  qhat = B;
183  rhat = uj1;
184  goto qhat_too_big;
185  }
186  else {
187  u_long nn = COMBINE(uj0, uj1);
188  qhat = nn / v1;
189  rhat = nn % v1;
190  }
191  while (v2 * qhat > COMBINE(rhat, uj2)) {
192  qhat_too_big: qhat--;
193  if ((rhat += v1) >= B)
194  break;
195  }
196  /*
197  * D4: Multiply and subtract.
198  * The variable `t' holds any borrows across the loop.
199  * We split this up so that we do not require v[0] = 0,
200  * and to eliminate a final special case.
201  */
202  for (t = 0, i = n; i > 0; i--) {
203  t = u[i + j] - v[i] * qhat - t;
204  u[i + j] = LHALF(t);
205  t = (B - HHALF(t)) & (B - 1);
206  }
207  t = u[j] - t;
208  u[j] = LHALF(t);
209  /*
210  * D5: test remainder.
211  * There is a borrow if and only if HHALF(t) is nonzero;
212  * in that (rare) case, qhat was too large (by exactly 1).
213  * Fix it by adding v[1..n] to u[j..j+n].
214  */
215  if (HHALF(t)) {
216  qhat--;
217  for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
218  t += u[i + j] + v[i];
219  u[i + j] = LHALF(t);
220  t = HHALF(t);
221  }
222  u[j] = LHALF(u[j] + t);
223  }
224  q[j] = qhat;
225  } while (++j <= m); /* D7: loop on j. */
226 
227  /*
228  * If caller wants the remainder, we have to calculate it as
229  * u[m..m+n] >> d (this is at most n digits and thus fits in
230  * u[m+1..m+n], but we may need more source digits).
231  */
232  if (arq) {
233  if (d) {
234  for (i = m + n; i > m; --i)
235  u[i] = (u[i] >> d) | LHALF(u[i - 1] << (HALF_BITS - d));
236  u[i] = 0;
237  }
238  tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
239  tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
240  *arq = tmp.q;
241  }
242 
243  tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
244  tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
245  return (tmp.q);
246 }
247 
249  u_quad_t a, b; {
250  u_quad_t r;
251 
252  (void) __qdivrem(a, b, &r);
253  return (r);
254 }
255 
256 int printOff = 0x0;
257 int ogprintOff = 0x1;
258 
259 int kprintf(const char *fmt, ...) {
260  va_list ap;
261  int retval;
262  char buf[512];
263 
264  va_start(ap, fmt);
265 
266  retval = kvprintf(fmt, NULL, &buf, 10, ap);
267  buf[retval] = '\0';
268  va_end(ap);
269 
270  if (printOff == 0x0)
271  kprint(buf);
272  if (ogprintOff == 0x0)
273  ogPrintf(buf);
274 
275  return (retval);
276 }
277 
278 int sprintf(char *buf, const char *fmt, ...) {
279  va_list args;
280  int i;
281  va_start(args, fmt);
282  /* i = vsprintf( buf, fmt, args ); */
283  i = kvprintf(fmt, NULL, buf, 10, args);
284  va_end(args);
285  return (i);
286 }
287 
288 /*
289  * Scaled down version of printf(3).
290  *
291  * Two additional formats:
292  *
293  * The format %b is supported to decode error registers.
294  * Its usage is:
295  *
296  * printf("reg=%b\n", regval, "<base><arg>*");
297  *
298  * where <base> is the output base expressed as a control character, e.g.
299  * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
300  * the first of which gives the bit number to be inspected (origin 1), and
301  * the next characters (up to a control character, i.e. a character <= 32),
302  * give the name of the register. Thus:
303  *
304  * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
305  *
306  * would produce output:
307  *
308  * reg=3<BITTWO,BITONE>
309  *
310  * XXX: %D -- Hexdump, takes pointer and separator string:
311  * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
312  * ("%*D", len, ptr, " " -> XX XX XX XX ...
313  */
314 
315 int kvprintf(const char *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) {
316 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
317  char nbuf[MAXNBUF];
318  char *d;
319  const char *p, *percent, *q;
320  u_char *up;
321  int ch, n;
322  uintmax_t num;
323  int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
324  int cflag, hflag, jflag, tflag, zflag;
325  int dwidth, upper;
326  char padc;
327  int stop = 0, retval = 0;
328 
329  num = 0;
330  if (!func)
331  d = (char *) arg;
332  else
333  d = NULL;
334 
335  if (fmt == NULL)
336  fmt = "(fmt null)\n";
337 
338  if (radix < 2 || radix > 36)
339  radix = 10;
340 
341  for (;;) {
342  padc = ' ';
343  width = 0;
344  while ((ch = (u_char) *fmt++) != '%' || stop) {
345  if (ch == '\0')
346  return (retval);
347  PCHAR(ch);
348  }
349  percent = fmt - 1;
350  qflag = 0;
351  lflag = 0;
352  ladjust = 0;
353  sharpflag = 0;
354  neg = 0;
355  sign = 0;
356  dot = 0;
357  dwidth = 0;
358  upper = 0;
359  cflag = 0;
360  hflag = 0;
361  jflag = 0;
362  tflag = 0;
363  zflag = 0;
364  reswitch: switch (ch = (u_char) *fmt++) {
365  case '.':
366  dot = 1;
367  goto reswitch;
368  case '#':
369  sharpflag = 1;
370  goto reswitch;
371  case '+':
372  sign = 1;
373  goto reswitch;
374  case '-':
375  ladjust = 1;
376  goto reswitch;
377  case '%':
378  PCHAR(ch)
379  ;
380  break;
381  case '*':
382  if (!dot) {
383  width = va_arg(ap, int);
384  if (width < 0) {
385  ladjust = !ladjust;
386  width = -width;
387  }
388  }
389  else {
390  dwidth = va_arg(ap, int);
391  }
392  goto reswitch;
393  case '0':
394  if (!dot) {
395  padc = '0';
396  goto reswitch;
397  }
398  case '1':
399  case '2':
400  case '3':
401  case '4':
402  case '5':
403  case '6':
404  case '7':
405  case '8':
406  case '9':
407  for (n = 0;; ++fmt) {
408  n = n * 10 + ch - '0';
409  ch = *fmt;
410  if (ch < '0' || ch > '9')
411  break;
412  }
413  if (dot)
414  dwidth = n;
415  else
416  width = n;
417  goto reswitch;
418  case 'b':
419  num = (u_int) va_arg(ap, int);
420  p = va_arg(ap, char *);
421  for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
422  PCHAR(*q--)
423  ;
424 
425  if (num == 0)
426  break;
427 
428  for (tmp = 0; *p;) {
429  n = *p++;
430  if (num & (1 << (n - 1))) {
431  PCHAR(tmp ? ',' : '<');
432  for (; (n = *p) > ' '; ++p)
433  PCHAR(n);
434  tmp = 1;
435  }
436  else
437  for (; *p > ' '; ++p)
438  continue;
439  }
440  if (tmp)
441  PCHAR('>')
442  ;
443  break;
444  case 'c':
445  PCHAR(va_arg(ap, int))
446  ;
447  break;
448  case 'D':
449  up = va_arg(ap, u_char *);
450  p = va_arg(ap, char *);
451  if (!width)
452  width = 16;
453  while (width--) {
454  PCHAR(hex2ascii( *up >> 4 ));
455  PCHAR(hex2ascii( *up & 0x0f ));
456  up++;
457  if (width)
458  for (q = p; *q; q++)
459  PCHAR(*q);
460  }
461  break;
462  case 'd':
463  case 'i':
464  base = 10;
465  sign = 1;
466  goto handle_sign;
467  case 'h':
468  if (hflag) {
469  hflag = 0;
470  cflag = 1;
471  }
472  else
473  hflag = 1;
474  goto reswitch;
475  case 'j':
476  jflag = 1;
477  goto reswitch;
478  case 'l':
479  if (lflag) {
480  lflag = 0;
481  qflag = 1;
482  }
483  else
484  lflag = 1;
485  goto reswitch;
486  case 'n':
487  if (jflag)
488  *(va_arg(ap, intmax_t *)) = retval;
489  else if (qflag)
490  *(va_arg(ap, quad_t *)) = retval;
491  else if (lflag)
492  *(va_arg(ap, long *)) = retval;
493  else if (zflag)
494  *(va_arg(ap, size_t *)) = retval;
495  else if (hflag)
496  *(va_arg(ap, short *)) = retval;
497  else if (cflag)
498  *(va_arg(ap, char *)) = retval;
499  else
500  *(va_arg(ap, int *)) = retval;
501  break;
502  case 'o':
503  base = 8;
504  goto handle_nosign;
505  case 'p':
506  base = 16;
507  sharpflag = (width == 0);
508  sign = 0;
509  num = (uintptr_t) va_arg(ap, void *);
510  goto number;
511  case 'q':
512  qflag = 1;
513  goto reswitch;
514  case 'r':
515  base = radix;
516  if (sign)
517  goto handle_sign;
518  goto handle_nosign;
519  case 's':
520  p = va_arg(ap, char *);
521  if (p == NULL)
522  p = "(null)";
523  if (!dot)
524  n = strlen(p);
525  else
526  for (n = 0; n < dwidth && p[n]; n++)
527  continue;
528 
529  width -= n;
530 
531  if (!ladjust && width > 0)
532  while (width--)
533  PCHAR(padc)
534  ;
535  while (n--)
536  PCHAR(*p++)
537  ;
538  if (ladjust && width > 0)
539  while (width--)
540  PCHAR(padc)
541  ;
542  break;
543  case 't':
544  tflag = 1;
545  goto reswitch;
546  case 'u':
547  base = 10;
548  goto handle_nosign;
549  case 'X':
550  upper = 1;
551  case 'x':
552  base = 16;
553  goto handle_nosign;
554  case 'y':
555  base = 16;
556  sign = 1;
557  goto handle_sign;
558  case 'z':
559  zflag = 1;
560  goto reswitch;
561  handle_nosign: sign = 0;
562  if (jflag)
563  num = va_arg(ap, uintmax_t);
564  else if (qflag)
565  num = va_arg(ap, u_quad_t);
566  else if (tflag)
567  num = va_arg(ap, ptrdiff_t);
568  else if (lflag)
569  num = va_arg(ap, u_long);
570  else if (zflag)
571  num = va_arg(ap, size_t);
572  else if (hflag)
573  num = (u_short) va_arg(ap, int);
574  else if (cflag)
575  num = (u_char) va_arg(ap, int);
576  else
577  num = va_arg(ap, u_int);
578  goto number;
579  handle_sign: if (jflag)
580  num = va_arg(ap, intmax_t);
581  else if (qflag)
582  num = va_arg(ap, quad_t);
583  else if (tflag)
584  num = va_arg(ap, ptrdiff_t);
585  else if (lflag)
586  num = va_arg(ap, long);
587  else if (zflag)
588  num = va_arg(ap, ssize_t);
589  else if (hflag)
590  num = (short) va_arg(ap, int);
591  else if (cflag)
592  num = (char) va_arg(ap, int);
593  else
594  num = va_arg(ap, int);
595  number: if (sign && (intmax_t) num < 0) {
596  neg = 1;
597  num = -(intmax_t) num;
598  }
599  p = ksprintn(nbuf, num, base, &n, upper);
600  tmp = 0;
601  if (sharpflag && num != 0) {
602  if (base == 8)
603  tmp++;
604  else if (base == 16)
605  tmp += 2;
606  }
607  if (neg)
608  tmp++;
609 
610  if (!ladjust && padc == '0')
611  dwidth = width - tmp;
612  width -= tmp + imax(dwidth, n);
613  dwidth -= n;
614  if (!ladjust)
615  while (width-- > 0)
616  PCHAR(' ')
617  ;
618  if (neg)
619  PCHAR('-')
620  ;
621  if (sharpflag && num != 0) {
622  if (base == 8) {
623  PCHAR('0');
624  }
625  else if (base == 16) {
626  PCHAR('0');
627  PCHAR('x');
628  }
629  }
630  while (dwidth-- > 0)
631  PCHAR('0')
632  ;
633 
634  while (*p)
635  PCHAR(*p--)
636  ;
637 
638  if (ladjust)
639  while (width-- > 0)
640  PCHAR(' ')
641  ;
642 
643  break;
644  default:
645  while (percent < fmt)
646  PCHAR(*percent++)
647  ;
648  /*
649  * Since we ignore a formatting argument it is no
650  * longer safe to obey the remaining formatting
651  * arguments as the arguments will no longer match
652  * the format specs.
653  */
654  stop = 1;
655  break;
656  }
657  }
658 #undef PCHAR
659  return (0);
660 }
661 
662 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) {
663  char *p, c;
664 
665  p = nbuf;
666  *p = '\0';
667 
668  do {
669  c = hex2ascii(num % base);
670  *++p = upper ? toupper(c) : c;
671  } while (num /= base);
672 
673  if (lenp)
674  *lenp = p - nbuf;
675 
676  return (p);
677 }
678 
679 /***
680  END
681  ***/
682 
u_long
unsigned long u_long
Definition: types.h:73
uu::uq
quad_t uq
Definition: kprintf.c:42
uu::sl
long sl[2]
Definition: kprintf.c:43
MAXNBUF
#define MAXNBUF
Definition: kprintf.h:35
uu::ul
u_long ul[2]
Definition: kprintf.c:44
LHALF
#define LHALF(x)
Definition: types.h:164
__inline
#define __inline
Definition: cdefs.h:179
uu
Definition: kprintf.c:40
string.h
u_quad_t
__uint64_t u_quad_t
Definition: types.h:55
video.h
va_end
#define va_end(ap)
Definition: stdarg.h:50
sprintf
int sprintf(char *buf, const char *fmt,...)
Definition: kprintf.c:278
strlen
int strlen(const char *str)
Definition: strlen.c:55
B
#define B
Definition: types.h:169
va_list
char * va_list
Definition: stdarg.h:32
intmax_t
int32_t intmax_t
Definition: types.h:134
quad_t
__int64_t quad_t
Definition: types.h:57
u_short
unsigned short u_short
Definition: types.h:71
PCHAR
#define PCHAR(c)
kpanic.h
COMBINE
#define COMBINE(a, b)
Definition: types.h:172
va_start
#define va_start(ap, last)
Definition: stdarg.h:41
__qdivrem
u_quad_t __qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
Definition: kprintf.c:56
kprintf.h
kprintf
int kprintf(const char *fmt,...)
Definition: kprintf.c:259
buf
Definition: buf.h:35
HALF_BITS
#define HALF_BITS
Definition: types.h:162
__umoddi3
u_quad_t __umoddi3(u_quad_t a, u_quad_t b)
Definition: kprintf.c:248
H
#define H
Definition: types.h:154
digit
unsigned short digit
Definition: types.h:146
ptrdiff_t
int32_t ptrdiff_t
Definition: types.h:135
ogPrintf
int ogPrintf(char *)
Definition: ogprintf.cc:40
kvprintf
int kvprintf(const char *fmt, void(*func)(int, void *), void *arg, int radix, va_list ap)
Definition: kprintf.c:315
uintmax_t
uint32_t uintmax_t
Definition: types.h:133
hex2ascii
#define hex2ascii(hex)
Definition: string.h:53
printOff
int printOff
Definition: kprintf.c:256
toupper
#define toupper(c)
Definition: string.h:55
L
#define L
Definition: types.h:155
va_arg
#define va_arg(ap, type)
Definition: stdarg.h:44
uintptr_t
uint32_t uintptr_t
Definition: types.h:136
HHALF
#define HHALF(x)
Definition: types.h:163
ssize_t
__ssize_t ssize_t
Definition: types.h:117
u_int
unsigned int u_int
Definition: types.h:72
u_char
unsigned char u_char
Definition: types.h:70
uu::q
quad_t q
Definition: kprintf.c:41
kprint
void kprint(char *string)
Definition: video.c:58
ogprintOff
int ogprintOff
Definition: kprintf.c:257
NULL
#define NULL
Definition: fat_string.h:17