Merge branch 'savannah/perl-module'
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 29 Jan 2009 22:37:37 +0000 (07:37 +0900)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 29 Jan 2009 22:37:37 +0000 (07:37 +0900)
Conflicts:

po/en_GB.po
src/libpspp/automake.mk

23 files changed:
Smake
configure.ac
po/en_GB.po
src/data/file-name.c
src/data/file-name.h
src/data/variable.c
src/language/command.def
src/language/stats/binomial.c
src/language/stats/crosstabs.q
src/language/stats/glm.q
src/language/utilities/include.c
src/libpspp/automake.mk
src/math/covariance-matrix.c
src/math/covariance-matrix.h
src/math/interaction.c
src/math/interaction.h
src/output/journal.c
src/ui/gui/automake.mk
src/ui/gui/output-viewer.c
src/ui/gui/output-viewer.h
src/ui/gui/psppire.c
src/ui/terminal/automake.mk
tests/command/insert.sh

diff --git a/Smake b/Smake
index 7905c430fe28401c4e5f454a0e4c3218d3a8f283..1dba188b271422372c213d48b3b4126e7988963f 100644 (file)
--- a/Smake
+++ b/Smake
@@ -10,6 +10,7 @@ GNULIB_MODULES = \
        byteswap \
        c-ctype \
        c-strtod \
+       close \
        crypto/md4 \
        dirname \
        environ \
index 7a67e6002438dfb8671b25d1553c86b6ace9fcf6..345ac46bd4569a418458cea29f00066277161388 100644 (file)
@@ -41,6 +41,10 @@ PSPP_LC_PAPER
 AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
 
 
