libc: remove doprint
This commit is contained in:
parent
50e3c936fa
commit
1c1bef69aa
2 changed files with 0 additions and 1234 deletions
|
@ -1,617 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
enum
|
||||
{
|
||||
SIZE = 1024,
|
||||
IDIGIT = 40,
|
||||
MAXCONV = 40,
|
||||
FDIGIT = 30,
|
||||
FDEFLT = 6,
|
||||
NONE = -1000,
|
||||
MAXFMT = 512,
|
||||
|
||||
FPLUS = 1<<0,
|
||||
FMINUS = 1<<1,
|
||||
FSHARP = 1<<2,
|
||||
FLONG = 1<<3,
|
||||
FSHORT = 1<<4,
|
||||
FUNSIGN = 1<<5,
|
||||
FVLONG = 1<<6,
|
||||
};
|
||||
|
||||
int printcol;
|
||||
|
||||
static int convcount;
|
||||
static char fmtindex[MAXFMT];
|
||||
|
||||
static int noconv(va_list*, Fconv*);
|
||||
static int flags(va_list*, Fconv*);
|
||||
|
||||
static int cconv(va_list*, Fconv*);
|
||||
static int rconv(va_list*, Fconv*);
|
||||
static int sconv(va_list*, Fconv*);
|
||||
static int percent(va_list*, Fconv*);
|
||||
static int column(va_list*, Fconv*);
|
||||
|
||||
int numbconv(va_list*, Fconv*);
|
||||
|
||||
static
|
||||
int (*fmtconv[MAXCONV])(va_list*, Fconv*) =
|
||||
{
|
||||
noconv
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
initfmt(void)
|
||||
{
|
||||
int cc;
|
||||
|
||||
cc = 0;
|
||||
fmtconv[cc] = noconv;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = flags;
|
||||
fmtindex['+'] = cc;
|
||||
fmtindex['-'] = cc;
|
||||
fmtindex['#'] = cc;
|
||||
fmtindex['h'] = cc;
|
||||
fmtindex['l'] = cc;
|
||||
fmtindex['u'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = numbconv;
|
||||
fmtindex['d'] = cc;
|
||||
fmtindex['o'] = cc;
|
||||
fmtindex['x'] = cc;
|
||||
fmtindex['X'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = cconv;
|
||||
fmtindex['c'] = cc;
|
||||
fmtindex['C'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = rconv;
|
||||
fmtindex['r'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = sconv;
|
||||
fmtindex['s'] = cc;
|
||||
fmtindex['S'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = percent;
|
||||
fmtindex['%'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = column;
|
||||
fmtindex['|'] = cc;
|
||||
cc++;
|
||||
|
||||
convcount = cc;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, int (*f)(va_list*, Fconv*))
|
||||
{
|
||||
|
||||
if(convcount == 0)
|
||||
initfmt();
|
||||
if(c < 0 || c >= MAXFMT)
|
||||
return -1;
|
||||
if(convcount >= MAXCONV)
|
||||
return -1;
|
||||
fmtconv[convcount] = f;
|
||||
fmtindex[c] = convcount;
|
||||
convcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
doprint(char *s, char *es, char *fmt, va_list argp)
|
||||
{
|
||||
int n, c;
|
||||
Rune rune;
|
||||
Fconv local;
|
||||
|
||||
if(s >= es)
|
||||
return s;
|
||||
local.out = s;
|
||||
local.eout = es-UTFmax-1;
|
||||
|
||||
loop:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
switch(c) {
|
||||
case 0:
|
||||
*local.out = 0;
|
||||
return local.out;
|
||||
|
||||
default:
|
||||
printcol++;
|
||||
goto common;
|
||||
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
goto common;
|
||||
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
goto common;
|
||||
|
||||
common:
|
||||
if(local.out < local.eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
n = runetochar(local.out, &rune);
|
||||
local.out += n;
|
||||
} else
|
||||
*local.out++ = c;
|
||||
goto loop;
|
||||
|
||||
case '%':
|
||||
break;
|
||||
}
|
||||
local.f1 = NONE;
|
||||
local.f2 = NONE;
|
||||
local.f3 = 0;
|
||||
|
||||
/*
|
||||
* read one of the following
|
||||
* 1. number, => f1, f2 in order.
|
||||
* 2. '*' same as number (from args)
|
||||
* 3. '.' ignored (separates numbers)
|
||||
* 4. flag => f3
|
||||
* 5. verb and terminate
|
||||
*/
|
||||
l0:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
|
||||
l1:
|
||||
if(c == 0) {
|
||||
fmt--;
|
||||
goto loop;
|
||||
}
|
||||
if(c == '.') {
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = 0;
|
||||
local.f2 = 0;
|
||||
goto l0;
|
||||
}
|
||||
if((c >= '1' && c <= '9') ||
|
||||
(c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */
|
||||
n = 0;
|
||||
while(c >= '0' && c <= '9') {
|
||||
n = n*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l1;
|
||||
}
|
||||
if(c == '*') {
|
||||
n = va_arg(argp, int);
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l0;
|
||||
}
|
||||
n = 0;
|
||||
if(c >= 0 && c < MAXFMT)
|
||||
n = fmtindex[c];
|
||||
local.chr = c;
|
||||
n = (*fmtconv[n])(&argp, &local);
|
||||
if(n < 0) {
|
||||
local.f3 |= -n;
|
||||
goto l0;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
numbconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[IDIGIT];
|
||||
int i, f, n, b, ucase;
|
||||
short h;
|
||||
long v;
|
||||
vlong vl;
|
||||
|
||||
SET(v);
|
||||
SET(vl);
|
||||
|
||||
ucase = 0;
|
||||
b = fp->chr;
|
||||
switch(fp->chr) {
|
||||
case 'u':
|
||||
fp->f3 |= FUNSIGN;
|
||||
case 'd':
|
||||
b = 10;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
b = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
ucase = 1;
|
||||
case 'x':
|
||||
b = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
f = 0;
|
||||
switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
|
||||
case FVLONG|FLONG:
|
||||
vl = va_arg(*arg, vlong);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FVLONG|FLONG:
|
||||
vl = va_arg(*arg, uvlong);
|
||||
break;
|
||||
|
||||
case FLONG:
|
||||
v = va_arg(*arg, long);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(*arg, ulong);
|
||||
break;
|
||||
|
||||
case FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = h;
|
||||
break;
|
||||
|
||||
case FUNSIGN|FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = (ushort)h;
|
||||
break;
|
||||
|
||||
default:
|
||||
v = va_arg(*arg, int);
|
||||
break;
|
||||
|
||||
case FUNSIGN:
|
||||
v = va_arg(*arg, unsigned);
|
||||
break;
|
||||
}
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(!(fp->f3 & FUNSIGN) && vl < 0) {
|
||||
vl = -vl;
|
||||
f = 1;
|
||||
}
|
||||
} else {
|
||||
if(!(fp->f3 & FUNSIGN) && v < 0) {
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
s[IDIGIT-1] = 0;
|
||||
for(i = IDIGIT-2;; i--) {
|
||||
if(fp->f3 & FVLONG)
|
||||
n = (uvlong)vl % b;
|
||||
else
|
||||
n = (ulong)v % b;
|
||||
n += '0';
|
||||
if(n > '9') {
|
||||
n += 'a' - ('9'+1);
|
||||
if(ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
s[i] = n;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(fp->f3 & FVLONG)
|
||||
vl = (uvlong)vl / b;
|
||||
else
|
||||
v = (ulong)v / b;
|
||||
if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
|
||||
continue;
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(vl <= 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(fp->f3 & FSHARP) {
|
||||
if(b == 8 && s[i] != '0')
|
||||
s[--i] = '0';
|
||||
if(b == 16) {
|
||||
if(ucase)
|
||||
s[--i] = 'X';
|
||||
else
|
||||
s[--i] = 'x';
|
||||
s[--i] = '0';
|
||||
}
|
||||
}
|
||||
if(f)
|
||||
s[--i] = '-';
|
||||
fp->f2 = NONE;
|
||||
strconv(s+i, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Strconv(Rune *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
for(; s[n]; n++)
|
||||
;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strconv(char *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
n = utflen(s);
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s & 0xff;
|
||||
if(c >= Runeself) {
|
||||
i = chartorune(&rune, s);
|
||||
s += i;
|
||||
c = rune;
|
||||
} else
|
||||
s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
noconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int n;
|
||||
char s[10];
|
||||
|
||||
if(convcount == 0) {
|
||||
initfmt();
|
||||
n = 0;
|
||||
if(fp->chr >= 0 && fp->chr < MAXFMT)
|
||||
n = fmtindex[fp->chr];
|
||||
return (*fmtconv[n])(arg, fp);
|
||||
}
|
||||
s[0] = '*';
|
||||
s[1] = fp->chr;
|
||||
s[2] = '*';
|
||||
s[3] = 0;
|
||||
fp->f1 = 0;
|
||||
fp->f2 = NONE;
|
||||
fp->f3 = 0;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
rconv(va_list*, Fconv *fp)
|
||||
{
|
||||
char s[ERRLEN];
|
||||
|
||||
s[0] = 0;
|
||||
errstr(s);
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
cconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[10];
|
||||
Rune rune;
|
||||
|
||||
rune = va_arg(*arg, int);
|
||||
if(fp->chr == 'c')
|
||||
rune &= 0xff;
|
||||
s[runetochar(s, &rune)] = 0;
|
||||
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
sconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char *s;
|
||||
Rune *r;
|
||||
|
||||
if(fp->chr == 's') {
|
||||
s = va_arg(*arg, char*);
|
||||
if(s == 0)
|
||||
s = "<null>";
|
||||
strconv(s, fp);
|
||||
} else {
|
||||
r = va_arg(*arg, Rune*);
|
||||
if(r == 0)
|
||||
r = L"<null>";
|
||||
Strconv(r, fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
percent(va_list*, Fconv *fp)
|
||||
{
|
||||
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = '%';
|
||||
printcol++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
column(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int col, pc;
|
||||
|
||||
col = va_arg(*arg, int);
|
||||
while(fp->out < fp->eout && printcol < col) {
|
||||
pc = (printcol+8) & ~7;
|
||||
if(pc <= col) {
|
||||
*fp->out++ = '\t';
|
||||
printcol = pc;
|
||||
} else {
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
flags(va_list*, Fconv *fp)
|
||||
{
|
||||
int f;
|
||||
|
||||
f = 0;
|
||||
switch(fp->chr) {
|
||||
case '+':
|
||||
f = FPLUS;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
f = FMINUS;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
f = FSHARP;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
f = FSHORT;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
f = FLONG;
|
||||
if(fp->f3 & FLONG)
|
||||
f = FVLONG;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
f = FUNSIGN;
|
||||
break;
|
||||
}
|
||||
return -f;
|
||||
}
|
|
@ -1,617 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
enum
|
||||
{
|
||||
SIZE = 1024,
|
||||
IDIGIT = 40,
|
||||
MAXCONV = 40,
|
||||
FDIGIT = 30,
|
||||
FDEFLT = 6,
|
||||
NONE = -1000,
|
||||
MAXFMT = 512,
|
||||
|
||||
FPLUS = 1<<0,
|
||||
FMINUS = 1<<1,
|
||||
FSHARP = 1<<2,
|
||||
FLONG = 1<<3,
|
||||
FSHORT = 1<<4,
|
||||
FUNSIGN = 1<<5,
|
||||
FVLONG = 1<<6,
|
||||
};
|
||||
|
||||
int printcol;
|
||||
|
||||
static int convcount;
|
||||
static char fmtindex[MAXFMT];
|
||||
|
||||
static int noconv(va_list*, Fconv*);
|
||||
static int flags(va_list*, Fconv*);
|
||||
|
||||
static int cconv(va_list*, Fconv*);
|
||||
static int rconv(va_list*, Fconv*);
|
||||
static int sconv(va_list*, Fconv*);
|
||||
static int percent(va_list*, Fconv*);
|
||||
static int column(va_list*, Fconv*);
|
||||
|
||||
int numbconv(va_list*, Fconv*);
|
||||
|
||||
static
|
||||
int (*fmtconv[MAXCONV])(va_list*, Fconv*) =
|
||||
{
|
||||
noconv
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
initfmt(void)
|
||||
{
|
||||
int cc;
|
||||
|
||||
cc = 0;
|
||||
fmtconv[cc] = noconv;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = flags;
|
||||
fmtindex['+'] = cc;
|
||||
fmtindex['-'] = cc;
|
||||
fmtindex['#'] = cc;
|
||||
fmtindex['h'] = cc;
|
||||
fmtindex['l'] = cc;
|
||||
fmtindex['u'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = numbconv;
|
||||
fmtindex['d'] = cc;
|
||||
fmtindex['o'] = cc;
|
||||
fmtindex['x'] = cc;
|
||||
fmtindex['X'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = cconv;
|
||||
fmtindex['c'] = cc;
|
||||
fmtindex['C'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = rconv;
|
||||
fmtindex['r'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = sconv;
|
||||
fmtindex['s'] = cc;
|
||||
fmtindex['S'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = percent;
|
||||
fmtindex['%'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = column;
|
||||
fmtindex['|'] = cc;
|
||||
cc++;
|
||||
|
||||
convcount = cc;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, int (*f)(va_list*, Fconv*))
|
||||
{
|
||||
|
||||
if(convcount == 0)
|
||||
initfmt();
|
||||
if(c < 0 || c >= MAXFMT)
|
||||
return -1;
|
||||
if(convcount >= MAXCONV)
|
||||
return -1;
|
||||
fmtconv[convcount] = f;
|
||||
fmtindex[c] = convcount;
|
||||
convcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
doprint(char *s, char *es, char *fmt, va_list argp)
|
||||
{
|
||||
int n, c;
|
||||
Rune rune;
|
||||
Fconv local;
|
||||
|
||||
if(s >= es)
|
||||
return s;
|
||||
local.out = s;
|
||||
local.eout = es-UTFmax-1;
|
||||
|
||||
loop:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
switch(c) {
|
||||
case 0:
|
||||
*local.out = 0;
|
||||
return local.out;
|
||||
|
||||
default:
|
||||
printcol++;
|
||||
goto common;
|
||||
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
goto common;
|
||||
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
goto common;
|
||||
|
||||
common:
|
||||
if(local.out < local.eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
n = runetochar(local.out, &rune);
|
||||
local.out += n;
|
||||
} else
|
||||
*local.out++ = c;
|
||||
goto loop;
|
||||
|
||||
case '%':
|
||||
break;
|
||||
}
|
||||
local.f1 = NONE;
|
||||
local.f2 = NONE;
|
||||
local.f3 = 0;
|
||||
|
||||
/*
|
||||
* read one of the following
|
||||
* 1. number, => f1, f2 in order.
|
||||
* 2. '*' same as number (from args)
|
||||
* 3. '.' ignored (separates numbers)
|
||||
* 4. flag => f3
|
||||
* 5. verb and terminate
|
||||
*/
|
||||
l0:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
|
||||
l1:
|
||||
if(c == 0) {
|
||||
fmt--;
|
||||
goto loop;
|
||||
}
|
||||
if(c == '.') {
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = 0;
|
||||
local.f2 = 0;
|
||||
goto l0;
|
||||
}
|
||||
if((c >= '1' && c <= '9') ||
|
||||
(c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */
|
||||
n = 0;
|
||||
while(c >= '0' && c <= '9') {
|
||||
n = n*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l1;
|
||||
}
|
||||
if(c == '*') {
|
||||
n = va_arg(argp, int);
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l0;
|
||||
}
|
||||
n = 0;
|
||||
if(c >= 0 && c < MAXFMT)
|
||||
n = fmtindex[c];
|
||||
local.chr = c;
|
||||
n = (*fmtconv[n])(&argp, &local);
|
||||
if(n < 0) {
|
||||
local.f3 |= -n;
|
||||
goto l0;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
numbconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[IDIGIT];
|
||||
int i, f, n, b, ucase;
|
||||
short h;
|
||||
long v;
|
||||
vlong vl;
|
||||
|
||||
SET(v);
|
||||
SET(vl);
|
||||
|
||||
ucase = 0;
|
||||
b = fp->chr;
|
||||
switch(fp->chr) {
|
||||
case 'u':
|
||||
fp->f3 |= FUNSIGN;
|
||||
case 'd':
|
||||
b = 10;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
b = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
ucase = 1;
|
||||
case 'x':
|
||||
b = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
f = 0;
|
||||
switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
|
||||
case FVLONG|FLONG:
|
||||
vl = va_arg(*arg, vlong);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FVLONG|FLONG:
|
||||
vl = va_arg(*arg, uvlong);
|
||||
break;
|
||||
|
||||
case FLONG:
|
||||
v = va_arg(*arg, long);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(*arg, ulong);
|
||||
break;
|
||||
|
||||
case FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = h;
|
||||
break;
|
||||
|
||||
case FUNSIGN|FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = (ushort)h;
|
||||
break;
|
||||
|
||||
default:
|
||||
v = va_arg(*arg, int);
|
||||
break;
|
||||
|
||||
case FUNSIGN:
|
||||
v = va_arg(*arg, unsigned);
|
||||
break;
|
||||
}
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(!(fp->f3 & FUNSIGN) && vl < 0) {
|
||||
vl = -vl;
|
||||
f = 1;
|
||||
}
|
||||
} else {
|
||||
if(!(fp->f3 & FUNSIGN) && v < 0) {
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
s[IDIGIT-1] = 0;
|
||||
for(i = IDIGIT-2;; i--) {
|
||||
if(fp->f3 & FVLONG)
|
||||
n = (uvlong)vl % b;
|
||||
else
|
||||
n = (ulong)v % b;
|
||||
n += '0';
|
||||
if(n > '9') {
|
||||
n += 'a' - ('9'+1);
|
||||
if(ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
s[i] = n;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(fp->f3 & FVLONG)
|
||||
vl = (uvlong)vl / b;
|
||||
else
|
||||
v = (ulong)v / b;
|
||||
if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
|
||||
continue;
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(vl <= 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(fp->f3 & FSHARP) {
|
||||
if(b == 8 && s[i] != '0')
|
||||
s[--i] = '0';
|
||||
if(b == 16) {
|
||||
if(ucase)
|
||||
s[--i] = 'X';
|
||||
else
|
||||
s[--i] = 'x';
|
||||
s[--i] = '0';
|
||||
}
|
||||
}
|
||||
if(f)
|
||||
s[--i] = '-';
|
||||
fp->f2 = NONE;
|
||||
strconv(s+i, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Strconv(Rune *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
for(; s[n]; n++)
|
||||
;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strconv(char *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
n = utflen(s);
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s & 0xff;
|
||||
if(c >= Runeself) {
|
||||
i = chartorune(&rune, s);
|
||||
s += i;
|
||||
c = rune;
|
||||
} else
|
||||
s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
noconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int n;
|
||||
char s[10];
|
||||
|
||||
if(convcount == 0) {
|
||||
initfmt();
|
||||
n = 0;
|
||||
if(fp->chr >= 0 && fp->chr < MAXFMT)
|
||||
n = fmtindex[fp->chr];
|
||||
return (*fmtconv[n])(arg, fp);
|
||||
}
|
||||
s[0] = '*';
|
||||
s[1] = fp->chr;
|
||||
s[2] = '*';
|
||||
s[3] = 0;
|
||||
fp->f1 = 0;
|
||||
fp->f2 = NONE;
|
||||
fp->f3 = 0;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
rconv(va_list*, Fconv *fp)
|
||||
{
|
||||
char s[ERRLEN];
|
||||
|
||||
s[0] = 0;
|
||||
errstr(s);
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
cconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[10];
|
||||
Rune rune;
|
||||
|
||||
rune = va_arg(*arg, int);
|
||||
if(fp->chr == 'c')
|
||||
rune &= 0xff;
|
||||
s[runetochar(s, &rune)] = 0;
|
||||
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
sconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char *s;
|
||||
Rune *r;
|
||||
|
||||
if(fp->chr == 's') {
|
||||
s = va_arg(*arg, char*);
|
||||
if(s == 0)
|
||||
s = "<null>";
|
||||
strconv(s, fp);
|
||||
} else {
|
||||
r = va_arg(*arg, Rune*);
|
||||
if(r == 0)
|
||||
r = L"<null>";
|
||||
Strconv(r, fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
percent(va_list*, Fconv *fp)
|
||||
{
|
||||
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = '%';
|
||||
printcol++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
column(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int col, pc;
|
||||
|
||||
col = va_arg(*arg, int);
|
||||
while(fp->out < fp->eout && printcol < col) {
|
||||
pc = (printcol+8) & ~7;
|
||||
if(pc <= col) {
|
||||
*fp->out++ = '\t';
|
||||
printcol = pc;
|
||||
} else {
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
flags(va_list*, Fconv *fp)
|
||||
{
|
||||
int f;
|
||||
|
||||
f = 0;
|
||||
switch(fp->chr) {
|
||||
case '+':
|
||||
f = FPLUS;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
f = FMINUS;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
f = FSHARP;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
f = FSHORT;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
f = FLONG;
|
||||
if(fp->f3 & FLONG)
|
||||
f = FVLONG;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
f = FUNSIGN;
|
||||
break;
|
||||
}
|
||||
return -f;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue