aboutsummaryrefslogtreecommitdiff
path: root/src/bi_sprintf.m4
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-05-24 08:49:33 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-05-24 08:49:33 +0000
commit8d018d3dae6ba0d59e255615758d31e59ed9cd9e (patch)
tree158dbff840b2880622ba4c201331aa0edde5f8b6 /src/bi_sprintf.m4
parent21a7ce190fa8746b791a5697f8f9195b44a33de5 (diff)
downloadmailfromd-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.m4108
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);

Return to:

Send suggestions and report system problems to the System administrator.