1/* Print output of stream to given obstack. 2 Copyright (C) 1996,1997,1999,2000,2001,2002 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, write to the Free 18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19 02111-1307 USA. */ 20 21#include "libioP.h" 22#include <stdlib.h> 23#include <assert.h> 24#include <string.h> 25#include <errno.h> 26#include <obstack.h> 27#include <stdarg.h> 28#include <stdio_ext.h> 29 30 31struct _IO_obstack_file 32{ 33 struct _IO_FILE_plus file; 34 struct obstack *obstack; 35}; 36 37 38static int 39_IO_obstack_overflow (_IO_FILE *fp, int c) 40{ 41 struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack; 42 int size; 43 44 /* Make room for another character. This might as well allocate a 45 new chunk a memory and moves the old contents over. */ 46 assert (c != EOF); 47 obstack_1grow (obstack, c); 48 49 /* Setup the buffer pointers again. */ 50 fp->_IO_write_base = obstack_base (obstack); 51 fp->_IO_write_ptr = obstack_next_free (obstack); 52 size = obstack_room (obstack); 53 fp->_IO_write_end = fp->_IO_write_ptr + size; 54 /* Now allocate the rest of the current chunk. */ 55 obstack_blank_fast (obstack, size); 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 int size; 69 70 /* We need some more memory. First shrink the buffer to the 71 space we really currently need. */ 72 obstack_blank_fast (obstack, fp->_IO_write_ptr - fp->_IO_write_end); 73 74 /* Now grow for N bytes, and put the data there. */ 75 obstack_grow (obstack, data, n); 76 77 /* Setup the buffer pointers again. */ 78 fp->_IO_write_base = obstack_base (obstack); 79 fp->_IO_write_ptr = obstack_next_free (obstack); 80 size = obstack_room (obstack); 81 fp->_IO_write_end = fp->_IO_write_ptr + size; 82 /* Now allocate the rest of the current chunk. */ 83 obstack_blank_fast (obstack, size); 84 } 85 else 86 fp->_IO_write_ptr = __mempcpy (fp->_IO_write_ptr, data, n); 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 JUMP_INIT(showmanyc, NULL), 114 JUMP_INIT(imbue, NULL) 115}; 116 117 118int 119_IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args) 120{ 121 struct obstack_FILE 122 { 123 struct _IO_obstack_file ofile; 124 } new_f; 125 int result; 126 int size; 127 int room; 128 129#ifdef _IO_MTSAFE_IO 130 new_f.ofile.file.file._lock = NULL; 131#endif 132 133 _IO_no_init (&new_f.ofile.file.file, _IO_USER_LOCK, -1, NULL, NULL); 134 _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps; 135 room = obstack_room (obstack); 136 size = obstack_object_size (obstack) + room; 137 if (size == 0) 138 { 139 /* We have to handle the allocation a bit different since the 140 `_IO_str_init_static' function would handle a size of zero 141 different from what we expect. */ 142 143 /* Get more memory. */ 144 obstack_make_room (obstack, 64); 145 146 /* Recompute how much room we have. */ 147 room = obstack_room (obstack); 148 size = room; 149 150 assert (size != 0); 151 } 152 153 INTUSE(_IO_str_init_static) ((struct _IO_strfile_ *) &new_f.ofile, 154 obstack_base (obstack), 155 size, obstack_next_free (obstack)); 156 /* Now allocate the rest of the current chunk. */ 157 assert (size == (new_f.ofile.file.file._IO_write_end 158 - new_f.ofile.file.file._IO_write_base)); 159 assert (new_f.ofile.file.file._IO_write_ptr 160 == (new_f.ofile.file.file._IO_write_base 161 + obstack_object_size (obstack))); 162 obstack_blank_fast (obstack, room); 163 164 new_f.ofile.obstack = obstack; 165 166 result = INTUSE(_IO_vfprintf) (&new_f.ofile.file.file, format, args); 167 168 /* Shrink the buffer to the space we really currently need. */ 169 obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_ptr 170 - new_f.ofile.file.file._IO_write_end)); 171 172 return result; 173} 174#ifdef weak_alias 175weak_alias (_IO_obstack_vprintf, obstack_vprintf) 176#endif 177 178 179int 180_IO_obstack_printf (struct obstack *obstack, const char *format, ...) 181{ 182 int result; 183 va_list ap; 184 va_start (ap, format); 185 result = _IO_obstack_vprintf (obstack, format, ap); 186 va_end (ap); 187 return result; 188} 189#ifdef weak_alias 190weak_alias (_IO_obstack_printf, obstack_printf) 191#endif 192