obprintf.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* Print output of stream to given obstack.
  2. Copyright (C) 1996-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <assert.h>
  16. #include <math_ldbl_opt.h>
  17. #include <obstack.h>
  18. #include <printf.h>
  19. #include <stdarg.h>
  20. #include <printf_buffer.h>
  21. struct __printf_buffer_obstack
  22. {
  23. struct __printf_buffer base;
  24. struct obstack *obstack;
  25. /* obstack_1grow is called for compatibility reasons. This needs
  26. one extra character, and this is the backing store for it. */
  27. char ch;
  28. };
  29. void
  30. __printf_buffer_flush_obstack (struct __printf_buffer_obstack *buf)
  31. {
  32. /* About to switch buffers, so record the bytes written so far. */
  33. buf->base.written += buf->base.write_ptr - buf->base.write_base;
  34. if (buf->base.write_ptr == &buf->ch + 1)
  35. {
  36. /* Errors are reported via a callback mechanism (presumably for
  37. process termination). */
  38. obstack_1grow (buf->obstack, buf->ch);
  39. buf->base.write_base = obstack_next_free (buf->obstack);
  40. buf->base.write_ptr = buf->base.write_base;
  41. size_t size = obstack_room (buf->obstack);
  42. buf->base.write_end = buf->base.write_ptr + size;
  43. /* Reserve the space on the obstack size. */
  44. obstack_blank_fast (buf->obstack, size);
  45. }
  46. else
  47. {
  48. /* Obtain the extra character. */
  49. buf->base.write_base = &buf->ch;
  50. buf->base.write_ptr = &buf->ch;
  51. buf->base.write_end = &buf->ch + 1;
  52. }
  53. }
  54. int
  55. __obstack_vprintf_internal (struct obstack *obstack, const char *format,
  56. va_list args, unsigned int mode_flags)
  57. {
  58. /* Legacy setup code for compatibility. */
  59. size_t room = obstack_room (obstack);
  60. size_t size = obstack_object_size (obstack) + room;
  61. if (size == 0)
  62. {
  63. /* Get more memory. */
  64. obstack_make_room (obstack, 64);
  65. /* Recompute how much room we have. */
  66. room = obstack_room (obstack);
  67. size = room;
  68. assert (size != 0);
  69. }
  70. struct __printf_buffer_obstack buf;
  71. {
  72. /* The obstack write location might be in the middle of an object. */
  73. char *ptr = obstack_next_free (obstack);
  74. char *end = obstack_base (obstack) + size;
  75. __printf_buffer_init (&buf.base, ptr, end - ptr,
  76. __printf_buffer_mode_obstack);
  77. }
  78. buf.obstack = obstack;
  79. /* Now allocate the rest of the current chunk. */
  80. obstack_blank_fast (obstack, room);
  81. __printf_buffer (&buf.base, format, args, mode_flags);
  82. if (buf.base.write_ptr == &buf.ch + 1)
  83. /* buf.ch is in use. Put it into the obstack. */
  84. obstack_1grow (buf.obstack, buf.ch);
  85. else if (buf.base.write_ptr != &buf.ch)
  86. /* Shrink the buffer to the space we really currently need. */
  87. obstack_blank_fast (buf.obstack, buf.base.write_ptr - buf.base.write_end);
  88. return __printf_buffer_done (&buf.base);
  89. }
  90. int
  91. __obstack_vprintf (struct obstack *obstack, const char *format, va_list ap)
  92. {
  93. return __obstack_vprintf_internal (obstack, format, ap, 0);
  94. }
  95. ldbl_weak_alias (__obstack_vprintf, obstack_vprintf)
  96. int
  97. __obstack_printf (struct obstack *obstack, const char *format, ...)
  98. {
  99. int result;
  100. va_list ap;
  101. va_start (ap, format);
  102. result = __obstack_vprintf_internal (obstack, format, ap, 0);
  103. va_end (ap);
  104. return result;
  105. }
  106. ldbl_weak_alias (__obstack_printf, obstack_printf)