mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-21 04:31:04 +08:00
125 lines
3.9 KiB
C
125 lines
3.9 KiB
C
/* Print output of stream to given obstack.
|
|
Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <assert.h>
|
|
#include <math_ldbl_opt.h>
|
|
#include <obstack.h>
|
|
#include <printf.h>
|
|
#include <stdarg.h>
|
|
#include <printf_buffer.h>
|
|
|
|
struct __printf_buffer_obstack
|
|
{
|
|
struct __printf_buffer base;
|
|
struct obstack *obstack;
|
|
|
|
/* obstack_1grow is called for compatibility reasons. This needs
|
|
one extra character, and this is the backing store for it. */
|
|
char ch;
|
|
};
|
|
|
|
void
|
|
__printf_buffer_flush_obstack (struct __printf_buffer_obstack *buf)
|
|
{
|
|
/* About to switch buffers, so record the bytes written so far. */
|
|
buf->base.written += buf->base.write_ptr - buf->base.write_base;
|
|
|
|
if (buf->base.write_ptr == &buf->ch + 1)
|
|
{
|
|
/* Errors are reported via a callback mechanism (presumably for
|
|
process termination). */
|
|
obstack_1grow (buf->obstack, buf->ch);
|
|
buf->base.write_base = obstack_next_free (buf->obstack);
|
|
buf->base.write_ptr = buf->base.write_base;
|
|
size_t size = obstack_room (buf->obstack);
|
|
buf->base.write_end = buf->base.write_ptr + size;
|
|
/* Reserve the space on the obstack size. */
|
|
obstack_blank_fast (buf->obstack, size);
|
|
}
|
|
else
|
|
{
|
|
/* Obtain the extra character. */
|
|
buf->base.write_base = &buf->ch;
|
|
buf->base.write_ptr = &buf->ch;
|
|
buf->base.write_end = &buf->ch + 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
__obstack_vprintf_internal (struct obstack *obstack, const char *format,
|
|
va_list args, unsigned int mode_flags)
|
|
{
|
|
/* Legacy setup code for compatibility. */
|
|
size_t room = obstack_room (obstack);
|
|
size_t size = obstack_object_size (obstack) + room;
|
|
if (size == 0)
|
|
{
|
|
/* Get more memory. */
|
|
obstack_make_room (obstack, 64);
|
|
|
|
/* Recompute how much room we have. */
|
|
room = obstack_room (obstack);
|
|
size = room;
|
|
|
|
assert (size != 0);
|
|
}
|
|
|
|
struct __printf_buffer_obstack buf;
|
|
{
|
|
/* The obstack write location might be in the middle of an object. */
|
|
char *ptr = obstack_next_free (obstack);
|
|
char *end = obstack_base (obstack) + size;
|
|
__printf_buffer_init (&buf.base, ptr, end - ptr,
|
|
__printf_buffer_mode_obstack);
|
|
}
|
|
buf.obstack = obstack;
|
|
|
|
/* Now allocate the rest of the current chunk. */
|
|
obstack_blank_fast (obstack, room);
|
|
|
|
__printf_buffer (&buf.base, format, args, mode_flags);
|
|
|
|
if (buf.base.write_ptr == &buf.ch + 1)
|
|
/* buf.ch is in use. Put it into the obstack. */
|
|
obstack_1grow (buf.obstack, buf.ch);
|
|
else if (buf.base.write_ptr != &buf.ch)
|
|
/* Shrink the buffer to the space we really currently need. */
|
|
obstack_blank_fast (buf.obstack, buf.base.write_ptr - buf.base.write_end);
|
|
|
|
return __printf_buffer_done (&buf.base);
|
|
}
|
|
|
|
int
|
|
__obstack_vprintf (struct obstack *obstack, const char *format, va_list ap)
|
|
{
|
|
return __obstack_vprintf_internal (obstack, format, ap, 0);
|
|
}
|
|
ldbl_weak_alias (__obstack_vprintf, obstack_vprintf)
|
|
|
|
int
|
|
__obstack_printf (struct obstack *obstack, const char *format, ...)
|
|
{
|
|
int result;
|
|
va_list ap;
|
|
va_start (ap, format);
|
|
result = __obstack_vprintf_internal (obstack, format, ap, 0);
|
|
va_end (ap);
|
|
return result;
|
|
}
|
|
ldbl_weak_alias (__obstack_printf, obstack_printf)
|