/* * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) * * * Dale Schumacher 399 Beacon Ave. * (alias: Dalnefre') St. Paul, MN 55104 * dal@syntel.UUCP United States of America * "It's not reality that's important, but how you perceive things." */ /* Altered to use stdarg, made the core function vfprintf. * Hooked into the stdio package using 'inside information' * Altered sizeof() assumptions, now assumes all integers except chars * will be either * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) * * -RDB */ #include #include #include #include #ifdef __STDC__ #include #define va_strt va_start #else #include #define va_strt(p,i) va_start(p) #endif #include "stdio.h" extern int vfnprintf(FILE * op, size_t max_size, register __const char *fmt, register va_list ap); #ifdef L_printf int printf(const char *fmt, ...) { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfnprintf(stdout, -1, fmt, ptr); va_end(ptr); return rv; } #endif #ifdef L_sprintf int sprintf(char *sp, const char *fmt, ...) { static FILE string[1] = { {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; va_list ptr; int rv; va_strt(ptr, fmt); string->bufpos = sp; rv = vfnprintf(string, -1, fmt, ptr); va_end(ptr); *(string->bufpos) = 0; return rv; } #endif #ifdef L_snprintf int snprintf(char *sp, size_t size, const char *fmt, ...) { static FILE string[1] = { {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; va_list ptr; int rv; va_strt(ptr, fmt); string->bufpos = sp; rv = vfnprintf(string, size, fmt, ptr); va_end(ptr); *(string->bufpos) = 0; return rv; } #endif #ifdef L_fprintf int fprintf(FILE * fp, const char *fmt, ...) { va_list ptr; int rv; va_strt(ptr, fmt); rv = vfnprintf(fp, -1, fmt, ptr); va_end(ptr); return rv; } #endif #ifdef L_vprintf int vprintf(const char *fmt, va_list ap) { return vfprintf(stdout, fmt, ap); } #endif #ifdef L_vsprintf int vsprintf(char *sp, __const char *fmt, va_list ap) { static FILE string[1] = { {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; int rv; string->bufpos = sp; rv = vfnprintf(string, -1, fmt, ap); *(string->bufpos) = 0; return rv; } #endif #ifdef L_vsprintf int vsnprintf(char *sp, size_t size, __const char *fmt, va_list ap) { static FILE string[1] = { {0, 0, (char *) (unsigned) -1, 0, (char *) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; int rv; string->bufpos = sp; rv = vfnprintf(string, size, fmt, ap); *(string->bufpos) = 0; return rv; } #endif #ifdef L_vfprintf #if FLOATS int _vfprintf_fp_ref = 1; #else int _vfprintf_fp_ref = 0; #endif static int printfield(op, buf, ljustf, sign, pad, width, preci, buffer_mode, max_size, current_size) register FILE *op; register unsigned char *buf; int ljustf; register char sign; char pad; register int width; int preci; int buffer_mode; size_t max_size; size_t current_size; /* * Output the given field in the manner specified by the arguments. Return * the number of characters output. */ { register int cnt = 0, len; register unsigned char ch; len = strlen(buf); if (*buf == '-') sign = *buf++; else if (sign) len++; if ((preci != -1) && (len > preci)) /* limit max data width */ len = preci; if (width < len) /* flexible field width or width overflow */ width = len; /* * at this point: width = total field width len = actual data width * (including possible sign character) */ cnt = width; width -= len; while (width || len) { if (!ljustf && width) { /* left padding */ if (len && sign && (pad == '0')) goto showsign; ch = pad; --width; } else if (len) { if (sign) { showsign:ch = sign; /* sign */ sign = '\0'; } else ch = *buf++; /* main field */ --len; } else { ch = pad; /* right padding */ --width; } current_size++; if (max_size > 0 && current_size < max_size) putc(ch, op); if (ch == '\n' && buffer_mode == _IOLBF) fflush(op); } return (cnt); } int vfnprintf(FILE * op, size_t max_size, register __const char *fmt, register va_list ap) { register int i, cnt = 0, ljustf, lval; int preci, dpoint, width; char pad, sign, radix, hash; register char *ptmp; char tmp[64], *ltostr(), *ultostr(); int buffer_mode; /* This speeds things up a bit for unbuffered */ buffer_mode = (op->mode & __MODE_BUF); op->mode &= (~__MODE_BUF); while (*fmt) { if (*fmt == '%') { if (buffer_mode == _IONBF) fflush(op); ljustf = 0; /* left justify flag */ sign = '\0'; /* sign char & status */ pad = ' '; /* justification padding char */ width = -1; /* min field width */ dpoint = 0; /* found decimal point */ preci = -1; /* max data width */ radix = 10; /* number base */ ptmp = tmp; /* pointer to area to print */ hash = 0; lval = (sizeof(int) == sizeof(long)); /* long value flaged */ fmtnxt: i = 0; for (;;) { ++fmt; if (*fmt < '0' || *fmt > '9') break; i = (i * 10) + (*fmt - '0'); if (dpoint) preci = i; else if (!i && (pad == ' ')) { pad = '0'; goto fmtnxt; } else width = i; } switch (*fmt) { case '\0': /* early EOS */ --fmt; goto charout; case '-': /* left justification */ ljustf = 1; goto fmtnxt; case ' ': case '+': /* leading sign flag */ sign = *fmt; goto fmtnxt; case '*': /* parameter width value */ i = va_arg(ap, int); if (dpoint) preci = i; else width = i; goto fmtnxt; case '.': /* secondary width field */ dpoint = 1; goto fmtnxt; case 'l': /* long data */ lval = 1; goto fmtnxt; case 'h': /* short data */ lval = 0; goto fmtnxt; case 'd': /* Signed decimal */ case 'i': ptmp = ltostr((long) ((lval) ? va_arg(ap, long) : va_arg(ap, short)), 10, 0); goto printit; case 'b': /* Unsigned binary */ radix = 2; goto usproc; case 'o': /* Unsigned octal */ radix = 8; goto usproc; case 'p': /* Pointer */ lval = (sizeof(char *) == sizeof(long)); pad = '0'; width = 6; preci = 8; /* fall thru */ case 'x': /* Unsigned hexadecimal */ case 'X': radix = 16; /* fall thru */ case 'u': /* Unsigned decimal */ usproc: ptmp = ultostr((unsigned long) ((lval) ? va_arg(ap, unsigned long) : va_arg(ap, unsigned short)), radix, (*fmt == 'X') ? 1 : 0); if (hash && radix == 8) { width = strlen(ptmp) + 1; pad = '0'; } goto printit; case '#': hash = 1; goto fmtnxt; case 'c': /* Character */ ptmp[0] = va_arg(ap, int); ptmp[1] = '\0'; goto nopad; case 's': /* String */ ptmp = va_arg(ap, char *); nopad: sign = '\0'; pad = ' '; printit: cnt += printfield(op, ptmp, ljustf, sign, pad, width, preci, buffer_mode, max_size, cnt); break; #if FLOATS case 'e': /* float */ case 'f': case 'g': case 'E': case 'G': fprintf(stderr, "LIBM:PRINTF"); gcvt(va_arg(ap, double), preci, ptmp); preci = -1; goto printit; #else case 'e': /* float */ case 'f': case 'g': case 'E': case 'G': fprintf(stderr, "LIBC:PRINTF"); exit(-1); #endif default: /* unknown character */ goto charout; } } else { charout: if (max_size > 0 && ++cnt < max_size) putc(*fmt, op); /* normal char out */ if (*fmt == '\n' && buffer_mode == _IOLBF) fflush(op); } ++fmt; } op->mode |= buffer_mode; if (buffer_mode == _IONBF) fflush(op); if (buffer_mode == _IOLBF) op->bufwrite = op->bufstart; return (cnt); } int vfprintf(FILE * op, register __const char *fmt, register va_list ap) { return (vfnprintf(op, -1, fmt, ap)); } #endif