Back to index

glibc  2.9
obprintf.c
Go to the documentation of this file.
00001 /* Print output of stream to given obstack.
00002    Copyright (C) 1996,1997,1999,2000,2001,2002,2003,2004,2005,2006,2008
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 
00023 #ifdef __STDC__
00024 #include <stdlib.h>
00025 #endif
00026 #include "libioP.h"
00027 #include "strfile.h"
00028 #include <assert.h>
00029 #include <string.h>
00030 #include <errno.h>
00031 #include <obstack.h>
00032 #include <stdarg.h>
00033 #include <stdio_ext.h>
00034 
00035 
00036 struct _IO_obstack_file
00037 {
00038   struct _IO_FILE_plus file;
00039   struct obstack *obstack;
00040 };
00041 
00042 
00043 static int
00044 _IO_obstack_overflow (_IO_FILE *fp, int c)
00045 {
00046   struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
00047   int size;
00048 
00049   /* Make room for another character.  This might as well allocate a
00050      new chunk a memory and moves the old contents over.  */
00051   assert (c != EOF);
00052   obstack_1grow (obstack, c);
00053 
00054   /* Setup the buffer pointers again.  */
00055   fp->_IO_write_base = obstack_base (obstack);
00056   fp->_IO_write_ptr = obstack_next_free (obstack);
00057   size = obstack_room (obstack);
00058   fp->_IO_write_end = fp->_IO_write_ptr + size;
00059   /* Now allocate the rest of the current chunk.  */
00060   obstack_blank_fast (obstack, size);
00061 
00062   return c;
00063 }
00064 
00065 
00066 static _IO_size_t
00067 _IO_obstack_xsputn (_IO_FILE *fp, const void *data, _IO_size_t n)
00068 {
00069   struct obstack *obstack = ((struct _IO_obstack_file *) fp)->obstack;
00070 
00071   if (fp->_IO_write_ptr + n > fp->_IO_write_end)
00072     {
00073       int size;
00074 
00075       /* We need some more memory.  First shrink the buffer to the
00076         space we really currently need.  */
00077       obstack_blank_fast (obstack, fp->_IO_write_ptr - fp->_IO_write_end);
00078 
00079       /* Now grow for N bytes, and put the data there.  */
00080       obstack_grow (obstack, data, n);
00081 
00082       /* Setup the buffer pointers again.  */
00083       fp->_IO_write_base = obstack_base (obstack);
00084       fp->_IO_write_ptr = obstack_next_free (obstack);
00085       size = obstack_room (obstack);
00086       fp->_IO_write_end = fp->_IO_write_ptr + size;
00087       /* Now allocate the rest of the current chunk.  */
00088       obstack_blank_fast (obstack, size);
00089     }
00090   else
00091     fp->_IO_write_ptr = __mempcpy (fp->_IO_write_ptr, data, n);
00092 
00093   return n;
00094 }
00095 
00096 
00097 /* the jump table.  */
00098 const struct _IO_jump_t _IO_obstack_jumps attribute_hidden =
00099 {
00100   JUMP_INIT_DUMMY,
00101   JUMP_INIT(finish, NULL),
00102   JUMP_INIT(overflow, _IO_obstack_overflow),
00103   JUMP_INIT(underflow, NULL),
00104   JUMP_INIT(uflow, NULL),
00105   JUMP_INIT(pbackfail, NULL),
00106   JUMP_INIT(xsputn, _IO_obstack_xsputn),
00107   JUMP_INIT(xsgetn, NULL),
00108   JUMP_INIT(seekoff, NULL),
00109   JUMP_INIT(seekpos, NULL),
00110   JUMP_INIT(setbuf, NULL),
00111   JUMP_INIT(sync, NULL),
00112   JUMP_INIT(doallocate, NULL),
00113   JUMP_INIT(read, NULL),
00114   JUMP_INIT(write, NULL),
00115   JUMP_INIT(seek, NULL),
00116   JUMP_INIT(close, NULL),
00117   JUMP_INIT(stat, NULL),
00118   JUMP_INIT(showmanyc, NULL),
00119   JUMP_INIT(imbue, NULL)
00120 };
00121 
00122 
00123 int
00124 _IO_obstack_vprintf (struct obstack *obstack, const char *format, va_list args)
00125 {
00126   struct obstack_FILE
00127     {
00128       struct _IO_obstack_file ofile;
00129   } new_f;
00130   int result;
00131   int size;
00132   int room;
00133 
00134 #ifdef _IO_MTSAFE_IO
00135   new_f.ofile.file.file._lock = NULL;
00136 #endif
00137 
00138   _IO_no_init (&new_f.ofile.file.file, _IO_USER_LOCK, -1, NULL, NULL);
00139   _IO_JUMPS (&new_f.ofile.file) = &_IO_obstack_jumps;
00140   room = obstack_room (obstack);
00141   size = obstack_object_size (obstack) + room;
00142   if (size == 0)
00143     {
00144       /* We have to handle the allocation a bit different since the
00145         `_IO_str_init_static' function would handle a size of zero
00146         different from what we expect.  */
00147 
00148       /* Get more memory.  */
00149       obstack_make_room (obstack, 64);
00150 
00151       /* Recompute how much room we have.  */
00152       room = obstack_room (obstack);
00153       size = room;
00154 
00155       assert (size != 0);
00156     }
00157 
00158   _IO_str_init_static_internal ((struct _IO_strfile_ *) &new_f.ofile,
00159                             obstack_base (obstack),
00160                             size, obstack_next_free (obstack));
00161   /* Now allocate the rest of the current chunk.  */
00162   assert (size == (new_f.ofile.file.file._IO_write_end
00163                  - new_f.ofile.file.file._IO_write_base));
00164   assert (new_f.ofile.file.file._IO_write_ptr
00165          == (new_f.ofile.file.file._IO_write_base
00166              + obstack_object_size (obstack)));
00167   obstack_blank_fast (obstack, room);
00168 
00169   new_f.ofile.obstack = obstack;
00170 
00171   result = INTUSE(_IO_vfprintf) (&new_f.ofile.file.file, format, args);
00172 
00173   /* Shrink the buffer to the space we really currently need.  */
00174   obstack_blank_fast (obstack, (new_f.ofile.file.file._IO_write_ptr
00175                             - new_f.ofile.file.file._IO_write_end));
00176 
00177   return result;
00178 }
00179 ldbl_weak_alias (_IO_obstack_vprintf, obstack_vprintf)
00180 
00181 
00182 int
00183 _IO_obstack_printf (struct obstack *obstack, const char *format, ...)
00184 {
00185   int result;
00186   va_list ap;
00187   va_start (ap, format);
00188   result = _IO_obstack_vprintf (obstack, format, ap);
00189   va_end (ap);
00190   return result;
00191 }
00192 ldbl_weak_alias (_IO_obstack_printf, obstack_printf)