1/* Word-wrapping and line-truncating streams. 2 Copyright (C) 1997, 2006 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Written by Miles Bader <miles@gnu.ai.mit.edu>. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program 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 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along 17 with this program; if not, write to the Free Software Foundation, 18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19 20/* This package emulates glibc `line_wrap_stream' semantics for systems that 21 don't have that. If the system does have it, it is just a wrapper for 22 that. This header file is only used internally while compiling argp, and 23 shouldn't be installed. */ 24 25#ifndef _ARGP_FMTSTREAM_H 26#define _ARGP_FMTSTREAM_H 27 28#include <stdio.h> 29#include <string.h> 30#include <unistd.h> 31 32#ifndef __attribute__ 33/* This feature is available in gcc versions 2.5 and later. */ 34# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ 35# define __attribute__(Spec) /* empty */ 36# endif 37/* The __-protected variants of `format' and `printf' attributes 38 are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ 39# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) || __STRICT_ANSI__ 40# define __format__ format 41# define __printf__ printf 42# endif 43#endif 44 45#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ 46 || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) 47/* line_wrap_stream is available, so use that. */ 48#define ARGP_FMTSTREAM_USE_LINEWRAP 49#endif 50 51#ifdef ARGP_FMTSTREAM_USE_LINEWRAP 52/* Just be a simple wrapper for line_wrap_stream; the semantics are 53 *slightly* different, as line_wrap_stream doesn't actually make a new 54 object, it just modifies the given stream (reversibly) to do 55 line-wrapping. Since we control who uses this code, it doesn't matter. */ 56 57#include <linewrap.h> 58 59typedef FILE *argp_fmtstream_t; 60 61#define argp_make_fmtstream line_wrap_stream 62#define __argp_make_fmtstream line_wrap_stream 63#define argp_fmtstream_free line_unwrap_stream 64#define __argp_fmtstream_free line_unwrap_stream 65 66#define __argp_fmtstream_putc(fs,ch) putc(ch,fs) 67#define argp_fmtstream_putc(fs,ch) putc(ch,fs) 68#define __argp_fmtstream_puts(fs,str) fputs(str,fs) 69#define argp_fmtstream_puts(fs,str) fputs(str,fs) 70#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) 71#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) 72#define __argp_fmtstream_printf fprintf 73#define argp_fmtstream_printf fprintf 74 75#define __argp_fmtstream_lmargin line_wrap_lmargin 76#define argp_fmtstream_lmargin line_wrap_lmargin 77#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin 78#define argp_fmtstream_set_lmargin line_wrap_set_lmargin 79#define __argp_fmtstream_rmargin line_wrap_rmargin 80#define argp_fmtstream_rmargin line_wrap_rmargin 81#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin 82#define argp_fmtstream_set_rmargin line_wrap_set_rmargin 83#define __argp_fmtstream_wmargin line_wrap_wmargin 84#define argp_fmtstream_wmargin line_wrap_wmargin 85#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin 86#define argp_fmtstream_set_wmargin line_wrap_set_wmargin 87#define __argp_fmtstream_point line_wrap_point 88#define argp_fmtstream_point line_wrap_point 89 90#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ 91/* Guess we have to define our own version. */ 92 93struct argp_fmtstream 94{ 95 FILE *stream; /* The stream we're outputting to. */ 96 97 size_t lmargin, rmargin; /* Left and right margins. */ 98 ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ 99 100 /* Point in buffer to which we've processed for wrapping, but not output. */ 101 size_t point_offs; 102 /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ 103 ssize_t point_col; 104 105 char *buf; /* Output buffer. */ 106 char *p; /* Current end of text in BUF. */ 107 char *end; /* Absolute end of BUF. */ 108}; 109 110typedef struct argp_fmtstream *argp_fmtstream_t; 111 112/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines 113 written on it with LMARGIN spaces and limits them to RMARGIN columns 114 total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by 115 replacing the whitespace before them with a newline and WMARGIN spaces. 116 Otherwise, chars beyond RMARGIN are simply dropped until a newline. 117 Returns NULL if there was an error. */ 118extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, 119 size_t __lmargin, 120 size_t __rmargin, 121 ssize_t __wmargin); 122extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, 123 size_t __lmargin, 124 size_t __rmargin, 125 ssize_t __wmargin); 126 127/* Flush __FS to its stream, and free it (but don't close the stream). */ 128extern void __argp_fmtstream_free (argp_fmtstream_t __fs); 129extern void argp_fmtstream_free (argp_fmtstream_t __fs); 130 131extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, 132 const char *__fmt, ...) 133 __attribute__ ((__format__ (printf, 2, 3))); 134extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, 135 const char *__fmt, ...) 136 __attribute__ ((__format__ (printf, 2, 3))); 137 138extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); 139extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); 140 141extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); 142extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); 143 144extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, 145 const char *__str, size_t __len); 146extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, 147 const char *__str, size_t __len); 148 149/* Access macros for various bits of state. */ 150#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) 151#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) 152#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) 153#define __argp_fmtstream_lmargin argp_fmtstream_lmargin 154#define __argp_fmtstream_rmargin argp_fmtstream_rmargin 155#define __argp_fmtstream_wmargin argp_fmtstream_wmargin 156 157/* Set __FS's left margin to LMARGIN and return the old value. */ 158extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, 159 size_t __lmargin); 160extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, 161 size_t __lmargin); 162 163/* Set __FS's right margin to __RMARGIN and return the old value. */ 164extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, 165 size_t __rmargin); 166extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, 167 size_t __rmargin); 168 169/* Set __FS's wrap margin to __WMARGIN and return the old value. */ 170extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, 171 size_t __wmargin); 172extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, 173 size_t __wmargin); 174 175/* Return the column number of the current output point in __FS. */ 176extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); 177extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); 178 179/* Internal routines. */ 180extern void _argp_fmtstream_update (argp_fmtstream_t __fs); 181extern void __argp_fmtstream_update (argp_fmtstream_t __fs); 182extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); 183extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); 184 185#ifdef __OPTIMIZE__ 186/* Inline versions of above routines. */ 187 188#if !_LIBC 189#define __argp_fmtstream_putc argp_fmtstream_putc 190#define __argp_fmtstream_puts argp_fmtstream_puts 191#define __argp_fmtstream_write argp_fmtstream_write 192#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin 193#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin 194#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin 195#define __argp_fmtstream_point argp_fmtstream_point 196#define __argp_fmtstream_update _argp_fmtstream_update 197#define __argp_fmtstream_ensure _argp_fmtstream_ensure 198#endif 199 200#ifndef ARGP_FS_EI 201#define ARGP_FS_EI extern inline __attribute__ ((__gnu_inline__)) 202#endif 203 204ARGP_FS_EI size_t 205__argp_fmtstream_write (argp_fmtstream_t __fs, 206 const char *__str, size_t __len) 207{ 208 if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) 209 { 210 memcpy (__fs->p, __str, __len); 211 __fs->p += __len; 212 return __len; 213 } 214 else 215 return 0; 216} 217 218ARGP_FS_EI int 219__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) 220{ 221 size_t __len = strlen (__str); 222 if (__len) 223 { 224 size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); 225 return __wrote == __len ? 0 : -1; 226 } 227 else 228 return 0; 229} 230 231ARGP_FS_EI int 232__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) 233{ 234 if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) 235 return *__fs->p++ = __ch; 236 else 237 return EOF; 238} 239 240/* Set __FS's left margin to __LMARGIN and return the old value. */ 241ARGP_FS_EI size_t 242__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) 243{ 244 size_t __old; 245 if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) 246 __argp_fmtstream_update (__fs); 247 __old = __fs->lmargin; 248 __fs->lmargin = __lmargin; 249 return __old; 250} 251 252/* Set __FS's right margin to __RMARGIN and return the old value. */ 253ARGP_FS_EI size_t 254__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) 255{ 256 size_t __old; 257 if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) 258 __argp_fmtstream_update (__fs); 259 __old = __fs->rmargin; 260 __fs->rmargin = __rmargin; 261 return __old; 262} 263 264/* Set FS's wrap margin to __WMARGIN and return the old value. */ 265ARGP_FS_EI size_t 266__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) 267{ 268 size_t __old; 269 if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) 270 __argp_fmtstream_update (__fs); 271 __old = __fs->wmargin; 272 __fs->wmargin = __wmargin; 273 return __old; 274} 275 276/* Return the column number of the current output point in __FS. */ 277ARGP_FS_EI size_t 278__argp_fmtstream_point (argp_fmtstream_t __fs) 279{ 280 if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) 281 __argp_fmtstream_update (__fs); 282 return __fs->point_col >= 0 ? __fs->point_col : 0; 283} 284 285#if !_LIBC 286#undef __argp_fmtstream_putc 287#undef __argp_fmtstream_puts 288#undef __argp_fmtstream_write 289#undef __argp_fmtstream_set_lmargin 290#undef __argp_fmtstream_set_rmargin 291#undef __argp_fmtstream_set_wmargin 292#undef __argp_fmtstream_point 293#undef __argp_fmtstream_update 294#undef __argp_fmtstream_ensure 295#endif 296 297#endif /* __OPTIMIZE__ */ 298 299#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ 300 301#endif /* argp-fmtstream.h */ 302