00001
00002
00003
00004 #include "includes.h"
00005
00006 #define do_div(n,base) \
00007 ({ \
00008 int __res; \
00009 __res = ((unsigned long)n) % (unsigned int)base; \
00010 n = ((unsigned long)n) / (unsigned int)base; \
00011 __res; \
00012 })
00013
00014 #define is_digit(c) ((c) >= '0' && (c) <= '9')
00015 static int skip_atoi(const char **s)
00016 {
00017 int i=0;
00018
00019 while (is_digit(**s))
00020 i = i*10 + *((*s)++) - '0';
00021 return i;
00022 }
00023
00024 unsigned short int strnlen(const char * s, unsigned short int count)
00025 {
00026 const char *sc;
00027
00028 for (sc = s; count-- && *sc != '\0'; ++sc)
00029 ;
00030 return sc - s;
00031 }
00032
00033
00034 #define ZEROPAD 1
00035 #define SIGN 2
00036 #define PLUS 4
00037 #define SPACE 8
00038 #define LEFT 16
00039 #define SPECIAL 32
00040 #define LARGE 64
00041
00042 static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
00043 {
00044 char c,sign,tmp[66];
00045 const char *digits;
00046 const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00047 const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00048 int i;
00049
00050 digits = (type & LARGE) ? large_digits : small_digits;
00051 if (type & LEFT)
00052 type &= ~ZEROPAD;
00053 if (base < 2 || base > 36)
00054 return 0;
00055 c = (type & ZEROPAD) ? '0' : ' ';
00056 sign = 0;
00057 if (type & SIGN) {
00058 if (num < 0) {
00059 sign = '-';
00060 num = -num;
00061 size--;
00062 } else if (type & PLUS) {
00063 sign = '+';
00064 size--;
00065 } else if (type & SPACE) {
00066 sign = ' ';
00067 size--;
00068 }
00069 }
00070 if (type & SPECIAL) {
00071 if (base == 16)
00072 size -= 2;
00073 else if (base == 8)
00074 size--;
00075 }
00076 i = 0;
00077 if (num == 0)
00078 tmp[i++]='0';
00079 else while (num != 0)
00080 tmp[i++] = digits[do_div(num,base)];
00081 if (i > precision)
00082 precision = i;
00083 size -= precision;
00084 if (!(type&(ZEROPAD+LEFT))) {
00085 while(size-->0) {
00086 if (buf <= end)
00087 *buf = ' ';
00088 ++buf;
00089 }
00090 }
00091 if (sign) {
00092 if (buf <= end)
00093 *buf = sign;
00094 ++buf;
00095 }
00096 if (type & SPECIAL) {
00097 if (base==8) {
00098 if (buf <= end)
00099 *buf = '0';
00100 ++buf;
00101 } else if (base==16) {
00102 if (buf <= end)
00103 *buf = '0';
00104 ++buf;
00105 if (buf <= end)
00106 *buf = digits[33];
00107 ++buf;
00108 }
00109 }
00110 if (!(type & LEFT)) {
00111 while (size-- > 0) {
00112 if (buf <= end)
00113 *buf = c;
00114 ++buf;
00115 }
00116 }
00117 while (i < precision--) {
00118 if (buf <= end)
00119 *buf = '0';
00120 ++buf;
00121 }
00122 while (i-- > 0) {
00123 if (buf <= end)
00124 *buf = tmp[i];
00125 ++buf;
00126 }
00127 while (size-- > 0) {
00128 if (buf <= end)
00129 *buf = ' ';
00130 ++buf;
00131 }
00132 return buf;
00133 }
00134
00135 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
00136 {
00137 int len;
00138 unsigned long long num;
00139 int i, base;
00140 char *str, *end, c;
00141 const char *s;
00142
00143 int flags;
00144
00145 int field_width;
00146 int precision;
00147
00148 int qualifier;
00149
00150
00151
00152 str = buf;
00153 end = buf + size - 1;
00154
00155 if (end < buf - 1) {
00156 end = ((void *) -1);
00157 size = end - buf + 1;
00158 }
00159
00160 for (; *fmt ; ++fmt) {
00161 if (*fmt != '%') {
00162 if (str <= end)
00163 *str = *fmt;
00164 ++str;
00165 continue;
00166 }
00167
00168
00169 flags = 0;
00170 repeat:
00171 ++fmt;
00172 switch (*fmt) {
00173 case '-': flags |= LEFT; goto repeat;
00174 case '+': flags |= PLUS; goto repeat;
00175 case ' ': flags |= SPACE; goto repeat;
00176 case '#': flags |= SPECIAL; goto repeat;
00177 case '0': flags |= ZEROPAD; goto repeat;
00178 }
00179
00180
00181 field_width = -1;
00182 if (is_digit(*fmt))
00183 field_width = skip_atoi(&fmt);
00184 else if (*fmt == '*') {
00185 ++fmt;
00186
00187 field_width = va_arg(args, int);
00188 if (field_width < 0) {
00189 field_width = -field_width;
00190 flags |= LEFT;
00191 }
00192 }
00193
00194
00195 precision = -1;
00196 if (*fmt == '.') {
00197 ++fmt;
00198 if (is_digit(*fmt))
00199 precision = skip_atoi(&fmt);
00200 else if (*fmt == '*') {
00201 ++fmt;
00202
00203 precision = va_arg(args, int);
00204 }
00205 if (precision < 0)
00206 precision = 0;
00207 }
00208
00209
00210 qualifier = -1;
00211 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
00212 qualifier = *fmt;
00213 ++fmt;
00214 if (qualifier == 'l' && *fmt == 'l') {
00215 qualifier = 'L';
00216 ++fmt;
00217 }
00218 }
00219
00220
00221 base = 10;
00222
00223 switch (*fmt) {
00224 case 'c':
00225 if (!(flags & LEFT)) {
00226 while (--field_width > 0) {
00227 if (str <= end)
00228 *str = ' ';
00229 ++str;
00230 }
00231 }
00232 c = (unsigned char) va_arg(args, int);
00233 if (str <= end)
00234 *str = c;
00235 ++str;
00236 while (--field_width > 0) {
00237 if (str <= end)
00238 *str = ' ';
00239 ++str;
00240 }
00241 continue;
00242
00243 case 's':
00244 s = va_arg(args, char *);
00245 if (!s)
00246 s = "<NULL>";
00247
00248 len = strnlen(s, precision);
00249
00250 if (!(flags & LEFT)) {
00251 while (len < field_width--) {
00252 if (str <= end)
00253 *str = ' ';
00254 ++str;
00255 }
00256 }
00257 for (i = 0; i < len; ++i) {
00258 if (str <= end)
00259 *str = *s;
00260 ++str; ++s;
00261 }
00262 while (len < field_width--) {
00263 if (str <= end)
00264 *str = ' ';
00265 ++str;
00266 }
00267 continue;
00268
00269 case 'p':
00270 if (field_width == -1) {
00271 field_width = 2*sizeof(void *);
00272 flags |= ZEROPAD;
00273 }
00274 str = number(str, end,
00275 (unsigned long) va_arg(args, void *),
00276 16, field_width, precision, flags);
00277 continue;
00278
00279
00280 case 'n':
00281
00282
00283 if (qualifier == 'l') {
00284 long * ip = va_arg(args, long *);
00285 *ip = (str - buf);
00286 } else if (qualifier == 'Z') {
00287 size_t * ip = va_arg(args, size_t *);
00288 *ip = (str - buf);
00289 } else {
00290 int * ip = va_arg(args, int *);
00291 *ip = (str - buf);
00292 }
00293 continue;
00294
00295 case '%':
00296 if (str <= end)
00297 *str = '%';
00298 ++str;
00299 continue;
00300
00301
00302 case 'o':
00303 base = 8;
00304 break;
00305
00306 case 'X':
00307 flags |= LARGE;
00308 case 'x':
00309 base = 16;
00310 break;
00311
00312 case 'd':
00313 case 'i':
00314 flags |= SIGN;
00315 case 'u':
00316 break;
00317
00318 default:
00319 if (str <= end)
00320 *str = '%';
00321 ++str;
00322 if (*fmt) {
00323 if (str <= end)
00324 *str = *fmt;
00325 ++str;
00326 } else {
00327 --fmt;
00328 }
00329 continue;
00330 }
00331 if (qualifier == 'L')
00332 num = va_arg(args, long long);
00333 else if (qualifier == 'l') {
00334 num = va_arg(args, unsigned long);
00335 if (flags & SIGN)
00336 num = (signed long) num;
00337 } else if (qualifier == 'Z') {
00338 num = va_arg(args, size_t);
00339 } else if (qualifier == 'h') {
00340 num = (unsigned short) va_arg(args, int);
00341 if (flags & SIGN)
00342 num = (signed short) num;
00343 } else {
00344 num = va_arg(args, unsigned int);
00345 if (flags & SIGN)
00346 num = (signed int) num;
00347 }
00348 str = number(str, end, num, base,
00349 field_width, precision, flags);
00350 }
00351 if (str <= end)
00352 *str = '\0';
00353 else if (size > 0)
00354
00355 *end = '\0';
00356
00357
00358
00359 return str-buf;
00360 }
00361 int printk(const char *fmt, ...)
00362 {
00363 va_list args;
00364 int printed_len;
00365
00366 static char printk_buf[1024];
00367
00368
00369 va_start(args, fmt);
00370 printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
00371 va_end(args);
00372
00373
00374
00375
00376
00377
00378 F_Uart0StringTx(printk_buf);
00379
00380
00381
00382
00383
00384
00385
00386 return printed_len;
00387 }
00388
00389