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