0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include "boot.h"
0017
0018 static int skip_atoi(const char **s)
0019 {
0020 int i = 0;
0021
0022 while (isdigit(**s))
0023 i = i * 10 + *((*s)++) - '0';
0024 return i;
0025 }
0026
0027 #define ZEROPAD 1
0028 #define SIGN 2
0029 #define PLUS 4
0030 #define SPACE 8
0031 #define LEFT 16
0032 #define SMALL 32
0033 #define SPECIAL 64
0034
0035 #define __do_div(n, base) ({ \
0036 int __res; \
0037 __res = ((unsigned long) n) % (unsigned) base; \
0038 n = ((unsigned long) n) / (unsigned) base; \
0039 __res; })
0040
0041 static char *number(char *str, long num, int base, int size, int precision,
0042 int type)
0043 {
0044
0045 static const char digits[16] = "0123456789ABCDEF";
0046
0047 char tmp[66];
0048 char c, sign, locase;
0049 int i;
0050
0051
0052
0053 locase = (type & SMALL);
0054 if (type & LEFT)
0055 type &= ~ZEROPAD;
0056 if (base < 2 || base > 16)
0057 return NULL;
0058 c = (type & ZEROPAD) ? '0' : ' ';
0059 sign = 0;
0060 if (type & SIGN) {
0061 if (num < 0) {
0062 sign = '-';
0063 num = -num;
0064 size--;
0065 } else if (type & PLUS) {
0066 sign = '+';
0067 size--;
0068 } else if (type & SPACE) {
0069 sign = ' ';
0070 size--;
0071 }
0072 }
0073 if (type & SPECIAL) {
0074 if (base == 16)
0075 size -= 2;
0076 else if (base == 8)
0077 size--;
0078 }
0079 i = 0;
0080 if (num == 0)
0081 tmp[i++] = '0';
0082 else
0083 while (num != 0)
0084 tmp[i++] = (digits[__do_div(num, base)] | locase);
0085 if (i > precision)
0086 precision = i;
0087 size -= precision;
0088 if (!(type & (ZEROPAD + LEFT)))
0089 while (size-- > 0)
0090 *str++ = ' ';
0091 if (sign)
0092 *str++ = sign;
0093 if (type & SPECIAL) {
0094 if (base == 8)
0095 *str++ = '0';
0096 else if (base == 16) {
0097 *str++ = '0';
0098 *str++ = ('X' | locase);
0099 }
0100 }
0101 if (!(type & LEFT))
0102 while (size-- > 0)
0103 *str++ = c;
0104 while (i < precision--)
0105 *str++ = '0';
0106 while (i-- > 0)
0107 *str++ = tmp[i];
0108 while (size-- > 0)
0109 *str++ = ' ';
0110 return str;
0111 }
0112
0113 int vsprintf(char *buf, const char *fmt, va_list args)
0114 {
0115 int len;
0116 unsigned long num;
0117 int i, base;
0118 char *str;
0119 const char *s;
0120
0121 int flags;
0122
0123 int field_width;
0124 int precision;
0125
0126 int qualifier;
0127
0128 for (str = buf; *fmt; ++fmt) {
0129 if (*fmt != '%') {
0130 *str++ = *fmt;
0131 continue;
0132 }
0133
0134
0135 flags = 0;
0136 repeat:
0137 ++fmt;
0138 switch (*fmt) {
0139 case '-':
0140 flags |= LEFT;
0141 goto repeat;
0142 case '+':
0143 flags |= PLUS;
0144 goto repeat;
0145 case ' ':
0146 flags |= SPACE;
0147 goto repeat;
0148 case '#':
0149 flags |= SPECIAL;
0150 goto repeat;
0151 case '0':
0152 flags |= ZEROPAD;
0153 goto repeat;
0154 }
0155
0156
0157 field_width = -1;
0158 if (isdigit(*fmt))
0159 field_width = skip_atoi(&fmt);
0160 else if (*fmt == '*') {
0161 ++fmt;
0162
0163 field_width = va_arg(args, int);
0164 if (field_width < 0) {
0165 field_width = -field_width;
0166 flags |= LEFT;
0167 }
0168 }
0169
0170
0171 precision = -1;
0172 if (*fmt == '.') {
0173 ++fmt;
0174 if (isdigit(*fmt))
0175 precision = skip_atoi(&fmt);
0176 else if (*fmt == '*') {
0177 ++fmt;
0178
0179 precision = va_arg(args, int);
0180 }
0181 if (precision < 0)
0182 precision = 0;
0183 }
0184
0185
0186 qualifier = -1;
0187 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
0188 qualifier = *fmt;
0189 ++fmt;
0190 }
0191
0192
0193 base = 10;
0194
0195 switch (*fmt) {
0196 case 'c':
0197 if (!(flags & LEFT))
0198 while (--field_width > 0)
0199 *str++ = ' ';
0200 *str++ = (unsigned char)va_arg(args, int);
0201 while (--field_width > 0)
0202 *str++ = ' ';
0203 continue;
0204
0205 case 's':
0206 s = va_arg(args, char *);
0207 len = strnlen(s, precision);
0208
0209 if (!(flags & LEFT))
0210 while (len < field_width--)
0211 *str++ = ' ';
0212 for (i = 0; i < len; ++i)
0213 *str++ = *s++;
0214 while (len < field_width--)
0215 *str++ = ' ';
0216 continue;
0217
0218 case 'p':
0219 if (field_width == -1) {
0220 field_width = 2 * sizeof(void *);
0221 flags |= ZEROPAD;
0222 }
0223 str = number(str,
0224 (unsigned long)va_arg(args, void *), 16,
0225 field_width, precision, flags);
0226 continue;
0227
0228 case 'n':
0229 if (qualifier == 'l') {
0230 long *ip = va_arg(args, long *);
0231 *ip = (str - buf);
0232 } else {
0233 int *ip = va_arg(args, int *);
0234 *ip = (str - buf);
0235 }
0236 continue;
0237
0238 case '%':
0239 *str++ = '%';
0240 continue;
0241
0242
0243 case 'o':
0244 base = 8;
0245 break;
0246
0247 case 'x':
0248 flags |= SMALL;
0249 case 'X':
0250 base = 16;
0251 break;
0252
0253 case 'd':
0254 case 'i':
0255 flags |= SIGN;
0256 case 'u':
0257 break;
0258
0259 default:
0260 *str++ = '%';
0261 if (*fmt)
0262 *str++ = *fmt;
0263 else
0264 --fmt;
0265 continue;
0266 }
0267 if (qualifier == 'l')
0268 num = va_arg(args, unsigned long);
0269 else if (qualifier == 'h') {
0270 num = (unsigned short)va_arg(args, int);
0271 if (flags & SIGN)
0272 num = (short)num;
0273 } else if (flags & SIGN)
0274 num = va_arg(args, int);
0275 else
0276 num = va_arg(args, unsigned int);
0277 str = number(str, num, base, field_width, precision, flags);
0278 }
0279 *str = '\0';
0280 return str - buf;
0281 }
0282
0283 int sprintf(char *buf, const char *fmt, ...)
0284 {
0285 va_list args;
0286 int i;
0287
0288 va_start(args, fmt);
0289 i = vsprintf(buf, fmt, args);
0290 va_end(args);
0291 return i;
0292 }
0293
0294 int printf(const char *fmt, ...)
0295 {
0296 char printf_buf[1024];
0297 va_list args;
0298 int printed;
0299
0300 va_start(args, fmt);
0301 printed = vsprintf(printf_buf, fmt, args);
0302 va_end(args);
0303
0304 puts(printf_buf);
0305
0306 return printed;
0307 }