vfprintf.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /* -*-comment-start: "//";comment-end:""-*-
  2. * GNU Mes --- Maxwell Equations of Software
  3. * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  4. *
  5. * This file is part of GNU Mes.
  6. *
  7. * GNU Mes is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * GNU Mes is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <mes/lib.h>
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. int
  25. vfprintf (FILE * f, char const *format, va_list ap)
  26. {
  27. int fd = (long) f;
  28. char const *p = format;
  29. int count = 0;
  30. while (*p)
  31. if (*p != '%')
  32. {
  33. count++;
  34. fputc (*p++, f);
  35. }
  36. else
  37. {
  38. p++;
  39. char c = *p;
  40. int left_p = 0;
  41. int precision = -1;
  42. int width = -1;
  43. if (c == '-')
  44. {
  45. left_p = 1;
  46. c = *++p;
  47. }
  48. char pad = ' ';
  49. if (c == ' ')
  50. {
  51. pad = c;
  52. c = *p++;
  53. }
  54. if (c == '0')
  55. {
  56. pad = c;
  57. c = *p++;
  58. }
  59. if (c >= '0' && c <= '9')
  60. {
  61. width = abtol (&p, 10);
  62. c = *p;
  63. }
  64. else if (c == '*')
  65. {
  66. width = va_arg (ap, int);
  67. c = *++p;
  68. }
  69. if (c == '.')
  70. {
  71. c = *++p;
  72. if (c >= '0' && c <= '9')
  73. {
  74. precision = abtol (&p, 10);
  75. c = *p;
  76. }
  77. else if (c == '*')
  78. {
  79. precision = va_arg (ap, int);
  80. c = *++p;
  81. }
  82. }
  83. if (c == 'l')
  84. c = *++p;
  85. if (c == 'l')
  86. {
  87. eputs ("vfprintf: skipping second: l\n");
  88. c = *++p;
  89. }
  90. switch (c)
  91. {
  92. case '%':
  93. {
  94. fputc (*p, f);
  95. count++;
  96. break;
  97. }
  98. case 'c':
  99. {
  100. char _c;
  101. _c = va_arg (ap, long);
  102. fputc (_c, f);
  103. break;
  104. }
  105. case 'd':
  106. case 'i':
  107. case 'o':
  108. case 'u':
  109. case 'x':
  110. case 'X':
  111. {
  112. long d = va_arg (ap, long);
  113. int base = c == 'o' ? 8 : c == 'x' || c == 'X' ? 16 : 10;
  114. char *s = ntoab (d, base, c != 'u' && c != 'x' && c != 'X');
  115. if (c == 'X')
  116. strupr (s);
  117. int length = strlen (s);
  118. if (precision == -1)
  119. precision = length;
  120. if (!left_p)
  121. {
  122. while (width-- > precision)
  123. {
  124. fputc (pad, f);
  125. count++;
  126. }
  127. while (precision > length)
  128. {
  129. fputc ('0', f);
  130. precision--;
  131. width--;
  132. count++;
  133. }
  134. }
  135. while (*s)
  136. {
  137. if (precision-- <= 0)
  138. break;
  139. width--;
  140. fputc (*s++, f);
  141. count++;
  142. }
  143. while (width > 0)
  144. {
  145. width--;
  146. fputc (pad, f);
  147. count++;
  148. }
  149. break;
  150. }
  151. case 's':
  152. {
  153. char *s = va_arg (ap, char *);
  154. int length = strlen (s);
  155. if (precision == -1)
  156. precision = length;
  157. if (!left_p)
  158. {
  159. while (width-- > precision)
  160. {
  161. fputc (pad, f);
  162. count++;
  163. }
  164. while (precision > length)
  165. {
  166. fputc (' ', f);
  167. precision--;
  168. width--;
  169. count++;
  170. }
  171. }
  172. while (*s)
  173. {
  174. if (precision-- <= 0)
  175. break;
  176. width--;
  177. fputc (*s++, f);
  178. count++;
  179. }
  180. while (width > 0)
  181. {
  182. width--;
  183. fputc (pad, f);
  184. count++;
  185. }
  186. break;
  187. }
  188. case 'f':
  189. case 'e':
  190. case 'E':
  191. case 'g':
  192. case 'G':
  193. {
  194. double d = va_arg8 (ap, double);
  195. char *s = dtoab (d, 10, 1);
  196. if (c == 'E' || c == 'G')
  197. strupr (s);
  198. int length = strlen (s);
  199. if (precision == -1)
  200. precision = length;
  201. if (!left_p)
  202. {
  203. while (width-- > precision)
  204. {
  205. fputc (pad, f);
  206. count++;
  207. }
  208. while (precision > length)
  209. {
  210. fputc (' ', f);
  211. precision--;
  212. width--;
  213. count++;
  214. }
  215. }
  216. while (*s)
  217. {
  218. if (precision-- <= 0)
  219. break;
  220. width--;
  221. fputc (*s++, f);
  222. count++;
  223. }
  224. while (width > 0)
  225. {
  226. width--;
  227. fputc (pad, f);
  228. count++;
  229. }
  230. break;
  231. }
  232. case 'n':
  233. {
  234. int *n = va_arg (ap, int *);
  235. *n = count;
  236. break;
  237. }
  238. default:
  239. {
  240. eputs ("vfprintf: not supported: %:");
  241. eputc (c);
  242. eputs ("\n");
  243. p++;
  244. }
  245. }
  246. p++;
  247. }
  248. va_end (ap);
  249. return 0;
  250. }