diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-24 08:49:33 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-05-24 08:49:33 +0000 |
commit | 8d018d3dae6ba0d59e255615758d31e59ed9cd9e (patch) | |
tree | 158dbff840b2880622ba4c201331aa0edde5f8b6 /src/bi_sprintf.m4 | |
parent | 21a7ce190fa8746b791a5697f8f9195b44a33de5 (diff) | |
download | mailfromd-8d018d3dae6ba0d59e255615758d31e59ed9cd9e.tar.gz mailfromd-8d018d3dae6ba0d59e255615758d31e59ed9cd9e.tar.bz2 |
Finish implementing sprintf
git-svn-id: file:///svnroot/mailfromd/trunk@1469 7a8a7f39-df28-0410-adc6-e0d955640f24
Diffstat (limited to 'src/bi_sprintf.m4')
-rw-r--r-- | src/bi_sprintf.m4 | 108 |
1 files changed, 99 insertions, 9 deletions
diff --git a/src/bi_sprintf.m4 b/src/bi_sprintf.m4 index 684cbea7..de1a571d 100644 --- a/src/bi_sprintf.m4 +++ b/src/bi_sprintf.m4 @@ -43,14 +43,16 @@ get_num(char *p, unsigned *pn) *pn = n; return p; } - + +#define __MF_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define SPRINTF_BUF_SIZE (__MF_MAX(3*sizeof(long), NUMERIC_BUFSIZE_BOUND) + 2) MF_DEFUN_VARARGS(sprintf, STRING, STRING format) { int i = 0; char *p = format; char *start; - char buf[NUMERIC_BUFSIZE_BOUND+1]; + char buf[SPRINTF_BUF_SIZE]; printf_format_state state = fmts_copy; int flags = 0; unsigned width = 0; @@ -64,6 +66,7 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) char *str; long num; int negative; + char fmtbuf[] = { '%', 'x', 0 }; switch (state) { case fmts_copy: @@ -185,7 +188,8 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) break; case fmts_prec_arg: - /* Expect precision argument position -- %2$#*1$.*_3$ */ + /* Expect precision argument position -- + %2$#*1$.*_3$ */ state = fmts_conv; if (isdigit(*p)) { char *q = get_num(p, &n); @@ -236,8 +240,9 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) } else negative = 0; /* If a precision is given with a - numeric conversion, the 0 flag is ignored. */ - /* A - overrides a 0 if both are given.*/ + numeric conversion, the 0 flag is ignored. + */ + /* A - overrides a 0 if both are given. */ if (prec || (flags & FMT_ADJUST_LEFT)) flags &= ~FMT_PADZERO; snprintf(buf+1, sizeof(buf)-1, "%ld", num); @@ -264,7 +269,9 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) if (width && width > n) { char *q; MF_GROW_TEMP_SPACE(NULL, width, q); - memset(q, (flags & FMT_PADZERO) ? '0' : ' ', + memset(q, + (flags & FMT_PADZERO) ? + '0' : ' ', width); if (flags & FMT_ADJUST_LEFT) memcpy(q, str, n); @@ -281,8 +288,10 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) break; case 'u': + num = MF_VA_ARG(argnum,NUMBER); /* If a precision is given with a - numeric conversion, the 0 flag is ignored. */ + numeric conversion, the 0 flag is ignored. + */ /* A - overrides a 0 if both are given.*/ if (prec || (flags & FMT_ADJUST_LEFT)) flags &= ~FMT_PADZERO; @@ -292,12 +301,15 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) if (prec && prec > n) { memmove(str + prec - n, str, n + 1); memset(str, '0', prec - n); + n = prec; } if (width && width > n) { char *q; MF_GROW_TEMP_SPACE(NULL, width, q); - memset(q, (flags & FMT_PADZERO) ? '0' : ' ', + memset(q, + (flags & FMT_PADZERO) ? + '0' : ' ', width); if (flags & FMT_ADJUST_LEFT) memcpy(q, str, n); @@ -309,8 +321,86 @@ MF_DEFUN_VARARGS(sprintf, STRING, STRING format) case 'x': case 'X': + num = MF_VA_ARG(argnum,NUMBER); + /* If a precision is given with a + numeric conversion, the 0 flag is ignored. + */ + /* A - overrides a 0 if both are given.*/ + if (prec || (flags & FMT_ADJUST_LEFT)) + flags &= ~FMT_PADZERO; + fmtbuf[1] = *p; + snprintf(buf+2, sizeof(buf)-2, fmtbuf, num); + str = buf + 2; + n = strlen(str); + if (prec && prec > n) { + memmove(str + prec - n, str, n + 1); + memset(str, '0', prec - n); + n = prec; + } + + if (flags & FMT_ALTERNATE) { + *--str = *p; + *--str = '0'; + n += 2; + } + + if (width && width > n) { + char *q; + MF_GROW_TEMP_SPACE(NULL, width, q); + memset(q, + (flags & FMT_PADZERO) ? + '0' : ' ', + width); + if (flags & FMT_ADJUST_LEFT) + memcpy(q, str, n); + else { + if (flags & FMT_ALTERNATE + && flags & FMT_PADZERO) { + q[0] = *str++; + q[1] = *str++; + n -= 2; + } + memcpy(q + width - n, str, n); + } + } else + MF_GROW_TEMP_SPACE(str, n); + break; + case 'o': - /* FIXME */ + num = MF_VA_ARG(argnum,NUMBER); + /* If a precision is given with a + numeric conversion, the 0 flag is ignored. + */ + /* A - overrides a 0 if both are given.*/ + if (prec || (flags & FMT_ADJUST_LEFT)) + flags &= ~FMT_PADZERO; + snprintf(buf+1, sizeof(buf)-1, "%o", num); + str = buf + 2; + n = strlen(str); + if (prec && prec > n) { + memmove(str + prec - n, str, n + 1); + memset(str, '0', prec - n); + } + + if ((flags & FMT_ALTERNATE) && *str != '0') { + *--str = '0'; + n++; + } + + if (width && width > n) { + char *q; + MF_GROW_TEMP_SPACE(NULL, width, q); + memset(q, + (flags & FMT_PADZERO) ? + '0' : ' ', + width); + if (flags & FMT_ADJUST_LEFT) + memcpy(q, str, n); + else + memcpy(q + width - n, str, n); + } else + MF_GROW_TEMP_SPACE(str, n); + break; default: MF_GROW_TEMP_SPACE(start, p - start + 1); |