doprnt.c (2102B)
1 #include <errno.h> 2 #include <stdarg.h> 3 #include <stddef.h> 4 #include <string.h> 5 6 #include <libk.h> 7 8 #include "stream.h" 9 10 static void 11 printc(Stream *sp, int c) 12 { 13 if (sp->base) { 14 if (sp->cnt < sp->len) 15 sp->base[sp->cnt++] = c; 16 } else { 17 putch(c); 18 sp->cnt++; 19 } 20 } 21 22 static void 23 printn(Stream *sp, long long n, int base, int sign, int fill) 24 { 25 int first, d; 26 unsigned long long div; 27 const static char digits[] = "0123456789ABCDEF"; 28 29 switch (base) { 30 case 8: 31 div = 01000000000000000000000u; 32 break; 33 case 10: 34 div = 10000000000000000000u; 35 break; 36 case 16: 37 default: 38 div = 0x1000000000000000u; 39 break; 40 } 41 42 if (sign && n < 0) { 43 n = -n; 44 printc(sp, '-'); 45 } 46 47 for (first = 1; div > 0; div /= base) { 48 d = n / div; 49 if (d == 0 && first && div != 1 && !fill) 50 continue; 51 n -= d * div; 52 printc(sp, digits[d]); 53 first = 0; 54 } 55 } 56 57 static long long 58 getnum(va_list *va, int size) 59 { 60 switch (size) { 61 case 0: 62 return va_arg(*va, int); 63 case 1: 64 return va_arg(*va, long); 65 case 2: 66 return va_arg(*va, long long); 67 case 3: 68 return (long long) va_arg(*va, void *); 69 case 4: 70 default: 71 return va_arg(*va, size_t); 72 } 73 } 74 75 void 76 doprnt(Stream *sp, const char *fmt, va_list va) 77 { 78 char c; 79 va_list va2; 80 int fill, base, sign, size; 81 char *s; 82 83 va_copy(va2, va); 84 while (( c = *fmt++) != '\0') { 85 if (c != '%') { 86 printc(sp, c); 87 continue; 88 } 89 90 fill = size = sign = 0; 91 flags: 92 switch (c = *fmt++) { 93 case '0': 94 fill = 1; 95 goto flags; 96 case 'l': 97 size++; 98 goto flags; 99 case 'z': 100 size = 4; 101 goto flags; 102 case 'o': 103 base = 8; 104 goto print_number; 105 case 'd': 106 sign = 1; 107 case 'u': 108 base = 10; 109 goto print_number; 110 case 'p': 111 size = 3; 112 fill = 1; 113 case 'X': 114 case 'x': 115 base = 16; 116 print_number: 117 printn(sp, getnum(&va2, size), base, sign, fill); 118 break; 119 case 'e': 120 s = strerror(errno); 121 goto printout; 122 case 's': 123 s = va_arg(va2, char *); 124 printout: 125 while (*s) 126 printc(sp, *s++); 127 break; 128 case 'c': 129 c = va_arg(va2, int); 130 case '%': 131 printc(sp, c); 132 break; 133 case '\0': 134 goto out_loop; 135 } 136 } 137 138 out_loop: 139 va_end(va2); 140 }