+ /* Create transformation. */
+ for (i = 0; i < arc->n_specs; i++)
+ {
+ struct arc_spec *spec = &arc->specs[i];
+ struct arc_item **items;
+ struct arc_item *item;
+ size_t n_items;
+ size_t j;
+
+ /* Create destination variable. */
+ spec->dst = dict_create_var_assert (dict, dst_names[i], 0);
+
+ /* Create array of pointers to items. */
+ n_items = hmap_count (spec->items);
+ items = xmalloc (n_items * sizeof *items);
+ j = 0;
+ HMAP_FOR_EACH (item, struct arc_item, hmap_node, spec->items)
+ items[j++] = item;
+
+ assert (j == n_items);
+
+ /* Sort array by value. */
+ sort (items, n_items, sizeof *items, compare_arc_items, NULL);
+
+ /* Assign recoded values in sorted order. */
+ for (j = 0; j < n_items; j++)
+ {
+ const union value *from = &items[j]->from;
+ size_t len;
+ char *recoded_value = NULL;
+ char *c;
+ const int src_width = items[j]->width;
+ union value to_val;
+ value_init (&to_val, 0);
+
+ items[j]->to = direction == ASCENDING ? j + 1 : n_items - j;
+
+ to_val.f = items[j]->to;
+
+ /* Add value labels to the destination variable which indicate
+ the source value from whence the new value comes. */
+ if (src_width > 0)
+ {
+ const char *str = CHAR_CAST_BUG (const char*, value_str (from, src_width));
+
+ recoded_value = recode_string (UTF8, dict_get_encoding (dict), str, src_width);
+ }
+ else
+ recoded_value = asnprintf (NULL, &len, "%g", from->f);
+
+ /* Remove trailing whitespace */
+ for (c = recoded_value; *c != '\0'; c++)
+ if ( *c == ' ')
+ {
+ *c = '\0';
+ break;
+ }
+
+ var_add_value_label (spec->dst, &to_val, recoded_value);
+ value_destroy (&to_val, 0);
+ free (recoded_value);
+ }
+
+ /* Free array. */
+ free (items);
+ }
+ add_transformation (ds, autorecode_trns_proc, autorecode_trns_free, arc);