34 #include "argp-fmtstream.h"
35 #include "argp-namefrob.h"
37 #ifndef ARGP_FMTSTREAM_USE_LINEWRAP
40 #define isblank(ch) ((ch)==' ' || (ch)=='\t')
43 #if defined _LIBC && defined USE_IN_LIBIO
44 # include <libio/libioP.h>
45 # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
48 #define INIT_BUF_SIZE 200
49 #define PRINTF_SIZE_GUESS 150
58 __argp_make_fmtstream (FILE *stream,
59 size_t lmargin,
size_t rmargin, ssize_t wmargin)
66 fs->lmargin = lmargin;
67 fs->rmargin = rmargin;
68 fs->wmargin = wmargin;
72 fs->buf = malloc (INIT_BUF_SIZE);
81 fs->end = fs->buf + INIT_BUF_SIZE;
88 weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
95 __argp_fmtstream_update (fs);
97 FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream);
102 weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
114 buf = fs->buf + fs->point_offs;
119 if (fs->point_col == 0 && fs->lmargin != 0)
122 const size_t pad = fs->lmargin;
123 if (fs->p + pad < fs->end)
127 memmove (buf + pad, buf, fs->p - buf);
129 memset (buf,
' ', pad);
136 for (i = 0; i < pad; i++)
137 PUTC_UNLOCKED (
' ', fs->stream);
143 nl = memchr (buf,
'\n', len);
145 if (fs->point_col < 0)
152 if (fs->point_col + len < fs->rmargin)
157 fs->point_col += len;
165 else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
183 memmove (buf + (r - fs->point_col), nl, fs->p - nl);
184 fs->p -= buf + (r - fs->point_col) - nl;
194 fs->point_col += len;
195 fs->p -= fs->point_col - r;
208 p = buf + (r + 1 - fs->point_col);
209 while (p >= buf && !isblank (*p))
219 while (p >= buf && isblank (*p));
226 p = buf + (r + 1 - fs->point_col);
230 while (p < nl && !isblank (*p));
243 while (isblank (*p));
253 if (nextline == buf + len + 1
254 ? fs->end - nl < fs->wmargin + 1
255 : nextline - (nl + 1) < fs->wmargin)
258 if (fs->end - fs->p > fs->wmargin + 1)
261 size_t mv = fs->p - nextline;
262 memmove (nl + 1 + fs->wmargin, nextline, mv);
263 nextline = nl + 1 + fs->wmargin;
264 len = nextline + mv - buf;
271 FWRITE_UNLOCKED (fs->buf, 1, nl - fs->buf, fs->stream);
272 PUTC_UNLOCKED (
'\n', fs->stream);
273 len += buf - fs->buf;
282 if (nextline - nl >= fs->wmargin
283 || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
285 for (i = 0; i < fs->wmargin; ++i)
288 for (i = 0; i < fs->wmargin; ++i)
289 PUTC_UNLOCKED (
' ', fs->stream);
294 memmove (nl, nextline, buf + len - nextline);
295 len -= nextline - buf;
306 fs->point_col = fs->wmargin ? fs->wmargin : -1;
311 fs->point_offs = fs->p - fs->buf;
317 __argp_fmtstream_ensure (
struct argp_fmtstream *fs,
size_t amount)
319 if ((
size_t) (fs->end - fs->p) < amount)
324 __argp_fmtstream_update (fs);
326 wrote = FWRITE_UNLOCKED (fs->buf, 1, fs->p - fs->buf, fs->stream);
327 if (wrote == fs->p - fs->buf)
335 fs->point_offs -= wrote;
336 memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
340 if ((
size_t) (fs->end - fs->buf) < amount)
343 size_t new_size = fs->end - fs->buf + amount;
344 char *new_buf = realloc (fs->buf, new_size);
348 __set_errno (ENOMEM);
353 fs->end = new_buf + new_size;
362 __argp_fmtstream_printf (
struct argp_fmtstream *fs,
const char *fmt, ...)
366 size_t size_guess = PRINTF_SIZE_GUESS;
372 if (! __argp_fmtstream_ensure (fs, size_guess))
375 va_start (args, fmt);
376 avail = fs->end - fs->p;
377 out = __vsnprintf (fs->p, avail, fmt, args);
380 size_guess = out + 1;
382 while (out >= avail);
389 weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
396 __const
char *__str,
size_t __len)
398 if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
400 memcpy (__fs->p, __str, __len);
411 size_t __len = strlen (__str);
414 size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
415 return __wrote == __len ? 0 : -1;
424 if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
425 return *__fs->p++ = __ch;
435 if ((
size_t) (__fs->p - __fs->buf) > __fs->point_offs)
436 __argp_fmtstream_update (__fs);
437 __old = __fs->lmargin;
438 __fs->lmargin = __lmargin;
447 if ((
size_t) (__fs->p - __fs->buf) > __fs->point_offs)
448 __argp_fmtstream_update (__fs);
449 __old = __fs->rmargin;
450 __fs->rmargin = __rmargin;
459 if ((
size_t) (__fs->p - __fs->buf) > __fs->point_offs)
460 __argp_fmtstream_update (__fs);
461 __old = __fs->wmargin;
462 __fs->wmargin = __wmargin;
470 if ((
size_t) (__fs->p - __fs->buf) > __fs->point_offs)
471 __argp_fmtstream_update (__fs);
472 return __fs->point_col >= 0 ? __fs->point_col : 0;