(root)/
bison-3.8.2/
lib/
obstack_printf.c
       1  /* Formatted output to obstacks.
       2     Copyright (C) 2008-2021 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published
       6     by the Free Software Foundation; either version 3 of the License,
       7     or (at your option) any later version.
       8  
       9     This file is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  /* Specification.  */
      20  #include <stdio.h>
      21  
      22  #include "obstack.h"
      23  #include "vasnprintf.h"
      24  
      25  #include <errno.h>
      26  #include <stdarg.h>
      27  #include <stdlib.h>
      28  
      29  /* Grow an obstack with formatted output.  Return the number of bytes
      30     added to OBS.  No trailing nul byte is added, and the object should
      31     be closed with obstack_finish before use.
      32  
      33     Upon memory allocation error, call obstack_alloc_failed_handler.
      34     Upon other error, return -1.  */
      35  int
      36  obstack_printf (struct obstack *obs, const char *format, ...)
      37  {
      38    va_list args;
      39    int result;
      40  
      41    va_start (args, format);
      42    result = obstack_vprintf (obs, format, args);
      43    va_end (args);
      44    return result;
      45  }
      46  
      47  /* Grow an obstack with formatted output.  Return the number of bytes
      48     added to OBS.  No trailing nul byte is added, and the object should
      49     be closed with obstack_finish before use.
      50  
      51     Upon memory allocation error, call obstack_alloc_failed_handler.
      52     Upon other error, return -1.  */
      53  int
      54  obstack_vprintf (struct obstack *obs, const char *format, va_list args)
      55  {
      56    /* If we are close to the end of the current obstack chunk, use a
      57       stack-allocated buffer and copy, to reduce the likelihood of a
      58       small-size malloc.  Otherwise, print directly into the
      59       obstack.  */
      60    enum { CUTOFF = 1024 };
      61    char buf[CUTOFF];
      62    char *base = obstack_next_free (obs);
      63    size_t len = obstack_room (obs);
      64    char *str;
      65  
      66    if (len < CUTOFF)
      67      {
      68        base = buf;
      69        len = CUTOFF;
      70      }
      71    str = vasnprintf (base, &len, format, args);
      72    if (!str)
      73      {
      74        if (errno == ENOMEM)
      75          obstack_alloc_failed_handler ();
      76        return -1;
      77      }
      78    if (str == base && str != buf)
      79      /* The output was already computed in place, but we need to
      80         account for its size.  */
      81      obstack_blank_fast (obs, len);
      82    else
      83      {
      84        /* The output exceeded available obstack space or we used buf;
      85           copy the resulting string.  */
      86        obstack_grow (obs, str, len);
      87        if (str != buf)
      88          free (str);
      89      }
      90    return len;
      91  }