aboutsummaryrefslogtreecommitdiff
path: root/editors
diff options
context:
space:
mode:
Diffstat (limited to 'editors')
-rw-r--r--editors/awk.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 75f757dbb..17710e57e 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2357,36 +2357,55 @@ static char *awk_printf(node *n, size_t *len)
2357 2357
2358 b = NULL; 2358 b = NULL;
2359 i = 0; 2359 i = 0;
2360 while (*f) { /* "print one format spec" loop */ 2360 while (1) { /* "print one format spec" loop */
2361 char *s; 2361 char *s;
2362 char c; 2362 char c;
2363 char sv; 2363 char sv;
2364 var *arg; 2364 var *arg;
2365 size_t slen; 2365 size_t slen;
2366 2366
2367 /* Find end of the next format spec, or end of line */
2367 s = f; 2368 s = f;
2368 while (*f && (*f != '%' || *++f == '%')) 2369 while (1) {
2369 f++; 2370 c = *f;
2370 while (*f && !isalpha(*f)) { 2371 if (!c) /* no percent chars found at all */
2371 if (*f == '*') 2372 goto nul;
2372 syntax_error("%*x formats are not supported");
2373 f++; 2373 f++;
2374 if (c == '%')
2375 break;
2374 } 2376 }
2377 /* we are past % in "....%..." */
2375 c = *f; 2378 c = *f;
2376 if (!c) { 2379 if (!c) /* "....%" */
2377 /* Tail of fmt with no percent chars, 2380 goto nul;
2378 * or "....%" (percent seen, but no format specifier char found) 2381 if (c == '%') { /* "....%%...." */
2379 */ 2382 slen = f - s;
2380 slen = strlen(s); 2383 s = xstrndup(s, slen);
2381 goto tail; 2384 f++;
2385 goto append; /* print "....%" part verbatim */
2382 } 2386 }
2383 sv = *++f; 2387 while (1) {
2384 *f = '\0'; 2388 if (isalpha(c))
2389 break;
2390 if (c == '*')
2391 syntax_error("%*x formats are not supported");
2392 c = *++f;
2393 if (!c) { /* "....%...." and no letter found after % */
2394 /* Example: awk 'BEGIN { printf "^^^%^^^\n"; }' */
2395 nul:
2396 slen = f - s;
2397 goto tail; /* print remaining string, exit loop */
2398 }
2399 }
2400 /* we are at A in "....%...A..." */
2401
2385 arg = evaluate(nextarg(&n), TMPVAR); 2402 arg = evaluate(nextarg(&n), TMPVAR);
2386 2403
2387 /* Result can be arbitrarily long. Example: 2404 /* Result can be arbitrarily long. Example:
2388 * printf "%99999s", "BOOM" 2405 * printf "%99999s", "BOOM"
2389 */ 2406 */
2407 sv = *++f;
2408 *f = '\0';
2390 if (c == 'c') { 2409 if (c == 'c') {
2391 char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg); 2410 char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg);
2392 char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */); 2411 char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */);
@@ -2405,13 +2424,14 @@ static char *awk_printf(node *n, size_t *len)
2405 } else if (strchr("eEfFgGaA", c)) { 2424 } else if (strchr("eEfFgGaA", c)) {
2406 s = xasprintf(s, d); 2425 s = xasprintf(s, d);
2407 } else { 2426 } else {
2427//TODO: GNU Awk 5.0.1: printf "%W" prints "%W", does not error out
2408 syntax_error(EMSG_INV_FMT); 2428 syntax_error(EMSG_INV_FMT);
2409 } 2429 }
2410 } 2430 }
2411 slen = strlen(s); 2431 slen = strlen(s);
2412 } 2432 }
2413 *f = sv; 2433 *f = sv;
2414 2434 append:
2415 if (i == 0) { 2435 if (i == 0) {
2416 b = s; 2436 b = s;
2417 i = slen; 2437 i = slen;
@@ -2421,7 +2441,7 @@ static char *awk_printf(node *n, size_t *len)
2421 b = xrealloc(b, i + slen + 1); 2441 b = xrealloc(b, i + slen + 1);
2422 strcpy(b + i, s); 2442 strcpy(b + i, s);
2423 i += slen; 2443 i += slen;
2424 if (!c) /* tail? */ 2444 if (!c) /* s is NOT allocated and this is the last part of string? */
2425 break; 2445 break;
2426 free(s); 2446 free(s);
2427 } 2447 }