strfmon.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <stdarg.h>
  4. #include <monetary.h>
  5. #include <errno.h>
  6. #include <stdarg.h>
  7. static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_list ap)
  8. {
  9. size_t l;
  10. double x;
  11. int fill, nogrp, negpar, nosym, left, intl;
  12. int lp, rp, w, fw;
  13. char *s0=s;
  14. for (; n && *fmt; ) {
  15. if (*fmt != '%') {
  16. literal:
  17. *s++ = *fmt++;
  18. n--;
  19. continue;
  20. }
  21. fmt++;
  22. if (*fmt == '%') goto literal;
  23. fill = ' ';
  24. nogrp = 0;
  25. negpar = 0;
  26. nosym = 0;
  27. left = 0;
  28. for (; ; fmt++) {
  29. switch (*fmt) {
  30. case '=':
  31. fill = *++fmt;
  32. continue;
  33. case '^':
  34. nogrp = 1;
  35. continue;
  36. case '(':
  37. negpar = 1;
  38. case '+':
  39. continue;
  40. case '!':
  41. nosym = 1;
  42. continue;
  43. case '-':
  44. left = 1;
  45. continue;
  46. }
  47. break;
  48. }
  49. for (fw=0; isdigit(*fmt); fmt++)
  50. fw = 10*fw + (*fmt-'0');
  51. lp = 0;
  52. rp = 2;
  53. if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt); fmt++)
  54. lp = 10*lp + (*fmt-'0');
  55. if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++)
  56. rp = 10*rp + (*fmt-'0');
  57. intl = *fmt++ == 'i';
  58. w = lp + 1 + rp;
  59. if (!left && fw>w) w = fw;
  60. x = va_arg(ap, double);
  61. l = snprintf(s, n, "%*.*f", w, rp, x);
  62. if (l >= n) {
  63. errno = E2BIG;
  64. return -1;
  65. }
  66. s += l;
  67. n -= l;
  68. }
  69. return s-s0;
  70. }
  71. ssize_t strfmon_l(char *restrict s, size_t n, locale_t loc, const char *restrict fmt, ...)
  72. {
  73. va_list ap;
  74. ssize_t ret;
  75. va_start(ap, fmt);
  76. ret = vstrfmon_l(s, n, loc, fmt, ap);
  77. va_end(ap);
  78. return ret;
  79. }
  80. ssize_t strfmon(char *restrict s, size_t n, const char *restrict fmt, ...)
  81. {
  82. va_list ap;
  83. ssize_t ret;
  84. va_start(ap, fmt);
  85. ret = vstrfmon_l(s, n, 0, fmt, ap);
  86. va_end(ap);
  87. return ret;
  88. }