/* from Dale Schumacher's dLibs library */ #ifndef __NO_FLOATS__ #define FLOATS 1 #endif #include #include #include #include #include #define alloca __builtin_alloca #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define TEN_MUL(X) ((((X) << 2) + (X)) << 1) int _printf(op, put, fmt, args) char *op; unsigned int (*put)(); register unsigned char *fmt; register unsigned int *args; { register int i, cnt = 0, ljustf, lval; int preci, dpoint, width; int prefixf; /* `#' flag */ char pad, sign, radix; register char *ptmp; char *_ltoa(), *_ultoa(); #if FLOATS double fx; #endif char prefix[3]; char *tmp = (char *)alloca((size_t)128); prefix[0] = '\0'; while(*fmt) { if(*fmt == '%') { ljustf = FALSE; /* left justify flag */ sign = '\0'; /* sign char & status */ pad = ' '; /* justification padding char */ width = -1; /* min field width */ dpoint = FALSE; /* found decimal point */ preci = -1; /* max data width */ radix = 10; /* number base */ ptmp = tmp; /* pointer to area to print */ lval = FALSE; /* long value flaged */ prefixf = FALSE; /* add prefix flag */ fmtnxt: i = 0; while (isdigit(*++fmt)) { i = TEN_MUL(i) + (*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 = TRUE; goto fmtnxt; case ' ': case '+': /* leading sign flag */ sign = *fmt; goto fmtnxt; case '*': /* parameter width value */ i = *args++; if (dpoint) preci = i; else width = i; goto fmtnxt; case '.': /* secondary width field */ dpoint = TRUE; goto fmtnxt; case 'l': /* long data */ lval = TRUE; goto fmtnxt; case '#': prefixf = TRUE; goto fmtnxt; case 'h': /* here for completeness, does not need to do anything as short ints are promoted to ints at call time */ goto fmtnxt; case 'd': /* Signed decimal */ case 'i': _ltoa((long)((lval) ?(*((long *) args)) :(*((int *) args))), ptmp, 10); if(lval) args = ((unsigned int *) (((long *) args) + 1)); else args = ((unsigned int *) (((int *) args) + 1)); goto printit; case 'b': /* Unsigned binary */ radix = 2; goto usproc; case 'o': /* Unsigned octal */ if(prefixf) strcpy(prefix, "0"); radix = 8; goto usproc; case 'p': /* Pointer */ lval = TRUE; pad = '0'; width = 6; preci = 8; radix = 16; goto usproc; case 'x': /* Unsigned hexadecimal */ case 'X': if(prefixf) strcpy(prefix, "0X"); radix = 16; /* fall thru */ case 'u': /* Unsigned decimal */ usproc: if(prefixf && prefix[0] != '\0') { strcpy(tmp, prefix); prefix[0] = '\0'; while(*ptmp != '\0') ptmp++; } _ultoa((unsigned long)((lval) ?(*((unsigned long *) args)) : *args++ ), ptmp, radix); ptmp = tmp; if(lval) args = ((unsigned int *) (((unsigned long *) args) + 1)); if (*fmt == 'x') strlwr(ptmp); goto printit; #if FLOATS case 'e': /* float */ case 'f': case 'g': case 'E': case 'G': fx = *((double *) args); args=(unsigned int *) (((double *) args)+1); fp_print(fx, *fmt, preci, ptmp); preci = -1; goto printit; #endif case 'c': /* Character */ ptmp[0] = *args++; ptmp[1] = '\0'; goto nopad; case 's': /* String */ ptmp = *((char **) args); args = ((unsigned int *) (((char **) args) + 1)); nopad: sign = '\0'; pad = ' '; printit: cnt += _prtfld(op, put, ptmp, ljustf, sign, pad, width, preci); break; default: /* unknown character */ goto charout; } } else { charout: (*put)(*fmt, op); /* normal char out */ ++cnt; } ++fmt; } return(cnt); }