Implement the PRESERVE and RESTORE commands. 20100830040502/pspp 20100831040502/pspp 20100901040503/pspp 20100902040507/pspp 20100903040502/pspp
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Aug 2010 22:17:11 +0000 (15:17 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Aug 2010 22:17:11 +0000 (15:17 -0700)
NEWS
doc/utilities.texi
src/data/settings.c
src/data/settings.h
src/language/command.def
src/language/utilities/set.q
tests/language/utilities/set.at

diff --git a/NEWS b/NEWS
index a6192187aa451f1a6dd9b01823984c42356f036e..921e804123fbaaddc12390c47b201ff2bc8e65d2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,5 @@
 PSPP NEWS -- history of user-visible changes.
-Time-stamp: <2010-08-04 22:26:05 blp>
+Time-stamp: <2010-08-29 15:12:21 blp>
 Copyright (C) 1996-9, 2000, 2008, 2009, 2010 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -12,6 +12,8 @@ Changes from 0.7.3 to 0.7.5:
  * SAVE TRANSLATE is now implemented, with initial support for saving
    data in comma-separated value and tab-delimited formats.
 
+ * The PRESERVE and RESTORE commands are now implemented.
+
 Changes from 0.7.2 to 0.7.3:
 
  * Charts are now produced with Cairo and Pango, instead of libplot.
index 6b248e621fe9766dd5df0eeec079b9420bfa31c1..d4e7d3d9aa565e4da975e47610e26dbabfc83d44 100644 (file)
@@ -25,6 +25,7 @@ encountered in the input.
 * INCLUDE::                     Include a file within the current one.
 * INSERT::                      Insert a file within the current one.
 * PERMISSIONS::                 Change permissions on a file.
+* PRESERVE and RESTORE::        Saving settings and restoring them later.
 * SET::                         Adjust PSPP runtime parameters.
 * SHOW::                        Display runtime parameters.
 * SUBTITLE::                    Provide a document subtitle.
@@ -308,6 +309,22 @@ unchanged.
 This command cannot be used if the SAFER setting is active.
 
 
+@node PRESERVE and RESTORE
+@section PRESERVE and RESTORE
+@vindex PRESERVE
+@vindex RESTORE
+
+@display
+PRESERVE.
+@dots{}
+RESTORE.
+@end display
+
+@cmd{PRESERVE} saves all of the settings that @cmd{SET} (@pxref{SET})
+can adjust.  A later @cmd{RESTORE} command restores those settings.
+
+@cmd{PRESERVE} can be nested up to five levels deep.
+
 @node SET
 @section SET
 @vindex SET
index 551556f011cd89affcb3050042174948d73f268a..13512cc03242f7b7d7d78e6ebf2d0369bb9f13c3 100644 (file)
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include "settings.h"
+
+#include "data/settings.h"
+
 #include <assert.h>
 #include <stdlib.h>
 #include <time.h>
-#include "format.h"
-#include "value.h"
-#include "xalloc.h"
-#include <data/case.h>
-#include <libpspp/i18n.h>
-#include <libpspp/integer-format.h>
-#include <libpspp/message.h>
 
-#include "error.h"
-#include "minmax.h"
+#include "data/case.h"
+#include "data/format.h"
+#include "data/value.h"
+#include "libpspp/i18n.h"
+#include "libpspp/integer-format.h"
+#include "libpspp/message.h"
+
+#include "gl/error.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -119,6 +122,7 @@ static struct settings the_settings = {
    SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL}
 };
 
+/* Initializes the settings module. */
 void
 settings_init (void)
 {
@@ -128,10 +132,48 @@ settings_init (void)
   settings_set_decimal_char (get_system_decimal ());
 }
 
