Setup LOCPATH for tst-ftell-active-handler and tst-ftell-partial-wide in libio
[platform/upstream/glibc.git] / libio / obprintf.c
1 /* Print output of stream to given obstack.
2    Copyright (C) 1996-2014 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 Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the 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    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20
21 #include <stdlib.h>
22 #include "libioP.h"
23 #include "strfile.h"
24 #include <assert.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <obstack.h>
28 #include <stdarg.h>
29 #include <stdio_ext.h>
30
31
32 struct _IO_obstack_file
33 {
34   struct _IO_FILE_plus file;
35   struct obstack *obstack;
36 };
37
38
39 static int
40 _IO_obstack_overflow (_IO_FILE *fp, int c)
41 {
42   struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
43   int size;
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   assert (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   size = obstack_room (obstack);
54   fp->_IO_write_end = fp->_IO_write_ptr + size;
55   /* Now allocate the rest of the current chunk.  */
56   obstack_blank_fast (obstack, size);
57
58   return c;
59 }
60
61
62 static _IO_size_t
63 _IO_obstack_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
64 {
65   struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
66
67   if (fp->_IO_write_ptr + n > fp->_IO_write_end)
68     {
69       int size;
70
71       /* We need some more memory.  First shrink the buffer to the
72          space we really currently need.  */
73       obstack_blank_fast (obstack, fp->_IO_write_ptr - fp->_IO_write_end);
74
75       /* Now grow for N bytes, and put the data there.  */
76       obstack_grow (obstack, data, n);
77
78       /* Setup the buffer pointers again.  */
79       fp->_IO_write_base = obstack_base (obstack);
80       fp->_IO_write_ptr = obstack_next_free (obstack);
81       size = obstack_room (obstack);
82       fp->_IO_write_end = fp->_IO_write_ptr + size;
83       /* Now allocate the rest of the current chunk.  */
84       obstack_blank_fast (obstack, size);
85     }
86   else
87     fp->_IO_write_ptr = __mempcpy (fp->_IO_write_ptr, data, n);
88
89   return n;
90 }
91
92
93 /* the jump table.  */
94 const struct _IO_jump_t _IO_obstack_jumps attribute_hidden =
95 {
96   JUMP_INIT_DUMMY,
97   JUMP_INIT(finish, NULL),
98   JUMP_INIT(overflow, _IO_obstack_overflow),
99   JUMP_INIT(underflow, NULL),
100   JUMP_INIT(uflow, NULL),
101   JUMP_INIT(pbackfail, NULL),
102   JUMP_INIT(xsputn, _IO_obstack_xsputn),
103   JUMP_INIT(xsgetn, NULL),
104   JUMP_INIT(seekoff, NULL),
105   JUMP_INIT(seekpos, NULL),
106   JUMP_INIT(setbuf, NULL),
107   JUMP_INIT(sync, NULL),
108   JUMP_INIT(doallocate, NULL),
109   JUMP_INIT(read, NULL),
110   JUMP_INIT(write, NULL),
111   JUMP_INIT(seek, NULL),
112   JUMP_INIT(close, NULL),
113   JUMP_INIT(stat, NULL),
114   JUMP_INIT(showmanyc, NULL),
115   JUMP_INIT(imbue, NULL)
116 };
117
118
119 int
120 _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
121 {
122   struct obstack_FILE
123     {
124       struct _IO_obstack_file ofile;
125   } new_f;
126   int result;
127   int size;
128   int room;
129
130 #ifdef _IO_MTSAFE_IO
131   new_f.ofile.file.file._lock = NULL;
132 #endif
133
134   _IO_no_init (&new_f.ofile.file.file, _IO_USER_LOCK, -1, NULL, NULL);
135   _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
136   room = obstack_room (obstack);
137   size = obstack_object_size (obstack) + room;
138   if (size == 0)
139     {
140       /* We have to handle the allocation a bit different since the
141          `_IO_str_init_static' function would handle a size of zero
142          different from what we expect.  */
143
144       /* Get more memory.  */
145       obstack_make_room (obstack, 64);
146
147       /* Recompute how much room we have.  */
148       room = obstack_room (obstack);
149       size = room;
150
151       assert (size != 0);
152     }
153
154   _IO_str_init_static_internal ((struct _IO_strfile_ *) &new_f.ofile,
155                                 obstack_base (obstack),
156                                 size, obstack_next_free (obstack));
157   /* Now allocate the rest of the current chunk.  */
158   assert (size == (new_f.ofile.file.file._IO_write_end
159                    - new_f.ofile.file.file._IO_write_base));
160   assert (new_f.ofile.file.file._IO_write_ptr
161           == (new_f.ofile.file.file._IO_write_base
162               + obstack_object_size (obstack)));
163   obstack_blank_fast (obstack, room);
164
165   new_f.ofile.obstack = obstack;
166
167   result = _IO_vfprintf (&new_f.ofile.file.file, format, args);
168
169   /* Shrink the buffer to the space we really currently need.  */
170   obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_ptr
171                                 - new_f.ofile.file.file._IO_write_end));
172
173   return result;
174 }
175 ldbl_weak_alias (_IO_obstack_vprintf, obstack_vprintf)
176
177
178 int
179 _IO_obstack_printf (struct obstack *obstack, const char *format, ...)
180 {
181   int result;
182   va_list ap;
183   va_start (ap, format);
184   result = _IO_obstack_vprintf (obstack, format, ap);
185   va_end (ap);
186   return result;
187 }
188 ldbl_weak_alias (_IO_obstack_printf, obstack_printf)