(root)/
glibc-2.38/
libio/
obprintf.c
       1  /* Print output of stream to given obstack.
       2     Copyright (C) 1996-2023 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)