00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include <config.h>
00025 #endif
00026
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <errno.h>
00030 #include <stdarg.h>
00031 #include <ctype.h>
00032
00033 #include "argp-fmtstream.h"
00034 #include "argp-namefrob.h"
00035
00036 #ifndef ARGP_FMTSTREAM_USE_LINEWRAP
00037
00038 #ifndef isblank
00039 #define isblank(ch) ((ch)==' ' || (ch)=='\t')
00040 #endif
00041
00042 #if defined _LIBC && defined USE_IN_LIBIO
00043 # include <wchar.h>
00044 # include <libio/libioP.h>
00045 # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
00046 #endif
00047
00048 #define INIT_BUF_SIZE 200
00049 #define PRINTF_SIZE_GUESS 150
00050
00051
00052
00053
00054
00055
00056
00057 argp_fmtstream_t
00058 __argp_make_fmtstream (FILE *stream,
00059 size_t lmargin, size_t rmargin, ssize_t wmargin)
00060 {
00061 argp_fmtstream_t fs;
00062
00063 fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
00064 if (fs != NULL)
00065 {
00066 fs->stream = stream;
00067
00068 fs->lmargin = lmargin;
00069 fs->rmargin = rmargin;
00070 fs->wmargin = wmargin;
00071 fs->point_col = 0;
00072 fs->point_offs = 0;
00073
00074 fs->buf = (char *) malloc (INIT_BUF_SIZE);
00075 if (! fs->buf)
00076 {
00077 free (fs);
00078 fs = 0;
00079 }
00080 else
00081 {
00082 fs->p = fs->buf;
00083 fs->end = fs->buf + INIT_BUF_SIZE;
00084 }
00085 }
00086
00087 return fs;
00088 }
00089 #if 0
00090
00091 #ifdef weak_alias
00092 weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
00093 #endif
00094 #endif
00095
00096
00097 void
00098 __argp_fmtstream_free (argp_fmtstream_t fs)
00099 {
00100 __argp_fmtstream_update (fs);
00101 if (fs->p > fs->buf)
00102 {
00103 #ifdef USE_IN_LIBIO
00104 __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
00105 #else
00106 fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
00107 #endif
00108 }
00109 free (fs->buf);
00110 free (fs);
00111 }
00112 #if 0
00113
00114 #ifdef weak_alias
00115 weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
00116 #endif
00117 #endif
00118
00119
00120
00121 void
00122 __argp_fmtstream_update (argp_fmtstream_t fs)
00123 {
00124 char *buf, *nl;
00125 size_t len;
00126
00127
00128 buf = fs->buf + fs->point_offs;
00129 while (buf < fs->p)
00130 {
00131 size_t r;
00132
00133 if (fs->point_col == 0 && fs->lmargin != 0)
00134 {
00135
00136 const size_t pad = fs->lmargin;
00137 if (fs->p + pad < fs->end)
00138 {
00139
00140
00141 memmove (buf + pad, buf, fs->p - buf);
00142 fs->p += pad;
00143 memset (buf, ' ', pad);
00144 buf += pad;
00145 }
00146 else
00147 {
00148
00149 size_t i;
00150 for (i = 0; i < pad; i++)
00151 {
00152 #ifdef USE_IN_LIBIO
00153 if (_IO_fwide (fs->stream, 0) > 0)
00154 putwc_unlocked (L' ', fs->stream);
00155 else
00156 #endif
00157 putc_unlocked (' ', fs->stream);
00158 }
00159 }
00160 fs->point_col = pad;
00161 }
00162
00163 len = fs->p - buf;
00164 nl = memchr (buf, '\n', len);
00165
00166 if (fs->point_col < 0)
00167 fs->point_col = 0;
00168
00169 if (!nl)
00170 {
00171
00172
00173 if (fs->point_col + len < fs->rmargin)
00174 {
00175
00176
00177
00178 fs->point_col += len;
00179 break;
00180 }
00181 else
00182
00183
00184 nl = fs->p;
00185 }
00186 else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
00187 {
00188
00189
00190 fs->point_col = 0;
00191 buf = nl + 1;
00192 continue;
00193 }
00194
00195
00196 r = fs->rmargin - 1;
00197
00198 if (fs->wmargin < 0)
00199 {
00200
00201
00202 if (nl < fs->p)
00203 {
00204 memmove (buf + (r - fs->point_col), nl, fs->p - nl);
00205 fs->p -= buf + (r - fs->point_col) - nl;
00206
00207 fs->point_col = 0;
00208 buf += r + 1;
00209 }
00210 else
00211 {
00212
00213
00214
00215 fs->point_col += len;
00216 fs->p -= fs->point_col - r;
00217 break;
00218 }
00219 }
00220 else
00221 {
00222
00223
00224
00225
00226 char *p, *nextline;
00227 int i;
00228
00229 p = buf + (r + 1 - fs->point_col);
00230 while (p >= buf && !isblank (*p))
00231 --p;
00232 nextline = p + 1;
00233
00234 if (nextline > buf)
00235 {
00236
00237 if (p >= buf)
00238 do
00239 --p;
00240 while (p >= buf && isblank (*p));
00241 nl = p + 1;
00242 }
00243 else
00244 {
00245
00246
00247 p = buf + (r + 1 - fs->point_col);
00248
00249 do
00250 ++p;
00251 while (p < nl && !isblank (*p));
00252 if (p == nl)
00253 {
00254
00255 fs->point_col = 0;
00256 buf = nl + 1;
00257 continue;
00258 }
00259
00260 nl = p;
00261
00262 do
00263 ++p;
00264 while (isblank (*p));
00265
00266 nextline = p;
00267 }
00268
00269
00270
00271
00272
00273
00274 if ((nextline == buf + len + 1
00275 ? fs->end - nl < fs->wmargin + 1
00276 : nextline - (nl + 1) < fs->wmargin)
00277 && fs->p > nextline)
00278 {
00279
00280 if (fs->end - fs->p > fs->wmargin + 1)
00281
00282 {
00283 size_t mv = fs->p - nextline;
00284 memmove (nl + 1 + fs->wmargin, nextline, mv);
00285 nextline = nl + 1 + fs->wmargin;
00286 len = nextline + mv - buf;
00287 *nl++ = '\n';
00288 }
00289 else
00290
00291 {
00292 #ifdef _LIBC
00293 __fxprintf (fs->stream, "%.*s\n",
00294 (int) (nl - fs->buf), fs->buf);
00295 #else
00296 if (nl > fs->buf)
00297 fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
00298 putc_unlocked ('\n', fs->stream);
00299 #endif
00300
00301 len += buf - fs->buf;
00302 nl = buf = fs->buf;
00303 }
00304 }
00305 else
00306
00307
00308 *nl++ = '\n';
00309
00310 if (nextline - nl >= fs->wmargin
00311 || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
00312
00313 for (i = 0; i < fs->wmargin; ++i)
00314 *nl++ = ' ';
00315 else
00316 for (i = 0; i < fs->wmargin; ++i)
00317 #ifdef USE_IN_LIBIO
00318 if (_IO_fwide (fs->stream, 0) > 0)
00319 putwc_unlocked (L' ', fs->stream);
00320 else
00321 #endif
00322 putc_unlocked (' ', fs->stream);
00323
00324
00325
00326 if (nl < nextline)
00327 memmove (nl, nextline, buf + len - nextline);
00328 len -= nextline - buf;
00329
00330
00331 buf = nl;
00332
00333
00334 fs->p = nl + len;
00335
00336
00337
00338
00339 fs->point_col = fs->wmargin ? fs->wmargin : -1;
00340 }
00341 }
00342
00343
00344 fs->point_offs = fs->p - fs->buf;
00345 }
00346
00347
00348
00349 int
00350 __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
00351 {
00352 if ((size_t) (fs->end - fs->p) < amount)
00353 {
00354 ssize_t wrote;
00355
00356
00357 __argp_fmtstream_update (fs);
00358
00359 #ifdef _LIBC
00360 __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
00361 wrote = fs->p - fs->buf;
00362 #else
00363 wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
00364 #endif
00365 if (wrote == fs->p - fs->buf)
00366 {
00367 fs->p = fs->buf;
00368 fs->point_offs = 0;
00369 }
00370 else
00371 {
00372 fs->p -= wrote;
00373 fs->point_offs -= wrote;
00374 memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
00375 return 0;
00376 }
00377
00378 if ((size_t) (fs->end - fs->buf) < amount)
00379
00380 {
00381 size_t old_size = fs->end - fs->buf;
00382 size_t new_size = old_size + amount;
00383 char *new_buf;
00384
00385 if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
00386 {
00387 __set_errno (ENOMEM);
00388 return 0;
00389 }
00390
00391 fs->buf = new_buf;
00392 fs->end = new_buf + new_size;
00393 fs->p = fs->buf;
00394 }
00395 }
00396
00397 return 1;
00398 }
00399
00400 ssize_t
00401 __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
00402 {
00403 int out;
00404 size_t avail;
00405 size_t size_guess = PRINTF_SIZE_GUESS;
00406
00407 do
00408 {
00409 va_list args;
00410
00411 if (! __argp_fmtstream_ensure (fs, size_guess))
00412 return -1;
00413
00414 va_start (args, fmt);
00415 avail = fs->end - fs->p;
00416 out = __vsnprintf (fs->p, avail, fmt, args);
00417 va_end (args);
00418 if ((size_t) out >= avail)
00419 size_guess = out + 1;
00420 }
00421 while ((size_t) out >= avail);
00422
00423 fs->p += out;
00424
00425 return out;
00426 }
00427 #if 0
00428
00429 #ifdef weak_alias
00430 weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
00431 #endif
00432 #endif
00433
00434 #endif