diff options
Diffstat (limited to 'src/builtin/sprintf.bi')
-rw-r--r-- | src/builtin/sprintf.bi | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/src/builtin/sprintf.bi b/src/builtin/sprintf.bi index 11effd58..0a927dd2 100644 --- a/src/builtin/sprintf.bi +++ b/src/builtin/sprintf.bi @@ -31,132 +31,133 @@ typedef enum { fmts_width_arg, /* Expect width argument position -- %2$#*_1$ */ fmts_prec, /* Expect precision */ fmts_prec_arg, /* Expect precision argument position */ fmts_conv /* Expect conversion specifier */ } printf_format_state; -char * -get_num(char *p, unsigned *pn) +static int +get_num(const char *p, int i, unsigned *pn) { unsigned n = 0; - for (; *p && mu_isdigit(*p); p++) - n = n * 10 + *p - '0'; + + for (; p[i] && mu_isdigit(p[i]); i++) + n = n * 10 + p[i] - '0'; *pn = n; - return p; + return i; } #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_NO_PROM(sprintf, STRING, STRING format) { int i = 0; - char *p = format; - char *start; + int cur = 0; + int start; char buf[SPRINTF_BUF_SIZE]; printf_format_state state = fmts_copy; int flags = 0; unsigned width = 0; unsigned prec = 0; unsigned argnum; MF_OBSTACK_BEGIN(); MF_VA_START(); - while (*p) { + while (format[cur]) { unsigned n; char *str; long num; int negative; char fmtbuf[] = { '%', 'x', 0 }; switch (state) { case fmts_copy: /* Expect `%', and copy all the rest verbatim */ - if (*p == '%') { - start = p; + if (format[cur] == '%') { + start = cur; state = fmts_pos; flags = 0; width = 0; prec = 0; } else - MF_OBSTACK_1GROW(*p); - p++; + MF_OBSTACK_1GROW(format[cur]); + cur++; break; case fmts_pos: /* Expect '%' or an argument position -- %_% or %_2$ */ - if (*p == '%') { + if (format[cur] == '%') { MF_OBSTACK_1GROW('%'); - p++; + cur++; state = fmts_copy; break; } - if (mu_isdigit(*p)) { - char *q = get_num(p, &n); - if (*q == '$') { + if (mu_isdigit(format[cur])) { + int pos = get_num(format, cur, &n); + if (format[pos] == '$') { argnum = n - 1; flags |= FMT_ALTPOS; - p = q + 1; + cur = pos + 1; } } state = fmts_flags; break; case fmts_flags: /* Expect flags -- %2$_# */ - switch (*p) { + switch (format[cur]) { case '#': flags |= FMT_ALTERNATE; - p++; + cur++; break; case '0': flags |= FMT_PADZERO; - p++; + cur++; break; case '-': flags |= FMT_ADJUST_LEFT; - p++; + cur++; break; case ' ': flags |= FMT_SPACEPFX; - p++; + cur++; break; case '+': flags |= FMT_SIGNPFX; - p++; + cur++; break; default: state = fmts_width; } break; case fmts_width: /* Expect width -- %2$#_8 or %2$#_* */ - if (mu_isdigit(*p)) { - p = get_num(p, &width); + if (mu_isdigit(format[cur])) { + cur = get_num(format, cur, &width); state = fmts_prec; - } else if (*p == '*') { - p++; + } else if (format[cur] == '*') { + cur++; state = fmts_width_arg; } else state = fmts_prec; break; case fmts_width_arg: /* Expect width argument position -- %2$#*_1$ */ state = fmts_prec; - if (mu_isdigit(*p)) { - char *q = get_num(p, &n); - if (*q == '$') { + if (mu_isdigit(format[cur])) { + int pos = get_num(format, cur, &n); + if (format[pos] == '$') { MF_VA_ARG(n-1, NUMBER, num); - p = q + 1; + cur = pos + 1; if (num < 0) { flags |= FMT_SPACEPFX; num = - num; } width = (unsigned) num; break; @@ -173,47 +174,47 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format) width = (unsigned) num; break; case fmts_prec: /* Expect precision -- %2$#*1$_. */ state = fmts_conv; - if (*p == '.') { - p++; - if (mu_isdigit(*p)) { - p = get_num(p, &prec); - } else if (*p == '*') { - p++; + if (format[cur] == '.') { + cur++; + if (mu_isdigit(format[cur])) { + cur = get_num(format, cur, &prec); + } else if (format[cur] == '*') { + cur++; state = fmts_prec_arg; } } break; case fmts_prec_arg: /* Expect precision argument position -- %2$#*1$.*_3$ */ state = fmts_conv; - if (mu_isdigit(*p)) { - char *q = get_num(p, &n); - if (*q == '$') { + if (mu_isdigit(format[cur])) { + int pos = get_num(format, cur, &n); + if (format[pos] == '$') { MF_VA_ARG(n-1, NUMBER, num); if (num > 0) prec = (unsigned) num; - p = q + 1; + cur = pos + 1; break; } } MF_VA_ARG(i, NUMBER, num); i++; if (num > 0) prec = (unsigned) num; break; case fmts_conv: /* Expect conversion specifier */ if (!(flags & FMT_ALTPOS)) argnum = i++; - switch (*p) { + switch (format[cur]) { case 's': MF_VA_ARG(argnum, STRING, str); n = strlen(str); if (prec && prec < n) n = prec; if (width) { @@ -328,24 +329,24 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format) /* 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; + fmtbuf[1] = format[cur]; 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 = format[cur]; *--str = '0'; n += 2; } if (width && width > n) { char *q; @@ -403,16 +404,17 @@ MF_DEFUN_VARARGS_NO_PROM(sprintf, STRING, STRING format) memcpy(q + width - n, str, n); } else MF_OBSTACK_GROW(str, n); break; default: - MF_OBSTACK_GROW(start, p - start + 1); + MF_OBSTACK_GROW(&format[start], + cur - start + 1); } - p++; + cur++; state = fmts_copy; } } MF_OBSTACK_1GROW(0); MF_VA_END(); MF_RETURN_OBSTACK(); |