gui: Factor out duplicated code for executing and pasting syntax.
[pspp-builds.git] / src / ui / gui / executor.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2007, 2009, 2010  Free Software Foundation
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 "ui/gui/executor.h"
20
21 #include "data/lazy-casereader.h"
22 #include "data/procedure.h"
23 #include "language/command.h"
24 #include "language/lexer/lexer.h"
25 #include "language/syntax-string-source.h"
26 #include "libpspp/cast.h"
27 #include "libpspp/getl.h"
28 #include "output/driver.h"
29 #include "ui/gui/psppire-data-store.h"
30 #include "ui/gui/psppire-output-window.h"
31
32 extern struct dataset *the_dataset;
33 extern struct source_stream *the_source_stream;
34 extern PsppireDataStore *the_data_store;
35
36 /* Lazy casereader callback function used by execute_syntax. */
37 static struct casereader *
38 create_casereader_from_data_store (void *data_store_)
39 {
40   PsppireDataStore *data_store = data_store_;
41   return psppire_data_store_get_reader (data_store);
42 }
43
44 gboolean
45 execute_syntax (struct getl_interface *sss)
46 {
47   struct lexer *lexer;
48   gboolean retval = TRUE;
49
50   struct casereader *reader;
51   const struct caseproto *proto;
52   casenumber case_cnt;
53   unsigned long int lazy_serial;
54
55   /* When the user executes a number of snippets of syntax in a
56      row, none of which read from the active file, the GUI becomes
57      progressively less responsive.  The reason is that each syntax
58      execution encapsulates the active file data in another
59      datasheet layer.  The cumulative effect of having a number of
60      layers of datasheets wastes time and space.
61
62      To solve the problem, we use a "lazy casereader", a wrapper
63      around the casereader obtained from the data store, that
64      only actually instantiates that casereader when it is
65      needed.  If the data store casereader is never needed, then
66      it is reused the next time syntax is run, without wrapping
67      it in another layer. */
68   proto = psppire_data_store_get_proto (the_data_store);
69   case_cnt = psppire_data_store_get_case_count (the_data_store);
70   reader = lazy_casereader_create (proto, case_cnt,
71                                    create_casereader_from_data_store,
72                                    the_data_store, &lazy_serial);
73   proc_set_active_file_data (the_dataset, reader);
74
75   g_return_val_if_fail (proc_has_active_file (the_dataset), FALSE);
76
77   lexer = lex_create (the_source_stream);
78
79   getl_append_source (the_source_stream, sss, GETL_BATCH, ERRMODE_CONTINUE);
80
81   for (;;)
82     {
83       enum cmd_result result = cmd_parse (lexer, the_dataset);
84
85       if ( cmd_result_is_failure (result))
86         {
87           retval = FALSE;
88           if ( source_stream_current_error_mode (the_source_stream)
89                == ERRMODE_STOP )
90             break;
91         }
92
93       if ( result == CMD_EOF || result == CMD_FINISH)
94         break;
95     }
96
97   getl_abort_noninteractive (the_source_stream);
98
99   lex_destroy (lexer);
100
101   proc_execute (the_dataset);
102
103   psppire_dict_replace_dictionary (the_data_store->dict,
104                                    dataset_dict (the_dataset));
105
106   reader = proc_extract_active_file_data (the_dataset);
107   if (!lazy_casereader_destroy (reader, lazy_serial))
108     psppire_data_store_set_reader (the_data_store, reader);
109
110   output_flush ();
111
112   return retval;
113 }
114
115 /* Executes null-terminated string SYNTAX as syntax.
116    Returns SYNTAX. */
117 gchar *
118 execute_syntax_string (gchar *syntax)
119 {
120   execute_const_syntax_string (syntax);
121   return syntax;
122 }
123
124 /* Executes null-terminated string SYNTAX as syntax. */
125 void
126 execute_const_syntax_string (const gchar *syntax)
127 {
128   execute_syntax (create_syntax_string_source (syntax));
129 }