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