ref: f801657f77f3923ec2388c25bdcb036c8019ba89
dir: /libkern/fmt.c/
/*
* The authors of this software are Rob Pike and Ken Thompson.
* Copyright (c) 2002 by Lucent Technologies.
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*/
#include <u.h>
#include "kern.h"
#include "fmtdef.h"
int (*doquote)(int);
static Fmts
fmtfmt(int c)
{
switch(c) {
case ' ': return _flagfmt;
case '#': return _flagfmt;
case '%': return _percentfmt;
case '+': return _flagfmt;
case ':': return _flagfmt;
case '-': return _flagfmt;
case 'C': return _runefmt;
case 'S': return _runesfmt;
case 'X': return _ifmt;
case 'b': return _ifmt;
case 'c': return _charfmt;
case 'd': return _ifmt;
case 'h': return _flagfmt;
case 'l': return _flagfmt;
case 'n': return _countfmt;
case 'o': return _ifmt;
case 'p': return _ifmt;
case 's': return _strfmt;
case 'u': return _flagfmt;
case 'x': return _ifmt;
}
return _badfmt;
}
void*
_fmtdispatch(Fmt *f, void *fmt, int isrunes)
{
Rune rune, r;
int i, n;
f->flags = 0;
f->width = f->prec = 0;
for(;;){
if(isrunes){
r = *(Rune*)fmt;
fmt = (Rune*)fmt + 1;
}else{
fmt = (char*)fmt + chartorune(&rune, fmt);
r = rune;
}
f->r = r;
switch(r){
case '\0':
return nil;
case '.':
f->flags |= FmtWidth|FmtPrec;
continue;
case '0':
if(!(f->flags & FmtWidth)){
f->flags |= FmtZero;
continue;
}
/* fall through */
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
i = 0;
while(r >= '0' && r <= '9'){
i = i * 10 + r - '0';
if(isrunes){
r = *(Rune*)fmt;
fmt = (Rune*)fmt + 1;
}else{
r = *(char*)fmt;
fmt = (char*)fmt + 1;
}
}
if(isrunes)
fmt = (Rune*)fmt - 1;
else
fmt = (char*)fmt - 1;
numflag:
if(f->flags & FmtWidth){
f->flags |= FmtPrec;
f->prec = i;
}else{
f->flags |= FmtWidth;
f->width = i;
}
continue;
case '*':
i = va_arg(f->args, int);
if(i < 0){
i = -i;
f->flags |= FmtLeft;
}
goto numflag;
}
n = (*fmtfmt(r))(f);
if(n < 0)
return nil;
if(n == 0)
return fmt;
}
}