aboutsummaryrefslogtreecommitdiff
path: root/sys/libfmt/do.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/libfmt/do.c')
-rw-r--r--sys/libfmt/do.c730
1 files changed, 0 insertions, 730 deletions
diff --git a/sys/libfmt/do.c b/sys/libfmt/do.c
deleted file mode 100644
index eaac0a3..0000000
--- a/sys/libfmt/do.c
+++ /dev/null
@@ -1,730 +0,0 @@
-#include "internal.h"
-#include <stdatomic.h>
-
-#define atomic _Atomic
-#define MaxFmt 128
-#define atomic·load atomic_load
-#define atomic·store atomic_store
-
-// -----------------------------------------------------------------------
-// globals
-
-/* built in verbs */
-static int fmtflag(fmt·State *);
-static int fmtpercent(fmt·State *);
-static int fmtrune(fmt·State *);
-static int fmtfloat(fmt·State *);
-static int fmtutf8(fmt·State *);
-static int fmtint(fmt·State *);
-static int fmtchar(fmt·State *);
-static int fmtcount(fmt·State *);
-static int fmtstring(fmt·State *);
-static int fmterror(fmt·State *);
-
-static int badfmt(fmt·State *);
-
-static struct
-{
- atomic int len;
- Verb verb[MaxFmt];
-} formatter =
-{
- ATOMIC_VAR_INIT(30),
- {
- {' ', fmtflag},
- {'#', fmtflag},
- {'%', fmtpercent},
- {'\'',fmtflag},
- {'+', fmtflag},
- {',', fmtflag},
- {'-', fmtflag},
- {'C', fmtrune},
- {'E', fmtfloat},
- {'F', fmtfloat},
- {'G', fmtfloat},
- {'L', fmtflag},
- {'S', fmtutf8},
- {'X', fmtint},
- {'b', fmtint},
- {'c', fmtchar},
- {'d', fmtint},
- {'e', fmtfloat},
- {'f', fmtfloat},
- {'g', fmtfloat},
- {'h', fmtflag},
- {'i', fmtint},
- {'l', fmtflag},
- {'n', fmtcount},
- {'o', fmtint},
- {'p', fmtint},
- {'r', fmterror},
- {'s', fmtstring},
- {'U', fmtflag},
- {'u', fmtint},
- {'x', fmtint},
- }
-};
-
-// -----------------------------------------------------------------------
-// internal functions
-
-static Formatter
-format(int c)
-{
- Verb *v, *e;
- e = &formatter.verb[atomic·load(&formatter.len)];
- for(v=e; v > formatter.verb; --v){
- if(v->c == c)
- return v->fmt;
- }
-
- return badfmt;
-}
-
-static char *
-dispatch(fmt·State *io, char *fmt)
-{
- rune r;
- int i, n;
-
- io->flag = 0;
- io->width = io->prec = 0;
-
- /*
- * the form of each print verb:
- * % [flags] verb
- * + the verb is a single character
- * + each flag is either
- * - a single character
- * - a decimal numeric string
- * - up to 2 decimal strings can be used
- * - [width|*].[prec|*]
- * - if missing, set to 0
- * - if *, grab from varargs
- */
- for(;;){
- fmt += utf8·decode(fmt, &r);
- io->verb = r;
- switch(r){
- case 0:
- return nil;
- case '.':
- io->flag |= fmt·Width|fmt·Prec;
- continue;
- case '0':
- if(!(io->flag & fmt·Width)){
- io->flag |= fmt·Zero;
- continue;
- }
- /* fallthrough */
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- i = 0;
- while('0' <= r && r <= '9'){
- i = 10*i + (r-'0');
- r = *fmt++;
- }
- fmt--;
- number:
- if(io->flag & fmt·Width){
- io->flag |= fmt·Prec;
- io->prec = i;
- }else{
- io->flag |= fmt·Width;
- io->width = i;
- }
- continue;
- case '*':
- i = va_arg(io->args, int);
- if(i < 0){
- if(io->flag&fmt·Prec){
- io->flag &= ~fmt·Prec;
- io->prec = 0;
- continue;
- }
- i = -i;
- io->flag |= fmt·Left;
- }
- goto number;
- }
- n = format(r)(io);
- if(n < 0)
- return nil;
- if(!n)
- return fmt;
- }
-}
-
-static char *
-flush(fmt·State *io, char *b, int len)
-{
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(!io->flush || !(*io->flush)(io) || io->buffer.cur + len >= io->buffer.end) {
- io->buffer.end = io->buffer.cur;
- return nil;
- }
- return io->buffer.cur;
-}
-
-static int
-pad(fmt·State *io, int n)
-{
- int i;
- char *b=io->buffer.cur, *e=io->buffer.end;
-
- for(i=0; i<n; i++){
- if(b>=e){
- if(!(b=flush(io, b, 1)))
- return -1;
- e = io->buffer.end;
- }
- *b++ = ' ';
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- return 0;
-}
-
-static int
-copy(fmt·State *io, char *m, int sz, int n)
-{
- ulong f;
- rune r;
- int nc, w, nb;
- char *b, *e, *me;
-
- w = 0;
- f = io->flag;
- me = m + sz;
-
- if(f&fmt·Width)
- w = io->width;
- if(f&fmt·Prec && n > io->prec)
- n = io->prec;
- if(!(f&fmt·Left) && pad(io, w-n)<0)
- return -1;
-
- b = io->buffer.cur;
- e = io->buffer.end;
-
- for(nc=n; nc>0; nc--){
- r = *(uchar *)m;
- if(utf8·onebyte(r)){
- nb=1;
- m++;
- }else if((me-m) >= UTFmax || utf8·canfit(m, me-m)){
- nb=utf8·decode(m, &r);
- m+=n;
- }else
- break;
-
- if(b+n>e){
- if(!(b=flush(io, b, nb)))
- return -1;
- e = io->buffer.end;
- }
- b += utf8·encode(&r, b);
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(f&fmt·Left && pad(io, w-n)<0)
- return -1;
-
- return 0;
-}
-
-static int
-copyrune(fmt·State *io, rune *m, int n)
-{
- ulong f;
- rune r, *me;
- int w, nb;
- char *b, *e;
-
- w = 0;
- f = io->flag;
-
- if(f&fmt·Width)
- w = io->width;
- if(f&fmt·Prec && n > io->prec)
- n = io->prec;
-
- if(!(f&fmt·Left) && pad(io, w-n)<0)
- return -1;
-
- b = io->buffer.cur;
- e = io->buffer.end;
-
- for(me=m+n; m < me; m++){
- r = *m;
- nb = utf8·runelen(r);
- if(b + nb > e){
- if(!(b=flush(io, b, nb)))
- return -1;
- e = io->buffer.end;
- }
- b += utf8·encode(&r, b);
- }
-
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(f&fmt·Left && pad(io, w-n)<0)
- return -1;
-
- return 0;
-}
-
-static int
-copystring(fmt·State *io, char *s)
-{
- rune r;
- int i,j;
-
- if(!s)
- return copy(io, "<nil>", 5, 5);
-
- if(io->flag&fmt·Prec){
- i = 0;
- for(j=0; j < io->prec && s[i]; j++)
- i += utf8·decode(s+i, &r);
-
- return copy(io, s, i, j);
- }
- return copy(io, s, strlen(s), utf8·len(s));
-}
-
-static int
-copyutf8(fmt·State *io, rune *s)
-{
- rune *e;
- int n,p;
-
- if(!s)
- return copy(io, "<nil>", 5, 5);
-
- if(io->flag & fmt·Prec){
- p = io->prec;
- for(n=0; n<p; n++)
- if(!s[n])
- break;
- }else{
- for(e=s; *e; e++)
- ;
- n = e - s;
- }
-
- return copyrune(io, s, n);
-}
-
-// -----------------------------------------------------------------------
-// format helpers
-
-static int
-needseperate(int *digits, char **groups)
-{
- int group;
-
- (*digits)++;
- group = *(uchar *)*groups;
-
- if(group == 0xFF || group == 0x7f || group == 0x00)
- return 0;
- if(*digits > group){
- if((*groups)[1] != 0)
- (*groups)++;
- *digits = 1;
- return 1;
- }
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// formatters
-
-static int
-fmtchar(fmt·State *io)
-{
- char x[1];
- x[0] = va_arg(io->args, int);
- io->prec = 1;
-
- return copy(io, x, 1, 1);
-}
-
-static int
-fmtstring(fmt·State *io)
-{
- char *s;
- s = va_arg(io->args, char *);
- return copystring(io, s);
-}
-
-static int
-fmterror(fmt·State *io)
-{
- char *s;
- s = strerror(errno);
- return copystring(io, s);
-}
-
-static int
-fmtrune(fmt·State *io)
-{
- rune x[1];
-
- x[0] = va_arg(io->args, int);
- return copyrune(io, x, 1);
-}
-
-static int
-fmtutf8(fmt·State *io)
-{
- rune *s;
-
- s = va_arg(io->args, rune *);
- return copyutf8(io, s);
-}
-
-static int
-fmtpercent(fmt·State *io)
-{
- rune x[1];
-
- x[0] = io->verb;
- io->prec = 1;
- return copyrune(io, x, 1);
-}
-
-static int
-fmtint(fmt·State *io)
-{
- union{
- ulong u;
- uvlong v;
- } val;
- int neg, base, i, n, f, w, isv;
- int digits, bytes, runes, excess;
- char *groups, *thousands;
- char *p, *conv, buf[140];
-
- f = io->flag;
- neg = 0;
- isv = 0;
- val.u = 0;
-
- switch(io->verb){
- case 'o': case 'p': case 'u': case 'x': case 'X':
- f |= fmt·Unsigned;
- f &= ~(fmt·Sign|fmt·Space);
- }
-
- /* set flags */
- if(io->verb=='p'){
- val.u = (ulong)va_arg(io->args, void*);
- io->verb = 'x';
- f |= fmt·Unsigned;
- }else if(f&fmt·Vlong){
- isv=1;
- if(f&fmt·Unsigned)
- val.v = va_arg(io->args, uvlong);
- else
- val.v = va_arg(io->args, vlong);
- }else if(f&fmt·Long){
- if(f&fmt·Unsigned)
- val.u = va_arg(io->args, ulong);
- else
- val.u = va_arg(io->args, long);
- }else if(f&fmt·Byte){
- if(f&fmt·Unsigned)
- val.u = (uchar)va_arg(io->args, int);
- else
- val.u = (char)va_arg(io->args, int);
- }else if(f&fmt·Short){
- if(f&fmt·Unsigned)
- val.u = (ushort)va_arg(io->args, int);
- else
- val.u = (short)va_arg(io->args, int);
- }else{
- if(f&fmt·Unsigned)
- val.u = va_arg(io->args, uint);
- else
- val.u = va_arg(io->args, int);
- }
-
- conv = "0123456789abcdef";
- groups = "\4";
- thousands = io->thousands;
- /* get base */
- switch(io->verb){
- case 'd': case 'i': case 'u':
- base = 10;
- groups = io->groups;
- break;
- case 'X':
- conv = "0123456789ABCDEF";
- /*fallthrough*/
- case 'x':
- base = 16;
- thousands = ":";
- break;
- case 'b':
- base = 2;
- thousands = ":";
- break;
- case 'o':
- base = 8;
- break;
- default:
- return -1;
- }
-
- /* check for negativity */
- if(!(f&fmt·Unsigned)){
- if(isv && (vlong)val.v < 0){
- val.v = -(vlong)val.v;
- neg = 1;
- }else if(!isv && (long)val.u < 0){
- val.u = -(long)val.u;
- neg = 1;
- }
- }
-
- p = buf + sizeof(buf) - 1;
- n = 0;
- digits = 0;
- excess = 0;
- runes = utf8·len(thousands);
- bytes = strlen(thousands);
-
-#define PARSE(VALUE) \
- while((VALUE)){ \
- i = (VALUE) % base; \
- (VALUE) /= base; \
- if((f&fmt·Comma) && n%4 == 3){ \
- *p-- = ','; \
- n++; \
- } \
- if((f&fmt·Apost) && needseperate(&digits, &groups)){ \
- n += runes; \
- excess += bytes - runes; \
- p -= bytes; \
- memmove(p+1, thousands, bytes); \
- } \
- *p-- = conv[i]; \
- n++; \
- }
- if(isv)
- PARSE(val.v)
- else
- PARSE(val.u)
-#undef PARSE
-
- if(!n){
- if(!(f&fmt·Prec) || io->prec != 0 || (io->verb == 'o' && (f&fmt·Sharp))){
- *p-- = '0';
- n = 1;
- if(f&fmt·Apost)
- needseperate(&digits,&groups);
- }
-
- if(io->verb == 'x' || io->verb == 'X')
- f &= ~fmt·Sharp;
- }
-
- for(w = io->prec; n < w && p > buf+3; n++){
- if((f&fmt·Apost) && needseperate(&digits, &groups)){
- n += runes;
- excess += bytes - runes;
- p -= bytes;
- memmove(p+1, thousands, bytes);
- }
- *p-- = '0';
- }
-
- if(neg || (f&(fmt·Sign|fmt·Space)))
- n++;
-
- if(f&fmt·Sharp){
- if(base==16)
- n += 2;
- else if(base == 8){
- if(p[1] == '0')
- f &= ~fmt·Sharp;
- else
- n++;
- }
- }
-
- if(f&fmt·Zero && !(f & (fmt·Left|fmt·Prec))){
- w = 0;
- if(f & fmt·Width)
- w = io->width;
- for(; n < w && p > buf+3; n++){
- if((f & fmt·Apost) && needseperate(&digits, &groups)){
- n += runes;
- excess += bytes - runes;
- p -= bytes;
- memmove(p+1, thousands, bytes);
- }
- *p-- = '0';
- }
- io->flag &= ~fmt·Width;
- }
-
- if(f&fmt·Sharp){
- if(base==16)
- *p-- = io->verb;
- if(base==16 || base == 8)
- *p-- = '0';
- }
-
- if(neg)
- *p-- = '-';
- else if(f & fmt·Sign)
- *p-- = '+';
- else if (f & fmt·Space)
- *p-- = ' ';
-
- io->flag &= ~fmt·Prec;
- return copy(io, p+1, n+excess, n);
-}
-
-static int
-fmtcount(fmt·State *io)
-{
- void *p;
- ulong f;
-
- f = io->flag;
- p = va_arg(io->args, void*);
-
- if(f&fmt·Vlong)
- *(vlong*)p = io->n;
- else if(f&fmt·Long)
- *(long*)p = io->n;
- else if(f&fmt·Byte)
- *(char*)p = io->n;
- else if(f&fmt·Short)
- *(short*)p = io->n;
- else
- *(int*)p = io->n;
-
- return 0;
-}
-
-static int
-fmtflag(fmt·State *io)
-{
- switch(io->verb){
- case ',': io->flag |= fmt·Comma; break;
- case '-': io->flag |= fmt·Left; break;
- case '+': io->flag |= fmt·Sign; break;
- case '#': io->flag |= fmt·Sharp; break;
- case '\'': io->flag |= fmt·Apost; break;
- case ' ': io->flag |= fmt·Space; break;
- case 'u': io->flag |= fmt·Unsigned; break;
- case 'L': io->flag |= fmt·Ldouble; break;
- case 'h':
- if(io->flag&fmt·Short)
- io->flag |= fmt·Byte;
- io->flag |= fmt·Short;
- break;
- case 'l':
- if(io->flag&fmt·Long)
- io->flag |= fmt·Vlong;
- io->flag |= fmt·Long;
- break;
- }
- return 1;
-}
-
-static int
-badfmt(fmt·State *io)
-{
- int n;
- char x[UTFmax+2];
-
- x[0] = '%';
- n = 1 + utf8·encode(&io->verb, x+1);
- x[n++] = '%';
- io->prec = n;
- copy(io, x, n, n);
-
- return 0;
-}
-
-#include "float.c"
-
-// -----------------------------------------------------------------------
-// exports
-
-int
-fmt·do(fmt·State *io, char *fmt)
-{
- rune r;
- int c, n;
- char *b, *e;
-
- for(;;){
- b = io->buffer.cur;
- e = io->buffer.end;
- while((c = *(uchar *)fmt) && c != '%'){
- if(utf8·onebyte(c)){
- if(b >= e){
- if(!(b=flush(io, b, 1)))
- return -1;
- e = io->buffer.end;
- }
- *b++ = *fmt++;
- }else{
- n = utf8·decode(fmt, &r);
- if(b + n > e){
- if(!(b=flush(io, b, n)))
- return -1;
- e = io->buffer.end;
- }
- while(n--)
- *b++ = *fmt++;
- }
- }
- fmt++;
- io->n += b - io->buffer.cur;
- io->buffer.cur = b;
- if(!c) /* we hit our nul terminator */
- return io->n - n;
- io->buffer.end = e;
-
- if(!(fmt=dispatch(io, fmt)))
- return -1;
- }
-}
-
-int
-fmt·install(int verb, Formatter func)
-{
- Verb *v;
- int i, ret;
-
-lock:
- if(verb <= 0 || verb >= 65536){
- ret = -1;
- goto unlock;
- }
- if(!func)
- func = badfmt;
-
- if((i = atomic·load(&formatter.len))==MaxFmt)
- return -1;
-
- v = &formatter.verb[i];
- v->c = verb;
- v->fmt = func;
-
- atomic·store(&formatter.len, i+1);
- ret = 0;
-unlock:
- return ret;
-}