pspp-convert: Support decrypting SPV files.
[pspp] / src / data / settings.c
index 10b20f8a352b9b83eec4307c41696f1a180a56bf..f4efb99fa84ee0d4eedd18236f72db9c6b363954 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2015 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
 
    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
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
    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 <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/minmax.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
-static int global_algorithm = ENHANCED;
-
 struct settings
 {
   /* Integer format used for IB and PIB input. */
 struct settings
 {
   /* Integer format used for IB and PIB input. */
@@ -49,8 +49,8 @@ struct settings
   /* Format of reals in output (SET WRB). */
   enum float_format output_float_format;
 
   /* Format of reals in output (SET WRB). */
   enum float_format output_float_format;
 
-  int *viewlength;
-  int *viewwidth;
+  int viewlength;
+  int viewwidth;
   bool safer_mode;
   bool include;
   int epoch;
   bool safer_mode;
   bool include;
   int epoch;
@@ -63,103 +63,120 @@ struct settings
   bool printback;
   bool mprint;
   int mxloops;
   bool printback;
   bool mprint;
   int mxloops;
-  bool nulline;
-  char endcmd;
   size_t workspace;
   struct fmt_spec default_format;
   bool testing_mode;
   size_t workspace;
   struct fmt_spec default_format;
   bool testing_mode;
+  int fuzzbits;
 
   int cmd_algorithm;
 
   int cmd_algorithm;
-  int *algorithm;
+  int global_algorithm;
   int syntax;
 
   int syntax;
 
-  struct fmt_number_style *styles;
+  struct fmt_settings *styles;
 
   enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
 
   enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
+
+  enum settings_value_show show_values;
+  enum settings_value_show show_variables;
 };
 
 static struct settings the_settings = {
 };
 
 static struct settings the_settings = {
-    /* input_integer_format */
-  INTEGER_NATIVE,
-    /* input_float_format */
-  FLOAT_NATIVE_DOUBLE,
-    /* output_integer_format */
-  INTEGER_NATIVE,
-    /* output_float_format */
-  FLOAT_NATIVE_DOUBLE,
-    /* viewlength */
-  NULL,
-    /* viewwidth */
-  NULL,
-    /* safer_mode */
-  false,
-    /* include */
-  true,
-    /* epoch */
-  -1,
-    /* route_errors_to_terminal */
-  true,
-    /* route_errors_to_listing */
-  true,
-    /* scompress */
-  true,
-    /* undefined */
-  true,
-    /* blanks */
-  SYSMIS,
-    /* max_messages */
+  INTEGER_NATIVE,               /* input_integer_format */
+  FLOAT_NATIVE_DOUBLE,          /* input_float_format */
+  INTEGER_NATIVE,               /* output_integer_format */
+  FLOAT_NATIVE_DOUBLE,          /* output_float_format */
+  24,                           /* viewlength */
+  79,                           /* viewwidth */
+  false,                        /* safer_mode */
+  true,                         /* include */
+  -1,                           /* epoch */
+  true,                         /* route_errors_to_terminal */
+  true,                         /* route_errors_to_listing */
+  true,                         /* scompress */
+  true,                         /* undefined */
+  SYSMIS,                       /* blanks */
+
+  /* max_messages */
   {
     100,                        /* MSG_S_ERROR */
     100,                        /* MSG_S_WARNING */
     100                         /* MSG_S_NOTE */
   },
   {
     100,                        /* MSG_S_ERROR */
     100,                        /* MSG_S_WARNING */
     100                         /* MSG_S_NOTE */
   },
-    /* printback */
-  true,
-    /* mprint */
-  true,
-    /* mxloops */
-  1,
-    /* nulline */
-  true,
-    /* endcmd */
-  '.',
-    /* workspace */
-  64L * 1024 * 1024,
-    /* default_format */
-  {FMT_F, 8, 2},
-    /* testing_mode */
-  false,
-    /* cmd_algorithm */
-  ENHANCED,
-    /* algorithm */
-  &global_algorithm,
-    /* syntax */
-  ENHANCED,
-    /* styles */
-  NULL,
-    /* output devices */
+
+  true,                         /* printback */
+  true,                         /* mprint */
+  40,                           /* mxloops */
+  64L * 1024 * 1024,            /* workspace */
+  {FMT_F, 8, 2},                /* default_format */
+  false,                        /* testing_mode */
+  6,                            /* fuzzbits */
+  ENHANCED,                     /* cmd_algorithm */
+  ENHANCED,                     /* global_algorithm */
+  ENHANCED,                     /* syntax */
+  NULL,                         /* styles */
+
+  /* output_routing */
   {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
    SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
    0,
   {SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
    SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL,
    0,
-   SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL}
-};
+   SETTINGS_DEVICE_LISTING | SETTINGS_DEVICE_TERMINAL},
 
 
-static void init_viewport ( int *, int *);
+  SETTINGS_VALUE_SHOW_LABEL,
+  SETTINGS_VALUE_SHOW_LABEL
+};
 
 
+/* Initializes the settings module. */
 void
 void
