format: New function fmt_from_u32().
[pspp] / src / data / format.c
index 3a380bda45c0d960758739531289436da37f7af9..a2cb1310624dc35b8b0f126a9cc909378047506c 100644 (file)
@@ -293,6 +293,16 @@ fmt_for_output_from_input (const struct fmt_spec *input)
     case FMT_MONTH:
       break;
 
+    case FMT_MTIME:
+      if (input->d)
+        output.w = MAX (input->w, input->d + 6);
+      break;
+
+    case FMT_YMDHMS:
+      if (input->w)
+        output.w = MAX (input->w, input->d + 20);
+      break;
+
     default:
       NOT_REACHED ();
     }
@@ -719,6 +729,14 @@ fmt_max_decimals (enum fmt_type type, int width, enum fmt_use use)
       max_d = width - 21;
       break;
 
+    case FMT_YMDHMS:
+      max_d = width - 20;
+      break;
+
+    case FMT_MTIME:
+      max_d = width - 6;
+      break;
+
     case FMT_TIME:
       max_d = width - 9;
       break;
@@ -877,6 +895,40 @@ fmt_from_io (int io, enum fmt_type *fmt_type)
     }
 }
 
+/* Translate U32, which is in the form found in SAV and SPV files, into a
+   format specification, and stores the new specification in *F.
+
+   If LOOSE is false, checks that the format specification is appropriate as an
+   output format for a variable with the given WIDTH and reports an error if
+   not.  If LOOSE is true, instead adjusts the format's width and decimals as
+   necessary to be suitable.
+
+   Return true if successful, false if there was an error.. */
+bool
+fmt_from_u32 (uint32_t u32, int width, bool loose, struct fmt_spec *f)
+{
+  uint8_t raw_type = u32 >> 16;
+  uint8_t w = u32 >> 8;
+  uint8_t d = u32;
+
+  msg_disable ();
+  f->w = w;
+  f->d = d;
+  bool ok = fmt_from_io (raw_type, &f->type);
+  if (ok)
+    {
+      if (loose)
+        fmt_fix_output (f);
+      else
+        ok = fmt_check_output (f);
+    }
+  if (ok)
+    ok = fmt_check_width_compat (f, width);
+  msg_enable ();
+
+  return ok;
+}
+
 /* Returns true if TYPE may be used as an input format,
    false otherwise. */
 bool
@@ -946,6 +998,16 @@ fmt_date_template (enum fmt_type type, int width)
       s2 = "dd-mmm-yyyy HH:MM:SS";
       break;
 
+    case FMT_YMDHMS:
+      s1 = "yyyy-mm-dd HH:MM";
+      s2 = "yyyy-mm-dd HH:MM:SS";
+      break;
+
+    case FMT_MTIME:
+      s1 = "MM";
+      s2 = "MM:SS";
+      break;
+
     case FMT_TIME:
       s1 = "H:MM";
       s2 = "H:MM:SS";
@@ -990,6 +1052,8 @@ fmt_gui_name (enum fmt_type type)
     case FMT_MOYR:
     case FMT_WKYR:
     case FMT_DATETIME:
+    case FMT_YMDHMS:
+    case FMT_MTIME:
     case FMT_TIME:
     case FMT_DTIME:
     case FMT_WKDAY:
@@ -1158,3 +1222,6 @@ get_fmt_desc (enum fmt_type type)
 }
 
 const struct fmt_spec F_8_0 = {FMT_F, 8, 0};
+const struct fmt_spec F_8_2 = {FMT_F, 8, 2};
+const struct fmt_spec F_4_3 = {FMT_F, 4, 3};
+const struct fmt_spec F_5_1 = {FMT_F, 5, 1};