[v3,0/7] Fix some libm static issues
[platform/upstream/glibc.git] / libio / obprintf.c
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
26 struct __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
36 void
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
63 int
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.base, ptr, end - ptr,
88                           __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.base, format, 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.base);
105 }
106
107 int
108 __obstack_vprintf (struct obstack *obstack, const char *format, va_list ap)
109 {
110   return __obstack_vprintf_internal (obstack, format, ap, 0);
111 }
112 ldbl_weak_alias (__obstack_vprintf, obstack_vprintf)
113
114 int
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, ap, 0);
121   va_end (ap);
122   return result;
123 }
124 ldbl_weak_alias (__obstack_printf, obstack_printf)