1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "data/short-names.h"
21 #include "data/dictionary.h"
22 #include "data/sys-file-private.h"
23 #include "data/variable.h"
24 #include "libpspp/assertion.h"
25 #include "libpspp/compiler.h"
26 #include "libpspp/message.h"
27 #include "libpspp/str.h"
28 #include "libpspp/stringi-set.h"
31 #define _(msgid) gettext (msgid)
33 /* Sets V's short name to BASE, followed by a suffix of the form
34 _A, _B, _C, ..., _AA, _AB, etc. according to the value of
35 SUFFIX_NUMBER. Truncates BASE as necessary to fit. */
37 set_var_short_name_suffix (struct variable *v, size_t i,
38 const char *base, int suffix_number)
40 char suffix[SHORT_NAME_LEN + 1];
41 char short_name[SHORT_NAME_LEN + 1];
44 assert (suffix_number >= 0);
47 var_set_short_name (v, i, base);
51 if (!str_format_26adic (suffix_number, &suffix[1], sizeof suffix - 1))
52 msg (SE, _("Variable suffix too large."));
53 len = strlen (suffix);
55 /* Append suffix to V's short name. */
56 str_copy_trunc (short_name, sizeof short_name, base);
57 if (strlen (short_name) + len > SHORT_NAME_LEN)
58 ofs = SHORT_NAME_LEN - len;
60 ofs = strlen (short_name);
61 strcpy (short_name + ofs, suffix);
64 var_set_short_name (v, i, short_name);
68 claim_short_name (struct variable *v, size_t i,
69 struct stringi_set *short_names)
71 const char *short_name = var_get_short_name (v, i);
72 if (short_name != NULL && !stringi_set_insert (short_names, short_name))
73 var_set_short_name (v, i, NULL);
76 /* Form initial short_name from the variable name, then try _A,
77 _B, ... _AA, _AB, etc., if needed. */
79 assign_short_name (struct variable *v, size_t i,
80 struct stringi_set *short_names)
84 if (var_get_short_name (v, i) != NULL)
87 for (trial = 0; ; trial++)
90 var_set_short_name (v, i, var_get_name (v));
92 set_var_short_name_suffix (v, i, var_get_name (v), trial);
94 if (stringi_set_insert (short_names, var_get_short_name (v, i)))
99 /* Assigns a valid, unique short_name[] to each variable in D.
100 Each variable whose actual name is short has highest priority
101 for that short name. Otherwise, variables with an existing
102 short_name[] have the next highest priority for a given short
103 name; if it is already taken, then the variable is treated as
104 if short_name[] had been empty. Otherwise, long names are
105 truncated to form short names. If that causes conflicts,
106 variables are renamed as PREFIX_A, PREFIX_B, and so on. */
108 short_names_assign (struct dictionary *d)
110 size_t var_cnt = dict_get_var_cnt (d);
111 struct stringi_set short_names;
114 stringi_set_init (&short_names);
116 /* Clear short names that conflict with a variable name. */
117 for (i = 0; i < var_cnt; i++)
119 struct variable *v = dict_get_var (d, i);
120 int segment_cnt = sfm_width_to_segments (var_get_width (v));
121 for (j = 0; j < segment_cnt; j++)
123 const char *name = var_get_short_name (v, j);
126 struct variable *ov = dict_lookup_var (d, name);
127 if (ov != NULL && (ov != v || j > 0))
128 var_set_short_name (v, j, NULL);
133 /* Give variables whose names are short the corresponding short
135 for (i = 0; i < var_cnt; i++)
137 struct variable *v = dict_get_var (d, i);
138 const char *name = var_get_name (v);
139 if (strlen (name) <= SHORT_NAME_LEN)
140 var_set_short_name (v, 0, name);
143 /* Each variable with an assigned short name for its first
144 segment now gets it unless there is a conflict. In case of
145 conflict, the claimant earlier in dictionary order wins.
146 Then similarly for additional segments of very long
148 for (i = 0; i < var_cnt; i++)
150 struct variable *v = dict_get_var (d, i);
151 claim_short_name (v, 0, &short_names);
153 for (i = 0; i < var_cnt; i++)
155 struct variable *v = dict_get_var (d, i);
156 int segment_cnt = sfm_width_to_segments (var_get_width (v));
157 for (j = 1; j < segment_cnt; j++)
158 claim_short_name (v, j, &short_names);
161 /* Assign short names to first segment of remaining variables,
162 then similarly for additional segments. */
163 for (i = 0; i < var_cnt; i++)
165 struct variable *v = dict_get_var (d, i);
166 assign_short_name (v, 0, &short_names);
168 for (i = 0; i < var_cnt; i++)
170 struct variable *v = dict_get_var (d, i);
171 int segment_cnt = sfm_width_to_segments (var_get_width (v));
172 for (j = 1; j < segment_cnt; j++)
173 assign_short_name (v, j, &short_names);
176 stringi_set_destroy (&short_names);