awk: unbreak "printf('%c') can output NUL" testcase
function old new delta awk_printf 546 593 +47 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
3d57a84907
commit
4ef8841b21
@ -2309,11 +2309,11 @@ static int awk_getline(rstream *rsm, var *v)
|
|||||||
#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS
|
#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS
|
||||||
# define awk_printf(a, b) awk_printf(a)
|
# define awk_printf(a, b) awk_printf(a)
|
||||||
#endif
|
#endif
|
||||||
static char *awk_printf(node *n, int *len)
|
static char *awk_printf(node *n, size_t *len)
|
||||||
{
|
{
|
||||||
char *b;
|
char *b;
|
||||||
char *fmt, *f;
|
char *fmt, *f;
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
//tmpvar = nvalloc(1);
|
//tmpvar = nvalloc(1);
|
||||||
#define TMPVAR (&G.awk_printf__tmpvar)
|
#define TMPVAR (&G.awk_printf__tmpvar)
|
||||||
@ -2333,6 +2333,7 @@ static char *awk_printf(node *n, int *len)
|
|||||||
char c;
|
char c;
|
||||||
char sv;
|
char sv;
|
||||||
var *arg;
|
var *arg;
|
||||||
|
size_t slen;
|
||||||
|
|
||||||
s = f;
|
s = f;
|
||||||
while (*f && (*f != '%' || *++f == '%'))
|
while (*f && (*f != '%' || *++f == '%'))
|
||||||
@ -2347,6 +2348,7 @@ static char *awk_printf(node *n, int *len)
|
|||||||
/* Tail of fmt with no percent chars,
|
/* Tail of fmt with no percent chars,
|
||||||
* or "....%" (percent seen, but no format specifier char found)
|
* or "....%" (percent seen, but no format specifier char found)
|
||||||
*/
|
*/
|
||||||
|
slen = strlen(s);
|
||||||
goto tail;
|
goto tail;
|
||||||
}
|
}
|
||||||
sv = *++f;
|
sv = *++f;
|
||||||
@ -2357,31 +2359,38 @@ static char *awk_printf(node *n, int *len)
|
|||||||
* printf "%99999s", "BOOM"
|
* printf "%99999s", "BOOM"
|
||||||
*/
|
*/
|
||||||
if (c == 'c') {
|
if (c == 'c') {
|
||||||
s = xasprintf(s, is_numeric(arg) ?
|
c = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg);
|
||||||
(char)getvar_i(arg) : *getvar_s(arg));
|
s = xasprintf(s, c);
|
||||||
} else if (c == 's') {
|
/* + 1 if c == NUL: handle printf "%c" 0 case
|
||||||
s = xasprintf(s, getvar_s(arg));
|
* (and printf "%22c" 0 etc, but still fails for e.g. printf "%-22c" 0) */
|
||||||
|
slen = strlen(s) + (c == '\0');
|
||||||
} else {
|
} else {
|
||||||
double d = getvar_i(arg);
|
if (c == 's') {
|
||||||
if (strchr("diouxX", c)) {
|
s = xasprintf(s, getvar_s(arg));
|
||||||
//TODO: make it wider here (%x -> %llx etc)?
|
|
||||||
s = xasprintf(s, (int)d);
|
|
||||||
} else if (strchr("eEfFgGaA", c)) {
|
|
||||||
s = xasprintf(s, d);
|
|
||||||
} else {
|
} else {
|
||||||
syntax_error(EMSG_INV_FMT);
|
double d = getvar_i(arg);
|
||||||
|
if (strchr("diouxX", c)) {
|
||||||
|
//TODO: make it wider here (%x -> %llx etc)?
|
||||||
|
s = xasprintf(s, (int)d);
|
||||||
|
} else if (strchr("eEfFgGaA", c)) {
|
||||||
|
s = xasprintf(s, d);
|
||||||
|
} else {
|
||||||
|
syntax_error(EMSG_INV_FMT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
slen = strlen(s);
|
||||||
}
|
}
|
||||||
*f = sv;
|
*f = sv;
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
b = s;
|
b = s;
|
||||||
i = strlen(b);
|
i = slen;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tail:
|
tail:
|
||||||
b = xrealloc(b, i + strlen(s) + 1);
|
b = xrealloc(b, i + slen + 1);
|
||||||
i = stpcpy(b + i, s) - b;
|
strcpy(b + i, s);
|
||||||
|
i += slen;
|
||||||
if (!c) /* tail? */
|
if (!c) /* tail? */
|
||||||
break;
|
break;
|
||||||
free(s);
|
free(s);
|
||||||
@ -2926,7 +2935,6 @@ static var *evaluate(node *op, var *res)
|
|||||||
debug_printf_eval("PRINTF\n");
|
debug_printf_eval("PRINTF\n");
|
||||||
{
|
{
|
||||||
FILE *F = stdout;
|
FILE *F = stdout;
|
||||||
IF_FEATURE_AWK_GNU_EXTENSIONS(int len;)
|
|
||||||
|
|
||||||
if (op->r.n) {
|
if (op->r.n) {
|
||||||
rstream *rsm = newfile(R.s);
|
rstream *rsm = newfile(R.s);
|
||||||
@ -2966,6 +2974,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
}
|
}
|
||||||
fputs(getvar_s(intvar[ORS]), F);
|
fputs(getvar_s(intvar[ORS]), F);
|
||||||
} else { /* PRINTF */
|
} else { /* PRINTF */
|
||||||
|
IF_FEATURE_AWK_GNU_EXTENSIONS(size_t len;)
|
||||||
char *s = awk_printf(op1, &len);
|
char *s = awk_printf(op1, &len);
|
||||||
#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
|
#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
|
||||||
fwrite(s, len, 1, F);
|
fwrite(s, len, 1, F);
|
||||||
|
Loading…
Reference in New Issue
Block a user