WvStreams
|
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 */