-settings_init (int *width, int *length)
+settings_init (void)
 {
 {
-  init_viewport (width, length);
   settings_set_epoch (-1);
   settings_set_epoch (-1);
-  the_settings.styles = fmt_create ();
+  the_settings.styles = fmt_settings_create ();
 
   settings_set_decimal_char (get_system_decimal ());
 }
 
 
   settings_set_decimal_char (get_system_decimal ());
 }
 
+/* Cleans up the settings module. */
 void
 settings_done (void)
 {
 void
 settings_done (void)
 {
-  fmt_done (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
 }
 
 /* Returns the floating-point format used for RB and RBHEX
@@ -226,35 +243,28 @@ settings_set_output_float_format ( enum float_format float_format)
 int
 settings_get_viewlength (void)
 {
 int
 settings_get_viewlength (void)
 {
-  return *the_settings.viewlength;
+  return the_settings.viewlength;
 }
 
 /* Sets the view length. */
 void
 settings_set_viewlength ( int viewlength_)
 {
 }
 
 /* Sets the view length. */
 void
 settings_set_viewlength ( int viewlength_)
 {
-  *the_settings.viewlength = viewlength_;
+  the_settings.viewlength = viewlength_;
 }
 
 /* Screen width. */
 int
 settings_get_viewwidth(void)
 {
 }
 
 /* Screen width. */
 int
 settings_get_viewwidth(void)
 {
-  return *the_settings.viewwidth;
+  return the_settings.viewwidth;
 }
 
 /* Sets the screen width. */
 void
 settings_set_viewwidth ( int viewwidth_)
 {
 }
 
 /* Sets the screen width. */
 void
 settings_set_viewwidth ( int viewwidth_)
 {
-  *the_settings.viewwidth = viewwidth_;
-}
-
-static void
-init_viewport ( int  *width, int *length)
-{
-  the_settings.viewwidth = width;
-  the_settings.viewlength = length;
+  the_settings.viewwidth = viewwidth_;
 }
 
 /* Whether PSPP can erase and overwrite files. */
 }
 
 /* Whether PSPP can erase and overwrite files. */
@@ -364,9 +374,9 @@ settings_get_max_messages (enum msg_severity severity)
 
 /* Sets the maximum number of messages to show of the given SEVERITY before
    aborting to MAX.  (The value for MSG_S_WARNING is interpreted as maximum
 
 /* Sets the maximum number of messages to show of the given SEVERITY before
    aborting to MAX.  (The value for MSG_S_WARNING is interpreted as maximum
-   number of warnings and errors combined.)  In addition, in the case of 
+   number of warnings and errors combined.)  In addition, in the case of
    warnings the special value of zero indicates that no warnings are to be
    warnings the special value of zero indicates that no warnings are to be
-   issued. 
+   issued.
 */
 void
 settings_set_max_messages (enum msg_severity severity, int max)
 */
 void
 settings_set_max_messages (enum msg_severity severity, int max)
@@ -422,34 +432,6 @@ settings_set_mxloops ( int mxloops)
   the_settings.mxloops = mxloops;
 }
 
   the_settings.mxloops = mxloops;
 }
 
