fprintf.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: f_printf.c
  15. * Date: 2021-08-23 16:24:02
  16. * LastEditTime: 2022-02-17 18:01:19
  17. * Description:  This files is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. #include <stdarg.h>
  24. #include "fearly_uart.h"
  25. #define putchar(c) OutByte(c)
  26. #define PAD_RIGHT 1
  27. #define PAD_ZERO 2
  28. static void printchar(char **str, int c)
  29. {
  30. if (str)
  31. {
  32. **str = c;
  33. ++(*str);
  34. }
  35. else
  36. (void)putchar((const char)c);
  37. }
  38. static int prints(char **out, const char *string, int width, int pad)
  39. {
  40. register int pc = 0, padchar = ' ';
  41. if (width > 0)
  42. {
  43. register int len = 0;
  44. register const char *ptr;
  45. for (ptr = string; *ptr; ++ptr)
  46. ++len;
  47. if (len >= width)
  48. width = 0;
  49. else
  50. width -= len;
  51. if (pad & PAD_ZERO)
  52. padchar = '0';
  53. }
  54. if (!(pad & PAD_RIGHT))
  55. {
  56. for (; width > 0; --width)
  57. {
  58. printchar(out, padchar);
  59. ++pc;
  60. }
  61. }
  62. for (; *string; ++string)
  63. {
  64. printchar(out, *string);
  65. ++pc;
  66. }
  67. for (; width > 0; --width)
  68. {
  69. printchar(out, padchar);
  70. ++pc;
  71. }
  72. return pc;
  73. }
  74. /* the following should be enough for 32 bit int */
  75. #define PRINT_BUF_LEN 12
  76. static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
  77. {
  78. char print_buf[PRINT_BUF_LEN];
  79. register char *s;
  80. register int t, neg = 0, pc = 0;
  81. register unsigned int u = i;
  82. if (i == 0)
  83. {
  84. print_buf[0] = '0';
  85. print_buf[1] = '\0';
  86. return prints(out, print_buf, width, pad);
  87. }
  88. if (sg && b == 10 && i < 0)
  89. {
  90. neg = 1;
  91. u = -i;
  92. }
  93. s = print_buf + PRINT_BUF_LEN - 1;
  94. *s = '\0';
  95. while (u)
  96. {
  97. t = u % b;
  98. if (t >= 10)
  99. t += letbase - '0' - 10;
  100. *--s = t + '0';
  101. u /= b;
  102. }
  103. if (neg)
  104. {
  105. if (width && (pad & PAD_ZERO))
  106. {
  107. printchar(out, '-');
  108. ++pc;
  109. --width;
  110. }
  111. else
  112. {
  113. *--s = '-';
  114. }
  115. }
  116. return pc + prints(out, s, width, pad);
  117. }
  118. static int print(char **out, const char *format, va_list args)
  119. {
  120. register int width, pad;
  121. register int pc = 0;
  122. char scr[2];
  123. for (; *format != 0; ++format)
  124. {
  125. if (*format == '%')
  126. {
  127. ++format;
  128. width = pad = 0;
  129. if (*format == '\0')
  130. break;
  131. if (*format == '%')
  132. goto out;
  133. if (*format == '-')
  134. {
  135. ++format;
  136. pad = PAD_RIGHT;
  137. }
  138. while (*format == '0')
  139. {
  140. ++format;
  141. pad |= PAD_ZERO;
  142. }
  143. for (; *format >= '0' && *format <= '9'; ++format)
  144. {
  145. width *= 10;
  146. width += *format - '0';
  147. }
  148. if (*format == 's')
  149. {
  150. //register char *s = (char *)va_arg( args, int );
  151. register char *s = (char *)va_arg(args, char *);
  152. pc += prints(out, s ? s : "(null)", width, pad);
  153. continue;
  154. }
  155. if (*format == 'd')
  156. {
  157. pc += printi(out, va_arg(args, int), 10, 1, width, pad, 'a');
  158. continue;
  159. }
  160. if (*format == 'x')
  161. {
  162. pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'a');
  163. continue;
  164. }
  165. if (*format == 'X')
  166. {
  167. pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'A');
  168. continue;
  169. }
  170. if (*format == 'u')
  171. {
  172. pc += printi(out, va_arg(args, int), 10, 0, width, pad, 'a');
  173. continue;
  174. }
  175. if (*format == 'c')
  176. {
  177. /* char are converted to int then pushed on the stack */
  178. scr[0] = (char)va_arg(args, int);
  179. scr[1] = '\0';
  180. pc += prints(out, scr, width, pad);
  181. continue;
  182. }
  183. }
  184. else
  185. {
  186. out:
  187. printchar(out, *format);
  188. ++pc;
  189. }
  190. }
  191. if (out)
  192. **out = '\0';
  193. va_end(args);
  194. return pc;
  195. }
  196. int f_printf(const char *format, ...)
  197. {
  198. va_list args;
  199. va_start(args, format);
  200. return print(0, format, args);
  201. }
  202. #ifdef TEST_PRINTF
  203. int test_printf(void)
  204. {
  205. char *ptr = "Hello world!";
  206. char *np = 0;
  207. int i = 5;
  208. unsigned int bs = sizeof(int) * 8;
  209. int mi;
  210. char buf[80];
  211. mi = (1 << (bs - 1)) + 1;
  212. f_printf("%s\n", ptr);
  213. f_printf("printf test\n");
  214. f_printf("%s is null pointer\n", np);
  215. f_printf("%d = 5\n", i);
  216. f_printf("%d = - max int\n", mi);
  217. f_printf("char %c = 'a'\n", 'a');
  218. f_printf("hex %x = ff\n", 0xff);
  219. f_printf("hex %02x = 00\n", 0);
  220. f_printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
  221. f_printf("%d %s(s)%", 0, "message");
  222. f_printf("\n");
  223. f_printf("%d %s(s) with %%\n", 0, "message");
  224. sprintf(buf, "justif: \"%-10s\"\n", "left");
  225. f_printf("%s", buf);
  226. sprintf(buf, "justif: \"%10s\"\n", "right");
  227. f_printf("%s", buf);
  228. sprintf(buf, " 3: %04d zero padded\n", 3);
  229. f_printf("%s", buf);
  230. sprintf(buf, " 3: %-4d left justif.\n", 3);
  231. f_printf("%s", buf);
  232. sprintf(buf, " 3: %4d right justif.\n", 3);
  233. f_printf("%s", buf);
  234. sprintf(buf, "-3: %04d zero padded\n", -3);
  235. f_printf("%s", buf);
  236. sprintf(buf, "-3: %-4d left justif.\n", -3);
  237. f_printf("%s", buf);
  238. sprintf(buf, "-3: %4d right justif.\n", -3);
  239. f_printf("%s", buf);
  240. return 0;
  241. }
  242. #endif