Added categorical variable support for model export
[pspp-builds.git] / src / readln.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, USA. */
19
20 #include <config.h>
21
22 #include <stdlib.h>
23 #include <stdbool.h>
24 #include <assert.h>
25 #include <errno.h>
26
27 #include "readln.h"
28 #include "command.h"
29 #include "version.h"
30 #include "getl.h"
31 #include "str.h"
32 #include "tab.h"
33 #include "error.h"
34 #include "filename.h"
35 #include "settings.h"
36
37 #include "gettext.h"
38 #define _(msgid) gettext (msgid)
39
40
41 #if HAVE_LIBREADLINE
42 #include <readline/readline.h>
43 #endif
44
45 #if HAVE_LIBHISTORY
46 static char *history_file;
47
48 #if HAVE_READLINE_HISTORY_H
49 #include <readline/history.h>
50 #else /* no readline/history.h */
51 extern void add_history (char *);
52 extern void using_history (void);
53 extern int read_history (char *);
54 extern void stifle_history (int);
55 extern int write_history (char *);
56 #endif /* no readline/history.h */
57 #endif /* -lhistory */
58
59
60 static int read_console (void);
61
62 static bool initialised = false;
63
64 /* Initialize getl. */
65 void
66 readln_initialize (void)
67 {
68   initialised = true;
69 #if HAVE_LIBREADLINE 
70   rl_completion_entry_function = pspp_completion_function;
71 #endif
72 }
73
74 /* Close getl. */
75 void
76 readln_uninitialize (void)
77 {
78   initialised = false;
79 #if HAVE_LIBHISTORY && defined (unix)
80   if (history_file)
81     write_history (history_file);
82 #endif
83 }
84
85 static bool welcomed = false;
86
87 /* Display a welcoming message. */
88 static void
89 welcome (void)
90 {
91   welcomed = true;
92   fputs ("PSPP is free software and you are welcome to distribute copies of "
93          "it\nunder certain conditions; type \"show copying.\" to see the "
94          "conditions.\nThere is ABSOLUTELY NO WARRANTY for PSPP; type \"show "
95          "warranty.\" for details.\n", stdout);
96   puts (stat_version);
97 }
98
99 /* From repeat.c. */
100 extern void perform_DO_REPEAT_substitutions (void);
101
102   /* Global variables. */
103 int getl_mode;
104 int getl_interactive;
105 int getl_prompt;
106
107 /* 
108 extern struct cmd_set cmd;
109 */
110
111
112 /* Reads a single line into getl_buf from the list of files.  Will not
113    read from the eof of one file to the beginning of another unless
114    the options field on the new file's getl_script is nonzero.  Return
115    zero on eof. */
116 int
117 getl_read_line (void)
118 {
119   assert (initialised);
120   getl_mode = GETL_MODE_BATCH;
121   
122   while (getl_head)
123     {
124       struct getl_script *s = getl_head;
125
126       ds_clear (&getl_buf);
127       if (s->separate)
128         return 0;
129
130       if (s->first_line)
131         {
132           if (!getl_handle_line_buffer ())
133             {
134               getl_close_file ();
135               continue;
136             }
137           perform_DO_REPEAT_substitutions ();
138           if (getl_head->print)
139             tab_output_text (TAB_LEFT | TAT_FIX | TAT_PRINTF, "+%s",
140                              ds_c_str (&getl_buf));
141           return 1;
142         }
143       
144       if (s->f == NULL)
145         {
146           msg (VM (1), _("%s: Opening as syntax file."), s->fn);
147           s->f = fn_open (s->fn, "r");
148
149           if (s->f == NULL)
150             {
151               msg (ME, _("Opening `%s': %s."), s->fn, strerror (errno));
152               getl_close_file ();
153               continue;
154             }
155         }
156
157       if (!ds_gets (&getl_buf, s->f))
158         {
159           if (ferror (s->f))
160             msg (ME, _("Reading `%s': %s."), s->fn, strerror (errno));
161           getl_close_file ();
162           continue;
163         }
164       if (ds_length (&getl_buf) > 0 && ds_end (&getl_buf)[-1] == '\n')
165         ds_truncate (&getl_buf, ds_length (&getl_buf) - 1);
166
167       if (get_echo())
168         tab_output_text (TAB_LEFT | TAT_FIX, ds_c_str (&getl_buf));
169
170       getl_head->ln++;
171
172       /* Allows shebang invocation: `#! /usr/local/bin/pspp'. */
173       if (ds_c_str (&getl_buf)[0] == '#'
174           && ds_c_str (&getl_buf)[1] == '!')
175         continue;
176
177       return 1;
178     }
179
180   if (getl_interactive == 0)
181     return 0;
182
183   getl_mode = GETL_MODE_INTERACTIVE;
184   
185   if (!welcomed)
186     welcome ();
187
188   return read_console ();
189 }
190
191
192 /* PORTME: Adapt to your local system's idea of the terminal. */
193 #if HAVE_LIBREADLINE
194
195 #if HAVE_READLINE_READLINE_H
196 #include <readline/readline.h>
197 #else /* no readline/readline.h */
198 extern char *readline (char *);
199 #endif /* no readline/readline.h */
200
201 static int
202 read_console (void)
203 {
204   char *line;
205   const char *prompt;
206
207   assert(initialised);
208
209   err_error_count = err_warning_count = 0;
210   err_already_flagged = 0;
211
212 #if HAVE_LIBHISTORY
213   if (!history_file)
214     {
215 #ifdef unix
216       history_file = tilde_expand (HISTORY_FILE);
217 #endif
218       using_history ();
219       read_history (history_file);
220       stifle_history (MAX_HISTORY);
221     }
222 #endif /* -lhistory */
223
224   switch (getl_prompt)
225     {
226     case GETL_PRPT_STANDARD:
227       prompt = get_prompt ();
228       break;
229
230     case GETL_PRPT_CONTINUATION:
231       prompt = get_cprompt ();
232       break;
233
234     case GETL_PRPT_DATA:
235       prompt = get_dprompt ();
236       break;
237
238     default:
239       assert (0);
240       abort ();
241     }
242
243   line = readline (prompt);
244   if (!line)
245     return 0;
246
247 #if HAVE_LIBHISTORY
248   if (*line)
249     add_history (line);
250 #endif
251
252   ds_clear (&getl_buf);
253   ds_puts (&getl_buf, line);
254
255   free (line);
256
257   return 1;
258 }
259 #else /* no -lreadline */
260 static int
261 read_console (void)
262 {
263   assert(initialised);
264
265   err_error_count = err_warning_count = 0;
266   err_already_flagged = 0;
267
268   fputs (getl_prompt ? get_cprompt() : get_prompt(), stdout);
269   ds_clear (&getl_buf);
270   if (ds_gets (&getl_buf, stdin))
271     return 1;
272
273   if (ferror (stdin))
274     msg (FE, "stdin: fgets(): %s.", strerror (errno));
275
276   return 0;
277 }
278 #endif /* no -lreadline */
279