-/* Whether a blank line is a command terminator. */
-bool
-settings_get_nulline (void)
-{
-  return the_settings.nulline;
-}
-
-/* Set whether a blank line is a command terminator. */
-void
-settings_set_nulline ( bool nulline)
-{
-  the_settings.nulline = nulline;
-}
-
-/* The character used to terminate commands. */
-char
-settings_get_endcmd (void)
-{
-  return the_settings.endcmd;
-}
-
-/* Set the character used to terminate commands. */
-void
-settings_set_endcmd ( char endcmd)
-{
-  the_settings.endcmd = endcmd;
-}
-
 /* Approximate maximum amount of memory to use for cases, in
    bytes. */
 size_t
 /* Approximate maximum amount of memory to use for cases, in
    bytes. */
 size_t
@@ -471,7 +453,7 @@ settings_get_workspace_cases (const struct caseproto *proto)
    bytes. */
 
 void
    bytes. */
 
 void
-settings_set_workspace ( size_t workspace)
+settings_set_workspace (size_t workspace)
 {
   the_settings.workspace = workspace;
 }
 {
   the_settings.workspace = workspace;
 }
@@ -507,18 +489,30 @@ settings_set_testing_mode ( bool testing_mode)
   the_settings.testing_mode = testing_mode;
 }
 
   the_settings.testing_mode = testing_mode;
 }
 
+int
+settings_get_fuzzbits (void)
+{
+  return the_settings.fuzzbits;
+}
+
+void
+settings_set_fuzzbits (int fuzzbits)
+{
+  the_settings.fuzzbits = fuzzbits;
+}
+
 /* Return the current algorithm setting */
 enum behavior_mode
 settings_get_algorithm (void)
 {
 /* Return the current algorithm setting */
 enum behavior_mode
 settings_get_algorithm (void)
 {
-  return *the_settings.algorithm;
+  return the_settings.cmd_algorithm;
 }
 
 /* Set the algorithm option globally. */
 void
 settings_set_algorithm (enum behavior_mode mode)
 {
 }
 
 /* Set the algorithm option globally. */
 void
 settings_set_algorithm (enum behavior_mode mode)
 {
-  global_algorithm = mode;
+  the_settings.global_algorithm = the_settings.cmd_algorithm = mode;
 }
 
 /* Set the algorithm option for this command only */
 }
 
 /* Set the algorithm option for this command only */
@@ -526,14 +520,13 @@ void
 settings_set_cmd_algorithm ( enum behavior_mode mode)
 {
   the_settings.cmd_algorithm = mode;
 settings_set_cmd_algorithm ( enum behavior_mode mode)
 {
   the_settings.cmd_algorithm = mode;
-  the_settings.algorithm = &the_settings.cmd_algorithm;
 }
 
 /* Unset the algorithm option for this command */
 void
 unset_cmd_algorithm (void)
 {
 }
 
 /* Unset the algorithm option for this command */
 void
 unset_cmd_algorithm (void)
 {
-  the_settings.algorithm = &global_algorithm;
+  the_settings.cmd_algorithm = the_settings.global_algorithm;
 }
 
 /* Get the current syntax setting */
 }
 
 /* Get the current syntax setting */
@@ -552,11 +545,10 @@ settings_set_syntax ( enum behavior_mode mode)
 
 \f
 
 
 \f
 
-/* Find the grouping characters in CC_STRING and set CC's
-   grouping and decimal members appropriately.  Returns true if
-   successful, false otherwise. */
+/* Find the grouping characters in CC_STRING and sets *GROUPING and *DECIMAL
+   appropriately.  Returns true if successful, false otherwise. */
 static bool
 static bool
