c84f71d54cee3dc69bd8fa20bc4950bda0f7ef1c
[pspp-builds.git] / src / language / stats / sort-criteria.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include <language/stats/sort-criteria.h>
20
21 #include <stdlib.h>
22
23 #include <data/case-ordering.h>
24 #include <data/dictionary.h>
25 #include <data/variable.h>
26 #include <language/lexer/lexer.h>
27 #include <language/lexer/variable-parser.h>
28 #include <libpspp/message.h>
29
30 #include "gettext.h"
31 #define _(msgid) gettext (msgid)
32
33 /* Parses a list of sort keys and returns a struct sort_criteria
34    based on it.  Returns a null pointer on error.
35    If SAW_DIRECTION is nonnull, sets *SAW_DIRECTION to true if at
36    least one parenthesized sort direction was specified, false
37    otherwise. */
38 struct case_ordering *
39 parse_case_ordering (struct lexer *lexer, const struct dictionary *dict,
40                      bool *saw_direction)
41 {
42   struct case_ordering *ordering = case_ordering_create (dict);
43   const struct variable **vars = NULL;
44   size_t var_cnt = 0;
45
46  if (saw_direction != NULL)
47     *saw_direction = false;
48
49   do
50     {
51       enum sort_direction direction;
52       size_t i;
53
54       /* Variables. */
55       free (vars);
56       vars = NULL;
57       if (!parse_variables_const (lexer, dict, &vars, &var_cnt, PV_NO_SCRATCH))
58         goto error;
59
60       /* Sort direction. */
61       if (lex_match (lexer, '('))
62         {
63           if (lex_match_id (lexer, "D") || lex_match_id (lexer, "DOWN"))
64             direction = SRT_DESCEND;
65           else if (lex_match_id (lexer, "A") || lex_match_id (lexer, "UP"))
66             direction = SRT_ASCEND;
67           else
68             {
69               msg (SE, _("`A' or `D' expected inside parentheses."));
70               goto error;
71             }
72           if (!lex_match (lexer, ')'))
73             {
74               msg (SE, _("`)' expected."));
75               goto error;
76             }
77           if (saw_direction != NULL)
78             *saw_direction = true;
79         }
80       else
81         direction = SRT_ASCEND;
82
83       for (i = 0; i < var_cnt; i++)
84         if (!case_ordering_add_var (ordering, vars[i], direction))
85           msg (SW, _("Variable %s specified twice in sort criteria."),
86                var_get_name (vars[i]));
87     }
88   while (lex_token (lexer) == T_ID
89          && dict_lookup_var (dict, lex_tokid (lexer)) != NULL);
90
91   free (vars);
92   return ordering;
93
94  error:
95   free (vars);
96   case_ordering_destroy (ordering);
97   return NULL;
98 }