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