lexer: Fix buffer overread in journaling when source does not end in \n.
[pspp] / src / data / settings.c
index 13512cc03242f7b7d7d78e6ebf2d0369bb9f13c3..114200cf060d5a4ed0d5adc2c910f2a3e81b0c42 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
@@ -29,7 +29,6 @@
 #include "libpspp/integer-format.h"
 #include "libpspp/message.h"
 
 #include "libpspp/integer-format.h"
 #include "libpspp/message.h"
 
-#include "gl/error.h"
 #include "gl/minmax.h"
 #include "gl/xalloc.h"
 
 #include "gl/minmax.h"
 #include "gl/xalloc.h"
 
@@ -64,11 +63,10 @@ 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 global_algorithm;
 
   int cmd_algorithm;
   int global_algorithm;
@@ -77,6 +75,9 @@ struct settings
   struct fmt_settings *styles;
 
   enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
   struct fmt_settings *styles;
 
   enum settings_output_devices output_routing[SETTINGS_N_OUTPUT_TYPES];
+
+  enum settings_var_style var_output_style;
+  enum settings_value_style value_output_style;
 };
 
 static struct settings the_settings = {
 };
 
 static struct settings the_settings = {
@@ -104,12 +105,11 @@ static struct settings the_settings = {
 
   true,                         /* printback */
   true,                         /* mprint */
 
   true,                         /* printback */
   true,                         /* mprint */
-  1,                            /* mxloops */
-  true,                         /* nulline */
-  '.',                          /* endcmd */
+  40,                           /* mxloops */
   64L * 1024 * 1024,            /* workspace */
   {FMT_F, 8, 2},                /* default_format */
   false,                        /* testing_mode */
   64L * 1024 * 1024,            /* workspace */
   {FMT_F, 8, 2},                /* default_format */
   false,                        /* testing_mode */
+  6,                            /* fuzzbits */
   ENHANCED,                     /* cmd_algorithm */
   ENHANCED,                     /* global_algorithm */
   ENHANCED,                     /* syntax */
   ENHANCED,                     /* cmd_algorithm */
   ENHANCED,                     /* global_algorithm */
   ENHANCED,                     /* syntax */
@@ -119,7 +119,10 @@ static struct settings the_settings = {
   {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},
+
+  SETTINGS_VAR_STYLE_LABELS,
+  SETTINGS_VAL_STYLE_LABELS
 };
 
 /* Initializes the settings module. */
 };
 
 /* Initializes the settings module. */
@@ -371,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)
@@ -429,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
@@ -478,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;
 }
@@ -514,6 +489,18 @@ 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)
@@ -558,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;
@@ -584,36 +570,32 @@ 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 AFFIX, using BUFFER for storage.  BUFFER must
-   have at least FMT_STYLE_AFFIX_MAX + 1 bytes of space.  Tokens are delimited
-   by GROUPING.  The token is truncated to at most FMT_STYLE_AFFIX_MAX bytes,
-   followed by a null terminator.  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,
-                  char buffer[FMT_STYLE_AFFIX_MAX + 1])
+extract_cc_token (const char *in, int grouping, char **affixp)
 {
 {
-  size_t ofs = 0;
+  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)
-        buffer[ofs++] = *in;
+      *out++ = *in;
     }
     }
-  *affix = ss_buffer (buffer, ofs);
+  *out = '\0';
 
   if (*in == grouping)
     in++;
 
   if (*in == grouping)
     in++;
@@ -625,16 +607,13 @@ extract_cc_token (const char *in, int grouping, struct substring *affix,
 bool
 settings_set_cc (const char *cc_string, enum fmt_type type)
 {
 bool
 settings_set_cc (const char *cc_string, enum fmt_type type)
 {
-  char a[FMT_STYLE_AFFIX_MAX + 1];
-  char b[FMT_STYLE_AFFIX_MAX + 1];
-  char c[FMT_STYLE_AFFIX_MAX + 1];
-  char d[FMT_STYLE_AFFIX_MAX + 1];
-  struct fmt_number_style cc;
+  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)."),
@@ -642,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, a);
-  cc_string = extract_cc_token (cc_string, cc.grouping, &cc.prefix, b);
-  cc_string = extract_cc_token (cc_string, cc.grouping, &cc.suffix, c);
-  cc_string = extract_cc_token (cc_string, cc.grouping, &cc.neg_suffix, d);
+  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, &cc);
+  fmt_settings_set_style (the_settings.styles, type, decimal, grouping,
+                          neg_prefix, prefix, suffix, neg_suffix);
+
+  free (neg_suffix);
+  free (suffix);
+  free (prefix);
+  free (neg_prefix);
 
   return true;
 }
 
   return true;
 }
@@ -688,20 +673,20 @@ settings_dollar_template (const struct fmt_spec *fmt)
 
   fns = fmt_settings_get_style (the_settings.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);
@@ -721,3 +706,30 @@ 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_style
+settings_get_value_style (void)
+{
+  return the_settings.value_output_style;
+}
+
+void
+settings_set_value_style (enum settings_value_style s)
+{
+  the_settings.value_output_style = s;
+}
+
+
+
+enum settings_var_style
+settings_get_var_style (void)
+{
+  return the_settings.var_output_style;
+}
+
+
+void
+settings_set_var_style (enum settings_var_style s)
+{
+  the_settings.var_output_style = s;
+}