diff options
-rw-r--r-- | src/builtin/sprintf.bi | 96 | ||||
-rw-r--r-- | src/prog.c | 21 |
2 files changed, 63 insertions, 54 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(); @@ -381,13 +381,13 @@ static void env_register_auto(eval_environ_t env, void *ptr); void env_get_locus(eval_environ_t env, struct mu_locus_range *locus) { mu_locus_range_init(locus); locus->beg.mu_file = (char*)(env->dataseg + env->locus.file); - env_register_auto(env, (void*) locus->beg.mu_file); + env_register_auto(env, (void*) &locus->beg.mu_file); locus->beg.mu_line = env->locus.line; #if 0 locus->beg.mu_col = env->locus.point; ... #endif } @@ -490,38 +490,45 @@ env_function_cleanup_add(eval_environ_t env, void *data, The auto_ptr array is cleared (by calling env_unregister_autos) after executing each instruction (see eval_environment). */ static void env_register_auto(eval_environ_t env, void *ptr) { + char *addr = *(char**)ptr; + if (env->numautos == MAX_AUTO_PTR) runtime_error(env, "INTERNAL ERROR at %s:%d, please report", __FILE__, __LINE__); + /* Check if address is within the dataseg */ + if (!(addr >= (char*) env->dataseg + && (addr < (char*) (env->dataseg + datasize + env->stack_size)))) + ptr = NULL; env->auto_ptr[env->numautos++] = ptr; } /* Pop the last registered auto variable */ -void +static void env_pop_auto(eval_environ_t env) { env->numautos--; } -void +static void env_unregister_autos(eval_environ_t env) { env->numautos = 0; } -void +static void env_fixup_autos(eval_environ_t env, ptrdiff_t offset) { int i; for (i = 0; i < env->numautos; i++) { STKVAL *pptr = env->auto_ptr[i]; - mf_c_val(*pptr,str) += offset; /*FIXME*/ + if (pptr) + mf_c_val(*pptr,str) += offset; /*FIXME*/ } } int expand_dataseg(eval_environ_t env, size_t count, const char *errtext) @@ -796,13 +803,13 @@ heap_obstack_finish(eval_environ_t env) void * heap_obstack_grow(eval_environ_t env, void * MFL_DATASEG ptr, size_t size) { size_t words = B2STACK(size); char *ret; - env_register_auto(env, ptr); + env_register_auto(env, (void*) &ptr); if (env->tos - env->toh < words + B2STACK(env->temp_size)) expand_dataseg(env, words, _("memory chunk too big to fit into heap")); ret = (char*) env_data_ref(env, env->temp_start) + env->temp_size; if (ptr) memmove(ret, ptr, size); @@ -826,13 +833,13 @@ env_data_ref(eval_environ_t env, size_t off) void pushs(eval_environ_t env, const char * MFL_DATASEG s) { size_t off; - env_register_auto(env, (void*) s); + env_register_auto(env, (void*) &s); off = heap_reserve(env, strlen(s) + 1); strcpy((char*) env_data_ref(env, off), s); env_pop_auto(env); push(env, (STKVAL) off); } |