1/* Print output of stream to given obstack.
2   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
5
6   The GNU C Library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Library General Public License as
8   published by the Free Software Foundation; either version 2 of the
9   License, or (at your option) any later version.
10
11   The GNU C Library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15
16   You should have received a copy of the GNU Library General Public
17   License along with the GNU C Library; see the file COPYING.LIB.  If not,
18   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.  */
20
21
22#ifdef __STDC__
23#include <stdlib.h>
24#endif
25#include "libioP.h"
26#include <string.h>
27#include <errno.h>
28#include <obstack.h>
29#include <stdarg.h>
30
31
32struct _IO_obstack_file
33{
34  struct _IO_FILE file;
35  const void *vtable;
36  struct obstack *obstack;
37};
38
39
40static int
41_IO_obstack_overflow (_IO_FILE *fp, int c)
42{
43  struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
44
45  /* Make room for another character.  This might as well allocate a
46     new chunk a memory and moves the old contents over.  */
47  if (c != EOF)
48    obstack_1grow (obstack, c);
49
50  /* Setup the buffer pointers again.  */
51  fp->_IO_write_base = obstack_base (obstack);
52  fp->_IO_write_ptr = obstack_next_free (obstack);
53  fp->_IO_write_end = fp->_IO_write_base + obstack_room (obstack);
54  /* Now allocate the rest of the current chunk.  */
55  obstack_blank_fast (obstack, fp->_IO_write_end - fp->_IO_write_ptr);
56
57  return c;
58}
59
60
61static _IO_size_t
62_IO_obstack_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
63{
64  struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
65
66  if (fp->_IO_write_ptr + n > fp->_IO_write_end)
67    {
68      /* We need some more memory.  First shrink the buffer to the
69	 space we really currently need.  */
70      obstack_blank (obstack, fp->_IO_write_ptr - fp->_IO_write_end);
71
72      /* Now grow for N bytes.  */
73      obstack_blank (obstack, n);
74
75      /* Setup the buffer pointers again.  */
76      fp->_IO_write_base = obstack_base (obstack);
77      fp->_IO_write_ptr = obstack_next_free (obstack);
78      fp->_IO_write_end = (fp->_IO_write_base + obstack_room (obstack));
79      /* Now allocate the rest of the current chunk.  */
80      obstack_blank_fast (obstack, fp->_IO_write_end - fp->_IO_write_ptr);
81    }
82  else
83    {
84      memcpy (fp->_IO_write_ptr, data, n);
85      fp->_IO_write_ptr += n;
86    }
87
88  return n;
89}
90
91
92/* the jump table.  */
93static struct _IO_jump_t _IO_obstack_jumps =
94{
95  JUMP_INIT_DUMMY,
96  JUMP_INIT(finish, NULL),
97  JUMP_INIT(overflow, _IO_obstack_overflow),
98  JUMP_INIT(underflow, NULL),
99  JUMP_INIT(uflow, NULL),
100  JUMP_INIT(pbackfail, NULL),
101  JUMP_INIT(xsputn, _IO_obstack_xsputn),
102  JUMP_INIT(xsgetn, NULL),
103  JUMP_INIT(seekoff, NULL),
104  JUMP_INIT(seekpos, NULL),
105  JUMP_INIT(setbuf, NULL),
106  JUMP_INIT(sync, NULL),
107  JUMP_INIT(doallocate, NULL),
108  JUMP_INIT(read, NULL),
109  JUMP_INIT(write, NULL),
110  JUMP_INIT(seek, NULL),
111  JUMP_INIT(close, NULL),
112  JUMP_INIT(stat, NULL)
113};
114
115
116int
117_IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
118{
119  struct obstack_FILE
120    {
121      struct _IO_obstack_file ofile;
122#ifdef _IO_MTSAFE_IO
123      _IO_lock_t lock;
124#endif
125  } new_f;
126  int result;
127
128#ifdef _IO_MTSAFE_IO
129  new_f.ofile.file._lock = &new_f.lock;
130#endif
131
132  _IO_init ((_IO_FILE *) &new_f.ofile, 0);
133  _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
134  _IO_str_init_static (&new_f.ofile.file, obstack_base (obstack),
135		       (obstack_object_size (obstack) +
136			obstack_room (obstack)), obstack_next_free (obstack));
137  /* Now allocate the rest of the current chunk.  */
138  obstack_blank_fast (obstack,
139		      (new_f.ofile.file._IO_write_end
140		       - new_f.ofile.file._IO_write_ptr));
141  new_f.ofile.obstack = obstack;
142
143  result = _IO_vfprintf ((_IO_FILE *) &new_f, format, args);
144
145  /* Shrink the buffer to the space we really currently need.  */
146  obstack_blank (obstack, (new_f.ofile.file._IO_write_ptr
147			   - new_f.ofile.file._IO_write_end));
148
149  return result;
150}
151#ifdef weak_alias
152weak_alias (_IO_obstack_vprintf, obstack_vprintf)
153#endif
154
155
156int
157_IO_obstack_printf (struct obstack *obstack, const char *format, ...)
158{
159  int result;
160  va_list ap;
161  va_start (ap, format);
162  result = _IO_obstack_vprintf (obstack, format, ap);
163  va_end (ap);
164  return result;
165}
166#ifdef weak_alias
167weak_alias (_IO_obstack_printf, obstack_printf)
168#endif
169