PageRenderTime 80ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/lib_generic/vsprintf.c

https://github.com/CharlieWood/uboot-imx
C | 398 lines | 337 code | 40 blank | 21 comment | 107 complexity | 510ead15bf7df291c4f28790644a5f68 MD5 | raw file
  1. /*
  2. * linux/lib/vsprintf.c
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. */
  6. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  7. /*
  8. * Wirzenius wrote this portably, Torvalds fucked it up :-)
  9. */
  10. #include <stdarg.h>
  11. #include <linux/types.h>
  12. #include <linux/string.h>
  13. #include <linux/ctype.h>
  14. #include <common.h>
  15. #if !defined (CONFIG_PANIC_HANG)
  16. #include <command.h>
  17. /*cmd_boot.c*/
  18. extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
  19. #endif
  20. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  21. {
  22. unsigned long result = 0,value;
  23. if (*cp == '0') {
  24. cp++;
  25. if ((*cp == 'x') && isxdigit(cp[1])) {
  26. base = 16;
  27. cp++;
  28. }
  29. if (!base) {
  30. base = 8;
  31. }
  32. }
  33. if (!base) {
  34. base = 10;
  35. }
  36. while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  37. ? toupper(*cp) : *cp)-'A'+10) < base) {
  38. result = result*base + value;
  39. cp++;
  40. }
  41. if (endp)
  42. *endp = (char *)cp;
  43. return result;
  44. }
  45. long simple_strtol(const char *cp,char **endp,unsigned int base)
  46. {
  47. if(*cp=='-')
  48. return -simple_strtoul(cp+1,endp,base);
  49. return simple_strtoul(cp,endp,base);
  50. }
  51. #ifdef CFG_64BIT_STRTOUL
  52. unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
  53. {
  54. unsigned long long result = 0, value;
  55. if (*cp == '0') {
  56. cp++;
  57. if ((*cp == 'x') && isxdigit (cp[1])) {
  58. base = 16;
  59. cp++;
  60. }
  61. if (!base) {
  62. base = 8;
  63. }
  64. }
  65. if (!base) {
  66. base = 10;
  67. }
  68. while (isxdigit (*cp) && (value = isdigit (*cp)
  69. ? *cp - '0'
  70. : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) {
  71. result = result * base + value;
  72. cp++;
  73. }
  74. if (endp)
  75. *endp = (char *) cp;
  76. return result;
  77. }
  78. #endif /* CFG_64BIT_STRTOUL */
  79. /* we use this so that we can do without the ctype library */
  80. #define is_digit(c) ((c) >= '0' && (c) <= '9')
  81. static int skip_atoi(const char **s)
  82. {
  83. int i=0;
  84. while (is_digit(**s))
  85. i = i*10 + *((*s)++) - '0';
  86. return i;
  87. }
  88. #define ZEROPAD 1 /* pad with zero */
  89. #define SIGN 2 /* unsigned/signed long */
  90. #define PLUS 4 /* show plus */
  91. #define SPACE 8 /* space if plus */
  92. #define LEFT 16 /* left justified */
  93. #define SPECIAL 32 /* 0x */
  94. #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
  95. #ifdef CFG_64BIT_VSPRINTF
  96. #define do_div(n,base) ({ \
  97. unsigned int __res; \
  98. __res = ((unsigned long long) n) % base; \
  99. n = ((unsigned long long) n) / base; \
  100. __res; \
  101. })
  102. #else
  103. #define do_div(n,base) ({ \
  104. int __res; \
  105. __res = ((unsigned long) n) % base; \
  106. n = ((unsigned long) n) / base; \
  107. __res; \
  108. })
  109. #endif
  110. #ifdef CFG_64BIT_VSPRINTF
  111. static char * number(char * str, long long num, unsigned int base, int size, int precision ,int type)
  112. #else
  113. static char * number(char * str, long num, unsigned int base, int size, int precision ,int type)
  114. #endif
  115. {
  116. char c,sign,tmp[66];
  117. const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  118. int i;
  119. if (type & LARGE)
  120. digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  121. if (type & LEFT)
  122. type &= ~ZEROPAD;
  123. if (base < 2 || base > 36)
  124. return 0;
  125. c = (type & ZEROPAD) ? '0' : ' ';
  126. sign = 0;
  127. if (type & SIGN) {
  128. if (num < 0) {
  129. sign = '-';
  130. num = -num;
  131. size--;
  132. } else if (type & PLUS) {
  133. sign = '+';
  134. size--;
  135. } else if (type & SPACE) {
  136. sign = ' ';
  137. size--;
  138. }
  139. }
  140. if (type & SPECIAL) {
  141. if (base == 16)
  142. size -= 2;
  143. else if (base == 8)
  144. size--;
  145. }
  146. i = 0;
  147. if (num == 0)
  148. tmp[i++]='0';
  149. else while (num != 0)
  150. tmp[i++] = digits[do_div(num,base)];
  151. if (i > precision)
  152. precision = i;
  153. size -= precision;
  154. if (!(type&(ZEROPAD+LEFT)))
  155. while(size-->0)
  156. *str++ = ' ';
  157. if (sign)
  158. *str++ = sign;
  159. if (type & SPECIAL) {
  160. if (base==8)
  161. *str++ = '0';
  162. else if (base==16) {
  163. *str++ = '0';
  164. *str++ = digits[33];
  165. }
  166. }
  167. if (!(type & LEFT))
  168. while (size-- > 0)
  169. *str++ = c;
  170. while (i < precision--)
  171. *str++ = '0';
  172. while (i-- > 0)
  173. *str++ = tmp[i];
  174. while (size-- > 0)
  175. *str++ = ' ';
  176. return str;
  177. }
  178. /* Forward decl. needed for IP address printing stuff... */
  179. int sprintf(char * buf, const char *fmt, ...);
  180. int vsprintf(char *buf, const char *fmt, va_list args)
  181. {
  182. int len;
  183. #ifdef CFG_64BIT_VSPRINTF
  184. unsigned long long num;
  185. #else
  186. unsigned long num;
  187. #endif
  188. int i, base;
  189. char * str;
  190. const char *s;
  191. int flags; /* flags to number() */
  192. int field_width; /* width of output field */
  193. int precision; /* min. # of digits for integers; max
  194. number of chars for from string */
  195. int qualifier; /* 'h', 'l', or 'q' for integer fields */
  196. for (str=buf ; *fmt ; ++fmt) {
  197. if (*fmt != '%') {
  198. *str++ = *fmt;
  199. continue;
  200. }
  201. /* process flags */
  202. flags = 0;
  203. repeat:
  204. ++fmt; /* this also skips first '%' */
  205. switch (*fmt) {
  206. case '-': flags |= LEFT; goto repeat;
  207. case '+': flags |= PLUS; goto repeat;
  208. case ' ': flags |= SPACE; goto repeat;
  209. case '#': flags |= SPECIAL; goto repeat;
  210. case '0': flags |= ZEROPAD; goto repeat;
  211. }
  212. /* get field width */
  213. field_width = -1;
  214. if (is_digit(*fmt))
  215. field_width = skip_atoi(&fmt);
  216. else if (*fmt == '*') {
  217. ++fmt;
  218. /* it's the next argument */
  219. field_width = va_arg(args, int);
  220. if (field_width < 0) {
  221. field_width = -field_width;
  222. flags |= LEFT;
  223. }
  224. }
  225. /* get the precision */
  226. precision = -1;
  227. if (*fmt == '.') {
  228. ++fmt;
  229. if (is_digit(*fmt))
  230. precision = skip_atoi(&fmt);
  231. else if (*fmt == '*') {
  232. ++fmt;
  233. /* it's the next argument */
  234. precision = va_arg(args, int);
  235. }
  236. if (precision < 0)
  237. precision = 0;
  238. }
  239. /* get the conversion qualifier */
  240. qualifier = -1;
  241. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'q') {
  242. qualifier = *fmt;
  243. if (qualifier == 'l' && *(fmt+1) == 'l') {
  244. qualifier = 'q';
  245. ++fmt;
  246. }
  247. ++fmt;
  248. }
  249. /* default base */
  250. base = 10;
  251. switch (*fmt) {
  252. case 'c':
  253. if (!(flags & LEFT))
  254. while (--field_width > 0)
  255. *str++ = ' ';
  256. *str++ = (unsigned char) va_arg(args, int);
  257. while (--field_width > 0)
  258. *str++ = ' ';
  259. continue;
  260. case 's':
  261. s = va_arg(args, char *);
  262. if (!s)
  263. s = "<NULL>";
  264. len = strnlen(s, precision);
  265. if (!(flags & LEFT))
  266. while (len < field_width--)
  267. *str++ = ' ';
  268. for (i = 0; i < len; ++i)
  269. *str++ = *s++;
  270. while (len < field_width--)
  271. *str++ = ' ';
  272. continue;
  273. case 'p':
  274. if (field_width == -1) {
  275. field_width = 2*sizeof(void *);
  276. flags |= ZEROPAD;
  277. }
  278. str = number(str,
  279. (unsigned long) va_arg(args, void *), 16,
  280. field_width, precision, flags);
  281. continue;
  282. case 'n':
  283. if (qualifier == 'l') {
  284. long * ip = va_arg(args, long *);
  285. *ip = (str - buf);
  286. } else {
  287. int * ip = va_arg(args, int *);
  288. *ip = (str - buf);
  289. }
  290. continue;
  291. case '%':
  292. *str++ = '%';
  293. continue;
  294. /* integer number formats - set up the flags and "break" */
  295. case 'o':
  296. base = 8;
  297. break;
  298. case 'X':
  299. flags |= LARGE;
  300. case 'x':
  301. base = 16;
  302. break;
  303. case 'd':
  304. case 'i':
  305. flags |= SIGN;
  306. case 'u':
  307. break;
  308. default:
  309. *str++ = '%';
  310. if (*fmt)
  311. *str++ = *fmt;
  312. else
  313. --fmt;
  314. continue;
  315. }
  316. #ifdef CFG_64BIT_VSPRINTF
  317. if (qualifier == 'q') /* "quad" for 64 bit variables */
  318. num = va_arg(args, unsigned long long);
  319. else
  320. #endif
  321. if (qualifier == 'l')
  322. num = va_arg(args, unsigned long);
  323. else if (qualifier == 'h') {
  324. num = (unsigned short) va_arg(args, int);
  325. if (flags & SIGN)
  326. num = (short) num;
  327. } else if (flags & SIGN)
  328. num = va_arg(args, int);
  329. else
  330. num = va_arg(args, unsigned int);
  331. str = number(str, num, base, field_width, precision, flags);
  332. }
  333. *str = '\0';
  334. return str-buf;
  335. }
  336. int sprintf(char * buf, const char *fmt, ...)
  337. {
  338. va_list args;
  339. int i;
  340. va_start(args, fmt);
  341. i=vsprintf(buf,fmt,args);
  342. va_end(args);
  343. return i;
  344. }
  345. void panic(const char *fmt, ...)
  346. {
  347. va_list args;
  348. va_start(args, fmt);
  349. vprintf(fmt, args);
  350. putc('\n');
  351. va_end(args);
  352. #if defined (CONFIG_PANIC_HANG)
  353. hang();
  354. #else
  355. udelay (100000); /* allow messages to go out */
  356. do_reset (NULL, 0, 0, NULL);
  357. #endif
  358. }