WvStreams
argp-fmtstream.h
00001 /* Word-wrapping and line-truncating streams.
00002    Copyright (C) 1997, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Miles Bader <miles@gnu.ai.mit.edu>.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public License as
00008    published by the Free Software Foundation; either version 2 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00018    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 /* This package emulates glibc `line_wrap_stream' semantics for systems that
00022    don't have that.  If the system does have it, it is just a wrapper for
00023    that.  This header file is only used internally while compiling argp, and
00024    shouldn't be installed.  */
00025 
00026 #ifndef _ARGP_FMTSTREAM_H
00027 #define _ARGP_FMTSTREAM_H
00028 
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 
00033 #if _LIBC || (defined (HAVE_FLOCKFILE) && defined(HAVE_PUTC_UNLOCKED) \
00034      && defined (HAVE_FPUTS_UNLOCKED) && defined (HAVE_FWRITE_UNLOCKED) )
00035 /* Use locking funxtions */
00036 # define FLOCKFILE(f) flockfile(f)
00037 # define FUNLOCKFILE(f) funlockfile(f)
00038 # define PUTC_UNLOCKED(c, f) putc_unlocked((c), (f))
00039 # define FPUTS_UNLOCKED(s, f) fputs_unlocked((s), (f))
00040 # define FWRITE_UNLOCKED(b, s, n, f) fwrite_unlocked((b), (s), (n), (f))
00041 #else
00042 /* Disable stdio locking */
00043 # define FLOCKFILE(f)
00044 # define FUNLOCKFILE(f)
00045 #ifndef _WIN32
00046 # define PUTC_UNLOCKED(c, f) putc((c), (f))
00047 #else
00048 /* Mingw does something really dumb with putc (probably evaluating the 'stream'
00049  * argument to it, which putc can technically do by the spec), which causes it
00050  * to fatally abort.  If we use fputc, this problem goes away
00051  */
00052 # define PUTC_UNLOCKED(c, f) fputc((c), (f))
00053 #endif
00054 # define FPUTS_UNLOCKED(s, f) fputs((s), (f))
00055 # define FWRITE_UNLOCKED(b, s, n, f) fwrite((b), (s), (n), (f))
00056 #endif /* No thread safe i/o */
00057 
00058 #if    (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
00059     || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
00060 /* line_wrap_stream is available, so use that.  */
00061 #define ARGP_FMTSTREAM_USE_LINEWRAP
00062 #endif
00063 
00064 #ifdef ARGP_FMTSTREAM_USE_LINEWRAP
00065 /* Just be a simple wrapper for line_wrap_stream; the semantics are
00066    *slightly* different, as line_wrap_stream doesn't actually make a new
00067    object, it just modifies the given stream (reversibly) to do
00068    line-wrapping.  Since we control who uses this code, it doesn't matter.  */
00069 
00070 #include <linewrap.h>
00071 
00072 typedef FILE *argp_fmtstream_t;
00073 
00074 #define argp_make_fmtstream line_wrap_stream
00075 #define __argp_make_fmtstream line_wrap_stream
00076 #define argp_fmtstream_free line_unwrap_stream
00077 #define __argp_fmtstream_free line_unwrap_stream
00078 
00079 #define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
00080 #define argp_fmtstream_putc(fs,ch) putc(ch,fs)
00081 #define __argp_fmtstream_puts(fs,str) fputs(str,fs)
00082 #define argp_fmtstream_puts(fs,str) fputs(str,fs)
00083 #define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
00084 #define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
00085 #define __argp_fmtstream_printf fprintf
00086 #define argp_fmtstream_printf fprintf
00087 
00088 #define __argp_fmtstream_lmargin line_wrap_lmargin
00089 #define argp_fmtstream_lmargin line_wrap_lmargin
00090 #define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
00091 #define argp_fmtstream_set_lmargin line_wrap_set_lmargin
00092 #define __argp_fmtstream_rmargin line_wrap_rmargin
00093 #define argp_fmtstream_rmargin line_wrap_rmargin
00094 #define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
00095 #define argp_fmtstream_set_rmargin line_wrap_set_rmargin
00096 #define __argp_fmtstream_wmargin line_wrap_wmargin
00097 #define argp_fmtstream_wmargin line_wrap_wmargin
00098 #define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
00099 #define argp_fmtstream_set_wmargin line_wrap_set_wmargin
00100 #define __argp_fmtstream_point line_wrap_point
00101 #define argp_fmtstream_point line_wrap_point
00102 
00103 #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
00104 /* Guess we have to define our own version.  */
00105 
00106 #ifndef __const
00107 #define __const const
00108 #endif
00109 
00110 
00111 struct argp_fmtstream
00112 {
00113   FILE *stream;                 /* The stream we're outputting to.  */
00114 
00115   size_t lmargin, rmargin;      /* Left and right margins.  */
00116   ssize_t wmargin;              /* Margin to wrap to, or -1 to truncate.  */
00117 
00118   /* Point in buffer to which we've processed for wrapping, but not output.  */
00119   size_t point_offs;
00120   /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin.  */
00121   ssize_t point_col;
00122 
00123   char *buf;                    /* Output buffer.  */
00124   char *p;                      /* Current end of text in BUF. */
00125   char *end;                    /* Absolute end of BUF.  */
00126 };
00127 
00128 typedef struct argp_fmtstream *argp_fmtstream_t;
00129 
00130 /* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
00131    written on it with LMARGIN spaces and limits them to RMARGIN columns
00132    total.  If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
00133    replacing the whitespace before them with a newline and WMARGIN spaces.
00134    Otherwise, chars beyond RMARGIN are simply dropped until a newline.
00135    Returns NULL if there was an error.  */
00136 extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
00137                                                size_t __lmargin,
00138                                                size_t __rmargin,
00139                                                ssize_t __wmargin);
00140 extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
00141                                              size_t __lmargin,
00142                                              size_t __rmargin,
00143                                              ssize_t __wmargin);
00144 
00145 /* Flush __FS to its stream, and free it (but don't close the stream).  */
00146 extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
00147 extern void argp_fmtstream_free (argp_fmtstream_t __fs);
00148 
00149 extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
00150                                        __const char *__fmt, ...)
00151      PRINTF_STYLE(2,3);
00152 extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
00153                                       __const char *__fmt, ...)
00154      PRINTF_STYLE(2,3);
00155 
00156 extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
00157 extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
00158 
00159 extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
00160 extern int argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str);
00161 
00162 extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
00163                                       __const char *__str, size_t __len);
00164 extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
00165                                     __const char *__str, size_t __len);
00166 
00167 /* Access macros for various bits of state.  */
00168 #define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
00169 #define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
00170 #define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
00171 #define __argp_fmtstream_lmargin argp_fmtstream_lmargin
00172 #define __argp_fmtstream_rmargin argp_fmtstream_rmargin
00173 #define __argp_fmtstream_wmargin argp_fmtstream_wmargin
00174 
00175 /* Set __FS's left margin to LMARGIN and return the old value.  */
00176 extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
00177                                           size_t __lmargin);
00178 extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
00179                                             size_t __lmargin);
00180 
00181 /* Set __FS's right margin to __RMARGIN and return the old value.  */
00182 extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
00183                                           size_t __rmargin);
00184 extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
00185                                             size_t __rmargin);
00186 
00187 /* Set __FS's wrap margin to __WMARGIN and return the old value.  */
00188 extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
00189                                           size_t __wmargin);
00190 extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
00191                                             size_t __wmargin);
00192 
00193 /* Return the column number of the current output point in __FS.  */
00194 extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
00195 extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
00196 
00197 /* Internal routines.  */
00198 extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
00199 extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
00200 extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
00201 extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
00202 
00203 #ifdef __OPTIMIZE__
00204 /* Inline versions of above routines.  */
00205 
00206 #if !_LIBC
00207 #define __argp_fmtstream_putc argp_fmtstream_putc
00208 #define __argp_fmtstream_puts argp_fmtstream_puts
00209 #define __argp_fmtstream_write argp_fmtstream_write
00210 #define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
00211 #define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
00212 #define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
00213 #define __argp_fmtstream_point argp_fmtstream_point
00214 #define __argp_fmtstream_update _argp_fmtstream_update
00215 #define __argp_fmtstream_ensure _argp_fmtstream_ensure
00216 #endif
00217 
00218 #ifndef ARGP_FS_EI
00219 #define ARGP_FS_EI extern inline
00220 #endif
00221 
00222 ARGP_FS_EI size_t
00223 __argp_fmtstream_write (argp_fmtstream_t __fs,
00224                         __const char *__str, size_t __len)
00225 {
00226   if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
00227     {
00228       memcpy (__fs->p, __str, __len);
00229       __fs->p += __len;
00230       return __len;
00231     }
00232   else
00233     return 0;
00234 }
00235 
00236 ARGP_FS_EI int
00237 __argp_fmtstream_puts (argp_fmtstream_t __fs, __const char *__str)
00238 {
00239   size_t __len = strlen (__str);
00240   if (__len)
00241     {
00242       size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
00243       return __wrote == __len ? 0 : -1;
00244     }
00245   else
00246     return 0;
00247 }
00248 
00249 ARGP_FS_EI int
00250 __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
00251 {
00252   if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
00253     return *__fs->p++ = __ch;
00254   else
00255     return EOF;
00256 }
00257 
00258 /* Set __FS's left margin to __LMARGIN and return the old value.  */
00259 ARGP_FS_EI size_t
00260 __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
00261 {
00262   size_t __old;
00263   if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
00264     __argp_fmtstream_update (__fs);
00265   __old = __fs->lmargin;
00266   __fs->lmargin = __lmargin;
00267   return __old;
00268 }
00269 
00270 /* Set __FS's right margin to __RMARGIN and return the old value.  */
00271 ARGP_FS_EI size_t
00272 __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
00273 {
00274   size_t __old;
00275   if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
00276     __argp_fmtstream_update (__fs);
00277   __old = __fs->rmargin;
00278   __fs->rmargin = __rmargin;
00279   return __old;
00280 }
00281 
00282 /* Set FS's wrap margin to __WMARGIN and return the old value.  */
00283 ARGP_FS_EI size_t
00284 __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
00285 {
00286   size_t __old;
00287   if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
00288     __argp_fmtstream_update (__fs);
00289   __old = __fs->wmargin;
00290   __fs->wmargin = __wmargin;
00291   return __old;
00292 }
00293 
00294 /* Return the column number of the current output point in __FS.  */
00295 ARGP_FS_EI size_t
00296 __argp_fmtstream_point (argp_fmtstream_t __fs)
00297 {
00298   if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
00299     __argp_fmtstream_update (__fs);
00300   return __fs->point_col >= 0 ? __fs->point_col : 0;
00301 }
00302 
00303 #if !_LIBC
00304 #undef __argp_fmtstream_putc
00305 #undef __argp_fmtstream_puts
00306 #undef __argp_fmtstream_write
00307 #undef __argp_fmtstream_set_lmargin
00308 #undef __argp_fmtstream_set_rmargin
00309 #undef __argp_fmtstream_set_wmargin
00310 #undef __argp_fmtstream_point
00311 #undef __argp_fmtstream_update
00312 #undef __argp_fmtstream_ensure
00313 #endif
00314 
00315 #endif /* __OPTIMIZE__ */
00316 
00317 #endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
00318 
00319 #endif /* argp-fmtstream.h */