-find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
+find_cc_separators (const char *cc_string, char *decimal, char *grouping)
 {
   const char *sp;
   int comma_cnt, dot_cnt;
 {
   const char *sp;
   int comma_cnt, dot_cnt;
@@ -578,52 +570,50 @@ find_cc_separators (const char *cc_string, struct fmt_number_style *cc)
 
   if (comma_cnt == 3)
     {
 
   if (comma_cnt == 3)
     {
-      cc->decimal = '.';
-      cc->grouping = ',';
+      *decimal = '.';
+      *grouping = ',';
     }
   else
     {
     }
   else
     {
-      cc->decimal = ',';
-      cc->grouping = '.';
+      *decimal = ',';
+      *grouping = '.';
     }
   return true;
 }
 
     }
   return true;
 }
 
-/* Extracts a token from IN into a newly allocated AFFIX.  Tokens
-   are delimited by GROUPING.  The token is truncated to at most
-   FMT_STYLE_AFFIX_MAX characters.  Returns the first character
-   following the token. */
+/* Extracts a token from IN into a newly allocated string AFFIXP.  Tokens are
+   delimited by GROUPING.  Returns the first character following the token. */
 static const char *
 static const char *
-extract_cc_token (const char *in, int grouping, struct substring *affix)
+extract_cc_token (const char *in, int grouping, char **affixp)
 {
 {
-  size_t ofs = 0;
-  ss_alloc_uninit (affix, FMT_STYLE_AFFIX_MAX);
+  char *out;
+
+  out = *affixp = xmalloc (strlen (in) + 1);
   for (; *in != '\0' && *in != grouping; in++)
     {
       if (*in == '\'' && in[1] == grouping)
         in++;
   for (; *in != '\0' && *in != grouping; in++)
     {
       if (*in == '\'' && in[1] == grouping)
         in++;
-      if (ofs < FMT_STYLE_AFFIX_MAX)
-        ss_data (*affix)[ofs++] = *in;
+      *out++ = *in;
     }
     }
-  affix->length = ofs;
+  *out = '\0';
 
   if (*in == grouping)
     in++;
   return in;
 }
 
 
   if (*in == grouping)
     in++;
   return in;
 }
 
-
 /* Sets custom currency specifier CC having name CC_NAME ('A' through
    'E') to correspond to the settings in CC_STRING. */
 bool
 settings_set_cc (const char *cc_string, enum fmt_type type)
 {
 /* Sets custom currency specifier CC having name CC_NAME ('A' through
    'E') to correspond to the settings in CC_STRING. */
 bool
 settings_set_cc (const char *cc_string, enum fmt_type type)
 {
-  struct fmt_number_style *cc = &the_settings.styles[type];
+  char *neg_prefix, *prefix, *suffix, *neg_suffix;
+  char decimal, grouping;
 
   assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
 
   /* Determine separators. */
 
   assert (fmt_get_category (type) == FMT_CAT_CUSTOM);
 
   /* Determine separators. */
-  if (!find_cc_separators (cc_string, cc))
+  if (!find_cc_separators (cc_string, &decimal, &grouping))
     {
       msg (SE, _("%s: Custom currency string `%s' does not contain "
                  "exactly three periods or commas (or it contains both)."),
     {
       msg (SE, _("%s: Custom currency string `%s' does not contain "
                  "exactly three periods or commas (or it contains both)."),
@@ -631,12 +621,18 @@ settings_set_cc (const char *cc_string, enum fmt_type type)
       return false;
     }
 
       return false;
     }
 
-  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_prefix);
-  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->prefix);
-  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->suffix);
-  cc_string = extract_cc_token (cc_string, cc->grouping, &cc->neg_suffix);
+  cc_string = extract_cc_token (cc_string, grouping, &neg_prefix);
+  cc_string = extract_cc_token (cc_string, grouping, &prefix);
+  cc_string = extract_cc_token (cc_string, grouping, &suffix);
+  cc_string = extract_cc_token (cc_string, grouping, &neg_suffix);
+
+  fmt_settings_set_style (the_settings.styles, type, decimal, grouping,
+                          neg_prefix, prefix, suffix, neg_suffix);
 
 
-  fmt_check_style (cc);
+  free (neg_suffix);
+  free (suffix);
+  free (prefix);
+  free (neg_prefix);
 
   return true;
 }
 
   return true;
 }
