printk.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // Created by longjin on 2022/1/22.
  3. //
  4. #include "printk.h"
  5. int skip_and_atoi(const char **s)
  6. {
  7. /**
  8. * @brief 获取连续的一段字符对应整数的值
  9. * @param:**s 指向 指向字符串的指针 的指针
  10. */
  11. int ans = 0;
  12. while (is_digit(**s))
  13. {
  14. ans = ans * 10 + (**s) - '0';
  15. ++(*s);
  16. }
  17. return ans;
  18. }
  19. int vsprintf(char *buf, const char *fmt, va_list args)
  20. {
  21. /**
  22. * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
  23. * @param buf 结果缓冲区
  24. * @param fmt 格式化字符串
  25. * @param args 内容
  26. * @return 最终字符串的长度
  27. */
  28. char *str, *s;
  29. str = buf;
  30. int flags; // 用来存储格式信息的bitmap
  31. int field_width; //区域宽度
  32. int precision; //精度
  33. int qualifier; //数据显示的类型
  34. int len;
  35. //开始解析字符串
  36. for (; *fmt; ++fmt)
  37. {
  38. //内容不涉及到格式化,直接输出
  39. if (*fmt != '%')
  40. {
  41. *str = *fmt;
  42. ++str;
  43. }
  44. //开始格式化字符串
  45. //清空标志位和field宽度
  46. field_width = flags = 0;
  47. ++fmt;
  48. bool flag_tmp = true;
  49. bool flag_break = false;
  50. while (flag_tmp)
  51. {
  52. switch (*fmt)
  53. {
  54. case '\0':
  55. //结束解析
  56. flag_break = true;
  57. flag_tmp = false;
  58. break;
  59. case '%':
  60. //输出 %
  61. *str = '%';
  62. ++str;
  63. ++fmt;
  64. flag_break = true;
  65. break;
  66. case '-':
  67. // 左对齐
  68. flags |= LEFT;
  69. ++fmt;
  70. break;
  71. case '+':
  72. //在正数前面显示加号
  73. flags |= PLUS;
  74. ++fmt;
  75. break;
  76. case ' ':
  77. flags |= SPACE;
  78. ++fmt;
  79. break;
  80. case '#':
  81. //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
  82. flags |= SPECIAL;
  83. ++fmt;
  84. break;
  85. case '0':
  86. //显示的数字之前填充‘0’来取代空格
  87. flags |= PAD_ZERO;
  88. ++fmt;
  89. break;
  90. default:
  91. flag_tmp = false;
  92. break;
  93. }
  94. }
  95. if (flag_break)
  96. break;
  97. //获取区域宽度
  98. if (*fmt == '*')
  99. {
  100. field_width = va_arg(args, int);
  101. ++fmt;
  102. }
  103. else if (is_digit(*fmt))
  104. field_width = skip_and_atoi(&fmt);
  105. //获取小数精度
  106. precision = -1;
  107. if (*fmt == '.')
  108. {
  109. ++fmt;
  110. if (*fmt == '*')
  111. {
  112. precision = va_arg(args, int);
  113. ++fmt;
  114. }
  115. else if is_digit (*fmt)
  116. {
  117. precision = skip_and_atoi(&fmt);
  118. }
  119. }
  120. //获取要显示的数据的类型
  121. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
  122. {
  123. qualifier = *fmt;
  124. ++fmt;
  125. }
  126. //转化成字符串
  127. switch (*fmt)
  128. {
  129. // 显示一个字符
  130. case 'c':
  131. //靠右对齐
  132. if (!(flags & LEFT))
  133. {
  134. while (--field_width)
  135. {
  136. *str = ' ';
  137. ++str;
  138. }
  139. }
  140. else //靠左对齐
  141. {
  142. *str = (char)va_arg(args, int);
  143. ++str;
  144. --field_width;
  145. }
  146. while (--field_width)
  147. {
  148. *str = ' ';
  149. ++str;
  150. }
  151. break;
  152. //显示一个字符串
  153. case 's':
  154. s = va_arg(args, char *);
  155. if (!s)
  156. s = '\0';
  157. len = strlen(s);
  158. if (precision < 0)
  159. {
  160. //未指定精度
  161. precision = len;
  162. }
  163. else if (len > precision)
  164. {
  165. len = precision;
  166. }
  167. //靠右对齐
  168. if (!(flags & LEFT))
  169. while (len < field_width--)
  170. {
  171. *str = ' ';
  172. ++str;
  173. }
  174. for (int i = 0; i < len; i++)
  175. {
  176. *str = *s;
  177. ++s;
  178. ++str;
  179. }
  180. while (len<field_width--)
  181. {
  182. *str = ' ';
  183. ++str;
  184. }
  185. break;
  186. default:
  187. break;
  188. }
  189. }
  190. }