From ca31bef58d82ef1dfdb00a7a65667608ddc6ec9f Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 1 May 2006 22:14:53 +0000 Subject: [PATCH] Prohibit LAG following TEMPORARY. This both matches SPSS behavior and fixes a bug: we saved the cases for LAG before TEMPORARY but allowed access to variables created afterward anyhow (which could cause a segfault). --- src/language/expressions/ChangeLog | 18 ++++++++++++++++++ src/language/expressions/generate.pl | 3 +++ src/language/expressions/operations.def | 8 ++++---- src/language/expressions/parse.c | 5 +++++ src/language/expressions/parse.inc.pl | 1 + src/language/expressions/private.h | 6 +++++- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/language/expressions/ChangeLog b/src/language/expressions/ChangeLog index 5b04f9ff..7f21130e 100644 --- a/src/language/expressions/ChangeLog +++ b/src/language/expressions/ChangeLog @@ -1,3 +1,21 @@ +Mon May 1 15:11:48 2006 Ben Pfaff + + Prohibit LAG following TEMPORARY. This both matches SPSS behavior + and fixes a bug: we saved the cases for LAG before TEMPORARY but + allowed access to variables created afterward anyhow (which could + cause a segfault). + + * generate.pl: Parse "perm_only" flag on operations. + + * operations.def: Add "perm_only" flag to LAG operations. + + * parse.c: Disallow OPF_PERM_ONLY operations after TEMPORARY. + + * parse.inc.pl: Output OPF_PERM_ONLY flag for "perm_only" + operations. + + * private.h: Add OPF_PERM_ONLY flag. + Sun Apr 23 22:06:45 2006 Ben Pfaff Continue reforming error message support. In this phase, get rid diff --git a/src/language/expressions/generate.pl b/src/language/expressions/generate.pl index 9d753867..4ad1764b 100644 --- a/src/language/expressions/generate.pl +++ b/src/language/expressions/generate.pl @@ -233,6 +233,7 @@ sub parse_input { $op{OPTIMIZABLE} = 1; $op{UNIMPLEMENTED} = 0; $op{EXTENSION} = 0; + $op{PERM_ONLY} = 0; for (;;) { if (match ('extension')) { $op{EXTENSION} = 1; @@ -240,6 +241,8 @@ sub parse_input { $op{OPTIMIZABLE} = 0; } elsif (match ('absorb_miss')) { $op{ABSORB_MISS} = 1; + } elsif (match ('perm_only')) { + $op{PERM_ONLY} = 1; } else { last; } diff --git a/src/language/expressions/operations.def b/src/language/expressions/operations.def index bd5af76c..95ac1e0b 100644 --- a/src/language/expressions/operations.def +++ b/src/language/expressions/operations.def @@ -956,7 +956,7 @@ no_opt string operator STR_VAR () return s; } -no_opt function LAG (num_var v, pos_int n_before) +no_opt perm_only function LAG (num_var v, pos_int n_before) { struct ccase *c = lagged_case (n_before); if (c != NULL) @@ -968,7 +968,7 @@ no_opt function LAG (num_var v, pos_int n_before) return SYSMIS; } -no_opt function LAG (num_var v) +no_opt perm_only function LAG (num_var v) { struct ccase *c = lagged_case (1); if (c != NULL) @@ -980,7 +980,7 @@ no_opt function LAG (num_var v) return SYSMIS; } -no_opt string function LAG (str_var v, pos_int n_before) +no_opt perm_only string function LAG (str_var v, pos_int n_before) expression e; { struct ccase *c = lagged_case (n_before); @@ -990,7 +990,7 @@ no_opt string function LAG (str_var v, pos_int n_before) return empty_string; } -no_opt string function LAG (str_var v) +no_opt perm_only string function LAG (str_var v) expression e; { struct ccase *c = lagged_case (1); diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index f2bc3254..b4294c16 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -1222,6 +1222,11 @@ parse_function (struct expression *e) msg (SE, _("%s is not yet implemented."), f->prototype); goto fail; } + if ((f->flags & OPF_PERM_ONLY) && in_temporary_transformations ()) + { + msg (SE, _("%s may not appear after TEMPORARY."), f->prototype); + goto fail; + } n = expr_allocate_composite (e, f - operations, args, arg_cnt); n->composite.min_valid = min_valid != -1 ? min_valid : f->array_min_elems; diff --git a/src/language/expressions/parse.inc.pl b/src/language/expressions/parse.inc.pl index ea878c92..47c590fb 100644 --- a/src/language/expressions/parse.inc.pl +++ b/src/language/expressions/parse.inc.pl @@ -55,6 +55,7 @@ sub generate_output { push (@flags, "OPF_NONOPTIMIZABLE") if !$op->{OPTIMIZABLE}; push (@flags, "OPF_EXTENSION") if $op->{EXTENSION}; push (@flags, "OPF_UNIMPLEMENTED") if $op->{UNIMPLEMENTED}; + push (@flags, "OPF_PERM_ONLY") if $op->{PERM_ONLY}; push (@members, @flags ? join (' | ', @flags) : 0); push (@members, "OP_$op->{RETURNS}{NAME}"); diff --git a/src/language/expressions/private.h b/src/language/expressions/private.h index 9e00bdf4..0d81c22c 100644 --- a/src/language/expressions/private.h +++ b/src/language/expressions/private.h @@ -58,7 +58,11 @@ enum operation_flags OPF_UNIMPLEMENTED = 020, /* If set, this operation is a PSPP extension. */ - OPF_EXTENSION = 040 + OPF_EXTENSION = 040, + + /* If set, this operation may not occur after TEMPORARY. + (Currently this applies only to LAG.) */ + OPF_PERM_ONLY = 0100 }; #define EXPR_ARG_MAX 4 -- 2.30.2