+
+ if (n_vars > 1)
+ {
+ hmap_init (&bar->secondaries);
+ int idx = 0;
+ /* Iterate the categories, and create a hash table of secondary categories */
+ for (i = 0; i < n_cats; i++)
+ {
+ struct freq *src = cats[i];
+
+ struct category *foo;
+ int flag = 0;
+ size_t hash = value_hash (&src->values[sidx], var_get_width (var[sidx]), 0);
+ HMAP_FOR_EACH_WITH_HASH (foo, struct category, node, hash, &bar->secondaries)
+ {
+ if (value_equal (&foo->val, &src->values[sidx], var_get_width (var[sidx])))
+ {
+ flag = 1;
+ break;
+ }
+ }
+
+ if (!flag)
+ {
+ struct category *s = xzalloc (sizeof *s);
+ s->idx = idx++;
+ s->width = var_get_width (var[sidx]);
+ value_init (&s->val, s->width);
+ value_copy (&s->val, &src->values[sidx], var_get_width (var[sidx]));
+ ds_init_empty (&s->label);
+ var_append_value_name (var[sidx], &s->val, &s->label);
+
+ hmap_insert (&bar->secondaries, &s->node, hash);
+ bar->ss = xrealloc (bar->ss, idx * sizeof *bar->ss);
+ bar->ss[idx - 1] = s;
+ }
+ }
+
+ int n_category = hmap_count (&bar->secondaries);
+
+ sort (bar->ss, n_category, sizeof *bar->ss,
+ compare_category_3way, bar);
+ }
+
+
+ /* Deep copy. Not necessary for cmd line, but essential for the GUI,
+ since an expose callback will access these structs which may not
+ exist.
+ */
+ bar->cats = xcalloc (n_cats, sizeof *bar->cats);
+
+ bar->widths[0] = var_get_width (bar->var[0]);
+ if (n_vars > 1)
+ bar->widths[1] = var_get_width (bar->var[1]);
+
+ {
+ struct hmap level2table;
+ hmap_init (&level2table);
+ int x = 0;
+
+ for (i = 0; i < n_cats; i++)
+ {
+ struct freq *c = cats[i];
+
+ struct freq *foo;
+ bool flag = false;
+ size_t hash = hash_freq_2level_ptr (&c, bar);
+ HMAP_FOR_EACH_WITH_HASH (foo, struct freq, node, hash, &level2table)
+ {
+ if (0 == compare_freq_2level_ptr_3way (&foo, &c, bar))
+ {
+ foo->count += c->count;
+ bar->total_count += c->count;
+
+ if (foo->count > bar->largest)
+ bar->largest = foo->count;
+
+ flag = true;
+ break;
+ }
+ }
+
+ if (!flag)
+ {
+ struct freq *aggregated_freq = freq_clone (c, n_vars, bar->widths);
+ hmap_insert (&level2table, &aggregated_freq->node, hash);
+
+ if (c->count > bar->largest)
+ bar->largest = aggregated_freq->count;
+
+ bar->total_count += c->count;
+ bar->cats[x++] = aggregated_freq;
+ }
+ }
+
+ bar->n_nzcats = hmap_count (&level2table);
+ hmap_destroy (&level2table);
+ }
+
+ sort (bar->cats, bar->n_nzcats, sizeof *bar->cats,
+ compare_freq_2level_ptr_3way, bar);
+