+/* Cleans up the settings module. */
 void
 settings_done (void)
 {
-  fmt_settings_destroy (the_settings.styles);
+  settings_destroy (&the_settings);
+}
+
+static void
+settings_copy (struct settings *dst, const struct settings *src)
+{
+  *dst = *src;
+  dst->styles = fmt_settings_clone (src->styles);
+}
+
+/* Returns a copy of the current settings. */
+struct settings *
+settings_get (void)
+{
+  struct settings *s = xmalloc (sizeof *s);
+  settings_copy (s, &the_settings);
+  return s;
+}
+
+/* Replaces the current settings by those in S.  The caller retains ownership
+   of S. */
+void
+settings_set (const struct settings *s)
+{
+  settings_destroy (&the_settings);
+  settings_copy (&the_settings, s);
+}
+
+/* Destroys S. */
+void
+settings_destroy (struct settings *s)
+{
+  if (s != NULL)
+    {
+      fmt_settings_destroy (s->styles);
+      if (s != &the_settings)
+        free (s);
+    }
 }
 
 /* Returns the floating-point format used for RB and RBHEX
index 27ba0cee1a9d1267220bfcd013f6676bbac90b3f..e68325f7f2bca21aed2ef100420a170b15c2522a 100644 (file)
@@ -31,6 +31,10 @@ struct settings;
 void settings_init (void);
 void settings_done (void);
 
+struct settings *settings_get (void);
+void settings_set (const struct settings *);
+void settings_destroy (struct settings *);
+
 enum float_format settings_get_input_float_format (void);
 void settings_set_input_float_format ( enum float_format);
 
index 174b80248e49248960c65515124bad634f0e6e7b..8400fdee7dff6b2d7e5b26ea390ddbf8cf07ff06 100644 (file)
@@ -31,8 +31,10 @@ DEF_CMD (S_ANY, 0, "N OF CASES", cmd_n_of_cases)
 DEF_CMD (S_ANY, F_ABBREV, "N", cmd_n_of_cases)
 DEF_CMD (S_ANY, 0, "NEW FILE", cmd_new_file)
 DEF_CMD (S_ANY, 0, "PERMISSIONS", cmd_permissions)
+DEF_CMD (S_ANY, 0, "PRESERVE", cmd_preserve)
 DEF_CMD (S_ANY, F_ABBREV, "Q", cmd_finish)
 DEF_CMD (S_ANY, 0, "QUIT", cmd_finish)
+DEF_CMD (S_ANY, 0, "RESTORE", cmd_restore)
 DEF_CMD (S_ANY, 0, "SET", cmd_set)
 DEF_CMD (S_ANY, 0, "SHOW", cmd_show)
 DEF_CMD (S_ANY, F_KEEP_FINAL_TOKEN, "SUBTITLE", cmd_subtitle)
@@ -224,7 +226,6 @@ UNIMPL_CMD ("POINT", "Marker in keyed file")
 UNIMPL_CMD ("PPLOT", "Plot time series variables")
 UNIMPL_CMD ("PREDICT", "Specify forecast period")
 UNIMPL_CMD ("PREFSCAL", "Multidimensional unfolding")
-UNIMPL_CMD ("PRESERVE", "Push settings")
 UNIMPL_CMD ("PRINCALS", "PCA by alternating least squares")
 UNIMPL_CMD ("PROBIT", "Probit analysis")
 UNIMPL_CMD ("PROCEDURE OUTPUT", "Specify output file")
@@ -237,7 +238,6 @@ UNIMPL_CMD ("RECORD TYPE", "Defines a type of record within FILE TYPE")
 UNIMPL_CMD ("REFORMAT", "Read obsolete files")
 UNIMPL_CMD ("REPEATING DATA", "Specify multiple cases per input record")
 UNIMPL_CMD ("REPORT", "Pretty print working file")
-UNIMPL_CMD ("RESTORE", "Restore settings")
 UNIMPL_CMD ("RMV", "Replace missing values")
 UNIMPL_CMD ("SCRIPT", "Run script file")
 UNIMPL_CMD ("SEASON", "Estimate seasonal factors")
index 3c0109cce89b4a1023640b08608a460934597dba..30f3c56e578fda7ed4c7b6ba79d5058c4bbb07ed 100644 (file)
@@ -923,6 +923,45 @@ cmd_show (struct lexer *lexer, struct dataset *ds)
 
   return CMD_SUCCESS;
 }
+\f
+#define MAX_SAVED_SETTINGS 5
+
+static struct settings *saved_settings[MAX_SAVED_SETTINGS];
+static int n_saved_settings;
+
+int
+cmd_preserve (struct lexer *lexer, struct dataset *ds UNUSED)
+{
+  if (n_saved_settings < MAX_SAVED_SETTINGS)
+    {
+      saved_settings[n_saved_settings++] = settings_get ();
+      return lex_end_of_command (lexer);
+    }
+  else
+    {
+      msg (SE, _("Too many PRESERVE commands without a RESTORE: at most "
+                 "%d levels of saved settings are allowed."),
+           MAX_SAVED_SETTINGS);
+      return CMD_CASCADING_FAILURE;
+    }
+}
+
+int
+cmd_restore (struct lexer *lexer, struct dataset *ds UNUSED)
+{
+  if (n_saved_settings > 0)
+    {
+      struct settings *s = saved_settings[--n_saved_settings];
+      settings_set (s);
+      settings_destroy (s);
+      return lex_end_of_command (lexer);
+    }
+  else
+    {
+      msg (SE, _("RESTORE without matching PRESERVE."));
+      return CMD_FAILURE;
+    }
+}
 
 /*
    Local Variables:
index e1b92573f31e910e32540d3846d54e85fdf21a05..e84b44d9b2f98fecca6a46067d30315722d4f568 100644 (file)
@@ -92,3 +92,23 @@ x,y,z
 ])
 
 AT_CLEANUP
+\f
+AT_BANNER([PRESERVE and RESTORE])
+
+AT_SETUP([PRESERVE of SET FORMAT])
+AT_DATA([set.pspp], [dnl
+SHOW FORMAT.
+PRESERVE.
+SET FORMAT F10.0.
+SHOW FORMAT
+RESTORE.
+SHOW FORMAT.
+])
+AT_CHECK([pspp -O format=csv set.pspp], [0], [dnl
+set.pspp:1: note: SHOW: FORMAT is F8.2.
+
+set.pspp:5: note: SHOW: FORMAT is F10.0.
+
+set.pspp:6: note: SHOW: FORMAT is F8.2.
+])
+AT_CLEANUP