summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-03-21 00:24:20 +0100
committerGitHub <noreply@github.com>2022-03-21 00:24:20 +0100
commit718dfbda7d58308054ec7c6d9340751e97811d5d (patch)
treef461f2dc89f5cea5ccbf4a6200b539dbe883eab6 /lib.c
parenta88aca97633c2ec58987a76a5a8d910c37680e07 (diff)
parent668c5c02e56b922aeb7b8870057622b6940413d2 (diff)
Merge pull request #53 from jow-/string-format-argpos-support
lib: add argument position support (`%m$`) to `sprintf()` and `printf()`
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/lib.c b/lib.c
index 6290420..8fdf2ec 100644
--- a/lib.c
+++ b/lib.c
@@ -1198,7 +1198,7 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
uint32_t conv, flags, width, precision;
uc_value_t *fmt = uc_fn_arg(0), *arg;
const char *fstr, *last, *p, *cfmt;
- size_t argidx = 1, sfmtlen;
+ size_t argidx = 1, argpos, sfmtlen;
uint64_t u;
int64_t n;
double d;
@@ -1218,6 +1218,26 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
width = 0;
precision = 0;
+ argpos = argidx;
+
+ if (*p >= '1' && *p <= '9') {
+ while (isdigit(*p))
+ width = width * 10 + (*p++ - '0');
+
+ /* if a dollar sign follows, this is an argument index */
+ if (*p == '$') {
+ argpos = width;
+ width = 0;
+ p++;
+ }
+
+ /* otherwise skip to parsing precision, flags can't possibly follow */
+ else {
+ flags |= FMT_F_WIDTH;
+ goto parse_precision;
+ }
+ }
+
while (*p != '\0' && strchr("#0- +", *p)) {
switch (*p++) {
case '#': flags |= FMT_F_ALT; break;
@@ -1235,6 +1255,7 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
flags |= FMT_F_WIDTH;
}
+parse_precision:
if (*p == '.') {
p++;
@@ -1374,7 +1395,8 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
break;
case FMT_C_INT:
- arg = uc_fn_arg(argidx++);
+ argidx++;
+ arg = uc_fn_arg(argpos);
n = ucv_to_integer(arg);
if (errno == ERANGE)
@@ -1384,7 +1406,8 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
break;
case FMT_C_UINT:
- arg = uc_fn_arg(argidx++);
+ argidx++;
+ arg = uc_fn_arg(argpos);
u = ucv_to_unsigned(arg);
if (errno == ERANGE)
@@ -1394,17 +1417,20 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
break;
case FMT_C_DBL:
- d = ucv_to_double(uc_fn_arg(argidx++));
+ argidx++;
+ d = ucv_to_double(uc_fn_arg(argpos));
ucv_stringbuf_printf(buf, sfmt, d);
break;
case FMT_C_CHR:
- n = ucv_to_integer(uc_fn_arg(argidx++));
+ argidx++;
+ n = ucv_to_integer(uc_fn_arg(argpos));
ucv_stringbuf_printf(buf, sfmt, (int)n);
break;
case FMT_C_STR:
- arg = uc_fn_arg(argidx++);
+ argidx++;
+ arg = uc_fn_arg(argpos);
switch (ucv_type(arg)) {
case UC_STRING:
@@ -1424,8 +1450,9 @@ uc_printf_common(uc_vm_t *vm, size_t nargs, uc_stringbuf_t *buf)
break;
case FMT_C_JSON:
+ argidx++;
s = ucv_to_jsonstring_formatted(vm,
- uc_fn_arg(argidx++),
+ uc_fn_arg(argpos),
precision > 0 ? (precision > 1 ? ' ' : '\t') : '\0',
precision > 0 ? (precision > 1 ? precision - 1 : 1) : 0);