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

source code of glibc/libio/obprintf.c