Fix printf format conversions. (#59)

Further simplify printf % parsing by eating the length specifiers
during the copy phase, and substitute 'j' when finalizing the format.
Add some more tests for this.
This commit is contained in:
zoulasc 2019-12-11 02:17:34 -05:00 committed by Arnold Robbins
parent af86dacfad
commit a96aebbbd6
2 changed files with 16 additions and 18 deletions

18
run.c
View File

@ -855,7 +855,12 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
for (t = fmt; (*t++ = *s) != '\0'; s++) {
if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
FATAL("format item %.30s... ran format() out of memory", os);
if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
/* Ignore size specifiers */
if (strchr("hjLlqtz", *s)) {
t--;
continue;
}
if (isalpha((uschar)*s))
break; /* the ansi panoply */
if (*s == '$') {
FATAL("'$' not permitted in awk formats");
@ -889,15 +894,8 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co
case 'f': case 'e': case 'g': case 'E': case 'G':
flag = 'f';
break;
case 'd': case 'i':
flag = 'd';
if(*(s-1) == 'l') break;
*(t-1) = 'j';
*t = 'd';
*++t = '\0';
break;
case 'o': case 'x': case 'X': case 'u':
flag = *(s-1) == 'l' ? 'd' : 'u';
case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
flag = *s == 'd' || *s == 'i' ? 'd' : 'u';
*(t-1) = 'j';
*t = *s;
*++t = '\0';

View File

@ -167,15 +167,15 @@ try { printf("a%-*.*sb\n", $1, $2, "hello") }
2 1 ah b
3 1 ah b
try { printf("%d %ld\n", $1, $1) }
1 1 1
10 10 10
10000 10000 10000
try { printf("%d %ld %lld %zd %jd %hd %hhd\n", $1, $1, $1, $1, $1, $1, $1) }
1 1 1 1 1 1 1 1
10 10 10 10 10 10 10 10
10000 10000 10000 10000 10000 10000 10000 10000
try { printf("%x %lx\n", $1, $1) }
1 1 1
10 a a
10000 2710 2710
try { printf("%x %lx %llx %zx %jx %hx %hhx\n", $1, $1, $1, $1, $1, $1, $1) }
1 1 1 1 1 1 1 1
10 a a a a a a a
10000 2710 2710 2710 2710 2710 2710 2710
try { if ($1 ~ $2) print 1; else print 0 }
a \141 1