You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vsprintf.c 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <stdarg.h>
  2. #include "if_ether.h" /* for ETH_ALEN */
  3. #include "limits.h" /* for CHAR_BIT */
  4. #include "console.h"
  5. #include "vsprintf.h"
  6. #define LONG_SHIFT ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
  7. #define INT_SHIFT ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
  8. #define SHRT_SHIFT ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
  9. #define CHAR_SHIFT ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
  10. /**************************************************************************
  11. PRINTF and friends
  12. Formats:
  13. %[#]x - 4 bytes int (8 hex digits, lower case)
  14. %[#]X - 4 bytes int (8 hex digits, upper case)
  15. %[#]lx - 8 bytes long (16 hex digits, lower case)
  16. %[#]lX - 8 bytes long (16 hex digits, upper case)
  17. %[#]hx - 2 bytes int (4 hex digits, lower case)
  18. %[#]hX - 2 bytes int (4 hex digits, upper case)
  19. %[#]hhx - 1 byte int (2 hex digits, lower case)
  20. %[#]hhX - 1 byte int (2 hex digits, upper case)
  21. - optional # prefixes 0x or 0X
  22. %d - decimal int
  23. %c - char
  24. %s - string
  25. %@ - Internet address in ddd.ddd.ddd.ddd notation
  26. %! - Ethernet address in xx:xx:xx:xx:xx:xx notation
  27. Note: width specification ignored
  28. **************************************************************************/
  29. static int vsprintf(char *buf, const char *fmt, va_list args)
  30. {
  31. char *p, *s;
  32. s = buf;
  33. for ( ; *fmt != '\0'; ++fmt) {
  34. if (*fmt != '%') {
  35. buf ? *s++ = *fmt : putchar(*fmt);
  36. continue;
  37. }
  38. /* skip width specs */
  39. fmt++;
  40. while (*fmt >= '0' && *fmt <= '9')
  41. fmt++;
  42. if (*fmt == '.')
  43. fmt++;
  44. while (*fmt >= '0' && *fmt <= '9')
  45. fmt++;
  46. if (*fmt == 's') {
  47. for(p = va_arg(args, char *); *p != '\0'; p++)
  48. buf ? *s++ = *p : putchar(*p);
  49. }
  50. else { /* Length of item is bounded */
  51. char tmp[40], *q = tmp;
  52. int alt = 0;
  53. int shift = INT_SHIFT;
  54. if (*fmt == '#') {
  55. alt = 1;
  56. fmt++;
  57. }
  58. if (*fmt == 'l') {
  59. shift = LONG_SHIFT;
  60. fmt++;
  61. }
  62. else if (*fmt == 'h') {
  63. shift = SHRT_SHIFT;
  64. fmt++;
  65. if (*fmt == 'h') {
  66. shift = CHAR_SHIFT;
  67. fmt++;
  68. }
  69. }
  70. /*
  71. * Before each format q points to tmp buffer
  72. * After each format q points past end of item
  73. */
  74. if ((*fmt | 0x20) == 'x') {
  75. /* With x86 gcc, sizeof(long) == sizeof(int) */
  76. unsigned long h;
  77. int ncase;
  78. if (shift > INT_SHIFT) {
  79. h = va_arg(args, unsigned long);
  80. } else {
  81. h = va_arg(args, unsigned int);
  82. }
  83. ncase = (*fmt & 0x20);
  84. if (alt) {
  85. *q++ = '0';
  86. *q++ = 'X' | ncase;
  87. }
  88. for ( ; shift >= 0; shift -= 4)
  89. *q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
  90. }
  91. else if (*fmt == 'd') {
  92. char *r;
  93. long i;
  94. if (shift > INT_SHIFT) {
  95. i = va_arg(args, long);
  96. } else {
  97. i = va_arg(args, int);
  98. }
  99. if (i < 0) {
  100. *q++ = '-';
  101. i = -i;
  102. }
  103. p = q; /* save beginning of digits */
  104. do {
  105. *q++ = '0' + (i % 10);
  106. i /= 10;
  107. } while (i);
  108. /* reverse digits, stop in middle */
  109. r = q; /* don't alter q */
  110. while (--r > p) {
  111. i = *r;
  112. *r = *p;
  113. *p++ = i;
  114. }
  115. }
  116. else if (*fmt == '@') {
  117. unsigned char *r;
  118. union {
  119. uint32_t l;
  120. unsigned char c[4];
  121. } u;
  122. u.l = va_arg(args, uint32_t);
  123. for (r = &u.c[0]; r < &u.c[4]; ++r)
  124. q += sprintf(q, "%d.", *r);
  125. --q;
  126. }
  127. else if (*fmt == '!') {
  128. char *r;
  129. p = va_arg(args, char *);
  130. for (r = p + ETH_ALEN; p < r; ++p)
  131. q += sprintf(q, "%hhX:", *p);
  132. --q;
  133. }
  134. else if (*fmt == 'c')
  135. *q++ = va_arg(args, int);
  136. else
  137. *q++ = *fmt;
  138. /* now output the saved string */
  139. for (p = tmp; p < q; ++p)
  140. buf ? *s++ = *p : putchar(*p);
  141. }
  142. }
  143. if (buf)
  144. *s = '\0';
  145. return (s - buf);
  146. }
  147. int sprintf(char *buf, const char *fmt, ...)
  148. {
  149. va_list args;
  150. int i;
  151. va_start(args, fmt);
  152. i=vsprintf(buf, fmt, args);
  153. va_end(args);
  154. return i;
  155. }
  156. void printf(const char *fmt, ...)
  157. {
  158. va_list args;
  159. int i;
  160. va_start(args, fmt);
  161. i=vsprintf(0, fmt, args);
  162. va_end(args);
  163. }