1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #ifdef HAVE_CONFIG_H
25: # include <config.h>
26: #endif
27:
28: #include <stdlib.h>
29: #include <string.h>
30: #include <errno.h>
31: #include <stdarg.h>
32: #include <ctype.h>
33:
34: #include "argp-fmtstream.h"
35: #include "argp-namefrob.h"
36:
37: #ifndef ARGP_FMTSTREAM_USE_LINEWRAP
38:
39: #ifndef isblank
40: #define isblank(ch) ((ch)==' ' || (ch)=='\t')
41: #endif
42:
43: #if defined _LIBC && defined USE_IN_LIBIO
44: # include <wchar.h>
45: # include <libio/libioP.h>
46: # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
47: #endif
48:
49: #define INIT_BUF_SIZE 200
50: #define PRINTF_SIZE_GUESS 150
51: ^L
52:
53:
54:
55:
56:
57:
58: argp_fmtstream_t
59: __argp_make_fmtstream (FILE *stream,
60: size_t lmargin, size_t rmargin, ssize_t wmargin)
61: {
62: argp_fmtstream_t fs;
63:
64: fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
65: if (fs != NULL)
66: {
67: fs->stream = stream;
68:
69: fs->lmargin = lmargin;
70: fs->rmargin = rmargin;
71: fs->wmargin = wmargin;
72: fs->point_col = 0;
73: fs->point_offs = 0;
74:
75: fs->buf = (char *) malloc (INIT_BUF_SIZE);
76: if (! fs->buf)
77: {
78: free (fs);
79: fs = 0;
80: }
81: else
82: {
83: fs->p = fs->buf;
84: fs->end = fs->buf + INIT_BUF_SIZE;
85: }
86: }
87:
88: return fs;
89: }
90: #if 0
91:
92: #ifdef weak_alias
93: weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
94: #endif
95: #endif
96:
97:
98: void
99: __argp_fmtstream_free (argp_fmtstream_t fs)
100: {
101: __argp_fmtstream_update (fs);
102: if (fs->p > fs->buf)
103: {
104: #ifdef USE_IN_LIBIO
105: __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
106: #else
107: fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
108: #endif
109: }
110: free (fs->buf);
111: free (fs);
112: }
113: #if 0
114:
115: #ifdef weak_alias
116: weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
117: #endif
118: #endif
119: ^L
120:
121:
122: void
123: __argp_fmtstream_update (argp_fmtstream_t fs)
124: {
125: char *buf, *nl;
126: size_t len;
127:
128:
129: buf = fs->buf + fs->point_offs;
130: while (buf < fs->p)
131: {
132: size_t r;
133:
134: if (fs->point_col == 0 && fs->lmargin != 0)
135: {
136:
137: const size_t pad = fs->lmargin;
138: if (fs->p + pad < fs->end)
139: {
140:
141:
142: memmove (buf + pad, buf, fs->p - buf);
143: fs->p += pad;
144: memset (buf, ' ', pad);
145: buf += pad;
146: }
147: else
148: {
149:
150: size_t i;
151: for (i = 0; i < pad; i++)
152: {
153: #ifdef USE_IN_LIBIO
154: if (_IO_fwide (fs->stream, 0) > 0)
155: putwc_unlocked (L' ', fs->stream);
156: else
157: #endif
158: putc_unlocked (' ', fs->stream);
159: }
160: }
161: fs->point_col = pad;
162: }
163:
164: len = fs->p - buf;
165: nl = memchr (buf, '\n', len);
166:
167: if (fs->point_col < 0)
168: fs->point_col = 0;
169:
170: if (!nl)
171: {
172:
173:
174: if (fs->point_col + len < fs->rmargin)
175: {
176:
177:
178:
179: fs->point_col += len;
180: break;
181: }
182: else
183:
184:
185: nl = fs->p;
186: }
187: else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
188: {
189:
190:
191: fs->point_col = 0;
192: buf = nl + 1;
193: continue;
194: }
195:
196:
197: r = fs->rmargin - 1;
198:
199: if (fs->wmargin < 0)
200: {
201:
202:
203: if (nl < fs->p)
204: {
205: memmove (buf + (r - fs->point_col), nl, fs->p - nl);
206: fs->p -= buf + (r - fs->point_col) - nl;
207:
208: fs->point_col = 0;
209: buf += r + 1;
210: }
211: else
212: {
213:
214:
215:
216: fs->point_col += len;
217: fs->p -= fs->point_col - r;
218: break;
219: }
220: }
221: else
222: {
223:
224:
225:
226:
227: char *p, *nextline;
228: int i;
229:
230: p = buf + (r + 1 - fs->point_col);
231: while (p >= buf && !isblank (*p))
232: --p;
233: nextline = p + 1;
234:
235: if (nextline > buf)
236: {
237:
238: if (p >= buf)
239: do
240: --p;
241: while (p >= buf && isblank (*p));
242: nl = p + 1;
243: }
244: else
245: {
246:
247:
248: p = buf + (r + 1 - fs->point_col);
249:
250: do
251: ++p;
252: while (p < nl && !isblank (*p));
253: if (p == nl)
254: {
255:
256: fs->point_col = 0;
257: buf = nl + 1;
258: continue;
259: }
260:
261: nl = p;
262:
263: do
264: ++p;
265: while (isblank (*p));
266:
267: nextline = p;
268: }
269:
270:
271:
272:
273:
274:
275: if ((nextline == buf + len + 1
276: ? fs->end - nl < fs->wmargin + 1
277: : nextline - (nl + 1) < fs->wmargin)
278: && fs->p > nextline)
279: {
280:
281: if (fs->end - fs->p > fs->wmargin + 1)
282:
283: {
284: size_t mv = fs->p - nextline;
285: memmove (nl + 1 + fs->wmargin, nextline, mv);
286: nextline = nl + 1 + fs->wmargin;
287: len = nextline + mv - buf;
288: *nl++ = '\n';
289: }
290: else
291:
292: {
293: #ifdef _LIBC
294: __fxprintf (fs->stream, "%.*s\n",
295: (int) (nl - fs->buf), fs->buf);
296: #else
297: if (nl > fs->buf)
298: fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
299: putc_unlocked ('\n', fs->stream);
300: #endif
301:
302: len += buf - fs->buf;
303: nl = buf = fs->buf;
304: }
305: }
306: else
307:
308:
309: *nl++ = '\n';
310:
311: if (nextline - nl >= fs->wmargin
312: || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
313:
314: for (i = 0; i < fs->wmargin; ++i)
315: *nl++ = ' ';
316: else
317: for (i = 0; i < fs->wmargin; ++i)
318: #ifdef USE_IN_LIBIO
319: if (_IO_fwide (fs->stream, 0) > 0)
320: putwc_unlocked (L' ', fs->stream);
321: else
322: #endif
323: putc_unlocked (' ', fs->stream);
324:
325:
326:
327: if (nl < nextline)
328: memmove (nl, nextline, buf + len - nextline);
329: len -= nextline - buf;
330:
331:
332: buf = nl;
333:
334:
335: fs->p = nl + len;
336:
337:
338:
339:
340: fs->point_col = fs->wmargin ? fs->wmargin : -1;
341: }
342: }
343:
344:
345: fs->point_offs = fs->p - fs->buf;
346: }
347: ^L
348:
349:
350: int
351: __argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
352: {
353: if ((size_t) (fs->end - fs->p) < amount)
354: {
355: ssize_t wrote;
356:
357:
358: __argp_fmtstream_update (fs);
359:
360: #ifdef _LIBC
361: __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
362: wrote = fs->p - fs->buf;
363: #else
364: wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
365: #endif
366: if (wrote == fs->p - fs->buf)
367: {
368: fs->p = fs->buf;
369: fs->point_offs = 0;
370: }
371: else
372: {
373: fs->p -= wrote;
374: fs->point_offs -= wrote;
375: memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
376: return 0;
377: }
378:
379: if ((size_t) (fs->end - fs->buf) < amount)
380:
381: {
382: size_t old_size = fs->end - fs->buf;
383: size_t new_size = old_size + amount;
384: char *new_buf;
385:
386: if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
387: {
388: __set_errno (ENOMEM);
389: return 0;
390: }
391:
392: fs->buf = new_buf;
393: fs->end = new_buf + new_size;
394: fs->p = fs->buf;
395: }
396: }
397:
398: return 1;
399: }
400: ^L
401: ssize_t
402: __argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
403: {
404: int out;
405: size_t avail;
406: size_t size_guess = PRINTF_SIZE_GUESS;
407:
408: do
409: {
410: va_list args;
411:
412: if (! __argp_fmtstream_ensure (fs, size_guess))
413: return -1;
414:
415: va_start (args, fmt);
416: avail = fs->end - fs->p;
417: out = __vsnprintf (fs->p, avail, fmt, args);
418: va_end (args);
419: if ((size_t) out >= avail)
420: size_guess = out + 1;
421: }
422: while ((size_t) out >= avail);
423:
424: fs->p += out;
425:
426: return out;
427: }
428: #if 0
429:
430: #ifdef weak_alias
431: weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
432: #endif
433: #endif
434:
435: #endif