Change many %g format specifiers to %.*g with precision DBL_DIG + 1.
[pspp] / src / language / stats / descriptives.c
index 94421ef1e979807776a954d354c5be08019fcccc..f80965616f0c1f5fc29b04a9a788440d8471f676 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-2000, 2009-2012 Free Software Foundation, Inc.
+   Copyright (C) 1997-2000, 2009-2014 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
@@ -16,6 +16,7 @@
 
 #include <config.h>
 
+#include <float.h>
 #include <limits.h>
 #include <math.h>
 #include <stdlib.h>
@@ -397,6 +398,13 @@ cmd_descriptives (struct lexer *lexer, struct dataset *ds)
             }
         }
 
+      /* It would be better to handle Z scores correctly (however we define
+         that) when TEMPORARY is in effect, but in the meantime this at least
+         prevents a use-after-free error.  See bug #38786.  */
+      if (proc_make_temporary_transformations_permanent (ds))
+        msg (SW, _("DESCRIPTIVES with Z scores ignores TEMPORARY.  "
+                   "Temporary transformations will be made permanent."));
+
       proto = caseproto_create ();
       for (i = 0; i < 1 + 2 * z_cnt; i++)
         proto = caseproto_add_width (proto, 0);
@@ -434,7 +442,8 @@ cmd_descriptives (struct lexer *lexer, struct dataset *ds)
       dsc->vars[i].moments = moments_create (dsc->max_moment);
 
   /* Data pass. */
-  grouper = casegrouper_create_splits (proc_open (ds), dict);
+  grouper = casegrouper_create_splits (proc_open_filtering (ds, z_cnt == 0),
+                                       dict);
   while (casegrouper_get_next_group (grouper, &group))
     calc_descriptives (dsc, group, ds);
   ok = casegrouper_destroy (grouper);
@@ -994,17 +1003,18 @@ display (struct dsc_proc *dsc)
 
       nc = 0;
       tab_text (t, nc++, i + 1, TAB_LEFT, var_to_string (dv->v));
-      tab_text_format (t, nc++, i + 1, 0, "%g", dv->valid);
+      tab_text_format (t, nc++, i + 1, 0, "%.*g", DBL_DIG + 1, dv->valid);
       if (dsc->format == DSC_SERIAL)
-       tab_text_format (t, nc++, i + 1, 0, "%g", dv->missing);
+       tab_text_format (t, nc++, i + 1, 0, "%.*g", DBL_DIG + 1, dv->missing);
 
       for (j = 0; j < DSC_N_STATS; j++)
        if (dsc->show_stats & (1ul << j))
          tab_double (t, nc++, i + 1, TAB_NONE, dv->stats[j], NULL);
     }
 
-  tab_title (t, _("Valid cases = %g; cases with missing value(s) = %g."),
-            dsc->valid, dsc->missing_listwise);
+  tab_title (t, _("Valid cases = %.*g; cases with missing value(s) = %.*g."),
+            DBL_DIG + 1, dsc->valid,
+             DBL_DIG + 1, dsc->missing_listwise);
 
   tab_submit (t);
 }