+AC_ARG_VAR([PSPP_LDFLAGS], [linker flags to be used for linking the pspp binary only])
+AC_ARG_VAR([PSPPIRE_LDFLAGS], [linker flags to be used for linking the psppire binary only])
+
+
 AC_ARG_WITH(
   gui, 
   [AS_HELP_STRING([--without-gui], [don't build the PSPPIRE gui])])
index 1927c41f5842c74b17de5d253468d8d29fa276f7..6f2af173e2ce3cf41935de8de653a6d6c1d16337 100644 (file)
@@ -991,28 +991,28 @@ msgstr ""
 msgid "An I/O error occurred writing system file \"%s\"."
 msgstr ""
 
-#: src/data/variable.c:236
+#: src/data/variable.c:240
 #, c-format
 msgid ""
 "Character `%c' (in %s) may not appear as the first character in a variable "
 "name."
 msgstr ""
 
-#: src/data/variable.c:248
+#: src/data/variable.c:252
 #, c-format
 msgid "Character `%c' (in %s) may not appear in a variable name."
 msgstr ""
 
-#: src/data/variable.c:276
+#: src/data/variable.c:280
 msgid "Variable name cannot be empty string."
 msgstr ""
 
-#: src/data/variable.c:282
+#: src/data/variable.c:286
 #, c-format
 msgid "Variable name %s exceeds %d-character limit."
 msgstr ""
 
-#: src/data/variable.c:290
+#: src/data/variable.c:294
 #, c-format
 msgid "`%s' may not be used as a variable name because it is a reserved word."
 msgstr ""
@@ -4048,32 +4048,37 @@ msgstr ""
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
-#: src/language/utilities/include.c:90
+#: src/language/utilities/include.c:92
 msgid "Expecting BATCH or INTERACTIVE after SYNTAX."
 msgstr ""
 
-#: src/language/utilities/include.c:107
+#: src/language/utilities/include.c:109
 msgid "Expecting YES or NO after CD."
 msgstr ""
 
-#: src/language/utilities/include.c:124
+#: src/language/utilities/include.c:126
 msgid "Expecting CONTINUE or STOP after ERROR."
 msgstr ""
 
-#: src/language/utilities/include.c:131
+#: src/language/utilities/include.c:133
 #, c-format
 msgid "Unexpected token: `%s'."
 msgstr ""
 
-#: src/language/utilities/include.c:176
+#: src/language/utilities/include.c:178
 msgid "expecting file name"
 msgstr ""
 
-#: src/language/utilities/include.c:188
+#: src/language/utilities/include.c:190
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
 
+#: src/language/utilities/include.c:198
+#, c-format
+msgid "Unable to open `%s': %s."
+msgstr ""
+
 #: src/language/utilities/permissions.c:73
 #, c-format
 msgid "Expecting %s or %s."
@@ -4507,12 +4512,12 @@ msgstr ""
 msgid "unknown configuration parameter `%s' for HTML device driver"
 msgstr ""
 
-#: src/output/journal.c:68
+#: src/output/journal.c:69
 #, c-format
 msgid "error writing \"%s\""
 msgstr ""
 
-#: src/output/journal.c:90
+#: src/output/journal.c:94
 #, c-format
 msgid "error creating \"%s\""
 msgstr ""
@@ -5817,20 +5822,20 @@ msgstr ""
 msgid "Paste"
 msgstr ""
 
-#: src/ui/gui/psppire.c:214
+#: src/ui/gui/psppire.c:226
 msgid "_Reset"
 msgstr ""
 
-#: src/ui/gui/psppire.c:215
+#: src/ui/gui/psppire.c:227
 msgid "_Select"
 msgstr ""
 
-#: src/ui/gui/psppire.c:251
+#: src/ui/gui/psppire.c:263
 #, c-format
 msgid "Cannot open %s: %s.\n"
 msgstr ""
 
-#: src/ui/gui/psppire.c:268
+#: src/ui/gui/psppire.c:280
 #, c-format
 msgid "%s is neither a system nor portable file"
 msgstr ""
index 86c8e17e467d45c3cf7edac34166b20357cba62f..14afd60e53be5f86e01963d6f0a9aa08927e5de3 100644 (file)
@@ -452,3 +452,45 @@ fn_hash_identity (const struct file_identity *identity)
     hash ^= hsh_hash_string (identity->name);
   return hash;
 }
+
+
+
+#ifdef WINDOWS32
+
+/* Apparently windoze users like to see output dumped into their home directory,
+   not the current directory (!) */
+const char *
+default_output_path (void)
+{
+  static const char *home_dir = NULL;
+
+  /* Windows NT defines HOMEDRIVE and HOMEPATH.  But give preference
+     to HOME, because the user can change HOME.  */
+  if (home_dir == NULL)
+    {
+      const char *home_drive = getenv ("HOMEDRIVE");
+      const char *home_path = getenv ("HOMEPATH");
+
+      if (home_drive != NULL && home_path != NULL)
+       home_dir = xasprintf ("%s%s%c",
+                             home_drive, home_path, DIRECTORY_SEPARATOR);
+      else
+       home_dir = "c:/users/default/"; /* poor default */
+    }
+  return home_dir;
+}
+
+#else
+
+/* ... whereas the rest of the world just likes it to be
+   put "here" for easy access. */
+const char *
+default_output_path (void)
+{
+  static char current_dir[]  = "";
+
+  return current_dir;
+}
+
+#endif
+
index b4231d2f87178b841f85cf62d69a76e15b871b5e..d34bd4196fea046db722197aa403db964a423deb 100644 (file)
@@ -52,4 +52,6 @@ int fn_compare_file_identities (const struct file_identity *,
                                 const struct file_identity *);
 unsigned int fn_hash_identity (const struct file_identity *);
 
+const char * default_output_path (void);
+
 #endif /* file-name.h */
index ccbe65dc0ed9757be75091637bb346b276182d84..30cf03b134666cf8f6db1f457c8e3733b0b311e9 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -148,17 +148,21 @@ var_clone (const struct variable *old_var)
   return new_var;
 }
 
-/* Create a variable to be used for internal calculations only */
+/* Create a variable to be used for internal calculations only.
+   The variable is assigned a unique dictionary index and a case
+   index of CASE_IDX. */
 struct variable *
 var_create_internal (int case_idx)
 {
   struct variable *v = var_create ("$internal", 0);
-
   struct vardict_info vdi;
+  static int counter = INT_MAX / 2;
 
   vdi.dict = NULL;
-  vdi.dict_index = 0;
   vdi.case_index = case_idx;
+  vdi.dict_index = counter++;
+  if (counter == INT_MAX)
+    counter = INT_MAX / 2;
 
   var_set_vardict (v, &vdi);
 
index e06261f94cdf89ac17e8c04c6bacff26b885f792..f87747d892e8d9566da798936f243ad0fdd46ec1 100644 (file)
@@ -98,7 +98,6 @@ DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "XSAVE", cmd_xsave)
 DEF_CMD (S_DATA, 0, "AGGREGATE", cmd_aggregate)
 DEF_CMD (S_DATA, 0, "AUTORECODE", cmd_autorecode)
 DEF_CMD (S_DATA, F_KEEP_FINAL_TOKEN, "BEGIN DATA", cmd_begin_data)
-DEF_CMD (S_DATA, 0, "CORRELATIONS", cmd_correlations)
 DEF_CMD (S_DATA, 0, "COUNT", cmd_count)
 DEF_CMD (S_DATA, 0, "CROSSTABS", cmd_crosstabs)
 DEF_CMD (S_DATA, 0, "DELETE VARIABLES", cmd_delete_variables)
@@ -114,7 +113,6 @@ DEF_CMD (S_DATA, 0, "MEANS", cmd_means)
 DEF_CMD (S_DATA, 0, "MODIFY VARS", cmd_modify_vars)
 DEF_CMD (S_DATA, 0, "NPAR TESTS", cmd_npar_tests)
 DEF_CMD (S_DATA, 0, "ONEWAY", cmd_oneway)
-DEF_CMD (S_DATA, 0, "PEARSON CORRELATIONS", cmd_correlations)
 DEF_CMD (S_DATA, 0, "RANK", cmd_rank)
 DEF_CMD (S_DATA, 0, "REGRESSION", cmd_regression)
 DEF_CMD (S_DATA, 0, "RELIABILITY", cmd_reliability)
@@ -157,6 +155,7 @@ UNIMPL_CMD ("CCF", "Time series cross correlation")
 UNIMPL_CMD ("CLEAR TRANSFORMATIONS", "Clears transformations from active file")
 UNIMPL_CMD ("CLUSTER", "Hierachial clustering")
 UNIMPL_CMD ("CONJOINT", "Analyse full concept data")
+UNIMPL_CMD ("CORRELATIONS", "Correlation coefficients")
 UNIMPL_CMD ("CORRESPONDENCE", "Show correspondence")
 UNIMPL_CMD ("COXREG", "Cox proportional hazards regression")
 UNIMPL_CMD ("CREATE", "Create time series data")
@@ -217,6 +216,7 @@ UNIMPL_CMD ("ORTHOPLAN", "Orthogonal effects design")
 UNIMPL_CMD ("OVERALS", "Nonlinear canonical correlation")
 UNIMPL_CMD ("PACF", "Partial autocorrelation")
 UNIMPL_CMD ("PARTIAL CORR", "Partial correlation")
+UNIMPL_CMD ("PEARSON CORRELATIONS", "Correlation coefficients")
 UNIMPL_CMD ("PLANCARDS", "Conjoint analysis planning")
 UNIMPL_CMD ("PLUM", "Estimate ordinal regression models")
 UNIMPL_CMD ("POINT", "Marker in keyed file")
index 15d0e4032a146c094e5275cd21f25cdfadc71afe..b62b4dce1375a11c11030ca299de2284141261b9 100644 (file)
@@ -112,7 +112,7 @@ do_binomial (const struct dictionary *dict,
           int width = var_get_width (var);
 
          if (var_is_value_missing (var, value, exclude))
-           break;
+           continue;
 
          if ( NULL == cat1[v].value )
            {
@@ -158,16 +158,20 @@ binomial_execute (const struct dataset *ds,
 
   if ( bst->category1 != SYSMIS )
     {
+      int i;
       union value v;
       v.f = bst->category1;
-      cat1->value = value_dup (&v, 0);
+      for (i = 0; i < ost->n_vars; i++)
+       cat1[i].value = value_dup (&v, 0);
     }
 
   if ( bst->category2 != SYSMIS )
     {
+      int i;
       union value v;
       v.f = bst->category2;
-      cat2->value = value_dup (&v, 0);
+      for (i = 0; i < ost->n_vars; i++)
+       cat2[i].value = value_dup (&v, 0);
     }
 
   if (do_binomial (dataset_dict(ds), input, bst, cat1, cat2, exclude))
index 60d2faee8b7348c2ffa26f2b911ea705b78b5866..68d11e307e0ff41584d1ffae0ef4abd6d8c9ff74 100644 (file)
@@ -1675,7 +1675,7 @@ enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx,
 
   if (mode == GENERAL)
     {
-      int width = var_get_width (v);
+      int width = MIN (var_get_width (v), MAX_SHORT_STRING);
       int i;
 
       *values = xnmalloc (entry_cnt, sizeof **values);
index 07ee7ab53166fcbd917a79933f18eaf9761b8ea8..26b903651eea06771c7b90799f9700162a9fb478 100644 (file)
@@ -243,7 +243,7 @@ run_glm (struct casereader *input,
          /* 
             Accumulate the covariance matrix.
          */
-         covariance_matrix_accumulate (cov, c);
+         covariance_matrix_accumulate (cov, c, NULL, 0);
          n_data++;
        }
       covariance_matrix_compute (cov);
index 8e69dab50c6260f63795d569c910ab48cd743c47..fe98aeb87f3347b82b61853adc70360cee87f132 100644 (file)
@@ -16,7 +16,9 @@
 
 #include <config.h>
 #include <ctype.h>
+#include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <language/command.h>
 #include <libpspp/message.h>
 #include <libpspp/getl.h>
@@ -191,6 +193,13 @@ parse_insert (struct lexer *lexer, char **filename)
     }
 
   *filename = relative_filename;
+  if (*filename == NULL) 
+    {
+      msg (SE, _("Unable to open `%s': %s."),
+           relative_filename, strerror (errno));
+      free (relative_filename);
+      return CMD_FAILURE;
+    }
 
   return CMD_SUCCESS;
 }
index 9eed00276db9f03eb33ea74058db61cad1b8a0d3..dc512bb288907f59cc668e1ea989e8c7858f6916 100644 (file)
@@ -75,7 +75,7 @@ src_libpspp_libpspp_la_CPPFLAGS = -I $(top_srcdir)/src/libpspp $(AM_CPPFLAGS)
 
 nodist_src_libpspp_libpspp_la_SOURCES = src/libpspp/version.c
 
-src/libpspp/version.c: $(top_srcdir)/AUTHORS $(top_builddir)/Makefile
+src/libpspp/version.c: $(top_srcdir)/AUTHORS Makefile
        @$(MKDIR_P) src/libpspp
        echo "/*        -*- mode: c; buffer-read-only: t -*-" > $@
        echo "   Generated by src/libpspp/automake.mk --- Do not edit.">> $@
index 32ca9bca9f7a20f1d7bd6d899027af54b6639998..e1b612affe747949867ea53efadfb4de64b1c5a5 100644 (file)
@@ -64,10 +64,13 @@ struct covariance_matrix
   int n_pass;
   int missing_handling;
   enum mv_class missing_value;
-  void (*accumulate) (struct covariance_matrix *, const struct ccase *);
+  void (*accumulate) (struct covariance_matrix *, const struct ccase *,
+                     const struct interaction_variable **, size_t);
   void (*update_moments) (struct covariance_matrix *, size_t, double);
 };
 
+
+
 static struct hsh_table *covariance_hsh_create (size_t);
 static hsh_hash_func covariance_accumulator_hash;
 static unsigned int hash_numeric_alpha (const struct variable *,
@@ -93,9 +96,13 @@ static struct covariance_accumulator *get_new_covariance_accumulator (const
                                                                      value
                                                                      *);
 static void covariance_accumulate_listwise (struct covariance_matrix *,
-                                           const struct ccase *);
+                                           const struct ccase *,
+                                           const struct interaction_variable **,
+                                           size_t);
 static void covariance_accumulate_pairwise (struct covariance_matrix *,
-                                           const struct ccase *);
+                                           const struct ccase *,
+                                           const struct interaction_variable **,
+                                           size_t);
 
 struct covariance_matrix *
 covariance_matrix_init (size_t n_variables,
@@ -227,7 +234,7 @@ column_iterate (struct design_matrix *cov, const struct variable *v,
       col += i;
       y = -1.0 * cat_get_category_count (i, v) / ssize;
       tmp_val = cat_subscript_to_value (i, v);
-      if (compare_values_short (tmp_val, val1, v))
+      if (!compare_values_short (tmp_val, val1, v))
        {
          y += -1.0;
        }
@@ -262,7 +269,7 @@ covariance_pass_two (struct design_matrix *cov, double mean1, double mean2,
          row += i;
          x = -1.0 * cat_get_category_count (i, v1) / ssize;
          tmp_val = cat_subscript_to_value (i, v1);
-         if (compare_values_short (tmp_val, val1, v1))
+         if (!compare_values_short (tmp_val, val1, v1))
            {
              x += 1.0;
            }
@@ -399,23 +406,23 @@ match_nodes (const struct covariance_accumulator *c,
          }
        if (var_is_numeric (v1) && var_is_alpha (v2))
          {
-           if (compare_values_short (val2, c->val2, v2))
+           if (!compare_values_short (val2, c->val2, v2))
              {
                return 0;
              }
          }
        if (var_is_alpha (v1) && var_is_numeric (v2))
          {
-           if (compare_values_short (val1, c->val1, v1))
+           if (!compare_values_short (val1, c->val1, v1))
              {
                return 0;
              }
          }
        if (var_is_alpha (v1) && var_is_alpha (v2))
          {
-           if (compare_values_short (val1, c->val1, v1))
+           if (!compare_values_short (val1, c->val1, v1))
              {
-               if (compare_values_short (val2, c->val2, v2))
+               if (!compare_values_short (val2, c->val2, v2))
                  {
                    return 0;
                  }
@@ -490,13 +497,13 @@ update_product (const struct variable *v1, const struct variable *v2,
   return 0.0;
 }
 static double
-update_sum (const struct variable *var, const union value *val)
+update_sum (const struct variable *var, const union value *val, double weight)
 {
   assert (var != NULL);
   assert (val != NULL);
   if (var_is_alpha (var))
     {
-      return 1.0;
+      return weight;
     }
   return val->f;
 }
@@ -525,20 +532,27 @@ get_covariance_variables (const struct covariance_matrix *cov)
   return cov->v_variables;
 }
 
+
 static void
 update_hash_entry (struct hsh_table *c,
                   const struct variable *v1,
                   const struct variable *v2,
-                  const union value *val1, const union value *val2)
+                  const union value *val1, const union value *val2, 
+                  const struct interaction_value *i_val1,
+                  const struct interaction_value *i_val2)
 {
   struct covariance_accumulator *ca;
   struct covariance_accumulator *new_entry;
+  double iv_f1;
+  double iv_f2;
 
-
+  iv_f1 = interaction_value_get_nonzero_entry (i_val1);
+  iv_f2 = interaction_value_get_nonzero_entry (i_val2);
   ca = get_new_covariance_accumulator (v1, v2, val1, val2);
   ca->dot_product = update_product (ca->v1, ca->v2, ca->val1, ca->val2);
-  ca->sum1 = update_sum (ca->v1, ca->val1);
-  ca->sum2 = update_sum (ca->v2, ca->val2);
+  ca->dot_product *= iv_f1 * iv_f2;
+  ca->sum1 = update_sum (ca->v1, ca->val1, iv_f1);
+  ca->sum2 = update_sum (ca->v2, ca->val2, iv_f2);
   ca->ssize = 1.0;
   new_entry = hsh_insert (c, ca);
   if (new_entry != NULL)
@@ -568,13 +582,17 @@ update_hash_entry (struct hsh_table *c,
  */
 static void
 covariance_accumulate_pairwise (struct covariance_matrix *cov,
-                               const struct ccase *ccase)
+                               const struct ccase *ccase, 
+                               const struct interaction_variable **i_var,
+                               size_t n_intr)
 {
   size_t i;
   size_t j;
   const union value *val1;
   const union value *val2;
   const struct variable **v_variables;
+  struct interaction_value *i_val1 = NULL;
+  struct interaction_value *i_val2 = NULL;
 
   assert (cov != NULL);
   assert (ccase != NULL);
@@ -584,24 +602,40 @@ covariance_accumulate_pairwise (struct covariance_matrix *cov,
 
   for (i = 0; i < cov->n_variables; ++i)
     {
-      val1 = case_data (ccase, v_variables[i]);
+      if (is_interaction (v_variables[i], i_var, n_intr))
+       {
+         i_val1 = interaction_case_data (ccase, v_variables[i], i_var, n_intr);
+         val1 = interaction_value_get (i_val1);
+       }
+      else
+       {
+         val1 = case_data (ccase, v_variables[i]);
+       }
       if (!var_is_value_missing (v_variables[i], val1, cov->missing_value))
        {
          cat_value_update (v_variables[i], val1);
-         if (var_is_alpha (v_variables[i]))
+         if (var_is_numeric (v_variables[i]))
            cov->update_moments (cov, i, val1->f);
 
          for (j = i; j < cov->n_variables; j++)
            {
-             val2 = case_data (ccase, v_variables[j]);
+             if (is_interaction (v_variables[j], i_var, n_intr))
+               {
+                 i_val2 = interaction_case_data (ccase, v_variables[j], i_var, n_intr);
+                 val2 = interaction_value_get (i_val2);
+               }
+             else
+               {
+                 val2 = case_data (ccase, v_variables[j]);
+               }
              if (!var_is_value_missing
                  (v_variables[j], val2, cov->missing_value))
                {
                  update_hash_entry (cov->ca, v_variables[i], v_variables[j],
-                                    val1, val2);
+                                    val1, val2, i_val1, i_val2);
                  if (j != i)
                    update_hash_entry (cov->ca, v_variables[j],
-                                      v_variables[i], val2, val1);
+                                      v_variables[i], val2, val1, i_val2, i_val1);
                }
            }
        }
@@ -625,13 +659,17 @@ covariance_accumulate_pairwise (struct covariance_matrix *cov,
  */
 static void
 covariance_accumulate_listwise (struct covariance_matrix *cov,
-                               const struct ccase *ccase)
+                               const struct ccase *ccase,
+                               const struct interaction_variable **i_var,
+                               size_t n_intr)
 {
   size_t i;
   size_t j;
   const union value *val1;
   const union value *val2;
   const struct variable **v_variables;
+  struct interaction_value *i_val1 = NULL;
+  struct interaction_value *i_val2 = NULL;
 
   assert (cov != NULL);
   assert (ccase != NULL);
@@ -641,19 +679,35 @@ covariance_accumulate_listwise (struct covariance_matrix *cov,
 
   for (i = 0; i < cov->n_variables; ++i)
     {
-      val1 = case_data (ccase, v_variables[i]);
+      if (is_interaction (v_variables[i], i_var, n_intr))
+       {
+         i_val1 = interaction_case_data (ccase, v_variables[i], i_var, n_intr);
+         val1 = interaction_value_get (i_val1);
+       }
+      else
+       {
+         val1 = case_data (ccase, v_variables[i]);
+       }
       cat_value_update (v_variables[i], val1);
-      if (var_is_alpha (v_variables[i]))
+      if (var_is_numeric (v_variables[i]))
        cov->update_moments (cov, i, val1->f);
 
       for (j = i; j < cov->n_variables; j++)
        {
-         val2 = case_data (ccase, v_variables[j]);
+         if (is_interaction (v_variables[j], i_var, n_intr))
+           {
+             i_val2 = interaction_case_data (ccase, v_variables[j], i_var, n_intr);
+             val2 = interaction_value_get (i_val2);
+           }
+         else
+           {
+             val2 = case_data (ccase, v_variables[j]);
+           }
          update_hash_entry (cov->ca, v_variables[i], v_variables[j],
-                            val1, val2);
+                            val1, val2, i_val1, i_val2);
          if (j != i)
            update_hash_entry (cov->ca, v_variables[j], v_variables[i],
-                              val2, val1);
+                              val2, val1, i_val2, i_val1);
        }
     }
 }
@@ -662,13 +716,13 @@ covariance_accumulate_listwise (struct covariance_matrix *cov,
   Call this function during the data pass. Each case will be added to
   a hash containing all values of the covariance matrix. After the
   data have been passed, call covariance_matrix_compute to put the
-  values in the struct covariance_matrix.
+  values in the struct covariance_matrix. 
  */
 void
 covariance_matrix_accumulate (struct covariance_matrix *cov,
-                             const struct ccase *ccase)
+                             const struct ccase *ccase, void **aux, size_t n_intr)
 {
-  cov->accumulate (cov, ccase);
+  cov->accumulate (cov, ccase, (const struct interaction_variable **) aux, n_intr);
 }
 
 static void
@@ -689,7 +743,7 @@ covariance_matrix_insert (struct design_matrix *cov,
     {
       i = 0;
       tmp_val = cat_subscript_to_value (i, v1);
-      while (!compare_values_short (tmp_val, val1, v1))
+      while (compare_values_short (tmp_val, val1, v1))
        {
          i++;
          tmp_val = cat_subscript_to_value (i, v1);
@@ -704,7 +758,7 @@ covariance_matrix_insert (struct design_matrix *cov,
          col = design_matrix_var_to_column (cov, v2);
          i = 0;
          tmp_val = cat_subscript_to_value (i, v1);
-         while (!compare_values_short (tmp_val, val1, v1))
+         while (compare_values_short (tmp_val, val1, v1))
            {
              i++;
              tmp_val = cat_subscript_to_value (i, v1);
index 33a5d750533be2526ed6f23042ee2512da2dc057..b692e7e8003e4ee852a09a22c8acda31864c4901 100644 (file)
@@ -22,6 +22,7 @@
 #define COVARIANCE_MATRIX_H
 
 #include <math/design-matrix.h>
+#include <math/interaction.h>
 
 struct moments1;
 struct ccase;
@@ -53,6 +54,6 @@ struct covariance_matrix *covariance_matrix_init (size_t,
                                                  int, int, enum mv_class);
 void covariance_matrix_free (struct covariance_matrix *);
 void covariance_matrix_accumulate (struct covariance_matrix *,
-                                  const struct ccase *);
+                                  const struct ccase *, void **, size_t);
 struct design_matrix *covariance_to_design (const struct covariance_matrix *);
 #endif
index c8ead42912f17787dc4c01e8e46ced248e255a59..33da8423bd7c7545a69e4c51a1d0a9a5abd4318d 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
   OBS_VALS member. If there are K categorical variables, each with
   N_1, N_2, ..., N_K categories, then the interaction will have
   N_1 * N_2 * N_3 *...* N_K - 1 entries.
+
+  When using these functions, make sure the orders of variables and
+  values match when appropriate.
  */
 
 #include <config.h>
 #include <assert.h>
 #include <gsl/gsl_math.h>
 #include <gsl/gsl_vector.h>
-#include <data/category.h>
+#include <data/value.h>
 #include <data/variable.h>
-#include "interaction.h"
+#include <math/interaction.h>
+#include <string.h>
+#include <xalloc.h>
 
-#include "xalloc.h"
+struct interaction_variable
+{
+  int n_vars;
+  const struct variable **members;
+  struct variable *intr;
+  size_t n_alpha;
+};
+
+struct interaction_value
+{
+  const struct interaction_variable *intr;
+  union value *val; /* Concatenation of the string values in this
+                      interaction's value, or the product of a bunch
+                      of numeric values for a purely numeric
+                      interaction.
+                   */
+  double f; /* Product of the numerical values in this interaction's value. */
+};
 
 /*
-  Convert a list of values to a binary vector. The order of VALS must
-  correspond to the order of V.
+  An interaction_variable has type alpha if any of members have type
+  alpha. Otherwise, its type is numeric.
  */
-gsl_vector *
-get_interaction (union value **vals, const struct variable **v, size_t n_vars)
+struct interaction_variable *
+interaction_variable_create (const struct variable **vars, int n_vars)
 {
-  gsl_vector *result = NULL;
-  size_t *subs = NULL;
-  size_t length = 1;
+  struct interaction_variable *result = NULL;
   size_t i;
-  size_t j;
-  double tmp = 1.0;
 
-  assert (n_vars > 0);
-  for (i = 0; i < n_vars; i++)
+  if (n_vars > 0)
     {
-      if (var_is_alpha (v[i]))
+      result = xmalloc (sizeof (*result));
+      result->n_alpha = 0;
+      result->members = xnmalloc (n_vars, sizeof (*result->members));
+      result->intr = var_create_internal (0);
+      result->n_vars = n_vars;
+      for (i = 0; i < n_vars; i++)
        {
-         length *= cat_get_n_categories (v[i]);
+         result->members[i] = vars[i];
+         if (var_is_alpha (vars[i]))
+           {
+             result->n_alpha++;
+           }
        }
-      else
+    }
+  /*
+    VAR_SET_WIDTH sets the type of the variable.
+   */
+  var_set_width (result->intr, MAX_SHORT_STRING * result->n_alpha + 1);
+
+  return result;
+}
+void interaction_variable_destroy (struct interaction_variable *iv)
+{
+  var_destroy (iv->intr);
+  free (iv->members);
+  free (iv);
+}
+
+/*
+  Get one of the member variables.
+ */
+const struct variable *
+interaction_variable_get_member (const struct interaction_variable *iv, size_t i)
+{
+  return iv->members[i];
+}
+
+size_t
+interaction_get_n_vars (const struct interaction_variable *iv)
+{
+  return (iv == NULL) ? 0 : iv->n_vars;
+}
+
+size_t
+interaction_get_n_alpha (const struct interaction_variable *iv)
+{
+  return iv->n_alpha;
+}
+
+size_t
+interaction_get_n_numeric (const struct interaction_variable *iv)
+{
+  return (interaction_get_n_vars (iv) - interaction_get_n_alpha (iv));
+}
+
+/*
+  Get the interaction varibale itself.
+ */
+const struct variable *
+interaction_variable_get_var (const struct interaction_variable *iv)
+{
+  return iv->intr;
+}
+/*
+  Given list of values, compute the value of the corresponding
+  interaction.  This "value" is not stored as the typical vector of
+  0's and one double, but rather the string values are concatenated to
+  make one big string value, and the numerical values are multiplied
+  together to give the non-zero entry of the corresponding vector.
+ */
+struct interaction_value *
+interaction_value_create (const struct interaction_variable *var, const union value **vals)
+{
+  struct interaction_value *result = NULL;
+  const struct variable *member;
+  size_t i;
+  size_t n_vars;
+  
+  if (var != NULL)
+    {
+      result = xmalloc (sizeof (*result));
+      result->intr = var;
+      n_vars = interaction_get_n_vars (var);
+      result->val = value_create (n_vars * MAX_SHORT_STRING + 1);
+      result->f = 1.0;
+      for (i = 0; i < n_vars; i++)
+       {
+         member = interaction_variable_get_member (var, i);
+
+         if (var_is_value_missing (member, vals[i], MV_ANY))
+           {
+             value_set_missing (result->val, MAX_SHORT_STRING);
+             result->f = SYSMIS;
+             break;
+           }
+         else
+           {
+             if (var_is_alpha (var->members[i]))
+               {
+                 strncat (result->val->s, vals[i]->s, MAX_SHORT_STRING);
+               }
+             else if (var_is_numeric (var->members[i]))
+               {
+                 result->f *= vals[i]->f;
+               }
+           }
+       }
+      if (interaction_get_n_alpha (var) == 0)
        {
-         length = (length > 0) ? length : 1;
+         /*
+           If there are no categorical variables, then the
+           interaction consists of only numeric data. In this case,
+           code that uses this interaction_value will see the union
+           member as the numeric value. If we were to store that
+           numeric value in result->f as well, the calling code may
+           inadvertently square this value by multiplying by
+           result->val->f. Such multiplication would be correct for an
+           interaction consisting of both categorical and numeric
+           data, but a mistake for purely numerical interactions. To
+           avoid the error, we set result->f to 1.0 for numeric
+           interactions.
+          */
+         result->val->f = result->f;
+         result->f = 1.0;
        }
     }
-  if (length > 0)
+  return result;
+}
+
+union value *
+interaction_value_get (const struct interaction_value *val)
+{
+  return val->val;
+}
+
+/*
+  Returns the numeric value of the non-zero entry for the vector
+  corresponding to this interaction.  Do not use this function to get
+  the numeric value of a purley numeric interaction. Instead, use the
+  union value * returned by interaction_value_get.
+ */
+double 
+interaction_value_get_nonzero_entry (const struct interaction_value *val)
+{
+  if (val != NULL)
+    return val->f;
+  return 1.0;
+}
+
+void 
+interaction_value_destroy (struct interaction_value *val)
+{
+  if (val != NULL)
     {
-      length--;
+      free (val->val);
+      free (val);
     }
+}
 
-  result = gsl_vector_calloc (length);
-  subs = xnmalloc (n_vars, sizeof (*subs));
-  for (j = 0; j < n_vars; j++)
+/*
+  Return a value from a variable that is an interaction. 
+ */
+struct interaction_value *
+interaction_case_data (const struct ccase *ccase, const struct variable *var, 
+                      const struct interaction_variable **intr_vars, size_t n_intr)
+{
+  size_t i;
+  size_t n_vars;
+  const struct interaction_variable *iv;
+  const struct variable *intr;
+  const struct variable *member;
+  const union value **vals = NULL;
+
+  for (i = 0; i < n_intr; i++)
     {
-      if (var_is_alpha (v[j]))
+      iv = intr_vars[i];
+      intr = interaction_variable_get_var (iv);
+      if (var_get_dict_index (intr) == var_get_dict_index (var))
        {
-         subs[j] = cat_value_find (v[j], vals[j]);
+         break;
        }
     }
-  j = subs[0];
-  for (i = 1; i < n_vars; i++)
+  n_vars = interaction_get_n_vars (iv);
+  vals = xnmalloc (n_vars, sizeof (*vals));
+  for (i = 0; i < n_vars; i++)
     {
-      j = j * cat_get_n_categories (v[i]) + subs[i];
+      member = interaction_variable_get_member (iv, i);
+      vals[i] = case_data (ccase, member);
     }
-  gsl_vector_set (result, j, 1.0);
-  /*
-     If any of the variables are numeric, the interaction of that
-     variable with another is just a scalar product.
-   */
-  for (i = 1; i < n_vars; i++)
+  return interaction_value_create (iv, vals);
+}
+
+bool
+is_interaction (const struct variable *var, const struct interaction_variable **iv, size_t n_intr)
+{
+  size_t i;
+  const struct variable *intr;
+  
+  for (i = 0; i < n_intr; i++)
     {
-      if (var_is_numeric (v[i]))
+      intr = interaction_variable_get_var (iv[i]);
+      if (var_get_dict_index (intr) == var_get_dict_index (var))
        {
-         tmp *= vals[i]->f;
+         return true;
        }
     }
-  if (fabs (tmp - 1.0) > GSL_DBL_EPSILON)
-    {
-      gsl_vector_set (result, j, tmp);
-    }
-  free (subs);
-
-  return result;
+  return false;
 }
+  
index 070060781635131ca91f05fb6ac7e787f421f48d..73b440be32b014cc4da06c715266efb1b4e6da18 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-gsl_vector *
-get_interaction (union value **, const struct variable **, size_t);
+#ifndef INTERACTION_H
+#define INTERACTION_H
+#include <data/case.h>
+
+struct interaction_variable;
+struct interaction_value;
+
+struct interaction_variable * interaction_variable_create (const struct variable **, int);
+void interaction_variable_destroy (struct interaction_variable *);
+struct interaction_value * interaction_value_create (const struct interaction_variable *, const union value **);
+void interaction_value_destroy (struct interaction_value *);
+size_t interaction_variable_get_n_vars (const struct interaction_variable *);
+double interaction_value_get_nonzero_entry (const struct interaction_value *);
+union value * interaction_value_get (const struct interaction_value *);
+const struct variable * interaction_variable_get_var (const struct interaction_variable *);
+size_t interaction_get_n_numeric (const struct interaction_variable *);
+size_t interaction_get_n_alpha (const struct interaction_variable *);
+size_t interaction_get_n_vars (const struct interaction_variable *);
+const struct variable * interaction_variable_get_member (const struct interaction_variable *, size_t);
+bool is_interaction (const struct variable *, const struct interaction_variable **, size_t);
+struct interaction_value *
+interaction_case_data (const struct ccase *, const struct variable *, 
+                      const struct interaction_variable **, size_t);
+double interaction_value_get_nonzero_entry (const struct interaction_value *);
+#endif
index ef50285ea4ee1b8ba04624a37447daac433f16bb..67657f6247cc8ec731cf8154c4f45aa48d369003 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <data/file-name.h>
 #include <libpspp/str.h>
 
 #include "fwriteerror.h"
@@ -83,7 +84,10 @@ journal_write (bool prefix, const char *line)
   if (journal_file == NULL)
     {
       if (journal_file_name == NULL)
-        journal_file_name = xstrdup ("pspp.jnl");
+       {
+         const char *output_path = default_output_path ();
+         journal_file_name = xasprintf ("%s%s", output_path, "pspp.jnl");
+       }
       journal_file = fopen (journal_file_name, "w");
       if (journal_file == NULL)
         {
index af880fc3052ec6f72d11472fbe26c0dfdf17652a..2183e4e8af619cb69eeaeaf4749f0efab242adc9 100644 (file)
@@ -9,6 +9,7 @@ src_ui_gui_psppire_CFLAGS = $(GTK_CFLAGS) $(GLADE_CFLAGS) -Wall \
 
 
 src_ui_gui_psppire_LDFLAGS = \
+       $(PSPPIRE_LDFLAGS) \
        $(PG_LDFLAGS)
 
 
index bf647e9051199eda18135237e6f477aab4249814..2b0c4af8094dbdd1668d7c6254d3f2e7f018ef18 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <config.h>
 #include <gtk/gtk.h>
+#include <data/file-name.h>
 #include "window-manager.h"
 #include "output-viewer.h"
 #include "helper.h"
@@ -62,7 +63,7 @@ on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
 
   the_output_viewer = NULL;
 
-  unlink (OUTPUT_FILE_NAME);
+  unlink (output_file_name ());
 
   return FALSE;
 }
@@ -181,7 +182,7 @@ reload_the_viewer (void)
   struct stat buf;
 
   /* If there is no output, then don't do anything */
-  if (0 != stat (OUTPUT_FILE_NAME, &buf))
+  if (0 != stat (output_file_name (), &buf))
     return ;
 
   if ( NULL == the_output_viewer )
@@ -193,6 +194,7 @@ reload_the_viewer (void)
   reload_viewer (the_output_viewer);
 }
 
+#define OUTPUT_FILE_NAME "psppire.txt"
 
 void
 reload_viewer (struct output_viewer *ov)
@@ -248,10 +250,10 @@ reload_viewer (struct output_viewer *ov)
   {
     if ( ov->fp == NULL)
       {
-       ov->fp = fopen (OUTPUT_FILE_NAME, "r");
+       ov->fp = fopen (output_file_name (), "r");
        if ( ov->fp == NULL)
          {
-           g_print ("Cannot open %s\n", OUTPUT_FILE_NAME);
+           g_print ("Cannot open %s\n", output_file_name ());
            return;
          }
       }
@@ -277,3 +279,16 @@ reload_viewer (struct output_viewer *ov)
 
 
 
+
+const char *
+output_file_name (void)
+{
+  const char *dir = default_output_path ();
+  static char *filename = NULL;
+
+  if ( NULL == filename )
+    filename = xasprintf ("%s%s", dir, OUTPUT_FILE_NAME);
+
+
+  return filename;
+}
index b5c9ffcea77e4a62fc4c0e36158931a37ad29c5a..e5bf5c1cc34e821ca3dd4d416138a28e35d6c693 100644 (file)
@@ -33,7 +33,6 @@ void reload_viewer (struct output_viewer *);
 void reload_the_viewer (void);
 
 
-#define OUTPUT_FILE_NAME "psppire.txt"
-
+const char * output_file_name (void);
 
 #endif
index 02415d68bc3df8a6250d0a115f622c52de6c787f..2918238c419b2c23173edfad68b2a5d28aa75847 100644 (file)
@@ -121,13 +121,25 @@ initialize (struct command_line_processor *clp, int argc, char **argv)
 
   create_icon_factory ();
 
-  outp_configure_driver_line (
-    ss_cstr ("gui:ascii:screen:squeeze=on headers=off top-margin=0 "
-             "bottom-margin=0 paginate=off length=auto width=auto "
-            "emphasis=none "
-             "output-file=\"" OUTPUT_FILE_NAME "\" append=yes"));
+  {
+    const char *filename = output_file_name ();
+
+    struct string config_string;
+
+    ds_init_empty (&config_string);
+
+    ds_put_format (&config_string,
+                  "gui:ascii:screen:squeeze=on headers=off top-margin=0 "
+                  "bottom-margin=0 paginate=off length=auto width=auto "
+                  "emphasis=none "
+                  "output-file=\"%s\" append=yes", filename);
 
-  unlink (OUTPUT_FILE_NAME);
+    outp_configure_driver_line (ds_ss (&config_string));
+
+    unlink (filename);
+
+    ds_destroy (&config_string);
+  }
 
   journal_enable ();
   textdomain (PACKAGE);
index 598cdddd8eefaeea38196d188be9e33baeda36f0..5ab098577a57f015040543faf7387960ab46a8cd 100644 (file)
@@ -30,7 +30,7 @@ src_ui_terminal_pspp_LDADD = \
        @LIBINTL@ @LIBREADLINE@
 
 
-src_ui_terminal_pspp_LDFLAGS = $(PG_LDFLAGS)
+src_ui_terminal_pspp_LDFLAGS = $(PSPP_LDFLAGS) $(PG_LDFLAGS)
 
 if RELOCATABLE_VIA_LD
 src_ui_terminal_pspp_LDFLAGS += `$(RELOCATABLE_LDFLAGS) $(bindir)`
index be7f9e08c565c52677a4e0704f92acd86b84a948..f80dc5fc4a0df3f1c4250ef32e0bf3bb45e7a524 100755 (executable)
@@ -252,4 +252,23 @@ $TEMPDIR/foo.sps:10: error: DISPLAY: AKSDJ is not a variable name.
 EOF
 if [ $? -ne 0 ] ; then fail ; fi
 
+# Test for regression against bug #24569 in which PSPP crashed
+# upon attempt to insert a nonexistent file.
+activity="create wrapper 9"
+cat <<EOF > $TESTFILE
+INSERT 
+  FILE='$TEMPDIR/nonexistent'
+  ERROR=CONTINUE.
+  .
+
+LIST.
+
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+#This command should fail
+activity="run program 7"
+$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null
+if [ $? -eq 0 ] ; then no_result ; fi
+
 pass;