X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fexpr-evl.c;h=3c7433753197d08caf4a7801da771409cbfa1cb7;hb=3e66793381d0eaee26bd980c9a5479129fa44386;hp=b8991547a359ae9a43f68331d9e9c536e4288e42;hpb=3a7fba81ceae5b049d0f7d671e9e3c3c43bbf703;p=pspp-builds.git diff --git a/src/expr-evl.c b/src/expr-evl.c index b8991547..3c743375 100644 --- a/src/expr-evl.c +++ b/src/expr-evl.c @@ -17,23 +17,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* AIX requires this to be the first thing in the file. */ #include -#if __GNUC__ -#define alloca __builtin_alloca -#else -#if HAVE_ALLOCA_H -#include -#else -#ifdef _AIX -#pragma alloca -#else -#ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -#endif -#endif -#endif -#endif #if TIME_WITH_SYS_TIME #include @@ -49,137 +33,92 @@ char *alloca (); #include #include "expr.h" #include "exprP.h" -#include +#include "error.h" #include #include #include -#include "approx.h" #include "data-in.h" #include "error.h" #include "julcal/julcal.h" #include "magic.h" +#include "misc.h" +#include "moments.h" +#include "pool.h" #include "random.h" -#include "stats.h" #include "str.h" #include "var.h" #include "vfm.h" #include "vfmP.h" -/* FIXME: This could be even more efficient if we caught SYSMIS when - it first reared its ugly head, then threw it into an entirely new - switch that handled SYSMIS aggressively like all the code does now. - But I've spent a couple of weeks on the expression code, and that's - enough to make anyone sick. For that matter, it could be more - efficient if I hand-coded it in assembly for a dozen processors, - but I'm not going to do that either. */ - -/* These macros are defined differently depending on the way that - the stack is managed. (i.e., I have to adapt the code to inferior - environments.) - - void CHECK_STRING_SPACE(int x): Assure that at least X+1 bytes of - space are available in the string evaluation stack. - - unsigned char *ALLOC_STRING_SPACE(int x): Return a pointer to X+1 - bytes of space. CHECK_STRING_SPACE must have previously been - called with an argument of at least X. */ - -#if PAGED_STACK -#define CHECK_STRING_SPACE(X) /* nothing to do! */ -#define ALLOC_STRING_SPACE(X) \ - alloca((X) + 1) -#else /* !PAGED_STACK */ -#define CHECK_STRING_SPACE(X) \ - do \ - { \ - if (str_stk + X >= str_end) \ - { \ - e->str_size += 1024; \ - e->str_stk = xrealloc (e->str_stk, e->str_size); \ - str_end = e->str_stk + e->str_size - 1; \ - } \ - } \ - while (0) - -#define ALLOC_STRING_SPACE(X) \ - (str_stk += X + 1, str_stk - X - 1) -#endif /* !PAGED_STACK */ - double -expr_evaluate (struct expression *e, struct ccase *c, union value *v) +expr_evaluate (const struct expression *e, const struct ccase *c, int case_num, + union value *v) { unsigned char *op = e->op; double *dbl = e->num; unsigned char *str = e->str; -#if !PAGED_STACK - unsigned char *str_stk = e->str_stk; - unsigned char *str_end = e->str_stk + e->str_size - 1; -#endif struct variable **vars = e->var; int i, j; /* Stack pointer. */ union value *sp = e->stack; + pool_clear (e->pool); + for (;;) { switch (*op++) { - case OP_PLUS: - sp -= *op - 1; - if (sp->f != SYSMIS) - for (i = 1; i < *op; i++) - { - if (sp[i].f == SYSMIS) - { - sp->f = SYSMIS; - break; - } - else - sp->f += sp[i].f; - } - op++; + case OP_ADD: + sp--; + if (sp[1].f == SYSMIS) + sp[0].f = SYSMIS; + else if (sp[0].f != SYSMIS) + sp[0].f += sp[1].f; + break; + case OP_SUB: + sp--; + if (sp[1].f == SYSMIS) + sp[0].f = SYSMIS; + else if (sp[0].f != SYSMIS) + sp[0].f -= sp[1].f; break; case OP_MUL: - sp -= *op - 1; - if (sp->f != SYSMIS) - for (i = 1; i < *op; i++) - { - if (sp[i].f == SYSMIS) - { - sp->f = SYSMIS; - break; - } - else - sp->f *= sp[i].f; - } - op++; + sp--; + if (sp[1].f == SYSMIS) + sp[0].f = SYSMIS; + else if (sp[0].f != SYSMIS) + sp[0].f *= sp[1].f; + break; + case OP_DIV: + sp--; + if (sp[1].f == SYSMIS || sp[1].f == 0.) + sp[0].f = SYSMIS; + else if (sp[0].f != SYSMIS) + sp[0].f /= sp[1].f; break; case OP_POW: sp--; if (sp[0].f == SYSMIS) { - if (approx_eq (sp[1].f, 0.0)) + if (sp[1].f == 0.0) sp->f = 1.0; } else if (sp[1].f == SYSMIS) { if (sp[0].f == 0.0) - /* SYSMIS**0 */ sp->f = 0.0; else sp->f = SYSMIS; } - else if (approx_eq (sp[0].f, 0.0) && approx_eq (sp[1].f, 0.0)) + else if (sp[0].f == 0.0 && sp[1].f <= 0.0) sp->f = SYSMIS; else sp->f = pow (sp[0].f, sp[1].f); break; case OP_AND: - /* Note that the equality operator (==) may be used here - (instead of approx_eq) because booleans are always - *exactly* 0, 1, or SYSMIS. + /* Note that booleans are always one of 0, 1, or SYSMIS. Truth table (in order of detection): @@ -250,7 +189,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_eq (sp[0].f, sp[1].f); + sp->f = sp[0].f == sp[1].f; } break; case OP_GE: @@ -260,7 +199,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_ge (sp[0].f, sp[1].f); + sp->f = sp[0].f >= sp[1].f; } break; case OP_GT: @@ -270,7 +209,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_gt (sp[0].f, sp[1].f); + sp->f = sp[0].f > sp[1].f; } break; case OP_LE: @@ -280,7 +219,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_le (sp[0].f, sp[1].f); + sp->f = sp[0].f <= sp[1].f; } break; case OP_LT: @@ -290,7 +229,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_lt (sp[0].f, sp[1].f); + sp->f = sp[0].f < sp[1].f; } break; case OP_NE: @@ -300,37 +239,37 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp[1].f == SYSMIS) sp->f = SYSMIS; else - sp->f = approx_ne (sp[0].f, sp[1].f); + sp->f = sp[0].f != sp[1].f; } break; /* String operators. */ - case OP_STRING_EQ: + case OP_EQ_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) == 0; break; - case OP_STRING_GE: + case OP_GE_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) >= 0; break; - case OP_STRING_GT: + case OP_GT_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) > 0; break; - case OP_STRING_LE: + case OP_LE_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) <= 0; break; - case OP_STRING_LT: + case OP_LT_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) < 0; break; - case OP_STRING_NE: + case OP_NE_STRING: sp--; sp[0].f = st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[1].c[1], sp[1].c[0]) != 0; @@ -393,7 +332,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) if (sp->f != SYSMIS) { errno = 0; - sp->f = log10 (sp->f); + sp->f = log (sp->f); if (errno) sp->f = SYSMIS; } @@ -452,8 +391,8 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp -= n_args - 1; if (sp->f == SYSMIS) break; - for (i = 1; i <= n_args; i++) - if (approx_eq (sp[0].f, sp[i].f)) + for (i = 1; i < n_args; i++) + if (sp[0].f == sp[i].f) { sp->f = 1.0; goto main_loop; @@ -466,37 +405,34 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) case OP_ANY_STRING: { int n_args = *op++; + int result = 0.0; sp -= n_args - 1; - for (i = 1; i <= n_args; i++) + for (i = 1; i < n_args; i++) if (!st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[i].c[1], sp[i].c[0])) { - sp->f = 1.0; - goto main_loop; + result = 1.0; + break; } - sp->f = 0.0; + sp->f = result; } break; case OP_CFVAR: { int n_args = *op++; - int nv = 0; - double sum[2] = - {0.0, 0.0}; + double weight, mean, variance; sp -= n_args - 1; - for (i = 0; i < n_args; i++) - if (sp[i].f != SYSMIS) - { - nv++; - sum[0] += sp[i].f; - sum[1] += sp[i].f * sp[i].f; - } - if (nv < *op++) + + moments_of_values (sp, n_args, + &weight, &mean, &variance, NULL, NULL); + + if (weight < *op++ || mean == SYSMIS + || mean == 0 || variance == SYSMIS) sp->f = SYSMIS; else - sp->f = calc_cfvar (sum, nv); + sp->f = sqrt (variance) / mean; } break; case OP_MAX: @@ -519,24 +455,29 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp->f = max; } break; + case OP_MAX_STRING: + { + int n_args = *op++; + int max_idx = 0; + + sp -= n_args - 1; + for (i = 1; i < n_args; i++) + if (st_compare_pad (&sp[i].c[1], sp[i].c[0], + &sp[max_idx].c[1], sp[max_idx].c[0]) > 0) + max_idx = i; + sp[0].c = sp[max_idx].c; + } + break; case OP_MEAN: { int n_args = *op++; - int nv = 0; - double sum[1] = - {0.0}; + double weight, mean; sp -= n_args - 1; - for (i = 0; i < n_args; i++) - if (sp[i].f != SYSMIS) - { - nv++; - sum[0] += sp[i].f; - } - if (nv < *op++) - sp->f = SYSMIS; - else - sp->f = calc_mean (sum, nv); + + moments_of_values (sp, n_args, + &weight, &mean, NULL, NULL, NULL); + sp->f = weight < *op++ ? SYSMIS : mean; } break; case OP_MIN: @@ -559,6 +500,19 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp->f = min; } break; + case OP_MIN_STRING: + { + int n_args = *op++; + int min_idx = 0; + + sp -= n_args - 1; + for (i = 1; i < n_args; i++) + if (st_compare_pad (&sp[i].c[1], sp[i].c[0], + &sp[min_idx].c[1], sp[min_idx].c[0]) < 0) + min_idx = i; + sp[0].c = sp[min_idx].c; + } + break; case OP_NMISS: { int n_args = *op++; @@ -591,11 +545,10 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp -= n_args - 1; if (sp->f == SYSMIS) break; - for (i = 1; i <= n_args; i += 2) + for (i = 1; i < n_args; i += 2) if (sp[i].f == SYSMIS || sp[i + 1].f == SYSMIS) continue; - else if (approx_ge (sp[0].f, sp[i].f) - && approx_le (sp[0].f, sp[i + 1].f)) + else if (sp[0].f >= sp[i].f && sp[0].f <= sp[i + 1].f) { sp->f = 1.0; goto main_loop; @@ -610,7 +563,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) int n_args = *op++; sp -= n_args - 1; - for (i = 1; i <= n_args; i += 2) + for (i = 1; i < n_args; i += 2) if (st_compare_pad (&sp[0].c[1], sp[0].c[0], &sp[i].c[1], sp[i].c[0]) >= 0 && st_compare_pad (&sp[0].c[1], sp[0].c[0], @@ -625,23 +578,12 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) case OP_SD: { int n_args = *op++; - int nv = 0; - double sum[2]; - - sum[0] = sum[1] = 0.0; + double weight, variance; sp -= n_args - 1; - for (i = 0; i < n_args; i++) - if (sp[i].f != SYSMIS) - { - nv++; - sum[0] += sp[i].f; - sum[1] += sp[i].f * sp[i].f; - } - if (nv < *op++) - sp->f = SYSMIS; - else - sp->f = calc_stddev (calc_variance (sum, nv)); + moments_of_values (sp, n_args, + &weight, NULL, &variance, NULL, NULL); + sp->f = weight < *op++ ? SYSMIS : sqrt (variance); } break; case OP_SUM: @@ -666,34 +608,54 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) case OP_VARIANCE: { int n_args = *op++; - int nv = 0; - double sum[2]; - - sum[0] = sum[1] = 0.0; + double weight, variance; sp -= n_args - 1; - for (i = 0; i < n_args; i++) - if (sp[i].f != SYSMIS) - { - nv++; - sum[0] += sp[i].f; - sum[1] += sp[i].f * sp[i].f; - } - if (nv < *op++) - sp->f = SYSMIS; - else - sp->f = calc_variance (sum, nv); + moments_of_values (sp, n_args, + &weight, NULL, &variance, NULL, NULL); + sp->f = weight < *op++ ? SYSMIS : variance; } break; /* Time construction function. */ - case OP_TIME_HMS: - sp -= 2; - if (sp[0].f == SYSMIS || sp[1].f == SYSMIS || sp[2].f == SYSMIS) - sp->f = SYSMIS; - else - sp->f = 60. * (60. * sp[0].f + sp[1].f) + sp[2].f; + case OP_TIME_HMS: + sp -= 2; + if (sp[0].f == SYSMIS || sp[1].f == SYSMIS || sp[2].f == SYSMIS) + sp->f = SYSMIS; + else + { + double min, max; + min = min (sp[0].f, min (sp[1].f, sp[2].f)); + max = max (sp[0].f, max (sp[1].f, sp[2].f)); + if (min < 0. && max > 0.) + { + msg (SW, _("TIME.HMS cannot mix positive and negative " + "in its arguments.")); + sp->f = SYSMIS; + } + else + sp->f = 60. * (60. * sp[0].f + sp[1].f) + sp[2].f; + } + break; + case OP_CTIME_DAYS: + if (sp->f != SYSMIS) + sp->f /= 60. * 60. * 24.; break; + case OP_CTIME_HOURS: + if (sp->f != SYSMIS) + sp->f /= 60. * 60; + break; + case OP_CTIME_MINUTES: + if (sp->f != SYSMIS) + sp->f /= 60.; + break; + case OP_TIME_DAYS: + if (sp->f != SYSMIS) + sp->f *= 60. * 60. * 24.; + break; + case OP_CTIME_SECONDS: + /* No-op. */ + break; /* Date construction functions. */ case OP_DATE_DMY: @@ -727,14 +689,19 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) break; case OP_DATE_WKYR: sp--; - if (sp[0].f == SYSMIS) + if (sp[0].f == SYSMIS || sp[1].f == SYSMIS) sp->f = SYSMIS; - else + else if (sp[0].f < 0. || sp[0].f > 53.) + { + msg (SW, _("Week argument to WKYR must be in range 0 to 53.")); + sp->f = SYSMIS; + } + else { - sp[1].f = yrmoda (sp[1].f, 1, 1); - if (sp->f != SYSMIS) - sp[1].f = 60. * 60. * 24. * (sp[1].f + 7. * (floor (sp[0].f) - 1.)); - sp->f = sp[1].f; + double result = yrmoda (sp[1].f, 1, 1); + if (result != SYSMIS) + result = 60. * 60. * 24. * (result + 7. * (sp->f - 1.)); + sp->f = result; } break; case OP_DATE_YRDAY: @@ -829,8 +796,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) int n_args = *op++; unsigned char *dest; - CHECK_STRING_SPACE (255); - dest = ALLOC_STRING_SPACE (255); + dest = pool_alloc (e->pool, 256); dest[0] = 0; sp -= n_args - 1; @@ -852,83 +818,116 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp[0].c = dest; } break; - case OP_INDEX: + case OP_INDEX_2: sp--; if (sp[1].c[0] == 0) sp->f = SYSMIS; else { int last = sp[0].c[0] - sp[1].c[0]; + int result = 0; for (i = 0; i <= last; i++) - if (!memcmp (&sp[0].c[i + 1], &sp[0].c[1], sp[0].c[0])) + if (!memcmp (&sp[0].c[i + 1], &sp[1].c[1], sp[1].c[0])) { - sp->f = i + 1; - goto main_loop; + result = i + 1; + break; } - sp->f = 0.0; + sp->f = result; } break; - case OP_INDEX_OPT: - { - /* Length of each search string. */ - int part_len = sp[2].f; - - sp -= 2; - if (sp[1].c[0] == 0 || part_len <= 0 || sp[2].f == SYSMIS - || sp[1].c[0] % part_len != 0) - sp->f = SYSMIS; - else - { - /* Last possible index. */ - int last = sp[0].c[0] - part_len; - - for (i = 0; i <= last; i++) - for (j = 0; j < sp[1].c[0]; j += part_len) - if (!memcmp (&sp[0].c[i], &sp[1].c[j], part_len)) - { - sp->f = i + 1; - goto main_loop; - } - sp->f = 0.0; - } - } - break; - case OP_RINDEX: + case OP_INDEX_3: + sp -= 2; + if (sp[1].c[0] == 0) + { + sp->f = SYSMIS; + break; + } + else if (sp[2].f == SYSMIS) + { + msg (SW, _("Argument 3 of RINDEX may not be system-missing.")); + sp->f = SYSMIS; + } + else + { + int part_len = sp[2].f; + int result = 0; + if (part_len < 0 || part_len > sp[1].c[0] + || sp[1].c[0] % part_len != 0) + { + msg (SW, _("Argument 3 of RINDEX must be between 1 and " + "the length of argument 2, and it must " + "evenly divide the length of argument 2.")); + sp->f = SYSMIS; + break; + } + else + { + int last = sp[0].c[0] - part_len; + for (i = 0; i <= last; i++) + for (j = 0; j < sp[1].c[0]; j += part_len) + if (!memcmp (&sp[0].c[i + 1], &sp[1].c[j + 1], part_len)) + { + result = i + 1; + goto index_3_out; + } + index_3_out: + sp->f = result; + } + } + break; + case OP_RINDEX_2: sp--; if (sp[1].c[0] == 0) sp->f = SYSMIS; else { + int result = 0; for (i = sp[0].c[0] - sp[1].c[0]; i >= 0; i--) - if (!memcmp (&sp[0].c[i + 1], &sp[0].c[1], sp[0].c[0])) + if (!memcmp (&sp[0].c[i + 1], &sp[1].c[1], sp[1].c[0])) { - sp->f = i + 1; - goto main_loop; + result = i + 1; + break; } - sp->f = 0.0; + sp->f = result; } break; - case OP_RINDEX_OPT: - { - /* Length of each search string. */ - int part_len = sp[2].f; - - sp -= 2; - if (sp[1].c[0] == 0 || part_len <= 0 || sp[2].f == SYSMIS - || sp[1].c[0] % part_len != 0) - sp->f = SYSMIS; - else - { - for (i = sp[0].c[0] - part_len; i >= 0; i--) - for (j = 0; j < sp[1].c[0]; j += part_len) - if (!memcmp (&sp[0].c[i], &sp[1].c[j], part_len)) - { - sp->f = i + 1; - goto main_loop; - } - sp->f = 0.0; - } - } + case OP_RINDEX_3: + sp -= 2; + if (sp[1].c[0] == 0) + { + sp->f = SYSMIS; + break; + } + else if (sp[2].f == SYSMIS) + { + msg (SW, _("Argument 3 of RINDEX may not be system-missing.")); + sp->f = SYSMIS; + } + else + { + int part_len = sp[2].f; + int result = 0; + if (part_len < 0 || part_len > sp[1].c[0] + || sp[1].c[0] % part_len != 0) + { + msg (SW, _("Argument 3 of RINDEX must be between 1 and " + "the length of argument 2, and it must " + "evenly divide the length of argument 2.")); + sp->f = SYSMIS; + } + else + { + for (i = sp[0].c[0] - part_len; i >= 0; i--) + for (j = 0; j < sp[1].c[0]; j += part_len) + if (!memcmp (&sp[0].c[i + 1], &sp[1].c[j + 1], part_len)) + { + result = i + 1; + goto rindex_3_out; + } + rindex_3_out: + sp->f = result; + } + } break; case OP_LENGTH: sp->f = sp[0].c[0]; @@ -942,26 +941,6 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp[0].c[i] = toupper ((unsigned char) (sp[0].c[i])); break; case OP_LPAD: - { - int len; - sp--; - len = sp[1].f; - if (sp[1].f == SYSMIS || len < 0 || len > 255) - sp->c[0] = 0; - else if (len > sp[0].c[0]) - { - unsigned char *dest; - - CHECK_STRING_SPACE (len); - dest = ALLOC_STRING_SPACE (len); - dest[0] = len; - memset (&dest[1], ' ', len - sp->c[0]); - memcpy (&dest[len - sp->c[0] + 1], &sp->c[1], sp->c[0]); - sp->c = dest; - } - } - break; - case OP_LPAD_OPT: { int len; sp -= 2; @@ -972,8 +951,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) { unsigned char *dest; - CHECK_STRING_SPACE (len); - dest = ALLOC_STRING_SPACE (len); + dest = pool_alloc (e->pool, len + 1); dest[0] = len; memset (&dest[1], sp[2].c[1], len - sp->c[0]); memcpy (&dest[len - sp->c[0] + 1], &sp->c[1], sp->c[0]); @@ -982,26 +960,6 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) } break; case OP_RPAD: - { - int len; - sp--; - len = sp[1].f; - if (sp[1].f == SYSMIS || len < 0 || len > 255) - sp->c[0] = 0; - else if (len > sp[0].c[0]) - { - unsigned char *dest; - - CHECK_STRING_SPACE (len); - dest = ALLOC_STRING_SPACE (len); - dest[0] = len; - memcpy (&dest[1], &sp->c[1], sp->c[0]); - memset (&dest[sp->c[0] + 1], ' ', len - sp->c[0]); - sp->c = dest; - } - } - break; - case OP_RPAD_OPT: { int len; sp -= 2; @@ -1012,8 +970,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) { unsigned char *dest; - CHECK_STRING_SPACE (len); - dest = ALLOC_STRING_SPACE (len); + dest = pool_alloc (e->pool, len + 1); dest[0] = len; memcpy (&dest[1], &sp->c[1], sp->c[0]); memset (&dest[sp->c[0] + 1], sp[2].c[1], len - sp->c[0]); @@ -1022,20 +979,6 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) } break; case OP_LTRIM: - { - int len = sp[0].c[0]; - - i = 1; - while (i <= len && sp[0].c[i] == ' ') - i++; - if (--i) - { - sp[0].c[i] = sp[0].c[0] - i; - sp->c = &sp[0].c[i]; - } - } - break; - case OP_LTRIM_OPT: { sp--; if (sp[1].c[0] != 1) @@ -1057,50 +1000,30 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) } break; case OP_RTRIM: - assert (' ' != 0); - while (sp[0].c[sp[0].c[0]] == ' ') - sp[0].c[0]--; - break; - case OP_RTRIM_OPT: sp--; if (sp[1].c[0] != 1) sp[0].c[0] = 0; else { - /* Note that NULs are not allowed in strings. This code - needs to change if this decision is changed. */ int cmp = sp[1].c[1]; - while (sp[0].c[sp[0].c[0]] == cmp) + while (sp[0].c[0] > 0 && sp[0].c[sp[0].c[0]] == cmp) sp[0].c[0]--; } break; case OP_NUMBER: { struct data_in di; - - di.s = &sp->c[1]; - di.e = &sp->c[1] + sp->c[0]; - di.v = sp; - di.flags = DI_IGNORE_ERROR; - di.f1 = 1; - di.format.type = FMT_F; - di.format.w = sp->c[0]; - di.format.d = 0; - data_in (&di); - } - break; - case OP_NUMBER_OPT: - { - struct data_in di; + union value out; di.s = &sp->c[1]; - di.e = &sp->c[1] + sp->c[0]; - di.v = sp; - di.flags = DI_IGNORE_ERROR; + di.v = &out; + di.flags = 0; di.f1 = 1; di.format.type = *op++; di.format.w = *op++; di.format.d = *op++; + di.e = &sp->c[1] + min (sp->c[0], di.format.w); data_in (&di); + sp->f = out.f; } break; case OP_STRING: @@ -1112,15 +1035,15 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) f.w = *op++; f.d = *op++; - CHECK_STRING_SPACE (f.w); - dest = ALLOC_STRING_SPACE (f.w); + dest = pool_alloc (e->pool, f.w + 1); dest[0] = f.w; + assert ((formats[f.type].cat & FCAT_STRING) == 0); data_out (&dest[1], &f, sp); sp->c = dest; } break; - case OP_SUBSTR: + case OP_SUBSTR_2: { int index; @@ -1136,7 +1059,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) } } break; - case OP_SUBSTR_OPT: + case OP_SUBSTR_3: { int index; int n; @@ -1162,18 +1085,14 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) break; /* Artificial. */ - case OP_INV: - if (sp->f != SYSMIS) - sp->f = 1. / sp->f; - break; case OP_SQUARE: if (sp->f != SYSMIS) sp->f *= sp->f; break; case OP_NUM_TO_BOOL: - if (approx_eq (sp->f, 0.0)) + if (sp->f == 0.0) sp->f = 0.0; - else if (approx_eq (sp->f, 1.0)) + else if (sp->f == 1.0) sp->f = 1.0; else if (sp->f != SYSMIS) { @@ -1192,7 +1111,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) { if (sp[1].f == SYSMIS) { - if (approx_ne (sp[0].f, 0.0)) + if (sp[0].f != 0.0) sp->f = SYSMIS; } else @@ -1208,10 +1127,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp->f *= rng_get_double (pspp_rng ()); break; case OP_SYSMIS: - if (sp[0].f == SYSMIS || !finite (sp[0].f)) - sp->f = 1.0; - else - sp->f = 0.0; + sp->f = sp->f == SYSMIS || !finite (sp->f); break; case OP_VEC_ELEM_NUM: { @@ -1231,6 +1147,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) sp->f = SYSMIS; break; } + assert (c != NULL); sp->f = c->data[v->var[rindx - 1]->fv].f; } break; @@ -1251,16 +1168,15 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) msg (SE, _("%g is not a valid index value for vector %s. " "The result will be set to the empty string."), sp[0].f, vect->name); - CHECK_STRING_SPACE (0); - sp->c = ALLOC_STRING_SPACE (0); + sp->c = pool_alloc (e->pool, 1); sp->c[0] = 0; break; } v = vect->var[rindx - 1]; - CHECK_STRING_SPACE (v->width); - sp->c = ALLOC_STRING_SPACE (v->width); + sp->c = pool_alloc (e->pool, v->width + 1); sp->c[0] = v->width; + assert (c != NULL); memcpy (&sp->c[1], c->data[v->fv].s, v->width); } break; @@ -1272,13 +1188,13 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) break; case OP_STR_CON: sp++; - CHECK_STRING_SPACE (*str); - sp->c = ALLOC_STRING_SPACE (*str); + sp->c = pool_alloc (e->pool, *str + 1); memcpy (sp->c, str, *str + 1); str += *str + 1; break; case OP_NUM_VAR: sp++; + assert (c != NULL); sp->f = c->data[(*vars)->fv].f; if (is_num_user_missing (sp->f, *vars)) sp->f = SYSMIS; @@ -1289,9 +1205,9 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) int width = (*vars)->width; sp++; - CHECK_STRING_SPACE (width); - sp->c = ALLOC_STRING_SPACE (width); + sp->c = pool_alloc (e->pool, width + 1); sp->c[0] = width; + assert (c != NULL); memcpy (&sp->c[1], &c->data[(*vars)->fv], width); vars++; } @@ -1318,8 +1234,7 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) int width = (*vars)->width; sp++; - CHECK_STRING_SPACE (width); - sp->c = ALLOC_STRING_SPACE (width); + sp->c = pool_alloc (e->pool, width + 1); sp->c[0] = width; if (c == NULL) @@ -1332,39 +1247,30 @@ expr_evaluate (struct expression *e, struct ccase *c, union value *v) break; case OP_NUM_SYS: sp++; + assert (c != NULL); sp->f = c->data[*op++].f == SYSMIS; break; - case OP_STR_MIS: - sp++; - sp->f = is_str_user_missing (c->data[(*vars)->fv].s, *vars); - vars++; - break; case OP_NUM_VAL: sp++; + assert (c != NULL); sp->f = c->data[*op++].f; break; case OP_CASENUM: sp++; - sp->f = vfm_sink_info.ncases + 1; + sp->f = case_num; break; case OP_SENTINEL: goto finished; default: -#if GLOBAL_DEBUGGING - printf (_("evaluate_expression(): not implemented: %s\n"), - ops[op[-1]].name); -#else - printf (_("evaluate_expression(): not implemented: %d\n"), op[-1]); -#endif assert (0); } main_loop: ; } finished: - if (e->type != EX_STRING) + if (e->type != EXPR_STRING) { double value = sp->f; if (!finite (value)) @@ -1377,12 +1283,7 @@ finished: { assert (v); -#if PAGED_STACK - memcpy (e->str_stack, sp->c, sp->c[0] + 1); - v->c = e->str_stack; -#else v->c = sp->c; -#endif return 0.0; }