1 #include "libcflat.h" 2 3 #define BUFSZ 2000 4 5 typedef struct pstream { 6 char *buffer; 7 int remain; 8 int added; 9 } pstream_t; 10 11 typedef struct strprops { 12 char pad; 13 int npad; 14 } strprops_t; 15 16 static void addchar(pstream_t *p, char c) 17 { 18 if (p->remain) { 19 *p->buffer++ = c; 20 --p->remain; 21 } 22 ++p->added; 23 } 24 25 void print_str(pstream_t *p, const char *s, strprops_t props) 26 { 27 const char *s_orig = s; 28 int npad = props.npad; 29 30 if (npad > 0) { 31 npad -= strlen(s_orig); 32 while (npad > 0) { 33 addchar(p, props.pad); 34 --npad; 35 } 36 } 37 38 while (*s) 39 addchar(p, *s++); 40 41 if (npad < 0) { 42 props.pad = ' '; /* ignore '0' flag with '-' flag */ 43 npad += strlen(s_orig); 44 while (npad < 0) { 45 addchar(p, props.pad); 46 ++npad; 47 } 48 } 49 } 50 51 static char digits[16] = "0123456789abcdef"; 52 53 void print_int(pstream_t *ps, long long n, int base, strprops_t props) 54 { 55 char buf[sizeof(long) * 3 + 2], *p = buf; 56 int s = 0, i; 57 58 if (n < 0) { 59 n = -n; 60 s = 1; 61 } 62 63 while (n) { 64 *p++ = digits[n % base]; 65 n /= base; 66 } 67 68 if (s) 69 *p++ = '-'; 70 71 if (p == buf) 72 *p++ = '0'; 73 74 for (i = 0; i < (p - buf) / 2; ++i) { 75 char tmp; 76 77 tmp = buf[i]; 78 buf[i] = p[-1-i]; 79 p[-1-i] = tmp; 80 } 81 82 *p = 0; 83 84 print_str(ps, buf, props); 85 } 86 87 void print_unsigned(pstream_t *ps, unsigned long long n, int base, 88 strprops_t props) 89 { 90 char buf[sizeof(long) * 3 + 1], *p = buf; 91 int i; 92 93 while (n) { 94 *p++ = digits[n % base]; 95 n /= base; 96 } 97 98 if (p == buf) 99 *p++ = '0'; 100 101 for (i = 0; i < (p - buf) / 2; ++i) { 102 char tmp; 103 104 tmp = buf[i]; 105 buf[i] = p[-1-i]; 106 p[-1-i] = tmp; 107 } 108 109 *p = 0; 110 111 print_str(ps, buf, props); 112 } 113 114 static int fmtnum(const char **fmt) 115 { 116 const char *f = *fmt; 117 int len = 0, num; 118 119 if (*f == '-') 120 ++f, ++len; 121 122 while (*f >= '0' && *f <= '9') 123 ++f, ++len; 124 125 num = atol(*fmt); 126 *fmt += len; 127 return num; 128 } 129 130 int vsnprintf(char *buf, int size, const char *fmt, va_list va) 131 { 132 pstream_t s; 133 134 s.buffer = buf; 135 s.remain = size - 1; 136 s.added = 0; 137 while (*fmt) { 138 char f = *fmt++; 139 int nlong = 0; 140 strprops_t props; 141 memset(&props, 0, sizeof(props)); 142 props.pad = ' '; 143 144 if (f != '%') { 145 addchar(&s, f); 146 continue; 147 } 148 morefmt: 149 f = *fmt++; 150 switch (f) { 151 case '%': 152 addchar(&s, '%'); 153 break; 154 case 'c': 155 addchar(&s, va_arg(va, int)); 156 break; 157 case '\0': 158 --fmt; 159 break; 160 case '0': 161 props.pad = '0'; 162 ++fmt; 163 /* fall through */ 164 case '1'...'9': 165 case '-': 166 --fmt; 167 props.npad = fmtnum(&fmt); 168 goto morefmt; 169 case 'l': 170 ++nlong; 171 goto morefmt; 172 case 'd': 173 switch (nlong) { 174 case 0: 175 print_int(&s, va_arg(va, int), 10, props); 176 break; 177 case 1: 178 print_int(&s, va_arg(va, long), 10, props); 179 break; 180 default: 181 print_int(&s, va_arg(va, long long), 10, props); 182 break; 183 } 184 break; 185 case 'u': 186 switch (nlong) { 187 case 0: 188 print_unsigned(&s, va_arg(va, unsigned), 10, props); 189 break; 190 case 1: 191 print_unsigned(&s, va_arg(va, unsigned long), 10, props); 192 break; 193 default: 194 print_unsigned(&s, va_arg(va, unsigned long long), 10, props); 195 break; 196 } 197 break; 198 case 'x': 199 switch (nlong) { 200 case 0: 201 print_unsigned(&s, va_arg(va, unsigned), 16, props); 202 break; 203 case 1: 204 print_unsigned(&s, va_arg(va, unsigned long), 16, props); 205 break; 206 default: 207 print_unsigned(&s, va_arg(va, unsigned long long), 16, props); 208 break; 209 } 210 break; 211 case 'p': 212 print_str(&s, "0x", props); 213 print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); 214 break; 215 case 's': 216 print_str(&s, va_arg(va, const char *), props); 217 break; 218 default: 219 addchar(&s, f); 220 break; 221 } 222 } 223 *s.buffer = 0; 224 ++s.added; 225 return s.added; 226 } 227 228 229 int snprintf(char *buf, int size, const char *fmt, ...) 230 { 231 va_list va; 232 int r; 233 234 va_start(va, fmt); 235 r = vsnprintf(buf, size, fmt, va); 236 va_end(va); 237 return r; 238 } 239 240 int vprintf(const char *fmt, va_list va) 241 { 242 char buf[BUFSZ]; 243 int r; 244 245 r = vsnprintf(buf, sizeof(buf), fmt, va); 246 puts(buf); 247 return r; 248 } 249 250 int printf(const char *fmt, ...) 251 { 252 va_list va; 253 char buf[BUFSZ]; 254 int r; 255 256 va_start(va, fmt); 257 r = vsnprintf(buf, sizeof buf, fmt, va); 258 va_end(va); 259 puts(buf); 260 return r; 261 } 262