/* Copyright(C) 1994 TOSHIBA Corporation All Rights Reseved */
/* $RCSfile: __doform.c,v $ */
/* $Revision: 1.11 $ */
/* $Date: 2003/05/13 01:12:08 $ */
#if defined(__900__) && defined(PIC)
#pragma far_pic_on
#pragma far_pid_on
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
static void __CDECL _dodigit(char *str, long val);
static void __CDECL _doudigit(char *str, unsigned long val);
static void __CDECL _doxdigit(char *str, unsigned long val, int cap);
static void __CDECL _doodigit(char *str, unsigned long val);
#ifdef FLOAT
char * __CDECL _facnv( char* dbl, unsigned char* s, int flag, int* e, int* sgn );
static void __CDECL _dofloat(char c, void (*fnc)(int c), char* val, int flag, int width, int precision);
static void __CDECL _dofloat_f(char c, void (*fnc)(int c), int flag, int width, int precision, char *buf, int expr, int sgn);
static void __CDECL _dofloat_e(char c, void (*fnc)(int c), int flag, int width, int precision, char *buf, int expr, int sgn);
static int __CDECL _zerochk(char *str);
#endif
#define PLUS 0x01
#define MINUS 0x02
#define BLANK 0x04
#define SHARP 0x08
#define PRECISION 0x10
#define SHORT 0x20
#define LONG 0x40
#define LONGDOUBLE 0x80
#define SIGNED 0x100
#define ISPLUS(x) (x & PLUS)
#define ISMINUS(x) (x & MINUS)
#define ISBLANK(x) (x & BLANK)
#define ISSHARP(x) (x & SHARP)
#define ISPRECISION(x) (x & PRECISION)
#define ISSHORT(x) (x & SHORT)
#define ISLONG(x) (x & LONG)
#define ISLONGDOUBLE(x) (x & LONGDOUBLE)
static int padchar;
static int out_cnt;
int __CDECL _doprnt(const char *fmt,va_list *args,void (*fnc)(int c))
{
register int cnt;
register int c;
register int flag;
register int width;
register int precision;
union {
double a;
long double b;
} work;
cnt = 0;
while((c = *fmt++) != '\0') {
if (c != '%') {
fnc(c);
cnt++;
continue;
}
flag = precision = width = 0;
padchar = ' ';
/* flag set */
flagset: switch (c = *fmt++) {
case ' ':
flag |= BLANK;
goto flagset;
case '#':
flag |= SHARP;
goto flagset;
case '+':
flag |= PLUS;
goto flagset;
case '-':
flag |= MINUS;
goto flagset;
case '0':
padchar = '0';
goto flagset;
}
/* width set */
if (c == '*') {
if ((width = va_arg(*args,int)) < 0) {
width = -width;
flag |= MINUS;
}
c = *fmt++;
}
else {
while( isdigit(c) ) {
width = width * 10 + (c - '0');
c=*fmt++ ;
}
}
/* precision set */
if (c == '.') {
flag |= PRECISION;
if ((c = *fmt++) == '*') {
if ((precision = va_arg(*args,int)) < 0) {
flag &= ~PRECISION;
}
c = *fmt++;
}
else {
while( isdigit(c) ) {
precision = precision * 10 + (c - '0');
c=*fmt++ ;
}
}
}
/* size set */
if (c == 'h') {
flag |= SHORT;
c = *fmt++;
}
else if (c == 'l') {
flag |= LONG;
c = *fmt++;
}
else if (c == 'L') {
flag |= LONGDOUBLE;
c = *fmt++;
}
/* type set & output */
switch(c) {
case 'c':
case '%':
if (!ISMINUS(flag)) {
while((--width) > 0) {
cnt++;
fnc(padchar);
}
}
cnt++;
if (c == 'c')
fnc(va_arg(*args,int));
else fnc('%');
if (ISMINUS(flag)) {
while((--width) > 0) {
cnt++;
fnc(' ');
}
}
break;
case 's':
{
register char *str;
register int len;
str = va_arg(*args,char *);
len = strlen(str);
if (!ISPRECISION(flag) || precision >= len)
precision = len;
else len = precision;
if (len > width) {
width = 0;
cnt += len;
}
else {
cnt+=width;
width-=len;
}
if (!ISMINUS(flag)) {
while(width--) fnc(padchar);
}
while (precision--) fnc(*str++);
if (ISMINUS(flag)) {
while(width--) fnc(' ');
}
}
break;
case 'd':
case 'i':
{
register int len,sgn;
register long val;
char buf[12];
#ifdef INT_LONG
val = va_arg(*args,long);
if(ISSHORT(flag)) val = (short)val;
#else
if (ISLONG(flag)) val = va_arg(*args,long);
else val = va_arg(*args,short);
#endif
sgn = 0;
if (ISPRECISION(flag) && precision == 0 && val == 0) {
buf[0] = '\0';
len = 0;
}
else {
_dodigit(buf,val);
len = strlen(buf);
if (val < 0) sgn = 1;
}
if (!ISPRECISION(flag) || precision < len) precision = 0;
else precision -= len;
if (flag & (BLANK | PLUS)) sgn = 1;
width -= (len + precision + sgn);
if (width < 0) width = 0;
cnt += (width + len + precision + sgn);
if(width && !ISMINUS(flag) && (padchar == ' ' || ISPRECISION(flag))) {
while (width--) fnc(' ');
width = 0;
}
if (val < 0) fnc('-');
else {
if (ISPLUS(flag)) fnc('+');
else if (ISBLANK(flag)) fnc(' ');
}
if (!ISMINUS(flag) && padchar == '0') {
while (width--) fnc('0');
}
while (precision--) fnc('0');
while (len) fnc(buf[--len]);
if (ISMINUS(flag)) {
while (width--) fnc(' ');
}
}
break;
case 'u':
{
register int len;
register long val;
char buf[12];
#ifdef INT_LONG
val = va_arg(*args,unsigned long);
if(ISSHORT(flag)) val = (unsigned short)val;
#else
if (ISLONG(flag)) val = va_arg(*args,unsigned long);
else val = va_arg(*args,unsigned short);
#endif
if (ISPRECISION(flag) && precision == 0 && val == 0) {
buf[0] = '\0';
len = 0;
}
else {
_doudigit(buf,val);
len = strlen(buf);
}
if (!ISPRECISION(flag) || precision < len) precision = 0;
else precision -= len;
width -= (len + precision);
if (width < 0) width = 0;
cnt += (width + len + precision);
if (!ISMINUS(flag)) {
while (width--) fnc(padchar);
}
while (precision--) fnc('0');
while (len) fnc(buf[--len]);
if (ISMINUS(flag)) {
while (width--) fnc(' ');
}
}
break;
case 'p':
flag |= LONG;
case 'x':
case 'X':
{
register int tlen;
register int len;
register long val;
char buf[12];
#ifdef INT_LONG
val = va_arg(*args,unsigned long);
if (ISSHORT(flag)) val = (unsigned short)val;
#else
if (ISLONG(flag)) val = va_arg(*args,unsigned long);
else val = va_arg(*args,unsigned short);
#endif
if (ISPRECISION(flag) && precision == 0 && val == 0) {
buf[0] = '\0';
len = 0;
}
else {
_doxdigit(buf,val,c);
len = strlen(buf);
}
if (!ISPRECISION(flag) || precision < len) precision = 0;
else precision -= len;
if (ISSHARP(flag)) tlen = 2;
else tlen = 0;
width -= (len + precision + tlen);
if (width < 0) width = 0;
cnt += (width + len + precision + tlen);
if (!ISMINUS(flag) && padchar == ' ') {
while (width--) fnc(' ');
}
if (tlen && len) {
fnc('0');
fnc(c);
}
if (!ISMINUS(flag) && padchar == '0') {
while (width--) fnc('0');
}
while (precision--) fnc('0');
while (len) fnc(buf[--len]);
if (ISMINUS(flag)) {
while (width--) fnc(' ');
}
}
break;
case 'o':
{
register int tlen;
register int len;
register long val;
char buf[12];
#ifdef INT_LONG
val = va_arg(*args,unsigned long);
if (ISSHORT(flag)) val = (unsigned short)val;
#else
if (ISLONG(flag)) val = va_arg(*args,unsigned long);
else val = va_arg(*args,unsigned short);
#endif
if (ISPRECISION(flag) && precision == 0 && val == 0) {
buf[0] = '\0';
len = 0;
}
else {
_doodigit(buf,val);
len = strlen(buf);
}
if (!ISPRECISION(flag) || precision < len) precision = 0;
else precision -= len;
if (ISSHARP(flag)) tlen = 1;
else tlen = 0;
width -= (len +
评论0