obstack_printf.c 2.7 KB

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