#include "sfhdr.h"
#if __STD_C
static char* sffmtint(const char* str, int* v)
#else
static char* sffmtint(str, v)
char* str;
int* v;
#endif
{
for(*v = 0; isdigit(*str); ++str)
*v = *v * 10 + (*str - '0');
*v -= 1;
return (char*)str;
}
#if __STD_C
static Fmtpos_t* sffmtpos(Sfio_t* f, const char* form, va_list args, int type)
#else
static Fmtpos_t* sffmtpos(f,form,args,type)
Sfio_t* f;
char* form;
va_list args;
int type;
#endif
{
int base, fmt, flags, dot, width, precis;
ssize_t n_str, size = 0;
char *t_str, *sp;
int v, n, skip, dollar, decimal, thousand;
Sffmt_t *ft, savft;
Fmtpos_t* fp;
int argp, argn, maxp, need[FP_INDEX];
if(type < 0)
fp = NIL(Fmtpos_t*);
else if(!(fp = sffmtpos(f,form,args,-1)) )
return NIL(Fmtpos_t*);
dollar = decimal = thousand = 0; argn = maxp = -1;
while((n = *form) )
{ if(n != '%')
{ sp = (char*)form++;
while(*form && *form != '%')
form += 1;
continue;
}
else form += 1;
if(*form == 0)
break;
else if(*form == '%')
{ form += 1;
continue;
}
if(*form == '*' && type > 0)
{ skip = 1;
form += 1;
argp = -1;
}
else
{ skip = 0;
sp = sffmtint(form,&argp);
if(*sp == '$')
{ dollar = 1;
form = sp+1;
}
else argp = -1;
}
flags = dot = 0;
t_str = NIL(char*); n_str = 0;
size = width = precis = base = -1;
for(n = 0; n < FP_INDEX; ++n)
need[n] = -1;
loop_flags:
switch((fmt = *form++) )
{
case LEFTP :
t_str = (char*)form;
for(v = 1;;)
{ switch(*form++)
{
case 0 :
form = t_str;
t_str = NIL(char*);
n_str = 0;
goto loop_flags;
case LEFTP :
v += 1;
continue;
case RIGHTP :
if((v -= 1) != 0)
continue;
n_str = form-t_str;
if(*t_str == '*')
{ t_str = sffmtint(t_str+1,&n);
if(*t_str == '$')
dollar = 1;
else n = -1;
if((n = FP_SET(n,argn)) > maxp)
maxp = n;
if(fp && fp[n].ft.fmt == 0)
{ fp[n].ft.fmt = LEFTP;
fp[n].ft.form = (char*)form;
}
need[FP_STR] = n;
}
goto loop_flags;
}
}
case '-' :
flags |= SFFMT_LEFT;
flags &= ~SFFMT_ZERO;
goto loop_flags;
case '0' :
if(!(flags&SFFMT_LEFT) )
flags |= SFFMT_ZERO;
goto loop_flags;
case ' ' :
if(!(flags&SFFMT_SIGN) )
flags |= SFFMT_BLANK;
goto loop_flags;
case '+' :
flags |= SFFMT_SIGN;
flags &= ~SFFMT_BLANK;
goto loop_flags;
case '#' :
flags |= SFFMT_ALTER;
goto loop_flags;
case QUOTE:
SFSETLOCALE(&decimal,&thousand);
if(thousand)
flags |= SFFMT_THOUSAND;
goto loop_flags;
case '.' :
if((dot += 1) == 2)
base = 0;
if(isdigit(*form))
{ fmt = *form++;
goto dot_size;
}
else if(*form != '*')
goto loop_flags;
else form += 1;
case '*' :
form = sffmtint(form,&n);
if(*form == '$' )
{ dollar = 1;
form += 1;
}
else n = -1;
if((n = FP_SET(n,argn)) > maxp)
maxp = n;
if(fp && fp[n].ft.fmt == 0)
{ fp[n].ft.fmt = '.';
fp[n].ft.size = dot;
fp[n].ft.form = (char*)form;
}
if(dot <= 2)
need[dot] = n;
goto loop_flags;
case '1' : case '2' : case '3' :
case '4' : case '5' : case '6' :
case '7' : case '8' : case '9' :
dot_size :
for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
v = v*10 + (fmt - '0');
if(dot == 0)
width = v;
else if(dot == 1)
precis = v;
else if(dot == 2)
base = v;
goto loop_flags;
case 'I' :
size = 0;
flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
if(isdigit(*form) )
{ for(n = *form; isdigit(n); n = *++form)
size = size*10 + (n - '0');
}
else if(*form == '*')
{ form = sffmtint(form+1,&n);
if(*form == '$' )
{ dollar = 1;
form += 1;
}
else n = -1;
if((n = FP_SET(n,argn)) > maxp)
maxp = n;
if(fp && fp[n].ft.fmt == 0)
{ fp[n].ft.fmt = 'I';
fp[n].ft.size = sizeof(int);
fp[n].ft.form = (char*)form;
}
need[FP_SIZE] = n;
}
goto loop_flags;
case 'l' :
size = -1;
flags &= ~SFFMT_TYPES;
if(*form == 'l')
{ form += 1;
flags |= SFFMT_LLONG;
}
else flags |= SFFMT_LONG;
goto loop_flags;
case 'h' :
size = -1;
flags &= ~SFFMT_TYPES;
if(*form == 'h')
{ form += 1;
flags |= SFFMT_SSHORT;
}
else flags |= SFFMT_SHORT;
goto loop_flags;
case 'L' :
size = -1;
flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
goto loop_flags;
}
if(flags & (SFFMT_TYPES & ~SFFMT_IFLAG) )
{ if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
{ size = (flags&SFFMT_LLONG) ? sizeof(Sflong_t) :
(flags&SFFMT_LONG) ? sizeof(long) :
(flags&SFFMT_SHORT) ? sizeof(short) :
(flags&SFFMT_SSHORT) ? sizeof(char) :
(flags&SFFMT_JFLAG) ? sizeof(Sflong_t) :
(flags&SFFMT_TFLAG) ? sizeof(ptrdiff_t) :
(flags&SFFMT_ZFLAG) ? sizeof(size_t) :
-1;
}
else if(_Sftype[fmt]&SFFMT_FLOAT)
{ size = (flags&SFFMT_LDOUBLE) ? sizeof(Sfdouble_t) :
(flags&(SFFMT_LONG|SFFMT_LLONG)) ?
sizeof(double) : -1;
}
}
if(skip)
continue;
if((argp = FP_SET(argp,argn)) > maxp)
maxp = argp;
if(dollar && fmt == '!')
return NIL(Fmtpos_t*);
if(fp && fp[argp].ft.fmt == 0)
{ fp[argp].ft.form = (char*)form;
fp[argp].ft.fmt = fp[argp].fmt = fmt;
fp[argp].ft.size = size;
fp[argp].ft.flags = flags;
fp[argp].ft.width = width;
fp[argp].ft.precis = precis;
fp[argp].ft.base = base;
fp[argp].ft.t_str = t_str;
fp[argp].ft.n_str = n_str;
for(n = 0; n < FP_INDEX; ++n)
fp[argp].need[n] = need[n];
}
}
if(!fp)
{ if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
return NIL(Fmtpos_t*);
for(n = 0; n <= maxp; ++n)
fp[n].ft.fmt = 0;
return fp;
}
for(n = 0, ft = NIL(Sffmt_t*); n <= maxp; ++n)
{ if(fp[n].ft.fmt == 0)
{ fp[n].ft.fmt = 'd';
fp[n].ft.width = 0;
fp[n].ft.precis = 0;
fp[n].ft.base = 0;
fp[n].ft.size = 0;
fp[n].ft.t_str = 0;
fp[n].ft.n_str = 0;
fp[n].ft.flags = 0;
for(v = 0; v < FP_INDEX; ++v)
fp[n].need[v] = -1;
}
if(ft && ft->extf)
{ fp[n].ft.version = ft->version;
fp[n].ft.extf = ft->extf;
fp[n].ft.eventf = ft->eventf;
if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
fp[n].ft.width = fp[v].argv.i;
if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
fp[n].ft.precis = fp[v].argv.i;
if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
fp[n].ft.base = fp[v].argv.i;
if((v = fp[n].need[FP_STR]) >= 0 && v < n)
fp[n].ft.t_str = fp[v].argv.s;
if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
fp[n].ft.size = fp[v].argv.i;
memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
va_copy(ft->args,args);
ft->flags |= SFFMT_ARGPOS;
v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
va_copy(args,ft->args);
memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
if(v < 0)
{ memcpy(ft,&savft,sizeof(Sffmt_t));
ft = NIL(Sffmt_t*);
}
if(!(fp[n].ft.flags&SFFMT_VALUE) )
goto arg_list;
}
else
{ arg_list:
if(fp[n].ft.fmt == LEFTP)
{ fp[n].argv.s = va_arg(args, char*);
fp[n].ft.size = strlen(fp[n].argv.s);
}
else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
fp[n].argv.i = va_arg(args, int);
else if(fp[n].ft.fmt == '!')
{ if(ft)
memcpy(ft,&savft,sizeof(Sffmt_t));
fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
if(ft->form)
ft = NIL(Sffmt_t*);
if(ft)
memcpy(&savft,ft,sizeof(Sffmt_t));
}
else if(type > 0)
fp[n].argv.vp = va_arg(args, Void_t*);
else switch(_Sftype[fp[n].ft.fmt])
{ case SFFMT_INT:
case SFFMT_UINT:
#if !_ast_intmax_long
if(FMTCMP(size, Sflong_t, Sflong_t))
fp[n].argv.ll = va_arg(args, Sflong_t);
else
#endif
if(FMTCMP(size, long, Sflong_t) )
fp[n].argv.l = va_arg(args, long);
else fp[n].argv.i = va_arg(args, int);
break;
case SFFMT_FLOAT:
#if !_ast_fltmax_double
if(FMTCMP(size, Sfdouble_t, Sfdouble_t))
fp[n].argv.ld = va_arg(args,Sfdouble_t);
else
#endif
fp[n].argv.d = va_arg(args,double);
break;
case SFFMT_POINTER:
fp[n].argv.vp = va_arg(args,Void_t*);
break;
case SFFMT_BYTE:
if(fp[n].ft.base >= 0)
fp[n].argv.s = va_arg(args,char*);
else fp[n].argv.c = (char)va_arg(args,int);
break;
default:
break;
}
}
}
if(ft)
memcpy(ft,&savft,sizeof(Sffmt_t));
return fp;
}
static int sfcvinit()
{ reg int d, l;
for(d = 0; d <= SF_MAXCHAR; ++d)
{ _Sfcv36[d] = SF_RADIX;
_Sfcv64[d] = SF_RADIX;
}
for(d = 0; d < 10; ++d)
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
_Sfcv64[(uchar)_Sfdigits[d]] = d;
}
for(; d < 36; ++d)
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
_Sfcv64[(uchar)_Sfdigits[d]] = d;
}
for(l = 10; d < 62; ++l, ++d)
{ _Sfcv36[(uchar)_Sfdigits[d]] = l;
_Sfcv64[(uchar)_Sfdigits[d]] = d;
}
for(; d < SF_RADIX; ++d)
{ _Sfcv36[(uchar)_Sfdigits[d]] = d;
_Sfcv64[(uchar)_Sfdigits[d]] = d;
}
_Sftype['d'] = _Sftype['i'] = SFFMT_INT;
_Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
_Sftype['e'] = _Sftype['E'] =
_Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
_Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
_Sftype['c'] = SFFMT_BYTE;
_Sftype['['] = SFFMT_CLASS;
return 1;
}
Sftab_t _Sftable =
{
{ 1e1, 1e2, 1e4, 1e8, 1e16, 1e32 },
{ 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32 },
{ '0','0', '0','1', '0','2', '0','3', '0','4',
'0','5', '0','6', '0','7', '0','8', '0','9',
'1','0', '1','1', '1','2', '1','3', '1','4',
'1','5', '1','6', '1','7', '1','8', '1','9',
'2','0', '2','1', '2','2', '2','3', '2','4',
'2','5', '2','6', '2','7', '2','8', '2','9',
'3','0', '3','1', '3','2', '3','3', '3','4',
'3','5', '3','6', '3','7', '3','8', '3','9',
'4','0', '4','1', '4','2', '4','3', '4','4',
'4','5', '4','6', '4','7', '4','8', '4','9',
'5','0', '5','1', '5','2', '5','3', '5','4',
'5','5', '5','6', '5','7', '5','8', '5','9',
'6','0', '6','1', '6','2', '6','3', '6','4',
'6','5', '6','6', '6','7', '6','8', '6','9',
'7','0', '7','1', '7','2', '7','3', '7','4',
'7','5', '7','6', '7','7', '7','8', '7','9',
'8','0', '8','1', '8','2', '8','3', '8','4',
'8','5', '8','6', '8','7', '8','8', '8','9',
'9','0', '9','1', '9','2', '9','3', '9','4',
'9','5', '9','6', '9','7', '9','8', '9','9',
},
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_",
sfcvinit, 0,
sffmtpos,
sffmtint
};