add more spacing
[personal-kdebase.git] / workspace / kdm / backend / printf.c
blobeb69398337a8ccc71d03039036c33953163f6624
1 /*
3 Copyright 2001,2002,2004 Oswald Buddenhagen <ossi@kde.org>
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of a copyright holder shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from the copyright holder.
30 * xdm - display manager daemon
31 * Author: Keith Packard, MIT X Consortium
33 * printf.c - working horse of error.c
37 * NOTE: this file is meant to be included, not linked,
38 * so it can be used in the helper programs without much voodoo.
41 /* ########## printf core implementation with some extensions ########## */
43 * How to use the extensions:
44 * - put ' or " in the flags field to quote a string with this char and
45 * escape special characters (only available, if PRINT_QUOTES is defined)
46 * - put \\ in the flags field to quote special characters and leading and
47 * trailing spaces (only available, if PRINT_QUOTES is defined)
48 * - arrays (only available, if PRINT_ARRAYS is defined)
49 * - the array modifier [ comes after the maximal field width specifier
50 * - the array length can be specified literally, with the '*' modifier
51 * (in which case an argument is expected) or will be automatically
52 * determined (stop values are -1 for ints and 0 for strings)
53 * - these modifiers expect their argument to be an in-line string quoted
54 * with an arbitrary character:
55 * - (, ) -> array pre-/suf-fix; default ""
56 * - <, > -> element pre-/suf-fix; default ""
57 * - | -> element separator; default " "
58 * - these modifiers expect no argument:
59 * - : -> print '<number of elements>: ' before an array
60 * - , -> short for |','
61 * - { -> short for ('{')' }'<' '|''
62 * - the pointer to the array is the last argument to the format
63 * - the %m conversion from syslog() is supported
66 /**************************************************************
67 * Partially stolen from OpenSSH's OpenBSD compat directory.
68 * (C) Patrick Powell, Brandon Long, Thomas Roessler,
69 * Michael Elkins, Ben Lindstrom
70 **************************************************************/
72 #include <ctype.h>
73 #include <string.h>
74 #include <stdarg.h>
76 /* format flags - Bits */
77 #define DP_F_MINUS (1 << 0)
78 #define DP_F_PLUS (1 << 1)
79 #define DP_F_SPACE (1 << 2)
80 #define DP_F_NUM (1 << 3)
81 #define DP_F_ZERO (1 << 4)
82 #define DP_F_UPCASE (1 << 5)
83 #define DP_F_UNSIGNED (1 << 6)
84 #define DP_F_SQUOTE (1 << 7)
85 #define DP_F_DQUOTE (1 << 8)
86 #define DP_F_BACKSL (1 << 9)
87 #define DP_F_ARRAY (1 << 10)
88 #define DP_F_COLON (1 << 11)
90 /* Conversion Flags */
91 #define DP_C_INT 0
92 #define DP_C_BYTE 1
93 #define DP_C_SHORT 2
94 #define DP_C_LONG 3
95 #define DP_C_STR 10
97 typedef void (*OutCh)( void *bp, char c );
100 static void
101 fmtint( OutCh dopr_outch, void *bp,
102 long value, int base, int min, int max, int flags )
104 const char *ctab;
105 unsigned long uvalue;
106 int signvalue = 0;
107 int place = 0;
108 int spadlen = 0; /* amount to space pad */
109 int zpadlen = 0; /* amount to zero pad */
110 char convert[20];
112 if (max < 0)
113 max = 0;
115 uvalue = value;
117 if (!(flags & DP_F_UNSIGNED)) {
118 if (value < 0) {
119 signvalue = '-';
120 uvalue = -value;
121 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
122 signvalue = '+';
123 else if (flags & DP_F_SPACE)
124 signvalue = ' ';
127 ctab = (flags & DP_F_UPCASE) ? "0123456789ABCDEF" : "0123456789abcdef";
128 do {
129 convert[place++] = ctab[uvalue % (unsigned)base];
130 uvalue = uvalue / (unsigned)base;
131 } while (uvalue);
133 zpadlen = max - place;
134 spadlen = min - (max > place ? max : place) -
135 (signvalue ? 1 : 0) - ((flags & DP_F_NUM) ? 2 : 0);
136 if (zpadlen < 0)
137 zpadlen = 0;
138 if (spadlen < 0)
139 spadlen = 0;
140 if (flags & DP_F_ZERO) {
141 zpadlen = zpadlen > spadlen ? zpadlen : spadlen;
142 spadlen = 0;
144 if (flags & DP_F_MINUS)
145 spadlen = -spadlen; /* Left Justifty */
148 /* Spaces */
149 while (spadlen > 0) {
150 dopr_outch( bp, ' ' );
151 --spadlen;
154 /* Sign */
155 if (signvalue)
156 dopr_outch( bp, signvalue );
158 /* Prefix */
159 if (flags & DP_F_NUM) {
160 dopr_outch( bp, '0' );
161 dopr_outch( bp, 'x' );
164 /* Zeros */
165 if (zpadlen > 0)
166 while (zpadlen > 0) {
167 dopr_outch( bp, '0' );
168 --zpadlen;
171 /* Digits */
172 while (place > 0)
173 dopr_outch( bp, convert[--place] );
175 /* Left Justified spaces */
176 while (spadlen < 0) {
177 dopr_outch( bp, ' ' );
178 ++spadlen;
182 typedef struct {
183 const char *str;
184 size_t len;
185 } str_t;
187 static void
188 putstr( OutCh dopr_outch, void *bp, str_t *st )
190 size_t pt;
192 for (pt = 0; pt < st->len; pt++)
193 dopr_outch( bp, st->str[pt] );
196 static str_t _null_parents = { "(null)", 6 };
197 #ifdef PRINT_ARRAYS
198 static str_t _null_dparents = { "((null))", 8 };
199 #endif
200 #if defined(PRINT_QUOTES) || defined(PRINT_ARRAYS)
201 static str_t _null_caps = { "NULL", 4 };
202 #endif
204 static void
205 fmtstr( OutCh dopr_outch, void *bp,
206 const char *value, int flags, int min, int max )
208 int padlen, strln, curcol;
209 #ifdef PRINT_QUOTES
210 int lastcol;
211 #endif
212 char ch;
214 if (!value) {
215 #ifdef PRINT_QUOTES
216 if (flags & (DP_F_SQUOTE | DP_F_DQUOTE))
217 putstr( dopr_outch, bp, &_null_caps );
218 else
219 #endif
220 putstr( dopr_outch, bp, &_null_parents );
221 return;
224 for (strln = 0; (unsigned)strln < (unsigned)max && value[strln]; strln++);
225 padlen = min - strln;
226 if (padlen < 0)
227 padlen = 0;
228 if (flags & DP_F_MINUS)
229 padlen = -padlen; /* Left Justify */
231 for (; padlen > 0; padlen--)
232 dopr_outch( bp, ' ' );
233 #ifdef PRINT_QUOTES
234 lastcol = 0;
235 if (flags & DP_F_SQUOTE)
236 dopr_outch( bp, '\'' );
237 else if (flags & DP_F_DQUOTE)
238 dopr_outch( bp, '"');
239 else if (flags & DP_F_BACKSL)
240 for (lastcol = strln; lastcol && value[lastcol - 1] == ' '; lastcol--);
241 #endif
242 for (curcol = 0; curcol < strln; curcol++) {
243 ch = value[curcol];
244 #ifdef PRINT_QUOTES
245 if (flags & (DP_F_SQUOTE | DP_F_DQUOTE | DP_F_BACKSL)) {
246 switch (ch) {
247 case '\r': ch = 'r'; break;
248 case '\n': ch = 'n'; break;
249 case '\t': ch = 't'; break;
250 case '\a': ch = 'a'; break;
251 case '\b': ch = 'b'; break;
252 case '\v': ch = 'v'; break;
253 case '\f': ch = 'f'; break;
254 default:
255 if (ch < 32 ||
256 ((unsigned char)ch >= 0x7f && (unsigned char)ch < 0xa0))
258 dopr_outch( bp, '\\' );
259 fmtint( dopr_outch, bp, (unsigned char)ch, 8, 3, 3, DP_F_ZERO );
260 continue;
261 } else {
262 if ((ch == '\'' && (flags & DP_F_SQUOTE)) ||
263 (ch == '"' && (flags & DP_F_DQUOTE) ) ||
264 (ch == ' ' && (flags & DP_F_BACKSL) &&
265 (!curcol || curcol >= lastcol)) ||
266 ch == '\\')
267 dopr_outch( bp, '\\' );
268 dopr_outch( bp, ch );
269 continue;
272 dopr_outch( bp, '\\' );
274 #endif
275 dopr_outch( bp, ch );
277 #ifdef PRINT_QUOTES
278 if (flags & DP_F_SQUOTE)
279 dopr_outch( bp, '\'' );
280 else if (flags & DP_F_DQUOTE)
281 dopr_outch( bp, '"' );
282 #endif
283 for (; padlen < 0; padlen++)
284 dopr_outch( bp, ' ' );
287 static void
288 doPrint( OutCh dopr_outch, void *bp, const char *format, va_list args )
290 const char *strvalue;
291 #ifdef PRINT_ARRAYS
292 str_t arpr, arsf, arepr, aresf, aresp, *arp;
293 void *arptr;
294 #endif
295 unsigned long value;
296 int radix, min, max, flags, cflags, errn;
297 #ifdef PRINT_ARRAYS
298 int arlen;
299 unsigned aridx;
300 char sch;
301 #endif
302 char ch;
303 #define NCHR if (!(ch = *format++)) return
305 # ifdef PRINT_ARRAYS
306 arlen = 0;
307 # endif
308 radix = 0;
309 errn = errno;
310 for (;;) {
311 for (;;) {
312 NCHR;
313 if (ch == '%')
314 break;
315 dopr_outch (bp, ch);
317 flags = cflags = min = 0;
318 max = -1;
319 for (;;) {
320 NCHR;
321 switch (ch) {
322 case '#': flags |= DP_F_NUM; continue;
323 case '-': flags |= DP_F_MINUS; continue;
324 case '+': flags |= DP_F_PLUS; continue;
325 case ' ': flags |= DP_F_SPACE; continue;
326 case '0': flags |= DP_F_ZERO; continue;
327 #ifdef PRINT_QUOTES
328 case '"': flags |= DP_F_DQUOTE; continue;
329 case '\'': flags |= DP_F_SQUOTE; continue;
330 case '\\': flags |= DP_F_BACKSL; continue;
331 #endif
333 break;
335 for (;;) {
336 if (isdigit( (unsigned char)ch )) {
337 min = 10 * min + (ch - '0');
338 NCHR;
339 continue;
340 } else if (ch == '*') {
341 min = va_arg( args, int );
342 NCHR;
344 break;
346 if (ch == '.') {
347 max = 0;
348 for (;;) {
349 NCHR;
350 if (isdigit( (unsigned char)ch )) {
351 max = 10 * max + (ch - '0');
352 continue;
353 } else if (ch == '*') {
354 max = va_arg( args, int );
355 NCHR;
357 break;
360 #ifdef PRINT_ARRAYS
361 if (ch == '[') {
362 flags |= DP_F_ARRAY;
363 arlen = -1;
364 arpr.len = arsf.len = arepr.len = aresf.len = 0;
365 aresp.len = 1, aresp.str = " ";
366 for (;;) {
367 NCHR;
368 if (isdigit( (unsigned char)ch )) {
369 arlen = 0;
370 for (;;) {
371 arlen += (ch - '0');
372 NCHR;
373 if (!isdigit( (unsigned char)ch ))
374 break;
375 arlen *= 10;
378 switch (ch) {
379 case ':': flags |= DP_F_COLON; continue;
380 case '*': arlen = va_arg( args, int ); continue;
381 case '(': arp = &arpr; goto rar;
382 case ')': arp = &arsf; goto rar;
383 case '<': arp = &arepr; goto rar;
384 case '>': arp = &aresf; goto rar;
385 case '|': arp = &aresp;
386 rar:
387 NCHR;
388 sch = ch;
389 arp->str = format;
390 do {
391 NCHR;
392 } while (ch != sch);
393 arp->len = format - arp->str - 1;
394 continue;
395 case ',':
396 aresp.len = 1, aresp.str = ",";
397 continue;
398 case '{':
399 aresp.len = 0, arpr.len = arepr.len = 1, arsf.len = 2;
400 arpr.str = "{", arepr.str = " ", arsf.str = " }";
401 continue;
403 break;
406 #endif
407 for (;;) {
408 switch (ch) {
409 case 'h':
410 cflags = DP_C_SHORT;
411 NCHR;
412 if (ch == 'h') {
413 cflags = DP_C_BYTE;
414 NCHR;
416 continue;
417 case 'l':
418 cflags = DP_C_LONG;
419 NCHR;
420 continue;
422 break;
424 switch (ch) {
425 case '%':
426 dopr_outch( bp, ch );
427 break;
428 case 'm':
429 fmtstr( dopr_outch, bp, strerror( errn ), flags, min, max );
430 break;
431 case 'c':
432 dopr_outch( bp, va_arg( args, int ) );
433 break;
434 case 's':
435 #ifdef PRINT_ARRAYS
436 cflags = DP_C_STR;
437 goto printit;
438 #else
439 strvalue = va_arg( args, char * );
440 fmtstr( dopr_outch, bp, strvalue, flags, min, max );
441 break;
442 #endif
443 case 'u':
444 flags |= DP_F_UNSIGNED;
445 case 'd':
446 case 'i':
447 radix = 10;
448 goto printit;
449 case 'X':
450 flags |= DP_F_UPCASE;
451 case 'x':
452 flags |= DP_F_UNSIGNED;
453 radix = 16;
454 printit:
455 #ifdef PRINT_ARRAYS
456 if (flags & DP_F_ARRAY) {
457 if (!(arptr = va_arg( args, void * )))
458 putstr( dopr_outch, bp,
459 arpr.len ? &_null_caps : &_null_dparents );
460 else {
461 if (arlen == -1) {
462 arlen = 0;
463 switch (cflags) {
464 case DP_C_STR: while (((char **)arptr)[arlen]) arlen++; break;
465 case DP_C_BYTE: while (((unsigned char *)arptr)[arlen] != (unsigned char)-1) arlen++; break;
466 case DP_C_SHORT: while (((unsigned short int *)arptr)[arlen] != (unsigned short int)-1) arlen++; break;
467 case DP_C_LONG: while (((unsigned long int *)arptr)[arlen] != (unsigned long int)-1) arlen++; break;
468 default: while (((unsigned int *)arptr)[arlen] != (unsigned int)-1) arlen++; break;
471 if (flags & DP_F_COLON) {
472 fmtint( dopr_outch, bp, (long)arlen, 10, 0, -1, DP_F_UNSIGNED );
473 dopr_outch( bp, ':' );
474 dopr_outch( bp, ' ' );
476 putstr( dopr_outch, bp, &arpr );
477 for (aridx = 0; aridx < (unsigned)arlen; aridx++) {
478 if (aridx)
479 putstr( dopr_outch, bp, &aresp );
480 putstr( dopr_outch, bp, &arepr );
481 if (cflags == DP_C_STR) {
482 strvalue = ((char **)arptr)[aridx];
483 fmtstr( dopr_outch, bp, strvalue, flags, min, max );
484 } else {
485 if (flags & DP_F_UNSIGNED) {
486 switch (cflags) {
487 case DP_C_BYTE: value = ((unsigned char *)arptr)[aridx]; break;
488 case DP_C_SHORT: value = ((unsigned short int *)arptr)[aridx]; break;
489 case DP_C_LONG: value = ((unsigned long int *)arptr)[aridx]; break;
490 default: value = ((unsigned int *)arptr)[aridx]; break;
492 } else {
493 switch (cflags) {
494 case DP_C_BYTE: value = ((signed char *)arptr)[aridx]; break;
495 case DP_C_SHORT: value = ((short int *)arptr)[aridx]; break;
496 case DP_C_LONG: value = ((long int *)arptr)[aridx]; break;
497 default: value = ((int *)arptr)[aridx]; break;
500 fmtint( dopr_outch, bp, value, radix, min, max, flags );
502 putstr( dopr_outch, bp, &aresf );
504 putstr( dopr_outch, bp, &arsf );
506 } else {
507 if (cflags == DP_C_STR) {
508 strvalue = va_arg( args, char * );
509 fmtstr( dopr_outch, bp, strvalue, flags, min, max );
510 } else {
511 #endif
512 if (flags & DP_F_UNSIGNED) {
513 switch (cflags) {
514 case DP_C_LONG: value = va_arg( args, unsigned long int ); break;
515 default: value = va_arg( args, unsigned int ); break;
517 } else {
518 switch (cflags) {
519 case DP_C_LONG: value = va_arg( args, long int ); break;
520 default: value = va_arg( args, int ); break;
523 fmtint( dopr_outch, bp, value, radix, min, max, flags );
524 #ifdef PRINT_ARRAYS
527 #endif
528 break;
529 case 'p':
530 value = (long)va_arg( args, void * );
531 fmtint( dopr_outch, bp, value, 16, sizeof(long) * 2 + 2,
532 max, flags | DP_F_UNSIGNED | DP_F_ZERO | DP_F_NUM );
533 break;
538 /* ########## end of printf core implementation ########## */
542 * Logging function for xdm and helper programs.
544 #ifndef NO_LOGGER
546 #include <stdio.h>
547 #include <time.h>
549 #ifdef USE_SYSLOG
550 # include <syslog.h>
551 # ifdef LOG_NAME
552 # define InitLog() openlog(LOG_NAME, LOG_PID, LOG_DAEMON)
553 # else
554 # define InitLog() openlog(prog, LOG_PID, LOG_DAEMON)
555 # endif
556 static int lognums[] = { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR, LOG_CRIT };
557 #else
558 # define InitLog() while(0)
559 #endif
561 static const char *lognams[] = { "debug", "info", "warning", "error", "panic" };
563 static void
564 logTime( char *dbuf )
566 time_t tim;
567 (void)time( &tim );
568 strftime( dbuf, 20, "%b %e %H:%M:%S", localtime( &tim ) );
571 #if defined(LOG_DEBUG_MASK) || defined(USE_SYSLOG)
572 STATIC int debugLevel;
573 #endif
575 #define OOMSTR "Out of memory. Expect problems.\n"
577 STATIC void
578 logOutOfMem( void )
580 static time_t last;
581 time_t tnow;
583 time( &tnow );
584 if (last + 100 > tnow) { /* don't log bursts */
585 last = tnow;
586 return;
588 last = tnow;
589 #ifdef USE_SYSLOG
590 if (!(debugLevel & DEBUG_NOSYSLOG))
591 syslog( LOG_CRIT, OOMSTR );
592 else
593 #endif
595 int el;
596 char dbuf[24], sbuf[128];
597 logTime( dbuf );
598 el = sprintf( sbuf, "%s "
599 #ifdef LOG_NAME
600 LOG_NAME "[%ld]: " OOMSTR, dbuf,
601 #else
602 "%s[%ld]: " OOMSTR, dbuf, prog,
603 #endif
604 (long)getpid() );
605 write( 2, sbuf, el );
609 typedef struct {
610 char *buf;
611 int clen, blen, type;
612 char lmbuf[128];
613 } OCLBuf;
615 static void
616 flush_OCL( OCLBuf *oclbp )
618 if (oclbp->clen) {
619 #ifdef USE_SYSLOG
620 if (!(debugLevel & DEBUG_NOSYSLOG))
621 syslog( lognums[oclbp->type], "%.*s", oclbp->clen, oclbp->buf );
622 else
623 #endif
625 oclbp->buf[oclbp->clen] = '\n';
626 write( 2, oclbp->buf, oclbp->clen + 1 );
628 oclbp->clen = 0;
632 static void
633 outCh_OCL( void *bp, char c )
635 OCLBuf *oclbp = (OCLBuf *)bp;
636 char *nbuf;
637 int nlen;
639 if (c == '\n')
640 flush_OCL( oclbp );
641 else {
642 if (oclbp->clen >= oclbp->blen - 1) {
643 if (oclbp->buf == oclbp->lmbuf) {
644 flush_OCL( oclbp );
645 oclbp->buf = 0;
646 oclbp->blen = 0;
648 nlen = oclbp->blen * 3 / 2 + 128;
649 nbuf = Realloc( oclbp->buf, nlen );
650 if (nbuf) {
651 oclbp->buf = nbuf;
652 oclbp->blen = nlen;
653 } else {
654 flush_OCL( oclbp );
655 oclbp->buf = oclbp->lmbuf;
656 oclbp->blen = sizeof(oclbp->lmbuf);
659 #ifdef USE_SYSLOG
660 if (!oclbp->clen && (debugLevel & DEBUG_NOSYSLOG)) {
661 #else
662 if (!oclbp->clen) {
663 #endif
664 char dbuf[24];
665 logTime( dbuf );
666 oclbp->clen = sprintf( oclbp->buf, "%s "
667 #ifdef LOG_NAME
668 LOG_NAME "[%ld] %s: ", dbuf,
669 #else
670 "%s[%ld] %s: ", dbuf, prog,
671 #endif
672 (long)getpid(), lognams[oclbp->type] );
674 oclbp->buf[oclbp->clen++] = c;
678 static void
679 logger( int type, const char *fmt, va_list args )
681 OCLBuf oclb;
683 oclb.buf = 0;
684 oclb.blen = oclb.clen = 0;
685 oclb.type = type;
686 doPrint( outCh_OCL, &oclb, fmt, args );
687 /* no flush, every message is supposed to be \n-terminated */
688 if (oclb.buf && oclb.buf != oclb.lmbuf)
689 free( oclb.buf );
692 #ifdef LOG_DEBUG_MASK
693 STATIC void
694 debug( const char *fmt, ... )
696 if (debugLevel & LOG_DEBUG_MASK) {
697 va_list args;
698 int olderrno = errno;
699 va_start( args, fmt );
700 logger( DM_DEBUG, fmt, args );
701 va_end( args );
702 errno = olderrno;
705 #endif
707 #ifndef LOG_NO_INFO
708 STATIC void
709 logInfo( const char *fmt, ... )
711 va_list args;
713 va_start( args, fmt );
714 logger( DM_INFO, fmt, args );
715 va_end( args );
717 #endif
719 #ifndef LOG_NO_WARN
720 STATIC void
721 logWarn( const char *fmt, ... )
723 va_list args;
725 va_start( args, fmt );
726 logger( DM_WARN, fmt, args );
727 va_end( args );
729 #endif
731 #ifndef LOG_NO_ERROR
732 STATIC void
733 logError( const char *fmt, ... )
735 va_list args;
737 va_start( args, fmt );
738 logger( DM_ERR, fmt, args );
739 va_end( args );
741 #endif
743 #ifdef LOG_PANIC_EXIT
744 STATIC void
745 logPanic( const char *fmt, ... )
747 va_list args;
749 va_start( args, fmt );
750 logger( DM_PANIC, fmt, args );
751 va_end( args );
752 exit( LOG_PANIC_EXIT );
754 #endif
756 #endif /* NO_LOGGER */
758 #ifdef NEED_FDPRINTF
760 typedef struct {
761 char *buf;
762 int clen, blen, tlen;
763 } OCFBuf;
765 static void
766 outCh_OCF( void *bp, char c )
768 OCFBuf *ocfbp = (OCFBuf *)bp;
769 char *nbuf;
770 int nlen;
772 ocfbp->tlen++;
773 if (ocfbp->clen >= ocfbp->blen) {
774 if (ocfbp->blen < 0)
775 return;
776 nlen = ocfbp->blen * 3 / 2 + 100;
777 nbuf = Realloc( ocfbp->buf, nlen );
778 if (!nbuf) {
779 free( ocfbp->buf );
780 ocfbp->blen = -1;
781 ocfbp->buf = 0;
782 ocfbp->clen = 0;
783 return;
785 ocfbp->blen = nlen;
786 ocfbp->buf = nbuf;
788 ocfbp->buf[ocfbp->clen++] = c;
791 STATIC int
792 FdPrintf( int fd, const char *fmt, ... )
794 va_list args;
795 OCFBuf ocfb = { 0, 0, 0, -1 };
797 va_start( args, fmt );
798 doPrint( outCh_OCF, &ocfb, fmt, args );
799 va_end( args );
800 if (ocfb.buf) {
801 debug( "FdPrintf %\".*s to %d\n", ocfb.clen, ocfb.buf, fd );
802 (void)write( fd, ocfb.buf, ocfb.clen );
803 free( ocfb.buf );
805 return ocfb.tlen;
808 #endif /* NEED_FDPRINTF */
810 #ifdef NEED_ASPRINTF
812 typedef struct {
813 char *buf;
814 int clen, blen, tlen;
815 } OCABuf;
817 static void
818 outCh_OCA( void *bp, char c )
820 OCABuf *ocabp = (OCABuf *)bp;
821 char *nbuf;
822 int nlen;
824 ocabp->tlen++;
825 if (ocabp->clen >= ocabp->blen) {
826 if (ocabp->blen < 0)
827 return;
828 nlen = ocabp->blen * 3 / 2 + 100;
829 nbuf = Realloc( ocabp->buf, nlen );
830 if (!nbuf) {
831 free( ocabp->buf );
832 ocabp->blen = -1;
833 ocabp->buf = 0;
834 ocabp->clen = 0;
835 return;
837 ocabp->blen = nlen;
838 ocabp->buf = nbuf;
840 ocabp->buf[ocabp->clen++] = c;
843 STATIC int
844 VASPrintf( char **strp, const char *fmt, va_list args )
846 OCABuf ocab = { 0, 0, 0, -1 };
848 doPrint( outCh_OCA, &ocab, fmt, args );
849 outCh_OCA( &ocab, 0 );
850 *strp = Realloc( ocab.buf, ocab.clen );
851 if (!*strp)
852 *strp = ocab.buf;
853 return ocab.tlen;
856 STATIC int
857 ASPrintf( char **strp, const char *fmt, ... )
859 va_list args;
860 int len;
862 va_start( args, fmt );
863 len = VASPrintf( strp, fmt, args );
864 va_end( args );
865 return len;
868 #endif /* NEED_ASPRINTF */