Whitespace changes only: Remove trailing whitespace
[pspp] / src / language / xforms / recode.c
index 44e5b8513326e32a844ba9bee618d94ce74ba777..361b5a64f867b27b20d4f69c1c7d968b3c79280d 100644 (file)
@@ -125,7 +125,7 @@ static void set_map_out_num (struct map_out *, double);
 static void set_map_out_str (struct map_out *, struct pool *,
                              struct substring);
 
-static void enlarge_dst_widths (struct recode_trns *);
+static bool enlarge_dst_widths (struct recode_trns *);
 static void create_dst_vars (struct recode_trns *, struct dictionary *);
 
 static trns_proc_func recode_trns_proc;
@@ -157,7 +157,13 @@ cmd_recode (struct lexer *lexer, struct dataset *ds)
       /* Ensure that all the output strings are at least as wide
          as the widest destination variable. */
       if (trns->dst_type == VAL_STRING)
-        enlarge_dst_widths (trns);
+       {
+         if ( ! enlarge_dst_widths (trns))
+           {
+             recode_trns_free (trns);
+             return CMD_FAILURE;
+           }
+       }
 
       /* Create destination variables, if needed.
          This must be the final step; otherwise we'd have to
@@ -322,7 +328,7 @@ parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool,
         set_map_in_generic (in, MAP_MISSING);
       else if (!lex_force_string (lexer))
         return false;
-      else 
+      else
        {
          set_map_in_str (in, pool, lex_tokss (lexer), max_src_width,
                           dict_encoding);
@@ -330,7 +336,7 @@ parse_map_in (struct lexer *lexer, struct map_in *in, struct pool *pool,
          if (lex_token (lexer) == T_ID
              && lex_id_match (ss_cstr ("THRU"), lex_tokss (lexer)))
            {
-             msg (SE, _("THRU is not allowed with string variables."));
+             msg (SE, _("%s is not allowed with string variables."), "THRU");
              return false;
            }
        }
@@ -406,10 +412,10 @@ parse_map_out (struct lexer *lexer, struct pool *pool, struct map_out *out)
       set_map_out_str (out, pool, lex_tokss (lexer));
       lex_get (lexer);
     }
-  else if (lex_match_id (lexer, "COPY")) 
+  else if (lex_match_id (lexer, "COPY"))
     {
       out->copy_input = true;
-      out->width = 0; 
+      out->width = 0;
     }
   else
     {
@@ -528,26 +534,46 @@ parse_dst_vars (struct lexer *lexer, struct recode_trns *trns,
 
 /* Ensures that all the output values in TRNS are as wide as the
    widest destination variable. */
-static void
+static bool
 enlarge_dst_widths (struct recode_trns *trns)
 {
   size_t i;
-
+  const struct variable *narrow_var = NULL;
+  int min_dst_width = INT_MAX;
   trns->max_dst_width = 0;
+
   for (i = 0; i < trns->var_cnt; i++)
     {
       const struct variable *v = trns->dst_vars[i];
       if (var_get_width (v) > trns->max_dst_width)
         trns->max_dst_width = var_get_width (v);
+
+      if (var_get_width (v) < min_dst_width)
+       {
+         min_dst_width = var_get_width (v);
+         narrow_var = v;
+       }
     }
 
   for (i = 0; i < trns->map_cnt; i++)
     {
       struct map_out *out = &trns->mappings[i].out;
       if (!out->copy_input)
-        value_resize_pool (trns->pool, &out->value,
-                           out->width, trns->max_dst_width);
+       {
+         if (out->width > min_dst_width)
+           {
+             msg (ME,
+                  _("Cannot recode because the variable %s would require a width of %d bytes or greater, but it has a width of only %d bytes."),
+                  var_get_name (narrow_var), out->width, min_dst_width);
+             return false;
+           }
+
+         value_resize_pool (trns->pool, &out->value,
+                            out->width, trns->max_dst_width);
+       }
     }
+
+  return true;
 }
 
 /* Creates destination variables that don't already exist. */