5ac07efb89d2ac4fbd6bc71112579f245f23f0cc
[pspp-builds.git] / src / language / stats / sort-criteria.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    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, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20
21 #include <language/stats/sort-criteria.h>
22
23 #include <stdlib.h>
24
25 #include <data/case-ordering.h>
26 #include <data/dictionary.h>
27 #include <data/variable.h>
28 #include <language/lexer/lexer.h>
29 #include <language/lexer/variable-parser.h>
30 #include <libpspp/message.h>
31
32 #include "gettext.h"
33 #define _(msgid) gettext (msgid)
34
35 /* Parses a list of sort keys and returns a struct sort_criteria
36    based on it.  Returns a null pointer on error.
37    If SAW_DIRECTION is nonnull, sets *SAW_DIRECTION to true if at
38    least one parenthesized sort direction was specified, false
39    otherwise. */
40 struct case_ordering *
41 parse_case_ordering (struct lexer *lexer, const struct dictionary *dict,
42                      bool *saw_direction)
43 {
44   struct case_ordering *ordering = case_ordering_create (dict);
45   const struct variable **vars = NULL;
46   size_t var_cnt = 0;
47
48  if (saw_direction != NULL)
49     *saw_direction = false;
50
51   do
52     {
53       enum sort_direction direction;
54       size_t i;
55
56       /* Variables. */
57       free (vars);
58       vars = NULL;
59       if (!parse_variables_const (lexer, dict, &vars, &var_cnt, PV_NO_SCRATCH))
60         goto error;
61
62       /* Sort direction. */
63       if (lex_match (lexer, '('))
64         {
65           if (lex_match_id (lexer, "D") || lex_match_id (lexer, "DOWN"))
66             direction = SRT_DESCEND;
67           else if (lex_match_id (lexer, "A") || lex_match_id (lexer, "UP"))
68             direction = SRT_ASCEND;
69           else
70             {
71               msg (SE, _("`A' or `D' expected inside parentheses."));
72               goto error;
73             }
74           if (!lex_match (lexer, ')'))
75             {
76               msg (SE, _("`)' expected."));
77               goto error;
78             }
79           if (saw_direction != NULL)
80             *saw_direction = true;
81         }
82       else
83         direction = SRT_ASCEND;
84
85       for (i = 0; i < var_cnt; i++)
86         if (!case_ordering_add_var (ordering, vars[i], direction))
87           msg (SW, _("Variable %s specified twice in sort criteria."),
88                var_get_name (vars[i]));
89     }
90   while (lex_token (lexer) == T_ID
91          && dict_lookup_var (dict, lex_tokid (lexer)) != NULL);
92
93   free (vars);
94   return ordering;
95
96  error:
97   free (vars);
98   case_ordering_destroy (ordering);
99   return NULL;
100 }