@@ -645,56 +641,52 @@ settings_set_cc (const char *cc_string, enum fmt_type type)
 int
 settings_get_decimal_char (enum fmt_type type)
 {
 int
 settings_get_decimal_char (enum fmt_type type)
 {
-  return fmt_get_style (the_settings.styles, type)->decimal;
+  return fmt_settings_get_style (the_settings.styles, type)->decimal;
 }
 
 void
 settings_set_decimal_char (char decimal)
 {
 }
 
 void
 settings_set_decimal_char (char decimal)
 {
-  fmt_set_decimal (the_settings.styles, decimal);
+  fmt_settings_set_decimal (the_settings.styles, decimal);
 }
 
 }
 
-
-
 /* Returns the number formatting style associated with the given
    format TYPE. */
 const struct fmt_number_style *
 settings_get_style (enum fmt_type type)
 {
   assert (is_fmt_type (type));
 /* Returns the number formatting style associated with the given
    format TYPE. */
 const struct fmt_number_style *
 settings_get_style (enum fmt_type type)
 {
   assert (is_fmt_type (type));
-  return &the_settings.styles[type];
+  return fmt_settings_get_style (the_settings.styles, type);
 }
 
 }
 
-
 /* Returns a string of the form "$#,###.##" according to FMT,
    which must be of type FMT_DOLLAR.  The caller must free the
    string. */
 char *
 settings_dollar_template (const struct fmt_spec *fmt)
 {
 /* Returns a string of the form "$#,###.##" according to FMT,
    which must be of type FMT_DOLLAR.  The caller must free the
    string. */
 char *
 settings_dollar_template (const struct fmt_spec *fmt)
 {
-  const struct fmt_number_style *styles = the_settings.styles;
   struct string str = DS_EMPTY_INITIALIZER;
   int c;
   const struct fmt_number_style *fns ;
 
   assert (fmt->type == FMT_DOLLAR);
 
   struct string str = DS_EMPTY_INITIALIZER;
   int c;
   const struct fmt_number_style *fns ;
 
   assert (fmt->type == FMT_DOLLAR);
 
-  fns = fmt_get_style (styles, fmt->type);
+  fns = fmt_settings_get_style (the_settings.styles, fmt->type);
 
 
-  ds_put_char (&str, '$');
+  ds_put_byte (&str, '$');
   for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
     {
   for (c = MAX (fmt->w - fmt->d - 1, 0); c > 0; )
     {
-      ds_put_char (&str, '#');
+      ds_put_byte (&str, '#');
       if (--c % 4 == 0 && c > 0)
         {
       if (--c % 4 == 0 && c > 0)
         {
-          ds_put_char (&str, fns->grouping);
+          ds_put_byte (&str, fns->grouping);
           --c;
         }
     }
   if (fmt->d > 0)
     {
           --c;
         }
     }
   if (fmt->d > 0)
     {
-      ds_put_char (&str, fns->decimal);
-      ds_put_char_multiple (&str, '#', fmt->d);
+      ds_put_byte (&str, fns->decimal);
+      ds_put_byte_multiple (&str, '#', fmt->d);
     }
 
   return ds_cstr (&str);
     }
 
   return ds_cstr (&str);
@@ -714,3 +706,28 @@ settings_get_output_routing (enum settings_output_type type)
   assert (type < SETTINGS_N_OUTPUT_TYPES);
   return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
 }
   assert (type < SETTINGS_N_OUTPUT_TYPES);
   return the_settings.output_routing[type] | SETTINGS_DEVICE_UNFILTERED;
 }
+
+enum settings_value_show
+settings_get_show_values (void)
+{
+  return the_settings.show_values;
+}
+
+void
+settings_set_show_values (enum settings_value_show s)
+{
+  the_settings.show_values = s;
+}
+
+
+enum settings_value_show
+settings_get_show_variables (void)
+{
+  return the_settings.show_variables;
+}
+
+void
+settings_set_show_variables (enum settings_value_show s)
+{
+  the_settings.show_variables = s;
+}