/* * 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 "stdio.h" #ifdef L_printf #ifdef __STDC__ int printf(const char * fmt, ...) #else int printf(fmt) __const char *fmt; #endif { va_list ptr; int rv; va_start(ptr, fmt); rv = vfprintf(stdout,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_sprintf #ifdef __STDC__ int sprintf(char * sp, const char * fmt, ...) #else int sprintf(sp, fmt) char * sp; __const char *fmt; #endif { static FILE string[1] = { {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, _IOFBF | __MODE_WRITE} }; va_list ptr; int rv; va_start(ptr, fmt); string->bufpos = sp; rv = vfprintf(string,fmt,ptr); va_end(ptr); *(string->bufpos) = 0; return rv; } #endif #ifdef L_fprintf #ifdef __STDC__ int fprintf(FILE * fp, const char * fmt, ...) #else int fprintf(fp, fmt) FILE * fp; __const char *fmt; #endif { va_list ptr; int rv; va_start(ptr, fmt); rv = vfprintf(fp,fmt,ptr); va_end(ptr); return rv; } #endif #ifdef L_vprintf int vprintf(fmt, ap) __const char *fmt; va_list ap; { return vfprintf(stdout,fmt,ap); } #endif #ifdef L_vsprintf int vsprintf(sp, fmt, ap) 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 = vfprintf(string,fmt,ap); *(string->bufpos) = 0; return rv; } #endif #ifdef L_vfprintf static int prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode) register FILE *op; register unsigned char *buf; int ljustf; register char sign; char pad; register int width; int preci; int buffer_mode; /* * 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; } putc(ch, op); if( ch == '\n' && buffer_mode == _IOLBF ) fflush(op); } return (cnt); } int vfprintf(op, fmt, ap) FILE *op; 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; #if FLOATS double fx; #endif /* 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); 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); if( hash && radix == 8 ) { width = strlen(ptmp)+1; pad='0'; } goto printit; case '#': hash=1; goto fmtnxt; #if FLOATS case 'e': /* float */ case 'f': case 'g': case 'E': case 'G': fx = va_arg(ap, double); fp_print(fx, *fmt, preci, ptmp); preci = -1; goto printit; #endif 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 += prtfld(op, ptmp, ljustf, sign, pad, width, preci, buffer_mode); break; default: /* unknown character */ goto charout; } } else { charout: putc(*fmt, op); /* normal char out */ ++cnt; 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); } #endif